1 package be
.nikiroo
.utils
.ui
;
3 import java
.beans
.PropertyChangeEvent
;
4 import java
.beans
.PropertyChangeListener
;
5 import java
.util
.ArrayList
;
6 import java
.util
.HashMap
;
8 import java
.util
.TreeSet
;
10 import javax
.swing
.SwingWorker
;
13 * This class helps you delay some graphical actions and execute the most recent
14 * ones when under contention.
18 * <li>it takes an ID and an associated {@link SwingWorker} and will call
19 * {@link SwingWorker#execute()} after a small delay (see
20 * {@link DelayWorker#DelayWorker(int)})</li>
21 * <li>if a second call to {@link DelayWorker#delay(String, SwingWorker)} comes
22 * with the same ID before the first one is done, it will be put on a waiting
24 * <li>if a third call still with the same ID comes, its associated worker will
25 * <b>replace</b> the one in the queue (only one worker per ID in the queue,
26 * always the latest one)</li>
27 * <li>when the first worker is done, it will check the waiting queue and
28 * execute that latest worker if any</li>
34 @SuppressWarnings("rawtypes")
35 public class DelayWorker
{
36 private Map
<String
, SwingWorker
> lazyEnCours
;
37 private Object lazyEnCoursLock
;
39 private TreeSet
<String
> wip
;
41 private Object waiter
;
44 private boolean paused
;
48 * Create a new {@link DelayWorker} with the given delay (in milliseconds)
49 * before each drain of the queue.
52 * the delay in milliseconds (can be 0, cannot be negative)
54 public DelayWorker(final int delayMs
) {
56 throw new IllegalArgumentException(
57 "A waiting delay cannot be negative");
60 lazyEnCours
= new HashMap
<String
, SwingWorker
>();
61 lazyEnCoursLock
= new Object();
62 wip
= new TreeSet
<String
>();
63 waiter
= new Object();
67 loop
= new Thread(new Runnable() {
72 Thread
.sleep(delayMs
);
73 } catch (InterruptedException e
) {
76 Map
<String
, SwingWorker
> workers
= new HashMap
<String
, SwingWorker
>();
77 synchronized (lazyEnCoursLock
) {
78 for (String key
: new ArrayList
<String
>(
79 lazyEnCours
.keySet())) {
80 if (!wip
.contains(key
)) {
81 workers
.put(key
, lazyEnCours
.remove(key
));
86 for (final String key
: workers
.keySet()) {
87 SwingWorker worker
= workers
.get(key
);
89 synchronized (lazyEnCoursLock
) {
93 worker
.addPropertyChangeListener(
94 new PropertyChangeListener() {
96 public void propertyChange(
97 PropertyChangeEvent evt
) {
98 synchronized (lazyEnCoursLock
) {
109 synchronized (waiter
) {
114 } catch (InterruptedException e
) {
116 } while (cont
&& paused
);
122 loop
.setDaemon(true);
123 loop
.setName("Loop for DelayWorker");
127 * Start the internal loop that will drain the processing queue. <b>MUST
128 * NOT</b> be started twice (but see {@link DelayWorker#pause()} and
129 * {@link DelayWorker#resume()} instead).
131 public void start() {
136 * Pause the system until {@link DelayWorker#resume()} is called -- note
137 * that it will still continue on the processes currently scheduled to run,
138 * but will pause after that.
140 * Can be called even if already paused, will just do nothing in that
143 public void pause() {
148 * Check if the {@link DelayWorker} is currently paused.
150 * @return TRUE if it is
152 public boolean isPaused() {
157 * Resume the system after a pause.
159 * Can be called even if already running, will just do nothing in that
162 public void resume() {
163 synchronized (waiter
) {
172 * Note: this is final, you <b>MUST NOT</b> call {@link DelayWorker#start()}
173 * a second time (but see {@link DelayWorker#pause()} and
174 * {@link DelayWorker#resume()} instead).
177 synchronized (waiter
) {
184 * Clear all the processes that were put on the queue but not yet scheduled
185 * to be executed -- note that it will still continue on the processes
186 * currently scheduled to run.
188 public void clear() {
189 synchronized (lazyEnCoursLock
) {
196 * Put a new process in the delay queue.
199 * the ID of this process (if you want to skip workers when they
200 * are superseded by a new one, you need to use the same ID key)
202 * the process to delay
204 public void delay(String id
, SwingWorker worker
) {
205 synchronized (lazyEnCoursLock
) {
206 lazyEnCours
.put(id
, worker
);
213 * Wake up the loop thread.
215 private void wakeup() {
216 synchronized (waiter
) {