1 /*
   2  * Copyright (c) 1998, 2017, 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 java.awt.*;
  29 import java.beans.PropertyChangeEvent;
  30 import java.beans.PropertyChangeListener;
  31 import javax.swing.plaf.*;
  32 import javax.swing.*;
  33 import javax.swing.plaf.basic.*;
  34 import javax.swing.text.DefaultEditorKit;
  35 
  36 import java.awt.Color;
  37 import java.lang.ref.ReferenceQueue;
  38 import java.lang.ref.WeakReference;
  39 
  40 import java.security.AccessController;
  41 
  42 import sun.awt.*;
  43 import sun.security.action.GetPropertyAction;
  44 import sun.swing.DefaultLayoutStyle;
  45 import static javax.swing.UIDefaults.LazyValue;
  46 
  47 import sun.swing.SwingAccessor;
  48 import sun.swing.SwingUtilities2;
  49 
  50 /**
  51  * The Java Look and Feel, otherwise known as Metal.
  52  * <p>
  53  * Each of the {@code ComponentUI}s provided by {@code
  54  * MetalLookAndFeel} derives its behavior from the defaults
  55  * table. Unless otherwise noted each of the {@code ComponentUI}
  56  * implementations in this package document the set of defaults they
  57  * use. Unless otherwise noted the defaults are installed at the time
  58  * {@code installUI} is invoked, and follow the recommendations
  59  * outlined in {@code LookAndFeel} for installing defaults.
  60  * <p>
  61  * {@code MetalLookAndFeel} derives it's color palette and fonts from
  62  * {@code MetalTheme}. The default theme is {@code OceanTheme}. The theme
  63  * can be changed using the {@code setCurrentTheme} method, refer to it
  64  * for details on changing the theme. Prior to 1.5 the default
  65  * theme was {@code DefaultMetalTheme}. The system property
  66  * {@code "swing.metalTheme"} can be set to {@code "steel"} to indicate
  67  * the default should be {@code DefaultMetalTheme}.
  68  * <p>
  69  * <strong>Warning:</strong>
  70  * Serialized objects of this class will not be compatible with
  71  * future Swing releases. The current serialization support is
  72  * appropriate for short term storage or RMI between applications running
  73  * the same version of Swing.  As of 1.4, support for long term storage
  74  * of all JavaBeans&trade;
  75  * has been added to the <code>java.beans</code> package.
  76  * Please see {@link java.beans.XMLEncoder}.
  77  *
  78  * @see MetalTheme
  79  * @see DefaultMetalTheme
  80  * @see OceanTheme
  81  *
  82  * @author Steve Wilson
  83  */
  84 @SuppressWarnings("serial") // Same-version serialization only
  85 public class MetalLookAndFeel extends BasicLookAndFeel
  86 {
  87 
  88     private static boolean METAL_LOOK_AND_FEEL_INITED = false;
  89 
  90 
  91     /**
  92      * True if checked for windows yet.
  93      */
  94     private static boolean checkedWindows;
  95     /**
  96      * True if running on Windows.
  97      */
  98     private static boolean isWindows;
  99 
 100     /**
 101      * Set to true first time we've checked swing.useSystemFontSettings.
 102      */
 103     private static boolean checkedSystemFontSettings;
 104 
 105     /**
 106      * True indicates we should use system fonts, unless the developer has
 107      * specified otherwise with Application.useSystemFontSettings.
 108      */
 109     private static boolean useSystemFonts;
 110 
 111 
 112     /**
 113      * Returns true if running on Windows.
 114      */
 115     static boolean isWindows() {
 116         if (!checkedWindows) {
 117             OSInfo.OSType osType = AccessController.doPrivileged(OSInfo.getOSTypeAction());
 118             if (osType == OSInfo.OSType.WINDOWS) {
 119                 isWindows = true;
 120                 String systemFonts = AccessController.doPrivileged(
 121                     new GetPropertyAction("swing.useSystemFontSettings"));
 122                 useSystemFonts = (systemFonts != null &&
 123                                (Boolean.valueOf(systemFonts).booleanValue()));
 124             }
 125             checkedWindows = true;
 126         }
 127         return isWindows;
 128     }
 129 
 130     /**
 131      * Returns true if system fonts should be used, this is only useful
 132      * for windows.
 133      */
 134     static boolean useSystemFonts() {
 135         if (isWindows() && useSystemFonts) {
 136             if (METAL_LOOK_AND_FEEL_INITED) {
 137                 Object value = UIManager.get(
 138                                  "Application.useSystemFontSettings");
 139 
 140                 return (value == null || Boolean.TRUE.equals(value));
 141             }
 142             // If an instanceof MetalLookAndFeel hasn't been inited yet, we
 143             // don't want to trigger loading of a UI by asking the UIManager
 144             // for a property, assume the user wants system fonts. This will
 145             // be properly adjusted when install is invoked on the
 146             // MetalTheme
 147             return true;
 148         }
 149         return false;
 150     }
 151 
 152     /**
 153      * Returns true if the high contrast theme should be used as the default
 154      * theme.
 155      */
 156     private static boolean useHighContrastTheme() {
 157         if (isWindows() && useSystemFonts()) {
 158             Boolean highContrast = (Boolean)Toolkit.getDefaultToolkit().
 159                                   getDesktopProperty("win.highContrast.on");
 160 
 161             return (highContrast == null) ? false : highContrast.
 162                                             booleanValue();
 163         }
 164         return false;
 165     }
 166 
 167     /**
 168      * Returns true if we're using the Ocean Theme.
 169      */
 170     static boolean usingOcean() {
 171         return (getCurrentTheme() instanceof OceanTheme);
 172     }
 173 
 174     /**
 175      * Returns the name of this look and feel. This returns
 176      * {@code "Metal"}.
 177      *
 178      * @return the name of this look and feel
 179      */
 180     public String getName() {
 181         return "Metal";
 182     }
 183 
 184     /**
 185      * Returns an identifier for this look and feel. This returns
 186      * {@code "Metal"}.
 187      *
 188      * @return the identifier of this look and feel
 189      */
 190     public String getID() {
 191         return "Metal";
 192     }
 193 
 194     /**
 195      * Returns a short description of this look and feel. This returns
 196      * {@code "The Java(tm) Look and Feel"}.
 197 
 198      * @return a short description for the look and feel
 199      */
 200     public String getDescription() {
 201         return "The Java(tm) Look and Feel";
 202     }
 203 
 204     /**
 205      * Returns {@code false}; {@code MetalLookAndFeel} is not a native
 206      * look and feel.
 207      *
 208      * @return {@code false}
 209      */
 210     public boolean isNativeLookAndFeel() {
 211         return false;
 212     }
 213 
 214     /**
 215      * Returns {@code true}; {@code MetalLookAndFeel} can be run on
 216      * any platform.
 217      *
 218      * @return {@code true}
 219      */
 220     public boolean isSupportedLookAndFeel() {
 221         return true;
 222     }
 223 
 224     /**
 225      * Returns {@code true}; metal can provide {@code Window}
 226      * decorations.
 227      *
 228      * @return {@code true}
 229      *
 230      * @see JDialog#setDefaultLookAndFeelDecorated
 231      * @see JFrame#setDefaultLookAndFeelDecorated
 232      * @see JRootPane#setWindowDecorationStyle
 233      * @since 1.4
 234      */
 235     public boolean getSupportsWindowDecorations() {
 236         return true;
 237     }
 238 
 239     /**
 240      * Populates {@code table} with mappings from {@code uiClassID} to
 241      * the fully qualified name of the ui class. {@code
 242      * MetalLookAndFeel} registers an entry for each of the classes in
 243      * the package {@code javax.swing.plaf.metal} that are named
 244      * MetalXXXUI. The string {@code XXX} is one of Swing's uiClassIDs. For
 245      * the {@code uiClassIDs} that do not have a class in metal, the
 246      * corresponding class in {@code javax.swing.plaf.basic} is
 247      * used. For example, metal does not have a class named {@code
 248      * "MetalColorChooserUI"}, as such, {@code
 249      * javax.swing.plaf.basic.BasicColorChooserUI} is used.
 250      *
 251      * @param table the {@code UIDefaults} instance the entries are
 252      *        added to
 253      * @throws NullPointerException if {@code table} is {@code null}
 254      *
 255      * @see javax.swing.plaf.basic.BasicLookAndFeel#initClassDefaults
 256      */
 257     protected void initClassDefaults(UIDefaults table)
 258     {
 259         super.initClassDefaults(table);
 260         final String metalPackageName = "javax.swing.plaf.metal.";
 261 
 262         Object[] uiDefaults = {
 263                    "ButtonUI", metalPackageName + "MetalButtonUI",
 264                  "CheckBoxUI", metalPackageName + "MetalCheckBoxUI",
 265                  "ComboBoxUI", metalPackageName + "MetalComboBoxUI",
 266               "DesktopIconUI", metalPackageName + "MetalDesktopIconUI",
 267               "FileChooserUI", metalPackageName + "MetalFileChooserUI",
 268             "InternalFrameUI", metalPackageName + "MetalInternalFrameUI",
 269                     "LabelUI", metalPackageName + "MetalLabelUI",
 270        "PopupMenuSeparatorUI", metalPackageName + "MetalPopupMenuSeparatorUI",
 271               "ProgressBarUI", metalPackageName + "MetalProgressBarUI",
 272               "RadioButtonUI", metalPackageName + "MetalRadioButtonUI",
 273                 "ScrollBarUI", metalPackageName + "MetalScrollBarUI",
 274                "ScrollPaneUI", metalPackageName + "MetalScrollPaneUI",
 275                 "SeparatorUI", metalPackageName + "MetalSeparatorUI",
 276                    "SliderUI", metalPackageName + "MetalSliderUI",
 277                 "SplitPaneUI", metalPackageName + "MetalSplitPaneUI",
 278                "TabbedPaneUI", metalPackageName + "MetalTabbedPaneUI",
 279                 "TextFieldUI", metalPackageName + "MetalTextFieldUI",
 280              "ToggleButtonUI", metalPackageName + "MetalToggleButtonUI",
 281                   "ToolBarUI", metalPackageName + "MetalToolBarUI",
 282                   "ToolTipUI", metalPackageName + "MetalToolTipUI",
 283                      "TreeUI", metalPackageName + "MetalTreeUI",
 284                  "RootPaneUI", metalPackageName + "MetalRootPaneUI",
 285         };
 286 
 287         table.putDefaults(uiDefaults);
 288     }
 289 
 290     /**
 291      * Populates {@code table} with system colors. The following values are
 292      * added to {@code table}:
 293      * <table border="1" cellpadding="1" cellspacing="0"
 294      *         summary="Metal's system color mapping">
 295      *  <tr valign="top" style="text-align:left">
 296      *    <th style="background-color:#CCCCFF;text-align:left">Key
 297      *    <th style="background-color:#CCCCFF;text-align:left">Value
 298      *  <tr valign="top" style="text-align:left">
 299      *    <td>"desktop"
 300      *    <td>{@code theme.getDesktopColor()}
 301      *  <tr valign="top" style="text-align:left">
 302      *    <td>"activeCaption"
 303      *    <td>{@code theme.getWindowTitleBackground()}
 304      *  <tr valign="top" style="text-align:left">
 305      *    <td>"activeCaptionText"
 306      *    <td>{@code theme.getWindowTitleForeground()}
 307      *  <tr valign="top" style="text-align:left">
 308      *    <td>"activeCaptionBorder"
 309      *    <td>{@code theme.getPrimaryControlShadow()}
 310      *  <tr valign="top" style="text-align:left">
 311      *    <td>"inactiveCaption"
 312      *    <td>{@code theme.getWindowTitleInactiveBackground()}
 313      *  <tr valign="top" style="text-align:left">
 314      *    <td>"inactiveCaptionText"
 315      *    <td>{@code theme.getWindowTitleInactiveForeground()}
 316      *  <tr valign="top" style="text-align:left">
 317      *    <td>"inactiveCaptionBorder"
 318      *    <td>{@code theme.getControlShadow()}
 319      *  <tr valign="top" style="text-align:left">
 320      *    <td>"window"
 321      *    <td>{@code theme.getWindowBackground()}
 322      *  <tr valign="top" style="text-align:left">
 323      *    <td>"windowBorder"
 324      *    <td>{@code theme.getControl()}
 325      *  <tr valign="top" style="text-align:left">
 326      *    <td>"windowText"
 327      *    <td>{@code theme.getUserTextColor()}
 328      *  <tr valign="top" style="text-align:left">
 329      *    <td>"menu"
 330      *    <td>{@code theme.getMenuBackground()}
 331      *  <tr valign="top" style="text-align:left">
 332      *    <td>"menuText"
 333      *    <td>{@code theme.getMenuForeground()}
 334      *  <tr valign="top" style="text-align:left">
 335      *    <td>"text"
 336      *    <td>{@code theme.getWindowBackground()}
 337      *  <tr valign="top" style="text-align:left">
 338      *    <td>"textText"
 339      *    <td>{@code theme.getUserTextColor()}
 340      *  <tr valign="top" style="text-align:left">
 341      *    <td>"textHighlight"
 342      *    <td>{@code theme.getTextHighlightColor()}
 343      *  <tr valign="top" style="text-align:left">
 344      *    <td>"textHighlightText"
 345      *    <td>{@code theme.getHighlightedTextColor()}
 346      *  <tr valign="top" style="text-align:left">
 347      *    <td>"textInactiveText"
 348      *    <td>{@code theme.getInactiveSystemTextColor()}
 349      *  <tr valign="top" style="text-align:left">
 350      *    <td>"control"
 351      *    <td>{@code theme.getControl()}
 352      *  <tr valign="top" style="text-align:left">
 353      *    <td>"controlText"
 354      *    <td>{@code theme.getControlTextColor()}
 355      *  <tr valign="top" style="text-align:left">
 356      *    <td>"controlHighlight"
 357      *    <td>{@code theme.getControlHighlight()}
 358      *  <tr valign="top" style="text-align:left">
 359      *    <td>"controlLtHighlight"
 360      *    <td>{@code theme.getControlHighlight()}
 361      *  <tr valign="top" style="text-align:left">
 362      *    <td>"controlShadow"
 363      *    <td>{@code theme.getControlShadow()}
 364      *  <tr valign="top" style="text-align:left">
 365      *    <td>"controlDkShadow"
 366      *    <td>{@code theme.getControlDarkShadow()}
 367      *  <tr valign="top" style="text-align:left">
 368      *    <td>"scrollbar"
 369      *    <td>{@code theme.getControl()}
 370      *  <tr valign="top" style="text-align:left">
 371      *    <td>"info"
 372      *    <td>{@code theme.getPrimaryControl()}
 373      *  <tr valign="top" style="text-align:left">
 374      *    <td>"infoText"
 375      *    <td>{@code theme.getPrimaryControlInfo()}
 376      * </table>
 377      * The value {@code theme} corresponds to the current {@code MetalTheme}.
 378      *
 379      * @param table the {@code UIDefaults} object the values are added to
 380      * @throws NullPointerException if {@code table} is {@code null}
 381      */
 382     protected void initSystemColorDefaults(UIDefaults table)
 383     {
 384         MetalTheme theme = getCurrentTheme();
 385         Color control = theme.getControl();
 386         Object[] systemColors = {
 387                 "desktop", theme.getDesktopColor(), /* Color of the desktop background */
 388           "activeCaption", theme.getWindowTitleBackground(), /* Color for captions (title bars) when they are active. */
 389       "activeCaptionText", theme.getWindowTitleForeground(), /* Text color for text in captions (title bars). */
 390     "activeCaptionBorder", theme.getPrimaryControlShadow(), /* Border color for caption (title bar) window borders. */
 391         "inactiveCaption", theme.getWindowTitleInactiveBackground(), /* Color for captions (title bars) when not active. */
 392     "inactiveCaptionText", theme.getWindowTitleInactiveForeground(), /* Text color for text in inactive captions (title bars). */
 393   "inactiveCaptionBorder", theme.getControlShadow(), /* Border color for inactive caption (title bar) window borders. */
 394                  "window", theme.getWindowBackground(), /* Default color for the interior of windows */
 395            "windowBorder", control, /* ??? */
 396              "windowText", theme.getUserTextColor(), /* ??? */
 397                    "menu", theme.getMenuBackground(), /* Background color for menus */
 398                "menuText", theme.getMenuForeground(), /* Text color for menus  */
 399                    "text", theme.getWindowBackground(), /* Text background color */
 400                "textText", theme.getUserTextColor(), /* Text foreground color */
 401           "textHighlight", theme.getTextHighlightColor(), /* Text background color when selected */
 402       "textHighlightText", theme.getHighlightedTextColor(), /* Text color when selected */
 403        "textInactiveText", theme.getInactiveSystemTextColor(), /* Text color when disabled */
 404                 "control", control, /* Default color for controls (buttons, sliders, etc) */
 405             "controlText", theme.getControlTextColor(), /* Default color for text in controls */
 406        "controlHighlight", theme.getControlHighlight(), /* Specular highlight (opposite of the shadow) */
 407      "controlLtHighlight", theme.getControlHighlight(), /* Highlight color for controls */
 408           "controlShadow", theme.getControlShadow(), /* Shadow color for controls */
 409         "controlDkShadow", theme.getControlDarkShadow(), /* Dark shadow color for controls */
 410               "scrollbar", control, /* Scrollbar background (usually the "track") */
 411                    "info", theme.getPrimaryControl(), /* ToolTip Background */
 412                "infoText", theme.getPrimaryControlInfo()  /* ToolTip Text */
 413         };
 414 
 415         table.putDefaults(systemColors);
 416     }
 417 
 418     /**
 419      * Initialize the defaults table with the name of the ResourceBundle
 420      * used for getting localized defaults.
 421      */
 422     private void initResourceBundle(UIDefaults table) {
 423         SwingAccessor.getUIDefaultsAccessor()
 424                      .addInternalBundle(table,
 425                              "com.sun.swing.internal.plaf.metal.resources.metal");
 426     }
 427 
 428     /**
 429      * Populates {@code table} with the defaults for metal.
 430      *
 431      * @param table the {@code UIDefaults} to add the values to
 432      * @throws NullPointerException if {@code table} is {@code null}
 433      */
 434     protected void initComponentDefaults(UIDefaults table) {
 435         super.initComponentDefaults( table );
 436 
 437         initResourceBundle(table);
 438 
 439         Color acceleratorForeground = getAcceleratorForeground();
 440         Color acceleratorSelectedForeground = getAcceleratorSelectedForeground();
 441         Color control = getControl();
 442         Color controlHighlight = getControlHighlight();
 443         Color controlShadow = getControlShadow();
 444         Color controlDarkShadow = getControlDarkShadow();
 445         Color controlTextColor = getControlTextColor();
 446         Color focusColor = getFocusColor();
 447         Color inactiveControlTextColor = getInactiveControlTextColor();
 448         Color menuBackground = getMenuBackground();
 449         Color menuSelectedBackground = getMenuSelectedBackground();
 450         Color menuDisabledForeground = getMenuDisabledForeground();
 451         Color menuSelectedForeground = getMenuSelectedForeground();
 452         Color primaryControl = getPrimaryControl();
 453         Color primaryControlDarkShadow = getPrimaryControlDarkShadow();
 454         Color primaryControlShadow = getPrimaryControlShadow();
 455         Color systemTextColor = getSystemTextColor();
 456 
 457         Insets zeroInsets = new InsetsUIResource(0, 0, 0, 0);
 458 
 459         Integer zero = Integer.valueOf(0);
 460 
 461         LazyValue textFieldBorder =
 462             t -> MetalBorders.getTextFieldBorder();
 463 
 464         LazyValue dialogBorder = t -> new MetalBorders.DialogBorder();
 465 
 466         LazyValue questionDialogBorder = t -> new MetalBorders.QuestionDialogBorder();
 467 
 468         Object fieldInputMap = new UIDefaults.LazyInputMap(new Object[] {
 469                            "ctrl C", DefaultEditorKit.copyAction,
 470                            "ctrl V", DefaultEditorKit.pasteAction,
 471                            "ctrl X", DefaultEditorKit.cutAction,
 472                              "COPY", DefaultEditorKit.copyAction,
 473                             "PASTE", DefaultEditorKit.pasteAction,
 474                               "CUT", DefaultEditorKit.cutAction,
 475                    "control INSERT", DefaultEditorKit.copyAction,
 476                      "shift INSERT", DefaultEditorKit.pasteAction,
 477                      "shift DELETE", DefaultEditorKit.cutAction,
 478                        "shift LEFT", DefaultEditorKit.selectionBackwardAction,
 479                     "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
 480                       "shift RIGHT", DefaultEditorKit.selectionForwardAction,
 481                    "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
 482                         "ctrl LEFT", DefaultEditorKit.previousWordAction,
 483                      "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
 484                        "ctrl RIGHT", DefaultEditorKit.nextWordAction,
 485                     "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
 486                   "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
 487                "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
 488                  "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
 489               "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
 490                            "ctrl A", DefaultEditorKit.selectAllAction,
 491                              "HOME", DefaultEditorKit.beginLineAction,
 492                               "END", DefaultEditorKit.endLineAction,
 493                        "shift HOME", DefaultEditorKit.selectionBeginLineAction,
 494                         "shift END", DefaultEditorKit.selectionEndLineAction,
 495                        "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
 496                  "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
 497                            "ctrl H", DefaultEditorKit.deletePrevCharAction,
 498                            "DELETE", DefaultEditorKit.deleteNextCharAction,
 499                       "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
 500                   "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
 501                             "RIGHT", DefaultEditorKit.forwardAction,
 502                              "LEFT", DefaultEditorKit.backwardAction,
 503                          "KP_RIGHT", DefaultEditorKit.forwardAction,
 504                           "KP_LEFT", DefaultEditorKit.backwardAction,
 505                             "ENTER", JTextField.notifyAction,
 506                   "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/,
 507                    "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/
 508         });
 509 
 510         Object passwordInputMap = new UIDefaults.LazyInputMap(new Object[] {
 511                            "ctrl C", DefaultEditorKit.copyAction,
 512                            "ctrl V", DefaultEditorKit.pasteAction,
 513                            "ctrl X", DefaultEditorKit.cutAction,
 514                              "COPY", DefaultEditorKit.copyAction,
 515                             "PASTE", DefaultEditorKit.pasteAction,
 516                               "CUT", DefaultEditorKit.cutAction,
 517                    "control INSERT", DefaultEditorKit.copyAction,
 518                      "shift INSERT", DefaultEditorKit.pasteAction,
 519                      "shift DELETE", DefaultEditorKit.cutAction,
 520                        "shift LEFT", DefaultEditorKit.selectionBackwardAction,
 521                     "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
 522                       "shift RIGHT", DefaultEditorKit.selectionForwardAction,
 523                    "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
 524                         "ctrl LEFT", DefaultEditorKit.beginLineAction,
 525                      "ctrl KP_LEFT", DefaultEditorKit.beginLineAction,
 526                        "ctrl RIGHT", DefaultEditorKit.endLineAction,
 527                     "ctrl KP_RIGHT", DefaultEditorKit.endLineAction,
 528                   "ctrl shift LEFT", DefaultEditorKit.selectionBeginLineAction,
 529                "ctrl shift KP_LEFT", DefaultEditorKit.selectionBeginLineAction,
 530                  "ctrl shift RIGHT", DefaultEditorKit.selectionEndLineAction,
 531               "ctrl shift KP_RIGHT", DefaultEditorKit.selectionEndLineAction,
 532                            "ctrl A", DefaultEditorKit.selectAllAction,
 533                              "HOME", DefaultEditorKit.beginLineAction,
 534                               "END", DefaultEditorKit.endLineAction,
 535                        "shift HOME", DefaultEditorKit.selectionBeginLineAction,
 536                         "shift END", DefaultEditorKit.selectionEndLineAction,
 537                        "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
 538                  "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
 539                            "ctrl H", DefaultEditorKit.deletePrevCharAction,
 540                            "DELETE", DefaultEditorKit.deleteNextCharAction,
 541                             "RIGHT", DefaultEditorKit.forwardAction,
 542                              "LEFT", DefaultEditorKit.backwardAction,
 543                          "KP_RIGHT", DefaultEditorKit.forwardAction,
 544                           "KP_LEFT", DefaultEditorKit.backwardAction,
 545                             "ENTER", JTextField.notifyAction,
 546                   "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/,
 547                    "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/
 548         });
 549 
 550         Object multilineInputMap = new UIDefaults.LazyInputMap(new Object[] {
 551                            "ctrl C", DefaultEditorKit.copyAction,
 552                            "ctrl V", DefaultEditorKit.pasteAction,
 553                            "ctrl X", DefaultEditorKit.cutAction,
 554                              "COPY", DefaultEditorKit.copyAction,
 555                             "PASTE", DefaultEditorKit.pasteAction,
 556                               "CUT", DefaultEditorKit.cutAction,
 557                    "control INSERT", DefaultEditorKit.copyAction,
 558                      "shift INSERT", DefaultEditorKit.pasteAction,
 559                      "shift DELETE", DefaultEditorKit.cutAction,
 560                        "shift LEFT", DefaultEditorKit.selectionBackwardAction,
 561                     "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
 562                       "shift RIGHT", DefaultEditorKit.selectionForwardAction,
 563                    "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
 564                         "ctrl LEFT", DefaultEditorKit.previousWordAction,
 565                      "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
 566                        "ctrl RIGHT", DefaultEditorKit.nextWordAction,
 567                     "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
 568                   "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
 569                "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
 570                  "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
 571               "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
 572                            "ctrl A", DefaultEditorKit.selectAllAction,
 573                              "HOME", DefaultEditorKit.beginLineAction,
 574                               "END", DefaultEditorKit.endLineAction,
 575                        "shift HOME", DefaultEditorKit.selectionBeginLineAction,
 576                         "shift END", DefaultEditorKit.selectionEndLineAction,
 577 
 578                                "UP", DefaultEditorKit.upAction,
 579                             "KP_UP", DefaultEditorKit.upAction,
 580                              "DOWN", DefaultEditorKit.downAction,
 581                           "KP_DOWN", DefaultEditorKit.downAction,
 582                           "PAGE_UP", DefaultEditorKit.pageUpAction,
 583                         "PAGE_DOWN", DefaultEditorKit.pageDownAction,
 584                     "shift PAGE_UP", "selection-page-up",
 585                   "shift PAGE_DOWN", "selection-page-down",
 586                "ctrl shift PAGE_UP", "selection-page-left",
 587              "ctrl shift PAGE_DOWN", "selection-page-right",
 588                          "shift UP", DefaultEditorKit.selectionUpAction,
 589                       "shift KP_UP", DefaultEditorKit.selectionUpAction,
 590                        "shift DOWN", DefaultEditorKit.selectionDownAction,
 591                     "shift KP_DOWN", DefaultEditorKit.selectionDownAction,
 592                             "ENTER", DefaultEditorKit.insertBreakAction,
 593                        "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
 594                  "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
 595                            "ctrl H", DefaultEditorKit.deletePrevCharAction,
 596                            "DELETE", DefaultEditorKit.deleteNextCharAction,
 597                       "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
 598                   "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
 599                             "RIGHT", DefaultEditorKit.forwardAction,
 600                              "LEFT", DefaultEditorKit.backwardAction,
 601                          "KP_RIGHT", DefaultEditorKit.forwardAction,
 602                           "KP_LEFT", DefaultEditorKit.backwardAction,
 603                               "TAB", DefaultEditorKit.insertTabAction,
 604                   "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/,
 605                         "ctrl HOME", DefaultEditorKit.beginAction,
 606                          "ctrl END", DefaultEditorKit.endAction,
 607                   "ctrl shift HOME", DefaultEditorKit.selectionBeginAction,
 608                    "ctrl shift END", DefaultEditorKit.selectionEndAction,
 609                            "ctrl T", "next-link-action",
 610                      "ctrl shift T", "previous-link-action",
 611                        "ctrl SPACE", "activate-link-action",
 612                    "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/
 613         });
 614 
 615         LazyValue scrollPaneBorder = t -> new MetalBorders.ScrollPaneBorder();
 616         LazyValue buttonBorder =
 617             t -> MetalBorders.getButtonBorder();
 618 
 619         LazyValue toggleButtonBorder =
 620             t -> MetalBorders.getToggleButtonBorder();
 621 
 622         LazyValue titledBorderBorder =
 623             t -> new BorderUIResource.LineBorderUIResource(controlShadow);
 624 
 625         LazyValue desktopIconBorder =
 626             t -> MetalBorders.getDesktopIconBorder();
 627 
 628         LazyValue menuBarBorder =
 629             t -> new MetalBorders.MenuBarBorder();
 630 
 631         LazyValue popupMenuBorder =
 632             t -> new MetalBorders.PopupMenuBorder();
 633         LazyValue menuItemBorder =
 634             t -> new MetalBorders.MenuItemBorder();
 635 
 636         Object menuItemAcceleratorDelimiter = "-";
 637         LazyValue toolBarBorder = t -> new MetalBorders.ToolBarBorder();
 638 
 639         LazyValue progressBarBorder = t ->
 640             new BorderUIResource.LineBorderUIResource(controlDarkShadow, 1);
 641 
 642         LazyValue toolTipBorder = t ->
 643             new BorderUIResource.LineBorderUIResource(primaryControlDarkShadow);
 644 
 645         LazyValue toolTipBorderInactive = t ->
 646             new BorderUIResource.LineBorderUIResource(controlDarkShadow);
 647 
 648         LazyValue focusCellHighlightBorder = t ->
 649             new BorderUIResource.LineBorderUIResource(focusColor);
 650 
 651         Object tabbedPaneTabAreaInsets = new InsetsUIResource(4, 2, 0, 6);
 652 
 653         Object tabbedPaneTabInsets = new InsetsUIResource(0, 9, 1, 9);
 654 
 655         int internalFrameIconSize = 16;
 656 
 657         Object[] defaultCueList = new Object[] {
 658                 "OptionPane.errorSound",
 659                 "OptionPane.informationSound",
 660                 "OptionPane.questionSound",
 661                 "OptionPane.warningSound" };
 662 
 663         MetalTheme theme = getCurrentTheme();
 664         Object menuTextValue = new FontActiveValue(theme,
 665                                                    MetalTheme.MENU_TEXT_FONT);
 666         Object controlTextValue = new FontActiveValue(theme,
 667                                MetalTheme.CONTROL_TEXT_FONT);
 668         Object userTextValue = new FontActiveValue(theme,
 669                                                    MetalTheme.USER_TEXT_FONT);
 670         Object windowTitleValue = new FontActiveValue(theme,
 671                                MetalTheme.WINDOW_TITLE_FONT);
 672         Object subTextValue = new FontActiveValue(theme,
 673                                                   MetalTheme.SUB_TEXT_FONT);
 674         Object systemTextValue = new FontActiveValue(theme,
 675                                                  MetalTheme.SYSTEM_TEXT_FONT);
 676         //
 677         // DEFAULTS TABLE
 678         //
 679 
 680         Object[] defaults = {
 681             // *** Auditory Feedback
 682             "AuditoryCues.defaultCueList", defaultCueList,
 683             // this key defines which of the various cues to render
 684             // This is disabled until sound bugs can be resolved.
 685             "AuditoryCues.playList", null, // defaultCueList,
 686 
 687             // Text (Note: many are inherited)
 688             "TextField.border", textFieldBorder,
 689             "TextField.font", userTextValue,
 690 
 691             "PasswordField.border", textFieldBorder,
 692             // passwordField.font should actually map to
 693             // win.ansiFixed.font.height on windows.
 694             "PasswordField.font", userTextValue,
 695             "PasswordField.echoChar", (char)0x2022,
 696 
 697             // TextArea.font should actually map to win.ansiFixed.font.height
 698             // on windows.
 699             "TextArea.font", userTextValue,
 700 
 701             "TextPane.background", table.get("window"),
 702             "TextPane.font", userTextValue,
 703 
 704             "EditorPane.background", table.get("window"),
 705             "EditorPane.font", userTextValue,
 706 
 707             "TextField.focusInputMap", fieldInputMap,
 708             "PasswordField.focusInputMap", passwordInputMap,
 709             "TextArea.focusInputMap", multilineInputMap,
 710             "TextPane.focusInputMap", multilineInputMap,
 711             "EditorPane.focusInputMap", multilineInputMap,
 712 
 713             // FormattedTextFields
 714             "FormattedTextField.border", textFieldBorder,
 715             "FormattedTextField.font", userTextValue,
 716             "FormattedTextField.focusInputMap",
 717               new UIDefaults.LazyInputMap(new Object[] {
 718                            "ctrl C", DefaultEditorKit.copyAction,
 719                            "ctrl V", DefaultEditorKit.pasteAction,
 720                            "ctrl X", DefaultEditorKit.cutAction,
 721                              "COPY", DefaultEditorKit.copyAction,
 722                             "PASTE", DefaultEditorKit.pasteAction,
 723                               "CUT", DefaultEditorKit.cutAction,
 724                    "control INSERT", DefaultEditorKit.copyAction,
 725                      "shift INSERT", DefaultEditorKit.pasteAction,
 726                      "shift DELETE", DefaultEditorKit.cutAction,
 727                        "shift LEFT", DefaultEditorKit.selectionBackwardAction,
 728                     "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
 729                       "shift RIGHT", DefaultEditorKit.selectionForwardAction,
 730                    "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
 731                         "ctrl LEFT", DefaultEditorKit.previousWordAction,
 732                      "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
 733                        "ctrl RIGHT", DefaultEditorKit.nextWordAction,
 734                     "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
 735                   "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
 736                "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
 737                  "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
 738               "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
 739                            "ctrl A", DefaultEditorKit.selectAllAction,
 740                              "HOME", DefaultEditorKit.beginLineAction,
 741                               "END", DefaultEditorKit.endLineAction,
 742                        "shift HOME", DefaultEditorKit.selectionBeginLineAction,
 743                         "shift END", DefaultEditorKit.selectionEndLineAction,
 744                        "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
 745                  "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
 746                            "ctrl H", DefaultEditorKit.deletePrevCharAction,
 747                            "DELETE", DefaultEditorKit.deleteNextCharAction,
 748                       "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
 749                   "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
 750                             "RIGHT", DefaultEditorKit.forwardAction,
 751                              "LEFT", DefaultEditorKit.backwardAction,
 752                          "KP_RIGHT", DefaultEditorKit.forwardAction,
 753                           "KP_LEFT", DefaultEditorKit.backwardAction,
 754                             "ENTER", JTextField.notifyAction,
 755                   "ctrl BACK_SLASH", "unselect",
 756                    "control shift O", "toggle-componentOrientation",
 757                            "ESCAPE", "reset-field-edit",
 758                                "UP", "increment",
 759                             "KP_UP", "increment",
 760                              "DOWN", "decrement",
 761                           "KP_DOWN", "decrement",
 762               }),
 763 
 764 
 765             // Buttons
 766             "Button.defaultButtonFollowsFocus", Boolean.FALSE,
 767             "Button.disabledText", inactiveControlTextColor,
 768             "Button.select", controlShadow,
 769             "Button.border", buttonBorder,
 770             "Button.font", controlTextValue,
 771             "Button.focus", focusColor,
 772             "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] {
 773                           "SPACE", "pressed",
 774                  "released SPACE", "released"
 775               }),
 776 
 777             "CheckBox.disabledText", inactiveControlTextColor,
 778             "Checkbox.select", controlShadow,
 779             "CheckBox.font", controlTextValue,
 780             "CheckBox.focus", focusColor,
 781             "CheckBox.icon",(LazyValue) t -> MetalIconFactory.getCheckBoxIcon(),
 782             "CheckBox.focusInputMap",
 783                new UIDefaults.LazyInputMap(new Object[] {
 784                             "SPACE", "pressed",
 785                    "released SPACE", "released"
 786                  }),
 787             // margin is 2 all the way around, BasicBorders.RadioButtonBorder
 788             // (checkbox uses RadioButtonBorder) is 2 all the way around too.
 789             "CheckBox.totalInsets", new Insets(4, 4, 4, 4),
 790 
 791             "RadioButton.disabledText", inactiveControlTextColor,
 792             "RadioButton.select", controlShadow,
 793             "RadioButton.icon",(LazyValue) t -> MetalIconFactory.getRadioButtonIcon(),
 794             "RadioButton.font", controlTextValue,
 795             "RadioButton.focus", focusColor,
 796             "RadioButton.focusInputMap",
 797                new UIDefaults.LazyInputMap(new Object[] {
 798                           "SPACE", "pressed",
 799                  "released SPACE", "released"
 800               }),
 801             // margin is 2 all the way around, BasicBorders.RadioButtonBorder
 802             // is 2 all the way around too.
 803             "RadioButton.totalInsets", new Insets(4, 4, 4, 4),
 804 
 805             "ToggleButton.select", controlShadow,
 806             "ToggleButton.disabledText", inactiveControlTextColor,
 807             "ToggleButton.focus", focusColor,
 808             "ToggleButton.border", toggleButtonBorder,
 809             "ToggleButton.font", controlTextValue,
 810             "ToggleButton.focusInputMap",
 811               new UIDefaults.LazyInputMap(new Object[] {
 812                             "SPACE", "pressed",
 813                    "released SPACE", "released"
 814                 }),
 815 
 816 
 817             // File View
 818             "FileView.directoryIcon",(LazyValue) t -> MetalIconFactory.getTreeFolderIcon(),
 819             "FileView.fileIcon",(LazyValue) t -> MetalIconFactory.getTreeLeafIcon(),
 820             "FileView.computerIcon",(LazyValue) t -> MetalIconFactory.getTreeComputerIcon(),
 821             "FileView.hardDriveIcon",(LazyValue) t -> MetalIconFactory.getTreeHardDriveIcon(),
 822             "FileView.floppyDriveIcon",(LazyValue) t -> MetalIconFactory.getTreeFloppyDriveIcon(),
 823 
 824             // File Chooser
 825             "FileChooser.detailsViewIcon",(LazyValue) t -> MetalIconFactory.getFileChooserDetailViewIcon(),
 826             "FileChooser.homeFolderIcon",(LazyValue) t -> MetalIconFactory.getFileChooserHomeFolderIcon(),
 827             "FileChooser.listViewIcon",(LazyValue) t -> MetalIconFactory.getFileChooserListViewIcon(),
 828             "FileChooser.newFolderIcon",(LazyValue) t -> MetalIconFactory.getFileChooserNewFolderIcon(),
 829             "FileChooser.upFolderIcon",(LazyValue) t -> MetalIconFactory.getFileChooserUpFolderIcon(),
 830 
 831             "FileChooser.usesSingleFilePane", Boolean.TRUE,
 832             "FileChooser.ancestorInputMap",
 833                new UIDefaults.LazyInputMap(new Object[] {
 834                      "ESCAPE", "cancelSelection",
 835                      "F2", "editFileName",
 836                      "F5", "refresh",
 837                      "BACK_SPACE", "Go Up"
 838                  }),
 839 
 840 
 841             // ToolTip
 842             "ToolTip.font", systemTextValue,
 843             "ToolTip.border", toolTipBorder,
 844             "ToolTip.borderInactive", toolTipBorderInactive,
 845             "ToolTip.backgroundInactive", control,
 846             "ToolTip.foregroundInactive", controlDarkShadow,
 847             "ToolTip.hideAccelerator", Boolean.FALSE,
 848 
 849             // ToolTipManager
 850             "ToolTipManager.enableToolTipMode", "activeApplication",
 851 
 852             // Slider Defaults
 853             "Slider.font", controlTextValue,
 854             "Slider.border", null,
 855             "Slider.foreground", primaryControlShadow,
 856             "Slider.focus", focusColor,
 857             "Slider.focusInsets", zeroInsets,
 858             "Slider.trackWidth",  7 ,
 859             "Slider.majorTickLength",  6 ,
 860             "Slider.horizontalThumbIcon",(LazyValue) t -> MetalIconFactory.getHorizontalSliderThumbIcon(),
 861             "Slider.verticalThumbIcon",(LazyValue) t -> MetalIconFactory.getVerticalSliderThumbIcon(),
 862             "Slider.focusInputMap",
 863                new UIDefaults.LazyInputMap(new Object[] {
 864                        "RIGHT", "positiveUnitIncrement",
 865                     "KP_RIGHT", "positiveUnitIncrement",
 866                         "DOWN", "negativeUnitIncrement",
 867                      "KP_DOWN", "negativeUnitIncrement",
 868                    "PAGE_DOWN", "negativeBlockIncrement",
 869               "ctrl PAGE_DOWN", "negativeBlockIncrement",
 870                         "LEFT", "negativeUnitIncrement",
 871                      "KP_LEFT", "negativeUnitIncrement",
 872                           "UP", "positiveUnitIncrement",
 873                        "KP_UP", "positiveUnitIncrement",
 874                      "PAGE_UP", "positiveBlockIncrement",
 875                 "ctrl PAGE_UP", "positiveBlockIncrement",
 876                         "HOME", "minScroll",
 877                          "END", "maxScroll"
 878                  }),
 879 
 880             // Progress Bar
 881             "ProgressBar.font", controlTextValue,
 882             "ProgressBar.foreground", primaryControlShadow,
 883             "ProgressBar.selectionBackground", primaryControlDarkShadow,
 884             "ProgressBar.border", progressBarBorder,
 885             "ProgressBar.cellSpacing", zero,
 886             "ProgressBar.cellLength", Integer.valueOf(1),
 887 
 888             // Combo Box
 889             "ComboBox.background", control,
 890             "ComboBox.foreground", controlTextColor,
 891             "ComboBox.selectionBackground", primaryControlShadow,
 892             "ComboBox.selectionForeground", controlTextColor,
 893             "ComboBox.font", controlTextValue,
 894             "ComboBox.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] {
 895                      "ESCAPE", "hidePopup",
 896                     "PAGE_UP", "pageUpPassThrough",
 897                   "PAGE_DOWN", "pageDownPassThrough",
 898                        "HOME", "homePassThrough",
 899                         "END", "endPassThrough",
 900                        "DOWN", "selectNext",
 901                     "KP_DOWN", "selectNext",
 902                    "alt DOWN", "togglePopup",
 903                 "alt KP_DOWN", "togglePopup",
 904                      "alt UP", "togglePopup",
 905                   "alt KP_UP", "togglePopup",
 906                       "SPACE", "spacePopup",
 907                      "ENTER", "enterPressed",
 908                          "UP", "selectPrevious",
 909                       "KP_UP", "selectPrevious"
 910               }),
 911 
 912             // Internal Frame Defaults
 913             "InternalFrame.icon",(LazyValue) t ->
 914                     MetalIconFactory.getInternalFrameDefaultMenuIcon(),
 915             "InternalFrame.border",(LazyValue) t ->
 916                     new MetalBorders.InternalFrameBorder(),
 917             "InternalFrame.optionDialogBorder",(LazyValue) t ->
 918                     new MetalBorders.OptionDialogBorder(),
 919             "InternalFrame.paletteBorder",(LazyValue) t ->
 920                     new MetalBorders.PaletteBorder(),
 921             "InternalFrame.paletteTitleHeight", 11,
 922             "InternalFrame.paletteCloseIcon",(LazyValue) t ->
 923                     new MetalIconFactory.PaletteCloseIcon(),
 924             "InternalFrame.closeIcon",
 925                (LazyValue) t -> MetalIconFactory.
 926                        getInternalFrameCloseIcon(internalFrameIconSize),
 927             "InternalFrame.maximizeIcon",
 928                (LazyValue) t -> MetalIconFactory.
 929                        getInternalFrameMaximizeIcon(internalFrameIconSize),
 930             "InternalFrame.iconifyIcon",
 931                (LazyValue) t -> MetalIconFactory.
 932                        getInternalFrameMinimizeIcon(internalFrameIconSize),
 933             "InternalFrame.minimizeIcon",
 934                (LazyValue) t -> MetalIconFactory.
 935                        getInternalFrameAltMaximizeIcon(internalFrameIconSize),
 936             "InternalFrame.titleFont",  windowTitleValue,
 937             "InternalFrame.windowBindings", null,
 938             // Internal Frame Auditory Cue Mappings
 939             "InternalFrame.closeSound", "sounds/FrameClose.wav",
 940             "InternalFrame.maximizeSound", "sounds/FrameMaximize.wav",
 941             "InternalFrame.minimizeSound", "sounds/FrameMinimize.wav",
 942             "InternalFrame.restoreDownSound", "sounds/FrameRestoreDown.wav",
 943             "InternalFrame.restoreUpSound", "sounds/FrameRestoreUp.wav",
 944 
 945             // Desktop Icon
 946             "DesktopIcon.border", desktopIconBorder,
 947             "DesktopIcon.font", controlTextValue,
 948             "DesktopIcon.foreground", controlTextColor,
 949             "DesktopIcon.background", control,
 950             "DesktopIcon.width", Integer.valueOf(160),
 951 
 952             "Desktop.ancestorInputMap",
 953                new UIDefaults.LazyInputMap(new Object[] {
 954                  "ctrl F5", "restore",
 955                  "ctrl F4", "close",
 956                  "ctrl F7", "move",
 957                  "ctrl F8", "resize",
 958                    "RIGHT", "right",
 959                 "KP_RIGHT", "right",
 960              "shift RIGHT", "shrinkRight",
 961           "shift KP_RIGHT", "shrinkRight",
 962                     "LEFT", "left",
 963                  "KP_LEFT", "left",
 964               "shift LEFT", "shrinkLeft",
 965            "shift KP_LEFT", "shrinkLeft",
 966                       "UP", "up",
 967                    "KP_UP", "up",
 968                 "shift UP", "shrinkUp",
 969              "shift KP_UP", "shrinkUp",
 970                     "DOWN", "down",
 971                  "KP_DOWN", "down",
 972               "shift DOWN", "shrinkDown",
 973            "shift KP_DOWN", "shrinkDown",
 974                   "ESCAPE", "escape",
 975                  "ctrl F9", "minimize",
 976                 "ctrl F10", "maximize",
 977                  "ctrl F6", "selectNextFrame",
 978                 "ctrl TAB", "selectNextFrame",
 979              "ctrl alt F6", "selectNextFrame",
 980        "shift ctrl alt F6", "selectPreviousFrame",
 981                 "ctrl F12", "navigateNext",
 982            "shift ctrl F12", "navigatePrevious"
 983               }),
 984 
 985             // Titled Border
 986             "TitledBorder.font", controlTextValue,
 987             "TitledBorder.titleColor", systemTextColor,
 988             "TitledBorder.border", titledBorderBorder,
 989 
 990             // Label
 991             "Label.font", controlTextValue,
 992             "Label.foreground", systemTextColor,
 993             "Label.disabledForeground", getInactiveSystemTextColor(),
 994 
 995             // List
 996             "List.font", controlTextValue,
 997             "List.focusCellHighlightBorder", focusCellHighlightBorder,
 998             "List.focusInputMap",
 999                new UIDefaults.LazyInputMap(new Object[] {
1000                            "ctrl C", "copy",
1001                            "ctrl V", "paste",
1002                            "ctrl X", "cut",
1003                              "COPY", "copy",
1004                             "PASTE", "paste",
1005                               "CUT", "cut",
1006                    "control INSERT", "copy",
1007                      "shift INSERT", "paste",
1008                      "shift DELETE", "cut",
1009                                "UP", "selectPreviousRow",
1010                             "KP_UP", "selectPreviousRow",
1011                          "shift UP", "selectPreviousRowExtendSelection",
1012                       "shift KP_UP", "selectPreviousRowExtendSelection",
1013                     "ctrl shift UP", "selectPreviousRowExtendSelection",
1014                  "ctrl shift KP_UP", "selectPreviousRowExtendSelection",
1015                           "ctrl UP", "selectPreviousRowChangeLead",
1016                        "ctrl KP_UP", "selectPreviousRowChangeLead",
1017                              "DOWN", "selectNextRow",
1018                           "KP_DOWN", "selectNextRow",
1019                        "shift DOWN", "selectNextRowExtendSelection",
1020                     "shift KP_DOWN", "selectNextRowExtendSelection",
1021                   "ctrl shift DOWN", "selectNextRowExtendSelection",
1022                "ctrl shift KP_DOWN", "selectNextRowExtendSelection",
1023                         "ctrl DOWN", "selectNextRowChangeLead",
1024                      "ctrl KP_DOWN", "selectNextRowChangeLead",
1025                              "LEFT", "selectPreviousColumn",
1026                           "KP_LEFT", "selectPreviousColumn",
1027                        "shift LEFT", "selectPreviousColumnExtendSelection",
1028                     "shift KP_LEFT", "selectPreviousColumnExtendSelection",
1029                   "ctrl shift LEFT", "selectPreviousColumnExtendSelection",
1030                "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection",
1031                         "ctrl LEFT", "selectPreviousColumnChangeLead",
1032                      "ctrl KP_LEFT", "selectPreviousColumnChangeLead",
1033                             "RIGHT", "selectNextColumn",
1034                          "KP_RIGHT", "selectNextColumn",
1035                       "shift RIGHT", "selectNextColumnExtendSelection",
1036                    "shift KP_RIGHT", "selectNextColumnExtendSelection",
1037                  "ctrl shift RIGHT", "selectNextColumnExtendSelection",
1038               "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection",
1039                        "ctrl RIGHT", "selectNextColumnChangeLead",
1040                     "ctrl KP_RIGHT", "selectNextColumnChangeLead",
1041                              "HOME", "selectFirstRow",
1042                        "shift HOME", "selectFirstRowExtendSelection",
1043                   "ctrl shift HOME", "selectFirstRowExtendSelection",
1044                         "ctrl HOME", "selectFirstRowChangeLead",
1045                               "END", "selectLastRow",
1046                         "shift END", "selectLastRowExtendSelection",
1047                    "ctrl shift END", "selectLastRowExtendSelection",
1048                          "ctrl END", "selectLastRowChangeLead",
1049                           "PAGE_UP", "scrollUp",
1050                     "shift PAGE_UP", "scrollUpExtendSelection",
1051                "ctrl shift PAGE_UP", "scrollUpExtendSelection",
1052                      "ctrl PAGE_UP", "scrollUpChangeLead",
1053                         "PAGE_DOWN", "scrollDown",
1054                   "shift PAGE_DOWN", "scrollDownExtendSelection",
1055              "ctrl shift PAGE_DOWN", "scrollDownExtendSelection",
1056                    "ctrl PAGE_DOWN", "scrollDownChangeLead",
1057                            "ctrl A", "selectAll",
1058                        "ctrl SLASH", "selectAll",
1059                   "ctrl BACK_SLASH", "clearSelection",
1060                             "SPACE", "addToSelection",
1061                        "ctrl SPACE", "toggleAndAnchor",
1062                       "shift SPACE", "extendTo",
1063                  "ctrl shift SPACE", "moveSelectionTo"
1064                  }),
1065 
1066             // ScrollBar
1067             "ScrollBar.background", control,
1068             "ScrollBar.highlight", controlHighlight,
1069             "ScrollBar.shadow", controlShadow,
1070             "ScrollBar.darkShadow", controlDarkShadow,
1071             "ScrollBar.thumb", primaryControlShadow,
1072             "ScrollBar.thumbShadow", primaryControlDarkShadow,
1073             "ScrollBar.thumbHighlight", primaryControl,
1074             "ScrollBar.width",  17 ,
1075             "ScrollBar.allowsAbsolutePositioning", Boolean.TRUE,
1076             "ScrollBar.ancestorInputMap",
1077                new UIDefaults.LazyInputMap(new Object[] {
1078                        "RIGHT", "positiveUnitIncrement",
1079                     "KP_RIGHT", "positiveUnitIncrement",
1080                         "DOWN", "positiveUnitIncrement",
1081                      "KP_DOWN", "positiveUnitIncrement",
1082                    "PAGE_DOWN", "positiveBlockIncrement",
1083                         "LEFT", "negativeUnitIncrement",
1084                      "KP_LEFT", "negativeUnitIncrement",
1085                           "UP", "negativeUnitIncrement",
1086                        "KP_UP", "negativeUnitIncrement",
1087                      "PAGE_UP", "negativeBlockIncrement",
1088                         "HOME", "minScroll",
1089                          "END", "maxScroll"
1090                  }),
1091 
1092             // ScrollPane
1093             "ScrollPane.border", scrollPaneBorder,
1094             "ScrollPane.ancestorInputMap",
1095                new UIDefaults.LazyInputMap(new Object[] {
1096                            "RIGHT", "unitScrollRight",
1097                         "KP_RIGHT", "unitScrollRight",
1098                             "DOWN", "unitScrollDown",
1099                          "KP_DOWN", "unitScrollDown",
1100                             "LEFT", "unitScrollLeft",
1101                          "KP_LEFT", "unitScrollLeft",
1102                               "UP", "unitScrollUp",
1103                            "KP_UP", "unitScrollUp",
1104                          "PAGE_UP", "scrollUp",
1105                        "PAGE_DOWN", "scrollDown",
1106                     "ctrl PAGE_UP", "scrollLeft",
1107                   "ctrl PAGE_DOWN", "scrollRight",
1108                        "ctrl HOME", "scrollHome",
1109                         "ctrl END", "scrollEnd"
1110                  }),
1111 
1112             // Tabbed Pane
1113             "TabbedPane.font", controlTextValue,
1114             "TabbedPane.tabAreaBackground", control,
1115             "TabbedPane.background", controlShadow,
1116             "TabbedPane.light", control,
1117             "TabbedPane.focus", primaryControlDarkShadow,
1118             "TabbedPane.selected", control,
1119             "TabbedPane.selectHighlight", controlHighlight,
1120             "TabbedPane.tabAreaInsets", tabbedPaneTabAreaInsets,
1121             "TabbedPane.tabInsets", tabbedPaneTabInsets,
1122             "TabbedPane.focusInputMap",
1123               new UIDefaults.LazyInputMap(new Object[] {
1124                          "RIGHT", "navigateRight",
1125                       "KP_RIGHT", "navigateRight",
1126                           "LEFT", "navigateLeft",
1127                        "KP_LEFT", "navigateLeft",
1128                             "UP", "navigateUp",
1129                          "KP_UP", "navigateUp",
1130                           "DOWN", "navigateDown",
1131                        "KP_DOWN", "navigateDown",
1132                      "ctrl DOWN", "requestFocusForVisibleComponent",
1133                   "ctrl KP_DOWN", "requestFocusForVisibleComponent",
1134                 }),
1135             "TabbedPane.ancestorInputMap",
1136                new UIDefaults.LazyInputMap(new Object[] {
1137                    "ctrl PAGE_DOWN", "navigatePageDown",
1138                      "ctrl PAGE_UP", "navigatePageUp",
1139                           "ctrl UP", "requestFocus",
1140                        "ctrl KP_UP", "requestFocus",
1141                  }),
1142 
1143             // Table
1144             "Table.font", userTextValue,
1145             "Table.focusCellHighlightBorder", focusCellHighlightBorder,
1146             "Table.scrollPaneBorder", scrollPaneBorder,
1147             "Table.dropLineColor", focusColor,
1148             "Table.dropLineShortColor", primaryControlDarkShadow,
1149             "Table.gridColor", controlShadow,  // grid line color
1150             "Table.ancestorInputMap",
1151                new UIDefaults.LazyInputMap(new Object[] {
1152                                "ctrl C", "copy",
1153                                "ctrl V", "paste",
1154                                "ctrl X", "cut",
1155                                  "COPY", "copy",
1156                                 "PASTE", "paste",
1157                                   "CUT", "cut",
1158                        "control INSERT", "copy",
1159                          "shift INSERT", "paste",
1160                          "shift DELETE", "cut",
1161                                 "RIGHT", "selectNextColumn",
1162                              "KP_RIGHT", "selectNextColumn",
1163                           "shift RIGHT", "selectNextColumnExtendSelection",
1164                        "shift KP_RIGHT", "selectNextColumnExtendSelection",
1165                      "ctrl shift RIGHT", "selectNextColumnExtendSelection",
1166                   "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection",
1167                            "ctrl RIGHT", "selectNextColumnChangeLead",
1168                         "ctrl KP_RIGHT", "selectNextColumnChangeLead",
1169                                  "LEFT", "selectPreviousColumn",
1170                               "KP_LEFT", "selectPreviousColumn",
1171                            "shift LEFT", "selectPreviousColumnExtendSelection",
1172                         "shift KP_LEFT", "selectPreviousColumnExtendSelection",
1173                       "ctrl shift LEFT", "selectPreviousColumnExtendSelection",
1174                    "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection",
1175                             "ctrl LEFT", "selectPreviousColumnChangeLead",
1176                          "ctrl KP_LEFT", "selectPreviousColumnChangeLead",
1177                                  "DOWN", "selectNextRow",
1178                               "KP_DOWN", "selectNextRow",
1179                            "shift DOWN", "selectNextRowExtendSelection",
1180                         "shift KP_DOWN", "selectNextRowExtendSelection",
1181                       "ctrl shift DOWN", "selectNextRowExtendSelection",
1182                    "ctrl shift KP_DOWN", "selectNextRowExtendSelection",
1183                             "ctrl DOWN", "selectNextRowChangeLead",
1184                          "ctrl KP_DOWN", "selectNextRowChangeLead",
1185                                    "UP", "selectPreviousRow",
1186                                 "KP_UP", "selectPreviousRow",
1187                              "shift UP", "selectPreviousRowExtendSelection",
1188                           "shift KP_UP", "selectPreviousRowExtendSelection",
1189                         "ctrl shift UP", "selectPreviousRowExtendSelection",
1190                      "ctrl shift KP_UP", "selectPreviousRowExtendSelection",
1191                               "ctrl UP", "selectPreviousRowChangeLead",
1192                            "ctrl KP_UP", "selectPreviousRowChangeLead",
1193                                  "HOME", "selectFirstColumn",
1194                            "shift HOME", "selectFirstColumnExtendSelection",
1195                       "ctrl shift HOME", "selectFirstRowExtendSelection",
1196                             "ctrl HOME", "selectFirstRow",
1197                                   "END", "selectLastColumn",
1198                             "shift END", "selectLastColumnExtendSelection",
1199                        "ctrl shift END", "selectLastRowExtendSelection",
1200                              "ctrl END", "selectLastRow",
1201                               "PAGE_UP", "scrollUpChangeSelection",
1202                         "shift PAGE_UP", "scrollUpExtendSelection",
1203                    "ctrl shift PAGE_UP", "scrollLeftExtendSelection",
1204                          "ctrl PAGE_UP", "scrollLeftChangeSelection",
1205                             "PAGE_DOWN", "scrollDownChangeSelection",
1206                       "shift PAGE_DOWN", "scrollDownExtendSelection",
1207                  "ctrl shift PAGE_DOWN", "scrollRightExtendSelection",
1208                        "ctrl PAGE_DOWN", "scrollRightChangeSelection",
1209                                   "TAB", "selectNextColumnCell",
1210                             "shift TAB", "selectPreviousColumnCell",
1211                                 "ENTER", "selectNextRowCell",
1212                           "shift ENTER", "selectPreviousRowCell",
1213                                "ctrl A", "selectAll",
1214                            "ctrl SLASH", "selectAll",
1215                       "ctrl BACK_SLASH", "clearSelection",
1216                                "ESCAPE", "cancel",
1217                                    "F2", "startEditing",
1218                                 "SPACE", "addToSelection",
1219                            "ctrl SPACE", "toggleAndAnchor",
1220                           "shift SPACE", "extendTo",
1221                      "ctrl shift SPACE", "moveSelectionTo",
1222                                    "F8", "focusHeader"
1223                  }),
1224             "Table.ascendingSortIcon",
1225                 SwingUtilities2.makeIcon(getClass(), MetalLookAndFeel.class,
1226                 "icons/sortUp.png"),
1227             "Table.descendingSortIcon",
1228                 SwingUtilities2.makeIcon(getClass(), MetalLookAndFeel.class,
1229                 "icons/sortDown.png"),
1230 
1231             "TableHeader.font", userTextValue,
1232             "TableHeader.cellBorder",(LazyValue) t -> new MetalBorders.TableHeaderBorder(),
1233 
1234             // MenuBar
1235             "MenuBar.border", menuBarBorder,
1236             "MenuBar.font", menuTextValue,
1237             "MenuBar.windowBindings", new Object[] {
1238                 "F10", "takeFocus" },
1239 
1240             // Menu
1241             "Menu.border", menuItemBorder,
1242             "Menu.borderPainted", Boolean.TRUE,
1243             "Menu.menuPopupOffsetX", zero,
1244             "Menu.menuPopupOffsetY", zero,
1245             "Menu.submenuPopupOffsetX", -4,
1246             "Menu.submenuPopupOffsetY", -3,
1247             "Menu.font", menuTextValue,
1248             "Menu.selectionForeground", menuSelectedForeground,
1249             "Menu.selectionBackground", menuSelectedBackground,
1250             "Menu.disabledForeground", menuDisabledForeground,
1251             "Menu.acceleratorFont", subTextValue,
1252             "Menu.acceleratorForeground", acceleratorForeground,
1253             "Menu.acceleratorSelectionForeground", acceleratorSelectedForeground,
1254             "Menu.checkIcon",(LazyValue) t -> MetalIconFactory.getMenuItemCheckIcon(),
1255             "Menu.arrowIcon",(LazyValue) t -> MetalIconFactory.getMenuArrowIcon(),
1256 
1257             // Menu Item
1258             "MenuItem.border", menuItemBorder,
1259             "MenuItem.borderPainted", Boolean.TRUE,
1260             "MenuItem.font", menuTextValue,
1261             "MenuItem.selectionForeground", menuSelectedForeground,
1262             "MenuItem.selectionBackground", menuSelectedBackground,
1263             "MenuItem.disabledForeground", menuDisabledForeground,
1264             "MenuItem.acceleratorFont", subTextValue,
1265             "MenuItem.acceleratorForeground", acceleratorForeground,
1266             "MenuItem.acceleratorSelectionForeground", acceleratorSelectedForeground,
1267             "MenuItem.acceleratorDelimiter", menuItemAcceleratorDelimiter,
1268             "MenuItem.checkIcon",(LazyValue) t -> MetalIconFactory.getMenuItemCheckIcon(),
1269             "MenuItem.arrowIcon",(LazyValue) t -> MetalIconFactory.getMenuItemArrowIcon(),
1270                  // Menu Item Auditory Cue Mapping
1271             "MenuItem.commandSound", "sounds/MenuItemCommand.wav",
1272 
1273             // OptionPane.
1274             "OptionPane.windowBindings", new Object[] {
1275                 "ESCAPE", "close" },
1276             // Option Pane Auditory Cue Mappings
1277             "OptionPane.informationSound", "sounds/OptionPaneInformation.wav",
1278             "OptionPane.warningSound", "sounds/OptionPaneWarning.wav",
1279             "OptionPane.errorSound", "sounds/OptionPaneError.wav",
1280             "OptionPane.questionSound", "sounds/OptionPaneQuestion.wav",
1281 
1282             // Option Pane Special Dialog Colors, used when MetalRootPaneUI
1283             // is providing window manipulation widgets.
1284             "OptionPane.errorDialog.border.background",
1285                         new ColorUIResource(153, 51, 51),
1286             "OptionPane.errorDialog.titlePane.foreground",
1287                         new ColorUIResource(51, 0, 0),
1288             "OptionPane.errorDialog.titlePane.background",
1289                         new ColorUIResource(255, 153, 153),
1290             "OptionPane.errorDialog.titlePane.shadow",
1291                         new ColorUIResource(204, 102, 102),
1292             "OptionPane.questionDialog.border.background",
1293                         new ColorUIResource(51, 102, 51),
1294             "OptionPane.questionDialog.titlePane.foreground",
1295                         new ColorUIResource(0, 51, 0),
1296             "OptionPane.questionDialog.titlePane.background",
1297                         new ColorUIResource(153, 204, 153),
1298             "OptionPane.questionDialog.titlePane.shadow",
1299                         new ColorUIResource(102, 153, 102),
1300             "OptionPane.warningDialog.border.background",
1301                         new ColorUIResource(153, 102, 51),
1302             "OptionPane.warningDialog.titlePane.foreground",
1303                         new ColorUIResource(102, 51, 0),
1304             "OptionPane.warningDialog.titlePane.background",
1305                         new ColorUIResource(255, 204, 153),
1306             "OptionPane.warningDialog.titlePane.shadow",
1307                         new ColorUIResource(204, 153, 102),
1308             // OptionPane fonts are defined below
1309 
1310             // Separator
1311             "Separator.background", getSeparatorBackground(),
1312             "Separator.foreground", getSeparatorForeground(),
1313 
1314             // Popup Menu
1315             "PopupMenu.border", popupMenuBorder,
1316                  // Popup Menu Auditory Cue Mappings
1317             "PopupMenu.popupSound", "sounds/PopupMenuPopup.wav",
1318             "PopupMenu.font", menuTextValue,
1319 
1320             // CB & RB Menu Item
1321             "CheckBoxMenuItem.border", menuItemBorder,
1322             "CheckBoxMenuItem.borderPainted", Boolean.TRUE,
1323             "CheckBoxMenuItem.font", menuTextValue,
1324             "CheckBoxMenuItem.selectionForeground", menuSelectedForeground,
1325             "CheckBoxMenuItem.selectionBackground", menuSelectedBackground,
1326             "CheckBoxMenuItem.disabledForeground", menuDisabledForeground,
1327             "CheckBoxMenuItem.acceleratorFont", subTextValue,
1328             "CheckBoxMenuItem.acceleratorForeground", acceleratorForeground,
1329             "CheckBoxMenuItem.acceleratorSelectionForeground", acceleratorSelectedForeground,
1330             "CheckBoxMenuItem.checkIcon",(LazyValue) t -> MetalIconFactory.getCheckBoxMenuItemIcon(),
1331             "CheckBoxMenuItem.arrowIcon",(LazyValue) t -> MetalIconFactory.getMenuItemArrowIcon(),
1332             "CheckBoxMenuItem.commandSound", "sounds/MenuItemCommand.wav",
1333 
1334             "RadioButtonMenuItem.border", menuItemBorder,
1335             "RadioButtonMenuItem.borderPainted", Boolean.TRUE,
1336             "RadioButtonMenuItem.font", menuTextValue,
1337             "RadioButtonMenuItem.selectionForeground", menuSelectedForeground,
1338             "RadioButtonMenuItem.selectionBackground", menuSelectedBackground,
1339             "RadioButtonMenuItem.disabledForeground", menuDisabledForeground,
1340             "RadioButtonMenuItem.acceleratorFont", subTextValue,
1341             "RadioButtonMenuItem.acceleratorForeground", acceleratorForeground,
1342             "RadioButtonMenuItem.acceleratorSelectionForeground", acceleratorSelectedForeground,
1343             "RadioButtonMenuItem.checkIcon",(LazyValue) t -> MetalIconFactory.getRadioButtonMenuItemIcon(),
1344             "RadioButtonMenuItem.arrowIcon",(LazyValue) t -> MetalIconFactory.getMenuItemArrowIcon(),
1345             "RadioButtonMenuItem.commandSound", "sounds/MenuItemCommand.wav",
1346 
1347             "Spinner.ancestorInputMap",
1348                new UIDefaults.LazyInputMap(new Object[] {
1349                                "UP", "increment",
1350                             "KP_UP", "increment",
1351                              "DOWN", "decrement",
1352                           "KP_DOWN", "decrement",
1353                }),
1354             "Spinner.arrowButtonInsets", zeroInsets,
1355             "Spinner.border", textFieldBorder,
1356             "Spinner.arrowButtonBorder", buttonBorder,
1357             "Spinner.font", controlTextValue,
1358 
1359             // SplitPane
1360 
1361             "SplitPane.dividerSize", 10,
1362             "SplitPane.ancestorInputMap",
1363                new UIDefaults.LazyInputMap(new Object[] {
1364                         "UP", "negativeIncrement",
1365                       "DOWN", "positiveIncrement",
1366                       "LEFT", "negativeIncrement",
1367                      "RIGHT", "positiveIncrement",
1368                      "KP_UP", "negativeIncrement",
1369                    "KP_DOWN", "positiveIncrement",
1370                    "KP_LEFT", "negativeIncrement",
1371                   "KP_RIGHT", "positiveIncrement",
1372                       "HOME", "selectMin",
1373                        "END", "selectMax",
1374                         "F8", "startResize",
1375                         "F6", "toggleFocus",
1376                   "ctrl TAB", "focusOutForward",
1377             "ctrl shift TAB", "focusOutBackward"
1378                  }),
1379             "SplitPane.centerOneTouchButtons", Boolean.FALSE,
1380             "SplitPane.dividerFocusColor", primaryControl,
1381 
1382             // Tree
1383             // Tree.font was mapped to system font pre 1.4.1
1384             "Tree.font", userTextValue,
1385             "Tree.textBackground", getWindowBackground(),
1386             "Tree.selectionBorderColor", focusColor,
1387             "Tree.openIcon",(LazyValue) t -> MetalIconFactory.getTreeFolderIcon(),
1388             "Tree.closedIcon",(LazyValue) t -> MetalIconFactory.getTreeFolderIcon(),
1389             "Tree.leafIcon",(LazyValue) t -> MetalIconFactory.getTreeLeafIcon(),
1390             "Tree.expandedIcon",(LazyValue) t -> MetalIconFactory.getTreeControlIcon(Boolean.valueOf(MetalIconFactory.DARK)),
1391             "Tree.collapsedIcon",(LazyValue) t -> MetalIconFactory.getTreeControlIcon(Boolean.valueOf( MetalIconFactory.LIGHT )),
1392 
1393             "Tree.line", primaryControl, // horiz lines
1394             "Tree.hash", primaryControl,  // legs
1395             "Tree.rowHeight", zero,
1396             "Tree.focusInputMap",
1397                new UIDefaults.LazyInputMap(new Object[] {
1398                                     "ADD", "expand",
1399                                "SUBTRACT", "collapse",
1400                                  "ctrl C", "copy",
1401                                  "ctrl V", "paste",
1402                                  "ctrl X", "cut",
1403                                    "COPY", "copy",
1404                                   "PASTE", "paste",
1405                                     "CUT", "cut",
1406                          "control INSERT", "copy",
1407                            "shift INSERT", "paste",
1408                            "shift DELETE", "cut",
1409                                      "UP", "selectPrevious",
1410                                   "KP_UP", "selectPrevious",
1411                                "shift UP", "selectPreviousExtendSelection",
1412                             "shift KP_UP", "selectPreviousExtendSelection",
1413                           "ctrl shift UP", "selectPreviousExtendSelection",
1414                        "ctrl shift KP_UP", "selectPreviousExtendSelection",
1415                                 "ctrl UP", "selectPreviousChangeLead",
1416                              "ctrl KP_UP", "selectPreviousChangeLead",
1417                                    "DOWN", "selectNext",
1418                                 "KP_DOWN", "selectNext",
1419                              "shift DOWN", "selectNextExtendSelection",
1420                           "shift KP_DOWN", "selectNextExtendSelection",
1421                         "ctrl shift DOWN", "selectNextExtendSelection",
1422                      "ctrl shift KP_DOWN", "selectNextExtendSelection",
1423                               "ctrl DOWN", "selectNextChangeLead",
1424                            "ctrl KP_DOWN", "selectNextChangeLead",
1425                                   "RIGHT", "selectChild",
1426                                "KP_RIGHT", "selectChild",
1427                                    "LEFT", "selectParent",
1428                                 "KP_LEFT", "selectParent",
1429                                 "PAGE_UP", "scrollUpChangeSelection",
1430                           "shift PAGE_UP", "scrollUpExtendSelection",
1431                      "ctrl shift PAGE_UP", "scrollUpExtendSelection",
1432                            "ctrl PAGE_UP", "scrollUpChangeLead",
1433                               "PAGE_DOWN", "scrollDownChangeSelection",
1434                         "shift PAGE_DOWN", "scrollDownExtendSelection",
1435                    "ctrl shift PAGE_DOWN", "scrollDownExtendSelection",
1436                          "ctrl PAGE_DOWN", "scrollDownChangeLead",
1437                                    "HOME", "selectFirst",
1438                              "shift HOME", "selectFirstExtendSelection",
1439                         "ctrl shift HOME", "selectFirstExtendSelection",
1440                               "ctrl HOME", "selectFirstChangeLead",
1441                                     "END", "selectLast",
1442                               "shift END", "selectLastExtendSelection",
1443                          "ctrl shift END", "selectLastExtendSelection",
1444                                "ctrl END", "selectLastChangeLead",
1445                                      "F2", "startEditing",
1446                                  "ctrl A", "selectAll",
1447                              "ctrl SLASH", "selectAll",
1448                         "ctrl BACK_SLASH", "clearSelection",
1449                               "ctrl LEFT", "scrollLeft",
1450                            "ctrl KP_LEFT", "scrollLeft",
1451                              "ctrl RIGHT", "scrollRight",
1452                           "ctrl KP_RIGHT", "scrollRight",
1453                                   "SPACE", "addToSelection",
1454                              "ctrl SPACE", "toggleAndAnchor",
1455                             "shift SPACE", "extendTo",
1456                        "ctrl shift SPACE", "moveSelectionTo"
1457                  }),
1458             "Tree.ancestorInputMap",
1459                new UIDefaults.LazyInputMap(new Object[] {
1460                      "ESCAPE", "cancel"
1461                  }),
1462 
1463             // ToolBar
1464             "ToolBar.border", toolBarBorder,
1465             "ToolBar.background", menuBackground,
1466             "ToolBar.foreground", getMenuForeground(),
1467             "ToolBar.font", menuTextValue,
1468             "ToolBar.dockingBackground", menuBackground,
1469             "ToolBar.floatingBackground", menuBackground,
1470             "ToolBar.dockingForeground", primaryControlDarkShadow,
1471             "ToolBar.floatingForeground", primaryControl,
1472             "ToolBar.rolloverBorder", (LazyValue) t -> MetalBorders.getToolBarRolloverBorder(),
1473             "ToolBar.nonrolloverBorder", (LazyValue) t -> MetalBorders.getToolBarNonrolloverBorder(),
1474             "ToolBar.ancestorInputMap",
1475                new UIDefaults.LazyInputMap(new Object[] {
1476                         "UP", "navigateUp",
1477                      "KP_UP", "navigateUp",
1478                       "DOWN", "navigateDown",
1479                    "KP_DOWN", "navigateDown",
1480                       "LEFT", "navigateLeft",
1481                    "KP_LEFT", "navigateLeft",
1482                      "RIGHT", "navigateRight",
1483                   "KP_RIGHT", "navigateRight"
1484                  }),
1485 
1486             // RootPane
1487             "RootPane.frameBorder", (LazyValue) t -> new MetalBorders.FrameBorder(),
1488             "RootPane.plainDialogBorder", dialogBorder,
1489             "RootPane.informationDialogBorder", dialogBorder,
1490             "RootPane.errorDialogBorder", (LazyValue) t -> new MetalBorders.ErrorDialogBorder(),
1491             "RootPane.colorChooserDialogBorder", questionDialogBorder,
1492             "RootPane.fileChooserDialogBorder", questionDialogBorder,
1493             "RootPane.questionDialogBorder", questionDialogBorder,
1494             "RootPane.warningDialogBorder", (LazyValue) t -> new MetalBorders.WarningDialogBorder(),
1495             // These bindings are only enabled when there is a default
1496             // button set on the rootpane.
1497             "RootPane.defaultButtonWindowKeyBindings", new Object[] {
1498                              "ENTER", "press",
1499                     "released ENTER", "release",
1500                         "ctrl ENTER", "press",
1501                "ctrl released ENTER", "release"
1502               },
1503         };
1504 
1505         table.putDefaults(defaults);
1506 
1507         if (isWindows() && useSystemFonts() && theme.isSystemTheme()) {
1508             Object messageFont = new MetalFontDesktopProperty(
1509                 "win.messagebox.font.height", MetalTheme.CONTROL_TEXT_FONT);
1510 
1511             defaults = new Object[] {
1512                 "OptionPane.messageFont", messageFont,
1513                 "OptionPane.buttonFont", messageFont,
1514             };
1515             table.putDefaults(defaults);
1516         }
1517 
1518         flushUnreferenced(); // Remove old listeners
1519 
1520         boolean lafCond = SwingUtilities2.isLocalDisplay();
1521         SwingUtilities2.putAATextInfo(lafCond, table);
1522         new AATextListener(this);
1523     }
1524 
1525     /**
1526      * Ensures the current {@code MetalTheme} is {@code non-null}. This is
1527      * a cover method for {@code getCurrentTheme}.
1528      *
1529      * @see #getCurrentTheme
1530      */
1531     protected void createDefaultTheme() {
1532         getCurrentTheme();
1533     }
1534 
1535     /**
1536      * Returns the look and feel defaults. This invokes, in order,
1537      * {@code createDefaultTheme()}, {@code super.getDefaults()} and
1538      * {@code getCurrentTheme().addCustomEntriesToTable(table)}.
1539      * <p>
1540      * While this method is public, it should only be invoked by the
1541      * {@code UIManager} when the look and feel is set as the current
1542      * look and feel and after {@code initialize} has been invoked.
1543      *
1544      * @return the look and feel defaults
1545      *
1546      * @see #createDefaultTheme
1547      * @see javax.swing.plaf.basic.BasicLookAndFeel#getDefaults()
1548      * @see MetalTheme#addCustomEntriesToTable(UIDefaults)
1549      */
1550     public UIDefaults getDefaults() {
1551         // PENDING: move this to initialize when API changes are allowed
1552         METAL_LOOK_AND_FEEL_INITED = true;
1553 
1554         createDefaultTheme();
1555         UIDefaults table = super.getDefaults();
1556         MetalTheme currentTheme = getCurrentTheme();
1557         currentTheme.addCustomEntriesToTable(table);
1558         currentTheme.install();
1559         return table;
1560     }
1561 
1562     /**
1563      * {@inheritDoc}
1564      *
1565      * @since 1.4
1566      */
1567     public void provideErrorFeedback(Component component) {
1568         super.provideErrorFeedback(component);
1569     }
1570 
1571     /**
1572      * Set the theme used by <code>MetalLookAndFeel</code>.
1573      * <p>
1574      * After the theme is set, {@code MetalLookAndFeel} needs to be
1575      * re-installed and the uis need to be recreated. The following
1576      * shows how to do this:
1577      * <pre>
1578      *   MetalLookAndFeel.setCurrentTheme(theme);
1579      *
1580      *   // re-install the Metal Look and Feel
1581      *   UIManager.setLookAndFeel(new MetalLookAndFeel());
1582      *
1583      *   // Update the ComponentUIs for all Components. This
1584      *   // needs to be invoked for all windows.
1585      *   SwingUtilities.updateComponentTreeUI(rootComponent);
1586      * </pre>
1587      * If this is not done the results are undefined.
1588      *
1589      * @param theme the theme to use
1590      * @throws NullPointerException if {@code theme} is {@code null}
1591      * @see #getCurrentTheme
1592      */
1593     public static void setCurrentTheme(MetalTheme theme) {
1594         // NOTE: because you need to recreate the look and feel after
1595         // this step, we don't bother blowing away any potential windows
1596         // values.
1597         if (theme == null) {
1598             throw new NullPointerException("Can't have null theme");
1599         }
1600         AppContext.getAppContext().put( "currentMetalTheme", theme );
1601     }
1602 
1603     /**
1604      * Return the theme currently being used by <code>MetalLookAndFeel</code>.
1605      * If the current theme is {@code null}, the default theme is created.
1606      *
1607      * @return the current theme
1608      * @see #setCurrentTheme
1609      * @since 1.5
1610      */
1611     public static MetalTheme getCurrentTheme() {
1612         MetalTheme currentTheme;
1613         AppContext context = AppContext.getAppContext();
1614         currentTheme = (MetalTheme) context.get( "currentMetalTheme" );
1615         if (currentTheme == null) {
1616             // This will happen in two cases:
1617             // . When MetalLookAndFeel is first being initialized.
1618             // . When a new AppContext has been created that hasn't
1619             //   triggered UIManager to load a LAF. Rather than invoke
1620             //   a method on the UIManager, which would trigger the loading
1621             //   of a potentially different LAF, we directly set the
1622             //   Theme here.
1623             if (useHighContrastTheme()) {
1624                 currentTheme = new MetalHighContrastTheme();
1625             }
1626             else {
1627                 // Create the default theme. We prefer Ocean, but will
1628                 // use DefaultMetalTheme if told to.
1629                 String theme = AccessController.doPrivileged(
1630                                new GetPropertyAction("swing.metalTheme"));
1631                 if ("steel".equals(theme)) {
1632                     currentTheme = new DefaultMetalTheme();
1633                 }
1634                 else {
1635                     currentTheme = new OceanTheme();
1636                 }
1637             }
1638             setCurrentTheme(currentTheme);
1639         }
1640         return currentTheme;
1641     }
1642 
1643     /**
1644      * Returns an <code>Icon</code> with a disabled appearance.
1645      * This method is used to generate a disabled <code>Icon</code> when
1646      * one has not been specified.  For example, if you create a
1647      * <code>JButton</code> and only specify an <code>Icon</code> via
1648      * <code>setIcon</code> this method will be called to generate the
1649      * disabled <code>Icon</code>. If null is passed as <code>icon</code>
1650      * this method returns null.
1651      * <p>
1652      * Some look and feels might not render the disabled Icon, in which
1653      * case they will ignore this.
1654      *
1655      * @param component JComponent that will display the Icon, may be null
1656      * @param icon Icon to generate disable icon from.
1657      * @return Disabled icon, or null if a suitable Icon can not be
1658      *         generated.
1659      * @since 1.5
1660      */
1661     public Icon getDisabledIcon(JComponent component, Icon icon) {
1662         if ((icon instanceof ImageIcon) && MetalLookAndFeel.usingOcean()) {
1663             return MetalUtils.getOceanDisabledButtonIcon(
1664                                   ((ImageIcon)icon).getImage());
1665         }
1666         return super.getDisabledIcon(component, icon);
1667     }
1668 
1669     /**
1670      * Returns an <code>Icon</code> for use by disabled
1671      * components that are also selected. This method is used to generate an
1672      * <code>Icon</code> for components that are in both the disabled and
1673      * selected states but do not have a specific <code>Icon</code> for this
1674      * state.  For example, if you create a <code>JButton</code> and only
1675      * specify an <code>Icon</code> via <code>setIcon</code> this method
1676      * will be called to generate the disabled and selected
1677      * <code>Icon</code>. If null is passed as <code>icon</code> this method
1678      * returns null.
1679      * <p>
1680      * Some look and feels might not render the disabled and selected Icon,
1681      * in which case they will ignore this.
1682      *
1683      * @param component JComponent that will display the Icon, may be null
1684      * @param icon Icon to generate disabled and selected icon from.
1685      * @return Disabled and Selected icon, or null if a suitable Icon can not
1686      *         be generated.
1687      * @since 1.5
1688      */
1689     public Icon getDisabledSelectedIcon(JComponent component, Icon icon) {
1690         if ((icon instanceof ImageIcon) && MetalLookAndFeel.usingOcean()) {
1691             return MetalUtils.getOceanDisabledButtonIcon(
1692                                   ((ImageIcon)icon).getImage());
1693         }
1694         return super.getDisabledSelectedIcon(component, icon);
1695     }
1696 
1697     /**
1698      * Returns the control text font of the current theme. This is a
1699      * cover method for {@code getCurrentTheme().getControlTextColor()}.
1700      *
1701      * @return the control text font
1702      *
1703      * @see MetalTheme
1704      */
1705     public static FontUIResource getControlTextFont() { return getCurrentTheme().getControlTextFont();}
1706 
1707     /**
1708      * Returns the system text font of the current theme. This is a
1709      * cover method for {@code getCurrentTheme().getSystemTextFont()}.
1710      *
1711      * @return the system text font
1712      *
1713      * @see MetalTheme
1714      */
1715     public static FontUIResource getSystemTextFont() { return getCurrentTheme().getSystemTextFont();}
1716 
1717     /**
1718      * Returns the user text font of the current theme. This is a
1719      * cover method for {@code getCurrentTheme().getUserTextFont()}.
1720      *
1721      * @return the user text font
1722      *
1723      * @see MetalTheme
1724      */
1725     public static FontUIResource getUserTextFont() { return getCurrentTheme().getUserTextFont();}
1726 
1727     /**
1728      * Returns the menu text font of the current theme. This is a
1729      * cover method for {@code getCurrentTheme().getMenuTextFont()}.
1730      *
1731      * @return the menu text font
1732      *
1733      * @see MetalTheme
1734      */
1735     public static FontUIResource getMenuTextFont() { return getCurrentTheme().getMenuTextFont();}
1736 
1737     /**
1738      * Returns the window title font of the current theme. This is a
1739      * cover method for {@code getCurrentTheme().getWindowTitleFont()}.
1740      *
1741      * @return the window title font
1742      *
1743      * @see MetalTheme
1744      */
1745     public static FontUIResource getWindowTitleFont() { return getCurrentTheme().getWindowTitleFont();}
1746 
1747     /**
1748      * Returns the sub-text font of the current theme. This is a
1749      * cover method for {@code getCurrentTheme().getSubTextFont()}.
1750      *
1751      * @return the sub-text font
1752      *
1753      * @see MetalTheme
1754      */
1755     public static FontUIResource getSubTextFont() { return getCurrentTheme().getSubTextFont();}
1756 
1757     /**
1758      * Returns the desktop color of the current theme. This is a
1759      * cover method for {@code getCurrentTheme().getDesktopColor()}.
1760      *
1761      * @return the desktop color
1762      *
1763      * @see MetalTheme
1764      */
1765     public static ColorUIResource getDesktopColor() { return getCurrentTheme().getDesktopColor(); }
1766 
1767     /**
1768      * Returns the focus color of the current theme. This is a
1769      * cover method for {@code getCurrentTheme().getFocusColor()}.
1770      *
1771      * @return the focus color
1772      *
1773      * @see MetalTheme
1774      */
1775     public static ColorUIResource getFocusColor() { return getCurrentTheme().getFocusColor(); }
1776 
1777     /**
1778      * Returns the white color of the current theme. This is a
1779      * cover method for {@code getCurrentTheme().getWhite()}.
1780      *
1781      * @return the white color
1782      *
1783      * @see MetalTheme
1784      */
1785     public static ColorUIResource getWhite() { return getCurrentTheme().getWhite(); }
1786 
1787     /**
1788      * Returns the black color of the current theme. This is a
1789      * cover method for {@code getCurrentTheme().getBlack()}.
1790      *
1791      * @return the black color
1792      *
1793      * @see MetalTheme
1794      */
1795     public static ColorUIResource getBlack() { return getCurrentTheme().getBlack(); }
1796 
1797     /**
1798      * Returns the control color of the current theme. This is a
1799      * cover method for {@code getCurrentTheme().getControl()}.
1800      *
1801      * @return the control color
1802      *
1803      * @see MetalTheme
1804      */
1805     public static ColorUIResource getControl() { return getCurrentTheme().getControl(); }
1806 
1807     /**
1808      * Returns the control shadow color of the current theme. This is a
1809      * cover method for {@code getCurrentTheme().getControlShadow()}.
1810      *
1811      * @return the control shadow color
1812      *
1813      * @see MetalTheme
1814      */
1815     public static ColorUIResource getControlShadow() { return getCurrentTheme().getControlShadow(); }
1816 
1817     /**
1818      * Returns the control dark shadow color of the current theme. This is a
1819      * cover method for {@code getCurrentTheme().getControlDarkShadow()}.
1820      *
1821      * @return the control dark shadow color
1822      *
1823      * @see MetalTheme
1824      */
1825     public static ColorUIResource getControlDarkShadow() { return getCurrentTheme().getControlDarkShadow(); }
1826 
1827     /**
1828      * Returns the control info color of the current theme. This is a
1829      * cover method for {@code getCurrentTheme().getControlInfo()}.
1830      *
1831      * @return the control info color
1832      *
1833      * @see MetalTheme
1834      */
1835     public static ColorUIResource getControlInfo() { return getCurrentTheme().getControlInfo(); }
1836 
1837     /**
1838      * Returns the control highlight color of the current theme. This is a
1839      * cover method for {@code getCurrentTheme().getControlHighlight()}.
1840      *
1841      * @return the control highlight color
1842      *
1843      * @see MetalTheme
1844      */
1845     public static ColorUIResource getControlHighlight() { return getCurrentTheme().getControlHighlight(); }
1846 
1847     /**
1848      * Returns the control disabled color of the current theme. This is a
1849      * cover method for {@code getCurrentTheme().getControlDisabled()}.
1850      *
1851      * @return the control disabled color
1852      *
1853      * @see MetalTheme
1854      */
1855     public static ColorUIResource getControlDisabled() { return getCurrentTheme().getControlDisabled(); }
1856 
1857     /**
1858      * Returns the primary control color of the current theme. This is a
1859      * cover method for {@code getCurrentTheme().getPrimaryControl()}.
1860      *
1861      * @return the primary control color
1862      *
1863      * @see MetalTheme
1864      */
1865     public static ColorUIResource getPrimaryControl() { return getCurrentTheme().getPrimaryControl(); }
1866 
1867     /**
1868      * Returns the primary control shadow color of the current theme. This is a
1869      * cover method for {@code getCurrentTheme().getPrimaryControlShadow()}.
1870      *
1871      * @return the primary control shadow color
1872      *
1873      * @see MetalTheme
1874      */
1875     public static ColorUIResource getPrimaryControlShadow() { return getCurrentTheme().getPrimaryControlShadow(); }
1876 
1877     /**
1878      * Returns the primary control dark shadow color of the current
1879      * theme. This is a cover method for {@code
1880      * getCurrentTheme().getPrimaryControlDarkShadow()}.
1881      *
1882      * @return the primary control dark shadow color
1883      *
1884      * @see MetalTheme
1885      */
1886     public static ColorUIResource getPrimaryControlDarkShadow() { return getCurrentTheme().getPrimaryControlDarkShadow(); }
1887 
1888     /**
1889      * Returns the primary control info color of the current theme. This is a
1890      * cover method for {@code getCurrentTheme().getPrimaryControlInfo()}.
1891      *
1892      * @return the primary control info color
1893      *
1894      * @see MetalTheme
1895      */
1896     public static ColorUIResource getPrimaryControlInfo() { return getCurrentTheme().getPrimaryControlInfo(); }
1897 
1898     /**
1899      * Returns the primary control highlight color of the current
1900      * theme. This is a cover method for {@code
1901      * getCurrentTheme().getPrimaryControlHighlight()}.
1902      *
1903      * @return the primary control highlight color
1904      *
1905      * @see MetalTheme
1906      */
1907     public static ColorUIResource getPrimaryControlHighlight() { return getCurrentTheme().getPrimaryControlHighlight(); }
1908 
1909     /**
1910      * Returns the system text color of the current theme. This is a
1911      * cover method for {@code getCurrentTheme().getSystemTextColor()}.
1912      *
1913      * @return the system text color
1914      *
1915      * @see MetalTheme
1916      */
1917     public static ColorUIResource getSystemTextColor() { return getCurrentTheme().getSystemTextColor(); }
1918 
1919     /**
1920      * Returns the control text color of the current theme. This is a
1921      * cover method for {@code getCurrentTheme().getControlTextColor()}.
1922      *
1923      * @return the control text color
1924      *
1925      * @see MetalTheme
1926      */
1927     public static ColorUIResource getControlTextColor() { return getCurrentTheme().getControlTextColor(); }
1928 
1929     /**
1930      * Returns the inactive control text color of the current theme. This is a
1931      * cover method for {@code
1932      * getCurrentTheme().getInactiveControlTextColor()}.
1933      *
1934      * @return the inactive control text color
1935      *
1936      * @see MetalTheme
1937      */
1938     public static ColorUIResource getInactiveControlTextColor() { return getCurrentTheme().getInactiveControlTextColor(); }
1939 
1940     /**
1941      * Returns the inactive system text color of the current theme. This is a
1942      * cover method for {@code
1943      * getCurrentTheme().getInactiveSystemTextColor()}.
1944      *
1945      * @return the inactive system text color
1946      *
1947      * @see MetalTheme
1948      */
1949     public static ColorUIResource getInactiveSystemTextColor() { return getCurrentTheme().getInactiveSystemTextColor(); }
1950 
1951     /**
1952      * Returns the user text color of the current theme. This is a
1953      * cover method for {@code getCurrentTheme().getUserTextColor()}.
1954      *
1955      * @return the user text color
1956      *
1957      * @see MetalTheme
1958      */
1959     public static ColorUIResource getUserTextColor() { return getCurrentTheme().getUserTextColor(); }
1960 
1961     /**
1962      * Returns the text highlight color of the current theme. This is a
1963      * cover method for {@code getCurrentTheme().getTextHighlightColor()}.
1964      *
1965      * @return the text highlight color
1966      *
1967      * @see MetalTheme
1968      */
1969     public static ColorUIResource getTextHighlightColor() { return getCurrentTheme().getTextHighlightColor(); }
1970 
1971     /**
1972      * Returns the highlighted text color of the current theme. This is a
1973      * cover method for {@code getCurrentTheme().getHighlightedTextColor()}.
1974      *
1975      * @return the highlighted text color
1976      *
1977      * @see MetalTheme
1978      */
1979     public static ColorUIResource getHighlightedTextColor() { return getCurrentTheme().getHighlightedTextColor(); }
1980 
1981     /**
1982      * Returns the window background color of the current theme. This is a
1983      * cover method for {@code getCurrentTheme().getWindowBackground()}.
1984      *
1985      * @return the window background color
1986      *
1987      * @see MetalTheme
1988      */
1989     public static ColorUIResource getWindowBackground() { return getCurrentTheme().getWindowBackground(); }
1990 
1991     /**
1992      * Returns the window title background color of the current
1993      * theme. This is a cover method for {@code
1994      * getCurrentTheme().getWindowTitleBackground()}.
1995      *
1996      * @return the window title background color
1997      *
1998      * @see MetalTheme
1999      */
2000     public static ColorUIResource getWindowTitleBackground() { return getCurrentTheme().getWindowTitleBackground(); }
2001 
2002     /**
2003      * Returns the window title foreground color of the current
2004      * theme. This is a cover method for {@code
2005      * getCurrentTheme().getWindowTitleForeground()}.
2006      *
2007      * @return the window title foreground color
2008      *
2009      * @see MetalTheme
2010      */
2011     public static ColorUIResource getWindowTitleForeground() { return getCurrentTheme().getWindowTitleForeground(); }
2012 
2013     /**
2014      * Returns the window title inactive background color of the current
2015      * theme. This is a cover method for {@code
2016      * getCurrentTheme().getWindowTitleInactiveBackground()}.
2017      *
2018      * @return the window title inactive background color
2019      *
2020      * @see MetalTheme
2021      */
2022     public static ColorUIResource getWindowTitleInactiveBackground() { return getCurrentTheme().getWindowTitleInactiveBackground(); }
2023 
2024     /**
2025      * Returns the window title inactive foreground color of the current
2026      * theme. This is a cover method for {@code
2027      * getCurrentTheme().getWindowTitleInactiveForeground()}.
2028      *
2029      * @return the window title inactive foreground color
2030      *
2031      * @see MetalTheme
2032      */
2033     public static ColorUIResource getWindowTitleInactiveForeground() { return getCurrentTheme().getWindowTitleInactiveForeground(); }
2034 
2035     /**
2036      * Returns the menu background color of the current theme. This is
2037      * a cover method for {@code getCurrentTheme().getMenuBackground()}.
2038      *
2039      * @return the menu background color
2040      *
2041      * @see MetalTheme
2042      */
2043     public static ColorUIResource getMenuBackground() { return getCurrentTheme().getMenuBackground(); }
2044 
2045     /**
2046      * Returns the menu foreground color of the current theme. This is
2047      * a cover method for {@code getCurrentTheme().getMenuForeground()}.
2048      *
2049      * @return the menu foreground color
2050      *
2051      * @see MetalTheme
2052      */
2053     public static ColorUIResource getMenuForeground() { return getCurrentTheme().getMenuForeground(); }
2054 
2055     /**
2056      * Returns the menu selected background color of the current theme. This is
2057      * a cover method for
2058      * {@code getCurrentTheme().getMenuSelectedBackground()}.
2059      *
2060      * @return the menu selected background color
2061      *
2062      * @see MetalTheme
2063      */
2064     public static ColorUIResource getMenuSelectedBackground() { return getCurrentTheme().getMenuSelectedBackground(); }
2065 
2066     /**
2067      * Returns the menu selected foreground color of the current theme. This is
2068      * a cover method for
2069      * {@code getCurrentTheme().getMenuSelectedForeground()}.
2070      *
2071      * @return the menu selected foreground color
2072      *
2073      * @see MetalTheme
2074      */
2075     public static ColorUIResource getMenuSelectedForeground() { return getCurrentTheme().getMenuSelectedForeground(); }
2076 
2077     /**
2078      * Returns the menu disabled foreground color of the current theme. This is
2079      * a cover method for
2080      * {@code getCurrentTheme().getMenuDisabledForeground()}.
2081      *
2082      * @return the menu disabled foreground color
2083      *
2084      * @see MetalTheme
2085      */
2086     public static ColorUIResource getMenuDisabledForeground() { return getCurrentTheme().getMenuDisabledForeground(); }
2087 
2088     /**
2089      * Returns the separator background color of the current theme. This is
2090      * a cover method for {@code getCurrentTheme().getSeparatorBackground()}.
2091      *
2092      * @return the separator background color
2093      *
2094      * @see MetalTheme
2095      */
2096     public static ColorUIResource getSeparatorBackground() { return getCurrentTheme().getSeparatorBackground(); }
2097 
2098     /**
2099      * Returns the separator foreground color of the current theme. This is
2100      * a cover method for {@code getCurrentTheme().getSeparatorForeground()}.
2101      *
2102      * @return the separator foreground color
2103      *
2104      * @see MetalTheme
2105      */
2106     public static ColorUIResource getSeparatorForeground() { return getCurrentTheme().getSeparatorForeground(); }
2107 
2108     /**
2109      * Returns the accelerator foreground color of the current theme. This is
2110      * a cover method for {@code getCurrentTheme().getAcceleratorForeground()}.
2111      *
2112      * @return the separator accelerator foreground color
2113      *
2114      * @see MetalTheme
2115      */
2116     public static ColorUIResource getAcceleratorForeground() { return getCurrentTheme().getAcceleratorForeground(); }
2117 
2118     /**
2119      * Returns the accelerator selected foreground color of the
2120      * current theme. This is a cover method for {@code
2121      * getCurrentTheme().getAcceleratorSelectedForeground()}.
2122      *
2123      * @return the accelerator selected foreground color
2124      *
2125      * @see MetalTheme
2126      */
2127     public static ColorUIResource getAcceleratorSelectedForeground() { return getCurrentTheme().getAcceleratorSelectedForeground(); }
2128 
2129 
2130     /**
2131      * Returns a {@code LayoutStyle} implementing the Java look and feel
2132      * design guidelines as specified at
2133      * <a href="http://www.oracle.com/technetwork/java/hig-136467.html">http://www.oracle.com/technetwork/java/hig-136467.html</a>.
2134      *
2135      * @return LayoutStyle implementing the Java look and feel design
2136      *         guidelines
2137      * @since 1.6
2138      */
2139     public LayoutStyle getLayoutStyle() {
2140         return MetalLayoutStyle.INSTANCE;
2141     }
2142 
2143 
2144     /**
2145      * FontActiveValue redirects to the appropriate metal theme method.
2146      */
2147     private static class FontActiveValue implements UIDefaults.ActiveValue {
2148         private int type;
2149         private MetalTheme theme;
2150 
2151         FontActiveValue(MetalTheme theme, int type) {
2152             this.theme = theme;
2153             this.type = type;
2154         }
2155 
2156         public Object createValue(UIDefaults table) {
2157             Object value = null;
2158             switch (type) {
2159             case MetalTheme.CONTROL_TEXT_FONT:
2160                 value = theme.getControlTextFont();
2161                 break;
2162             case MetalTheme.SYSTEM_TEXT_FONT:
2163                 value = theme.getSystemTextFont();
2164                 break;
2165             case MetalTheme.USER_TEXT_FONT:
2166                 value = theme.getUserTextFont();
2167                 break;
2168             case MetalTheme.MENU_TEXT_FONT:
2169                 value = theme.getMenuTextFont();
2170                 break;
2171             case MetalTheme.WINDOW_TITLE_FONT:
2172                 value = theme.getWindowTitleFont();
2173                 break;
2174             case MetalTheme.SUB_TEXT_FONT:
2175                 value = theme.getSubTextFont();
2176                 break;
2177             }
2178             return value;
2179         }
2180     }
2181 
2182     static ReferenceQueue<LookAndFeel> queue = new ReferenceQueue<LookAndFeel>();
2183 
2184     static void flushUnreferenced() {
2185         AATextListener aatl;
2186         while ((aatl = (AATextListener)queue.poll()) != null) {
2187             aatl.dispose();
2188         }
2189     }
2190 
2191     static class AATextListener
2192         extends WeakReference<LookAndFeel> implements PropertyChangeListener {
2193 
2194         private String key = SunToolkit.DESKTOPFONTHINTS;
2195 
2196         AATextListener(LookAndFeel laf) {
2197             super(laf, queue);
2198             Toolkit tk = Toolkit.getDefaultToolkit();
2199             tk.addPropertyChangeListener(key, this);
2200         }
2201 
2202         public void propertyChange(PropertyChangeEvent pce) {
2203             LookAndFeel laf = get();
2204             if (laf == null || laf != UIManager.getLookAndFeel()) {
2205                 dispose();
2206                 return;
2207             }
2208             UIDefaults defaults = UIManager.getLookAndFeelDefaults();
2209             boolean lafCond = SwingUtilities2.isLocalDisplay();
2210             SwingUtilities2.putAATextInfo(lafCond, defaults);
2211             updateUI();
2212         }
2213 
2214         void dispose() {
2215             Toolkit tk = Toolkit.getDefaultToolkit();
2216             tk.removePropertyChangeListener(key, this);
2217         }
2218 
2219         /**
2220          * Updates the UI of the passed in window and all its children.
2221          */
2222         private static void updateWindowUI(Window window) {
2223             SwingUtilities.updateComponentTreeUI(window);
2224             Window ownedWins[] = window.getOwnedWindows();
2225             for (Window w : ownedWins) {
2226                 updateWindowUI(w);
2227             }
2228         }
2229 
2230         /**
2231          * Updates the UIs of all the known Frames.
2232          */
2233         private static void updateAllUIs() {
2234             Frame appFrames[] = Frame.getFrames();
2235             for (Frame frame : appFrames) {
2236                 updateWindowUI(frame);
2237             }
2238         }
2239 
2240         /**
2241          * Indicates if an updateUI call is pending.
2242          */
2243         private static boolean updatePending;
2244 
2245         /**
2246          * Sets whether or not an updateUI call is pending.
2247          */
2248         private static synchronized void setUpdatePending(boolean update) {
2249             updatePending = update;
2250         }
2251 
2252         /**
2253          * Returns true if a UI update is pending.
2254          */
2255         private static synchronized boolean isUpdatePending() {
2256             return updatePending;
2257     }
2258 
2259         protected void updateUI() {
2260             if (!isUpdatePending()) {
2261                 setUpdatePending(true);
2262                 Runnable uiUpdater = new Runnable() {
2263                         public void run() {
2264                             updateAllUIs();
2265                             setUpdatePending(false);
2266                         }
2267                     };
2268                 SwingUtilities.invokeLater(uiUpdater);
2269             }
2270         }
2271     }
2272 
2273     // From the JLF Design Guidelines:
2274     // http://www.oracle.com/technetwork/java/jlf-135985.html
2275     @SuppressWarnings("fallthrough")
2276     private static class MetalLayoutStyle extends DefaultLayoutStyle {
2277         private static MetalLayoutStyle INSTANCE = new MetalLayoutStyle();
2278 
2279         @Override
2280         public int getPreferredGap(JComponent component1,
2281                 JComponent component2, ComponentPlacement type, int position,
2282                 Container parent) {
2283             // Checks args
2284             super.getPreferredGap(component1, component2, type, position,
2285                                   parent);
2286 
2287             int offset = 0;
2288 
2289             switch(type) {
2290             case INDENT:
2291                 // Metal doesn't spec this.
2292                 if (position == SwingConstants.EAST ||
2293                         position == SwingConstants.WEST) {
2294                     int indent = getIndent(component1, position);
2295                     if (indent > 0) {
2296                         return indent;
2297                     }
2298                     return 12;
2299                 }
2300                 // Fall through to related.
2301             case RELATED:
2302                 if (component1.getUIClassID() == "ToggleButtonUI" &&
2303                         component2.getUIClassID() == "ToggleButtonUI") {
2304                     ButtonModel sourceModel = ((JToggleButton)component1).
2305                             getModel();
2306                     ButtonModel targetModel = ((JToggleButton)component2).
2307                             getModel();
2308                     if ((sourceModel instanceof DefaultButtonModel) &&
2309                         (targetModel instanceof DefaultButtonModel) &&
2310                         (((DefaultButtonModel)sourceModel).getGroup() ==
2311                          ((DefaultButtonModel)targetModel).getGroup()) &&
2312                         ((DefaultButtonModel)sourceModel).getGroup() != null) {
2313                         // When toggle buttons are exclusive (that is,
2314                         // they form a radio button set), separate
2315                         // them with 2 pixels. This rule applies
2316                         // whether the toggle buttons appear in a
2317                         // toolbar or elsewhere in the interface.
2318                         // Note: this number does not appear to
2319                         // include any borders and so is not adjusted
2320                         // by the border of the toggle button
2321                         return 2;
2322                     }
2323                     // When toggle buttons are independent (like
2324                     // checkboxes) and used outside a toolbar,
2325                     // separate them with 5 pixels.
2326                     if (usingOcean()) {
2327                         return 6;
2328                     }
2329                     return 5;
2330                 }
2331                 offset = 6;
2332                 break;
2333             case UNRELATED:
2334                 offset = 12;
2335                 break;
2336             }
2337             if (isLabelAndNonlabel(component1, component2, position)) {
2338                 // Insert 12 pixels between the trailing edge of a
2339                 // label and any associated components. Insert 12
2340                 // pixels between the trailing edge of a label and the
2341                 // component it describes when labels are
2342                 // right-aligned. When labels are left-aligned, insert
2343                 // 12 pixels between the trailing edge of the longest
2344                 // label and its associated component
2345                 return getButtonGap(component1, component2, position,
2346                                     offset + 6);
2347             }
2348             return getButtonGap(component1, component2, position, offset);
2349         }
2350 
2351         @Override
2352         public int getContainerGap(JComponent component, int position,
2353                                    Container parent) {
2354             super.getContainerGap(component, position, parent);
2355             // Include 11 pixels between the bottom and right
2356             // borders of a dialog box and its command
2357             // buttons. (To the eye, the 11-pixel spacing appears
2358             // to be 12 pixels because the white borders on the
2359             // lower and right edges of the button components are
2360             // not visually significant.)
2361             // NOTE: this last text was designed with Steel in mind,
2362             // not Ocean.
2363             //
2364             // Insert 12 pixels between the edges of the panel and the
2365             // titled border. Insert 11 pixels between the top of the
2366             // title and the component above the titled border. Insert 12
2367             // pixels between the bottom of the title and the top of the
2368             // first label in the panel. Insert 11 pixels between
2369             // component groups and between the bottom of the last
2370             // component and the lower border.
2371             return getButtonGap(component, position, 12 -
2372                                 getButtonAdjustment(component, position));
2373         }
2374 
2375         @Override
2376         protected int getButtonGap(JComponent source, JComponent target,
2377                                    int position, int offset) {
2378             offset = super.getButtonGap(source, target, position, offset);
2379             if (offset > 0) {
2380                 int buttonAdjustment = getButtonAdjustment(source, position);
2381                 if (buttonAdjustment == 0) {
2382                     buttonAdjustment = getButtonAdjustment(
2383                             target, flipDirection(position));
2384                 }
2385                 offset -= buttonAdjustment;
2386             }
2387             if (offset < 0) {
2388                 return 0;
2389             }
2390             return offset;
2391         }
2392 
2393         private int getButtonAdjustment(JComponent source, int edge) {
2394             String classID = source.getUIClassID();
2395             if (classID == "ButtonUI" || classID == "ToggleButtonUI") {
2396                 if (!usingOcean() && (edge == SwingConstants.EAST ||
2397                                       edge == SwingConstants.SOUTH)) {
2398                     if (source.getBorder() instanceof UIResource) {
2399                         return 1;
2400                     }
2401                 }
2402             }
2403             else if (edge == SwingConstants.SOUTH) {
2404                 if ((classID == "RadioButtonUI" || classID == "CheckBoxUI") &&
2405                         !usingOcean()) {
2406                     return 1;
2407                 }
2408             }
2409             return 0;
2410         }
2411     }
2412 }