* refactored matching

* added ProgressDialog for long-running matching
* added delayed invokeLater to TunedUtil
* removed generics from ListEntry (only subclasses where used anyway)
* minor cleanup in notification package
This commit is contained in:
Reinhard Pointner 2008-04-27 17:36:27 +00:00
parent eabe011e9a
commit b5bee237d6
34 changed files with 376 additions and 315 deletions

View File

@ -16,18 +16,18 @@ import java.util.prefs.Preferences;
public class Settings {
private static Settings settings = new Settings();
public static final String NAME = "FileBot";
public static final String VERSION = "2.0";
public static final String ROOT = "filebot";
public static final String ROOT = NAME.toLowerCase();
public static final String SELECTED_PANEL = "panel";
public static final String SEARCH_HISTORY = "history/search";
public static final String SUBTITLE_HISTORY = "history/subtitle";
public static final String LANGUAGE_HISTORY = "history/language";
private static Settings settings = new Settings();
public static Settings getSettings() {
return settings;

View File

@ -9,8 +9,6 @@ import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JList;
import javax.swing.ListSelectionModel;
@ -21,6 +19,7 @@ import javax.swing.border.EmptyBorder;
import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer;
import net.sourceforge.tuned.ui.SimpleListModel;
import net.sourceforge.tuned.ui.TunedUtil;
class FileBotPanelSelectionList extends JList {
@ -70,26 +69,13 @@ class FileBotPanelSelectionList extends JList {
}
private class DragDropListener extends DropTargetAdapter implements ActionListener {
private class DragDropListener extends DropTargetAdapter {
private boolean selectEnabled = false;
private Timer timer = new Timer(SELECTDELAY_ON_DRAG_OVER, this);
private Timer dragEnterTimer;
public DragDropListener() {
timer.setRepeats(false);
}
public void actionPerformed(ActionEvent e) {
selectEnabled = true;
// bring window to front when on dnd
SwingUtilities.getWindowAncestor(FileBotPanelSelectionList.this).toFront();
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
if (selectEnabled) {
@ -101,14 +87,26 @@ class FileBotPanelSelectionList extends JList {
@Override
public void dragEnter(DropTargetDragEvent dtde) {
timer.start();
dragEnterTimer = TunedUtil.invokeLater(SELECTDELAY_ON_DRAG_OVER, new Runnable() {
@Override
public void run() {
selectEnabled = true;
// bring window to front when on dnd
SwingUtilities.getWindowAncestor(FileBotPanelSelectionList.this).toFront();
}
});
}
@Override
public void dragExit(DropTargetEvent dte) {
timer.stop();
selectEnabled = false;
if (dragEnterTimer != null) {
dragEnterTimer.stop();
}
}

View File

@ -5,6 +5,7 @@ package net.sourceforge.filebot.ui;
import javax.swing.Icon;
import javax.swing.SwingConstants;
import net.sourceforge.filebot.Settings;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.tuned.ui.notification.MessageNotification;
import net.sourceforge.tuned.ui.notification.NotificationManager;
@ -28,7 +29,7 @@ public class MessageManager {
private static void show(String message, Icon icon, int timeout) {
manager.show(new MessageNotification("FileBot", message, icon, timeout));
manager.show(new MessageNotification(Settings.NAME, message, icon, timeout));
}
}

View File

@ -82,14 +82,10 @@ public class SelectDialog<T> extends JDialog {
list.setSelectedIndex(0);
// Shortcut Enter
Integer actionMapKey = new Integer(selectAction.hashCode());
list.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released ENTER"), actionMapKey);
list.getActionMap().put(actionMapKey, selectAction);
TunedUtil.registerActionForKeystroke(list, KeyStroke.getKeyStroke("released ENTER"), selectAction);
// Shortcut Escape
actionMapKey = new Integer(cancelAction.hashCode());
list.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released ESCAPE"), actionMapKey);
list.getActionMap().put(actionMapKey, cancelAction);
TunedUtil.registerActionForKeystroke(list, KeyStroke.getKeyStroke("released ESCAPE"), cancelAction);
}

View File

@ -1,23 +0,0 @@
package net.sourceforge.filebot.ui.panel.rename;
import java.util.List;
import net.sourceforge.filebot.ui.panel.rename.entry.FileEntry;
class FilesRenameList extends RenameList {
public FilesRenameList() {
setTitle("Files");
setTransferablePolicy(new FilesListTransferablePolicy(getModel()));
}
@SuppressWarnings("unchecked")
public List<FileEntry> getListEntries() {
return (List<FileEntry>) getModel().getCopy();
}
}

View File

@ -6,9 +6,15 @@ import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
@ -16,18 +22,18 @@ import net.sourceforge.filebot.ui.panel.rename.match.Match;
import net.sourceforge.filebot.ui.panel.rename.match.Matcher;
import net.sourceforge.filebot.ui.panel.rename.similarity.LengthEqualsMetric;
import net.sourceforge.filebot.ui.panel.rename.similarity.MultiSimilarityMetric;
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;
class MatchAction extends AbstractAction {
private NamesRenameList namesList;
private FilesRenameList filesList;
private MultiSimilarityMetric metrics;
private Matcher matcher = new Matcher();
private final RenameList namesList;
private final RenameList filesList;
private boolean matchName2File;
@ -35,7 +41,7 @@ class MatchAction extends AbstractAction {
public static final String MATCH_FILES_2_NAMES_DESCRIPTION = "Match files to names";
public MatchAction(NamesRenameList namesList, FilesRenameList filesList) {
public MatchAction(RenameList namesList, RenameList filesList) {
super("Match");
this.namesList = namesList;
@ -71,45 +77,107 @@ class MatchAction extends AbstractAction {
}
public void actionPerformed(ActionEvent e) {
public void actionPerformed(ActionEvent evt) {
SwingUtilities.getRoot(namesList).setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
List<? extends ListEntry<?>> listA, listB;
RenameList primaryList = matchName2File ? namesList : filesList;
RenameList secondaryList = matchName2File ? filesList : namesList;
if (matchName2File) {
listA = namesList.getListEntries();
listB = filesList.getListEntries();
} else {
listB = namesList.getListEntries();
listA = filesList.getListEntries();
BackgroundMatcher backgroundMatcher = new BackgroundMatcher(primaryList, secondaryList, metrics);
SwingWorkerProgressMonitor monitor = new SwingWorkerProgressMonitor(SwingUtilities.getWindowAncestor(namesList), backgroundMatcher);
ProgressDialog progressDialog = monitor.getProgressDialog();
progressDialog.setTitle("Matching ...");
progressDialog.setHeader("Matching ...");
progressDialog.setIcon((Icon) getValue(SMALL_ICON));
backgroundMatcher.execute();
try {
// wait a for little while (matcher might finish within a few seconds)
backgroundMatcher.get(monitor.getMillisToPopup(), TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
// matcher will take longer, stop blocking EDT
progressDialog.setVisible(true);
} catch (Exception e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}
List<Match> matches = matcher.match(listA, listB, metrics);
List<ListEntry<?>> names = new ArrayList<ListEntry<?>>();
List<ListEntry<?>> files = new ArrayList<ListEntry<?>>();
for (Match match : matches) {
ListEntry<?> a, b;
if (matchName2File) {
a = match.getA();
b = match.getB();
} else {
b = match.getA();
a = match.getB();
}
if (a != null)
names.add(a);
if (b != null)
files.add(b);
}
namesList.getModel().set(names);
filesList.getModel().set(files);
SwingUtilities.getRoot(namesList).setCursor(Cursor.getDefaultCursor());
}
private class BackgroundMatcher extends SwingWorker<List<Match>, Object> {
private final RenameList primaryList;
private final RenameList secondaryList;
private final Matcher matcher;
public BackgroundMatcher(RenameList primaryList, RenameList secondaryList, SimilarityMetric similarityMetric) {
this.primaryList = primaryList;
this.secondaryList = secondaryList;
matcher = new Matcher(primaryList.getEntries(), secondaryList.getEntries(), similarityMetric);
}
@Override
protected List<Match> doInBackground() throws Exception {
int total = matcher.remaining();
List<Match> matches = new ArrayList<Match>(total);
while (matcher.hasNext() && !isCancelled()) {
firePropertyChange(SwingWorkerProgressMonitor.PROPERTY_NOTE, null, getNote());
matches.add(matcher.next());
setProgress((matches.size() * 100) / total);
firePropertyChange(SwingWorkerProgressMonitor.PROPERTY_PROGRESS_STRING, null, String.format("%d / %d", matches.size(), total));
}
return matches;
}
private String getNote() {
ListEntry current = matcher.getFirstPrimaryEntry();
if (current == null)
current = matcher.getFirstSecondaryEntry();
if (current == null)
return "";
return current.getName();
}
@Override
protected void done() {
if (isCancelled())
return;
try {
List<Match> matches = get();
primaryList.getModel().clear();
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());
}
} catch (Exception e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}
}
}
}

View File

@ -25,10 +25,10 @@ import net.sourceforge.filebot.ui.transferablepolicies.TextTransferablePolicy;
class NamesListTransferablePolicy extends MultiTransferablePolicy {
private final NamesRenameList list;
private final RenameList list;
public NamesListTransferablePolicy(NamesRenameList list) {
public NamesListTransferablePolicy(RenameList list) {
this.list = list;
addPolicy(new FilePolicy());
@ -36,10 +36,10 @@ class NamesListTransferablePolicy extends MultiTransferablePolicy {
}
private void submit(List<ListEntry<?>> entries) {
List<ListEntry<?>> invalidEntries = new ArrayList<ListEntry<?>>();
private void submit(List<ListEntry> entries) {
List<ListEntry> invalidEntries = new ArrayList<ListEntry>();
for (ListEntry<?> entry : entries) {
for (ListEntry entry : entries) {
if (FileBotUtil.isInvalidFileName(entry.getName()))
invalidEntries.add(entry);
}
@ -90,7 +90,7 @@ class NamesListTransferablePolicy extends MultiTransferablePolicy {
private void loadListFiles(List<File> files) {
try {
List<ListEntry<?>> entries = new ArrayList<ListEntry<?>>();
List<ListEntry> entries = new ArrayList<ListEntry>();
for (File file : files) {
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
@ -115,7 +115,7 @@ class NamesListTransferablePolicy extends MultiTransferablePolicy {
private void loadTorrentFiles(List<File> files) {
try {
List<ListEntry<?>> entries = new ArrayList<ListEntry<?>>();
List<ListEntry> entries = new ArrayList<ListEntry>();
for (File file : files) {
Torrent torrent = new Torrent(file);
@ -144,7 +144,7 @@ class NamesListTransferablePolicy extends MultiTransferablePolicy {
@Override
protected void load(String text) {
List<ListEntry<?>> entries = new ArrayList<ListEntry<?>>();
List<ListEntry> entries = new ArrayList<ListEntry>();
String[] lines = text.split("\n");

View File

@ -1,23 +0,0 @@
package net.sourceforge.filebot.ui.panel.rename;
import java.util.List;
import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
class NamesRenameList extends RenameList {
public NamesRenameList() {
setTitle("Names");
setTransferablePolicy(new NamesListTransferablePolicy(this));
}
@SuppressWarnings("unchecked")
public List<ListEntry<?>> getListEntries() {
return (List<ListEntry<?>>) getModel().getCopy();
}
}

View File

@ -18,12 +18,11 @@ import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
public class RenameAction extends AbstractAction {
private NamesRenameList namesList;
private FilesRenameList filesList;
private final RenameList namesList;
private final RenameList filesList;
public RenameAction(NamesRenameList namesList, FilesRenameList filesList) {
public RenameAction(RenameList namesList, RenameList filesList) {
super("Rename", ResourceManager.getIcon("action.rename"));
this.namesList = namesList;
this.filesList = filesList;
@ -33,8 +32,8 @@ public class RenameAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
List<ListEntry<?>> nameEntries = namesList.getListEntries();
List<FileEntry> fileEntries = filesList.getListEntries();
List<ListEntry> nameEntries = namesList.getEntries();
List<ListEntry> fileEntries = filesList.getEntries();
int minLength = Math.min(nameEntries.size(), fileEntries.size());
@ -42,8 +41,8 @@ public class RenameAction extends AbstractAction {
int errors = 0;
for (i = 0; i < minLength; i++) {
FileEntry fileEntry = fileEntries.get(i);
File f = fileEntry.getValue();
FileEntry fileEntry = (FileEntry) fileEntries.get(i);
File f = fileEntry.getFile();
String newName = nameEntries.get(i).toString() + FileFormat.getExtension(f, true);
@ -64,5 +63,4 @@ public class RenameAction extends AbstractAction {
namesList.repaint();
filesList.repaint();
}
}

View File

@ -6,6 +6,7 @@ import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Box;
@ -17,10 +18,11 @@ import javax.swing.border.EmptyBorder;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.ui.FileBotList;
import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
import net.sourceforge.filebot.ui.transfer.LoadAction;
abstract class RenameList extends FileBotList {
class RenameList extends FileBotList {
public RenameList() {
super(true, false, true);
@ -46,6 +48,12 @@ abstract class RenameList extends FileBotList {
viewport.setBackground(list.getBackground());
}
@SuppressWarnings("unchecked")
public List<ListEntry> getEntries() {
return (List<ListEntry>) getModel().getCopy();
}
private final AbstractAction upAction = new AbstractAction(null, ResourceManager.getIcon("action.up")) {
public void actionPerformed(ActionEvent e) {

View File

@ -31,9 +31,8 @@ import net.sourceforge.filebot.ui.FileBotPanel;
public class RenamePanel extends FileBotPanel {
private NamesRenameList namesList = new NamesRenameList();
private FilesRenameList filesList = new FilesRenameList();
private RenameList namesList = new RenameList();
private RenameList filesList = new RenameList();
private MatchAction matchAction = new MatchAction(namesList, filesList);
@ -47,6 +46,12 @@ public class RenamePanel extends FileBotPanel {
public RenamePanel() {
super("Rename", ResourceManager.getIcon("panel.rename"));
namesList.setTitle("Names");
namesList.setTransferablePolicy(new NamesListTransferablePolicy(namesList));
filesList.setTitle("Files");
filesList.setTransferablePolicy(new FilesListTransferablePolicy(filesList.getModel()));
RenameListCellRenderer cellrenderer = new RenameListCellRenderer(namesList.getModel(), filesList.getModel());
namesList.getListComponent().setCellRenderer(cellrenderer);

View File

@ -118,14 +118,14 @@ class SimilarityPanel extends Box {
fileList.removeListSelectionListener(updateMetricsListener);
}
private ListEntry<?> lastListEntryA = null;
private ListEntry lastListEntryA = null;
private ListEntry<?> lastListEntryB = null;
private ListEntry lastListEntryB = null;
public void updateMetrics() {
ListEntry<?> a = (ListEntry<?>) nameList.getSelectedValue();
ListEntry<?> b = (ListEntry<?>) fileList.getSelectedValue();
ListEntry a = (ListEntry) nameList.getSelectedValue();
ListEntry b = (ListEntry) fileList.getSelectedValue();
if ((a == lastListEntryA) && (b == lastListEntryB))
return;
@ -170,7 +170,7 @@ class SimilarityPanel extends Box {
}
public void update(ListEntry<?> a, ListEntry<?> b) {
public void update(ListEntry a, ListEntry b) {
value.setText(numberFormat.format(metric.getSimilarity(a, b)));
}

View File

@ -35,7 +35,7 @@ import net.sourceforge.tuned.ui.TunedUtil;
public class ValidateNamesDialog extends JDialog {
private final List<ListEntry<?>> entries;
private final List<ListEntry> entries;
private boolean cancelled = true;
@ -44,7 +44,7 @@ public class ValidateNamesDialog extends JDialog {
private final CancelAction cancelAction = new CancelAction();
public ValidateNamesDialog(Window owner, List<ListEntry<?>> entries) {
public ValidateNamesDialog(Window owner, List<ListEntry> entries) {
super(owner, "Invalid Names", ModalityType.DOCUMENT_MODAL);
this.entries = entries;
@ -116,7 +116,7 @@ public class ValidateNamesDialog extends JDialog {
@Override
public void actionPerformed(ActionEvent e) {
for (ListEntry<?> entry : entries) {
for (ListEntry entry : entries) {
String validatedName = FileBotUtil.validateFileName(entry.getName());
entry.setName(validatedName);
}

View File

@ -2,10 +2,10 @@
package net.sourceforge.filebot.ui.panel.rename.entry;
public abstract class AbstractFileEntry<T> extends ListEntry<T> {
public abstract class AbstractFileEntry extends ListEntry {
public AbstractFileEntry(String name, T value) {
super(name, value);
public AbstractFileEntry(String name) {
super(name);
}

View File

@ -7,15 +7,18 @@ import java.io.File;
import net.sourceforge.filebot.FileFormat;
public class FileEntry extends AbstractFileEntry<File> {
public class FileEntry extends AbstractFileEntry {
private final File file;
private final long length;
private final String type;
public FileEntry(File file) {
super(FileFormat.getFileName(file), file);
super(FileFormat.getFileName(file));
this.file = file;
this.length = file.length();
this.type = FileFormat.getFileType(file);
}
@ -30,4 +33,9 @@ public class FileEntry extends AbstractFileEntry<File> {
public String getType() {
return type;
}
public File getFile() {
return file;
}
}

View File

@ -2,15 +2,13 @@
package net.sourceforge.filebot.ui.panel.rename.entry;
public class ListEntry<T> {
public class ListEntry {
private String name;
private T value;
public ListEntry(String name, T value) {
public ListEntry(String name) {
this.name = name;
this.value = value;
}
@ -24,11 +22,6 @@ public class ListEntry<T> {
}
public T getValue() {
return value;
}
@Override
public String toString() {
return getName();

View File

@ -2,10 +2,10 @@
package net.sourceforge.filebot.ui.panel.rename.entry;
public class StringEntry extends ListEntry<String> {
public class StringEntry extends ListEntry {
public StringEntry(String string) {
super(string, string);
super(string);
}
}

View File

@ -3,20 +3,24 @@ package net.sourceforge.filebot.ui.panel.rename.entry;
import net.sourceforge.filebot.FileFormat;
import net.sourceforge.filebot.torrent.Torrent;
import net.sourceforge.filebot.torrent.Torrent.Entry;
public class TorrentEntry extends AbstractFileEntry<Torrent.Entry> {
public class TorrentEntry extends AbstractFileEntry {
public TorrentEntry(Entry value) {
super(FileFormat.getNameWithoutExtension(value.getName()), value);
private final Entry entry;
public TorrentEntry(Entry entry) {
super(FileFormat.getNameWithoutExtension(entry.getName()));
this.entry = entry;
}
@Override
public long getLength() {
return getValue().getLength();
return entry.getLength();
}
}

View File

@ -7,22 +7,22 @@ import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
public class Match {
private ListEntry<?> a;
private ListEntry<?> b;
private final ListEntry a;
private final ListEntry b;
public Match(ListEntry<?> a, ListEntry<?> b) {
public Match(ListEntry a, ListEntry b) {
this.a = a;
this.b = b;
}
public ListEntry<?> getA() {
public ListEntry getA() {
return a;
}
public ListEntry<?> getB() {
public ListEntry getB() {
return b;
}

View File

@ -2,43 +2,97 @@
package net.sourceforge.filebot.ui.panel.rename.match;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
import net.sourceforge.filebot.ui.panel.rename.similarity.SimilarityMetric;
public class Matcher {
public class Matcher implements Iterable<Match>, Iterator<Match> {
public List<Match> match(List<? extends ListEntry<?>> listA, List<? extends ListEntry<?>> listB, SimilarityMetric similarityMetric) {
List<Match> matches = new ArrayList<Match>();
for (ListEntry<?> entryA : listA) {
float maxSimilarity = -1;
ListEntry<?> mostSimilarEntry = null;
for (ListEntry<?> entryB : listB) {
float similarity = similarityMetric.getSimilarity(entryA, entryB);
if (similarity > maxSimilarity) {
maxSimilarity = similarity;
mostSimilarEntry = entryB;
}
}
if (mostSimilarEntry != null) {
listB.remove(mostSimilarEntry);
}
matches.add(new Match(entryA, mostSimilarEntry));
}
for (ListEntry<?> entryB : listB) {
matches.add(new Match(null, entryB));
}
return matches;
private final LinkedList<ListEntry> primaryList;
private final LinkedList<ListEntry> secondaryList;
private final SimilarityMetric similarityMetric;
public Matcher(List<? extends ListEntry> primaryList, List<? extends ListEntry> secondaryList, SimilarityMetric similarityMetric) {
this.primaryList = new LinkedList<ListEntry>(primaryList);
this.secondaryList = new LinkedList<ListEntry>(secondaryList);
this.similarityMetric = similarityMetric;
}
@Override
public Iterator<Match> iterator() {
return this;
}
@Override
public boolean hasNext() {
return !primaryList.isEmpty() || !secondaryList.isEmpty();
}
@Override
public Match next() {
if (primaryList.isEmpty()) {
return new Match(null, secondaryList.removeFirst());
}
ListEntry primaryEntry = primaryList.removeFirst();
float maxSimilarity = -1;
ListEntry mostSimilarSecondaryEntry = null;
for (ListEntry secondaryEntry : secondaryList) {
float similarity = similarityMetric.getSimilarity(primaryEntry, secondaryEntry);
if (similarity > maxSimilarity) {
maxSimilarity = similarity;
mostSimilarSecondaryEntry = secondaryEntry;
}
}
if (mostSimilarSecondaryEntry != null) {
secondaryList.remove(mostSimilarSecondaryEntry);
}
return new Match(primaryEntry, mostSimilarSecondaryEntry);
}
public ListEntry getFirstPrimaryEntry() {
if (primaryList.isEmpty())
return null;
return primaryList.getFirst();
}
public ListEntry getFirstSecondaryEntry() {
if (secondaryList.isEmpty())
return null;
return secondaryList.getFirst();
}
public int remaining() {
return Math.max(primaryList.size(), secondaryList.size());
}
/**
* The remove operation is not supported by this implementation of <code>Iterator</code>.
*
* @throws UnsupportedOperationException if this method is invoked.
* @see java.util.Iterator
*/
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}

View File

@ -9,10 +9,10 @@ import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
public class LengthEqualsMetric extends SimilarityMetric {
@Override
public float getSimilarity(ListEntry<?> a, ListEntry<?> b) {
if (a instanceof AbstractFileEntry && b instanceof AbstractFileEntry) {
long lengthA = ((AbstractFileEntry<?>) a).getLength();
long lengthB = ((AbstractFileEntry<?>) b).getLength();
public float getSimilarity(ListEntry a, ListEntry b) {
if ((a instanceof AbstractFileEntry) && (b instanceof AbstractFileEntry)) {
long lengthA = ((AbstractFileEntry) a).getLength();
long lengthB = ((AbstractFileEntry) b).getLength();
if (lengthA == lengthB)
return 1;

View File

@ -20,7 +20,7 @@ public class MultiSimilarityMetric extends SimilarityMetric implements Iterable<
@Override
public float getSimilarity(ListEntry<?> a, ListEntry<?> b) {
public float getSimilarity(ListEntry a, ListEntry b) {
float similarity = 0;
for (SimilarityMetric metric : similarityMetrics) {

View File

@ -7,7 +7,7 @@ import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
public abstract class SimilarityMetric {
public abstract float getSimilarity(ListEntry<?> a, ListEntry<?> b);
public abstract float getSimilarity(ListEntry a, ListEntry b);
public abstract String getDescription();

View File

@ -8,7 +8,7 @@ import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
public class StringEqualsMetric extends SimilarityMetric {
@Override
public float getSimilarity(ListEntry<?> a, ListEntry<?> b) {
public float getSimilarity(ListEntry a, ListEntry b) {
if (a.getName().equalsIgnoreCase(b.getName())) {
return 1;
}

View File

@ -3,7 +3,6 @@ package net.sourceforge.filebot.ui.panel.rename.similarity;
import net.sourceforge.filebot.ui.panel.rename.entry.ListEntry;
import uk.ac.shef.wit.simmetrics.similaritymetrics.AbstractStringMetric;
import uk.ac.shef.wit.simmetrics.similaritymetrics.MongeElkan;
@ -24,7 +23,7 @@ public class StringSimilarityMetric extends SimilarityMetric {
@Override
public float getSimilarity(ListEntry<?> a, ListEntry<?> b) {
public float getSimilarity(ListEntry a, ListEntry b) {
return metric.getSimilarity(a.getName(), b.getName());
}

View File

@ -2,8 +2,6 @@
package net.sourceforge.filebot.ui.panel.sfv;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@ -11,12 +9,15 @@ import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JProgressBar;
import javax.swing.Timer;
import javax.swing.border.Border;
import net.sourceforge.tuned.ui.TunedUtil;
class TotalProgressPanel extends Box {
private int millisToSetVisible = 200;
private JProgressBar progressBar = new JProgressBar(0, 0);
@ -49,7 +50,13 @@ class TotalProgressPanel extends Box {
Boolean active = (Boolean) evt.getNewValue();
if (active) {
new SetVisibleTimer().start();
TunedUtil.invokeLater(millisToSetVisible, new Runnable() {
@Override
public void run() {
setVisible(ChecksumComputationService.getService().isActive());
}
});
}
} else if (property == ChecksumComputationService.REMAINING_TASK_COUNT_PROPERTY) {
@ -68,22 +75,4 @@ class TotalProgressPanel extends Box {
}
};
private class SetVisibleTimer extends Timer implements ActionListener {
private static final int millisToSetVisible = 200;
public SetVisibleTimer() {
super(millisToSetVisible, null);
addActionListener(this);
setRepeats(false);
}
public void actionPerformed(ActionEvent e) {
setVisible(ChecksumComputationService.getService().isActive());
}
}
}

View File

@ -2,8 +2,6 @@
package net.sourceforge.tuned.ui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@ -13,7 +11,6 @@ import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.OverlayLayout;
import javax.swing.Timer;
public class LoadingOverlayPane extends JComponent {
@ -77,29 +74,21 @@ public class LoadingOverlayPane extends JComponent {
overlayEnabled = b;
if (overlayEnabled) {
new OverlayTimer().start();
TunedUtil.invokeLater(millisToOverlay, new Runnable() {
@Override
public void run() {
if (overlayEnabled) {
loadingLabel.setVisible(true);
}
}
});
} else {
loadingLabel.setVisible(false);
}
}
private class OverlayTimer extends Timer implements ActionListener {
public OverlayTimer() {
super(millisToOverlay, null);
addActionListener(this);
setRepeats(false);
}
public void actionPerformed(ActionEvent e) {
if (overlayEnabled) {
loadingLabel.setVisible(true);
}
}
}
private final PropertyChangeListener loadingListener = new PropertyChangeListener() {
@Override

View File

@ -5,11 +5,14 @@ package net.sourceforge.tuned.ui;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.KeyStroke;
import javax.swing.Timer;
public class TunedUtil {
@ -32,4 +35,22 @@ public class TunedUtil {
return new Point(p.x + d.width / 4, p.y + d.height / 7);
}
public static Timer invokeLater(int delay, final Runnable runnable) {
Timer timer = new Timer(delay, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
runnable.run();
}
});
timer.setRepeats(false);
timer.start();
return timer;
}
}

View File

@ -21,10 +21,6 @@ import javax.swing.SwingConstants;
import javax.swing.border.Border;
/**
* @author Reinhard
*
*/
public class MessageNotification extends NotificationWindow {
public MessageNotification(String head, String text, Icon icon, int timeout) {

View File

@ -6,10 +6,6 @@
package net.sourceforge.tuned.ui.notification;
/**
* @author Reinhard
*
*/
public interface NotificationLayout {
public void add(NotificationWindow notification);

View File

@ -6,14 +6,10 @@
package net.sourceforge.tuned.ui.notification;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
/**
* @author Reinhard
*
*/
public class NotificationManager {
private NotificationLayout layout;
@ -43,13 +39,13 @@ public class NotificationManager {
if (layout == null)
return;
notification.addWindowListener(new RemoveListener(layout));
notification.addComponentListener(new RemoveListener(layout));
layout.add(notification);
notification.setVisible(true);
}
private static class RemoveListener extends WindowAdapter {
private static class RemoveListener extends ComponentAdapter {
private NotificationLayout layout;
@ -59,10 +55,11 @@ public class NotificationManager {
}
public void windowClosing(WindowEvent e) {
NotificationWindow n = (NotificationWindow) e.getSource();
layout.remove(n);
n.dispose();
@Override
public void componentHidden(ComponentEvent e) {
NotificationWindow window = (NotificationWindow) e.getSource();
layout.remove(window);
window.dispose();
}
}

View File

@ -7,25 +7,21 @@ package net.sourceforge.tuned.ui.notification;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import net.sourceforge.tuned.ui.TunedUtil;
/**
* @author Reinhard
*
*/
public class NotificationWindow extends JWindow {
private Timer timer;
private int timeout;
public NotificationWindow(Window owner, int timeout) {
@ -35,6 +31,8 @@ public class NotificationWindow extends JWindow {
public NotificationWindow(Window owner, int timeout, boolean closeOnClick) {
super(owner);
this.timeout = timeout;
setAlwaysOnTop(true);
if (closeOnClick)
@ -42,19 +40,7 @@ public class NotificationWindow extends JWindow {
getGlassPane().setVisible(true);
if (timeout >= 0) {
ActionListener doClose = new ActionListener() {
public void actionPerformed(ActionEvent e) {
close();
}
};
timer = new Timer(timeout, doClose);
timer.setRepeats(false);
addWindowListener(windowListener);
}
addComponentListener(visibleListener);
}
@ -74,33 +60,43 @@ public class NotificationWindow extends JWindow {
public final void close() {
processWindowEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
setVisible(false);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
dispose();
}
});
// component hidden is not fired automatically
processComponentEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_HIDDEN));
}
private WindowAdapter windowListener = new WindowAdapter() {
private ComponentListener visibleListener = new ComponentAdapter() {
private Timer timer;
@Override
public void windowOpened(WindowEvent e) {
timer.start();
public void componentShown(ComponentEvent e) {
if (timeout >= 0) {
timer = TunedUtil.invokeLater(timeout, new Runnable() {
@Override
public void run() {
close();
}
});
}
}
@Override
public void windowClosing(WindowEvent e) {
if (timer != null)
public void componentHidden(ComponentEvent e) {
if (timer != null) {
timer.stop();
}
}
};
private MouseAdapter clickListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
close();
}

View File

@ -17,10 +17,6 @@ import java.util.ListIterator;
import javax.swing.SwingConstants;
/**
* @author Reinhard
*
*/
public class QueueNotificationLayout implements NotificationLayout, SwingConstants {
private ArrayList<NotificationWindow> notificationList = new ArrayList<NotificationWindow>();

View File

@ -13,11 +13,6 @@ import java.awt.Toolkit;
import javax.swing.SwingConstants;
/**
* @author Reinhard
*
*/
public class SimpleNotificationLayout implements NotificationLayout, SwingConstants {
private NotificationWindow currentNotification;