1 /* 2 * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing.plaf.metal; 27 28 import javax.swing.plaf.*; 29 import javax.swing.*; 30 import java.awt.*; 31 32 import sun.awt.AppContext; 33 import sun.security.action.GetPropertyAction; 34 import sun.swing.SwingUtilities2; 35 36 /** 37 * A concrete implementation of {@code MetalTheme} providing 38 * the original look of the Java Look and Feel, code-named "Steel". Refer 39 * to {@link MetalLookAndFeel#setCurrentTheme} for details on changing 40 * the default theme. 41 * <p> 42 * All colors returned by {@code DefaultMetalTheme} are completely 43 * opaque. 44 * 45 * <h3><a name="fontStyle"></a>Font Style</h3> 46 * 47 * {@code DefaultMetalTheme} uses bold fonts for many controls. To make all 48 * controls (with the exception of the internal frame title bars and 49 * client decorated frame title bars) use plain fonts you can do either of 50 * the following: 51 * <ul> 52 * <li>Set the system property <code>swing.boldMetal</code> to 53 * <code>false</code>. For example, 54 * <code>java -Dswing.boldMetal=false MyApp</code>. 55 * <li>Set the defaults property <code>swing.boldMetal</code> to 56 * <code>Boolean.FALSE</code>. For example: 57 * <code>UIManager.put("swing.boldMetal", Boolean.FALSE);</code> 58 * </ul> 59 * The defaults property <code>swing.boldMetal</code>, if set, 60 * takes precendence over the system property of the same name. After 61 * setting this defaults property you need to re-install 62 * <code>MetalLookAndFeel</code>, as well as update the UI 63 * of any previously created widgets. Otherwise the results are undefined. 64 * The following illustrates how to do this: 65 * <pre> 66 * // turn off bold fonts 67 * UIManager.put("swing.boldMetal", Boolean.FALSE); 68 * 69 * // re-install the Metal Look and Feel 70 * UIManager.setLookAndFeel(new MetalLookAndFeel()); 71 * 72 * // Update the ComponentUIs for all Components. This 73 * // needs to be invoked for all windows. 74 * SwingUtilities.updateComponentTreeUI(rootComponent); 75 * </pre> 76 * <p> 77 * <strong>Warning:</strong> 78 * Serialized objects of this class will not be compatible with 79 * future Swing releases. The current serialization support is 80 * appropriate for short term storage or RMI between applications running 81 * the same version of Swing. As of 1.4, support for long term storage 82 * of all JavaBeans<sup><font size="-2">TM</font></sup> 83 * has been added to the <code>java.beans</code> package. 84 * Please see {@link java.beans.XMLEncoder}. 85 * 86 * @see MetalLookAndFeel 87 * @see MetalLookAndFeel#setCurrentTheme 88 * 89 * @author Steve Wilson 90 */ 91 public class DefaultMetalTheme extends MetalTheme { 92 /** 93 * Whether or not fonts should be plain. This is only used if 94 * the defaults property 'swing.boldMetal' == "false". 95 */ 96 private static final boolean PLAIN_FONTS; 97 98 /** 99 * Names of the fonts to use. 100 */ 101 private static final String[] fontNames = { 102 Font.DIALOG,Font.DIALOG,Font.DIALOG,Font.DIALOG,Font.DIALOG,Font.DIALOG 103 }; 104 /** 105 * Styles for the fonts. This is ignored if the defaults property 106 * <code>swing.boldMetal</code> is false, or PLAIN_FONTS is true. 107 */ 108 private static final int[] fontStyles = { 109 Font.BOLD, Font.PLAIN, Font.PLAIN, Font.BOLD, Font.BOLD, Font.PLAIN 110 }; 111 /** 112 * Sizes for the fonts. 113 */ 114 private static final int[] fontSizes = { 115 12, 12, 12, 12, 12, 10 116 }; 117 118 // note the properties listed here can currently be used by people 119 // providing runtimes to hint what fonts are good. For example the bold 120 // dialog font looks bad on a Mac, so Apple could use this property to 121 // hint at a good font. 122 // 123 // However, we don't promise to support these forever. We may move 124 // to getting these from the swing.properties file, or elsewhere. 125 /** 126 * System property names used to look up fonts. 127 */ 128 private static final String[] defaultNames = { 129 "swing.plaf.metal.controlFont", 130 "swing.plaf.metal.systemFont", 131 "swing.plaf.metal.userFont", 132 "swing.plaf.metal.controlFont", 133 "swing.plaf.metal.controlFont", 134 "swing.plaf.metal.smallFont" 135 }; 136 137 /** 138 * Returns the ideal font name for the font identified by key. 139 */ 140 static String getDefaultFontName(int key) { 141 return fontNames[key]; 142 } 143 144 /** 145 * Returns the ideal font size for the font identified by key. 146 */ 147 static int getDefaultFontSize(int key) { 148 return fontSizes[key]; 149 } 150 151 /** 152 * Returns the ideal font style for the font identified by key. 153 */ 154 static int getDefaultFontStyle(int key) { 155 if (key != WINDOW_TITLE_FONT) { 156 Object boldMetal = null; 157 if (AppContext.getAppContext().get( 158 SwingUtilities2.LAF_STATE_KEY) != null) { 159 // Only access the boldMetal key if a look and feel has 160 // been loaded, otherwise we'll trigger loading the look 161 // and feel. 162 boldMetal = UIManager.get("swing.boldMetal"); 163 } 164 if (boldMetal != null) { 165 if (Boolean.FALSE.equals(boldMetal)) { 166 return Font.PLAIN; 167 } 168 } 169 else if (PLAIN_FONTS) { 170 return Font.PLAIN; 171 } 172 } 173 return fontStyles[key]; 174 } 175 176 /** 177 * Returns the default used to look up the specified font. 178 */ 179 static String getDefaultPropertyName(int key) { 180 return defaultNames[key]; 181 } 182 183 static { 184 Object boldProperty = java.security.AccessController.doPrivileged( 185 new GetPropertyAction("swing.boldMetal")); 186 if (boldProperty == null || !"false".equals(boldProperty)) { 187 PLAIN_FONTS = false; 188 } 189 else { 190 PLAIN_FONTS = true; 191 } 192 } 193 194 private static final ColorUIResource primary1 = new ColorUIResource( 195 102, 102, 153); 196 private static final ColorUIResource primary2 = new ColorUIResource(153, 197 153, 204); 198 private static final ColorUIResource primary3 = new ColorUIResource( 199 204, 204, 255); 200 private static final ColorUIResource secondary1 = new ColorUIResource( 201 102, 102, 102); 202 private static final ColorUIResource secondary2 = new ColorUIResource( 203 153, 153, 153); 204 private static final ColorUIResource secondary3 = new ColorUIResource( 205 204, 204, 204); 206 207 private FontDelegate fontDelegate; 208 209 /** 210 * Returns the name of this theme. This returns {@code "Steel"}. 211 * 212 * @return the name of this theme. 213 */ 214 public String getName() { return "Steel"; } 215 216 /** 217 * Creates and returns an instance of {@code DefaultMetalTheme}. 218 */ 219 public DefaultMetalTheme() { 220 install(); 221 } 222 223 /** 224 * Returns the primary 1 color. This returns a color with rgb values 225 * of 102, 102, and 153, respectively. 226 * 227 * @return the primary 1 color 228 */ 229 protected ColorUIResource getPrimary1() { return primary1; } 230 231 /** 232 * Returns the primary 2 color. This returns a color with rgb values 233 * of 153, 153, 204, respectively. 234 * 235 * @return the primary 2 color 236 */ 237 protected ColorUIResource getPrimary2() { return primary2; } 238 239 /** 240 * Returns the primary 3 color. This returns a color with rgb values 241 * 204, 204, 255, respectively. 242 * 243 * @return the primary 3 color 244 */ 245 protected ColorUIResource getPrimary3() { return primary3; } 246 247 /** 248 * Returns the secondary 1 color. This returns a color with rgb values 249 * 102, 102, and 102, respectively. 250 * 251 * @return the secondary 1 color 252 */ 253 protected ColorUIResource getSecondary1() { return secondary1; } 254 255 /** 256 * Returns the secondary 2 color. This returns a color with rgb values 257 * 153, 153, and 153, respectively. 258 * 259 * @return the secondary 2 color 260 */ 261 protected ColorUIResource getSecondary2() { return secondary2; } 262 263 /** 264 * Returns the secondary 3 color. This returns a color with rgb values 265 * 204, 204, and 204, respectively. 266 * 267 * @return the secondary 3 color 268 */ 269 protected ColorUIResource getSecondary3() { return secondary3; } 270 271 272 /** 273 * Returns the control text font. This returns Dialog, 12pt. If 274 * plain fonts have been enabled as described in <a href="#fontStyle"> 275 * font style</a>, the font style is plain. Otherwise the font style is 276 * bold. 277 * 278 * @return the control text font 279 */ 280 public FontUIResource getControlTextFont() { 281 return getFont(CONTROL_TEXT_FONT); 282 } 283 284 /** 285 * Returns the system text font. This returns Dialog, 12pt, plain. 286 * 287 * @return the sytem text font 288 */ 289 public FontUIResource getSystemTextFont() { 290 return getFont(SYSTEM_TEXT_FONT); 291 } 292 293 /** 294 * Returns the user text font. This returns Dialog, 12pt, plain. 295 * 296 * @return the user text font 297 */ 298 public FontUIResource getUserTextFont() { 299 return getFont(USER_TEXT_FONT); 300 } 301 302 /** 303 * Returns the menu text font. This returns Dialog, 12pt. If 304 * plain fonts have been enabled as described in <a href="#fontStyle"> 305 * font style</a>, the font style is plain. Otherwise the font style is 306 * bold. 307 * 308 * @return the menu text font 309 */ 310 public FontUIResource getMenuTextFont() { 311 return getFont(MENU_TEXT_FONT); 312 } 313 314 /** 315 * Returns the window title font. This returns Dialog, 12pt, bold. 316 * 317 * @return the window title font 318 */ 319 public FontUIResource getWindowTitleFont() { 320 return getFont(WINDOW_TITLE_FONT); 321 } 322 323 /** 324 * Returns the sub-text font. This returns Dialog, 10pt, plain. 325 * 326 * @return the sub-text font 327 */ 328 public FontUIResource getSubTextFont() { 329 return getFont(SUB_TEXT_FONT); 330 } 331 332 private FontUIResource getFont(int key) { 333 return fontDelegate.getFont(key); 334 } 335 336 void install() { 337 if (MetalLookAndFeel.isWindows() && 338 MetalLookAndFeel.useSystemFonts()) { 339 fontDelegate = new WindowsFontDelegate(); 340 } 341 else { 342 fontDelegate = new FontDelegate(); 343 } 344 } 345 346 /** 347 * Returns true if this is a theme provided by the core platform. 348 */ 349 boolean isSystemTheme() { 350 return (getClass() == DefaultMetalTheme.class); 351 } 352 353 /** 354 * FontDelegates add an extra level of indirection to obtaining fonts. 355 */ 356 private static class FontDelegate { 357 private static int[] defaultMapping = { 358 CONTROL_TEXT_FONT, SYSTEM_TEXT_FONT, 359 USER_TEXT_FONT, CONTROL_TEXT_FONT, 360 CONTROL_TEXT_FONT, SUB_TEXT_FONT 361 }; 362 FontUIResource fonts[]; 363 364 // menu and window are mapped to controlFont 365 public FontDelegate() { 366 fonts = new FontUIResource[6]; 367 } 368 369 public FontUIResource getFont(int type) { 370 int mappedType = defaultMapping[type]; 371 if (fonts[type] == null) { 372 Font f = getPrivilegedFont(mappedType); 373 374 if (f == null) { 375 f = new Font(getDefaultFontName(type), 376 getDefaultFontStyle(type), 377 getDefaultFontSize(type)); 378 } 379 fonts[type] = new FontUIResource(f); 380 } 381 return fonts[type]; 382 } 383 384 /** 385 * This is the same as invoking 386 * <code>Font.getFont(key)</code>, with the exception 387 * that it is wrapped inside a <code>doPrivileged</code> call. 388 */ 389 protected Font getPrivilegedFont(final int key) { 390 return (Font)java.security.AccessController.doPrivileged( 391 new java.security.PrivilegedAction() { 392 public Object run() { 393 return Font.getFont(getDefaultPropertyName(key)); 394 } 395 } 396 ); 397 } 398 } 399 400 /** 401 * The WindowsFontDelegate uses DesktopProperties to obtain fonts. 402 */ 403 private static class WindowsFontDelegate extends FontDelegate { 404 private MetalFontDesktopProperty[] props; 405 private boolean[] checkedPriviledged; 406 407 public WindowsFontDelegate() { 408 props = new MetalFontDesktopProperty[6]; 409 checkedPriviledged = new boolean[6]; 410 } 411 412 public FontUIResource getFont(int type) { 413 if (fonts[type] != null) { 414 return fonts[type]; 415 } 416 if (!checkedPriviledged[type]) { 417 Font f = getPrivilegedFont(type); 418 419 checkedPriviledged[type] = true; 420 if (f != null) { 421 fonts[type] = new FontUIResource(f); 422 return fonts[type]; 423 } 424 } 425 if (props[type] == null) { 426 props[type] = new MetalFontDesktopProperty(type); 427 } 428 // While passing null may seem bad, we don't actually use 429 // the table and looking it up is rather expensive. 430 return (FontUIResource)props[type].createValue(null); 431 } 432 } 433 }