Source code: echopoint/Timer.java
1 package echopoint;
2
3 /*
4 * This file is part of the Echo Point Project. This project is a collection
5 * of Components that have extended the Echo Web Application Framework.
6 *
7 * EchoPoint is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * EchoPoint is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Echo Point; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 import java.util.EventListener;
23
24 import nextapp.echo.Component;
25 import nextapp.echo.event.ActionEvent;
26 import nextapp.echo.event.ActionListener;
27
28 import echopoint.util.reflect.ReflectionSetter;
29
30 /**
31 *
32 * The <code>Timer</code> class is a <code>Component</code>
33 * that causes an action to occur at a predefined rate.
34 * <br>
35 * Each <code>Timer</code> has a list of <code>ActionListeners</code> and a
36 * delay ( the time between <code>actionPerfomed()</code> calls).
37 * <br>
38 * When delay milliseconds have passed, a <code>Timer</code> sends the
39 * <code>actionPerformed()</code> message to its listeners.
40 * <br>
41 * This cycle repeats until <code>stop()</code> is called, or
42 * halts immediately if the Timer is configured to
43 * send its message just once.
44 * <br>
45 * Note that this is a very coarse timer. The timer is run on the
46 * client and the timeout must travel back to the server before any
47 * other code can be notified of this event. Therefore the granuality
48 * of the timer cannot be gaurunteed, as it depends on the client speed and
49 * the network speed between the client and server.
50 * <br>
51 * This class is mostly useful for causing the client to update without having
52 * to have the user click on anything.
53 * <br>
54 * You can only have one effective Timer on a <code>Window</code> at a time.
55 * This is because once the lowest delay timer has popped, any screen updates
56 * will cause all Timers on that <code>Window</code> to be reset to their
57 * respective starting delays, regardless of how much time has passed since the
58 * last event happened on a given timer.
59 * <br>
60 * The reason the Timer is fired on the client rather than via a thread on the server,
61 * is to help support many clients (thousands). Each client is running their
62 * own timers, using their own processing power. If a single thread was created for
63 * all Timers (or worse one per client) then the system would eventually grind to a halt.
64 * <br>
65 * @author Brad Baker
66 */
67
68 public class Timer extends Component implements ReflectionSetter {
69
70 public static final String TIMER_CHANGED_PROPERTY = "timer";
71
72 private String actionCommand = "";
73 private int delay = -1;
74 private boolean hasFired = false;
75 private int initialDelay = -1;
76 private boolean repeats = true;
77 private boolean running = false;
78
79 /**
80 * Creates a <code>Timer</code> that will notify its
81 * listeners every <code>1000</code> milliseconds.
82 */
83 public Timer() {
84 this(1000, null);
85 }
86
87 /**
88 * Creates a <code>Timer</code> that will notify its
89 * listeners every <code>delay</code> milliseconds.
90 */
91 public Timer(int delay) {
92 this(delay, null);
93 }
94 /**
95 * Creates a <code>Timer</code> that will notify its
96 * listeners every <code>delay</code> milliseconds.
97 */
98 public Timer(int delay, ActionListener actionListener) {
99 super();
100 hasFired = false;
101
102 setRepeats(true);
103 setDelay(delay);
104 setInitialDelay(delay);
105 if(actionListener != null)
106 addActionListener(actionListener);
107 }
108 /**
109 * Adds an <code>ActionListener</code> to the Timer.
110 *
111 * @param l The <code>ActionListener</code> to be added.
112 */
113 public void addActionListener(ActionListener l) {
114 listenerList.addListener(ActionListener.class, l);
115 }
116 /**
117 * Notifies all listeners that have registered for this event type.
118 *
119 * @param e The <code>ActionEvent</code> to send.
120 */
121 public void fireActionPerformed(ActionEvent e) {
122 hasFired = true;
123
124 EventListener[] listeners = listenerList.getListeners(ActionListener.class);
125 for (int index = 0; index < listeners.length; ++index) {
126 ((ActionListener) listeners[index]).actionPerformed(e);
127 }
128 }
129 /**
130 * @return the action command for the Timer
131 *
132 */
133 public String getActionCommand() {
134 return actionCommand;
135 }
136 /**
137 * @return The delay in milliseconds of the <code>Timer</code>.
138 */
139 public int getDelay() {
140 return delay;
141 }
142 /**
143 * @return The initial delay in milliseconds of the <code>Timer</code>.
144 */
145 public int getInitialDelay() {
146 return initialDelay;
147 }
148 /**
149 * @return true if the <code>Timer</code> has fired before
150 */
151 public boolean hasFired() {
152 return hasFired;
153 }
154 /**
155 * Returns true if the <code>Timer</code> will send a
156 * <code>actionPerformed()</code> message to its listeners
157 * multiple times.
158 */
159 public boolean isRepeats() {
160 return repeats;
161 }
162 /**
163 * @return true of the <code>Timer</code> is running.
164 */
165 public boolean isRunning() {
166 return running;
167 }
168 /**
169 * Removes an <code>ActionListener</code> from the Timer.
170 *
171 * @param l The <code>ActionListener</code> to be removed.
172 */
173 public void removeActionListener(ActionListener l) {
174 listenerList.removeListener(ActionListener.class, l);
175 }
176 /**
177 * Restarts a <code>Timer</code>, canceling any pending firings, and causing
178 * it to fire with its initial dely.
179 */
180 public void restart() {
181 stop();
182 start();
183 }
184 /**
185 * Sets the Timer's action command.
186 *
187 * @param newValue The new action command for this timer.
188 */
189 public void setActionCommand(String newValue) {
190 String oldValue = actionCommand;
191
192 actionCommand = newValue;
193
194 firePropertyChange(TIMER_CHANGED_PROPERTY, oldValue, newValue);
195 }
196 /**
197 * Sets the <code>Timer's</code> delay, the number of
198 * milliseconds between successive <code>actionPerfomed()</code>
199 * messages to its listeners
200 * <br>
201 * This methods fires a <code>PropertyChangeEvent</code> with a
202 * <code>getPropertyName()</code> value of
203 * <code>Timer.TIMER_CHANGED_PROPERTY</code>
204 *
205 */
206 public void setDelay(int newValue) {
207 newValue = Math.abs(newValue);
208 int oldValue = delay;
209 delay = newValue;
210 firePropertyChange(TIMER_CHANGED_PROPERTY, oldValue, newValue);
211 }
212 /**
213 * Sets the <code>Timer's</code> initial delay. This will be
214 * used for the first "ringing" of the Timer only. Subsequent
215 * ringings will be spaced using the delay property.
216 * <br>
217 * This methods fires a <code>PropertyChangeEvent</code> with a
218 * <code>getPropertyName()</code> value of
219 * <code>Timer.TIMER_CHANGED_PROPERTY</code>
220 *
221 */
222 public void setInitialDelay(int newValue) {
223 newValue = Math.abs(newValue);
224 int oldValue = initialDelay;
225 initialDelay = newValue;
226 firePropertyChange(TIMER_CHANGED_PROPERTY, oldValue, newValue);
227 }
228 /**
229 * Instructs the <code>Timer</code> to send <code>actionPerformed()</code>
230 * to its listeners only once, and then stop.
231 * <br>
232 * This methods fires a <code>PropertyChangeEvent</code> with a
233 * <code>getPropertyName()</code> value of
234 * <code>Timer.TIMER_CHANGED_PROPERTY</code>
235 *
236 */
237 public void setRepeats(boolean newValue) {
238 boolean oldValue = repeats;
239 repeats = newValue;
240 firePropertyChange(TIMER_CHANGED_PROPERTY, oldValue, newValue);
241 }
242 /**
243 * Starts the <code>Timer</code>, causing it to send <code>actionPerformed()</code>
244 * messages to its listeners.
245 */
246 public void start() {
247 boolean oldValue = running;
248 running = true;
249 firePropertyChange(TIMER_CHANGED_PROPERTY, oldValue, running);
250 }
251 /**
252 * Stops the <code>Timer</code>, causing it to stop sending <code>actionPerformed()</code>
253 * messages to its listeners.
254 */
255 public void stop() {
256 boolean oldValue = running;
257 running = false;
258 firePropertyChange(TIMER_CHANGED_PROPERTY, oldValue, running);
259 }
260
261
262 /** @see echopoint.util.ReflectionSetter#set(Field, Object) */
263 public Object set(java.lang.reflect.Field field, Object newValue) throws Exception {
264 Object oldValue = field.get(this); field.set(this,newValue); return oldValue;
265 }
266
267 }