1 /**
2  * The chess framework library.
3  * More information is available at http://www.jinchess.com/.
4  * Copyright (C) 2002 Alexander Maryanovsky.
5  * All rights reserved.
6  *
7  * The chess framework library is free software; you can redistribute
8  * it and/or modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * The chess framework library is distributed in the hope that it will
13  * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with the chess framework library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 
22 package free.chess;
23 
24 import javax.swing.JComponent;
25 import javax.swing.Timer;
26 import java.awt.event.ActionListener;
27 import java.awt.event.ActionEvent;
28 
29 
30 /**
31  * The abstract superclass of all components who display a chess clock (one part
32  * of it).
33  */
34 
35 public abstract class AbstractChessClock extends JComponent{
36 
37 
38 
39   /**
40    * The code for the mode where only hours and minutes are displayed.
41    */
42 
43   public static final int HOUR_MINUTE_DISPLAY_MODE = 0;
44 
45 
46 
47   /**
48    * The code for the mode where minutes and seconds are displayed.
49    */
50 
51   public static final int MINUTE_SECOND_DISPLAY_MODE = 1;
52 
53 
54 
55   /**
56    * The code for the mode where minutes, seconds and second tenths are
57    * displayed.
58    */
59 
60   public static final int SECOND_TENTHS_DISPLAY_MODE = 2;
61 
62 
63 
64   /**
65    * The code for the mode where the actual display depends on the current time.
66    */
67 
68   public static final int TIME_DEPENDENT_DISPLAY_MODE = 3;
69 
70 
71 
72   /**
73    * The time that was last set on this clock. Note that if the clock is
74    * running, the actual time is calculated by subtracting from this value
75    * the amount of time that has passed since the clock started running.
76    */
77 
78   private int time;
79 
80 
81 
82   /**
83    * The threshold of time under which the clock displays second tenths, when in
84    * <code>TIME_DEPENDENT_DISPLAY_MODE</code> mode.
85    */
86 
87   private int secondTenthsThreshold = 10*1000;
88 
89 
90 
91   /**
92    * The threshold of time under which the clock displays minutes and seconds,
93    * when in <code>TIME_DEPENDENT_DISPLAY_MODE</code> mode.
94    */
95 
96   private int minutesSecondsThreshold = 20*60*1000;
97 
98 
99 
100   /**
101    * The repaint timer.
102    */
103 
104   private final Timer repaintTimer = new Timer(100, new ActionListener(){
105      public void actionPerformed(ActionEvent evt){
106        repaint();
107      }
108   });
109 
110 
111 
112   /**
113    * The value of the system clock at the time the clock was set to run.
114    * -1 if the clock is not running.
115    */
116 
117   private long runStart = -1;
118 
119 
120 
121   /**
122    * The current display mode of this clock. Possible values are
123    * {@link #HOUR_MINUTE_DISPLAY_MODE}, {@link #MINUTE_SECOND_DISPLAY_MODE) and
124    * {@link #SECOND_TENTHS_DISPLAY_MODE}.
125    */
126 
127   private int displayMode = TIME_DEPENDENT_DISPLAY_MODE;
128 
129 
130 
131   /**
132    * Is the clock currently active (the current turn belongs to the owner of
133    * this clock).
134    */
135 
136   private boolean isActive = false;
137 
138 
139 
140 
141   /**
142    * Creates a new <code>AbstractChessClock</code> with the given initial amount
143    * of time (in milliseconds) on it.
144    */
145 
AbstractChessClock(int time)146   public AbstractChessClock(int time){
147     this.time = time;
148   }
149 
150 
151 
152 
153   /**
154    * Sets the time displayed by this clock, in milliseconds.
155    */
156 
setTime(int time)157   public void setTime(int time){
158     this.time = time;
159     if (isRunning())
160       runStart = System.currentTimeMillis();
161     repaint();
162   }
163 
164 
165 
166 
167   /**
168    * Returns the time displayed by this clock, in milliseconds.
169    */
170 
getTime()171   public int getTime(){
172     if (isRunning())
173       return time - (int)(System.currentTimeMillis() - runStart);
174     else
175       return time;
176   }
177 
178 
179 
180   /**
181    * Returns whether the clock is running.
182    */
183 
isRunning()184   public boolean isRunning(){
185     return runStart >= 0;
186   }
187 
188 
189 
190   /**
191    * Sets the clock's running status.
192    */
193 
setRunning(boolean isRunning)194   public void setRunning(boolean isRunning){
195     if (isRunning == isRunning())
196       return;
197 
198     if (isRunning){
199       runStart = System.currentTimeMillis();
200       repaintTimer.start();
201     }
202     else{
203       time = time - (int)(System.currentTimeMillis() - runStart);
204       runStart = -1;
205       repaintTimer.stop();
206     }
207   }
208 
209 
210 
211   /**
212    * Sets the time thresholds under which the clock switches to display
213    * <code>minutes:seconds</code> and <code>minutes:seconds.tenths</code>, when
214    * in <code>TIME_DEPENDENT_DISPLAY_MODE</code> mode.
215    */
216 
setTimeDependentDisplayModeThresholds(int minutesSeconds, int secondTenths)217   public void setTimeDependentDisplayModeThresholds(int minutesSeconds, int secondTenths){
218     this.minutesSecondsThreshold = minutesSeconds;
219     this.secondTenthsThreshold = secondTenths;
220 
221     repaint();
222   }
223 
224 
225 
226   /**
227    * Sets the delay between repaints of the clock when it is running, in
228    * milliseconds.
229    */
230 
setRepaintDelay(int delay)231   public void setRepaintDelay(int delay){
232     repaintTimer.setDelay(delay);
233   }
234 
235 
236 
237   /**
238    * Returns the delay between repaints of the clock when it is running, in
239    * milliseconds.
240    */
241 
getRepaintDelay()242   public int getRepaintDelay(){
243     return repaintTimer.getDelay();
244   }
245 
246 
247 
248   /**
249    * Sets the display mode of this clock. Possible values are
250    * {@link #HOUR_MINUTE_DISPLAY_MODE}, {@link #MINUTE_SECOND_DISPLAY_MODE) and
251    * {@link #SECOND_TENTHS_DISPLAY_MODE}. Note that concrete implementations may
252    * ignore this setting.
253    */
254 
setDisplayMode(int displayMode)255   public void setDisplayMode(int displayMode){
256     switch (displayMode){
257       case HOUR_MINUTE_DISPLAY_MODE:
258       case MINUTE_SECOND_DISPLAY_MODE:
259       case SECOND_TENTHS_DISPLAY_MODE:
260       case TIME_DEPENDENT_DISPLAY_MODE:
261         break;
262       default:
263         throw new IllegalArgumentException("Unrecognized display mode value: " + displayMode);
264     }
265 
266     this.displayMode = displayMode;
267     repaint();
268   }
269 
270 
271 
272   /**
273    * Returns the current display mode of the clock. Possible values are
274    * {@link #HOUR_MINUTE_DISPLAY_MODE}, {@link #MINUTE_SECOND_DISPLAY_MODE},
275    * {@link #SECOND_TENTHS_DISPLAY_MODE} and
276    * {@link #TIME_DEPENDENT_DISPLAY_MODE}.
277    */
278 
getDisplayMode()279   public int getDisplayMode(){
280     return displayMode;
281   }
282 
283 
284 
285   /**
286    * Returns the actual display mode. If the display mode is
287    * <code>TIME_DEPENDENT_DISPLAY_MODE</code>, returns one of the other display
288    * modes based on the current time.
289    */
290 
getActualDisplayMode()291   protected int getActualDisplayMode(){
292     int displayMode = getDisplayMode();
293     if (displayMode != TIME_DEPENDENT_DISPLAY_MODE)
294       return displayMode;
295 
296     int time = Math.abs(getTime());
297     if (time < secondTenthsThreshold)
298       return SECOND_TENTHS_DISPLAY_MODE;
299     else if (time < minutesSecondsThreshold)
300       return MINUTE_SECOND_DISPLAY_MODE;
301     else
302       return HOUR_MINUTE_DISPLAY_MODE;
303   }
304 
305 
306 
307   /**
308    * Sets the active flag of this clock. The clock should be set to be active
309    * when its owner is also the owner of the current turn.
310    */
311 
setActive(boolean isActive)312   public void setActive(boolean isActive){
313     this.isActive = isActive;
314     repaint();
315   }
316 
317 
318 
319   /**
320    * Returns whether this clock is active.
321    */
322 
isActive()323   public boolean isActive(){
324     return isActive;
325   }
326 
327 
328 
329 }
330