* more accurate matching progress

* added SwingWorkerProgressMonitor and ProgressDialog
This commit is contained in:
Reinhard Pointner 2008-04-27 21:11:30 +00:00
parent b5bee237d6
commit b59e5dc714
6 changed files with 326 additions and 26 deletions

View File

@ -13,6 +13,7 @@ import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
@ -26,6 +27,7 @@ import net.sourceforge.filebot.ui.panel.rename.similarity.SimilarityMetric;
import net.sourceforge.filebot.ui.panel.rename.similarity.StringEqualsMetric;
import net.sourceforge.filebot.ui.panel.rename.similarity.StringSimilarityMetric;
import net.sourceforge.tuned.ui.ProgressDialog;
import net.sourceforge.tuned.ui.SwingWorkerProgressMonitor;
class MatchAction extends AbstractAction {
@ -78,13 +80,15 @@ class MatchAction extends AbstractAction {
public void actionPerformed(ActionEvent evt) {
SwingUtilities.getRoot(namesList).setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
JComponent source = (JComponent) evt.getSource();
SwingUtilities.getRoot(source).setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
RenameList primaryList = matchName2File ? namesList : filesList;
RenameList secondaryList = matchName2File ? filesList : namesList;
BackgroundMatcher backgroundMatcher = new BackgroundMatcher(primaryList, secondaryList, metrics);
SwingWorkerProgressMonitor monitor = new SwingWorkerProgressMonitor(SwingUtilities.getWindowAncestor(namesList), backgroundMatcher);
SwingWorkerProgressMonitor monitor = new SwingWorkerProgressMonitor(SwingUtilities.getWindowAncestor(source), backgroundMatcher);
ProgressDialog progressDialog = monitor.getProgressDialog();
progressDialog.setTitle("Matching ...");
@ -103,7 +107,7 @@ class MatchAction extends AbstractAction {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}
SwingUtilities.getRoot(namesList).setCursor(Cursor.getDefaultCursor());
SwingUtilities.getRoot(source).setCursor(Cursor.getDefaultCursor());
}
@ -125,7 +129,7 @@ class MatchAction extends AbstractAction {
@Override
protected List<Match> doInBackground() throws Exception {
int total = matcher.remaining();
int total = matcher.remainingMatches();
List<Match> matches = new ArrayList<Match>(total);
@ -167,12 +171,13 @@ class MatchAction extends AbstractAction {
secondaryList.getModel().clear();
for (Match match : matches) {
if (match.getA() != null)
primaryList.getModel().add(match.getA());
if (match.getB() != null)
secondaryList.getModel().add(match.getB());
primaryList.getModel().add(match.getA());
secondaryList.getModel().add(match.getB());
}
primaryList.getModel().addAll(matcher.getPrimaryList());
secondaryList.getModel().addAll(matcher.getSecondaryList());
} catch (Exception e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}

View File

@ -2,6 +2,7 @@
package net.sourceforge.filebot.ui.panel.rename.match;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@ -10,7 +11,7 @@ import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
import net.sourceforge.filebot.ui.panel.rename.similarity.SimilarityMetric;
public class Matcher implements Iterable<Match>, Iterator<Match> {
public class Matcher implements Iterator<Match> {
private final LinkedList<ListEntry> primaryList;
private final LinkedList<ListEntry> secondaryList;
@ -24,24 +25,14 @@ public class Matcher implements Iterable<Match>, Iterator<Match> {
}
@Override
public Iterator<Match> iterator() {
return this;
}
@Override
public boolean hasNext() {
return !primaryList.isEmpty() || !secondaryList.isEmpty();
return remainingMatches() > 0;
}
@Override
public Match next() {
if (primaryList.isEmpty()) {
return new Match(null, secondaryList.removeFirst());
}
ListEntry primaryEntry = primaryList.removeFirst();
float maxSimilarity = -1;
@ -80,8 +71,18 @@ public class Matcher implements Iterable<Match>, Iterator<Match> {
}
public int remaining() {
return Math.max(primaryList.size(), secondaryList.size());
public int remainingMatches() {
return Math.min(primaryList.size(), secondaryList.size());
}
public List<ListEntry> getPrimaryList() {
return Collections.unmodifiableList(primaryList);
}
public List<ListEntry> getSecondaryList() {
return Collections.unmodifiableList(secondaryList);
}

View File

@ -47,6 +47,16 @@ public class OpenSubtitlesClient {
}
/**
* Login as anonymous user
*
* @throws XmlRpcFault
*/
public void loginAnonymous() throws XmlRpcFault {
login("", "");
}
public void login(String username, String password) throws XmlRpcFault {
login(username, password, "en");
}
@ -56,8 +66,8 @@ public class OpenSubtitlesClient {
* This will login user. This method should be called always when starting talking with
* server.
*
* @param username blank for anonymous user.
* @param password blank for anonymous user.
* @param username username (blank for anonymous user)
* @param password password (blank for anonymous user)
* @param language <a href="http://en.wikipedia.org/wiki/List_of_ISO_639-2_codes">ISO639</a>
* 2 letter codes as language and later communication will be done in this
* language if applicable (error codes and so on).

View File

@ -49,7 +49,7 @@ public class OpenSubtitlesSubtitleClient extends SubtitleClient {
private synchronized void activate() {
try {
if (!client.isLoggedOn()) {
client.login("", "");
client.loginAnonymous();
}
} catch (Exception e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);

View File

@ -0,0 +1,168 @@
package net.sourceforge.tuned.ui;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
public class ProgressDialog extends JDialog {
private final JProgressBar progressBar = new JProgressBar(0, 100);
private final JLabel iconLabel = new JLabel();
private final JLabel headerLabel = new JLabel();
private final JLabel noteLabel = new JLabel();
private final JButton cancelButton;
private boolean cancelled = false;
public ProgressDialog(Window owner) {
super(owner, ModalityType.DOCUMENT_MODAL);
if (!owner.getIconImages().isEmpty()) {
setIconImages(owner.getIconImages());
}
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(closeListener);
cancelButton = new JButton(cancelAction);
progressBar.setStringPainted(true);
iconLabel.setHorizontalAlignment(SwingConstants.CENTER);
iconLabel.setVerticalAlignment(SwingConstants.CENTER);
iconLabel.setBorder(new EmptyBorder(0, 2, 0, 10));
Border labelBorder = new EmptyBorder(3, 0, 0, 0);
headerLabel.setBorder(labelBorder);
noteLabel.setBorder(labelBorder);
JComponent c = (JComponent) getContentPane();
c.setBorder(new EmptyBorder(5, 5, 5, 5));
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
buttonPanel.add(cancelButton);
Box messageBox = Box.createVerticalBox();
messageBox.add(headerLabel);
messageBox.add(noteLabel);
messageBox.add(Box.createVerticalGlue());
JPanel messagePanel = new JPanel(new BorderLayout());
messagePanel.add(iconLabel, BorderLayout.WEST);
messagePanel.add(messageBox, BorderLayout.CENTER);
JPanel progressBarPanel = new JPanel(new BorderLayout());
progressBarPanel.add(progressBar, BorderLayout.CENTER);
progressBarPanel.setBorder(new EmptyBorder(8, 12, 3, 12));
Box progressBox = Box.createVerticalBox();
progressBox.add(messagePanel);
progressBox.add(progressBarPanel);
c.add(progressBox, BorderLayout.CENTER);
c.add(buttonPanel, BorderLayout.SOUTH);
setSize(240, 138);
setResizable(false);
setLocation(TunedUtil.getPreferredLocation(this));
// Shortcut Escape
TunedUtil.registerActionForKeystroke(c, KeyStroke.getKeyStroke("released ESCAPE"), cancelAction);
}
public boolean isCancelled() {
return cancelled;
}
public void setIcon(Icon icon) {
iconLabel.setIcon(icon);
}
public void setNote(String text) {
noteLabel.setText(text);
}
public void setHeader(String text) {
headerLabel.setText(text);
}
public void setProgressMaximum(int n) {
progressBar.setMaximum(n);
}
public void setProgressMinimum(int n) {
progressBar.setMinimum(n);
}
public void setProgressValue(int n) {
progressBar.setValue(n);
}
public void setProgressString(String text) {
progressBar.setString(text);
}
public JButton getCancelButton() {
return cancelButton;
}
public void close() {
setVisible(false);
dispose();
}
private final Action cancelAction = new AbstractAction("Cancel") {
@Override
public void actionPerformed(ActionEvent e) {
cancelled = true;
close();
}
};
private final WindowListener closeListener = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
cancelled = true;
close();
}
};
}

View File

@ -0,0 +1,116 @@
package net.sourceforge.tuned.ui;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import javax.swing.SwingWorker;
import javax.swing.Timer;
public class SwingWorkerProgressMonitor {
public static final String PROPERTY_NOTE = "note";
public static final String PROPERTY_PROGRESS_STRING = "progress string";
private final SwingWorker<?, ?> worker;
private final ProgressDialog progressDialog;
private int millisToPopup = 2000;
public SwingWorkerProgressMonitor(Window owner, SwingWorker<?, ?> worker) {
this.worker = worker;
progressDialog = new ProgressDialog(owner);
worker.addPropertyChangeListener(listener);
progressDialog.getCancelButton().addActionListener(cancelListener);
}
public ProgressDialog getProgressDialog() {
return progressDialog;
}
public void setMillisToPopup(int millisToPopup) {
this.millisToPopup = millisToPopup;
}
public int getMillisToPopup() {
return millisToPopup;
}
private final SwingWorkerPropertyChangeAdapter listener = new SwingWorkerPropertyChangeAdapter() {
private Timer popupTimer;
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(PROPERTY_NOTE))
note(evt);
else if (evt.getPropertyName().equals(PROPERTY_PROGRESS_STRING))
progressString(evt);
else
super.propertyChange(evt);
}
@Override
public void started(PropertyChangeEvent evt) {
popupTimer = TunedUtil.invokeLater(millisToPopup, new Runnable() {
@Override
public void run() {
if (!worker.isDone()) {
progressDialog.setVisible(true);
}
}
});
}
@Override
public void done(PropertyChangeEvent evt) {
if (popupTimer != null) {
popupTimer.stop();
}
progressDialog.close();
}
@Override
public void progress(PropertyChangeEvent evt) {
progressDialog.setProgressValue((Integer) evt.getNewValue());
}
public void progressString(PropertyChangeEvent evt) {
progressDialog.setProgressString(evt.getNewValue().toString());
}
public void note(PropertyChangeEvent evt) {
progressDialog.setNote(evt.getNewValue().toString());
}
};
private final ActionListener cancelListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
worker.cancel(false);
}
};
}