* more accurate matching progress
* added SwingWorkerProgressMonitor and ProgressDialog
This commit is contained in:
parent
b5bee237d6
commit
b59e5dc714
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in New Issue