/[classpath]/classpath/javax/swing/Timer.java
ViewVC logotype

Diff of /classpath/javax/swing/Timer.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.17 by audriusa, Thu Feb 24 12:52:57 2005 UTC revision 1.18 by audriusa, Sat Feb 26 20:42:59 2005 UTC
# Line 1  Line 1 
1  /* Timer.java --  /* Timer.java --
2     Copyright (C) 2002, 2004  Free Software Foundation, Inc.     Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 46  import java.util.EventListener; Line 46  import java.util.EventListener;
46  import javax.swing.event.EventListenerList;  import javax.swing.event.EventListenerList;
47    
48  /**  /**
49   * DOCUMENT ME!   * Fires one or more action events after the specified delay.
50     * @author Ronald Veldema
51     * @author Audrius Meskauskas (audriusa@Bionformatics.org) - bug fixes
52     * and documentation comments
53   */   */
54  public class Timer implements Serializable  public class Timer
55      implements Serializable
56  {  {
57    /** DOCUMENT ME! */    /**
58    private static final long serialVersionUID = -1116180831621385484L;     * The timer thread
59       */
60    /** DOCUMENT ME! */    private class Waker
61    protected EventListenerList listenerList = new EventListenerList();      extends Thread
62      {
63    // This object manages a "queue" of virtual actionEvents, maintained as a      /**
64    // simple long counter. When the timer expires, a new event is queued,       * Fires events, pausing for required intervals.
65    // and a dispatcher object is pushed into the system event queue. When       */
66    // the system thread runs the dispatcher, it will fire as many      public void run()
67    // ActionEvents as have been queued, unless the timer is set to      {
68    // coalescing mode, in which case it will fire only one ActionEvent.        running = true;
69          try
70            {
71              sleep(initialDelay);
72    
73    /** DOCUMENT ME! */            queueEvent();
   private long queue;  
74    
75    /** DOCUMENT ME! */            while (running)
76    private Object queueLock = new Object();              {
77                  try
78                    {
79                      sleep(delay);
80                    }
81                  catch (InterruptedException e)
82                    {
83                      return;
84                    }
85                  queueEvent();
86    
87                  if (logTimers)
88                    System.out.println("javax.swing.Timer -> clocktick");
89    
90                  if ( ! repeats)
91                    break;
92                }
93              running = false;
94            }
95          catch (Exception e)
96            {
97              // The timer is no longer running.
98              running = false;
99            }
100        }
101      }
102    
103    /** DOCUMENT ME! */    /**
104    private Waker waker;     * Use serialVersionUID for interoperability.
105       */
106      private static final long serialVersionUID = -1116180831621385484L;
107    
108    private Runnable drainer = new Runnable()    /**
109       * The encloding class, used with {@link SwingUtilities#invokeLater}
110       * to invoke the {@link #drainEvents()}.
111       */
112      private Runnable drainer = new Runnable()
113      {      {
114        public void run()        public void run()
115        {        {
# Line 81  public class Timer implements Serializab Line 118  public class Timer implements Serializab
118      };      };
119    
120    /**    /**
121     * DOCUMENT ME!     * If <code>true</code>, the timer prints a message to
122       * {@link System#out} when firing each event.
123     */     */
124    private void queueEvent()    static boolean logTimers;
   {  
     synchronized (queueLock)  
       {  
         queue++;  
         if (queue == 1)  
           SwingUtilities.invokeLater(drainer);  
       }  
   }  
125    
126    /**    /**
127     * DOCUMENT ME!     * A field to store all listeners who are listening to this timer.
128     */     */
129    private void drainEvents()    protected EventListenerList listenerList = new EventListenerList();
   {  
     synchronized (queueLock)  
       {  
         if (isCoalesce())  
           {  
             if (queue > 0)  
               fireActionPerformed();  
           }  
         else  
           {  
             while (queue > 0)  
               {  
                 fireActionPerformed();  
                 queue--;  
               }  
           }  
         queue = 0;  
       }  
   }  
   
   static boolean logTimers;  
130    
131    /** DOCUMENT ME! */    /**
132       * <code>true</code> if the timer coalesces events.
133       */
134    boolean coalesce = true;    boolean coalesce = true;
135    
136    /** DOCUMENT ME! */    /**
137       * <code>true</code> if the timer is firing repetetive events.
138       */
139    boolean repeats = true;    boolean repeats = true;
140    
141    /** DOCUMENT ME! */    /**
142       * <code>true</code> if the timer is currently active, firing events
143       * as scheduled.
144       */
145    boolean running;    boolean running;
146    
147    /** DOCUMENT ME! */    /**
148    int ticks;     * The delay between subsequent repetetive events.
149       */
   /** DOCUMENT ME! */  
150    int delay;    int delay;
151    
152    /** DOCUMENT ME! */    /**
153       * The initial delay before the first event.
154       */
155    int initialDelay;    int initialDelay;
156    
157    /**    /**
158     * DOCUMENT ME!     * The number of events that have been already fired by this timer.
159       * This is used as a numeric identifier for the next event that would
160       * be fired.
161     */     */
162    private class Waker extends Thread    int ticks;
163    {  
164      /**    /**
165       * DOCUMENT ME!     * Stores the thread that posts events to the queue at required time
166       */     * intervals.
167      public void run()     */
168      {    private Waker waker;
169        running = true;  
170        try    /**
171          {     * This object manages a "queue" of virtual actionEvents, maintained as a
172            sleep(initialDelay);     * simple long counter. When the timer expires, a new event is queued,
173                 * and a dispatcher object is pushed into the system event queue. When
174            queueEvent();     * the system thread runs the dispatcher, it will fire as many
175       * ActionEvents as have been queued, unless the timer is set to
176            while (running)     * coalescing mode, in which case it will fire only one ActionEvent.
177              {     */
178                try    private long queue;
179                  {  
180                    sleep(delay);    /**
181                  }     * <code>synchronized(queueLock)</code> replaces
182                catch (InterruptedException e)     * <code>synchronized(queue)</code> that is not supported by this language.
183                  {     */
184                    return;    private Object queueLock = new Object();
                 }  
               queueEvent();  
   
               if (logTimers)  
                 System.out.println("javax.swing.Timer -> clocktick");  
   
               if (! repeats)  
                 break;  
             }  
           running = false;  
         }  
       catch (Exception e)  
         {  
 //        System.out.println("swing.Timer::" + e);  
         }  
     }  
   }  
185    
186    /**    /**
187     * Creates a new Timer object.     * Creates a new Timer object.
# Line 191  public class Timer implements Serializab Line 193  public class Timer implements Serializab
193    public Timer(int d, ActionListener listener)    public Timer(int d, ActionListener listener)
194    {    {
195      delay = d;      delay = d;
196          initialDelay = d;      initialDelay = d;
197    
198      if (listener != null)      if (listener != null)
199        addActionListener(listener);        addActionListener(listener);
200    }    }
201    
202    /**    /**
203     * DOCUMENT ME!     * Get the array of action listeners.
204     *     *
205     * @param c DOCUMENT ME!     * @return the array of action listeners that are listening for the events,
206     */     * fired by this timer
   public void setCoalesce(boolean c)  
   {  
     coalesce = c;  
   }  
   
   /**  
    * DOCUMENT ME!  
207     *     *
208     * @return DOCUMENT ME!     * @since 1.4
209     */     */
210    public boolean isCoalesce()    public ActionListener[] getActionListeners()
211    {    {
212      return coalesce;      return (ActionListener[]) listenerList.getListeners(ActionListener.class);
213    }    }
214    
215    /**    /**
216     * DOCUMENT ME!     * Sets whether the Timer coalesces multiple pending event firings.
217       * If the coalescing is enabled, the multiple events that have not been
218       * fired on time are replaced by the single event. The events may not
219       * be fired on time if the application is busy.
220     *     *
221     * @param listener DOCUMENT ME!     * @param c <code>true</code> (default) to enable the event coalescing,
222       * <code>false</code> otherwise
223     */     */
224    public void addActionListener(ActionListener listener)    public void setCoalesce(boolean c)
225    {    {
226      listenerList.add(ActionListener.class, listener);      coalesce = c;
227    }    }
228    
229    /**    /**
230     * DOCUMENT ME!     * Checks if the Timer coalesces multiple pending event firings.
231       * If the coalescing is enabled, the multiple events that have not been
232       * fired on time are replaced by the single event. The events may not
233       * be fired on time if the application is busy.
234     *     *
235     * @param listener DOCUMENT ME!     * @return <code>true</code> if the coalescing is enabled,
236       * <code>false</code> otherwise
237     */     */
238    public void removeActionListener(ActionListener listener)    public boolean isCoalesce()
239    {    {
240      listenerList.remove(ActionListener.class, listener);      return coalesce;
241    }    }
242    
243    /**    /**
244     * DOCUMENT ME!     * Get the event listeners of the given type that are listening for the
245     *     * events, fired by this timer.
    * @param listenerType DOCUMENT ME!  
246     *     *
247     * @return DOCUMENT ME!     * @param listenerType the listener type (for example, ActionListener.class)
248     *     *
249       * @return the array of event listeners that are listening for the events,
250       * fired by this timer
251     * @since 1.3     * @since 1.3
252     */     */
253    public EventListener[] getListeners(Class listenerType)    public EventListener[] getListeners(Class listenerType)
# Line 252  public class Timer implements Serializab Line 256  public class Timer implements Serializab
256    }    }
257    
258    /**    /**
259     * DOCUMENT ME!     * Set the timer logging state. If it is set to <code>true</code>, the
260     *     * timer prints a message to {@link System#out} when firing each
261     * @return DOCUMENT ME!     * action event.
    *  
    * @since 1.4  
    */  
   public ActionListener[] getActionListeners()  
   {  
     return (ActionListener[]) listenerList.getListeners(ActionListener.class);  
   }  
   
   /**  
    * DOCUMENT ME!  
    *  
    * @param event DOCUMENT ME!  
    */  
   protected void fireActionPerformed(ActionEvent event)  
   {  
     ActionListener[] listeners = getActionListeners();  
   
     for (int i = 0; i < listeners.length; i++)  
       listeners[i].actionPerformed(event);  
   }  
   
   /**  
    * DOCUMENT ME!  
    */  
   void fireActionPerformed()  
   {  
     fireActionPerformed(new ActionEvent(this, ticks++, "Timer"));  
   }  
   
   /**  
    * DOCUMENT ME!  
262     *     *
263     * @param lt DOCUMENT ME!     * @param lt <code>true</code> if logging is enabled, <code>false</code>
264       * (default value) otherwise
265     */     */
266    public static void setLogTimers(boolean lt)    public static void setLogTimers(boolean lt)
267    {    {
# Line 295  public class Timer implements Serializab Line 269  public class Timer implements Serializab
269    }    }
270    
271    /**    /**
272     * DOCUMENT ME!     * Return the logging state.
273     *     *
274     * @return DOCUMENT ME!     * @return <code>true</code> if the timer is printing a message to
275       * {@link System#out}
276       * when firing each action event
277     */     */
278    public static boolean getLogTimers()    public static boolean getLogTimers()
279    {    {
# Line 305  public class Timer implements Serializab Line 281  public class Timer implements Serializab
281    }    }
282    
283    /**    /**
284     * DOCUMENT ME!     * Set the delay between firing the subsequent events.
285       * This parameter does not change the value of the initial delay before
286       * firing the first event.
287     *     *
288     * @param d DOCUMENT ME!     * @param d The time gap between the subsequent events, in milliseconds
289     */     */
290    public void setDelay(int d)    public void setDelay(int d)
291    {    {
# Line 315  public class Timer implements Serializab Line 293  public class Timer implements Serializab
293    }    }
294    
295    /**    /**
296     * DOCUMENT ME!     * Get the delay between firing the subsequent events.
297     *     *
298     * @return DOCUMENT ME!     * @return The delay between subsequent events, in milliseconds
299     */     */
300    public int getDelay()    public int getDelay()
301    {    {
# Line 325  public class Timer implements Serializab Line 303  public class Timer implements Serializab
303    }    }
304    
305    /**    /**
306     * DOCUMENT ME!     * Set the intial delay before firing the first event since calling
307       * the {@link #start()} method. If the initial delay has not been
308       * set, it is assumed having the same value as the delay between the
309       * subsequent events.
310     *     *
311     * @param i DOCUMENT ME!     * @param i the initial delay, in milliseconds
312     */     */
313    public void setInitialDelay(int i)    public void setInitialDelay(int i)
314    {    {
# Line 335  public class Timer implements Serializab Line 316  public class Timer implements Serializab
316    }    }
317    
318    /**    /**
319     * DOCUMENT ME!     * Get the intial delay before firing the first event since calling
320       * the {@link #start()} method. If the initial delay has not been
321       * set, returns the same value as {@link #getDelay()}.
322     *     *
323     * @return DOCUMENT ME!     * @return the initial delay before firing the first action event.
324     */     */
325    public int getInitialDelay()    public int getInitialDelay()
326    {    {
# Line 345  public class Timer implements Serializab Line 328  public class Timer implements Serializab
328    }    }
329    
330    /**    /**
331     * DOCUMENT ME!     * Enable firing the repetetive events.
332     *     *
333     * @param r DOCUMENT ME!     * @param r <code>true</code> (default value) to fire repetetive events.
334       * <code>false</code> to fire
335       * only one event after the initial delay
336     */     */
337    public void setRepeats(boolean r)    public void setRepeats(boolean r)
338    {    {
# Line 355  public class Timer implements Serializab Line 340  public class Timer implements Serializab
340    }    }
341    
342    /**    /**
343     * DOCUMENT ME!     * Check is this timer fires repetetive events.
344     *     *
345     * @return DOCUMENT ME!     * @return <code>true</code> if the timer fires repetetive events,
346       * <code>false</code> if it fires
347       * only one event after the initial delay
348     */     */
349    public boolean isRepeats()    public boolean isRepeats()
350    {    {
# Line 365  public class Timer implements Serializab Line 352  public class Timer implements Serializab
352    }    }
353    
354    /**    /**
355     * DOCUMENT ME!     * Get the timer state.
356     *     *
357     * @return DOCUMENT ME!     * @return <code>true</code> if the timer has been started and is firing
358       * the action events as scheduled. <code>false</code>
359       * if the timer is inactive.
360     */     */
361    public boolean isRunning()    public boolean isRunning()
362    {    {
# Line 375  public class Timer implements Serializab Line 364  public class Timer implements Serializab
364    }    }
365    
366    /**    /**
367     * DOCUMENT ME!     * Add the action listener
368       *
369       * @param listener the action listener to add
370     */     */
371    public void start()    public void addActionListener(ActionListener listener)
372    {    {
373      if (isRunning())      listenerList.add(ActionListener.class, listener);
       return;  
     waker = new Waker();  
     waker.start();  
374    }    }
375    
376    /**    /**
377     * DOCUMENT ME!     * Remove the action listener.
378       *
379       * @param listener the action listener to remove
380       */
381      public void removeActionListener(ActionListener listener)
382      {
383        listenerList.remove(ActionListener.class, listener);
384      }
385    
386      /**
387       * Cancel all pending tasks and fire the first event after the initial
388       * delay.
389     */     */
390    public void restart()    public void restart()
391    {    {
# Line 395  public class Timer implements Serializab Line 394  public class Timer implements Serializab
394    }    }
395    
396    /**    /**
397     * DOCUMENT ME!     * Start firing the action events.
398       */
399      public void start()
400      {
401        if (isRunning())
402          return;
403        waker = new Waker();
404        waker.start();
405      }
406    
407      /**
408       * Stop firing the action events.
409     */     */
410    public void stop()    public void stop()
411    {    {
# Line 404  public class Timer implements Serializab Line 414  public class Timer implements Serializab
414        waker.interrupt();        waker.interrupt();
415      synchronized (queueLock)      synchronized (queueLock)
416        {        {
417          queue = 0;          queue = 0;
418          }
419      }
420    
421      /**
422       * Fire the given action event to the action listeners.
423       *
424       * @param event the event to fire
425       */
426      protected void fireActionPerformed(ActionEvent event)
427      {
428        ActionListener[] listeners = getActionListeners();
429    
430        for (int i = 0; i < listeners.length; i++)
431          listeners [ i ].actionPerformed(event);
432      }
433    
434      /**
435       * Fire the action event, named "Timer" and having the numeric
436       * identifier, equal to the numer of events that have been
437       * already fired before.
438       */
439      void fireActionPerformed()
440      {
441        fireActionPerformed(new ActionEvent(this, ticks++, "Timer"));
442      }
443    
444      /**
445       * Fire the queued action events.
446       * In the coalescing mode, a single event is fired as a replacement
447       * for all queued events. In non coalescing mode, a series of
448       * all queued events is fired.
449       */
450      private void drainEvents()
451      {
452        synchronized (queueLock)
453          {
454            if (isCoalesce())
455              {
456                if (queue > 0)
457                  fireActionPerformed();
458              }
459            else
460              {
461                while (queue > 0)
462                  {
463                    fireActionPerformed();
464                    queue--;
465                  }
466              }
467            queue = 0;
468          }
469      }
470    
471      /**
472      * Post a scheduled event to the event queue.
473      */
474      private void queueEvent()
475      {
476        synchronized (queueLock)
477          {
478            queue++;
479            if (queue == 1)
480              SwingUtilities.invokeLater(drainer);
481        }        }
482    }    }
483  }  }

Legend:
Removed from v.1.17  
changed lines
  Added in v.1.18

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26