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