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 java.awt.*;
25 import free.util.TextUtilities;
26 import free.util.GraphicsUtilities;
27 
28 
29 /**
30  * A Component for displaying a simple, text based chess clock. It also has the
31  * property of taking up as much space as it can, regardless of the set font
32  * size.
33  */
34 
35 public class JChessClock extends AbstractChessClock{
36 
37 
38 
39   /**
40    * The active background color.
41    */
42 
43   private Color activeBG = Color.blue;
44 
45 
46 
47 
48   /**
49    * The active foreground color.
50    */
51 
52   private Color activeFG = Color.white;
53 
54 
55 
56 
57   /**
58    * The inactive background color. Defaults to the paren't background.
59    */
60 
61   private Color inactiveBG = null;
62 
63 
64 
65 
66   /**
67    * The inactive foreground color.
68    */
69 
70   private Color inactiveFG = Color.black;
71 
72 
73 
74 
75   /**
76    * The size of the JChessClock the last time it was painted.
77    */
78 
79   private final Dimension lastSize = new Dimension();
80 
81 
82 
83 
84   /**
85    * The Font we used the last time this JChessClock was painted.
86    */
87 
88   private Font lastFont = null;
89 
90 
91 
92   /**
93    * The FontMetrics of the font we used the last time this JChessClock was painted.
94    */
95 
96   private FontMetrics lastFontMetrics = null;
97 
98 
99 
100 
101   /**
102    * Creates a new JChessClock with the given initial amount of time
103    * (in milliseconds) on it.
104    */
105 
JChessClock(int time)106   public JChessClock(int time){
107     super(time);
108     setFont(new Font("Monospaced", Font.BOLD, 50));
109   }
110 
111 
112 
113   /**
114    * Sets the background color of this JChessClock when it's active.
115    */
116 
setActiveBackground(Color color)117   public void setActiveBackground(Color color){
118     activeBG = color;
119   }
120 
121 
122 
123   /**
124    * Returns the background color of this JChessClock when it's active.
125    */
126 
getActiveBackground()127   public Color getActiveBackground(){
128     return activeBG;
129   }
130 
131 
132 
133   /**
134    * Sets the foreground color of this JChessClock when it's active.
135    */
136 
setActiveForeground(Color color)137   public void setActiveForeground(Color color){
138     activeFG = color;
139   }
140 
141 
142 
143 
144   /**
145    * Returns the foreground color of this JChessClock when it's active.
146    */
147 
getActiveForeground()148   public Color getActiveForeground(){
149     return activeFG;
150   }
151 
152 
153 
154 
155   /**
156    * Sets the background color of this JChessClock when it's inactive.
157    */
158 
setInactiveBackground(Color color)159   public void setInactiveBackground(Color color){
160     inactiveBG = color;
161   }
162 
163 
164 
165   /**
166    * Returns the background color of this JChessClock when it's inactive.
167    */
168 
getInactiveBackground()169   public Color getInactiveBackground(){
170     return inactiveBG;
171   }
172 
173 
174 
175   /**
176    * Sets the foreground color of this JChessClock when it's inactive.
177    */
178 
setInactiveForeground(Color color)179   public void setInactiveForeground(Color color){
180     inactiveFG = color;
181   }
182 
183 
184 
185 
186   /**
187    * Returns the foreground color of this JChessClock when it's inactive.
188    */
189 
getInactiveForeground()190   public Color getInactiveForeground(){
191     return inactiveFG;
192   }
193 
194 
195 
196 
197   /**
198    * Sets whether the owner of this JChessClock is also the owner of the current
199    * turn.
200    */
201 
setActive(boolean isActive)202   public void setActive(boolean isActive){
203     super.setActive(isActive);
204     repaint();
205   }
206 
207 
208 
209 
210   /**
211    * Returns the string that should be drawn for the given time, in milliseconds.
212    */
213 
createTimeString(int time)214   protected String createTimeString(int time){
215     boolean isNegative = time<0;
216 
217     time = Math.abs(time);
218     int hours = time/(1000*60*60);
219     time -= hours*1000*60*60;
220     int minutes = time/(1000*60);
221     time -= minutes*1000*60;
222     int seconds = time/1000;
223     time -= seconds*1000;
224     int tenths = time/100;
225     time -= tenths*100;
226 
227     String signString = isNegative ? "-" : "";
228 
229     switch (getActualDisplayMode()){
230       case HOUR_MINUTE_DISPLAY_MODE:
231         String sepString = (Math.abs(tenths) > 4) || !isRunning() ? ":" : " ";
232         return signString + String.valueOf(hours) +
233           sepString + TextUtilities.padStart(String.valueOf(minutes), '0', 2);
234       case MINUTE_SECOND_DISPLAY_MODE:
235         return signString + TextUtilities.padStart(String.valueOf(60*hours+minutes), '0', 2) +
236           "." + TextUtilities.padStart(String.valueOf(seconds), '0', 2);
237       case SECOND_TENTHS_DISPLAY_MODE:
238         return signString + TextUtilities.padStart(String.valueOf(60*hours+minutes), '0', 2) +
239           "." + TextUtilities.padStart(String.valueOf(seconds), '0', 2) + "." +
240           String.valueOf(tenths);
241       default:
242         throw new IllegalStateException("Bad display mode value: " + getDisplayMode());
243     }
244   }
245 
246 
247 
248 
249   /**
250    * Determines and returns the largest font of the same kind as the given Font
251    * with which the given text can be drawn so that it still fits into the given
252    * width and height.
253    */
254 
findLargestFittingFont(String text, int width, int height, Graphics g, Font font)255   protected Font findLargestFittingFont(String text, int width, int height, Graphics g, Font font){
256     int maxSize = GraphicsUtilities.getMaxFittingFontSize(g, font, text, new Dimension(width, height));
257     return new Font(font.getName(), font.getStyle(), maxSize);
258   }
259 
260 
261 
262 
263   /**
264    * Overrides JComponent.paintComponent(Graphics) to paint this JChessClock.
265    */
266 
paintComponent(Graphics g)267   public void paintComponent(Graphics g){
268     String text = createTimeString(getTime());
269     int width = getWidth();
270     int height = getHeight();
271     if ((width != lastSize.width) || (height != lastSize.height)){
272       lastSize.width = getWidth();
273       lastSize.height = getHeight();
274 
275       lastFont = findLargestFittingFont(text, lastSize.width, lastSize.height, g, getFont());
276       lastFontMetrics = g.getFontMetrics(lastFont);
277     }
278 
279     Color bgColor = isActive() ? getActiveBackground() : getInactiveBackground();
280     if (bgColor != null){
281       g.setColor(bgColor);
282       g.fillRect(0, 0, width, height);
283     }
284 
285     Color fgColor = isActive() ? getActiveForeground() : getInactiveForeground();
286     g.setColor(fgColor);
287     g.setFont(lastFont);
288     int x = 0;
289     int y = lastFontMetrics.getMaxAscent();
290     g.drawString(text, x, y);
291   }
292 
293 
294 
295 
296   /**
297    * Returns the preferred size of this JChessClock.
298    */
299 
getPreferredSize()300   public Dimension getPreferredSize(){
301     String text = createTimeString(getTime());
302     Font font = getFont();
303     Font prefFont = new Font(font.getName(),font.getStyle(),50);
304     FontMetrics fm = GraphicsUtilities.getFontMetrics(prefFont);
305     int fontWidth = fm.stringWidth(text);
306     int fontHeight = fm.getAscent() + fm.getDescent();
307     return new Dimension(fontWidth, fontHeight);
308   }
309 
310 
311 
312 
313   /**
314    * Returns the minimum size of this JChessClock.
315    */
316 
getMinimumSize()317   public Dimension getMinimumSize(){
318     String text = createTimeString(getTime());
319     Font font = getFont();
320     Font prefFont = new Font(font.getName(),font.getStyle(),12);
321     FontMetrics fm = GraphicsUtilities.getFontMetrics(prefFont);
322     int fontWidth = fm.stringWidth(text);
323     int fontHeight = fm.getAscent() + fm.getDescent();
324     return new Dimension(fontWidth, fontHeight);
325   }
326 
327 }
328