1  /*
     2   Copyright aswing.org, see the LICENCE.txt.
     3  */
     4   
     5  import org.aswing.*;
     6   
     7  /**
     8   * Fires one or more action events after a specified delay.  
     9   * For example, an animation object can use a <code>Timer</code>
    10   * as the trigger for drawing its frames.
    11   *
    12   *<p>
    13   * Setting up a timer
    14   * involves creating a <code>Timer</code> object,
    15   * registering one or more action listeners on it,
    16   * and starting the timer using
    17   * the <code>start</code> method.
    18   * For example, 
    19   * the following code creates and starts a timer
    20   * that fires an action event once per second
    21   * (as specified by the first argument to the <code>Timer</code> constructor).
    22   * The second argument to the <code>Timer</code> constructor
    23   * specifies a listener to receive the timer's action events.
    24   *
    25   *<pre>
    26   *  var delay:Number = 1000; //milliseconds
    27   *  var listener:Object = new Object();
    28   *  listener.taskPerformer = function() {
    29   *          <em>//...Perform a task...</em>
    30   *      }
    31   *  var timer:Timer = new Timer(delay);
    32   *  timer.addActionListener(listener.taskPerformer, listener);
    33   *  timer.start();
    34   * </pre>
    35   *
    36   * <p>
    37   * @author iiley
    38   */
    39  class org.aswing.utils.Timer extends EventDispatcher{
    40  	
    41  	private var delay:Number;
    42  	private var initialDelay:Number;
    43  	private var repeats:Boolean;
    44  	private var intervalID:Number;
    45  	private var isInitalFire:Boolean;
    46  	
    47  	/**
    48  	 * Construct Timer.
    49  	 * @see #setDelay()
    50       * @throws Error when init delay <= 0 or delay == null
    51  	 */
    52  	public function Timer(delay:Number){
    53  		if(delay == undefined || delay <=0){
    54  			trace("delay must > 0! when create a Timer");
    55  			throw new Error("delay must > 0! when create a Timer");
    56  		}
    57  		this.delay = delay;
    58  		this.initialDelay = undefined;
    59  		this.repeats = true;
    60  		this.isInitalFire = true;
    61  		this.intervalID = null;
    62  	}
    63  	
    64      /**
    65       * Adds an action listener to the <code>Timer</code>.
    66       *
    67       * @param func the listener function
    68       * @param obj the listener obj
    69       * 
    70       * @see org.aswing.EventDispatcher#addEventListener()
    71       * @see org.aswing.EventDispatcher#ON_ACT
    72       * @return the listener just added.
    73       */	
    74  	public function addActionListener(func:Function, obj:Object):Object{
    75  		return addEventListener(ON_ACT, func, obj);
    76  	}
    77  	
    78      /**
    79       * Sets the <code>Timer</code>'s delay, the number of milliseconds
    80       * between successive events.
    81       *
    82       * @param delay the delay in milliseconds
    83       * @see #setInitialDelay()
    84       * @throws Error when set delay <= 0 or delay == null
    85       */	
    86  	public function setDelay(delay:Number):Void{
    87  		if(delay == undefined || delay <= 0){
    88  			trace("Timer should be specified delay>0! Error delay = " + delay);
    89  			throw new Error("Timer should be specified delay>0! Error delay = " + delay);
    90  		}
    91  		this.delay = delay;
    92  	}
    93  	
    94      /**
    95       * Returns the delay, in milliseconds, 
    96       * between firings of events.
    97       *
    98       * @see #setDelay()
    99       * @see #getInitialDelay()
   100       */	
   101  	public function getDelay():Number{
   102  		return delay;
   103  	}
   104  	
   105      /**
   106       * Sets the <code>Timer</code>'s initial delay,
   107       * which by default is the same as the between-event delay.
   108       * This is used only for the first action event.
   109       * Subsequent events are spaced
   110       * using the delay property.
   111       * 
   112       * @param initialDelay the delay, in milliseconds, 
   113       *                     between the invocation of the <code>start</code>
   114       *                     method and the first event
   115       *                     fired by this timer
   116       *
   117       * @see #setDelay()
   118       * @throws Error when set initialDelay <= 0 or initialDelay == null
   119       */	
   120  	public function setInitialDelay(initialDelay:Number):Void{
   121  		if(initialDelay == undefined || initialDelay <= 0){
   122  			trace("Timer should be specified initialDelay>0! Error initialDelay = " + initialDelay);
   123  			throw new Error("Timer should be specified initialDelay>0! Error initialDelay = " + initialDelay);
   124  		}
   125  		this.initialDelay = initialDelay;
   126  	}
   127  	
   128      /**
   129       * Returns the <code>Timer</code>'s initial delay.
   130       *
   131       * @see #setInitialDelay()
   132       * @see #setDelay()
   133       */	
   134  	public function getInitialDelay():Number{
   135  		if(initialDelay == undefined){
   136  			return delay;
   137  		}else{
   138  			return initialDelay;
   139  		}
   140  	}
   141  	
   142  	/**
   143       * If <code>flag</code> is <code>false</code>,
   144       * instructs the <code>Timer</code> to send only once
   145       * action event to its listeners after a start.
   146       *
   147       * @param flag specify <code>false</code> to make the timer
   148       *             stop after sending its first action event.
   149       *             Default value is true.
   150  	 */
   151  	public function setRepeats(flag:Boolean):Void{
   152  		repeats = flag;
   153  	}
   154  	
   155      /**
   156       * Returns <code>true</code> (the default)
   157       * if the <code>Timer</code> will send
   158       * an action event 
   159       * to its listeners multiple times.
   160       *
   161       * @see #setRepeats()
   162       */	
   163  	public function isRepeats():Boolean{
   164  		return repeats;
   165  	}
   166  	
   167      /**
   168       * Starts the <code>Timer</code>,
   169       * causing it to start sending action events
   170       * to its listeners.
   171       *
   172       * @see #stop()
   173       */
   174      public function start():Void{
   175      	isInitalFire = true;
   176      	clearInterval(intervalID);
   177      	intervalID = setInterval(this, "fireActionPerformed", getInitialDelay());
   178      }
   179      
   180      /**
   181       * Returns <code>true</code> if the <code>Timer</code> is running.
   182       *
   183       * @see #start()
   184       */
   185      public function isRunning():Boolean{
   186      	return intervalID != null;
   187      }
   188      
   189      /**
   190       * Stops the <code>Timer</code>,
   191       * causing it to stop sending action events
   192       * to its listeners.
   193       *
   194       * @see #start()
   195       */
   196      public function stop():Void{
   197      	clearInterval(intervalID);
   198      	intervalID = null;
   199      }
   200      
   201      /**
   202       * Restarts the <code>Timer</code>,
   203       * canceling any pending firings and causing
   204       * it to fire with its initial delay.
   205       */
   206      public function restart():Void{
   207          stop();
   208          start();
   209      }
   210      
   211      private function fireActionPerformed():Void{
   212      	dispatchEvent(ON_ACT, createEventObj(ON_ACT));
   213      	if(isInitalFire){
   214      		isInitalFire = false;
   215      		if(repeats){
   216      			clearInterval(intervalID);
   217      			intervalID = setInterval(this, "fireActionPerformed", getDelay());
   218      		}else{
   219      			stop();
   220      		}
   221      	}
   222      }
   223  }
   224