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