46 |
import javax.swing.event.EventListenerList; |
import javax.swing.event.EventListenerList; |
47 |
|
|
48 |
/** |
/** |
49 |
* Fires one or more action events after the specified delay. |
* Fires one or more action events after the specified delay. This is |
50 |
|
* a specialised version of <code>java.util.Timer</code> just for |
51 |
|
* firing <code>ActionEvent</code>s. All Timers share one (daemon) |
52 |
|
* Thread (or java.util.Timer). All events are fired from the event |
53 |
|
* queue. |
54 |
|
* |
55 |
* @author Ronald Veldema |
* @author Ronald Veldema |
56 |
* @author Audrius Meskauskas (audriusa@Bionformatics.org) - bug fixes |
* @author Audrius Meskauskas (audriusa@Bionformatics.org) - bug fixes |
57 |
* and documentation comments |
* and documentation comments |
60 |
implements Serializable |
implements Serializable |
61 |
{ |
{ |
62 |
/** |
/** |
63 |
* The timer thread |
* Given to the shared java.util.Timer to (possibly repeatedly) call |
64 |
|
* queueEvent(). |
65 |
*/ |
*/ |
66 |
private class Waker |
private class Task extends java.util.TimerTask |
|
extends Thread |
|
67 |
{ |
{ |
|
/** |
|
|
* Fires events, pausing for required intervals. |
|
|
*/ |
|
68 |
public void run() |
public void run() |
69 |
{ |
{ |
70 |
try |
if (logTimers) |
71 |
{ |
System.out.println("javax.swing.Timer -> queueEvent()"); |
72 |
synchronized (queueLock) |
queueEvent(); |
73 |
{ |
|
74 |
try |
if (!repeats) |
75 |
{ |
task = null; |
|
queueLock.wait(initialDelay); |
|
|
} |
|
|
catch (InterruptedException e) |
|
|
{ |
|
|
// Ignored |
|
|
} |
|
|
|
|
|
if (!running) |
|
|
return; |
|
|
|
|
|
queueEvent(); |
|
|
|
|
|
if (repeats) |
|
|
while (running) |
|
|
{ |
|
|
try |
|
|
{ |
|
|
queueLock.wait(delay); |
|
|
} |
|
|
catch (InterruptedException e) |
|
|
{ |
|
|
// Ignored |
|
|
} |
|
|
|
|
|
if (!running) |
|
|
break; |
|
|
|
|
|
queueEvent(); |
|
|
|
|
|
if (logTimers) |
|
|
System.out.println("javax.swing.Timer -> clocktick"); |
|
|
|
|
|
if (!repeats) |
|
|
break; |
|
|
} |
|
|
running = false; |
|
|
} |
|
|
} |
|
|
finally |
|
|
{ |
|
|
// The timer is no longer running. |
|
|
running = false; |
|
|
} |
|
76 |
} |
} |
77 |
} |
} |
78 |
|
|
94 |
}; |
}; |
95 |
|
|
96 |
/** |
/** |
97 |
|
* The static java.util.Timer daemon which will be used to schedule |
98 |
|
* all javax.swing.Timer.Task objects. The daemon will always be |
99 |
|
* running, even if there's no task scheduled in it. |
100 |
|
*/ |
101 |
|
private static java.util.Timer timer = new java.util.Timer("swing.Timer", |
102 |
|
true); |
103 |
|
|
104 |
|
/** |
105 |
* If <code>true</code>, the timer prints a message to |
* If <code>true</code>, the timer prints a message to |
106 |
* {@link System#out} when firing each event. |
* {@link System#out} when firing each event. |
107 |
*/ |
*/ |
123 |
boolean repeats = true; |
boolean repeats = true; |
124 |
|
|
125 |
/** |
/** |
|
* <code>true</code> if the timer is currently active, firing events |
|
|
* as scheduled. |
|
|
*/ |
|
|
boolean running; |
|
|
|
|
|
/** |
|
126 |
* The delay between subsequent repetetive events. |
* The delay between subsequent repetetive events. |
127 |
*/ |
*/ |
128 |
int delay; |
int delay; |
140 |
int ticks; |
int ticks; |
141 |
|
|
142 |
/** |
/** |
143 |
* Stores the thread that posts events to the queue at required time |
* The task that calls queueEvent(). When null this Timer is stopped. |
|
* intervals. |
|
144 |
*/ |
*/ |
145 |
private Waker waker; |
private Task task; |
146 |
|
|
147 |
/** |
/** |
148 |
* This object manages a "queue" of virtual actionEvents, maintained as a |
* This object manages a "queue" of virtual actionEvents, maintained as a |
337 |
*/ |
*/ |
338 |
public boolean isRunning() |
public boolean isRunning() |
339 |
{ |
{ |
340 |
return running; |
return task != null; |
341 |
} |
} |
342 |
|
|
343 |
/** |
/** |
375 |
*/ |
*/ |
376 |
public void start() |
public void start() |
377 |
{ |
{ |
378 |
synchronized (queueLock) |
Task t = task; |
379 |
|
if (t == null) |
380 |
{ |
{ |
381 |
if (waker != null) |
t = new Task(); |
382 |
return; |
if (isRepeats()) |
383 |
waker = new Waker(); |
timer.schedule(t, getInitialDelay(), getDelay()); |
384 |
waker.start(); |
else |
385 |
|
timer.schedule(t, getInitialDelay()); |
386 |
|
task = t; |
387 |
} |
} |
388 |
} |
} |
389 |
|
|
392 |
*/ |
*/ |
393 |
public void stop() |
public void stop() |
394 |
{ |
{ |
395 |
synchronized (queueLock) |
Task t = task; |
396 |
|
if (t != null) |
397 |
{ |
{ |
398 |
running = false; |
t.cancel(); |
399 |
queue = 0; |
task = null; |
|
if (waker != null) |
|
|
queueLock.notifyAll(); |
|
|
waker = null; |
|
400 |
} |
} |
401 |
} |
} |
402 |
|
|
457 |
*/ |
*/ |
458 |
void queueEvent() |
void queueEvent() |
459 |
{ |
{ |
460 |
synchronized (queueLock) |
synchronized(queueLock) |
461 |
{ |
{ |
462 |
queue++; |
queue++; |
463 |
if (queue == 1) |
if (queue == 1) |
464 |
SwingUtilities.invokeLater(drainer); |
SwingUtilities.invokeLater(drainer); |
465 |
} |
} |
466 |
} |
} |
467 |
} |
} |