001: /*
002: * Copyright (c) 2001-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.looks.windows;
032:
033: import java.awt.Color;
034: import java.awt.Font;
035: import java.awt.Insets;
036: import java.lang.reflect.Method;
037:
038: import javax.swing.Icon;
039: import javax.swing.JComponent;
040: import javax.swing.UIDefaults;
041: import javax.swing.UIManager;
042: import javax.swing.border.Border;
043: import javax.swing.border.EmptyBorder;
044: import javax.swing.plaf.DimensionUIResource;
045: import javax.swing.plaf.IconUIResource;
046: import javax.swing.plaf.InsetsUIResource;
047: import javax.swing.plaf.basic.BasicBorders;
048:
049: import com.jgoodies.looks.*;
050: import com.jgoodies.looks.common.MinimumSizedIcon;
051: import com.jgoodies.looks.common.RGBGrayFilter;
052: import com.jgoodies.looks.common.ShadowPopupFactory;
053:
054: /**
055: * The main class of the JGoodies Windows Look&Feel.
056: * This look provides several corrections and extensions to Sun's Windows L&F.
057: * In addition it tries to provide a unified look for the J2SE 1.4.0x, 1.4.1x,
058: * 1.4.2, and 1.5 environments.
059: *
060: * @author Karsten Lentzsch
061: * @version $Revision: 1.36 $
062: */
063: public final class WindowsLookAndFeel extends
064: com.sun.java.swing.plaf.windows.WindowsLookAndFeel {
065:
066: /**
067: * An optional client property key for JMenu and JToolBar
068: * to set a border style - shadows the header style.
069: */
070: public static final String BORDER_STYLE_KEY = "jgoodies.windows.borderStyle";
071:
072: public String getID() {
073: return "JGoodies Windows";
074: }
075:
076: public String getName() {
077: return "JGoodies Windows";
078: }
079:
080: public String getDescription() {
081: return "The JGoodies Windows Look and Feel"
082: + " - \u00a9 2001-2007 JGoodies Karsten Lentzsch";
083: }
084:
085: // Optional Settings ******************************************************
086:
087: /**
088: * Looks up and retrieves the FontPolicy used by
089: * the JGoodies Windows Look&Feel.
090: * If a FontPolicy has been set for this look, it'll be returned.
091: * Otherwise, this method checks if a FontPolicy or FontSet is defined
092: * in the system properties or UIDefaults. If so, it is returned.
093: * If no FontPolicy has been set for this look, in the system
094: * properties or UIDefaults, the default Windows font policy
095: * will be returned.
096: *
097: * @return the FontPolicy set for this Look&feel - if any,
098: * the FontPolicy specified in the system properties or UIDefaults
099: * - if any, or the default Windows font policy.
100: *
101: * @see #setFontPolicy
102: * @see Options#WINDOWS_FONT_POLICY_KEY
103: * @see FontPolicies
104: * @see FontPolicies#customSettingsPolicy(FontPolicy)
105: * @see FontPolicies#getDefaultWindowsPolicy()
106: */
107: public static FontPolicy getFontPolicy() {
108: FontPolicy policy = (FontPolicy) UIManager
109: .get(Options.WINDOWS_FONT_POLICY_KEY);
110: if (policy != null)
111: return policy;
112:
113: FontPolicy defaultPolicy = FontPolicies
114: .getDefaultWindowsPolicy();
115: return FontPolicies.customSettingsPolicy(defaultPolicy);
116: }
117:
118: /**
119: * Sets the FontPolicy to be used with the JGoodies Windows L&F.
120: * If the specified policy is <code>null</code>, the default will be reset.
121: *
122: * @param fontPolicy the FontPolicy to be used with the JGoodies Windows
123: * L&F, or <code>null</code> to reset to the default
124: *
125: * @see #getFontPolicy()
126: * @see Options#WINDOWS_FONT_POLICY_KEY
127: */
128: public static void setFontPolicy(FontPolicy fontPolicy) {
129: UIManager.put(Options.WINDOWS_FONT_POLICY_KEY, fontPolicy);
130: }
131:
132: /**
133: * Looks up and retrieves the MicroLayoutPolicy used by
134: * the JGoodies Windows Look&Feel.
135: * If a MicroLayoutPolicy has been set for this look, it'll be returned.
136: * Otherwise, the default Windows micro layout policy will be returned.
137: *
138: * @return the MicroLayoutPolicy set for this Look&feel - if any,
139: * or the default Windows MicroLayoutPolicy.
140: *
141: * @see #setMicroLayoutPolicy
142: * @see Options#WINDOWS_MICRO_LAYOUT_POLICY_KEY
143: * @see MicroLayoutPolicies
144: * @see MicroLayoutPolicies#getDefaultWindowsPolicy()
145: */
146: public static MicroLayoutPolicy getMicroLayoutPolicy() {
147: MicroLayoutPolicy policy = (MicroLayoutPolicy) UIManager
148: .get(Options.WINDOWS_MICRO_LAYOUT_POLICY_KEY);
149: return policy != null ? policy : MicroLayoutPolicies
150: .getDefaultWindowsPolicy();
151: }
152:
153: /**
154: * Sets the MicroLayoutPolicy to be used with the JGoodies Windows L&F.
155: * If the specified policy is <code>null</code>, the default will be reset.
156: *
157: * @param microLayoutPolicy the MicroLayoutPolicy to be used with
158: * the JGoodies Windows L&F, or <code>null</code> to reset
159: * to the default
160: *
161: * @see #getMicroLayoutPolicy()
162: * @see Options#WINDOWS_MICRO_LAYOUT_POLICY_KEY
163: */
164: public static void setMicroLayoutPolicy(
165: MicroLayout microLayoutPolicy) {
166: UIManager.put(Options.WINDOWS_MICRO_LAYOUT_POLICY_KEY,
167: microLayoutPolicy);
168: }
169:
170: // Overriding Superclass Behavior ***************************************
171:
172: /**
173: * Invoked during <code>UIManager#setLookAndFeel</code>. In addition
174: * to the superclass behavior, we install the ShadowPopupFactory.
175: *
176: * @see #uninitialize
177: */
178: public void initialize() {
179: super .initialize();
180: ShadowPopupFactory.install();
181: }
182:
183: /**
184: * Invoked during <code>UIManager#setLookAndFeel</code>. In addition
185: * to the superclass behavior, we uninstall the ShadowPopupFactory.
186: *
187: * @see #initialize
188: */
189: public void uninitialize() {
190: super .uninitialize();
191: ShadowPopupFactory.uninstall();
192: }
193:
194: /**
195: * Returns an icon with a disabled appearance. This method is used
196: * to generate a disabled icon when one has not been specified.<p>
197: *
198: * This method will be used only on JDK 5.0 and later.
199: *
200: * @param component the component that will display the icon, may be null.
201: * @param icon the icon to generate disabled icon from.
202: * @return disabled icon, or null if a suitable icon can not be generated.
203: */
204: public Icon getDisabledIcon(JComponent component, Icon icon) {
205: Icon disabledIcon = RGBGrayFilter.getDisabledIcon(component,
206: icon);
207: return disabledIcon != null ? new IconUIResource(disabledIcon)
208: : null;
209: }
210:
211: /**
212: * Initializes the class defaults, that is, overrides some UI delegates
213: * with JGoodies Windows implementations.
214: */
215: protected void initClassDefaults(UIDefaults table) {
216: super .initClassDefaults(table);
217: final String windowsPrefix = "com.jgoodies.looks.windows.Windows";
218: final String commonPrefix = "com.jgoodies.looks.common.ExtBasic";
219:
220: // Overwrite some of the uiDefaults.
221: Object[] uiDefaults = {
222: // Modified size
223: "ComboBoxUI",
224: windowsPrefix + "ComboBoxUI",
225:
226: // Modified preferred height: can be even or odd
227: "ButtonUI",
228: windowsPrefix + "ButtonUI",
229:
230: // Can installs an optional etched border
231: "ScrollPaneUI",
232: windowsPrefix + "ScrollPaneUI",
233:
234: // Optional style and optional special borders
235: "MenuBarUI",
236: windowsPrefix + "MenuBarUI",
237:
238: // Provides an option for a no margin border
239: "PopupMenuUI",
240: windowsPrefix + "PopupMenuUI",
241:
242: // Honors the screen resolution and uses a minimum button width
243: "OptionPaneUI",
244: windowsPrefix + "OptionPaneUI",
245:
246: // 1.4.1 has ugly one touch triangles
247: "SplitPaneUI",
248: windowsPrefix + "SplitPaneUI",
249:
250: // Work in progress: Can have a flat presentation
251: "TabbedPaneUI",
252: windowsPrefix + "TabbedPaneUI",
253:
254: // Selects text after focus gained via keyboard
255: "TextFieldUI", windowsPrefix + "TextFieldUI",
256: "FormattedTextFieldUI",
257: windowsPrefix + "FormattedTextFieldUI",
258:
259: // Selects text after focus gained via keyboard
260: // Renders a dot, not the star ("*") character on Java 1.4 and 5
261: "PasswordFieldUI", windowsPrefix + "PasswordFieldUI",
262:
263: // Updates the disabled and inactive background
264: "TextAreaUI", windowsPrefix + "TextAreaUI",
265:
266: // Corrected position of the tree button icon
267: "TreeUI", windowsPrefix + "TreeUI",
268:
269: // Just to use shared UI delegate
270: "SeparatorUI", windowsPrefix + "SeparatorUI" };
271:
272: if (LookUtils.IS_JAVA_1_4_2_OR_LATER) {
273: // Modified Border
274: uiDefaults = append(uiDefaults, "SpinnerUI", windowsPrefix
275: + "SpinnerUI");
276: }
277:
278: // Aligned menu items
279: if (!LookUtils.IS_JAVA_6_OR_LATER
280: || !LookUtils.IS_OS_WINDOWS_VISTA
281: || !LookUtils.IS_LAF_WINDOWS_XP_ENABLED) {
282: uiDefaults = append(uiDefaults, "MenuItemUI", windowsPrefix
283: + "MenuItemUI");
284: uiDefaults = append(uiDefaults, "CheckBoxMenuItemUI",
285: commonPrefix + "CheckBoxMenuItemUI");
286: uiDefaults = append(uiDefaults, "RadioButtonMenuItemUI",
287: commonPrefix + "RadioButtonMenuItemUI");
288: // Has padding above and below the separator lines
289: uiDefaults = append(uiDefaults, "PopupMenuSeparatorUI",
290: commonPrefix + "PopupMenuSeparatorUI");
291: }
292:
293: if (LookUtils.IS_LAF_WINDOWS_XP_ENABLED) {
294: // Aligned menu items
295: if (!LookUtils.IS_JAVA_6_OR_LATER
296: || !LookUtils.IS_OS_WINDOWS_VISTA) {
297: uiDefaults = append(uiDefaults, "MenuUI", windowsPrefix
298: + "XPMenuUI");
299: }
300:
301: // Optional style and optional special borders;
302: // rollover borders for compound buttons
303: uiDefaults = append(uiDefaults, "ToolBarUI", windowsPrefix
304: + "XPToolBarUI");
305:
306: // Honors XP table header style for custom user renderers.
307: uiDefaults = append(uiDefaults, "TableHeaderUI",
308: windowsPrefix + "XPTableHeaderUI");
309: } else {
310: // Aligned menu items
311: uiDefaults = append(uiDefaults, "MenuUI", commonPrefix
312: + "MenuUI");
313:
314: // Optional style and optional special borders;
315: // rollover borders corrected
316: uiDefaults = append(uiDefaults, "ToolBarUI", windowsPrefix
317: + "ToolBarUI");
318:
319: // Black arrows
320: uiDefaults = append(uiDefaults, "ScrollBarUI",
321: windowsPrefix + "ScrollBarUI");
322:
323: if (!LookUtils.IS_JAVA_1_4_2_OR_LATER) {
324: // Uses unmodified size specified by "ToolBar.separatorSize"
325: uiDefaults = append(uiDefaults, "ToolBarSeparatorUI",
326: windowsPrefix + "ToolBarSeparatorUI");
327: }
328: }
329: table.putDefaults(uiDefaults);
330: }
331:
332: /**
333: * Initializes the component defaults.
334: */
335: protected void initComponentDefaults(UIDefaults table) {
336: super .initComponentDefaults(table);
337:
338: final boolean isXP = LookUtils.IS_LAF_WINDOWS_XP_ENABLED;
339: final boolean isClassic = !isXP;
340: final boolean isVista = LookUtils.IS_OS_WINDOWS_VISTA;
341:
342: initFontDefaults(table);
343:
344: if (isClassic) {
345: initComponentDefaultsClassic(table);
346: }
347: if (isXP && LookUtils.IS_JAVA_1_4) {
348: initComponentDefaultsXP14(table);
349: }
350:
351: MicroLayout microLayout = getMicroLayoutPolicy()
352: .getMicroLayout("Windows", table);
353: if (!isVista || !LookUtils.IS_JAVA_6_OR_LATER
354: || !LookUtils.IS_LAF_WINDOWS_XP_ENABLED) {
355: initMenuItemDefaults(table, microLayout);
356: }
357:
358: Object marginBorder = new BasicBorders.MarginBorder();
359: Object checkBoxMargin = microLayout.getCheckBoxMargin();
360:
361: Object etchedBorder = new UIDefaults.ProxyLazyValue(
362: "javax.swing.plaf.BorderUIResource",
363: "getEtchedBorderUIResource");
364: Object buttonBorder = new SimpleProxyLazyValue(
365: "com.jgoodies.looks.windows.WindowsLookAndFeel",
366: "getButtonBorder");
367:
368: Object menuBorder = isXP ? WindowsBorders.getXPMenuBorder()
369: : WindowsBorders.getMenuBorder();
370:
371: Object menuBarEmptyBorder = marginBorder;
372: Object menuBarSeparatorBorder = WindowsBorders
373: .getSeparatorBorder();
374: Object menuBarEtchedBorder = WindowsBorders.getEtchedBorder();
375: Object menuBarHeaderBorder = WindowsBorders
376: .getMenuBarHeaderBorder();
377:
378: Object toolBarEmptyBorder = marginBorder;
379: Object toolBarSeparatorBorder = WindowsBorders
380: .getSeparatorBorder();
381: Object toolBarEtchedBorder = WindowsBorders.getEtchedBorder();
382: Object toolBarHeaderBorder = WindowsBorders
383: .getToolBarHeaderBorder();
384:
385: Object buttonMargin = microLayout.getButtonMargin();
386:
387: Object toolBarSeparatorSize = LookUtils.IS_JAVA_1_4_2_OR_LATER ? null
388: : new DimensionUIResource(6, Options
389: .getDefaultIconSize().height);
390:
391: Object textInsets = microLayout.getTextInsets();
392: Object wrappedTextInsets = microLayout.getWrappedTextInsets();
393: Insets comboEditorInsets = microLayout
394: .getComboBoxEditorInsets();
395:
396: int comboBorderSize = microLayout.getComboBorderSize();
397: int comboPopupBorderSize = microLayout
398: .getComboPopupBorderSize();
399: int comboRendererGap = comboEditorInsets.left + comboBorderSize
400: - comboPopupBorderSize;
401: Object comboRendererBorder = new EmptyBorder(1,
402: comboRendererGap, 1, comboRendererGap);
403: Object comboTableEditorInsets = new Insets(0, 0, 0, 0);
404:
405: Object popupMenuSeparatorMargin = microLayout
406: .getPopupMenuSeparatorMargin();
407:
408: // Should be active.
409: int treeFontSize = table.getFont("Tree.font").getSize();
410: Integer rowHeight = new Integer(treeFontSize + 6);
411:
412: Class super class = getClass().getSuperclass();
413: Color controlColor = table.getColor("control");
414: Object disabledTextBackground = table
415: .getColor("TextField.disabledBackground");
416: Object inactiveTextBackground = table
417: .getColor("TextField.inactiveBackground");
418:
419: Object comboBoxDisabledBackground = (isVista && isXP) ? table
420: .getColor("ComboBox.background")
421: : disabledTextBackground;
422:
423: Object menuBarBackground = isXP ? table.get("control") : table
424: .get("menu");
425: Object menuSelectionBackground = isXP ? table
426: .get("MenuItem.selectionBackground") : table
427: .get("Menu.background");
428: Object menuSelectionForeground = isXP ? table
429: .get("MenuItem.selectionForeground") : table
430: .get("Menu.foreground");
431:
432: Character passwordEchoChar = new Character(isXP ? '\u25CF'
433: : '*');
434:
435: Object[] defaults = {
436: "Button.border",
437: buttonBorder,
438: "Button.margin",
439: buttonMargin, // Sun's 14px margin is too wide
440:
441: // 1.4.2 uses a 2 pixel non-standard border that leads to bad
442: // alignment in the typical case that the border is not painted
443: "CheckBox.border",
444: marginBorder,
445: "CheckBox.margin",
446: checkBoxMargin,
447:
448: "ComboBox.disabledBackground",
449: comboBoxDisabledBackground,
450: "ComboBox.editorBorder",
451: marginBorder,
452: "ComboBox.editorColumns",
453: new Integer(5),
454: "ComboBox.editorInsets",
455: comboEditorInsets, // Added by JGoodies
456: "ComboBox.tableEditorInsets",
457: comboTableEditorInsets,
458: "ComboBox.rendererBorder",
459: comboRendererBorder, // Added by JGoodies
460:
461: "EditorPane.margin",
462: wrappedTextInsets,
463:
464: // Begin 1.3 und 1.4.0
465: "Menu.border",
466: menuBorder, // Fixed in 1.4.1
467: "Menu.borderPainted",
468: Boolean.TRUE,
469: "Menu.background",
470: menuBarBackground,
471: "Menu.selectionForeground",
472: menuSelectionForeground,
473: "Menu.selectionBackground",
474: menuSelectionBackground,
475: // End 1.3 und 1.4.0
476:
477: "MenuBar.background",
478: menuBarBackground,
479: "MenuBar.border",
480: menuBarSeparatorBorder, // 1.4.1 Separator wrong
481: "MenuBar.emptyBorder",
482: menuBarEmptyBorder, // Added by JGoodies
483: "MenuBar.separatorBorder",
484: menuBarSeparatorBorder, // Added by JGoodies
485: "MenuBar.etchedBorder",
486: menuBarEtchedBorder, // Added by JGoodies
487: "MenuBar.headerBorder",
488: menuBarHeaderBorder, // Added by JGoodies
489:
490: "FormattedTextField.disabledBackground",
491: disabledTextBackground, // for readonly
492: "FormattedTextField.inactiveBackground",
493: inactiveTextBackground, // for readonly
494: "FormattedTextField.margin",
495: textInsets, // Poor in 1.6
496:
497: "PasswordField.margin",
498: textInsets, // Poor in 1.6
499: "PasswordField.echoChar",
500: passwordEchoChar,
501:
502: "PopupMenu.border",
503: WindowsBorders.getPopupMenuBorder(),
504: "PopupMenu.noMarginBorder",
505: WindowsBorders.getNoMarginPopupMenuBorder(),
506: "PopupMenuSeparator.margin",
507: popupMenuSeparatorMargin,
508:
509: "ScrollPane.etchedBorder",
510: etchedBorder, // Added by JGoodies
511:
512: "Spinner.defaultEditorInsets",
513: textInsets, // Added by JGoodies
514:
515: // 1.4.1 uses a 2 pixel non-standard border, that leads to bad
516: // alignment in the typical case that the border is not painted
517: "RadioButton.border",
518: marginBorder,
519: "RadioButton.margin",
520: checkBoxMargin,
521:
522: "Table.gridColor",
523: controlColor, // 1.4.1 Bug; active
524: "TextArea.margin",
525: wrappedTextInsets, // 1.4.1 Bug
526: "TextArea.disabledBackground", disabledTextBackground,
527: "TextArea.inactiveBackground", inactiveTextBackground,
528: "TextField.margin",
529: textInsets, // 1.4.1 Bug
530: "ToggleButton.margin",
531: buttonMargin, // Sun's 14px margin is too wide
532:
533: "ToolBar.emptyBorder",
534: toolBarEmptyBorder, // Added by JGoodies
535: "ToolBar.separatorBorder",
536: toolBarSeparatorBorder, // Added by JGoodies
537: "ToolBar.etchedBorder",
538: toolBarEtchedBorder, // Added by JGoodies
539: "ToolBar.headerBorder",
540: toolBarHeaderBorder, // Added by JGoodies
541: "ToolBar.separatorSize", toolBarSeparatorSize,
542: "ToolBar.margin", new InsetsUIResource(0, 10, 0, 0),
543:
544: "Tree.selectionBorderColor", controlColor, // 1.4.1 Bug; active
545: "Tree.rowHeight", rowHeight, // 1.4.1 Bug
546: };
547: if (LookUtils.IS_JAVA_1_4) {
548: defaults = append(defaults,
549: new Object[] {
550: "InternalFrame.icon",
551: makeIcon(super class, "icons/JavaCup.gif"),
552: "OptionPane.errorIcon",
553: isXP ? makeIcon(getClass(),
554: "icons/xp/Error.png") : makeIcon(
555: super class, "icons/Error.gif"),
556: "OptionPane.informationIcon",
557: isXP ? makeIcon(getClass(),
558: "icons/xp/Inform.png") : makeIcon(
559: super class, "icons/Inform.gif"),
560: "OptionPane.warningIcon",
561: isXP ? makeIcon(getClass(),
562: "icons/xp/Warn.png") : makeIcon(
563: super class, "icons/Warn.gif"),
564: "OptionPane.questionIcon",
565: isXP ? makeIcon(getClass(),
566: "icons/xp/Inform.png") : makeIcon(
567: super class, "icons/Question.gif") });
568: }
569: if (LookUtils.IS_JAVA_1_4 || LookUtils.IS_JAVA_5) {
570: defaults = append(defaults,
571: new Object[] {
572: "Tree.openIcon",
573: isXP ? makeIcon(getClass(),
574: "icons/xp/TreeOpen.png")
575: : makeIcon(getClass(),
576: "icons/TreeOpen.gif"),
577: "Tree.closedIcon",
578: isXP ? makeIcon(getClass(),
579: "icons/xp/TreeClosed.png")
580: : makeIcon(getClass(),
581: "icons/TreeClosed.gif") });
582: }
583: if (LookUtils.IS_JAVA_6_OR_LATER) {
584: defaults = append(defaults, new Object[] {
585: "Spinner.border", table.get("TextField.border") });
586: }
587: table.putDefaults(defaults);
588: }
589:
590: /**
591: * Initializes component defaults required in classic mode only.
592: */
593: private void initComponentDefaultsClassic(UIDefaults table) {
594: Object checkBoxIcon = new SimpleProxyLazyValue(
595: "com.jgoodies.looks.windows.WindowsLookAndFeel",
596: "getCheckBoxIcon");
597:
598: Object radioButtonIcon = new SimpleProxyLazyValue(
599: "com.jgoodies.looks.windows.WindowsLookAndFeel",
600: "getRadioButtonIcon");
601:
602: Border winInsetBorder = new BasicBorders.FieldBorder(table
603: .getColor("controlShadow"), table
604: .getColor("controlDkShadow"), table
605: .getColor("controlHighlight"), table
606: .getColor("controlLtHighlight"));
607:
608: Object[] defaults = {
609: "CheckBox.checkColor",
610: table.get("controlText"), // kind-of black
611: "CheckBox.icon", checkBoxIcon,
612: "RadioButton.checkColor",
613: table.get("controlText"), // kind-of black
614: "RadioButton.icon", radioButtonIcon,
615: "Table.scrollPaneBorder", winInsetBorder, // 1.4.1 Bug
616:
617: };
618: table.putDefaults(defaults);
619: }
620:
621: /**
622: * Initializes component defaults required in XP mode on Java 1.4.2 only.
623: */
624: private void initComponentDefaultsXP14(UIDefaults table) {
625: Object[] defaults = { "TitledBorder.titleColor",
626: table.getColor("activeCaption") };
627: table.putDefaults(defaults);
628: }
629:
630: /**
631: * Looks up the correct control font and sets it for all controls.
632: */
633: private void initFontDefaults(UIDefaults table) {
634: FontPolicy fontChoicePolicy = getFontPolicy();
635: FontSet fontSet = fontChoicePolicy.getFontSet("Windows", table);
636: initFontDefaults(table, fontSet);
637: }
638:
639: private void initMenuItemDefaults(UIDefaults table,
640: MicroLayout microLayout) {
641: Object menuMargin = microLayout.getMenuMargin();
642: Object menuItemMargin = microLayout.getMenuItemMargin();
643: Icon menuItemCheckIcon = new MinimumSizedIcon();
644: Object[] defaults = {
645:
646: "Menu.margin",
647: menuMargin, // 1.4.1 Bug
648:
649: "MenuItem.borderPainted", Boolean.TRUE,
650: "MenuItem.checkIcon", menuItemCheckIcon, // Aligns menu items
651: "MenuItem.margin", menuItemMargin, // 1.4.1 Bug
652: "CheckBoxMenuItem.margin", menuItemMargin, // 1.4.1 Bug
653: "RadioButtonMenuItem.margin", menuItemMargin, // 1.4.1 Bug
654: };
655: table.putDefaults(defaults);
656: }
657:
658: /**
659: * Sets Fonts in the given FontSet as defaults for all known
660: * component types in the given UIDefaults table.
661: *
662: * @param table the UIDefaults table used to set fonts
663: * @param fontSet describes the set of Fonts to be installed
664: */
665: private static void initFontDefaults(UIDefaults table,
666: FontSet fontSet) {
667: Font controlFont = fontSet.getControlFont();
668: Font menuFont = fontSet.getMenuFont();
669: Font messageFont = fontSet.getMessageFont();
670: Font toolTipFont = fontSet.getSmallFont();
671: Font titleFont = fontSet.getTitleFont();
672: Font windowFont = fontSet.getWindowTitleFont();
673:
674: Object[] defaults = { "Button.font", controlFont,
675: "CheckBox.font", controlFont, "ColorChooser.font",
676: controlFont, "ComboBox.font", controlFont,
677: "EditorPane.font", controlFont,
678: "FormattedTextField.font", controlFont, "Label.font",
679: controlFont, "List.font", controlFont, "Panel.font",
680: controlFont, "PasswordField.font", controlFont,
681: "ProgressBar.font", controlFont, "RadioButton.font",
682: controlFont, "ScrollPane.font", controlFont,
683: "Spinner.font", controlFont, "TabbedPane.font",
684: controlFont, "Table.font", controlFont,
685: "TableHeader.font", controlFont, "TextArea.font",
686: controlFont, "TextField.font",
687: controlFont,
688: "TextPane.font",
689: controlFont,
690: "ToolBar.font",
691: controlFont,
692: "ToggleButton.font",
693: controlFont,
694: "Tree.font",
695: controlFont,
696: "Viewport.font",
697: controlFont,
698:
699: "InternalFrame.titleFont",
700: windowFont, // controlBold
701: "OptionPane.font", messageFont,
702: "OptionPane.messageFont", messageFont,
703: "OptionPane.buttonFont", messageFont,
704: "TitledBorder.font",
705: titleFont,
706: "ToolTip.font",
707: toolTipFont,
708:
709: "CheckBoxMenuItem.font",
710: menuFont,
711: "CheckBoxMenuItem.acceleratorFont",
712: menuFont, // 1.3 only ?
713: "Menu.font", menuFont, "Menu.acceleratorFont",
714: menuFont, "MenuBar.font", menuFont, "MenuItem.font",
715: menuFont, "MenuItem.acceleratorFont", menuFont,
716: "PopupMenu.font", menuFont, "RadioButtonMenuItem.font",
717: menuFont, "RadioButtonMenuItem.acceleratorFont",
718: menuFont, // 1.3 only ?
719: };
720: table.putDefaults(defaults);
721: }
722:
723: // Getters for Proxy Access (Referred classes can stay package visible) ***
724:
725: public static Border getButtonBorder() {
726: return WindowsBorders.getButtonBorder();
727: }
728:
729: public static Icon getCheckBoxIcon() {
730: return WindowsIconFactory.getCheckBoxIcon();
731: }
732:
733: public static Icon getRadioButtonIcon() {
734: return WindowsIconFactory.getRadioButtonIcon();
735: }
736:
737: // Helper Code ************************************************************
738:
739: /**
740: * Appends the key and value to the given source array and returns
741: * a copy that has the two new elements at its end.
742: *
743: * @return an array with the key and value appended
744: */
745: private static Object[] append(Object[] source, String key,
746: Object value) {
747: int length = source.length;
748: Object[] destination = new Object[length + 2];
749: System.arraycopy(source, 0, destination, 0, length);
750: destination[length] = key;
751: destination[length + 1] = value;
752: return destination;
753: }
754:
755: /**
756: * Appends the key and value to the given source array and returns
757: * a copy that has the two new elements at its end.
758: *
759: * @return an array with the key and value appended
760: */
761: private static Object[] append(Object[] source,
762: Object[] keysAndValues) {
763: int length = source.length;
764: Object[] destination = new Object[length + keysAndValues.length];
765: System.arraycopy(source, 0, destination, 0, length);
766: for (int i = 0; i < keysAndValues.length; i++) {
767: destination[length + i] = keysAndValues[i];
768: }
769: return destination;
770: }
771:
772: // Helper Class ***********************************************************
773:
774: /**
775: * This class provides an implementation of <code>LazyValue</code> that
776: * can be used to delay loading of the Class for the instance to be created.
777: * It also avoids creation of an anonymous inner class for the
778: * <code>LazyValue</code>
779: * subclass. Both of these improve performance at the time that a
780: * a Look and Feel is loaded, at the cost of a slight performance
781: * reduction the first time <code>createValue</code> is called
782: * (since Reflection APIs are used).
783: */
784: private static class SimpleProxyLazyValue implements
785: UIDefaults.LazyValue {
786:
787: private final String className;
788: private final String methodName;
789:
790: /**
791: * Creates a <code>LazyValue</code> which will construct an instance
792: * when asked.
793: *
794: * @param c a <code>String</code> specifying the classname of the class
795: * containing a static method to be called for instance creation
796: * @param m a <code>String</code> specifying the static
797: * method to be called on class c
798: */
799: public SimpleProxyLazyValue(String c, String m) {
800: className = c;
801: methodName = m;
802: }
803:
804: /**
805: * Creates the value retrieved from the <code>UIDefaults</code> table.
806: * The object is created each time it is accessed.
807: *
808: * @param table a <code>UIDefaults</code> table
809: * @return the created <code>Object</code>
810: */
811: public Object createValue(UIDefaults table) {
812: Object instance = null;
813: try {
814: Class c;
815: // We use a separate ClassLoader
816: ClassLoader classLoader = table != null ? (ClassLoader) table
817: .get("ClassLoader")
818: : Thread.currentThread()
819: .getContextClassLoader();
820: if (classLoader == null) {
821: classLoader = getClass().getClassLoader();
822: }
823: c = Class.forName(className, true, classLoader);
824: Method m = c.getMethod(methodName, null);
825: instance = m.invoke(c, null);
826: } catch (Throwable t) {
827: LookUtils.log("Problem creating " + className
828: + " with method " + methodName + t);
829: }
830: return instance;
831: }
832: }
833:
834: }
|