Home » openjdk-7 » javax » swing » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2009, 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   package javax.swing;
   26   
   27   import java.awt.Component;
   28   import java.awt.Font;
   29   import java.awt.Color;
   30   import java.awt.Insets;
   31   import java.awt.Dimension;
   32   import java.awt.KeyboardFocusManager;
   33   import java.awt.KeyEventPostProcessor;
   34   import java.awt.Toolkit;
   35   
   36   import java.awt.event.KeyEvent;
   37   
   38   import java.security.AccessController;
   39   
   40   import javax.swing.plaf.ComponentUI;
   41   import javax.swing.border.Border;
   42   
   43   import javax.swing.event.SwingPropertyChangeSupport;
   44   import java.beans.PropertyChangeListener;
   45   
   46   import java.io.Serializable;
   47   import java.io.File;
   48   import java.io.FileInputStream;
   49   
   50   import java.util.ArrayList;
   51   import java.util.Properties;
   52   import java.util.StringTokenizer;
   53   import java.util.Vector;
   54   import java.util.Locale;
   55   
   56   import sun.awt.SunToolkit;
   57   import sun.awt.OSInfo;
   58   import sun.security.action.GetPropertyAction;
   59   import sun.swing.SwingUtilities2;
   60   import java.lang.reflect.Method;
   61   import java.util.HashMap;
   62   import sun.awt.AppContext;
   63   import sun.awt.AWTAccessor;
   64   
   65   
   66   /**
   67    * {@code UIManager} manages the current look and feel, the set of
   68    * available look and feels, {@code PropertyChangeListeners} that
   69    * are notified when the look and feel changes, look and feel defaults, and
   70    * convenience methods for obtaining various default values.
   71    *
   72    * <h3>Specifying the look and feel</h3>
   73    *
   74    * The look and feel can be specified in two distinct ways: by
   75    * specifying the fully qualified name of the class for the look and
   76    * feel, or by creating an instance of {@code LookAndFeel} and passing
   77    * it to {@code setLookAndFeel}. The following example illustrates
   78    * setting the look and feel to the system look and feel:
   79    * <pre>
   80    *   UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
   81    * </pre>
   82    * The following example illustrates setting the look and feel based on
   83    * class name:
   84    * <pre>
   85    *   UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
   86    * </pre>
   87    * Once the look and feel has been changed it is imperative to invoke
   88    * {@code updateUI} on all {@code JComponents}. The method {@link
   89    * SwingUtilities#updateComponentTreeUI} makes it easy to apply {@code
   90    * updateUI} to a containment hierarchy. Refer to it for
   91    * details. The exact behavior of not invoking {@code
   92    * updateUI} after changing the look and feel is
   93    * unspecified. It is very possible to receive unexpected exceptions,
   94    * painting problems, or worse.
   95    *
   96    * <h3>Default look and feel</h3>
   97    *
   98    * The class used for the default look and feel is chosen in the following
   99    * manner:
  100    * <ol>
  101    *   <li>If the system property <code>swing.defaultlaf</code> is
  102    *       {@code non-null}, use its value as the default look and feel class
  103    *       name.
  104    *   <li>If the {@link java.util.Properties} file <code>swing.properties</code>
  105    *       exists and contains the key <code>swing.defaultlaf</code>,
  106    *       use its value as the default look and feel class name. The location
  107    *       that is checked for <code>swing.properties</code> may vary depending
  108    *       upon the implementation of the Java platform. In Sun's implementation
  109    *       the location is <code>${java.home}/lib/swing.properties</code>.
  110    *       Refer to the release notes of the implementation being used for
  111    *       further details.
  112    *   <li>Otherwise use the cross platform look and feel.
  113    * </ol>
  114    *
  115    * <h3>Defaults</h3>
  116    *
  117    * {@code UIManager} manages three sets of {@code UIDefaults}. In order, they
  118    * are:
  119    * <ol>
  120    *   <li>Developer defaults. With few exceptions Swing does not
  121    *       alter the developer defaults; these are intended to be modified
  122    *       and used by the developer.
  123    *   <li>Look and feel defaults. The look and feel defaults are
  124    *       supplied by the look and feel at the time it is installed as the
  125    *       current look and feel ({@code setLookAndFeel()} is invoked). The
  126    *       look and feel defaults can be obtained using the {@code
  127    *       getLookAndFeelDefaults()} method.
  128    *   <li>Sytem defaults. The system defaults are provided by Swing.
  129    * </ol>
  130    * Invoking any of the various {@code get} methods
  131    * results in checking each of the defaults, in order, returning
  132    * the first {@code non-null} value. For example, invoking
  133    * {@code UIManager.getString("Table.foreground")} results in first
  134    * checking developer defaults. If the developer defaults contain
  135    * a value for {@code "Table.foreground"} it is returned, otherwise
  136    * the look and feel defaults are checked, followed by the system defaults.
  137    * <p>
  138    * It's important to note that {@code getDefaults} returns a custom
  139    * instance of {@code UIDefaults} with this resolution logic built into it.
  140    * For example, {@code UIManager.getDefaults().getString("Table.foreground")}
  141    * is equivalent to {@code UIManager.getString("Table.foreground")}. Both
  142    * resolve using the algorithm just described. In many places the
  143    * documentation uses the word defaults to refer to the custom instance
  144    * of {@code UIDefaults} with the resolution logic as previously described.
  145    * <p>
  146    * When the look and feel is changed, {@code UIManager} alters only the
  147    * look and feel defaults; the developer and system defaults are not
  148    * altered by the {@code UIManager} in any way.
  149    * <p>
  150    * The set of defaults a particular look and feel supports is defined
  151    * and documented by that look and feel. In addition, each look and
  152    * feel, or {@code ComponentUI} provided by a look and feel, may
  153    * access the defaults at different times in their life cycle. Some
  154    * look and feels may agressively look up defaults, so that changing a
  155    * default may not have an effect after installing the look and feel.
  156    * Other look and feels may lazily access defaults so that a change to
  157    * the defaults may effect an existing look and feel. Finally, other look
  158    * and feels might not configure themselves from the defaults table in
  159    * any way. None-the-less it is usually the case that a look and feel
  160    * expects certain defaults, so that in general
  161    * a {@code ComponentUI} provided by one look and feel will not
  162    * work with another look and feel.
  163    * <p>
  164    * <strong>Warning:</strong>
  165    * Serialized objects of this class will not be compatible with
  166    * future Swing releases. The current serialization support is
  167    * appropriate for short term storage or RMI between applications running
  168    * the same version of Swing.  As of 1.4, support for long term storage
  169    * of all JavaBeans<sup><font size="-2">TM</font></sup>
  170    * has been added to the <code>java.beans</code> package.
  171    * Please see {@link java.beans.XMLEncoder}.
  172    *
  173    * @author Thomas Ball
  174    * @author Hans Muller
  175    */
  176   public class UIManager implements Serializable
  177   {
  178       /**
  179        * This class defines the state managed by the <code>UIManager</code>.  For
  180        * Swing applications the fields in this class could just as well
  181        * be static members of <code>UIManager</code> however we give them
  182        * "AppContext"
  183        * scope instead so that applets (and potentially multiple lightweight
  184        * applications running in a single VM) have their own state. For example,
  185        * an applet can alter its look and feel, see <code>setLookAndFeel</code>.
  186        * Doing so has no affect on other applets (or the browser).
  187        */
  188       private static class LAFState
  189       {
  190           Properties swingProps;
  191           private UIDefaults[] tables = new UIDefaults[2];
  192   
  193           boolean initialized = false;
  194           MultiUIDefaults multiUIDefaults = new MultiUIDefaults(tables);
  195           LookAndFeel lookAndFeel;
  196           LookAndFeel multiLookAndFeel = null;
  197           Vector<LookAndFeel> auxLookAndFeels = null;
  198           SwingPropertyChangeSupport changeSupport;
  199   
  200           LookAndFeelInfo[] installedLAFs;
  201   
  202           UIDefaults getLookAndFeelDefaults() { return tables[0]; }
  203           void setLookAndFeelDefaults(UIDefaults x) { tables[0] = x; }
  204   
  205           UIDefaults getSystemDefaults() { return tables[1]; }
  206           void setSystemDefaults(UIDefaults x) { tables[1] = x; }
  207   
  208           /**
  209            * Returns the SwingPropertyChangeSupport for the current
  210            * AppContext.  If <code>create</code> is a true, a non-null
  211            * <code>SwingPropertyChangeSupport</code> will be returned, if
  212            * <code>create</code> is false and this has not been invoked
  213            * with true, null will be returned.
  214            */
  215           public synchronized SwingPropertyChangeSupport
  216                                    getPropertyChangeSupport(boolean create) {
  217               if (create && changeSupport == null) {
  218                   changeSupport = new SwingPropertyChangeSupport(
  219                                            UIManager.class);
  220               }
  221               return changeSupport;
  222           }
  223       }
  224   
  225   
  226   
  227   
  228       /* Lock object used in place of class object for synchronization. (4187686)
  229        */
  230       private static final Object classLock = new Object();
  231   
  232       /**
  233        * Return the <code>LAFState</code> object, lazily create one if necessary.
  234        * All access to the <code>LAFState</code> fields is done via this method,
  235        * for example:
  236        * <pre>
  237        *     getLAFState().initialized = true;
  238        * </pre>
  239        */
  240       private static LAFState getLAFState() {
  241           LAFState rv = (LAFState)SwingUtilities.appContextGet(
  242                   SwingUtilities2.LAF_STATE_KEY);
  243           if (rv == null) {
  244               synchronized (classLock) {
  245                   rv = (LAFState)SwingUtilities.appContextGet(
  246                           SwingUtilities2.LAF_STATE_KEY);
  247                   if (rv == null) {
  248                       SwingUtilities.appContextPut(
  249                               SwingUtilities2.LAF_STATE_KEY,
  250                               (rv = new LAFState()));
  251                   }
  252               }
  253           }
  254           return rv;
  255       }
  256   
  257   
  258       /* Keys used for the properties file in <java.home>/lib/swing.properties.
  259        * See loadUserProperties(), initialize().
  260        */
  261   
  262       private static final String defaultLAFKey = "swing.defaultlaf";
  263       private static final String auxiliaryLAFsKey = "swing.auxiliarylaf";
  264       private static final String multiplexingLAFKey = "swing.plaf.multiplexinglaf";
  265       private static final String installedLAFsKey = "swing.installedlafs";
  266       private static final String disableMnemonicKey = "swing.disablenavaids";
  267   
  268       /**
  269        * Return a swing.properties file key for the attribute of specified
  270        * look and feel.  The attr is either "name" or "class", a typical
  271        * key would be: "swing.installedlaf.windows.name"
  272        */
  273       private static String makeInstalledLAFKey(String laf, String attr) {
  274           return "swing.installedlaf." + laf + "." + attr;
  275       }
  276   
  277       /**
  278        * The filename for swing.properties is a path like this (Unix version):
  279        * <java.home>/lib/swing.properties.  This method returns a bogus
  280        * filename if java.home isn't defined.
  281        */
  282       private static String makeSwingPropertiesFilename() {
  283           String sep = File.separator;
  284           // No need to wrap this in a doPrivileged as it's called from
  285           // a doPrivileged.
  286           String javaHome = System.getProperty("java.home");
  287           if (javaHome == null) {
  288               javaHome = "<java.home undefined>";
  289           }
  290           return javaHome + sep + "lib" + sep + "swing.properties";
  291       }
  292   
  293   
  294       /**
  295        * Provides a little information about an installed
  296        * <code>LookAndFeel</code> for the sake of configuring a menu or
  297        * for initial application set up.
  298        *
  299        * @see UIManager#getInstalledLookAndFeels
  300        * @see LookAndFeel
  301        */
  302       public static class LookAndFeelInfo {
  303           private String name;
  304           private String className;
  305   
  306           /**
  307            * Constructs a <code>UIManager</code>s
  308            * <code>LookAndFeelInfo</code> object.
  309            *
  310            * @param name      a <code>String</code> specifying the name of
  311            *                      the look and feel
  312            * @param className a <code>String</code> specifiying the name of
  313            *                      the class that implements the look and feel
  314            */
  315           public LookAndFeelInfo(String name, String className) {
  316               this.name = name;
  317               this.className = className;
  318           }
  319   
  320           /**
  321            * Returns the name of the look and feel in a form suitable
  322            * for a menu or other presentation
  323            * @return a <code>String</code> containing the name
  324            * @see LookAndFeel#getName
  325            */
  326           public String getName() {
  327               return name;
  328           }
  329   
  330           /**
  331            * Returns the name of the class that implements this look and feel.
  332            * @return the name of the class that implements this
  333            *              <code>LookAndFeel</code>
  334            * @see LookAndFeel
  335            */
  336           public String getClassName() {
  337               return className;
  338           }
  339   
  340           /**
  341            * Returns a string that displays and identifies this
  342            * object's properties.
  343            *
  344            * @return a <code>String</code> representation of this object
  345            */
  346           public String toString() {
  347               return getClass().getName() + "[" + getName() + " " + getClassName() + "]";
  348           }
  349       }
  350   
  351   
  352       /**
  353        * The default value of <code>installedLAFS</code> is used when no
  354        * swing.properties
  355        * file is available or if the file doesn't contain a "swing.installedlafs"
  356        * property.
  357        *
  358        * @see #initializeInstalledLAFs
  359        */
  360       private static LookAndFeelInfo[] installedLAFs;
  361   
  362       static {
  363           ArrayList<LookAndFeelInfo> iLAFs = new ArrayList<LookAndFeelInfo>(4);
  364           iLAFs.add(new LookAndFeelInfo(
  365                         "Metal", "javax.swing.plaf.metal.MetalLookAndFeel"));
  366           iLAFs.add(new LookAndFeelInfo(
  367                         "Nimbus", "javax.swing.plaf.nimbus.NimbusLookAndFeel"));
  368           iLAFs.add(new LookAndFeelInfo("CDE/Motif",
  369                     "com.sun.java.swing.plaf.motif.MotifLookAndFeel"));
  370   
  371           // Only include windows on Windows boxs.
  372           OSInfo.OSType osType = AccessController.doPrivileged(OSInfo.getOSTypeAction());
  373           if (osType == OSInfo.OSType.WINDOWS) {
  374               iLAFs.add(new LookAndFeelInfo("Windows",
  375                           "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"));
  376               if (Toolkit.getDefaultToolkit().getDesktopProperty(
  377                       "win.xpstyle.themeActive") != null) {
  378                   iLAFs.add(new LookAndFeelInfo("Windows Classic",
  379                    "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"));
  380               }
  381           }
  382           else {
  383               // GTK is not shipped on Windows.
  384               iLAFs.add(new LookAndFeelInfo("GTK+",
  385                     "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"));
  386           }
  387           installedLAFs = iLAFs.toArray(new LookAndFeelInfo[iLAFs.size()]);
  388       }
  389   
  390   
  391       /**
  392        * Returns an array of {@code LookAndFeelInfo}s representing the
  393        * {@code LookAndFeel} implementations currently available. The
  394        * <code>LookAndFeelInfo</code> objects can be used by an
  395        * application to construct a menu of look and feel options for
  396        * the user, or to determine which look and feel to set at startup
  397        * time. To avoid the penalty of creating numerous {@code
  398        * LookAndFeel} objects, {@code LookAndFeelInfo} maintains the
  399        * class name of the {@code LookAndFeel} class, not the actual
  400        * {@code LookAndFeel} instance.
  401        * <p>
  402        * The following example illustrates setting the current look and feel
  403        * from an instance of {@code LookAndFeelInfo}:
  404        * <pre>
  405        *   UIManager.setLookAndFeel(info.getClassName());
  406        * </pre>
  407        *
  408        * @return an array of <code>LookAndFeelInfo</code> objects
  409        * @see #setLookAndFeel
  410        */
  411       public static LookAndFeelInfo[] getInstalledLookAndFeels() {
  412           maybeInitialize();
  413           LookAndFeelInfo[] ilafs = getLAFState().installedLAFs;
  414           if (ilafs == null) {
  415               ilafs = installedLAFs;
  416           }
  417           LookAndFeelInfo[] rv = new LookAndFeelInfo[ilafs.length];
  418           System.arraycopy(ilafs, 0, rv, 0, ilafs.length);
  419           return rv;
  420       }
  421   
  422   
  423       /**
  424        * Sets the set of available look and feels. While this method does
  425        * not check to ensure all of the {@code LookAndFeelInfos} are
  426        * {@code non-null}, it is strongly recommended that only {@code non-null}
  427        * values are supplied in the {@code infos} array.
  428        *
  429        * @param infos set of <code>LookAndFeelInfo</code> objects specifying
  430        *        the available look and feels
  431        *
  432        * @see #getInstalledLookAndFeels
  433        * @throws NullPointerException if {@code infos} is {@code null}
  434        */
  435       public static void setInstalledLookAndFeels(LookAndFeelInfo[] infos)
  436           throws SecurityException
  437       {
  438           maybeInitialize();
  439           LookAndFeelInfo[] newInfos = new LookAndFeelInfo[infos.length];
  440           System.arraycopy(infos, 0, newInfos, 0, infos.length);
  441           getLAFState().installedLAFs = newInfos;
  442       }
  443   
  444   
  445       /**
  446        * Adds the specified look and feel to the set of available look
  447        * and feels. While this method allows a {@code null} {@code info},
  448        * it is strongly recommended that a {@code non-null} value be used.
  449        *
  450        * @param info a <code>LookAndFeelInfo</code> object that names the
  451        *          look and feel and identifies the class that implements it
  452        * @see #setInstalledLookAndFeels
  453        */
  454       public static void installLookAndFeel(LookAndFeelInfo info) {
  455           LookAndFeelInfo[] infos = getInstalledLookAndFeels();
  456           LookAndFeelInfo[] newInfos = new LookAndFeelInfo[infos.length + 1];
  457           System.arraycopy(infos, 0, newInfos, 0, infos.length);
  458           newInfos[infos.length] = info;
  459           setInstalledLookAndFeels(newInfos);
  460       }
  461   
  462   
  463       /**
  464        * Adds the specified look and feel to the set of available look
  465        * and feels. While this method does not check the
  466        * arguments in any way, it is strongly recommended that {@code
  467        * non-null} values be supplied.
  468        *
  469        * @param name descriptive name of the look and feel
  470        * @param className name of the class that implements the look and feel
  471        * @see #setInstalledLookAndFeels
  472        */
  473       public static void installLookAndFeel(String name, String className) {
  474           installLookAndFeel(new LookAndFeelInfo(name, className));
  475       }
  476   
  477   
  478       /**
  479        * Returns the current look and feel or <code>null</code>.
  480        *
  481        * @return current look and feel, or <code>null</code>
  482        * @see #setLookAndFeel
  483        */
  484       public static LookAndFeel getLookAndFeel() {
  485           maybeInitialize();
  486           return getLAFState().lookAndFeel;
  487       }
  488   
  489   
  490       /**
  491        * Sets the current look and feel to {@code newLookAndFeel}.
  492        * If the current look and feel is {@code non-null} {@code
  493        * uninitialize} is invoked on it. If {@code newLookAndFeel} is
  494        * {@code non-null}, {@code initialize} is invoked on it followed
  495        * by {@code getDefaults}. The defaults returned from {@code
  496        * newLookAndFeel.getDefaults()} replace those of the defaults
  497        * from the previous look and feel. If the {@code newLookAndFeel} is
  498        * {@code null}, the look and feel defaults are set to {@code null}.
  499        * <p>
  500        * A value of {@code null} can be used to set the look and feel
  501        * to {@code null}. As the {@code LookAndFeel} is required for
  502        * most of Swing to function, setting the {@code LookAndFeel} to
  503        * {@code null} is strongly discouraged.
  504        * <p>
  505        * This is a JavaBeans bound property.
  506        *
  507        * @param newLookAndFeel {@code LookAndFeel} to install
  508        * @throws UnsupportedLookAndFeelException if
  509        *          {@code newLookAndFeel} is {@code non-null} and
  510        *          {@code newLookAndFeel.isSupportedLookAndFeel()} returns
  511        *          {@code false}
  512        * @see #getLookAndFeel
  513        */
  514       public static void setLookAndFeel(LookAndFeel newLookAndFeel)
  515           throws UnsupportedLookAndFeelException
  516       {
  517           if ((newLookAndFeel != null) && !newLookAndFeel.isSupportedLookAndFeel()) {
  518               String s = newLookAndFeel.toString() + " not supported on this platform";
  519               throw new UnsupportedLookAndFeelException(s);
  520           }
  521   
  522           LAFState lafState = getLAFState();
  523           LookAndFeel oldLookAndFeel = lafState.lookAndFeel;
  524           if (oldLookAndFeel != null) {
  525               oldLookAndFeel.uninitialize();
  526           }
  527   
  528           lafState.lookAndFeel = newLookAndFeel;
  529           if (newLookAndFeel != null) {
  530               sun.swing.DefaultLookup.setDefaultLookup(null);
  531               newLookAndFeel.initialize();
  532               lafState.setLookAndFeelDefaults(newLookAndFeel.getDefaults());
  533           }
  534           else {
  535               lafState.setLookAndFeelDefaults(null);
  536           }
  537   
  538           SwingPropertyChangeSupport changeSupport = lafState.
  539                                            getPropertyChangeSupport(false);
  540           if (changeSupport != null) {
  541               changeSupport.firePropertyChange("lookAndFeel", oldLookAndFeel,
  542                                                newLookAndFeel);
  543           }
  544       }
  545   
  546   
  547       /**
  548        * Loads the {@code LookAndFeel} specified by the given class
  549        * name, using the current thread's context class loader, and
  550        * passes it to {@code setLookAndFeel(LookAndFeel)}.
  551        *
  552        * @param className  a string specifying the name of the class that implements
  553        *        the look and feel
  554        * @exception ClassNotFoundException if the <code>LookAndFeel</code>
  555        *           class could not be found
  556        * @exception InstantiationException if a new instance of the class
  557        *          couldn't be created
  558        * @exception IllegalAccessException if the class or initializer isn't accessible
  559        * @exception UnsupportedLookAndFeelException if
  560        *          <code>lnf.isSupportedLookAndFeel()</code> is false
  561        * @throws ClassCastException if {@code className} does not identify
  562        *         a class that extends {@code LookAndFeel}
  563        */
  564       public static void setLookAndFeel(String className)
  565           throws ClassNotFoundException,
  566                  InstantiationException,
  567                  IllegalAccessException,
  568                  UnsupportedLookAndFeelException
  569       {
  570           if ("javax.swing.plaf.metal.MetalLookAndFeel".equals(className)) {
  571               // Avoid reflection for the common case of metal.
  572               setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
  573           }
  574           else {
  575               Class lnfClass = SwingUtilities.loadSystemClass(className);
  576               setLookAndFeel((LookAndFeel)(lnfClass.newInstance()));
  577           }
  578       }
  579   
  580       /**
  581        * Returns the name of the <code>LookAndFeel</code> class that implements
  582        * the native system look and feel if there is one, otherwise
  583        * the name of the default cross platform <code>LookAndFeel</code>
  584        * class. This value can be overriden by setting the
  585        * <code>swing.systemlaf</code> system property.
  586        *
  587        * @return the <code>String</code> of the <code>LookAndFeel</code>
  588        *          class
  589        *
  590        * @see #setLookAndFeel
  591        * @see #getCrossPlatformLookAndFeelClassName
  592        */
  593       public static String getSystemLookAndFeelClassName() {
  594           String systemLAF = AccessController.doPrivileged(
  595                                new GetPropertyAction("swing.systemlaf"));
  596           if (systemLAF != null) {
  597               return systemLAF;
  598           }
  599           OSInfo.OSType osType = AccessController.doPrivileged(OSInfo.getOSTypeAction());
  600           if (osType == OSInfo.OSType.WINDOWS) {
  601               return "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
  602           } else {
  603               String desktop = AccessController.doPrivileged(new GetPropertyAction("sun.desktop"));
  604               Toolkit toolkit = Toolkit.getDefaultToolkit();
  605               if ("gnome".equals(desktop) &&
  606                       toolkit instanceof SunToolkit &&
  607                       ((SunToolkit) toolkit).isNativeGTKAvailable()) {
  608                   // May be set on Linux and Solaris boxs.
  609                   return "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
  610               }
  611               if (osType == OSInfo.OSType.SOLARIS) {
  612                   return "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
  613               }
  614           }
  615           return getCrossPlatformLookAndFeelClassName();
  616       }
  617   
  618   
  619       /**
  620        * Returns the name of the <code>LookAndFeel</code> class that implements
  621        * the default cross platform look and feel -- the Java
  622        * Look and Feel (JLF).  This value can be overriden by setting the
  623        * <code>swing.crossplatformlaf</code> system property.
  624        *
  625        * @return  a string with the JLF implementation-class
  626        * @see #setLookAndFeel
  627        * @see #getSystemLookAndFeelClassName
  628        */
  629       public static String getCrossPlatformLookAndFeelClassName() {
  630           String laf = AccessController.doPrivileged(
  631                                new GetPropertyAction("swing.crossplatformlaf"));
  632           if (laf != null) {
  633               return laf;
  634           }
  635           return "javax.swing.plaf.metal.MetalLookAndFeel";
  636       }
  637   
  638   
  639       /**
  640        * Returns the defaults. The returned defaults resolve using the
  641        * logic specified in the class documentation.
  642        *
  643        * @return a <code>UIDefaults</code> object containing the default values
  644        */
  645       public static UIDefaults getDefaults() {
  646           maybeInitialize();
  647           return getLAFState().multiUIDefaults;
  648       }
  649   
  650       /**
  651        * Returns a font from the defaults. If the value for {@code key} is
  652        * not a {@code Font}, {@code null} is returned.
  653        *
  654        * @param key  an <code>Object</code> specifying the font
  655        * @return the <code>Font</code> object
  656        * @throws NullPointerException if {@code key} is {@code null}
  657        */
  658       public static Font getFont(Object key) {
  659           return getDefaults().getFont(key);
  660       }
  661   
  662       /**
  663        * Returns a font from the defaults that is appropriate
  664        * for the given locale. If the value for {@code key} is
  665        * not a {@code Font}, {@code null} is returned.
  666        *
  667        * @param key  an <code>Object</code> specifying the font
  668        * @param l the <code>Locale</code> for which the font is desired; refer
  669        *        to {@code UIDefaults} for details on how a {@code null}
  670        *        {@code Locale} is handled
  671        * @return the <code>Font</code> object
  672        * @throws NullPointerException if {@code key} is {@code null}
  673        * @since 1.4
  674        */
  675       public static Font getFont(Object key, Locale l) {
  676           return getDefaults().getFont(key,l);
  677       }
  678   
  679       /**
  680        * Returns a color from the defaults. If the value for {@code key} is
  681        * not a {@code Color}, {@code null} is returned.
  682        *
  683        * @param key  an <code>Object</code> specifying the color
  684        * @return the <code>Color</code> object
  685        * @throws NullPointerException if {@code key} is {@code null}
  686        */
  687       public static Color getColor(Object key) {
  688           return getDefaults().getColor(key);
  689       }
  690   
  691       /**
  692        * Returns a color from the defaults that is appropriate
  693        * for the given locale. If the value for {@code key} is
  694        * not a {@code Color}, {@code null} is returned.
  695        *
  696        * @param key  an <code>Object</code> specifying the color
  697        * @param l the <code>Locale</code> for which the color is desired; refer
  698        *        to {@code UIDefaults} for details on how a {@code null}
  699        *        {@code Locale} is handled
  700        * @return the <code>Color</code> object
  701        * @throws NullPointerException if {@code key} is {@code null}
  702        * @since 1.4
  703        */
  704       public static Color getColor(Object key, Locale l) {
  705           return getDefaults().getColor(key,l);
  706       }
  707   
  708       /**
  709        * Returns an <code>Icon</code> from the defaults. If the value for
  710        * {@code key} is not an {@code Icon}, {@code null} is returned.
  711        *
  712        * @param key  an <code>Object</code> specifying the icon
  713        * @return the <code>Icon</code> object
  714        * @throws NullPointerException if {@code key} is {@code null}
  715        */
  716       public static Icon getIcon(Object key) {
  717           return getDefaults().getIcon(key);
  718       }
  719   
  720       /**
  721        * Returns an <code>Icon</code> from the defaults that is appropriate
  722        * for the given locale. If the value for
  723        * {@code key} is not an {@code Icon}, {@code null} is returned.
  724        *
  725        * @param key  an <code>Object</code> specifying the icon
  726        * @param l the <code>Locale</code> for which the icon is desired; refer
  727        *        to {@code UIDefaults} for details on how a {@code null}
  728        *        {@code Locale} is handled
  729        * @return the <code>Icon</code> object
  730        * @throws NullPointerException if {@code key} is {@code null}
  731        * @since 1.4
  732        */
  733       public static Icon getIcon(Object key, Locale l) {
  734           return getDefaults().getIcon(key,l);
  735       }
  736   
  737       /**
  738        * Returns a border from the defaults. If the value for
  739        * {@code key} is not a {@code Border}, {@code null} is returned.
  740        *
  741        * @param key  an <code>Object</code> specifying the border
  742        * @return the <code>Border</code> object
  743        * @throws NullPointerException if {@code key} is {@code null}
  744        */
  745       public static Border getBorder(Object key) {
  746           return getDefaults().getBorder(key);
  747       }
  748   
  749       /**
  750        * Returns a border from the defaults that is appropriate
  751        * for the given locale.  If the value for
  752        * {@code key} is not a {@code Border}, {@code null} is returned.
  753        *
  754        * @param key  an <code>Object</code> specifying the border
  755        * @param l the <code>Locale</code> for which the border is desired; refer
  756        *        to {@code UIDefaults} for details on how a {@code null}
  757        *        {@code Locale} is handled
  758        * @return the <code>Border</code> object
  759        * @throws NullPointerException if {@code key} is {@code null}
  760        * @since 1.4
  761        */
  762       public static Border getBorder(Object key, Locale l) {
  763           return getDefaults().getBorder(key,l);
  764       }
  765   
  766       /**
  767        * Returns a string from the defaults. If the value for
  768        * {@code key} is not a {@code String}, {@code null} is returned.
  769        *
  770        * @param key  an <code>Object</code> specifying the string
  771        * @return the <code>String</code>
  772        * @throws NullPointerException if {@code key} is {@code null}
  773        */
  774       public static String getString(Object key) {
  775           return getDefaults().getString(key);
  776       }
  777   
  778       /**
  779        * Returns a string from the defaults that is appropriate for the
  780        * given locale.  If the value for
  781        * {@code key} is not a {@code String}, {@code null} is returned.
  782        *
  783        * @param key  an <code>Object</code> specifying the string
  784        * @param l the <code>Locale</code> for which the string is desired; refer
  785        *        to {@code UIDefaults} for details on how a {@code null}
  786        *        {@code Locale} is handled
  787        * @return the <code>String</code>
  788        * @since 1.4
  789        * @throws NullPointerException if {@code key} is {@code null}
  790        */
  791       public static String getString(Object key, Locale l) {
  792           return getDefaults().getString(key,l);
  793       }
  794   
  795       /**
  796        * Returns a string from the defaults that is appropriate for the
  797        * given locale.  If the value for
  798        * {@code key} is not a {@code String}, {@code null} is returned.
  799        *
  800        * @param key  an <code>Object</code> specifying the string
  801        * @param c {@code Component} used to determine the locale;
  802        *          {@code null} implies the default locale as
  803        *          returned by {@code Locale.getDefault()}
  804        * @return the <code>String</code>
  805        * @throws NullPointerException if {@code key} is {@code null}
  806        */
  807       static String getString(Object key, Component c) {
  808           Locale l = (c == null) ? Locale.getDefault() : c.getLocale();
  809           return getString(key, l);
  810       }
  811   
  812       /**
  813        * Returns an integer from the defaults. If the value for
  814        * {@code key} is not an {@code Integer}, or does not exist,
  815        * {@code 0} is returned.
  816        *
  817        * @param key  an <code>Object</code> specifying the int
  818        * @return the int
  819        * @throws NullPointerException if {@code key} is {@code null}
  820        */
  821       public static int getInt(Object key) {
  822           return getDefaults().getInt(key);
  823       }
  824   
  825       /**
  826        * Returns an integer from the defaults that is appropriate
  827        * for the given locale. If the value for
  828        * {@code key} is not an {@code Integer}, or does not exist,
  829        * {@code 0} is returned.
  830        *
  831        * @param key  an <code>Object</code> specifying the int
  832        * @param l the <code>Locale</code> for which the int is desired; refer
  833        *        to {@code UIDefaults} for details on how a {@code null}
  834        *        {@code Locale} is handled
  835        * @return the int
  836        * @throws NullPointerException if {@code key} is {@code null}
  837        * @since 1.4
  838        */
  839       public static int getInt(Object key, Locale l) {
  840           return getDefaults().getInt(key,l);
  841       }
  842   
  843       /**
  844        * Returns a boolean from the defaults which is associated with
  845        * the key value. If the key is not found or the key doesn't represent
  846        * a boolean value then {@code false} is returned.
  847        *
  848        * @param key  an <code>Object</code> specifying the key for the desired boolean value
  849        * @return the boolean value corresponding to the key
  850        * @throws NullPointerException if {@code key} is {@code null}
  851        * @since 1.4
  852        */
  853       public static boolean getBoolean(Object key) {
  854           return getDefaults().getBoolean(key);
  855       }
  856   
  857       /**
  858        * Returns a boolean from the defaults which is associated with
  859        * the key value and the given <code>Locale</code>. If the key is not
  860        * found or the key doesn't represent
  861        * a boolean value then {@code false} will be returned.
  862        *
  863        * @param key  an <code>Object</code> specifying the key for the desired
  864        *             boolean value
  865        * @param l the <code>Locale</code> for which the boolean is desired; refer
  866        *        to {@code UIDefaults} for details on how a {@code null}
  867        *        {@code Locale} is handled
  868        * @return the boolean value corresponding to the key
  869        * @throws NullPointerException if {@code key} is {@code null}
  870        * @since 1.4
  871        */
  872       public static boolean getBoolean(Object key, Locale l) {
  873           return getDefaults().getBoolean(key,l);
  874       }
  875   
  876       /**
  877        * Returns an <code>Insets</code> object from the defaults. If the value
  878        * for {@code key} is not an {@code Insets}, {@code null} is returned.
  879        *
  880        * @param key  an <code>Object</code> specifying the <code>Insets</code> object
  881        * @return the <code>Insets</code> object
  882        * @throws NullPointerException if {@code key} is {@code null}
  883        */
  884       public static Insets getInsets(Object key) {
  885           return getDefaults().getInsets(key);
  886       }
  887   
  888       /**
  889        * Returns an <code>Insets</code> object from the defaults that is
  890        * appropriate for the given locale. If the value
  891        * for {@code key} is not an {@code Insets}, {@code null} is returned.
  892        *
  893        * @param key  an <code>Object</code> specifying the <code>Insets</code> object
  894        * @param l the <code>Locale</code> for which the object is desired; refer
  895        *        to {@code UIDefaults} for details on how a {@code null}
  896        *        {@code Locale} is handled
  897        * @return the <code>Insets</code> object
  898        * @throws NullPointerException if {@code key} is {@code null}
  899        * @since 1.4
  900        */
  901       public static Insets getInsets(Object key, Locale l) {
  902           return getDefaults().getInsets(key,l);
  903       }
  904   
  905       /**
  906        * Returns a dimension from the defaults. If the value
  907        * for {@code key} is not a {@code Dimension}, {@code null} is returned.
  908        *
  909        * @param key  an <code>Object</code> specifying the dimension object
  910        * @return the <code>Dimension</code> object
  911        * @throws NullPointerException if {@code key} is {@code null}
  912        */
  913       public static Dimension getDimension(Object key) {
  914           return getDefaults().getDimension(key);
  915       }
  916   
  917       /**
  918        * Returns a dimension from the defaults that is appropriate
  919        * for the given locale. If the value
  920        * for {@code key} is not a {@code Dimension}, {@code null} is returned.
  921        *
  922        * @param key  an <code>Object</code> specifying the dimension object
  923        * @param l the <code>Locale</code> for which the object is desired; refer
  924        *        to {@code UIDefaults} for details on how a {@code null}
  925        *        {@code Locale} is handled
  926        * @return the <code>Dimension</code> object
  927        * @throws NullPointerException if {@code key} is {@code null}
  928        * @since 1.4
  929        */
  930       public static Dimension getDimension(Object key, Locale l) {
  931           return getDefaults().getDimension(key,l);
  932       }
  933   
  934       /**
  935        * Returns an object from the defaults.
  936        *
  937        * @param key  an <code>Object</code> specifying the desired object
  938        * @return the <code>Object</code>
  939        * @throws NullPointerException if {@code key} is {@code null}
  940        */
  941       public static Object get(Object key) {
  942           return getDefaults().get(key);
  943       }
  944   
  945       /**
  946        * Returns an object from the defaults that is appropriate for
  947        * the given locale.
  948        *
  949        * @param key  an <code>Object</code> specifying the desired object
  950        * @param l the <code>Locale</code> for which the object is desired; refer
  951        *        to {@code UIDefaults} for details on how a {@code null}
  952        *        {@code Locale} is handled
  953        * @return the <code>Object</code>
  954        * @throws NullPointerException if {@code key} is {@code null}
  955        * @since 1.4
  956        */
  957       public static Object get(Object key, Locale l) {
  958           return getDefaults().get(key,l);
  959       }
  960   
  961       /**
  962        * Stores an object in the developer defaults. This is a cover method
  963        * for {@code getDefaults().put(key, value)}. This only effects the
  964        * developer defaults, not the system or look and feel defaults.
  965        *
  966        * @param key    an <code>Object</code> specifying the retrieval key
  967        * @param value  the <code>Object</code> to store; refer to
  968        *               {@code UIDefaults} for details on how {@code null} is
  969        *               handled
  970        * @return the <code>Object</code> returned by {@link UIDefaults#put}
  971        * @throws NullPointerException if {@code key} is {@code null}
  972        * @see UIDefaults#put
  973        */
  974       public static Object put(Object key, Object value) {
  975           return getDefaults().put(key, value);
  976       }
  977   
  978       /**
  979        * Returns the appropriate {@code ComponentUI} implementation for
  980        * {@code target}. Typically, this is a cover for
  981        * {@code getDefaults().getUI(target)}. However, if an auxiliary
  982        * look and feel has been installed, this first invokes
  983        * {@code getUI(target)} on the multiplexing look and feel's
  984        * defaults, and returns that value if it is {@code non-null}.
  985        *
  986        * @param target the <code>JComponent</code> to return the
  987        *        {@code ComponentUI} for
  988        * @return the <code>ComponentUI</code> object for {@code target}
  989        * @throws NullPointerException if {@code target} is {@code null}
  990        * @see UIDefaults#getUI
  991        */
  992       public static ComponentUI getUI(JComponent target) {
  993           maybeInitialize();
  994           ComponentUI ui = null;
  995           LookAndFeel multiLAF = getLAFState().multiLookAndFeel;
  996           if (multiLAF != null) {
  997               // This can return null if the multiplexing look and feel
  998               // doesn't support a particular UI.
  999               ui = multiLAF.getDefaults().getUI(target);
 1000           }
 1001           if (ui == null) {
 1002               ui = getDefaults().getUI(target);
 1003           }
 1004           return ui;
 1005       }
 1006   
 1007   
 1008       /**
 1009        * Returns the {@code UIDefaults} from the current look and feel,
 1010        * that were obtained at the time the look and feel was installed.
 1011        * <p>
 1012        * In general, developers should use the {@code UIDefaults} returned from
 1013        * {@code getDefaults()}. As the current look and feel may expect
 1014        * certain values to exist, altering the {@code UIDefaults} returned
 1015        * from this method could have unexpected results.
 1016        *
 1017        * @return <code>UIDefaults</code> from the current look and feel
 1018        * @see #getDefaults
 1019        * @see #setLookAndFeel(LookAndFeel)
 1020        * @see LookAndFeel#getDefaults
 1021        */
 1022       public static UIDefaults getLookAndFeelDefaults() {
 1023           maybeInitialize();
 1024           return getLAFState().getLookAndFeelDefaults();
 1025       }
 1026   
 1027       /**
 1028        * Finds the Multiplexing <code>LookAndFeel</code>.
 1029        */
 1030       private static LookAndFeel getMultiLookAndFeel() {
 1031           LookAndFeel multiLookAndFeel = getLAFState().multiLookAndFeel;
 1032           if (multiLookAndFeel == null) {
 1033               String defaultName = "javax.swing.plaf.multi.MultiLookAndFeel";
 1034               String className = getLAFState().swingProps.getProperty(multiplexingLAFKey, defaultName);
 1035               try {
 1036                   Class lnfClass = SwingUtilities.loadSystemClass(className);
 1037                   multiLookAndFeel = (LookAndFeel)lnfClass.newInstance();
 1038               } catch (Exception exc) {
 1039                   System.err.println("UIManager: failed loading " + className);
 1040               }
 1041           }
 1042           return multiLookAndFeel;
 1043       }
 1044   
 1045       /**
 1046        * Adds a <code>LookAndFeel</code> to the list of auxiliary look and feels.
 1047        * The auxiliary look and feels tell the multiplexing look and feel what
 1048        * other <code>LookAndFeel</code> classes for a component instance are to be used
 1049        * in addition to the default <code>LookAndFeel</code> class when creating a
 1050        * multiplexing UI.  The change will only take effect when a new
 1051        * UI class is created or when the default look and feel is changed
 1052        * on a component instance.
 1053        * <p>Note these are not the same as the installed look and feels.
 1054        *
 1055        * @param laf the <code>LookAndFeel</code> object
 1056        * @see #removeAuxiliaryLookAndFeel
 1057        * @see #setLookAndFeel
 1058        * @see #getAuxiliaryLookAndFeels
 1059        * @see #getInstalledLookAndFeels
 1060        */
 1061       static public void addAuxiliaryLookAndFeel(LookAndFeel laf) {
 1062           maybeInitialize();
 1063   
 1064           if (!laf.isSupportedLookAndFeel()) {
 1065               // Ideally we would throw an exception here, but it's too late
 1066               // for that.
 1067               return;
 1068           }
 1069           Vector<LookAndFeel> v = getLAFState().auxLookAndFeels;
 1070           if (v == null) {
 1071               v = new Vector<LookAndFeel>();
 1072           }
 1073   
 1074           if (!v.contains(laf)) {
 1075               v.addElement(laf);
 1076               laf.initialize();
 1077               getLAFState().auxLookAndFeels = v;
 1078   
 1079               if (getLAFState().multiLookAndFeel == null) {
 1080                   getLAFState().multiLookAndFeel = getMultiLookAndFeel();
 1081               }
 1082           }
 1083       }
 1084   
 1085       /**
 1086        * Removes a <code>LookAndFeel</code> from the list of auxiliary look and feels.
 1087        * The auxiliary look and feels tell the multiplexing look and feel what
 1088        * other <code>LookAndFeel</code> classes for a component instance are to be used
 1089        * in addition to the default <code>LookAndFeel</code> class when creating a
 1090        * multiplexing UI.  The change will only take effect when a new
 1091        * UI class is created or when the default look and feel is changed
 1092        * on a component instance.
 1093        * <p>Note these are not the same as the installed look and feels.
 1094        * @return true if the <code>LookAndFeel</code> was removed from the list
 1095        * @see #removeAuxiliaryLookAndFeel
 1096        * @see #getAuxiliaryLookAndFeels
 1097        * @see #setLookAndFeel
 1098        * @see #getInstalledLookAndFeels
 1099        */
 1100       static public boolean removeAuxiliaryLookAndFeel(LookAndFeel laf) {
 1101           maybeInitialize();
 1102   
 1103           boolean result;
 1104   
 1105           Vector<LookAndFeel> v = getLAFState().auxLookAndFeels;
 1106           if ((v == null) || (v.size() == 0)) {
 1107               return false;
 1108           }
 1109   
 1110           result = v.removeElement(laf);
 1111           if (result) {
 1112               if (v.size() == 0) {
 1113                   getLAFState().auxLookAndFeels = null;
 1114                   getLAFState().multiLookAndFeel = null;
 1115               } else {
 1116                   getLAFState().auxLookAndFeels = v;
 1117               }
 1118           }
 1119           laf.uninitialize();
 1120   
 1121           return result;
 1122       }
 1123   
 1124       /**
 1125        * Returns the list of auxiliary look and feels (can be <code>null</code>).
 1126        * The auxiliary look and feels tell the multiplexing look and feel what
 1127        * other <code>LookAndFeel</code> classes for a component instance are
 1128        * to be used in addition to the default LookAndFeel class when creating a
 1129        * multiplexing UI.
 1130        * <p>Note these are not the same as the installed look and feels.
 1131        *
 1132        * @return list of auxiliary <code>LookAndFeel</code>s or <code>null</code>
 1133        * @see #addAuxiliaryLookAndFeel
 1134        * @see #removeAuxiliaryLookAndFeel
 1135        * @see #setLookAndFeel
 1136        * @see #getInstalledLookAndFeels
 1137        */
 1138       static public LookAndFeel[] getAuxiliaryLookAndFeels() {
 1139           maybeInitialize();
 1140   
 1141           Vector<LookAndFeel> v = getLAFState().auxLookAndFeels;
 1142           if ((v == null) || (v.size() == 0)) {
 1143               return null;
 1144           }
 1145           else {
 1146               LookAndFeel[] rv = new LookAndFeel[v.size()];
 1147               for (int i = 0; i < rv.length; i++) {
 1148                   rv[i] = v.elementAt(i);
 1149               }
 1150               return rv;
 1151           }
 1152       }
 1153   
 1154   
 1155       /**
 1156        * Adds a <code>PropertyChangeListener</code> to the listener list.
 1157        * The listener is registered for all properties.
 1158        *
 1159        * @param listener  the <code>PropertyChangeListener</code> to be added
 1160        * @see java.beans.PropertyChangeSupport
 1161        */
 1162       public static void addPropertyChangeListener(PropertyChangeListener listener)
 1163       {
 1164           synchronized (classLock) {
 1165               getLAFState().getPropertyChangeSupport(true).
 1166                                addPropertyChangeListener(listener);
 1167           }
 1168       }
 1169   
 1170   
 1171       /**
 1172        * Removes a <code>PropertyChangeListener</code> from the listener list.
 1173        * This removes a <code>PropertyChangeListener</code> that was registered
 1174        * for all properties.
 1175        *
 1176        * @param listener  the <code>PropertyChangeListener</code> to be removed
 1177        * @see java.beans.PropertyChangeSupport
 1178        */
 1179       public static void removePropertyChangeListener(PropertyChangeListener listener)
 1180       {
 1181           synchronized (classLock) {
 1182               getLAFState().getPropertyChangeSupport(true).
 1183                             removePropertyChangeListener(listener);
 1184           }
 1185       }
 1186   
 1187   
 1188       /**
 1189        * Returns an array of all the <code>PropertyChangeListener</code>s added
 1190        * to this UIManager with addPropertyChangeListener().
 1191        *
 1192        * @return all of the <code>PropertyChangeListener</code>s added or an empty
 1193        *         array if no listeners have been added
 1194        * @since 1.4
 1195        */
 1196       public static PropertyChangeListener[] getPropertyChangeListeners() {
 1197           synchronized(classLock) {
 1198               return getLAFState().getPropertyChangeSupport(true).
 1199                         getPropertyChangeListeners();
 1200           }
 1201       }
 1202   
 1203       private static Properties loadSwingProperties()
 1204       {
 1205           /* Don't bother checking for Swing properties if untrusted, as
 1206            * there's no way to look them up without triggering SecurityExceptions.
 1207            */
 1208           if (UIManager.class.getClassLoader() != null) {
 1209               return new Properties();
 1210           }
 1211           else {
 1212               final Properties props = new Properties();
 1213   
 1214               java.security.AccessController.doPrivileged(
 1215                   new java.security.PrivilegedAction<Object>() {
 1216                   public Object run() {
 1217                       try {
 1218                           File file = new File(makeSwingPropertiesFilename());
 1219   
 1220                           if (file.exists()) {
 1221                               // InputStream has been buffered in Properties
 1222                               // class
 1223                               FileInputStream ins = new FileInputStream(file);
 1224                               props.load(ins);
 1225                               ins.close();
 1226                           }
 1227                       }
 1228                       catch (Exception e) {
 1229                           // No such file, or file is otherwise non-readable.
 1230                       }
 1231   
 1232                       // Check whether any properties were overridden at the
 1233                       // command line.
 1234                       checkProperty(props, defaultLAFKey);
 1235                       checkProperty(props, auxiliaryLAFsKey);
 1236                       checkProperty(props, multiplexingLAFKey);
 1237                       checkProperty(props, installedLAFsKey);
 1238                       checkProperty(props, disableMnemonicKey);
 1239                       // Don't care about return value.
 1240                       return null;
 1241                   }
 1242               });
 1243               return props;
 1244           }
 1245       }
 1246   
 1247       private static void checkProperty(Properties props, String key) {
 1248           // No need to do catch the SecurityException here, this runs
 1249           // in a doPrivileged.
 1250           String value = System.getProperty(key);
 1251           if (value != null) {
 1252               props.put(key, value);
 1253           }
 1254       }
 1255   
 1256   
 1257       /**
 1258        * If a swing.properties file exist and it has a swing.installedlafs property
 1259        * then initialize the <code>installedLAFs</code> field.
 1260        *
 1261        * @see #getInstalledLookAndFeels
 1262        */
 1263       private static void initializeInstalledLAFs(Properties swingProps)
 1264       {
 1265           String ilafsString = swingProps.getProperty(installedLAFsKey);
 1266           if (ilafsString == null) {
 1267               return;
 1268           }
 1269   
 1270           /* Create a vector that contains the value of the swing.installedlafs
 1271            * property.  For example given "swing.installedlafs=motif,windows"
 1272            * lafs = {"motif", "windows"}.
 1273            */
 1274           Vector<String> lafs = new Vector<String>();
 1275           StringTokenizer st = new StringTokenizer(ilafsString, ",", false);
 1276           while (st.hasMoreTokens()) {
 1277               lafs.addElement(st.nextToken());
 1278           }
 1279   
 1280           /* Look up the name and class for each name in the "swing.installedlafs"
 1281            * list.  If they both exist then add a LookAndFeelInfo to
 1282            * the installedLafs array.
 1283            */
 1284           Vector<LookAndFeelInfo> ilafs = new Vector<LookAndFeelInfo>(lafs.size());
 1285           for (String laf : lafs) {
 1286               String name = swingProps.getProperty(makeInstalledLAFKey(laf, "name"), laf);
 1287               String cls = swingProps.getProperty(makeInstalledLAFKey(laf, "class"));
 1288               if (cls != null) {
 1289                   ilafs.addElement(new LookAndFeelInfo(name, cls));
 1290               }
 1291           }
 1292   
 1293           LookAndFeelInfo[] installedLAFs = new LookAndFeelInfo[ilafs.size()];
 1294           for(int i = 0; i < ilafs.size(); i++) {
 1295               installedLAFs[i] = ilafs.elementAt(i);
 1296           }
 1297           getLAFState().installedLAFs = installedLAFs;
 1298       }
 1299   
 1300   
 1301       /**
 1302        * If the user has specified a default look and feel, use that.
 1303        * Otherwise use the look and feel that's native to this platform.
 1304        * If this code is called after the application has explicitly
 1305        * set it's look and feel, do nothing.
 1306        *
 1307        * @see #maybeInitialize
 1308        */
 1309       private static void initializeDefaultLAF(Properties swingProps)
 1310       {
 1311           if (getLAFState().lookAndFeel != null) {
 1312               return;
 1313           }
 1314   
 1315           // Try to get default LAF from system property, then from AppContext
 1316           // (6653395), then use cross-platform one by default.
 1317           String lafName = null;
 1318           HashMap lafData =
 1319                   (HashMap) AppContext.getAppContext().remove("swing.lafdata");
 1320           if (lafData != null) {
 1321               lafName = (String) lafData.remove("defaultlaf");
 1322           }
 1323           if (lafName == null) {
 1324               lafName = getCrossPlatformLookAndFeelClassName();
 1325           }
 1326           lafName = swingProps.getProperty(defaultLAFKey, lafName);
 1327   
 1328           try {
 1329               setLookAndFeel(lafName);
 1330           } catch (Exception e) {
 1331               throw new Error("Cannot load " + lafName);
 1332           }
 1333   
 1334           // Set any properties passed through AppContext (6653395).
 1335           if (lafData != null) {
 1336               for (Object key: lafData.keySet()) {
 1337                   UIManager.put(key, lafData.get(key));
 1338               }
 1339           }
 1340       }
 1341   
 1342   
 1343       private static void initializeAuxiliaryLAFs(Properties swingProps)
 1344       {
 1345           String auxLookAndFeelNames = swingProps.getProperty(auxiliaryLAFsKey);
 1346           if (auxLookAndFeelNames == null) {
 1347               return;
 1348           }
 1349   
 1350           Vector<LookAndFeel> auxLookAndFeels = new Vector<LookAndFeel>();
 1351   
 1352           StringTokenizer p = new StringTokenizer(auxLookAndFeelNames,",");
 1353           String factoryName;
 1354   
 1355           /* Try to load each LookAndFeel subclass in the list.
 1356            */
 1357   
 1358           while (p.hasMoreTokens()) {
 1359               String className = p.nextToken();
 1360               try {
 1361                   Class lnfClass = SwingUtilities.loadSystemClass(className);
 1362                   LookAndFeel newLAF = (LookAndFeel)lnfClass.newInstance();
 1363                   newLAF.initialize();
 1364                   auxLookAndFeels.addElement(newLAF);
 1365               }
 1366               catch (Exception e) {
 1367                   System.err.println("UIManager: failed loading auxiliary look and feel " + className);
 1368               }
 1369           }
 1370   
 1371           /* If there were problems and no auxiliary look and feels were
 1372            * loaded, make sure we reset auxLookAndFeels to null.
 1373            * Otherwise, we are going to use the MultiLookAndFeel to get
 1374            * all component UI's, so we need to load it now.
 1375            */
 1376           if (auxLookAndFeels.size() == 0) {
 1377               auxLookAndFeels = null;
 1378           }
 1379           else {
 1380               getLAFState().multiLookAndFeel = getMultiLookAndFeel();
 1381               if (getLAFState().multiLookAndFeel == null) {
 1382                   auxLookAndFeels = null;
 1383               }
 1384           }
 1385   
 1386           getLAFState().auxLookAndFeels = auxLookAndFeels;
 1387       }
 1388   
 1389   
 1390       private static void initializeSystemDefaults(Properties swingProps) {
 1391           getLAFState().swingProps = swingProps;
 1392       }
 1393   
 1394   
 1395       /*
 1396        * This method is called before any code that depends on the
 1397        * <code>AppContext</code> specific LAFState object runs.  When the AppContext
 1398        * corresponds to a set of applets it's possible for this method
 1399        * to be re-entered, which is why we grab a lock before calling
 1400        * initialize().
 1401        */
 1402       private static void maybeInitialize() {
 1403           synchronized (classLock) {
 1404               if (!getLAFState().initialized) {
 1405                   getLAFState().initialized = true;
 1406                   initialize();
 1407               }
 1408           }
 1409       }
 1410   
 1411   
 1412       /*
 1413        * Only called by maybeInitialize().
 1414        */
 1415       private static void initialize() {
 1416           Properties swingProps = loadSwingProperties();
 1417           initializeSystemDefaults(swingProps);
 1418           initializeDefaultLAF(swingProps);
 1419           initializeAuxiliaryLAFs(swingProps);
 1420           initializeInstalledLAFs(swingProps);
 1421   
 1422           // Enable the Swing default LayoutManager.
 1423           String toolkitName = Toolkit.getDefaultToolkit().getClass().getName();
 1424           // don't set default policy if this is XAWT.
 1425           if (!"sun.awt.X11.XToolkit".equals(toolkitName)) {
 1426               if (FocusManager.isFocusManagerEnabled()) {
 1427                   KeyboardFocusManager.getCurrentKeyboardFocusManager().
 1428                       setDefaultFocusTraversalPolicy(
 1429                           new LayoutFocusTraversalPolicy());
 1430               }
 1431           }
 1432   
 1433           // Install Swing's PaintEventDispatcher
 1434           if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) {
 1435               sun.awt.PaintEventDispatcher.setPaintEventDispatcher(
 1436                                           new SwingPaintEventDispatcher());
 1437           }
 1438           // Install a hook that will be invoked if no one consumes the
 1439           // KeyEvent.  If the source isn't a JComponent this will process
 1440           // key bindings, if the source is a JComponent it implies that
 1441           // processKeyEvent was already invoked and thus no need to process
 1442           // the bindings again, unless the Component is disabled, in which
 1443           // case KeyEvents will no longer be dispatched to it so that we
 1444           // handle it here.
 1445           KeyboardFocusManager.getCurrentKeyboardFocusManager().
 1446                   addKeyEventPostProcessor(new KeyEventPostProcessor() {
 1447                       public boolean postProcessKeyEvent(KeyEvent e) {
 1448                           Component c = e.getComponent();
 1449   
 1450                           if ((!(c instanceof JComponent) ||
 1451                                (c != null && !c.isEnabled())) &&
 1452                                   JComponent.KeyboardState.shouldProcess(e) &&
 1453                                   SwingUtilities.processKeyBindings(e)) {
 1454                               e.consume();
 1455                               return true;
 1456                           }
 1457                           return false;
 1458                       }
 1459                   });
 1460           AWTAccessor.getComponentAccessor().
 1461               setRequestFocusController(JComponent.focusController);
 1462       }
 1463   }

Home » openjdk-7 » javax » swing » [javadoc | source]