001    package sale;
002    
003    /**
004     * A timer that has the functionality of the {@link StepTimer StepTimer} and additionally
005     * can increase the time automatically.
006     *
007     * @author Stephan Gambke
008     * @version 2.0 11/06/1999
009     * @since v2.0
010     */
011    public class AutoTimer extends StepTimer {
012    
013        /**
014             * ID for serialization.
015             */
016            private static final long serialVersionUID = 916786231358753844L;
017    
018            /**
019         * Communications channel used for controlling the internal processing loop.
020         */
021        private transient Object m_oTimer;
022        /**
023         * Return the communications channel used for controlling the internal processing loop.
024         */
025        private Object getTimer() {
026            if (m_oTimer == null) {
027                m_oTimer = new Object();
028            }
029    
030            return m_oTimer;
031        }
032    
033        /**
034         * Is the timer running ?
035         *
036         * @serial
037         */
038        private boolean m_fOnTheRun;
039    
040        /**
041         * Delay between increases.
042         *
043         * @serial
044         */
045        private long m_lDelay = 1;
046    
047        /**
048         * Create a new AutoTimer with a {@link Step Step} as time object and a delay of 10 seconds.
049         * The timer is initially not running.
050         */
051        public AutoTimer() {
052            this(new Step(), 10000);
053        }
054    
055        /**
056         * Create a new AutoTimer with the given time object and a delay of 10 seconds. The timer is initially not
057         * running.
058         *
059         * @param tTime the time object to be used
060         */
061        public AutoTimer(Time tTime) {
062            this(tTime, 10000);
063        }
064    
065        /**
066         * Create a new AutoTimer with the given time object and delay. The timer is initially not running.
067         *
068         * @param tTime the time object to use
069         * @param lDelay the delay in milliseconds between the increasing steps
070         */
071        public AutoTimer(Time tTime, long lDelay) {
072            super(tTime);
073            m_fOnTheRun = false;
074            setDelay(lDelay);
075        }
076    
077        /**
078         * Internal method that just calls <code>super.goAhead()</code>
079         *
080         * @override Never
081         */
082        private void doGoAhead() throws IllegalArgumentException {
083            super.goAhead();
084        }
085    
086        /**
087         * Increase the time by the current interval.
088         *
089         * <p>If no interval has yet been set, the interval given by the {@link Time#getDefaultInterval()} method
090         * of the time object is used.</p>
091         *
092         * <p>If the AutoTimer is running, the time is increased and the delay restartet.</p>
093         *
094         * @override Never
095         *
096         * @exception IllegalArgumentException if the interval does not meet the time object's class or format
097         * requirements.
098         */
099        public void goAhead() throws IllegalArgumentException {
100            if (m_fOnTheRun) {
101                synchronized (getTimer()) {
102                    getTimer().notifyAll();
103                }
104            } else {
105                doGoAhead();
106            }
107        }
108    
109        /**
110         * Set the timer running. If the timer is already running, nothing happens.
111         *
112         * <p>The first timer tick occurs at once.</p>
113         *
114         * @override Never
115         */
116        public void start() throws IllegalArgumentException {
117            synchronized (getTimer()) {
118                if (m_fOnTheRun) {
119                    return;
120                }
121    
122                m_fOnTheRun = true;
123    
124                new Thread() {
125                    public void run() {
126                        synchronized (getTimer()) {
127                            while (m_fOnTheRun) {
128                                try {
129                                    doGoAhead();
130                                    getTimer().wait(m_lDelay);
131                                }
132                                catch (InterruptedException iexc) {}
133                                catch (Throwable t) {
134                                    m_fOnTheRun = false;
135    
136                                    System.err.println("Error in AutoTimer: " + t);
137                                    t.printStackTrace();
138                                }
139                            }
140                        }
141                    }
142                }
143    
144                .start();
145            }
146        }
147    
148        /**
149         * Stop the timer.
150         *
151         * @override Never
152         */
153        public void stop() {
154            m_fOnTheRun = false;
155        }
156    
157        /**
158         * Set the delay between timer ticks.
159         *
160         * <p>If the AutoTimer is currently running, the new delay takes effect after the next tick.</p>
161         *
162         * @override Never
163         *
164         * @param lMilliSecs the delay in milliseconds. Must be > 0.
165         */
166        public void setDelay(long lMilliSecs) {
167            if (lMilliSecs > 0) {
168                m_lDelay = lMilliSecs;
169            }
170        }
171    
172        /**
173         * Get the current delay between timer ticks in milliseconds.
174         *
175         * @return a long value representing the delay
176         */
177        public long getDelay() {
178            return m_lDelay;
179        }
180    }