From b59e5dc7145ebcd2512227f9257d4465049fd15d Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Sun, 27 Apr 2008 21:11:30 +0000 Subject: [PATCH] * more accurate matching progress * added SwingWorkerProgressMonitor and ProgressDialog --- .../filebot/ui/panel/rename/MatchAction.java | 23 ++- .../ui/panel/rename/match/Matcher.java | 29 +-- .../filebot/web/OpenSubtitlesClient.java | 14 +- .../web/OpenSubtitlesSubtitleClient.java | 2 +- .../sourceforge/tuned/ui/ProgressDialog.java | 168 ++++++++++++++++++ .../tuned/ui/SwingWorkerProgressMonitor.java | 116 ++++++++++++ 6 files changed, 326 insertions(+), 26 deletions(-) create mode 100644 source/net/sourceforge/tuned/ui/ProgressDialog.java create mode 100644 source/net/sourceforge/tuned/ui/SwingWorkerProgressMonitor.java diff --git a/source/net/sourceforge/filebot/ui/panel/rename/MatchAction.java b/source/net/sourceforge/filebot/ui/panel/rename/MatchAction.java index f5da443a..9a588ead 100644 --- a/source/net/sourceforge/filebot/ui/panel/rename/MatchAction.java +++ b/source/net/sourceforge/filebot/ui/panel/rename/MatchAction.java @@ -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 doInBackground() throws Exception { - int total = matcher.remaining(); + int total = matcher.remainingMatches(); List matches = new ArrayList(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); } diff --git a/source/net/sourceforge/filebot/ui/panel/rename/match/Matcher.java b/source/net/sourceforge/filebot/ui/panel/rename/match/Matcher.java index 0580cdf7..64e6280b 100644 --- a/source/net/sourceforge/filebot/ui/panel/rename/match/Matcher.java +++ b/source/net/sourceforge/filebot/ui/panel/rename/match/Matcher.java @@ -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, Iterator { +public class Matcher implements Iterator { private final LinkedList primaryList; private final LinkedList secondaryList; @@ -24,24 +25,14 @@ public class Matcher implements Iterable, Iterator { } - @Override - public Iterator 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, Iterator { } - public int remaining() { - return Math.max(primaryList.size(), secondaryList.size()); + public int remainingMatches() { + return Math.min(primaryList.size(), secondaryList.size()); + } + + + public List getPrimaryList() { + return Collections.unmodifiableList(primaryList); + } + + + public List getSecondaryList() { + return Collections.unmodifiableList(secondaryList); } diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java b/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java index 8b47a9ba..e5d29ace 100644 --- a/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java +++ b/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java @@ -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 ISO639 * 2 letter codes as language and later communication will be done in this * language if applicable (error codes and so on). diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleClient.java b/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleClient.java index 2bd02861..3c77b5ec 100644 --- a/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleClient.java +++ b/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleClient.java @@ -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); diff --git a/source/net/sourceforge/tuned/ui/ProgressDialog.java b/source/net/sourceforge/tuned/ui/ProgressDialog.java new file mode 100644 index 00000000..18e16135 --- /dev/null +++ b/source/net/sourceforge/tuned/ui/ProgressDialog.java @@ -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(); + } + }; +} diff --git a/source/net/sourceforge/tuned/ui/SwingWorkerProgressMonitor.java b/source/net/sourceforge/tuned/ui/SwingWorkerProgressMonitor.java new file mode 100644 index 00000000..ceb96a7c --- /dev/null +++ b/source/net/sourceforge/tuned/ui/SwingWorkerProgressMonitor.java @@ -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); + } + + }; + +}