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