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:
Reinhard Pointner 2009-02-10 19:37:32 +00:00
parent 5674173417
commit dac55956f6
14 changed files with 237 additions and 171 deletions

View File

@ -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);
}
};
} }

View File

@ -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 {

View File

@ -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());
} }
} }
}; };

View File

@ -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);
} }
} }

View File

@ -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;
} }
} }

View File

@ -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();
}
};
} }

View File

@ -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));
} }

View File

@ -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

View File

@ -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;

View File

@ -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;
} }
} }

View File

@ -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);
} }
} }

View File

@ -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;
} }

View File

@ -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) {

View File

@ -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;
}
} }