1 /*
   2  * Copyright (c) 1997, 2006, 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;
  27 
  28 import java.awt.Font;
  29 import java.awt.event.InputEvent;
  30 import java.awt.event.KeyEvent;
  31 import java.awt.Color;
  32 import java.awt.Component;
  33 import java.awt.SystemColor;
  34 import java.awt.Toolkit;
  35 import sun.awt.SunToolkit;
  36 
  37 import javax.swing.text.*;
  38 import javax.swing.border.*;
  39 import javax.swing.plaf.*;
  40 
  41 import java.net.URL;
  42 import sun.swing.SwingUtilities2;
  43 import sun.swing.DefaultLayoutStyle;
  44 import sun.swing.ImageIconUIResource;
  45 
  46 import java.util.StringTokenizer;
  47 
  48 
  49 /**
  50  * {@code LookAndFeel}, as the name implies, encapsulates a look and
  51  * feel. Beyond installing a look and feel most developers never need to
  52  * interact directly with {@code LookAndFeel}. In general only developers
  53  * creating a custom look and feel need to concern themselves with this class.
  54  * <p>
  55  * Swing is built upon the foundation that each {@code JComponent}
  56  * subclass has an implementation of a specific {@code ComponentUI}
  57  * subclass. The {@code ComponentUI} is often referred to as "the ui",
  58  * "component ui", or "look and feel delegate". The {@code ComponentUI}
  59  * subclass is responsible for providing the look and feel specific
  60  * functionality of the component. For example, {@code JTree} requires
  61  * an implementation of the {@code ComponentUI} subclass {@code
  62  * TreeUI}. The implementation of the specific {@code
  63  * ComponentUI} subclass is provided by the {@code LookAndFeel}. Each
  64  * {@code JComponent} subclass identifies the {@code ComponentUI}
  65  * subclass it requires by way of the {@code JComponent} method {@code
  66  * getUIClassID}.
  67  * <p>
  68  * Each {@code LookAndFeel} implementation must provide
  69  * an implementation of the appropriate {@code ComponentUI} subclass by
  70  * specifying a value for each of Swing's ui class ids in the {@code
  71  * UIDefaults} object returned from {@code getDefaults}. For example,
  72  * {@code BasicLookAndFeel} uses {@code BasicTreeUI} as the concrete
  73  * implementation for {@code TreeUI}. This is accomplished by {@code
  74  * BasicLookAndFeel} providing the key-value pair {@code
  75  * "TreeUI"-"javax.swing.plaf.basic.BasicTreeUI"}, in the
  76  * {@code UIDefaults} returned from {@code getDefaults}. Refer to
  77  * {@link UIDefaults#getUI(JComponent)} for defails on how the implementation
  78  * of the {@code ComponentUI} subclass is obtained.
  79  * <p>
  80  * When a {@code LookAndFeel} is installed the {@code UIManager} does
  81  * not check that an entry exists for all ui class ids. As such,
  82  * random exceptions will occur if the current look and feel has not
  83  * provided a value for a particular ui class id and an instance of
  84  * the {@code JComponent} subclass is created.
  85  *
  86  * <h2>Recommendations for Look and Feels</h2>
  87  *
  88  * As noted in {@code UIManager} each {@code LookAndFeel} has the opportunity
  89  * to provide a set of defaults that are layered in with developer and
  90  * system defaults. Some of Swing's components require the look and feel
  91  * to provide a specific set of defaults. These are documented in the
  92  * classes that require the specific default.
  93  *
  94  * <h3><a name="#defaultRecommendation">ComponentUIs and defaults</a></h2>
  95  *
  96  * All {@code ComponentUIs} typically need to set various properties
  97  * on the {@code JComponent} the {@code ComponentUI} is providing the
  98  * look and feel for. This is typically done when the {@code
  99  * ComponentUI} is installed on the {@code JComponent}. Setting a
 100  * property should only be done if the developer has not set the
 101  * property. For non-primitive values it is recommended that the
 102  * {@code ComponentUI} only change the property on the {@code
 103  * JComponent} if the current value is {@code null} or implements
 104  * {@code UIResource}. If the current value is {@code null} or
 105  * implements {@code UIResource} it indicates the property has not
 106  * been set by the developer, and the ui is free to change it.  For
 107  * example, {@code BasicButtonUI.installDefaults} only changes the
 108  * font on the {@code JButton} if the return value from {@code
 109  * button.getFont()} is {@code null} or implements {@code
 110  * UIResource}. On the other hand if {@code button.getFont()} returned
 111  * a {@code non-null} value that did not implement {@code UIResource}
 112  * then {@code BasicButtonUI.installDefaults} would not change the
 113  * {@code JButton}'s font.
 114  * <p>
 115  * For primitive values, such as {@code opaque}, the method {@code
 116  * installProperty} should be invoked.  {@code installProperty} only changes
 117  * the correspoding property if the value has not been changed by the
 118  * developer.
 119  * <p>
 120  * {@code ComponentUI} implementations should use the various install methods
 121  * provided by this class as they handle the necessary checking and install
 122  * the property using the recommended guidelines.
 123  * <p>
 124  * <h3><a name="exceptions"></a>Exceptions</h3>
 125  *
 126  * All of the install methods provided by {@code LookAndFeel} need to
 127  * access the defaults if the value of the property being changed is
 128  * {@code null} or a {@code UIResource}. For example, installing the
 129  * font does the following:
 130  * <pre>
 131  *   JComponent c;
 132  *   Font font = c.getFont();
 133  *   if (font == null || (font instanceof UIResource)) {
 134  *       c.setFont(UIManager.getFont("fontKey"));
 135  *   }
 136  * </pre>
 137  * If the font is {@code null} or a {@code UIResource}, the
 138  * defaults table is queried with the key {@code fontKey}. All of
 139  * {@code UIDefault's} get methods throw a {@code
 140  * NullPointerException} if passed in {@code null}. As such, unless
 141  * otherwise noted each of the various install methods of {@code
 142  * LookAndFeel} throw a {@code NullPointerException} if the current
 143  * value is {@code null} or a {@code UIResource} and the supplied
 144  * defaults key is {@code null}. In addition, unless otherwise specified
 145  * all of the {@code install} methods throw a {@code NullPointerException} if
 146  * a {@code null} component is passed in.
 147  *
 148  * @author Tom Ball
 149  * @author Hans Muller
 150  */
 151 public abstract class LookAndFeel
 152 {
 153 
 154     /**
 155      * Convenience method for setting a component's foreground
 156      * and background color properties with values from the
 157      * defaults.  The properties are only set if the current
 158      * value is either {@code null} or a {@code UIResource}.
 159      *
 160      * @param c component to set the colors on
 161      * @param defaultBgName key for the background
 162      * @param defaultFgName key for the foreground
 163      *
 164      * @see #installColorsAndFont
 165      * @see UIManager#getColor
 166      * @throws NullPointerException as described in
 167      *         <a href="#exceptions">exceptions</a>
 168      */
 169     public static void installColors(JComponent c,
 170                                      String defaultBgName,
 171                                      String defaultFgName)
 172     {
 173         Color bg = c.getBackground();
 174         if (bg == null || bg instanceof UIResource) {
 175             c.setBackground(UIManager.getColor(defaultBgName));
 176         }
 177 
 178         Color fg = c.getForeground();
 179         if (fg == null || fg instanceof UIResource) {
 180             c.setForeground(UIManager.getColor(defaultFgName));
 181         }
 182     }
 183 
 184 
 185     /**
 186      * Convenience method for setting a component's foreground,
 187      * background and font properties with values from the
 188      * defaults.  The properties are only set if the current
 189      * value is either {@code null} or a {@code UIResource}.
 190      *
 191      * @param c component set to the colors and font on
 192      * @param defaultBgName key for the background
 193      * @param defaultFgName key for the foreground
 194      * @param defaultFontName key for the font
 195      * @throws NullPointerException as described in
 196      *         <a href="#exceptions">exceptions</a>
 197      *
 198      * @see #installColors
 199      * @see UIManager#getColor
 200      * @see UIManager#getFont
 201      */
 202     public static void installColorsAndFont(JComponent c,
 203                                          String defaultBgName,
 204                                          String defaultFgName,
 205                                          String defaultFontName) {
 206         Font f = c.getFont();
 207         if (f == null || f instanceof UIResource) {
 208             c.setFont(UIManager.getFont(defaultFontName));
 209         }
 210 
 211         installColors(c, defaultBgName, defaultFgName);
 212     }
 213 
 214 
 215     /**
 216      * Convenience method for setting a component's border property with
 217      * a value from the defaults. The border is only set if the border is
 218      * {@code null} or an instance of {@code UIResource}.
 219      *
 220      * @param c component to set the border on
 221      * @param defaultBorderName key specifying the border
 222      * @throws NullPointerException as described in
 223      *         <a href="#exceptions">exceptions</a>
 224      */
 225     public static void installBorder(JComponent c, String defaultBorderName) {
 226         Border b = c.getBorder();
 227         if (b == null || b instanceof UIResource) {
 228             c.setBorder(UIManager.getBorder(defaultBorderName));
 229         }
 230     }
 231 
 232 
 233     /**
 234      * Convenience method for uninstalling a border. If the border of
 235      * the component is a {@code UIResource}, it is set to {@code
 236      * null}.
 237      *
 238      * @param c component to uninstall the border on
 239      * @throws NullPointerException if {@code c} is {@code null}
 240      */
 241     public static void uninstallBorder(JComponent c) {
 242         if (c.getBorder() instanceof UIResource) {
 243             c.setBorder(null);
 244         }
 245     }
 246 
 247     /**
 248      * Convenience method for installing a property with the specified name
 249      * and value on a component if that property has not already been set
 250      * by the developer.  This method is intended to be used by
 251      * ui delegate instances that need to specify a default value for a
 252      * property of primitive type (boolean, int, ..), but do not wish
 253      * to override a value set by the client.  Since primitive property
 254      * values cannot be wrapped with the {@code UIResource} marker, this method
 255      * uses private state to determine whether the property has been set
 256      * by the client.
 257      *
 258      * @throws IllegalArgumentException if the specified property is not
 259      *         one which can be set using this method
 260      * @throws ClassCastException if the property value has not been set
 261      *         by the developer and the type does not match the property's type
 262      * @throws NullPointerException if {@code c} is {@code null}, or the
 263      *         named property has not been set by the developer and
 264      *         {@code propertyValue} is {@code null}
 265      * @param c target component to set the property on
 266      * @param propertyName name of the property to set
 267      * @param propertyValue value of the property
 268      * @since 1.5
 269      */
 270     public static void installProperty(JComponent c,
 271                                        String propertyName, Object propertyValue) {
 272         // this is a special case because the JPasswordField's ancestor heirarchy
 273         // includes a class outside of javax.swing, thus we cannot call setUIProperty
 274         // directly.
 275         if (SunToolkit.isInstanceOf(c, "javax.swing.JPasswordField")) {
 276             if (!((JPasswordField)c).customSetUIProperty(propertyName, propertyValue)) {
 277                 c.setUIProperty(propertyName, propertyValue);
 278             }
 279         } else {
 280             c.setUIProperty(propertyName, propertyValue);
 281         }
 282     }
 283 
 284     /**
 285      * Convenience method for building an array of {@code
 286      * KeyBindings}. While this method is not deprecated, developers
 287      * should instead use {@code ActionMap} and {@code InputMap} for
 288      * supplying key bindings.
 289      * <p>
 290      * This method returns an array of {@code KeyBindings}, one for each
 291      * alternating {@code key-action} pair in {@code keyBindingList}.
 292      * A {@code key} can either be a {@code String} in the format
 293      * specified by the <code>KeyStroke.getKeyStroke</code> method, or
 294      * a {@code KeyStroke}. The {@code action} part of the pair is a
 295      * {@code String} that corresponds to the name of the {@code
 296      * Action}.
 297      * <p>
 298      * The following example illustrates creating a {@code KeyBinding} array
 299      * from six alternating {@code key-action} pairs:
 300      * <pre>
 301      *  JTextComponent.KeyBinding[] multilineBindings = makeKeyBindings( new Object[] {
 302      *          "UP", DefaultEditorKit.upAction,
 303      *        "DOWN", DefaultEditorKit.downAction,
 304      *     "PAGE_UP", DefaultEditorKit.pageUpAction,
 305      *   "PAGE_DOWN", DefaultEditorKit.pageDownAction,
 306      *       "ENTER", DefaultEditorKit.insertBreakAction,
 307      *         "TAB", DefaultEditorKit.insertTabAction
 308      *  });
 309      * </pre>
 310      * If {@code keyBindingList's} length is odd, the last element is
 311      * ignored.
 312      * <p>
 313      * Supplying a {@code null} value for either the {@code key} or
 314      * {@code action} part of the {@code key-action} pair results in
 315      * creating a {@code KeyBinding} with the corresponding value
 316      * {@code null}. As other parts of Swing's expect {@code non-null} values
 317      * in a {@code KeyBinding}, you should avoid supplying {@code null} as
 318      * either the {@code key} or {@code action} part of the {@code key-action}
 319      * pair.
 320      *
 321      * @param keyBindingList an array of {@code key-action} pairs
 322      * @return an array of {@code KeyBindings}
 323      * @throws NullPointerException if {@code keyBindingList} is {@code null}
 324      * @throws ClassCastException if the {@code key} part of the pair is
 325      *         not a {@code KeyStroke} or {@code String}, or the
 326      *         {@code action} part of the pair is not a {@code String}
 327      * @see ActionMap
 328      * @see InputMap
 329      * @see KeyStroke#getKeyStroke
 330      */
 331     public static JTextComponent.KeyBinding[] makeKeyBindings(Object[] keyBindingList)
 332     {
 333         JTextComponent.KeyBinding[] rv = new JTextComponent.KeyBinding[keyBindingList.length / 2];
 334 
 335         for(int i = 0; i < rv.length; i ++) {
 336             Object o = keyBindingList[2 * i];
 337             KeyStroke keystroke = (o instanceof KeyStroke)
 338                 ? (KeyStroke) o
 339                 : KeyStroke.getKeyStroke((String) o);
 340             String action = (String) keyBindingList[2 * i + 1];
 341             rv[i] = new JTextComponent.KeyBinding(keystroke, action);
 342         }
 343 
 344         return rv;
 345     }
 346 
 347     /**
 348      * Creates a {@code InputMapUIResource} from <code>keys</code>. This is
 349      * a convenience method for creating a new {@code InputMapUIResource},
 350      * invoking {@code loadKeyBindings(map, keys)}, and returning the
 351      * {@code InputMapUIResource}.
 352      *
 353      * @param keys alternating pairs of {@code keystroke-action key}
 354      *        pairs as described in {@link #loadKeyBindings}
 355      * @return newly created and populated {@code InputMapUIResource}
 356      * @see #loadKeyBindings
 357      *
 358      * @since 1.3
 359      */
 360     public static InputMap makeInputMap(Object[] keys) {
 361         InputMap retMap = new InputMapUIResource();
 362         loadKeyBindings(retMap, keys);
 363         return retMap;
 364     }
 365 
 366     /**
 367      * Creates a {@code ComponentInputMapUIResource} from
 368      * <code>keys</code>. This is a convenience method for creating a
 369      * new {@code ComponentInputMapUIResource}, invoking {@code
 370      * loadKeyBindings(map, keys)}, and returning the {@code
 371      * ComponentInputMapUIResource}.
 372      *
 373      * @param c component to create the {@code ComponentInputMapUIResource}
 374      *          with
 375      * @param keys alternating pairs of {@code keystroke-action key}
 376      *        pairs as described in {@link #loadKeyBindings}
 377      * @return newly created and populated {@code InputMapUIResource}
 378      * @throws IllegalArgumentException if {@code c} is {@code null}
 379      *
 380      * @see #loadKeyBindings
 381      * @see ComponentInputMapUIResource
 382      *
 383      * @since 1.3
 384      */
 385     public static ComponentInputMap makeComponentInputMap(JComponent c,
 386                                                           Object[] keys) {
 387         ComponentInputMap retMap = new ComponentInputMapUIResource(c);
 388         loadKeyBindings(retMap, keys);
 389         return retMap;
 390     }
 391 
 392 
 393     /**
 394      * Populates an {@code InputMap} with the specified bindings.
 395      * The bindings are supplied as a list of alternating
 396      * {@code keystroke-action key} pairs. The {@code keystroke} is either
 397      * an instance of {@code KeyStroke}, or a {@code String}
 398      * that identifies the {@code KeyStroke} for the binding. Refer
 399      * to {@code KeyStroke.getKeyStroke(String)} for the specific
 400      * format. The {@code action key} part of the pair is the key
 401      * registered in the {@code InputMap} for the {@code KeyStroke}.
 402      * <p>
 403      * The following illustrates loading an {@code InputMap} with two
 404      * {@code key-action} pairs:
 405      * <pre>
 406      *   LookAndFeel.loadKeyBindings(inputMap, new Object[] {
 407      *     "control X", "cut",
 408      *     "control V", "paste"
 409      *   });
 410      * </pre>
 411      * <p>
 412      * Supplying a {@code null} list of bindings ({@code keys}) does not
 413      * change {@code retMap} in any way.
 414      * <p>
 415      * Specifying a {@code null} {@code action key} results in
 416      * removing the {@code keystroke's} entry from the {@code InputMap}.
 417      * A {@code null} {@code keystroke} is ignored.
 418      *
 419      * @param retMap {@code InputMap} to add the {@code key-action}
 420      *               pairs to
 421      * @param keys bindings to add to {@code retMap}
 422      * @throws NullPointerException if {@code keys} is
 423      *         {@code non-null}, not empty, and {@code retMap} is
 424      *         {@code null}
 425      *
 426      * @see KeyStroke#getKeyStroke(String)
 427      * @see InputMap
 428      *
 429      * @since 1.3
 430      */
 431     public static void loadKeyBindings(InputMap retMap, Object[] keys) {
 432         if (keys != null) {
 433             for (int counter = 0, maxCounter = keys.length;
 434                  counter < maxCounter; counter++) {
 435                 Object keyStrokeO = keys[counter++];
 436                 KeyStroke ks = (keyStrokeO instanceof KeyStroke) ?
 437                                 (KeyStroke)keyStrokeO :
 438                                 KeyStroke.getKeyStroke((String)keyStrokeO);
 439                 retMap.put(ks, keys[counter]);
 440             }
 441         }
 442     }
 443 
 444     /**
 445      * Creates and returns a {@code UIDefault.LazyValue} that loads an
 446      * image. The returned value is an implementation of {@code
 447      * UIDefaults.LazyValue}. When {@code createValue} is invoked on
 448      * the returned object, the image is loaded. If the image is {@code
 449      * non-null}, it is then wrapped in an {@code Icon} that implements {@code
 450      * UIResource}. The image is loaded using {@code
 451      * Class.getResourceAsStream(gifFile)}.
 452      * <p>
 453      * This method does not check the arguments in any way. It is
 454      * strongly recommended that {@code non-null} values are supplied else
 455      * exceptions may occur when {@code createValue} is invoked on the
 456      * returned object.
 457      *
 458      * @param baseClass {@code Class} used to load the resource
 459      * @param gifFile path to the image to load
 460      * @return a {@code UIDefaults.LazyValue}; when resolved the
 461      *         {@code LazyValue} loads the specified image
 462      * @see UIDefaults.LazyValue
 463      * @see Icon
 464      * @see Class#getResourceAsStream(String)
 465      */
 466     public static Object makeIcon(final Class<?> baseClass, final String gifFile) {
 467         return SwingUtilities2.makeIcon(baseClass, baseClass, gifFile);
 468     }
 469 
 470     /**
 471      * Returns the <code>LayoutStyle</code> for this look
 472      * and feel.  This never returns {@code null}.
 473      * <p>
 474      * You generally don't use the <code>LayoutStyle</code> from
 475      * the look and feel, instead use the <code>LayoutStyle</code>
 476      * method <code>getInstance</code>.
 477      *
 478      * @see LayoutStyle#getInstance
 479      * @return the <code>LayoutStyle</code> for this look and feel
 480      * @since 1.6
 481      */
 482     public LayoutStyle getLayoutStyle() {
 483         return DefaultLayoutStyle.getInstance();
 484     }
 485 
 486     /**
 487      * Invoked when the user attempts an invalid operation,
 488      * such as pasting into an uneditable <code>JTextField</code>
 489      * that has focus. The default implementation beeps. Subclasses
 490      * that wish different behavior should override this and provide
 491      * the additional feedback.
 492      *
 493      * @param component the <code>Component</code> the error occurred in,
 494      *                  may be <code>null</code>
 495      *                  indicating the error condition is not directly
 496      *                  associated with a <code>Component</code>
 497      * @since 1.4
 498      */
 499     public void provideErrorFeedback(Component component) {
 500         Toolkit toolkit = null;
 501         if (component != null) {
 502             toolkit = component.getToolkit();
 503         } else {
 504             toolkit = Toolkit.getDefaultToolkit();
 505         }
 506         toolkit.beep();
 507     } // provideErrorFeedback()
 508 
 509     /**
 510      * Returns the value of the specified system desktop property by
 511      * invoking <code>Toolkit.getDefaultToolkit().getDesktopProperty()</code>.
 512      * If the value of the specified property is {@code null},
 513      * {@code fallbackValue} is returned.
 514      *
 515      * @param systemPropertyName the name of the system desktop property being queried
 516      * @param fallbackValue the object to be returned as the value if the system value is null
 517      * @return the current value of the desktop property
 518      *
 519      * @see java.awt.Toolkit#getDesktopProperty
 520      *
 521      * @since 1.4
 522      */
 523     public static Object getDesktopPropertyValue(String systemPropertyName, Object fallbackValue) {
 524         Object value = Toolkit.getDefaultToolkit().getDesktopProperty(systemPropertyName);
 525         if (value == null) {
 526             return fallbackValue;
 527         } else if (value instanceof Color) {
 528             return new ColorUIResource((Color)value);
 529         } else if (value instanceof Font) {
 530             return new FontUIResource((Font)value);
 531         }
 532         return value;
 533     }
 534 
 535     /**
 536      * Returns an <code>Icon</code> with a disabled appearance.
 537      * This method is used to generate a disabled <code>Icon</code> when
 538      * one has not been specified.  For example, if you create a
 539      * <code>JButton</code> and only specify an <code>Icon</code> via
 540      * <code>setIcon</code> this method will be called to generate the
 541      * disabled <code>Icon</code>. If {@code null} is passed as
 542      * <code>icon</code> this method returns {@code null}.
 543      * <p>
 544      * Some look and feels might not render the disabled {@code Icon}, in which
 545      * case they will ignore this.
 546      *
 547      * @param component {@code JComponent} that will display the {@code Icon},
 548      *         may be {@code null}
 549      * @param icon {@code Icon} to generate the disabled icon from
 550      * @return disabled {@code Icon}, or {@code null} if a suitable
 551      *         {@code Icon} can not be generated
 552      * @since 1.5
 553      */
 554     public Icon getDisabledIcon(JComponent component, Icon icon) {
 555         if (icon instanceof ImageIcon) {
 556             return new ImageIconUIResource(GrayFilter.
 557                    createDisabledImage(((ImageIcon)icon).getImage()));
 558         }
 559         return null;
 560     }
 561 
 562     /**
 563      * Returns an <code>Icon</code> for use by disabled
 564      * components that are also selected. This method is used to generate an
 565      * <code>Icon</code> for components that are in both the disabled and
 566      * selected states but do not have a specific <code>Icon</code> for this
 567      * state.  For example, if you create a <code>JButton</code> and only
 568      * specify an <code>Icon</code> via <code>setIcon</code> this method
 569      * will be called to generate the disabled and selected
 570      * <code>Icon</code>. If {@code null} is passed as <code>icon</code> this
 571      * methods returns {@code null}.
 572      * <p>
 573      * Some look and feels might not render the disabled and selected
 574      * {@code Icon}, in which case they will ignore this.
 575      *
 576      * @param component {@code JComponent} that will display the {@code Icon},
 577      *        may be {@code null}
 578      * @param icon {@code Icon} to generate disabled and selected icon from
 579      * @return disabled and selected icon, or {@code null} if a suitable
 580      *         {@code Icon} can not be generated.
 581      * @since 1.5
 582      */
 583     public Icon getDisabledSelectedIcon(JComponent component, Icon icon) {
 584         return getDisabledIcon(component, icon);
 585     }
 586 
 587     /**
 588      * Return a short string that identifies this look and feel, e.g.
 589      * "CDE/Motif".  This string should be appropriate for a menu item.
 590      * Distinct look and feels should have different names, e.g.
 591      * a subclass of MotifLookAndFeel that changes the way a few components
 592      * are rendered should be called "CDE/Motif My Way"; something
 593      * that would be useful to a user trying to select a L&F from a list
 594      * of names.
 595      *
 596      * @return short identifier for the look and feel
 597      */
 598     public abstract String getName();
 599 
 600 
 601     /**
 602      * Return a string that identifies this look and feel.  This string
 603      * will be used by applications/services that want to recognize
 604      * well known look and feel implementations.  Presently
 605      * the well known names are "Motif", "Windows", "Mac", "Metal".  Note
 606      * that a LookAndFeel derived from a well known superclass
 607      * that doesn't make any fundamental changes to the look or feel
 608      * shouldn't override this method.
 609      *
 610      * @return identifier for the look and feel
 611      */
 612     public abstract String getID();
 613 
 614 
 615     /**
 616      * Return a one line description of this look and feel implementation,
 617      * e.g. "The CDE/Motif Look and Feel".   This string is intended for
 618      * the user, e.g. in the title of a window or in a ToolTip message.
 619      *
 620      * @return short description for the look and feel
 621      */
 622     public abstract String getDescription();
 623 
 624 
 625     /**
 626      * Returns {@code true} if the <code>LookAndFeel</code> returned
 627      * <code>RootPaneUI</code> instances support providing {@code Window}
 628      * decorations in a <code>JRootPane</code>.
 629      * <p>
 630      * The default implementation returns {@code false}, subclasses that
 631      * support {@code Window} decorations should override this and return
 632      * {@code true}.
 633      *
 634      * @return {@code true} if the {@code RootPaneUI} instances created by
 635      *         this look and feel support client side decorations
 636      * @see JDialog#setDefaultLookAndFeelDecorated
 637      * @see JFrame#setDefaultLookAndFeelDecorated
 638      * @see JRootPane#setWindowDecorationStyle
 639      * @since 1.4
 640      */
 641     public boolean getSupportsWindowDecorations() {
 642         return false;
 643     }
 644 
 645     /**
 646      * If the underlying platform has a "native" look and feel, and
 647      * this is an implementation of it, return {@code true}.  For
 648      * example, when the underlying platform is Solaris running CDE
 649      * a CDE/Motif look and feel implementation would return {@code
 650      * true}.
 651      *
 652      * @return {@code true} if this look and feel represents the underlying
 653      *         platform look and feel
 654      */
 655     public abstract boolean isNativeLookAndFeel();
 656 
 657 
 658     /**
 659      * Return {@code true} if the underlying platform supports and or permits
 660      * this look and feel.  This method returns {@code false} if the look
 661      * and feel depends on special resources or legal agreements that
 662      * aren't defined for the current platform.
 663      *
 664      *
 665      * @return {@code true} if this is a supported look and feel
 666      * @see UIManager#setLookAndFeel
 667      */
 668     public abstract boolean isSupportedLookAndFeel();
 669 
 670 
 671     /**
 672      * Initializes the look and feel. While this method is public,
 673      * it should only be invoked by the {@code UIManager} when a
 674      * look and feel is installed as the current look and feel. This
 675      * method is invoked before the {@code UIManager} invokes
 676      * {@code getDefaults}. This method is intended to perform any
 677      * initialization for the look and feel. Subclasses
 678      * should do any one-time setup they need here, rather than
 679      * in a static initializer, because look and feel class objects
 680      * may be loaded just to discover that {@code isSupportedLookAndFeel()}
 681      * returns {@code false}.
 682      *
 683      * @see #uninitialize
 684      * @see UIManager#setLookAndFeel
 685      */
 686     public void initialize() {
 687     }
 688 
 689 
 690     /**
 691      * Uninitializes the look and feel. While this method is public,
 692      * it should only be invoked by the {@code UIManager} when
 693      * the look and feel is uninstalled. For example,
 694      * {@code UIManager.setLookAndFeel} invokes this when the look and
 695      * feel is changed.
 696      * <p>
 697      * Subclasses may choose to free up some resources here.
 698      *
 699      * @see #initialize
 700      * @see UIManager#setLookAndFeel
 701      */
 702     public void uninitialize() {
 703     }
 704 
 705     /**
 706      * Returns the look and feel defaults. While this method is public,
 707      * it should only be invoked by the {@code UIManager} when the
 708      * look and feel is set as the current look and feel and after
 709      * {@code initialize} has been invoked.
 710      *
 711      * @return the look and feel defaults
 712      * @see #initialize
 713      * @see #uninitialize
 714      * @see UIManager#setLookAndFeel
 715      */
 716     public UIDefaults getDefaults() {
 717         return null;
 718     }
 719 
 720     /**
 721      * Returns a string that displays and identifies this
 722      * object's properties.
 723      *
 724      * @return a String representation of this object
 725      */
 726     public String toString() {
 727         return "[" + getDescription() + " - " + getClass().getName() + "]";
 728     }
 729 }