1 /* 2 * Copyright (c) 1998, 2014, 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 precedence 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™ 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 @SuppressWarnings("serial") // Same-version serialization only 92 public class DefaultMetalTheme extends MetalTheme { 93 /** 94 * Whether or not fonts should be plain. This is only used if 95 * the defaults property 'swing.boldMetal' == "false". 96 */ 97 private static final boolean PLAIN_FONTS; 98 99 /** 100 * Names of the fonts to use. 101 */ 102 private static final String[] fontNames = { 103 Font.DIALOG,Font.DIALOG,Font.DIALOG,Font.DIALOG,Font.DIALOG,Font.DIALOG 104 }; 105 /** 106 * Styles for the fonts. This is ignored if the defaults property 107 * <code>swing.boldMetal</code> is false, or PLAIN_FONTS is true. 108 */ 109 private static final int[] fontStyles = { 110 Font.BOLD, Font.PLAIN, Font.PLAIN, Font.BOLD, Font.BOLD, Font.PLAIN 111 }; 112 /** 113 * Sizes for the fonts. 114 */ 115 private static final int[] fontSizes = { 116 12, 12, 12, 12, 12, 10 117 }; 118 119 // note the properties listed here can currently be used by people 120 // providing runtimes to hint what fonts are good. For example the bold 121 // dialog font looks bad on a Mac, so Apple could use this property to 122 // hint at a good font. 123 // 124 // However, we don't promise to support these forever. We may move 125 // to getting these from the swing.properties file, or elsewhere. 126 /** 127 * System property names used to look up fonts. 128 */ 129 private static final String[] defaultNames = { 130 "swing.plaf.metal.controlFont", 131 "swing.plaf.metal.systemFont", 132 "swing.plaf.metal.userFont", 133 "swing.plaf.metal.controlFont", 134 "swing.plaf.metal.controlFont", 135 "swing.plaf.metal.smallFont" 136 }; 137 138 /** 139 * Returns the ideal font name for the font identified by key. 140 */ 141 static String getDefaultFontName(int key) { 142 return fontNames[key]; 143 } 144 145 /** 146 * Returns the ideal font size for the font identified by key. 147 */ 148 static int getDefaultFontSize(int key) { 149 return fontSizes[key]; 150 } 151 152 /** 153 * Returns the ideal font style for the font identified by key. 154 */ 155 static int getDefaultFontStyle(int key) { 156 if (key != WINDOW_TITLE_FONT) { 157 Object boldMetal = null; 158 if (AppContext.getAppContext().get( 159 SwingUtilities2.LAF_STATE_KEY) != null) { 160 // Only access the boldMetal key if a look and feel has 161 // been loaded, otherwise we'll trigger loading the look 162 // and feel. 163 boldMetal = UIManager.get("swing.boldMetal"); 164 } 165 if (boldMetal != null) { 166 if (Boolean.FALSE.equals(boldMetal)) { 167 return Font.PLAIN; 168 } 169 } 170 else if (PLAIN_FONTS) { 171 return Font.PLAIN; 172 } 173 } 174 return fontStyles[key]; 175 } 176 177 /** 178 * Returns the default used to look up the specified font. 179 */ 180 static String getDefaultPropertyName(int key) { 181 return defaultNames[key]; 182 } 183 184 static { 185 Object boldProperty = java.security.AccessController.doPrivileged( 186 new GetPropertyAction("swing.boldMetal")); 187 if (boldProperty == null || !"false".equals(boldProperty)) { 188 PLAIN_FONTS = false; 189 } 190 else { 191 PLAIN_FONTS = true; 192 } 193 } 194 195 private static final ColorUIResource primary1 = new ColorUIResource( 196 102, 102, 153); 197 private static final ColorUIResource primary2 = new ColorUIResource(153, 198 153, 204); 199 private static final ColorUIResource primary3 = new ColorUIResource( 200 204, 204, 255); 201 private static final ColorUIResource secondary1 = new ColorUIResource( 202 102, 102, 102); 203 private static final ColorUIResource secondary2 = new ColorUIResource( 204 153, 153, 153); 205 private static final ColorUIResource secondary3 = new ColorUIResource( 206 204, 204, 204); 207 208 private FontDelegate fontDelegate; 209 210 /** 211 * Returns the name of this theme. This returns {@code "Steel"}. 212 * 213 * @return the name of this theme. 214 */ 215 public String getName() { return "Steel"; } 216 217 /** 218 * Creates and returns an instance of {@code DefaultMetalTheme}. 219 */ 220 public DefaultMetalTheme() { 221 install(); 222 } 223 224 /** 225 * Returns the primary 1 color. This returns a color with rgb values 226 * of 102, 102, and 153, respectively. 227 * 228 * @return the primary 1 color 229 */ 230 protected ColorUIResource getPrimary1() { return primary1; } 231 232 /** 233 * Returns the primary 2 color. This returns a color with rgb values 234 * of 153, 153, 204, respectively. 235 * 236 * @return the primary 2 color 237 */ 238 protected ColorUIResource getPrimary2() { return primary2; } 239 240 /** 241 * Returns the primary 3 color. This returns a color with rgb values 242 * 204, 204, 255, respectively. 243 * 244 * @return the primary 3 color 245 */ 246 protected ColorUIResource getPrimary3() { return primary3; } 247 248 /** 249 * Returns the secondary 1 color. This returns a color with rgb values 250 * 102, 102, and 102, respectively. 251 * 252 * @return the secondary 1 color 253 */ 254 protected ColorUIResource getSecondary1() { return secondary1; } 255 256 /** 257 * Returns the secondary 2 color. This returns a color with rgb values 258 * 153, 153, and 153, respectively. 259 * 260 * @return the secondary 2 color 261 */ 262 protected ColorUIResource getSecondary2() { return secondary2; } 263 264 /** 265 * Returns the secondary 3 color. This returns a color with rgb values 266 * 204, 204, and 204, respectively. 267 * 268 * @return the secondary 3 color 269 */ 270 protected ColorUIResource getSecondary3() { return secondary3; } 271 272 273 /** 274 * Returns the control text font. This returns Dialog, 12pt. If 275 * plain fonts have been enabled as described in <a href="#fontStyle"> 276 * font style</a>, the font style is plain. Otherwise the font style is 277 * bold. 278 * 279 * @return the control text font 280 */ 281 public FontUIResource getControlTextFont() { 282 return getFont(CONTROL_TEXT_FONT); 283 } 284 285 /** 286 * Returns the system text font. This returns Dialog, 12pt, plain. 287 * 288 * @return the system text font 289 */ 290 public FontUIResource getSystemTextFont() { 291 return getFont(SYSTEM_TEXT_FONT); 292 } 293 294 /** 295 * Returns the user text font. This returns Dialog, 12pt, plain. 296 * 297 * @return the user text font 298 */ 299 public FontUIResource getUserTextFont() { 300 return getFont(USER_TEXT_FONT); 301 } 302 303 /** 304 * Returns the menu text font. This returns Dialog, 12pt. If 305 * plain fonts have been enabled as described in <a href="#fontStyle"> 306 * font style</a>, the font style is plain. Otherwise the font style is 307 * bold. 308 * 309 * @return the menu text font 310 */ 311 public FontUIResource getMenuTextFont() { 312 return getFont(MENU_TEXT_FONT); 313 } 314 315 /** 316 * Returns the window title font. This returns Dialog, 12pt, bold. 317 * 318 * @return the window title font 319 */ 320 public FontUIResource getWindowTitleFont() { 321 return getFont(WINDOW_TITLE_FONT); 322 } 323 324 /** 325 * Returns the sub-text font. This returns Dialog, 10pt, plain. 326 * 327 * @return the sub-text font 328 */ 329 public FontUIResource getSubTextFont() { 330 return getFont(SUB_TEXT_FONT); 331 } 332 333 private FontUIResource getFont(int key) { 334 return fontDelegate.getFont(key); 335 } 336 337 void install() { 338 if (MetalLookAndFeel.isWindows() && 339 MetalLookAndFeel.useSystemFonts()) { 340 fontDelegate = new WindowsFontDelegate(); 341 } 342 else { 343 fontDelegate = new FontDelegate(); 344 } 345 } 346 347 /** 348 * Returns true if this is a theme provided by the core platform. 349 */ 350 boolean isSystemTheme() { 351 return (getClass() == DefaultMetalTheme.class); 352 } 353 354 /** 355 * FontDelegates add an extra level of indirection to obtaining fonts. 356 */ 357 private static class FontDelegate { 358 private static int[] defaultMapping = { 359 CONTROL_TEXT_FONT, SYSTEM_TEXT_FONT, 360 USER_TEXT_FONT, CONTROL_TEXT_FONT, 361 CONTROL_TEXT_FONT, SUB_TEXT_FONT 362 }; 363 FontUIResource fonts[]; 364 365 // menu and window are mapped to controlFont 366 public FontDelegate() { 367 fonts = new FontUIResource[6]; 368 } 369 370 public FontUIResource getFont(int type) { 371 int mappedType = defaultMapping[type]; 372 if (fonts[type] == null) { 373 Font f = getPrivilegedFont(mappedType); 374 375 if (f == null) { 376 f = new Font(getDefaultFontName(type), 377 getDefaultFontStyle(type), 378 getDefaultFontSize(type)); 379 } 380 fonts[type] = new FontUIResource(f); 381 } 382 return fonts[type]; 383 } 384 385 /** 386 * This is the same as invoking 387 * <code>Font.getFont(key)</code>, with the exception 388 * that it is wrapped inside a <code>doPrivileged</code> call. 389 */ 390 protected Font getPrivilegedFont(final int key) { 391 return java.security.AccessController.doPrivileged( 392 new java.security.PrivilegedAction<Font>() { 393 public Font run() { 394 return Font.getFont(getDefaultPropertyName(key)); 395 } 396 } 397 ); 398 } 399 } 400 401 /** 402 * The WindowsFontDelegate uses DesktopProperties to obtain fonts. 403 */ 404 private static class WindowsFontDelegate extends FontDelegate { 405 private MetalFontDesktopProperty[] props; 406 private boolean[] checkedPriviledged; 407 408 public WindowsFontDelegate() { 409 props = new MetalFontDesktopProperty[6]; 410 checkedPriviledged = new boolean[6]; 411 } 412 413 public FontUIResource getFont(int type) { 414 if (fonts[type] != null) { 415 return fonts[type]; 416 } 417 if (!checkedPriviledged[type]) { 418 Font f = getPrivilegedFont(type); 419 420 checkedPriviledged[type] = true; 421 if (f != null) { 422 fonts[type] = new FontUIResource(f); 423 return fonts[type]; 424 } 425 } 426 if (props[type] == null) { 427 props[type] = new MetalFontDesktopProperty(type); 428 } 429 // While passing null may seem bad, we don't actually use 430 // the table and looking it up is rather expensive. 431 return (FontUIResource)props[type].createValue(null); 432 } 433 } 434 }