001 /**
002 * A Stopwatch models a countdown timer that can be turned on and off. It is
003 * also a task that can be scheduled using a java.util.Timer to notify a
004 * StopwatchListener of its decreasing time at regular intervals.
005 */
006
007 package ui;
008
009 import java.util.*;
010 import javax.swing.event.EventListenerList;
011
012 public class Stopwatch extends TimerTask {
013
014 private boolean running = false;
015
016 private long millisLeft;
017
018 private long startTime;
019
020 /** @requires millisLeft >= 0 */
021 public Stopwatch(long millisLeft) {
022 this.millisLeft = millisLeft;
023 }
024
025 /**
026 * Starts the timer, if it was not already running.
027 */
028 public void start() {
029 if (running) return;
030 running = true;
031 startTime = System.currentTimeMillis();
032 }
033
034 /**
035 * Stops the timer, if it was not already stopped.
036 */
037 public void stop() {
038 if (!running) return;
039 running = false;
040 long stopTime = System.currentTimeMillis();
041 millisLeft -= (stopTime - startTime);
042 }
043
044 /**
045 * Returns the amount of time left on the Stopwatch (or zero, if that time
046 * is less than zero).
047 */
048 public long getTime() {
049 if (running) {
050 return Math.max((millisLeft - (System.currentTimeMillis() - startTime)),
051 0);
052 } else {
053 return Math.max(millisLeft, 0);
054 }
055 }
056
057 private EventListenerList listenerList = new EventListenerList();
058
059 /**
060 * Adds a StopwatchListener to this. The listener's timeChanged method will
061 * fire everytime this is run as a TimerTask.
062 */
063 public void addStopwatchListener(StopwatchListener s) {
064 listenerList.add(StopwatchListener.class, s);
065 }
066
067 /**
068 * Removes a StopwatchListener from this
069 */
070 public void removeStopwatchListener(StopwatchListener s) {
071 listenerList.remove(StopwatchListener.class, s);
072 }
073
074 /**
075 * Informs all of this Stopwatch's listeners that its time is decreasing
076 */
077 protected void fireTimeChanged() {
078 // Guaranteed to return a non-null array
079 StopwatchListener[] listeners =
080 listenerList.getListeners(StopwatchListener.class);
081 // Process the listeners last to first, notifying
082 // those that are interested in this event
083 long time = getTime();
084 for (int i = listeners.length - 1; i >= 0; i --) {
085 listeners[i].timeChanged(time, this);
086 }
087 }
088
089 /**
090 * Informs all of this Stopwatch's listeners that its time is decreasing
091 */
092 public void run() {
093 fireTimeChanged();
094 }
095
096 }