Java tutorial
/* * Copyright (c) 2001-2013 JGoodies Software GmbH. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * o Neither the name of JGoodies Software GmbH nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jgoodies.looks.plastic; import static com.jgoodies.common.base.Preconditions.checkNotNull; import static com.jgoodies.common.internal.Messages.MUST_NOT_BE_NULL; import java.awt.Color; import java.awt.Insets; import java.awt.Toolkit; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.plaf.BorderUIResource; import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.FontUIResource; import javax.swing.plaf.IconUIResource; import javax.swing.plaf.InsetsUIResource; import javax.swing.plaf.basic.BasicBorders; import javax.swing.plaf.metal.MetalLookAndFeel; import javax.swing.plaf.metal.MetalTheme; import com.jgoodies.common.base.SystemUtils; import com.jgoodies.looks.FontPolicies; import com.jgoodies.looks.FontPolicy; import com.jgoodies.looks.LookUtils; import com.jgoodies.looks.MicroLayout; import com.jgoodies.looks.MicroLayoutPolicies; import com.jgoodies.looks.MicroLayoutPolicy; import com.jgoodies.looks.Options; import com.jgoodies.looks.common.MinimumSizedIcon; import com.jgoodies.looks.common.RGBGrayFilter; import com.jgoodies.looks.common.ShadowPopupFactory; import com.jgoodies.looks.plastic.theme.SkyBluer; /** * The base class for the JGoodies Plastic look&feel family. * Initializes class and component defaults for the Plastic L&f * and provides keys and optional features for the Plastic family. * * @author Karsten Lentzsch * @version $Revision: 1.46 $ */ public class PlasticLookAndFeel extends MetalLookAndFeel { // System and Client Property Keys **************************************** /** * Client property key to set a border style - shadows the header style. */ public static final String BORDER_STYLE_KEY = "Plastic.borderStyle"; /** * Client property key to disable the pseudo 3D effect. */ public static final String IS_3D_KEY = "Plastic.is3D"; /** * A System property key to set the default theme. */ public static final String DEFAULT_THEME_KEY = "Plastic.defaultTheme"; /** * A System property key that indicates that the high contrast * focus colors shall be choosen - if applicable. * If not set, some focus colors look good but have low contrast. * Basically, the low contrast scheme uses the Plastic colors * before 1.0.7, and the high contrast scheme is 1.0.7 - 1.0.9. */ public static final String HIGH_CONTRAST_FOCUS_ENABLED_KEY = "Plastic.highContrastFocus"; /** * A System property key for the rendering style of the Plastic * TabbedPane. Valid values are: <tt>default</tt> for the * Plastic 1.0 tabs, and <tt>metal</tt> for the Metal L&F tabs. */ protected static final String TAB_STYLE_KEY = "Plastic.tabStyle"; /** * A System property value that indicates that Plastic shall render * tabs in the Plastic 1.0 style. This is the default. */ public static final String TAB_STYLE_DEFAULT_VALUE = "default"; /** * A System property value that indicates that Plastic shall * render tabs in the Metal L&F style. */ public static final String TAB_STYLE_METAL_VALUE = "metal"; // State ***************************************************************** /** * Holds whether Plastic uses Metal or Plastic tabbed panes. */ private static boolean useMetalTabs = LookUtils.getSystemProperty(TAB_STYLE_KEY, "") .equalsIgnoreCase(TAB_STYLE_METAL_VALUE); /** * Holds whether we are using the high contrast focus colors. */ private static boolean useHighContrastFocusColors = LookUtils .getSystemProperty(HIGH_CONTRAST_FOCUS_ENABLED_KEY) != null; /** * The List of installed Plastic themes. */ private static List<PlasticTheme> installedThemes; /** The look-global state for the 3D enablement. */ private static boolean is3DEnabled = false; private static boolean selectTextOnKeyboardFocusGained = LookUtils.IS_OS_WINDOWS; // Instance Creation ****************************************************** /** * Constructs the PlasticLookAndFeel, creates the default theme * and sets it as current Plastic theme. */ public PlasticLookAndFeel() { getPlasticTheme(); } // L&f Description ******************************************************** @Override public String getID() { return "JGoodies Plastic"; } @Override public String getName() { return "JGoodies Plastic"; } @Override public String getDescription() { return "The JGoodies Plastic Look and Feel" + " - \u00a9 2001-2013 JGoodies Software GmbH"; } // Optional Settings ****************************************************** /** * Looks up and retrieves the FontPolicy used * by the JGoodies Plastic Look&Feel family. * If a FontPolicy has been set, it'll be returned. * Otherwise, this method checks if a FontPolicy or FontSet is defined * in the system properties or UIDefaults. If so, it is returned. * If no FontPolicy has been set for this look, in the system * properties or UIDefaults, the default Plastic font policy * will be returned. * * @return the FontPolicy set for this Look&feel - if any, * the FontPolicy specified in the system properties or UIDefaults * - if any, or the default Plastic font policy. * * @see #setFontPolicy * @see Options#PLASTIC_FONT_POLICY_KEY * @see FontPolicies * @see FontPolicies#customSettingsPolicy(FontPolicy) * @see FontPolicies#getDefaultPlasticPolicy() */ public static FontPolicy getFontPolicy() { FontPolicy policy = (FontPolicy) UIManager.get(Options.PLASTIC_FONT_POLICY_KEY); if (policy != null) { return policy; } FontPolicy defaultPolicy = FontPolicies.getDefaultPlasticPolicy(); return FontPolicies.customSettingsPolicy(defaultPolicy); } /** * Sets the FontPolicy to be used with the JGoodies Plastic L&F * family. If the specified policy is {@code null}, the default will * be reset. * * @param fontPolicy the FontPolicy to be used with * the JGoodies Plastic L&F family, or {@code null} to reset * to the default * * @see #getFontPolicy() * @see Options#PLASTIC_FONT_POLICY_KEY */ public static void setFontPolicy(FontPolicy fontPolicy) { UIManager.put(Options.PLASTIC_FONT_POLICY_KEY, fontPolicy); } /** * Looks up and retrieves the MicroLayoutPolicy used by * the JGoodies Plastic Look&Fs. * If a MicroLayoutPolicy has been set for this look, it'll be returned. * Otherwise, the default Plastic micro layout policy will be returned. * * @return the MicroLayoutPolicy set for this Look&feel - if any, * or the default Plastic MicroLayoutPolicy. * * @see #setMicroLayoutPolicy * @see Options#PLASTIC_MICRO_LAYOUT_POLICY_KEY * @see MicroLayoutPolicies */ public static MicroLayoutPolicy getMicroLayoutPolicy() { MicroLayoutPolicy policy = (MicroLayoutPolicy) UIManager.get(Options.PLASTIC_MICRO_LAYOUT_POLICY_KEY); return policy != null ? policy : MicroLayoutPolicies.getDefaultPlasticPolicy(); } /** * Sets the MicroLayoutPolicy to be used with the JGoodies Plastic L&Fs. * If the specified policy is {@code null}, the default will be reset. * * @param microLayoutPolicy the MicroLayoutPolicy to be used with * the JGoodies Plastic L&Fs, or {@code null} to reset * to the default * * @see #getMicroLayoutPolicy() * @see Options#PLASTIC_MICRO_LAYOUT_POLICY_KEY */ public static void setMicroLayoutPolicy(MicroLayout microLayoutPolicy) { UIManager.put(Options.PLASTIC_MICRO_LAYOUT_POLICY_KEY, microLayoutPolicy); } protected boolean is3DEnabled() { return is3DEnabled; } public static void set3DEnabled(boolean b) { is3DEnabled = b; } public static String getTabStyle() { return useMetalTabs ? TAB_STYLE_METAL_VALUE : TAB_STYLE_DEFAULT_VALUE; } public static void setTabStyle(String tabStyle) { useMetalTabs = tabStyle.equalsIgnoreCase(TAB_STYLE_METAL_VALUE); } public static boolean getHighContrastFocusColorsEnabled() { return useHighContrastFocusColors; } public static void setHighContrastFocusColorsEnabled(boolean b) { useHighContrastFocusColors = b; } public static boolean isSelectTextOnKeyboardFocusGained() { return selectTextOnKeyboardFocusGained; } /** * Sets whether text field text shall be selected when it gains focus * via the keyboard. This is enabled on Windows by default and * disabled on all other platforms. * * @param b <code>true</code> to enabled, <code>false</code> to disable */ public static void setSelectTextOnKeyboardFocusGained(boolean b) { selectTextOnKeyboardFocusGained = b; } // Overriding Superclass Behavior *************************************** /** * Invoked during {@code UIManager#setLookAndFeel}. In addition * to the superclass behavior, we install the ShadowPopupFactory. * * @see #uninitialize */ @Override public void initialize() { super.initialize(); ShadowPopupFactory.install(); } /** * Invoked during {@code UIManager#setLookAndFeel}. In addition * to the superclass behavior, we uninstall the ShadowPopupFactory. * * @see #initialize */ @Override public void uninitialize() { super.uninitialize(); ShadowPopupFactory.uninstall(); } /** * Returns an icon with a disabled appearance. This method is used * to generate a disabled icon when one has not been specified.<p> * * This method will be used only on JDK 5.0 and later. * * @param component the component that will display the icon, may be null. * @param icon the icon to generate disabled icon from. * @return disabled icon, or null if a suitable icon can not be generated. */ @Override public Icon getDisabledIcon(JComponent component, Icon icon) { Icon disabledIcon = RGBGrayFilter.getDisabledIcon(component, icon); return disabledIcon != null ? new IconUIResource(disabledIcon) : null; } /** * Initializes the class defaults, that is, overrides some UI delegates * with JGoodies Plastic implementations. * * @param table the UIDefaults table to work with * @see javax.swing.plaf.basic.BasicLookAndFeel#getDefaults() */ @Override protected void initClassDefaults(UIDefaults table) { super.initClassDefaults(table); final String plasticPrefix = "com.jgoodies.looks.plastic.Plastic"; final String commonPrefix = "com.jgoodies.looks.common.ExtBasic"; // Overwrite some of the uiDefaults. Object[] uiDefaults = { // 3D effect; optional narrow margins "ButtonUI", plasticPrefix + "ButtonUI", "ToggleButtonUI", plasticPrefix + "ToggleButtonUI", // 3D effect "ComboBoxUI", plasticPrefix + "ComboBoxUI", "ScrollBarUI", plasticPrefix + "ScrollBarUI", "SpinnerUI", plasticPrefix + "SpinnerUI", // Special borders defined by border style or header style, see LookUtils "MenuBarUI", plasticPrefix + "MenuBarUI", "ToolBarUI", plasticPrefix + "ToolBarUI", // Aligns menu icons "MenuUI", plasticPrefix + "MenuUI", "MenuItemUI", commonPrefix + "MenuItemUI", "CheckBoxMenuItemUI", commonPrefix + "CheckBoxMenuItemUI", "RadioButtonMenuItemUI", commonPrefix + "RadioButtonMenuItemUI", // Provides an option for a no margin border "PopupMenuUI", plasticPrefix + "PopupMenuUI", // Has padding above and below the separator lines "PopupMenuSeparatorUI", commonPrefix + "PopupMenuSeparatorUI", // Honors the screen resolution and uses a minimum button width "OptionPaneUI", plasticPrefix + "OptionPaneUI", // Can installs an optional etched border "ScrollPaneUI", plasticPrefix + "ScrollPaneUI", // Uses a modified split divider "SplitPaneUI", plasticPrefix + "SplitPaneUI", // Selects all text after focus gain via keyboard. "PasswordFieldUI", plasticPrefix + "PasswordFieldUI", // Updates the disabled and inactive background "TextAreaUI", plasticPrefix + "TextAreaUI", // Modified icons and lines "TreeUI", plasticPrefix + "TreeUI", // Just to use Plastic colors "InternalFrameUI", plasticPrefix + "InternalFrameUI", // Share the UI delegate instances "SeparatorUI", plasticPrefix + "SeparatorUI", "ToolBarSeparatorUI", plasticPrefix + "ToolBarSeparatorUI", // Optionally looks up the system icons "FileChooserUI", plasticPrefix + "FileChooserUI" }; if (!useMetalTabs) { // Modified tabs and ability use a version with reduced borders. uiDefaults = append(uiDefaults, "TabbedPaneUI", plasticPrefix + "TabbedPaneUI"); } if (isSelectTextOnKeyboardFocusGained()) { // Selects all text after focus gain via keyboard. uiDefaults = append(uiDefaults, "TextFieldUI", plasticPrefix + "TextFieldUI"); uiDefaults = append(uiDefaults, "FormattedTextFieldUI", plasticPrefix + "FormattedTextFieldUI"); } table.putDefaults(uiDefaults); } @Override protected void initComponentDefaults(UIDefaults table) { super.initComponentDefaults(table); MicroLayout microLayout = getMicroLayoutPolicy().getMicroLayout(getName(), table); Insets buttonBorderInsets = microLayout.getButtonBorderInsets(); Object marginBorder = new BasicBorders.MarginBorder(); Object buttonBorder = PlasticBorders.getButtonBorder(buttonBorderInsets); Object comboBoxButtonBorder = PlasticBorders.getComboBoxArrowButtonBorder(); Border comboBoxEditorBorder = PlasticBorders.getComboBoxEditorBorder(); Object menuItemBorder = PlasticBorders.getMenuItemBorder(); Object textFieldBorder = PlasticBorders.getTextFieldBorder(); Object toggleButtonBorder = PlasticBorders.getToggleButtonBorder(buttonBorderInsets); Object scrollPaneBorder = PlasticBorders.getScrollPaneBorder(); Object tableHeaderBorder = new BorderUIResource((Border) table.get("TableHeader.cellBorder")); Object menuBarEmptyBorder = marginBorder; Object menuBarSeparatorBorder = PlasticBorders.getSeparatorBorder(); Object menuBarEtchedBorder = PlasticBorders.getEtchedBorder(); Object menuBarHeaderBorder = PlasticBorders.getMenuBarHeaderBorder(); Object toolBarEmptyBorder = marginBorder; Object toolBarSeparatorBorder = PlasticBorders.getSeparatorBorder(); Object toolBarEtchedBorder = PlasticBorders.getEtchedBorder(); Object toolBarHeaderBorder = PlasticBorders.getToolBarHeaderBorder(); Object internalFrameBorder = getInternalFrameBorder(); Object paletteBorder = getPaletteBorder(); Color controlColor = table.getColor("control"); Object checkBoxIcon = PlasticIconFactory.getCheckBoxIcon(); Object checkBoxMargin = microLayout.getCheckBoxMargin(); Object buttonMargin = microLayout.getButtonMargin(); Object textInsets = microLayout.getTextInsets(); Object wrappedTextInsets = microLayout.getWrappedTextInsets(); Insets comboEditorInsets = microLayout.getComboBoxEditorInsets(); Insets comboEditorBorderInsets = comboBoxEditorBorder.getBorderInsets(null); int comboBorderSize = comboEditorBorderInsets.left; int comboPopupBorderSize = microLayout.getComboPopupBorderSize(); int comboRendererGap = comboEditorInsets.left + comboBorderSize - comboPopupBorderSize; Object comboRendererBorder = new EmptyBorder(1, comboRendererGap, 1, comboRendererGap); Object comboTableEditorInsets = new Insets(0, 0, 0, 0); Object menuItemMargin = microLayout.getMenuItemMargin(); Object menuMargin = microLayout.getMenuMargin(); Icon menuItemCheckIcon = new MinimumSizedIcon(); Icon checkBoxMenuItemIcon = PlasticIconFactory.getCheckBoxMenuItemIcon(); Icon radioButtonMenuItemIcon = PlasticIconFactory.getRadioButtonMenuItemIcon(); Color menuItemForeground = table.getColor("MenuItem.foreground"); Color inactiveTextBackground = table.getColor("TextField.inactiveBackground"); // Should be active. int treeFontSize = table.getFont("Tree.font").getSize(); Integer rowHeight = new Integer(treeFontSize + 6); Object treeExpandedIcon = PlasticIconFactory.getExpandedTreeIcon(); Object treeCollapsedIcon = PlasticIconFactory.getCollapsedTreeIcon(); ColorUIResource gray = new ColorUIResource(Color.GRAY); Boolean is3D = Boolean.valueOf(is3DEnabled()); Character passwordEchoChar = new Character(SystemUtils.IS_OS_WINDOWS ? '\u25CF' : '\u2022'); String iconPrefix = "icons/" + (SystemUtils.IS_LOW_RESOLUTION ? "32x32/" : "48x48/"); Object errorIcon = makeIcon(getClass(), iconPrefix + "dialog-error.png"); Object informationIcon = makeIcon(getClass(), iconPrefix + "dialog-information.png"); Object helpIcon = makeIcon(getClass(), iconPrefix + "dialog-help.png"); Object warningIcon = makeIcon(getClass(), iconPrefix + "dialog-warning.png"); Object[] defaults = { "Button.border", buttonBorder, "Button.margin", buttonMargin, "CheckBox.margin", checkBoxMargin, // Use a modified check "CheckBox.icon", checkBoxIcon, "CheckBoxMenuItem.border", menuItemBorder, "CheckBoxMenuItem.margin", menuItemMargin, // 1.4.1 Bug "CheckBoxMenuItem.checkIcon", checkBoxMenuItemIcon, "CheckBoxMenuItem.background", getMenuItemBackground(), // Added by JGoodies "CheckBoxMenuItem.selectionForeground", getMenuItemSelectedForeground(), "CheckBoxMenuItem.selectionBackground", getMenuItemSelectedBackground(), "CheckBoxMenuItem.acceleratorForeground", menuItemForeground, "CheckBoxMenuItem.acceleratorSelectionForeground", getMenuItemSelectedForeground(), "CheckBoxMenuItem.acceleratorSelectionBackground", getMenuItemSelectedBackground(), // ComboBox uses menu item selection colors "ComboBox.selectionForeground", getMenuSelectedForeground(), "ComboBox.selectionBackground", getMenuSelectedBackground(), "ComboBox.arrowButtonBorder", comboBoxButtonBorder, "ComboBox.editorBorder", comboBoxEditorBorder, "ComboBox.editorColumns", new Integer(5), "ComboBox.editorBorderInsets", comboEditorBorderInsets, // Added by JGoodies "ComboBox.editorInsets", textInsets, // Added by JGoodies "ComboBox.tableEditorInsets", comboTableEditorInsets, "ComboBox.rendererBorder", comboRendererBorder, // Added by JGoodies "EditorPane.margin", wrappedTextInsets, "InternalFrame.border", internalFrameBorder, "InternalFrame.paletteBorder", paletteBorder, "List.font", getControlTextFont(), "Menu.border", PlasticBorders.getMenuBorder(), "Menu.margin", menuMargin, "Menu.arrowIcon", PlasticIconFactory.getMenuArrowIcon(), "MenuBar.emptyBorder", menuBarEmptyBorder, // Added by JGoodies "MenuBar.separatorBorder", menuBarSeparatorBorder, // Added by JGoodies "MenuBar.etchedBorder", menuBarEtchedBorder, // Added by JGoodies "MenuBar.headerBorder", menuBarHeaderBorder, // Added by JGoodies "MenuItem.border", menuItemBorder, "MenuItem.checkIcon", menuItemCheckIcon, // Aligns menu items "MenuItem.margin", menuItemMargin, // 1.4.1 Bug "MenuItem.background", getMenuItemBackground(), // Added by JGoodies "MenuItem.selectionForeground", getMenuItemSelectedForeground(), // Added by JGoodies "MenuItem.selectionBackground", getMenuItemSelectedBackground(), // Added by JGoodies "MenuItem.acceleratorForeground", menuItemForeground, "MenuItem.acceleratorSelectionForeground", getMenuItemSelectedForeground(), "MenuItem.acceleratorSelectionBackground", getMenuItemSelectedBackground(), "OptionPane.errorIcon", errorIcon, "OptionPane.informationIcon", informationIcon, "OptionPane.questionIcon", helpIcon, "OptionPane.warningIcon", warningIcon, //"DesktopIcon.icon", makeIcon(superclass, "icons/DesktopIcon.gif"), "FileView.computerIcon", makeIcon(getClass(), "icons/Computer.gif"), "FileView.directoryIcon", makeIcon(getClass(), "icons/TreeClosed.gif"), "FileView.fileIcon", makeIcon(getClass(), "icons/File.gif"), "FileView.floppyDriveIcon", makeIcon(getClass(), "icons/FloppyDrive.gif"), "FileView.hardDriveIcon", makeIcon(getClass(), "icons/HardDrive.gif"), "FileChooser.homeFolderIcon", makeIcon(getClass(), "icons/HomeFolder.gif"), "FileChooser.newFolderIcon", makeIcon(getClass(), "icons/NewFolder.gif"), "FileChooser.upFolderIcon", makeIcon(getClass(), "icons/UpFolder.gif"), "Tree.closedIcon", makeIcon(getClass(), "icons/TreeClosed.gif"), "Tree.openIcon", makeIcon(getClass(), "icons/TreeOpen.gif"), "Tree.leafIcon", makeIcon(getClass(), "icons/TreeLeaf.gif"), "FormattedTextField.border", textFieldBorder, "FormattedTextField.margin", textInsets, "PasswordField.border", textFieldBorder, "PasswordField.margin", textInsets, "PasswordField.echoChar", passwordEchoChar, "PopupMenu.border", PlasticBorders.getPopupMenuBorder(), "PopupMenu.noMarginBorder", PlasticBorders.getNoMarginPopupMenuBorder(), "PopupMenuSeparator.margin", new InsetsUIResource(3, 4, 3, 4), "RadioButton.margin", checkBoxMargin, "RadioButtonMenuItem.border", menuItemBorder, "RadioButtonMenuItem.checkIcon", radioButtonMenuItemIcon, "RadioButtonMenuItem.margin", menuItemMargin, // 1.4.1 Bug "RadioButtonMenuItem.background", getMenuItemBackground(), // Added by JGoodies "RadioButtonMenuItem.selectionForeground", getMenuItemSelectedForeground(), "RadioButtonMenuItem.selectionBackground", getMenuItemSelectedBackground(), "RadioButtonMenuItem.acceleratorForeground", menuItemForeground, "RadioButtonMenuItem.acceleratorSelectionForeground", getMenuItemSelectedForeground(), "RadioButtonMenuItem.acceleratorSelectionBackground", getMenuItemSelectedBackground(), "Separator.foreground", getControlDarkShadow(), "ScrollPane.border", scrollPaneBorder, "ScrollPane.etchedBorder", scrollPaneBorder, // "ScrollPane.background", table.get("window"), "SimpleInternalFrame.activeTitleForeground", getSimpleInternalFrameForeground(), "SimpleInternalFrame.activeTitleBackground", getSimpleInternalFrameBackground(), "Spinner.border", PlasticBorders.getFlush3DBorder(), "Spinner.defaultEditorInsets", textInsets, "SplitPane.dividerSize", new Integer(7), "TabbedPane.focus", getFocusColor(), "TabbedPane.tabInsets", new InsetsUIResource(1, 9, 1, 8), "Table.foreground", table.get("textText"), "Table.gridColor", controlColor, //new ColorUIResource(new Color(216, 216, 216)), "Table.scrollPaneBorder", scrollPaneBorder, "TableHeader.cellBorder", tableHeaderBorder, "TextArea.inactiveBackground", inactiveTextBackground, "TextArea.margin", wrappedTextInsets, "TextField.border", textFieldBorder, "TextField.margin", textInsets, "TitledBorder.font", getTitleTextFont(), "TitledBorder.titleColor", getTitleTextColor(), "ToggleButton.border", toggleButtonBorder, "ToggleButton.margin", buttonMargin, "ToolBar.emptyBorder", toolBarEmptyBorder, // Added by JGoodies "ToolBar.separatorBorder", toolBarSeparatorBorder, // Added by JGoodies "ToolBar.etchedBorder", toolBarEtchedBorder, // Added by JGoodies "ToolBar.headerBorder", toolBarHeaderBorder, // Added by JGoodies "ToolTip.hideAccelerator", Boolean.TRUE, "Tree.expandedIcon", treeExpandedIcon, "Tree.collapsedIcon", treeCollapsedIcon, "Tree.line", gray, "Tree.hash", gray, "Tree.rowHeight", rowHeight, "Button.is3DEnabled", is3D, "ComboBox.is3DEnabled", is3D, "MenuBar.is3DEnabled", is3D, "ToolBar.is3DEnabled", is3D, "ScrollBar.is3DEnabled", is3D, "ToggleButton.is3DEnabled", is3D, // 1.4.1 uses a 2 pixel non-standard border, that leads to bad // alignment in the typical case that the border is not painted "CheckBox.border", marginBorder, "RadioButton.border", marginBorder, // Fix of the issue #21 "ProgressBar.selectionForeground", getSystemTextColor(), "ProgressBar.selectionBackground", getSystemTextColor() }; table.putDefaults(defaults); // Set paths to sounds for auditory feedback String soundPathPrefix = "/javax/swing/plaf/metal/"; Object[] auditoryCues = (Object[]) table.get("AuditoryCues.allAuditoryCues"); if (auditoryCues != null) { Object[] audioDefaults = new String[auditoryCues.length * 2]; for (int i = 0; i < auditoryCues.length; i++) { Object auditoryCue = auditoryCues[i]; audioDefaults[2 * i] = auditoryCue; audioDefaults[2 * i + 1] = soundPathPrefix + table.getString(auditoryCue); } table.putDefaults(audioDefaults); } } /** * Unlike my superclass I register a unified shadow color. * This color is used by my ThinBevelBorder class. * * @param table the UIDefaults table to work with */ @Override protected void initSystemColorDefaults(UIDefaults table) { super.initSystemColorDefaults(table); table.put("unifiedControlShadow", table.getColor("controlDkShadow")); table.put("primaryControlHighlight", getPrimaryControlHighlight()); } // Color Theme Behavior ************************************************************* private static final String THEME_CLASSNAME_PREFIX = "com.jgoodies.looks.plastic.theme."; /** * Creates and returns the default color theme. Honors the current platform * and platform flavor - if available. * * @return the default color theme for the current environment */ public static PlasticTheme createMyDefaultTheme() { String defaultName; if (SystemUtils.IS_LAF_WINDOWS_XP_ENABLED) { defaultName = getDefaultXPTheme(); } else if (LookUtils.IS_OS_WINDOWS_MODERN) { defaultName = "DesertBluer"; } else { defaultName = "SkyBlue"; } // Don't use the default now, so we can detect that the users tried to set one. String userName = LookUtils.getSystemProperty(DEFAULT_THEME_KEY, ""); boolean overridden = userName.length() > 0; String themeName = overridden ? userName : defaultName; PlasticTheme theme = createTheme(themeName); PlasticTheme result = theme != null ? theme : new SkyBluer(); // In case the user tried to set a theme, log a message. if (overridden) { String className = result.getClass().getName().substring(THEME_CLASSNAME_PREFIX.length()); if (className.equals(userName)) { LookUtils.log("I have successfully installed the '" + result.getName() + "' theme."); } else { LookUtils.log("I could not install the Plastic theme '" + userName + "'."); LookUtils.log("I have installed the '" + result.getName() + "' theme, instead."); } } return result; } private static String getDefaultXPTheme() { String fallbackName = "ExperienceBlue"; Toolkit toolkit = Toolkit.getDefaultToolkit(); String xpstyleDll = (String) toolkit.getDesktopProperty("win.xpstyle.dllName"); if (xpstyleDll == null) { return fallbackName; } boolean isStyleLuna = xpstyleDll.endsWith("luna.msstyles"); boolean isStyleRoyale = xpstyleDll.endsWith("Royale.msstyles"); boolean isStyleAero = xpstyleDll.endsWith("Aero.msstyles"); if (isStyleRoyale) { return "ExperienceRoyale"; } if (isStyleLuna) { String xpstyleColorName = (String) toolkit.getDesktopProperty("win.xpstyle.colorName"); if (xpstyleColorName == null) { return fallbackName; } if (xpstyleColorName.equalsIgnoreCase("HomeStead")) { return "ExperienceGreen"; } else if (xpstyleColorName.equalsIgnoreCase("Metallic")) { return "Silver"; } else { return fallbackName; } } if (isStyleAero) { return "LightGray"; } return fallbackName; } /** * Lazily initializes and returns the {@code List} of installed * color themes. * * @return a list of installed color/font themes */ public static List getInstalledThemes() { if (null == installedThemes) { installDefaultThemes(); } Collections.sort(installedThemes, new Comparator() { @Override public int compare(Object o1, Object o2) { MetalTheme theme1 = (MetalTheme) o1; MetalTheme theme2 = (MetalTheme) o2; return theme1.getName().compareTo(theme2.getName()); } }); return installedThemes; } /** * Install the default color themes. */ protected static void installDefaultThemes() { installedThemes = new ArrayList<PlasticTheme>(); String[] themeNames = { "BrownSugar", "DarkStar", "DesertBlue", "DesertBluer", "DesertGreen", "DesertRed", "DesertYellow", "ExperienceBlue", "ExperienceGreen", "ExperienceRoyale", "LightGray", "Silver", "SkyBlue", "SkyBluer", "SkyGreen", "SkyKrupp", "SkyPink", "SkyRed", "SkyYellow" }; for (int i = themeNames.length - 1; i >= 0; i--) { installTheme(createTheme(themeNames[i])); } } /** * Creates and returns a color theme from the specified theme name. * * @param themeName the unqualified name of the theme to create * @return the associated color theme or {@code null} in case of * a problem */ protected static PlasticTheme createTheme(String themeName) { String className = THEME_CLASSNAME_PREFIX + themeName; try { Class cl = Class.forName(className); return (PlasticTheme) cl.newInstance(); } catch (ClassNotFoundException e) { // Ignore the exception here and log below. } catch (IllegalAccessException e) { // Ignore the exception here and log below. } catch (InstantiationException e) { // Ignore the exception here and log below. } LookUtils.log("Can't create theme " + className); return null; } /** * Installs a color theme. * * @param theme the theme to install */ public static void installTheme(PlasticTheme theme) { if (null == installedThemes) { installDefaultThemes(); } installedThemes.add(theme); } /** * Lazily initializes and returns the PlasticTheme. * * @return the current PlasticTheme */ public static PlasticTheme getPlasticTheme() { MetalTheme theme = getCurrentTheme(); if (theme instanceof PlasticTheme) { return (PlasticTheme) theme; } PlasticTheme initialTheme = createMyDefaultTheme(); setPlasticTheme(initialTheme); return initialTheme; } /** * Sets the theme for colors and fonts used by the Plastic L&F.<p> * * After setting the theme, you need to re-install the Look&Feel, * as well as update the UI's of any previously created components * - just as if you'd change the Look&Feel. * * @param theme the PlasticTheme to be set * * @throws NullPointerException if the theme is null. * * @see #getPlasticTheme() */ public static void setPlasticTheme(PlasticTheme theme) { checkNotNull(theme, MUST_NOT_BE_NULL, "theme"); setCurrentTheme(theme); } // Accessed by ProxyLazyValues ****************************************** public static BorderUIResource getInternalFrameBorder() { return new BorderUIResource(PlasticBorders.getInternalFrameBorder()); } public static BorderUIResource getPaletteBorder() { return new BorderUIResource(PlasticBorders.getPaletteBorder()); } // Accessing Theme Colors and Fonts ************************************* public static ColorUIResource getPrimaryControlDarkShadow() { return getPlasticTheme().getPrimaryControlDarkShadow(); } public static ColorUIResource getPrimaryControlHighlight() { return getPlasticTheme().getPrimaryControlHighlight(); } public static ColorUIResource getPrimaryControlInfo() { return getPlasticTheme().getPrimaryControlInfo(); } public static ColorUIResource getPrimaryControlShadow() { return getPlasticTheme().getPrimaryControlShadow(); } public static ColorUIResource getPrimaryControl() { return getPlasticTheme().getPrimaryControl(); } public static ColorUIResource getControlHighlight() { return getPlasticTheme().getControlHighlight(); } public static ColorUIResource getControlDarkShadow() { return getPlasticTheme().getControlDarkShadow(); } public static ColorUIResource getControl() { return getPlasticTheme().getControl(); } public static ColorUIResource getFocusColor() { return getPlasticTheme().getFocusColor(); } public static ColorUIResource getMenuItemBackground() { return getPlasticTheme().getMenuItemBackground(); } public static ColorUIResource getMenuItemSelectedBackground() { return getPlasticTheme().getMenuItemSelectedBackground(); } public static ColorUIResource getMenuItemSelectedForeground() { return getPlasticTheme().getMenuItemSelectedForeground(); } public static ColorUIResource getWindowTitleBackground() { return getPlasticTheme().getWindowTitleBackground(); } public static ColorUIResource getWindowTitleForeground() { return getPlasticTheme().getWindowTitleForeground(); } public static ColorUIResource getWindowTitleInactiveBackground() { return getPlasticTheme().getWindowTitleInactiveBackground(); } public static ColorUIResource getWindowTitleInactiveForeground() { return getPlasticTheme().getWindowTitleInactiveForeground(); } public static ColorUIResource getSimpleInternalFrameForeground() { return getPlasticTheme().getSimpleInternalFrameForeground(); } public static ColorUIResource getSimpleInternalFrameBackground() { return getPlasticTheme().getSimpleInternalFrameBackground(); } public static ColorUIResource getTitleTextColor() { return getPlasticTheme().getTitleTextColor(); } public static FontUIResource getTitleTextFont() { return getPlasticTheme().getTitleTextFont(); } // Helper Code ************************************************************ /** * Appends the key and value to the given source array and returns * a copy that has the two new elements at its end. * * @return an array with the key and value appended */ private static Object[] append(Object[] source, String key, Object value) { int length = source.length; Object[] destination = new Object[length + 2]; System.arraycopy(source, 0, destination, 0, length); destination[length] = key; destination[length + 1] = value; return destination; } }