Refactor ProgressDialog

This commit is contained in:
Reinhard Pointner 2016-05-08 04:45:48 +08:00
parent 0e126daace
commit b487f25361
3 changed files with 28 additions and 132 deletions

View File

@ -4,11 +4,9 @@ import static net.filebot.Logging.*;
import static net.filebot.UserFiles.*; import static net.filebot.UserFiles.*;
import static net.filebot.util.ExceptionUtilities.*; import static net.filebot.util.ExceptionUtilities.*;
import static net.filebot.util.FileUtilities.*; import static net.filebot.util.FileUtilities.*;
import static net.filebot.util.ui.SwingUI.*;
import java.awt.Color; import java.awt.Color;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.util.ArrayList; import java.util.ArrayList;
@ -18,16 +16,17 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.ListSelectionModel; import javax.swing.ListSelectionModel;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel; import javax.swing.table.TableModel;
@ -38,9 +37,8 @@ import net.filebot.cli.ConflictAction;
import net.filebot.util.FileUtilities; import net.filebot.util.FileUtilities;
import net.filebot.util.ui.GradientStyle; import net.filebot.util.ui.GradientStyle;
import net.filebot.util.ui.LoadingOverlayPane; import net.filebot.util.ui.LoadingOverlayPane;
import net.filebot.util.ui.ProgressDialog; import net.filebot.util.ui.ProgressMonitor;
import net.filebot.util.ui.ProgressDialog.Cancellable; import net.filebot.util.ui.ProgressMonitor.ProgressWorker;
import net.filebot.util.ui.SwingWorkerPropertyChangeAdapter;
import net.filebot.util.ui.notification.SeparatorBorder; import net.filebot.util.ui.notification.SeparatorBorder;
import net.filebot.vfs.FileInfo; import net.filebot.vfs.FileInfo;
import net.filebot.vfs.SimpleFileInfo; import net.filebot.vfs.SimpleFileInfo;
@ -124,33 +122,8 @@ class ExtractTool extends Tool<TableModel> {
if (selectedFile == null) if (selectedFile == null)
return; return;
final ExtractJob job = new ExtractJob(archives, selectedFile, null, true, ConflictAction.AUTO); ExtractWorker worker = new ExtractWorker(archives, selectedFile, null, true, ConflictAction.AUTO);
final ProgressDialog dialog = new ProgressDialog(getWindow(evt.getSource()), job); ProgressMonitor.runTask("Extract", "Extracting files...", worker);
dialog.setLocation(getOffsetLocation(dialog.getOwner()));
dialog.setTitle("Extracting files...");
dialog.setIcon((Icon) getValue(SMALL_ICON));
dialog.setIndeterminate(true);
// close progress dialog when worker is finished
job.addPropertyChangeListener(new SwingWorkerPropertyChangeAdapter() {
@Override
protected void event(String name, Object oldValue, Object newValue) {
if (name.equals("currentFile")) {
String note = "Extracting " + ((File) newValue).getName();
dialog.setNote(note);
dialog.setWindowTitle(note);
}
}
@Override
protected void done(PropertyChangeEvent evt) {
dialog.close();
}
});
job.execute();
dialog.setVisible(true);
} }
}; };
@ -227,7 +200,7 @@ class ExtractTool extends Tool<TableModel> {
} }
protected static class ExtractJob extends SwingWorker<Void, Void> implements Cancellable { protected static class ExtractWorker implements ProgressWorker<Void> {
private final File[] archives; private final File[] archives;
private final File outputFolder; private final File outputFolder;
@ -236,7 +209,7 @@ class ExtractTool extends Tool<TableModel> {
private final boolean forceExtractAll; private final boolean forceExtractAll;
private final ConflictAction conflictAction; private final ConflictAction conflictAction;
public ExtractJob(Collection<File> archives, File outputFolder, FileFilter filter, boolean forceExtractAll, ConflictAction conflictAction) { public ExtractWorker(Collection<File> archives, File outputFolder, FileFilter filter, boolean forceExtractAll, ConflictAction conflictAction) {
this.archives = archives.toArray(new File[archives.size()]); this.archives = archives.toArray(new File[archives.size()]);
this.outputFolder = outputFolder; this.outputFolder = outputFolder;
this.filter = filter; this.filter = filter;
@ -245,11 +218,11 @@ class ExtractTool extends Tool<TableModel> {
} }
@Override @Override
protected Void doInBackground() throws Exception { public Void call(Consumer<String> message, BiConsumer<Long, Long> progress, Supplier<Boolean> cancelled) throws Exception {
for (File file : archives) { for (File file : archives) {
try { try {
// update progress dialog // update progress dialog
firePropertyChange("currentFile", null, file); message.accept(String.format("Extracting %s", file.getName()));
Archive archive = Archive.open(file); Archive archive = Archive.open(file);
try { try {
@ -304,18 +277,13 @@ class ExtractTool extends Tool<TableModel> {
log.log(Level.WARNING, "Failed to extract archive: " + file.getName(), e); log.log(Level.WARNING, "Failed to extract archive: " + file.getName(), e);
} }
if (isCancelled()) { if (cancelled.get()) {
throw new CancellationException(); throw new CancellationException("Extract cancelled");
} }
} }
return null; return null;
} }
@Override
public boolean cancel() {
return cancel(true);
}
} }
} }

View File

@ -3,28 +3,19 @@ package net.filebot.ui.rename;
import static net.filebot.Logging.*; import static net.filebot.Logging.*;
import static net.filebot.util.ui.SwingUI.*; import static net.filebot.util.ui.SwingUI.*;
import java.awt.Cursor;
import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.SwingWorker;
import net.filebot.ResourceManager; import net.filebot.ResourceManager;
import net.filebot.similarity.EpisodeMetrics; import net.filebot.similarity.EpisodeMetrics;
import net.filebot.similarity.Match; import net.filebot.similarity.Match;
import net.filebot.similarity.Matcher; import net.filebot.similarity.Matcher;
import net.filebot.similarity.SimilarityMetric; import net.filebot.util.ui.ProgressMonitor;
import net.filebot.util.ui.ProgressDialog;
import net.filebot.util.ui.ProgressDialog.Cancellable;
import net.filebot.util.ui.SwingWorkerPropertyChangeAdapter;
class MatchAction extends AbstractAction { class MatchAction extends AbstractAction {
@ -48,88 +39,26 @@ class MatchAction extends AbstractAction {
return; return;
} }
BackgroundMatcher backgroundMatcher = new BackgroundMatcher(model, EpisodeMetrics.defaultSequence(true));
backgroundMatcher.execute();
Window window = getWindow(evt.getSource());
window.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try { try {
// wait a for little while (matcher might finish in less than a second) withWaitCursor(evt.getSource(), () -> {
backgroundMatcher.get(2, TimeUnit.SECONDS); Matcher<Object, File> matcher = new Matcher<Object, File>(model.values(), model.candidates(), false, EpisodeMetrics.defaultSequence(true));
} catch (TimeoutException ex) { List<Match<Object, File>> matches = ProgressMonitor.runTask("Match", "Find optimal alignment. This may take a while.", (message, progress, cancelled) -> {
// matcher will probably take a while message.accept(String.format("Checking %d combinations...", matcher.remainingCandidates().size() * matcher.remainingValues().size()));
ProgressDialog dialog = createProgressDialog(window, backgroundMatcher); return matcher.match();
dialog.setLocation(getOffsetLocation(dialog.getOwner())); }).get();
// display progress dialog and stop blocking EDT
dialog.setVisible(true);
} catch (Exception e) {
debug.log(Level.SEVERE, e.getMessage(), e);
} finally {
window.setCursor(Cursor.getDefaultCursor());
}
}
protected ProgressDialog createProgressDialog(Window parent, final BackgroundMatcher worker) {
final ProgressDialog progressDialog = new ProgressDialog(parent, worker);
// configure dialog
progressDialog.setTitle("Matching...");
progressDialog.setNote("Processing...");
progressDialog.setIcon((Icon) getValue(SMALL_ICON));
// close progress dialog when worker is finished
worker.addPropertyChangeListener(new SwingWorkerPropertyChangeAdapter() {
@Override
protected void done(PropertyChangeEvent evt) {
progressDialog.close();
}
});
return progressDialog;
}
protected class BackgroundMatcher extends SwingWorker<List<Match<Object, File>>, Void> implements Cancellable {
private final Matcher<Object, File> matcher;
public BackgroundMatcher(MatchModel<Object, File> model, SimilarityMetric[] metrics) {
// match names against files
this.matcher = new Matcher<Object, File>(model.values(), model.candidates(), false, metrics);
}
@Override
protected List<Match<Object, File>> doInBackground() throws Exception {
return matcher.match();
}
@Override
protected void done() {
if (isCancelled())
return;
try {
List<Match<Object, File>> matches = get();
model.clear();
// put new data into model // put new data into model
model.clear();
model.addAll(matches); model.addAll(matches);
// insert objects that could not be matched at the end of the model // insert objects that could not be matched at the end of the model
model.addAll(matcher.remainingValues(), matcher.remainingCandidates()); model.addAll(matcher.remainingValues(), matcher.remainingCandidates());
} catch (Exception e) { });
debug.log(Level.SEVERE, e.getMessage(), e); } catch (CancellationException e) {
} debug.finest(e::toString);
} catch (Throwable e) {
log.log(Level.WARNING, e.getMessage(), e);
} }
@Override
public boolean cancel() {
return cancel(true);
}
} }
} }

View File

@ -97,9 +97,8 @@ class RenameAction extends AbstractAction {
} else { } else {
// call and wait // call and wait
RenameWorker worker = new RenameWorker(renameMap, renameLog, action); RenameWorker worker = new RenameWorker(renameMap, renameLog, action);
String title = String.format("%s - %s", getApplicationName(), action.getDisplayName());
String message = String.format("%s %d %s. This may take a while.", action.getDisplayName() + "ing", renameMap.size(), renameMap.size() == 1 ? "file" : "files"); String message = String.format("%s %d %s. This may take a while.", action.getDisplayName() + "ing", renameMap.size(), renameMap.size() == 1 ? "file" : "files");
ProgressMonitor.runTask(title, message, worker).get(); ProgressMonitor.runTask(action.getDisplayName(), message, worker).get();
} }
} catch (CancellationException e) { } catch (CancellationException e) {
debug.finest(e::toString); debug.finest(e::toString);