1 |
/* Timer.java -- |
/* Timer.java -- |
2 |
Copyright (C) 2002, 2004 Free Software Foundation, Inc. |
Copyright (C) 2002, 2004 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
35 |
obligated to do so. If you do not wish to do so, delete this |
obligated to do so. If you do not wish to do so, delete this |
36 |
exception statement from your version. */ |
exception statement from your version. */ |
37 |
|
|
|
|
|
38 |
package javax.swing; |
package javax.swing; |
39 |
|
|
40 |
import java.awt.event.ActionEvent; |
import java.awt.event.ActionEvent; |
41 |
import java.awt.event.ActionListener; |
import java.awt.event.ActionListener; |
42 |
import java.io.Serializable; |
import java.io.Serializable; |
43 |
import java.util.EventListener; |
import java.util.EventListener; |
|
|
|
44 |
import javax.swing.event.EventListenerList; |
import javax.swing.event.EventListenerList; |
45 |
|
|
46 |
|
|
47 |
|
/** |
48 |
|
* DOCUMENT ME! |
49 |
|
*/ |
50 |
public class Timer implements Serializable |
public class Timer implements Serializable |
51 |
{ |
{ |
52 |
|
/** DOCUMENT ME! */ |
53 |
private static final long serialVersionUID = -1116180831621385484L; |
private static final long serialVersionUID = -1116180831621385484L; |
54 |
|
|
55 |
|
/** DOCUMENT ME! */ |
56 |
protected EventListenerList listenerList = new EventListenerList(); |
protected EventListenerList listenerList = new EventListenerList(); |
57 |
|
|
58 |
// This object manages a "queue" of virtual actionEvents, maintained as a |
// This object manages a "queue" of virtual actionEvents, maintained as a |
59 |
// simple long counter. When the timer expires, a new event is queued, |
// simple long counter. When the timer expires, a new event is queued, |
60 |
// and a dispatcher object is pushed into the system event queue. When |
// and a dispatcher object is pushed into the system event queue. When |
62 |
// ActionEvents as have been queued, unless the timer is set to |
// ActionEvents as have been queued, unless the timer is set to |
63 |
// coalescing mode, in which case it will fire only one ActionEvent. |
// coalescing mode, in which case it will fire only one ActionEvent. |
64 |
|
|
65 |
|
/** DOCUMENT ME! */ |
66 |
private long queue; |
private long queue; |
67 |
|
|
68 |
|
/** DOCUMENT ME! */ |
69 |
private Object queueLock = new Object(); |
private Object queueLock = new Object(); |
70 |
|
|
71 |
|
/** DOCUMENT ME! */ |
72 |
|
private Waker waker; |
73 |
|
|
74 |
|
/** |
75 |
|
* DOCUMENT ME! |
76 |
|
*/ |
77 |
private void queueEvent() |
private void queueEvent() |
78 |
{ |
{ |
79 |
synchronized (queueLock) |
synchronized (queueLock) |
80 |
{ |
{ |
81 |
queue++; |
queue++; |
82 |
if (queue == 1) |
if (queue == 1) |
83 |
SwingUtilities.invokeLater(new Runnable() { public void run() { drainEvents(); } }); |
SwingUtilities.invokeLater(new Runnable() |
84 |
|
{ |
85 |
|
public void run() |
86 |
|
{ |
87 |
|
drainEvents(); |
88 |
|
} |
89 |
|
}); |
90 |
|
|
91 |
} |
} |
92 |
} |
} |
93 |
|
|
94 |
|
/** |
95 |
|
* DOCUMENT ME! |
96 |
|
*/ |
97 |
private void drainEvents() |
private void drainEvents() |
98 |
{ |
{ |
99 |
synchronized (queueLock) |
synchronized (queueLock) |
100 |
{ |
{ |
101 |
if (isCoalesce()) |
if (isCoalesce()) |
102 |
{ |
{ |
103 |
if (queue > 0) |
if (queue > 0) |
104 |
fireActionPerformed(); |
fireActionPerformed(); |
105 |
} |
} |
106 |
else |
else |
107 |
{ |
{ |
108 |
while(queue > 0) |
while (queue > 0) |
109 |
{ |
{ |
110 |
fireActionPerformed(); |
fireActionPerformed(); |
111 |
queue--; |
queue--; |
112 |
} |
} |
113 |
} |
} |
114 |
queue = 0; |
queue = 0; |
115 |
} |
} |
116 |
} |
} |
|
|
|
117 |
|
|
118 |
static boolean logTimers; |
static boolean logTimers; |
119 |
|
|
120 |
|
/** DOCUMENT ME! */ |
121 |
boolean coalesce = true; |
boolean coalesce = true; |
122 |
|
|
123 |
|
/** DOCUMENT ME! */ |
124 |
boolean repeats = true; |
boolean repeats = true; |
125 |
|
|
126 |
|
/** DOCUMENT ME! */ |
127 |
boolean running; |
boolean running; |
128 |
|
|
129 |
|
/** DOCUMENT ME! */ |
130 |
int ticks; |
int ticks; |
131 |
|
|
132 |
|
/** DOCUMENT ME! */ |
133 |
int delay; |
int delay; |
134 |
|
|
135 |
|
/** DOCUMENT ME! */ |
136 |
int initialDelay; |
int initialDelay; |
137 |
|
|
138 |
private class Waker |
/** |
139 |
extends Thread |
* DOCUMENT ME! |
140 |
|
*/ |
141 |
|
private class Waker extends Thread |
142 |
{ |
{ |
143 |
|
/** |
144 |
|
* DOCUMENT ME! |
145 |
|
*/ |
146 |
public void run() |
public void run() |
147 |
{ |
{ |
148 |
running = true; |
running = true; |
149 |
try |
try |
150 |
{ |
{ |
151 |
|
sleep(initialDelay); |
152 |
|
|
153 |
sleep(initialDelay); |
while (running) |
154 |
|
{ |
155 |
while (running) |
try |
156 |
{ |
{ |
157 |
sleep(delay); |
sleep(delay); |
158 |
queueEvent(); |
} |
159 |
|
catch (InterruptedException e) |
160 |
if (logTimers) |
{ |
161 |
System.out.println("javax.swing.Timer -> clocktick"); |
return; |
162 |
|
} |
163 |
if (! repeats) |
queueEvent(); |
164 |
break; |
|
165 |
} |
if (logTimers) |
166 |
running = false; |
System.out.println("javax.swing.Timer -> clocktick"); |
167 |
} |
|
168 |
catch (Exception e) |
if (! repeats) |
169 |
|
break; |
170 |
|
} |
171 |
|
running = false; |
172 |
|
} |
173 |
|
catch (Exception e) |
174 |
{ |
{ |
175 |
System.out.println("swing.Timer::" + e); |
System.out.println("swing.Timer::" + e); |
176 |
} |
} |
177 |
} |
} |
178 |
} |
} |
179 |
|
|
180 |
|
/** |
181 |
|
* Creates a new Timer object. |
182 |
|
* |
183 |
|
* @param d DOCUMENT ME! |
184 |
|
* @param listener DOCUMENT ME! |
185 |
|
*/ |
186 |
public Timer(int d, ActionListener listener) |
public Timer(int d, ActionListener listener) |
187 |
{ |
{ |
188 |
delay = d; |
delay = d; |
191 |
addActionListener(listener); |
addActionListener(listener); |
192 |
} |
} |
193 |
|
|
194 |
|
/** |
195 |
|
* DOCUMENT ME! |
196 |
|
* |
197 |
|
* @param c DOCUMENT ME! |
198 |
|
*/ |
199 |
public void setCoalesce(boolean c) |
public void setCoalesce(boolean c) |
200 |
{ |
{ |
201 |
coalesce = c; |
coalesce = c; |
202 |
} |
} |
203 |
|
|
204 |
|
/** |
205 |
|
* DOCUMENT ME! |
206 |
|
* |
207 |
|
* @return DOCUMENT ME! |
208 |
|
*/ |
209 |
public boolean isCoalesce() |
public boolean isCoalesce() |
210 |
{ |
{ |
211 |
return coalesce; |
return coalesce; |
212 |
} |
} |
213 |
|
|
214 |
|
/** |
215 |
|
* DOCUMENT ME! |
216 |
|
* |
217 |
|
* @param listener DOCUMENT ME! |
218 |
|
*/ |
219 |
public void addActionListener(ActionListener listener) |
public void addActionListener(ActionListener listener) |
220 |
{ |
{ |
221 |
listenerList.add (ActionListener.class, listener); |
listenerList.add(ActionListener.class, listener); |
222 |
} |
} |
223 |
|
|
224 |
|
/** |
225 |
|
* DOCUMENT ME! |
226 |
|
* |
227 |
|
* @param listener DOCUMENT ME! |
228 |
|
*/ |
229 |
public void removeActionListener(ActionListener listener) |
public void removeActionListener(ActionListener listener) |
230 |
{ |
{ |
231 |
listenerList.remove (ActionListener.class, listener); |
listenerList.remove(ActionListener.class, listener); |
232 |
} |
} |
233 |
|
|
234 |
/** |
/** |
235 |
|
* DOCUMENT ME! |
236 |
|
* |
237 |
|
* @param listenerType DOCUMENT ME! |
238 |
|
* |
239 |
|
* @return DOCUMENT ME! |
240 |
|
* |
241 |
* @since 1.3 |
* @since 1.3 |
242 |
*/ |
*/ |
243 |
public EventListener[] getListeners (Class listenerType) |
public EventListener[] getListeners(Class listenerType) |
244 |
{ |
{ |
245 |
return listenerList.getListeners (listenerType); |
return listenerList.getListeners(listenerType); |
246 |
} |
} |
247 |
|
|
248 |
/** |
/** |
249 |
|
* DOCUMENT ME! |
250 |
|
* |
251 |
|
* @return DOCUMENT ME! |
252 |
|
* |
253 |
* @since 1.4 |
* @since 1.4 |
254 |
*/ |
*/ |
255 |
public ActionListener[] getActionListeners () |
public ActionListener[] getActionListeners() |
256 |
{ |
{ |
257 |
return (ActionListener[]) listenerList.getListeners (ActionListener.class); |
return (ActionListener[]) listenerList.getListeners(ActionListener.class); |
258 |
} |
} |
259 |
|
|
260 |
protected void fireActionPerformed (ActionEvent event) |
/** |
261 |
|
* DOCUMENT ME! |
262 |
|
* |
263 |
|
* @param event DOCUMENT ME! |
264 |
|
*/ |
265 |
|
protected void fireActionPerformed(ActionEvent event) |
266 |
{ |
{ |
267 |
ActionListener[] listeners = getActionListeners(); |
ActionListener[] listeners = getActionListeners(); |
268 |
|
|
269 |
for (int i = 0; i < listeners.length; i++) |
for (int i = 0; i < listeners.length; i++) |
270 |
{ |
listeners[i].actionPerformed(event); |
|
listeners [i].actionPerformed (event); |
|
|
} |
|
271 |
} |
} |
272 |
|
|
273 |
void fireActionPerformed () |
/** |
274 |
|
* DOCUMENT ME! |
275 |
|
*/ |
276 |
|
void fireActionPerformed() |
277 |
{ |
{ |
278 |
fireActionPerformed (new ActionEvent (this, ticks++, "Timer")); |
fireActionPerformed(new ActionEvent(this, ticks++, "Timer")); |
279 |
} |
} |
280 |
|
|
281 |
|
/** |
282 |
|
* DOCUMENT ME! |
283 |
|
* |
284 |
|
* @param lt DOCUMENT ME! |
285 |
|
*/ |
286 |
public static void setLogTimers(boolean lt) |
public static void setLogTimers(boolean lt) |
287 |
{ |
{ |
288 |
logTimers = lt; |
logTimers = lt; |
289 |
} |
} |
290 |
|
|
291 |
|
/** |
292 |
|
* DOCUMENT ME! |
293 |
|
* |
294 |
|
* @return DOCUMENT ME! |
295 |
|
*/ |
296 |
public static boolean getLogTimers() |
public static boolean getLogTimers() |
297 |
{ |
{ |
298 |
return logTimers; |
return logTimers; |
299 |
} |
} |
300 |
|
|
301 |
|
/** |
302 |
|
* DOCUMENT ME! |
303 |
|
* |
304 |
|
* @param d DOCUMENT ME! |
305 |
|
*/ |
306 |
public void setDelay(int d) |
public void setDelay(int d) |
307 |
{ |
{ |
308 |
delay = d; |
delay = d; |
309 |
} |
} |
310 |
|
|
311 |
|
/** |
312 |
|
* DOCUMENT ME! |
313 |
|
* |
314 |
|
* @return DOCUMENT ME! |
315 |
|
*/ |
316 |
public int getDelay() |
public int getDelay() |
317 |
{ |
{ |
318 |
return delay; |
return delay; |
319 |
} |
} |
320 |
|
|
321 |
|
/** |
322 |
|
* DOCUMENT ME! |
323 |
|
* |
324 |
|
* @param i DOCUMENT ME! |
325 |
|
*/ |
326 |
public void setInitialDelay(int i) |
public void setInitialDelay(int i) |
327 |
{ |
{ |
328 |
initialDelay = i; |
initialDelay = i; |
329 |
} |
} |
330 |
|
|
331 |
|
/** |
332 |
|
* DOCUMENT ME! |
333 |
|
* |
334 |
|
* @return DOCUMENT ME! |
335 |
|
*/ |
336 |
public int getInitialDelay() |
public int getInitialDelay() |
337 |
{ |
{ |
338 |
return initialDelay; |
return initialDelay; |
339 |
} |
} |
340 |
|
|
341 |
|
/** |
342 |
|
* DOCUMENT ME! |
343 |
|
* |
344 |
|
* @param r DOCUMENT ME! |
345 |
|
*/ |
346 |
public void setRepeats(boolean r) |
public void setRepeats(boolean r) |
347 |
{ |
{ |
348 |
repeats = r; |
repeats = r; |
349 |
} |
} |
350 |
|
|
351 |
|
/** |
352 |
|
* DOCUMENT ME! |
353 |
|
* |
354 |
|
* @return DOCUMENT ME! |
355 |
|
*/ |
356 |
public boolean isRepeats() |
public boolean isRepeats() |
357 |
{ |
{ |
358 |
return repeats; |
return repeats; |
359 |
} |
} |
360 |
|
|
361 |
|
/** |
362 |
|
* DOCUMENT ME! |
363 |
|
* |
364 |
|
* @return DOCUMENT ME! |
365 |
|
*/ |
366 |
public boolean isRunning() |
public boolean isRunning() |
367 |
{ |
{ |
368 |
return running; |
return running; |
369 |
} |
} |
370 |
|
|
371 |
|
/** |
372 |
|
* DOCUMENT ME! |
373 |
|
*/ |
374 |
public void start() |
public void start() |
375 |
{ |
{ |
376 |
if (isRunning()) |
if (isRunning()) |
|
{ |
|
|
System.err.println("attempt to start a running timer"); |
|
377 |
return; |
return; |
378 |
} |
waker = new Waker(); |
379 |
new Waker().start(); |
waker.start(); |
380 |
} |
} |
381 |
|
|
382 |
|
/** |
383 |
|
* DOCUMENT ME! |
384 |
|
*/ |
385 |
public void restart() |
public void restart() |
386 |
{ |
{ |
387 |
synchronized (queueLock) |
stop(); |
|
{ |
|
|
queue = 0; |
|
|
} |
|
388 |
start(); |
start(); |
389 |
} |
} |
390 |
|
|
391 |
|
/** |
392 |
|
* DOCUMENT ME! |
393 |
|
*/ |
394 |
public void stop() |
public void stop() |
395 |
{ |
{ |
396 |
running = false; |
running = false; |
397 |
|
waker.interrupt(); |
398 |
|
synchronized (queueLock) |
399 |
|
{ |
400 |
|
queue = 0; |
401 |
|
} |
402 |
} |
} |
403 |
} |
} |