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 }