improvement:
* BackgroundFileTransferablePolicy uses ThreadLocal<Worker> now * support exception handling in BackgroundFileTransferablePolicy changes: * ChecksumComputationTask will only calculate one HashType * added ChecksumRow.dispose() fix: * honor convertValueToString() in SelectDialog
This commit is contained in:
parent
5674173417
commit
dac55956f6
|
@ -44,10 +44,7 @@ public class SelectDialog<T> extends JDialog {
|
||||||
list = new JList(new ArrayListModel(options));
|
list = new JList(new ArrayListModel(options));
|
||||||
list.setSelectedIndex(0);
|
list.setSelectedIndex(0);
|
||||||
|
|
||||||
DefaultFancyListCellRenderer cellRenderer = new DefaultFancyListCellRenderer(4);
|
list.setCellRenderer(new SelectListCellRenderer());
|
||||||
cellRenderer.setHighlightingEnabled(false);
|
|
||||||
|
|
||||||
list.setCellRenderer(cellRenderer);
|
|
||||||
list.addMouseListener(mouseListener);
|
list.addMouseListener(mouseListener);
|
||||||
|
|
||||||
JComponent c = (JComponent) getContentPane();
|
JComponent c = (JComponent) getContentPane();
|
||||||
|
@ -121,4 +118,20 @@ public class SelectDialog<T> extends JDialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
protected class SelectListCellRenderer extends DefaultFancyListCellRenderer {
|
||||||
|
|
||||||
|
public SelectListCellRenderer() {
|
||||||
|
super(4);
|
||||||
|
setHighlightingEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||||
|
super.configureListCellRendererComponent(list, convertValueToString(value), index, isSelected, cellHasFocus);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,13 @@ package net.sourceforge.filebot.ui.panel.analyze;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import net.sourceforge.filebot.ui.panel.analyze.FileTree.AbstractTreeNode;
|
import net.sourceforge.filebot.ui.panel.analyze.FileTree.AbstractTreeNode;
|
||||||
import net.sourceforge.filebot.ui.panel.analyze.FileTree.FileNode;
|
import net.sourceforge.filebot.ui.panel.analyze.FileTree.FileNode;
|
||||||
import net.sourceforge.filebot.ui.panel.analyze.FileTree.FolderNode;
|
import net.sourceforge.filebot.ui.panel.analyze.FileTree.FolderNode;
|
||||||
import net.sourceforge.filebot.ui.transfer.BackgroundFileTransferablePolicy;
|
import net.sourceforge.filebot.ui.transfer.BackgroundFileTransferablePolicy;
|
||||||
|
import net.sourceforge.tuned.ExceptionUtilities;
|
||||||
import net.sourceforge.tuned.FileUtilities;
|
import net.sourceforge.tuned.FileUtilities;
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +48,12 @@ class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<Abstra
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void process(Exception e) {
|
||||||
|
Logger.getLogger("ui").warning(ExceptionUtilities.getRootCause(e).getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void load(List<File> files) {
|
protected void load(List<File> files) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import java.awt.event.ActionEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
|
@ -215,7 +214,7 @@ public class RenamePanel extends FileBotPanel {
|
||||||
model.names().addAll(names);
|
model.names().addAll(names);
|
||||||
model.files().addAll(files);
|
model.files().addAll(files);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.getLogger("ui").log(Level.WARNING, ExceptionUtilities.getRootCause(e).getMessage(), e);
|
Logger.getLogger("ui").warning(ExceptionUtilities.getRootCause(e).getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class ChecksumCell {
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
super.propertyChange(evt);
|
super.propertyChange(evt);
|
||||||
|
|
||||||
propertyChangeSupport.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
|
pcs.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,17 +95,6 @@ public class ChecksumCell {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void dispose() {
|
|
||||||
if (task != null) {
|
|
||||||
task.cancel(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
hashes = null;
|
|
||||||
error = null;
|
|
||||||
task = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public State getState() {
|
public State getState() {
|
||||||
if (hashes != null)
|
if (hashes != null)
|
||||||
return State.READY;
|
return State.READY;
|
||||||
|
@ -121,21 +110,38 @@ public class ChecksumCell {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
// clear property change support first
|
||||||
|
for (PropertyChangeListener listener : pcs.getPropertyChangeListeners()) {
|
||||||
|
pcs.removePropertyChangeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task != null) {
|
||||||
|
task.cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashes = null;
|
||||||
|
error = null;
|
||||||
|
task = null;
|
||||||
|
pcs = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("%s %s", name, hashes);
|
return String.format("%s %s", name, hashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
|
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||||
|
|
||||||
|
|
||||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||||
propertyChangeSupport.addPropertyChangeListener(listener);
|
pcs.addPropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||||
propertyChangeSupport.removePropertyChangeListener(listener);
|
pcs.removePropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,8 @@ package net.sourceforge.filebot.ui.panel.sfv;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.EnumMap;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,21 +15,18 @@ class ChecksumComputationTask extends SwingWorker<Map<HashType, String>, Void> {
|
||||||
private static final int BUFFER_SIZE = 32 * 1024;
|
private static final int BUFFER_SIZE = 32 * 1024;
|
||||||
|
|
||||||
private final File file;
|
private final File file;
|
||||||
|
private final HashType type;
|
||||||
|
|
||||||
|
|
||||||
public ChecksumComputationTask(File file) {
|
public ChecksumComputationTask(File file, HashType type) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Map<HashType, String> doInBackground() throws Exception {
|
protected Map<HashType, String> doInBackground() throws Exception {
|
||||||
Map<HashType, Hash> hashes = new EnumMap<HashType, Hash>(HashType.class);
|
Hash hash = type.newInstance();
|
||||||
|
|
||||||
for (HashType type : HashType.values()) {
|
|
||||||
hashes.put(type, type.newInstance());
|
|
||||||
}
|
|
||||||
|
|
||||||
long length = file.length();
|
long length = file.length();
|
||||||
|
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
|
@ -45,15 +41,13 @@ class ChecksumComputationTask extends SwingWorker<Map<HashType, String>, Void> {
|
||||||
while ((len = in.read(buffer)) >= 0) {
|
while ((len = in.read(buffer)) >= 0) {
|
||||||
position += len;
|
position += len;
|
||||||
|
|
||||||
for (Hash hash : hashes.values()) {
|
|
||||||
hash.update(buffer, 0, len);
|
hash.update(buffer, 0, len);
|
||||||
}
|
|
||||||
|
|
||||||
// update progress
|
// update progress
|
||||||
setProgress((int) ((position * 100) / length));
|
setProgress((int) ((position * 100) / length));
|
||||||
|
|
||||||
// check abort status
|
// check abort status
|
||||||
if (isCancelled() || Thread.interrupted()) {
|
if (isCancelled()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,18 +56,7 @@ class ChecksumComputationTask extends SwingWorker<Map<HashType, String>, Void> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return digest(hashes);
|
return Collections.singletonMap(type, hash.digest());
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Map<HashType, String> digest(Map<HashType, Hash> hashes) {
|
|
||||||
Map<HashType, String> results = new EnumMap<HashType, String>(HashType.class);
|
|
||||||
|
|
||||||
for (Entry<HashType, Hash> entry : hashes.entrySet()) {
|
|
||||||
results.put(entry.getKey(), entry.getValue().digest());
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
package net.sourceforge.filebot.ui.panel.sfv;
|
package net.sourceforge.filebot.ui.panel.sfv;
|
||||||
|
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -56,30 +58,43 @@ public class ChecksumRow {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Collection<ChecksumCell> values() {
|
public void put(ChecksumCell cell) {
|
||||||
return Collections.unmodifiableCollection(hashes.values());
|
ChecksumCell old = hashes.put(cell.getRoot(), cell);
|
||||||
|
|
||||||
|
// dispose of old map entry
|
||||||
|
if (old != null) {
|
||||||
|
old.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update state immediately
|
||||||
public void add(ChecksumCell entry) {
|
|
||||||
hashes.put(entry.getRoot(), entry);
|
|
||||||
updateState();
|
updateState();
|
||||||
|
|
||||||
|
// keep state up-to-date
|
||||||
|
cell.addPropertyChangeListener(updateStateListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void updateState() {
|
public void updateState() {
|
||||||
// update state
|
|
||||||
state = getState(hashes.values());
|
state = getState(hashes.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected State getState(Collection<ChecksumCell> entries) {
|
public void dispose() {
|
||||||
|
for (ChecksumCell cell : hashes.values()) {
|
||||||
|
cell.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
hashes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected State getState(Collection<ChecksumCell> cells) {
|
||||||
// check states before we bother comparing the hash values
|
// check states before we bother comparing the hash values
|
||||||
for (ChecksumCell entry : entries) {
|
for (ChecksumCell cell : cells) {
|
||||||
if (entry.getState() == ChecksumCell.State.ERROR) {
|
if (cell.getState() == ChecksumCell.State.ERROR) {
|
||||||
// one error cell -> error state
|
// one error cell -> error state
|
||||||
return State.ERROR;
|
return State.ERROR;
|
||||||
} else if (entry.getState() != ChecksumCell.State.READY) {
|
} else if (cell.getState() != ChecksumCell.State.READY) {
|
||||||
// one cell that is not ready yet -> unknown state
|
// one cell that is not ready yet -> unknown state
|
||||||
return State.UNKNOWN;
|
return State.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
@ -92,8 +107,8 @@ public class ChecksumRow {
|
||||||
for (HashType type : HashType.values()) {
|
for (HashType type : HashType.values()) {
|
||||||
checksumSet.clear();
|
checksumSet.clear();
|
||||||
|
|
||||||
for (ChecksumCell entry : entries) {
|
for (ChecksumCell cell : cells) {
|
||||||
String checksum = entry.getChecksum(type);
|
String checksum = cell.getChecksum(type);
|
||||||
|
|
||||||
if (checksum != null) {
|
if (checksum != null) {
|
||||||
checksumSet.add(checksum);
|
checksumSet.add(checksum);
|
||||||
|
@ -134,4 +149,12 @@ public class ChecksumRow {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("%s %s", name, hashes);
|
return String.format("%s %s", name, hashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final PropertyChangeListener updateStateListener = new PropertyChangeListener() {
|
||||||
|
|
||||||
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,19 +24,19 @@ public class ChecksumTableExportHandler extends TextFileExportHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canExport() {
|
public boolean canExport() {
|
||||||
return model.getRowCount() > 0 && model.getChecksumList().size() > 0;
|
return model.getRowCount() > 0 && model.getChecksumColumns().size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void export(Formatter out) {
|
public void export(Formatter out) {
|
||||||
export(out, model.getChecksumList().get(0));
|
export(out, model.getChecksumColumns().get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDefaultFileName() {
|
public String getDefaultFileName() {
|
||||||
return getDefaultFileName(model.getChecksumList().get(0));
|
return getDefaultFileName(model.getChecksumColumns().get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class ChecksumTableModel extends AbstractTableModel implements Iterable<Checksum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<File> getChecksumList() {
|
public List<File> getChecksumColumns() {
|
||||||
return Collections.unmodifiableList(columns);
|
return Collections.unmodifiableList(columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ class ChecksumTableModel extends AbstractTableModel implements Iterable<Checksum
|
||||||
rows.add(row);
|
rows.add(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
row.add(entry);
|
row.put(entry);
|
||||||
|
|
||||||
// listen to changes (progress, state)
|
// listen to changes (progress, state)
|
||||||
entry.addPropertyChangeListener(progressListener);
|
entry.addPropertyChangeListener(progressListener);
|
||||||
|
@ -139,10 +139,7 @@ class ChecksumTableModel extends AbstractTableModel implements Iterable<Checksum
|
||||||
|
|
||||||
public void remove(int... index) {
|
public void remove(int... index) {
|
||||||
for (int i : index) {
|
for (int i : index) {
|
||||||
for (ChecksumCell entry : rows.get(i).values()) {
|
rows.get(i).dispose();
|
||||||
entry.removePropertyChangeListener(progressListener);
|
|
||||||
entry.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove rows
|
// remove rows
|
||||||
|
|
|
@ -5,19 +5,24 @@ package net.sourceforge.filebot.ui.panel.sfv;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.border.TitledBorder;
|
import javax.swing.border.TitledBorder;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
import net.sourceforge.filebot.ResourceManager;
|
import net.sourceforge.filebot.ResourceManager;
|
||||||
import net.sourceforge.filebot.ui.FileBotPanel;
|
import net.sourceforge.filebot.ui.FileBotPanel;
|
||||||
import net.sourceforge.filebot.ui.FileTransferableMessageHandler;
|
import net.sourceforge.filebot.ui.FileTransferableMessageHandler;
|
||||||
|
import net.sourceforge.filebot.ui.SelectDialog;
|
||||||
import net.sourceforge.filebot.ui.transfer.LoadAction;
|
import net.sourceforge.filebot.ui.transfer.LoadAction;
|
||||||
import net.sourceforge.filebot.ui.transfer.SaveAction;
|
import net.sourceforge.filebot.ui.transfer.SaveAction;
|
||||||
|
import net.sourceforge.tuned.FileUtilities;
|
||||||
import net.sourceforge.tuned.MessageHandler;
|
import net.sourceforge.tuned.MessageHandler;
|
||||||
import net.sourceforge.tuned.ui.TunedUtilities;
|
import net.sourceforge.tuned.ui.TunedUtilities;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import net.sourceforge.filebot.ui.transfer.BackgroundFileTransferablePolicy;
|
import net.sourceforge.filebot.ui.transfer.BackgroundFileTransferablePolicy;
|
||||||
|
import net.sourceforge.tuned.ExceptionUtilities;
|
||||||
|
|
||||||
|
|
||||||
class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<ChecksumCell> {
|
class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<ChecksumCell> {
|
||||||
|
@ -52,6 +53,12 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<ChecksumCel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void process(Exception e) {
|
||||||
|
Logger.getLogger("ui").warning(ExceptionUtilities.getRootCause(e).getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void loadSfvFile(File sfvFile, Executor executor) {
|
protected void loadSfvFile(File sfvFile, Executor executor) {
|
||||||
try {
|
try {
|
||||||
// don't use new Scanner(File) because of BUG 6368019 (http://bugs.sun.com/view_bug.do?bug_id=6368019)
|
// don't use new Scanner(File) because of BUG 6368019 (http://bugs.sun.com/view_bug.do?bug_id=6368019)
|
||||||
|
@ -60,6 +67,9 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<ChecksumCel
|
||||||
try {
|
try {
|
||||||
Pattern pattern = Pattern.compile("(.+)\\s+(\\p{XDigit}{8})");
|
Pattern pattern = Pattern.compile("(.+)\\s+(\\p{XDigit}{8})");
|
||||||
|
|
||||||
|
// root for relative file paths in sfv file
|
||||||
|
File root = sfvFile.getParentFile();
|
||||||
|
|
||||||
while (scanner.hasNextLine()) {
|
while (scanner.hasNextLine()) {
|
||||||
String line = scanner.nextLine();
|
String line = scanner.nextLine();
|
||||||
|
|
||||||
|
@ -71,21 +81,13 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<ChecksumCel
|
||||||
if (!matcher.matches())
|
if (!matcher.matches())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String filename = matcher.group(1);
|
String name = matcher.group(1);
|
||||||
String checksum = matcher.group(2);
|
String checksum = matcher.group(2);
|
||||||
|
|
||||||
publish(new ChecksumCell(filename, sfvFile, Collections.singletonMap(HashType.CRC32, checksum)));
|
ChecksumCell correct = new ChecksumCell(name, sfvFile, Collections.singletonMap(HashType.CRC32, checksum));
|
||||||
|
ChecksumCell current = createChecksumCell(name, root, new File(root, name), executor);
|
||||||
|
|
||||||
File column = sfvFile.getParentFile();
|
publish(correct, current);
|
||||||
File file = new File(column, filename);
|
|
||||||
|
|
||||||
if (file.exists()) {
|
|
||||||
ChecksumComputationTask task = new ChecksumComputationTask(file);
|
|
||||||
|
|
||||||
publish(new ChecksumCell(filename, column, task));
|
|
||||||
|
|
||||||
executor.execute(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Thread.interrupted()) {
|
if (Thread.interrupted()) {
|
||||||
break;
|
break;
|
||||||
|
@ -150,11 +152,17 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<ChecksumCel
|
||||||
load(f, root, newPrefix, executor);
|
load(f, root, newPrefix, executor);
|
||||||
}
|
}
|
||||||
} else if (file.isFile()) {
|
} else if (file.isFile()) {
|
||||||
ChecksumComputationTask task = new ChecksumComputationTask(file);
|
publish(createChecksumCell(prefix + file.getName(), root, file, executor));
|
||||||
|
|
||||||
publish(new ChecksumCell(prefix + file.getName(), root, task));
|
|
||||||
|
|
||||||
executor.execute(task);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected ChecksumCell createChecksumCell(String name, File root, File file, Executor executor) {
|
||||||
|
ChecksumCell cell = new ChecksumCell(name, root, new ChecksumComputationTask(new File(root, name), HashType.CRC32));
|
||||||
|
|
||||||
|
// start computation task
|
||||||
|
executor.execute(cell.getTask());
|
||||||
|
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,100 +7,94 @@ import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.beans.PropertyChangeSupport;
|
import java.beans.PropertyChangeSupport;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import javax.swing.SwingUtilities;
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
|
|
||||||
import net.sourceforge.tuned.ui.SwingWorkerPropertyChangeAdapter;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferablePolicy {
|
public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferablePolicy {
|
||||||
|
|
||||||
public static final String LOADING_PROPERTY = "loading";
|
public static final String LOADING_PROPERTY = "loading";
|
||||||
|
|
||||||
private BackgroundWorker worker = null;
|
private final ThreadLocal<BackgroundWorker> threadLocalWorker = new ThreadLocal<BackgroundWorker>() {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(Transferable tr) {
|
protected BackgroundWorker initialValue() {
|
||||||
if (isActive())
|
// fail if a non-background-worker thread is trying to access the thread-local worker object
|
||||||
return false;
|
throw new IllegalThreadStateException("Illegal access thread");
|
||||||
|
|
||||||
return super.accept(tr);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final List<BackgroundWorker> workers = new ArrayList<BackgroundWorker>(2);
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void handleTransferable(Transferable tr, TransferAction action) {
|
public void handleTransferable(Transferable tr, TransferAction action) {
|
||||||
List<File> files = getFilesFromTransferable(tr);
|
List<File> files = getFilesFromTransferable(tr);
|
||||||
|
|
||||||
if (action != TransferAction.ADD)
|
if (action != TransferAction.ADD)
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
worker = new BackgroundWorker(files);
|
// create and start worker
|
||||||
worker.addPropertyChangeListener(backgroundWorkerListener);
|
new BackgroundWorker(files).execute();
|
||||||
worker.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public synchronized boolean isActive() {
|
public void reset() {
|
||||||
return worker != null && !worker.isDone();
|
synchronized (workers) {
|
||||||
}
|
for (BackgroundWorker worker : workers) {
|
||||||
|
|
||||||
|
|
||||||
public synchronized void reset() {
|
|
||||||
if (isActive()) {
|
|
||||||
worker.cancel(true);
|
worker.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
workers.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receives data chunks from the publish method asynchronously on the Event Dispatch
|
|
||||||
* Thread.
|
|
||||||
*
|
|
||||||
* @param chunks
|
|
||||||
*/
|
|
||||||
protected abstract void process(List<V> chunks);
|
protected abstract void process(List<V> chunks);
|
||||||
|
|
||||||
|
|
||||||
/**
|
protected abstract void process(Exception e);
|
||||||
* Sends data chunks to the process method.
|
|
||||||
*
|
|
||||||
* @param chunks
|
protected final void publish(V... chunks) {
|
||||||
*/
|
threadLocalWorker.get().offer(chunks);
|
||||||
protected synchronized void publish(V... chunks) {
|
|
||||||
if (worker != null) {
|
|
||||||
worker.publishChunks(chunks);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class BackgroundWorker extends SwingWorker<Void, V> {
|
protected class BackgroundWorker extends SwingWorker<Object, V> {
|
||||||
|
|
||||||
private final List<File> files;
|
private final List<File> files;
|
||||||
|
|
||||||
|
|
||||||
public BackgroundWorker(List<File> files) {
|
public BackgroundWorker(List<File> files) {
|
||||||
this.files = files;
|
this.files = files;
|
||||||
|
// register this worker
|
||||||
|
synchronized (workers) {
|
||||||
|
if (workers.add(this) && workers.size() == 1) {
|
||||||
|
swingPropertyChangeSupport.firePropertyChange(LOADING_PROPERTY, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() {
|
protected Object doInBackground() {
|
||||||
|
// associate this worker with the current (background) thread
|
||||||
|
threadLocalWorker.set(this);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
load(files);
|
load(files);
|
||||||
} catch (Exception e) {
|
} finally {
|
||||||
Logger.getLogger("global").log(Level.WARNING, e.getMessage(), e);
|
threadLocalWorker.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void publishChunks(V... chunks) {
|
public void offer(V... chunks) {
|
||||||
if (!isCancelled()) {
|
if (!isCancelled()) {
|
||||||
publish(chunks);
|
publish(chunks);
|
||||||
}
|
}
|
||||||
|
@ -113,31 +107,54 @@ public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferab
|
||||||
BackgroundFileTransferablePolicy.this.process(chunks);
|
BackgroundFileTransferablePolicy.this.process(chunks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private final PropertyChangeListener backgroundWorkerListener = new SwingWorkerPropertyChangeAdapter() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void started(PropertyChangeEvent evt) {
|
|
||||||
propertyChangeSupport.firePropertyChange(LOADING_PROPERTY, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void done(PropertyChangeEvent evt) {
|
protected void done() {
|
||||||
propertyChangeSupport.firePropertyChange(LOADING_PROPERTY, true, false);
|
// unregister worker
|
||||||
|
synchronized (workers) {
|
||||||
|
if (workers.remove(this) && workers.isEmpty()) {
|
||||||
|
swingPropertyChangeSupport.firePropertyChange(LOADING_PROPERTY, true, false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCancelled()) {
|
||||||
|
try {
|
||||||
|
// check for exception
|
||||||
|
get();
|
||||||
|
} catch (Exception e) {
|
||||||
|
BackgroundFileTransferablePolicy.this.process(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final PropertyChangeSupport swingPropertyChangeSupport = new PropertyChangeSupport(this) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void firePropertyChange(final PropertyChangeEvent evt) {
|
||||||
|
if (SwingUtilities.isEventDispatchThread()) {
|
||||||
|
super.firePropertyChange(evt);
|
||||||
|
} else {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
swingPropertyChangeSupport.firePropertyChange(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
|
|
||||||
|
|
||||||
|
|
||||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||||
propertyChangeSupport.addPropertyChangeListener(listener);
|
swingPropertyChangeSupport.addPropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||||
propertyChangeSupport.removePropertyChangeListener(listener);
|
swingPropertyChangeSupport.removePropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
package net.sourceforge.tuned.ui;
|
package net.sourceforge.tuned.ui;
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import javax.swing.ListModel;
|
import javax.swing.ListModel;
|
||||||
|
@ -11,23 +10,23 @@ import javax.swing.event.ListDataListener;
|
||||||
|
|
||||||
public class ArrayListModel implements ListModel {
|
public class ArrayListModel implements ListModel {
|
||||||
|
|
||||||
private final ArrayList<Object> data;
|
private final Object[] data;
|
||||||
|
|
||||||
|
|
||||||
public ArrayListModel(Collection<? extends Object> data) {
|
public ArrayListModel(Collection<? extends Object> data) {
|
||||||
this.data = new ArrayList<Object>(data);
|
this.data = data.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getElementAt(int index) {
|
public Object getElementAt(int index) {
|
||||||
return data.get(index);
|
return data[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return data.size();
|
return data.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class LoadingOverlayPane extends JComponent {
|
||||||
animationComponent = new ProgressIndicator();
|
animationComponent = new ProgressIndicator();
|
||||||
animationComponent.setVisible(false);
|
animationComponent.setVisible(false);
|
||||||
|
|
||||||
add(animationComponent, String.format("pos n %s 100%%-%s n", offsetY != null ? offsetY : "8px", offsetX != null ? offsetX : "18px"));
|
add(animationComponent, String.format("pos n %s 100%%-%s n", offsetY != null ? offsetY : "8px", offsetX != null ? offsetX : "20px"));
|
||||||
add(component, "grow");
|
add(component, "grow");
|
||||||
|
|
||||||
if (propertyChangeSource != null) {
|
if (propertyChangeSource != null) {
|
||||||
|
|
|
@ -37,22 +37,9 @@ public class ProgressIndicator extends JComponent {
|
||||||
private final Dimension baseSize = new Dimension(32, 32);
|
private final Dimension baseSize = new Dimension(32, 32);
|
||||||
|
|
||||||
private double alpha = 0;
|
private double alpha = 0;
|
||||||
private double speed = 1.2;
|
private double speed = 24;
|
||||||
|
|
||||||
private final Timer updateTimer = new Timer(20, new ActionListener() {
|
private Timer updateTimer;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
Timer timer = (Timer) e.getSource();
|
|
||||||
|
|
||||||
alpha += (timer.getDelay() * speed) / 1000;
|
|
||||||
|
|
||||||
if (alpha >= 1)
|
|
||||||
alpha -= Math.floor(alpha);
|
|
||||||
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
public ProgressIndicator() {
|
public ProgressIndicator() {
|
||||||
|
@ -74,6 +61,13 @@ public class ProgressIndicator extends JComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void animateOnce() {
|
||||||
|
if ((alpha += (speed / 1000)) >= 1) {
|
||||||
|
alpha -= Math.floor(alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintComponent(Graphics g) {
|
public void paintComponent(Graphics g) {
|
||||||
Graphics2D g2d = (Graphics2D) g;
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
|
@ -123,12 +117,26 @@ public class ProgressIndicator extends JComponent {
|
||||||
|
|
||||||
|
|
||||||
public void startAnimation() {
|
public void startAnimation() {
|
||||||
updateTimer.restart();
|
if (updateTimer == null) {
|
||||||
|
updateTimer = new Timer(20, new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
animateOnce();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updateTimer.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void stopAnimation() {
|
public void stopAnimation() {
|
||||||
|
if (updateTimer != null) {
|
||||||
updateTimer.stop();
|
updateTimer.stop();
|
||||||
|
updateTimer = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue