blob: dbb9b346a4d6dd07d913a55ff6e9126f2b0b36ea [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.swing.plaf.metal;
27
28import javax.swing.plaf.*;
29import javax.swing.*;
30import java.awt.*;
31
32import sun.awt.AppContext;
33import sun.security.action.GetPropertyAction;
34import 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&nbsp;-Dswing.boldMetal=false&nbsp;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",&nbsp;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 */
91public 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}