KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > UIManager


1 /*
2  * @(#)UIManager.java 1.115 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing;
8
9 import java.awt.Component JavaDoc;
10 import java.awt.Container JavaDoc;
11 import java.awt.Window JavaDoc;
12 import java.awt.Font JavaDoc;
13 import java.awt.Color JavaDoc;
14 import java.awt.Insets JavaDoc;
15 import java.awt.Dimension JavaDoc;
16 import java.awt.KeyboardFocusManager JavaDoc;
17 import java.awt.KeyEventPostProcessor JavaDoc;
18 import java.awt.Toolkit JavaDoc;
19
20 import java.awt.event.KeyEvent JavaDoc;
21
22 import java.security.AccessController JavaDoc;
23
24 import javax.swing.plaf.ComponentUI JavaDoc;
25 import javax.swing.border.Border JavaDoc;
26
27 import javax.swing.event.SwingPropertyChangeSupport JavaDoc;
28 import java.beans.PropertyChangeListener JavaDoc;
29 import java.beans.PropertyChangeEvent JavaDoc;
30
31 import java.io.FileOutputStream JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.io.ObjectOutputStream JavaDoc;
34 import java.io.ObjectInputStream JavaDoc;
35 import java.io.Serializable JavaDoc;
36 import java.io.File JavaDoc;
37 import java.io.FileInputStream JavaDoc;
38 import java.io.BufferedInputStream JavaDoc;
39
40 import java.util.ArrayList JavaDoc;
41 import java.util.Enumeration JavaDoc;
42 import java.util.Hashtable JavaDoc;
43 import java.util.Properties JavaDoc;
44 import java.util.StringTokenizer JavaDoc;
45 import java.util.Vector JavaDoc;
46 import java.util.Locale JavaDoc;
47
48 import sun.security.action.GetPropertyAction;
49
50 /**
51  * This class keeps track of the current look and feel and its
52  * defaults.
53  * The default look and feel class is chosen in the following manner:
54  * <ol>
55  * <li>If the system property <code>swing.defaultlaf</code> is
56  * non-null, use it as the default look and feel class name.
57  * <li>If the {@link java.util.Properties} file <code>swing.properties</code>
58  * exists and contains the key <code>swing.defaultlaf</code>,
59  * use its value as default look and feel class name. The location of
60  * <code>swing.properties</code> may vary depending upon the
61  * implementation of the Java platform. In Sun's implementation
62  * this will reside in
63  * <code>&amp;java.home>/lib/swing.properties</code>. Refer to
64  * the release notes of the implementation you are using for
65  * further details.
66  * <li>Otherwise use the Java look and feel.
67  * </ol>
68  * <p>
69  * We manage three levels of defaults: user defaults, look
70  * and feel defaults, system defaults. A call to <code>UIManager.get</code>
71  * checks all three levels in order and returns the first non-<code>null</code>
72  * value for a key, if any. A call to <code>UIManager.put</code> just
73  * affects the user defaults. Note that a call to
74  * <code>setLookAndFeel</code> doesn't affect the user defaults, it just
75  * replaces the middle defaults "level".
76  * <p>
77  * <strong>Warning:</strong>
78  * Serialized objects of this class will not be compatible with
79  * future Swing releases. The current serialization support is
80  * appropriate for short term storage or RMI between applications running
81  * the same version of Swing. As of 1.4, support for long term storage
82  * of all JavaBeans<sup><font size="-2">TM</font></sup>
83  * has been added to the <code>java.beans</code> package.
84  * Please see {@link java.beans.XMLEncoder}.
85  *
86  * @see javax.swing.plaf.metal
87  *
88  * @version 1.115 12/19/03
89  * @author Thomas Ball
90  * @author Hans Muller
91  */

92 public class UIManager implements Serializable JavaDoc
93 {
94     /**
95      * This class defines the state managed by the <code>UIManager</code>. For
96      * Swing applications the fields in this class could just as well
97      * be static members of <code>UIManager</code> however we give them
98      * "AppContext"
99      * scope instead so that applets (and potentially multiple lightweight
100      * applications running in a single VM) have their own state. For example,
101      * an applet can alter its look and feel, see <code>setLookAndFeel</code>.
102      * Doing so has no affect on other applets (or the browser).
103      */

104     private static class LAFState
105     {
106         Properties JavaDoc swingProps;
107         private UIDefaults JavaDoc[] tables = new UIDefaults JavaDoc[2];
108
109         boolean initialized = false;
110         MultiUIDefaults JavaDoc multiUIDefaults = new MultiUIDefaults JavaDoc(tables);
111         LookAndFeel JavaDoc lookAndFeel;
112         LookAndFeel JavaDoc multiLookAndFeel = null;
113         Vector JavaDoc auxLookAndFeels = null;
114         SwingPropertyChangeSupport JavaDoc changeSupport;
115
116         UIDefaults JavaDoc getLookAndFeelDefaults() { return tables[0]; }
117         void setLookAndFeelDefaults(UIDefaults JavaDoc x) { tables[0] = x; }
118
119         UIDefaults JavaDoc getSystemDefaults() { return tables[1]; }
120         void setSystemDefaults(UIDefaults JavaDoc x) { tables[1] = x; }
121
122         /**
123          * Returns the SwingPropertyChangeSupport for the current
124          * AppContext. If <code>create</code> is a true, a non-null
125          * <code>SwingPropertyChangeSupport</code> will be returned, if
126          * <code>create</code> is false and this has not been invoked
127          * with true, null will be returned.
128          */

129         public synchronized SwingPropertyChangeSupport JavaDoc
130                                  getPropertyChangeSupport(boolean create) {
131             if (create && changeSupport == null) {
132                 changeSupport = new SwingPropertyChangeSupport JavaDoc(
133                                          UIManager JavaDoc.class);
134             }
135             return changeSupport;
136         }
137     }
138
139
140     /**
141      * The <code>AppContext</code> key for our one <code>LAFState</code> instance.
142      */

143     private static final Object JavaDoc lafStateACKey = new StringBuffer JavaDoc("LookAndFeel State");
144
145
146     /* Lock object used in place of class object for synchronization. (4187686)
147      */

148     private static final Object JavaDoc classLock = new Object JavaDoc();
149
150
151     /* Cache the last referenced LAFState to improve performance
152      * when accessing it. The cache is based on last thread rather
153      * than last AppContext because of the cost of looking up the
154      * AppContext each time. Since most Swing UI work is on the
155      * EventDispatchThread, this hits often enough to justify the
156      * overhead. (4193032)
157      */

158     private static Thread JavaDoc currentLAFStateThread = null;
159     private static LAFState currentLAFState = null;
160
161
162     /**
163      * Return the <code>LAFState</code> object, lazily create one if necessary.
164      * All access to the <code>LAFState</code> fields is done via this method,
165      * for example:
166      * <pre>
167      * getLAFState().initialized = true;
168      * </pre>
169      */

170     private static LAFState getLAFState() {
171     // First check whether we're running on the same thread as
172
// the last request.
173
Thread JavaDoc thisThread = Thread.currentThread();
174     if (thisThread == currentLAFStateThread) {
175         return currentLAFState;
176     }
177
178         LAFState rv = (LAFState)SwingUtilities.appContextGet(lafStateACKey);
179         if (rv == null) {
180         synchronized (classLock) {
181         rv = (LAFState)SwingUtilities.appContextGet(lafStateACKey);
182         if (rv == null) {
183             SwingUtilities.appContextPut(lafStateACKey,
184                          (rv = new LAFState()));
185         }
186         }
187         }
188
189     currentLAFStateThread = thisThread;
190     currentLAFState = rv;
191
192     return rv;
193     }
194
195
196     /* Keys used for the properties file in <java.home>/lib/swing.properties.
197      * See loadUserProperties(), initialize().
198      */

199
200     private static final String JavaDoc defaultLAFKey = "swing.defaultlaf";
201     private static final String JavaDoc auxiliaryLAFsKey = "swing.auxiliarylaf";
202     private static final String JavaDoc multiplexingLAFKey = "swing.plaf.multiplexinglaf";
203     private static final String JavaDoc installedLAFsKey = "swing.installedlafs";
204     private static final String JavaDoc disableMnemonicKey = "swing.disablenavaids";
205
206     /**
207      * Return a swing.properties file key for the attribute of specified
208      * look and feel. The attr is either "name" or "class", a typical
209      * key would be: "swing.installedlaf.windows.name"
210      */

211     private static String JavaDoc makeInstalledLAFKey(String JavaDoc laf, String JavaDoc attr) {
212         return "swing.installedlaf." + laf + "." + attr;
213     }
214
215     /**
216      * The filename for swing.properties is a path like this (Unix version):
217      * <java.home>/lib/swing.properties. This method returns a bogus
218      * filename if java.home isn't defined.
219      */

220     private static String JavaDoc makeSwingPropertiesFilename() {
221         String JavaDoc sep = File.separator;
222         // No need to wrap this in a doPrivileged as it's called from
223
// a doPrivileged.
224
String JavaDoc javaHome = System.getProperty("java.home");
225         if (javaHome == null) {
226             javaHome = "<java.home undefined>";
227         }
228         return javaHome + sep + "lib" + sep + "swing.properties";
229     }
230
231
232     /**
233      * Provides a little information about an installed
234      * <code>LookAndFeel</code> for the sake of configuring a menu or
235      * for initial application set up.
236      *
237      * @see UIManager#getInstalledLookAndFeels
238      * @see LookAndFeel
239      */

240     public static class LookAndFeelInfo {
241         private String JavaDoc name;
242         private String JavaDoc className;
243
244         /**
245          * Constructs a <code>UIManager</code>s
246          * <code>LookAndFeelInfo</code> object.
247          *
248          * @param name a <code>String</code> specifying the name of
249          * the look and feel
250          * @param className a <code>String</code> specifiying the name of
251          * the class that implements the look and feel
252          */

253         public LookAndFeelInfo(String JavaDoc name, String JavaDoc className) {
254             this.name = name;
255             this.className = className;
256         }
257
258         /**
259          * Returns the name of the look and feel in a form suitable
260          * for a menu or other presentation
261          * @return a <code>String</code> containing the name
262          * @see LookAndFeel#getName
263          */

264         public String JavaDoc getName() {
265             return name;
266         }
267
268         /**
269          * Returns the name of the class that implements this look and feel.
270          * @return the name of the class that implements this
271          * <code>LookAndFeel</code>
272          * @see LookAndFeel
273          */

274         public String JavaDoc getClassName() {
275             return className;
276         }
277
278         /**
279          * Returns a string that displays and identifies this
280          * object's properties.
281          *
282          * @return a <code>String</code> representation of this object
283          */

284         public String JavaDoc toString() {
285             return getClass().getName() + "[" + getName() + " " + getClassName() + "]";
286         }
287     }
288
289
290     /**
291      * The default value of <code>installedLAFS</code> is used when no
292      * swing.properties
293      * file is available or if the file doesn't contain a "swing.installedlafs"
294      * property.
295      *
296      * @see #initializeInstalledLAFs
297      */

298     private static LookAndFeelInfo[] installedLAFs;
299
300     static {
301         ArrayList JavaDoc iLAFs = new ArrayList JavaDoc(4);
302         iLAFs.add(new LookAndFeelInfo(
303                       "Metal", "javax.swing.plaf.metal.MetalLookAndFeel"));
304         iLAFs.add(new LookAndFeelInfo("CDE/Motif",
305                   "com.sun.java.swing.plaf.motif.MotifLookAndFeel"));
306
307         // Only include windows on Windows boxs.
308
String JavaDoc osName = (String JavaDoc)AccessController.doPrivileged(
309                              new GetPropertyAction("os.name"));
310         if (osName != null && osName.indexOf("Windows") != -1) {
311             iLAFs.add(new LookAndFeelInfo("Windows",
312                         "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"));
313             if (Toolkit.getDefaultToolkit().getDesktopProperty(
314                     "win.xpstyle.themeActive") != null) {
315                 iLAFs.add(new LookAndFeelInfo("Windows Classic",
316                  "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"));
317             }
318         }
319         else {
320             // GTK is not shipped on Windows.
321
iLAFs.add(new LookAndFeelInfo("GTK+",
322                   "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"));
323         }
324         installedLAFs = (LookAndFeelInfo[])iLAFs.toArray(
325                         new LookAndFeelInfo[iLAFs.size()]);
326     }
327
328
329     /**
330      * Returns an array of objects that provide some information about the
331      * <code>LookAndFeel</code> implementations that have been installed with this
332      * software development kit. The <code>LookAndFeel</code> info objects can
333      * used by an application to construct a menu of look and feel options for
334      * the user or to set the look and feel at start up time. Note that
335      * we do not return the <code>LookAndFeel</code> classes themselves here to
336      * avoid the cost of unnecessarily loading them.
337      * <p>
338      * Given a <code>LookAndFeelInfo</code> object one can set the current
339      * look and feel like this:
340      * <pre>
341      * UIManager.setLookAndFeel(info.getClassName());
342      * </pre>
343      * @return an array of <code>LookAndFeelInfo</code> objects
344      *
345      * @see #setLookAndFeel
346      */

347     public static LookAndFeelInfo[] getInstalledLookAndFeels() {
348         maybeInitialize();
349         LookAndFeelInfo[] ilafs = installedLAFs;
350         LookAndFeelInfo[] rv = new LookAndFeelInfo[ilafs.length];
351         System.arraycopy(ilafs, 0, rv, 0, ilafs.length);
352         return rv;
353     }
354
355
356     /**
357      * Replaces the current array of installed <code>LookAndFeelInfos</code>.
358      * @param infos new array of <code>LookAndFeelInfo</code> objects
359      *
360      * @see #getInstalledLookAndFeels
361      */

362     public static void setInstalledLookAndFeels(LookAndFeelInfo[] infos)
363         throws SecurityException JavaDoc
364     {
365         LookAndFeelInfo[] newInfos = new LookAndFeelInfo[infos.length];
366         System.arraycopy(infos, 0, newInfos, 0, infos.length);
367         installedLAFs = newInfos;
368     }
369
370
371     /**
372      * Adds the specified look and feel to the current array and
373      * then calls {@link #setInstalledLookAndFeels}.
374      * @param info a <code>LookAndFeelInfo</code> object that names the
375      * look and feel and identifies that class that implements it
376      */

377     public static void installLookAndFeel(LookAndFeelInfo info) {
378         LookAndFeelInfo[] infos = getInstalledLookAndFeels();
379         LookAndFeelInfo[] newInfos = new LookAndFeelInfo[infos.length + 1];
380         System.arraycopy(infos, 0, newInfos, 0, infos.length);
381         newInfos[infos.length] = info;
382         setInstalledLookAndFeels(newInfos);
383     }
384
385
386     /**
387      * Creates a new look and feel and adds it to the current array.
388      * Then calls {@link #setInstalledLookAndFeels}.
389      *
390      * @param name a <code>String</code> specifying the name of the
391      * look and feel
392      * @param className a <code>String</code> specifying the class name
393      * that implements the look and feel
394      */

395     public static void installLookAndFeel(String JavaDoc name, String JavaDoc className) {
396         installLookAndFeel(new LookAndFeelInfo(name, className));
397     }
398
399
400     /**
401      * Returns the current default look and feel or <code>null</code>.
402      *
403      * @return the current default look and feel, or <code>null</code>
404      * @see #setLookAndFeel
405      */

406     public static LookAndFeel JavaDoc getLookAndFeel() {
407         maybeInitialize();
408         return getLAFState().lookAndFeel;
409     }
410     
411
412     /**
413      * Sets the current default look and feel using a
414      * <code>LookAndFeel</code> object.
415      * <p>
416      * This is a JavaBeans bound property.
417      *
418      * @param newLookAndFeel the <code>LookAndFeel</code> object
419      * @exception UnsupportedLookAndFeelException if
420      * <code>lnf.isSupportedLookAndFeel()</code> is false
421      * @see #getLookAndFeel
422      */

423     public static void setLookAndFeel(LookAndFeel JavaDoc newLookAndFeel)
424         throws UnsupportedLookAndFeelException JavaDoc
425     {
426         if ((newLookAndFeel != null) && !newLookAndFeel.isSupportedLookAndFeel()) {
427             String JavaDoc s = newLookAndFeel.toString() + " not supported on this platform";
428             throw new UnsupportedLookAndFeelException JavaDoc(s);
429         }
430
431         LAFState lafState = getLAFState();
432         LookAndFeel JavaDoc oldLookAndFeel = lafState.lookAndFeel;
433         if (oldLookAndFeel != null) {
434             oldLookAndFeel.uninitialize();
435         }
436
437         lafState.lookAndFeel = newLookAndFeel;
438         if (newLookAndFeel != null) {
439             sun.swing.DefaultLookup.setDefaultLookup(null);
440             newLookAndFeel.initialize();
441             lafState.setLookAndFeelDefaults(newLookAndFeel.getDefaults());
442         }
443         else {
444             lafState.setLookAndFeelDefaults(null);
445         }
446
447         SwingPropertyChangeSupport JavaDoc changeSupport = lafState.
448                                          getPropertyChangeSupport(false);
449         if (changeSupport != null) {
450             changeSupport.firePropertyChange("lookAndFeel", oldLookAndFeel,
451                                              newLookAndFeel);
452         }
453     }
454
455     
456     /**
457      * Sets the current default look and feel using a class name.
458      *
459      * @param className a string specifying the name of the class that implements
460      * the look and feel
461      * @exception ClassNotFoundException if the <code>LookAndFeel</code>
462      * class could not be found
463      * @exception InstantiationException if a new instance of the class
464      * couldn't be created
465      * @exception IllegalAccessException if the class or initializer isn't accessible
466      * @exception UnsupportedLookAndFeelException if
467      * <code>lnf.isSupportedLookAndFeel()</code> is false
468      */

469     public static void setLookAndFeel(String JavaDoc className)
470         throws ClassNotFoundException JavaDoc,
471                InstantiationException JavaDoc,
472                IllegalAccessException JavaDoc,
473                UnsupportedLookAndFeelException JavaDoc
474     {
475         if ("javax.swing.plaf.metal.MetalLookAndFeel".equals(className)) {
476             // Avoid reflection for the common case of metal.
477
setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel JavaDoc());
478         }
479         else {
480             Class JavaDoc lnfClass = SwingUtilities.loadSystemClass(className);
481             setLookAndFeel((LookAndFeel JavaDoc)(lnfClass.newInstance()));
482         }
483     }
484
485
486     /**
487      * Returns the name of the <code>LookAndFeel</code> class that implements
488      * the native systems look and feel if there is one, otherwise
489      * the name of the default cross platform <code>LookAndFeel</code>
490      * class. If the system property <code>swing.systemlaf</code> has been
491      * defined, its value will be returned.
492      *
493      * @return the <code>String</code> of the <code>LookAndFeel</code>
494      * class
495      *
496      * @see #setLookAndFeel
497      * @see #getCrossPlatformLookAndFeelClassName
498      */

499     public static String JavaDoc getSystemLookAndFeelClassName() {
500     String JavaDoc systemLAF = (String JavaDoc)AccessController.doPrivileged(
501                              new GetPropertyAction("swing.systemlaf"));
502         if (systemLAF != null) {
503             return systemLAF;
504         }
505     String JavaDoc osName = (String JavaDoc)AccessController.doPrivileged(
506                              new GetPropertyAction("os.name"));
507
508         if (osName != null) {
509             if (osName.indexOf("Windows") != -1) {
510                 return "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
511             }
512             else {
513                 String JavaDoc desktop = (String JavaDoc)AccessController.doPrivileged(
514                              new GetPropertyAction("sun.desktop"));
515                 if ("gnome".equals(desktop)) {
516                     // May be set on Linux and Solaris boxs.
517
return "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
518                 }
519                 if ((osName.indexOf("Solaris") != -1) ||
520                      (osName.indexOf("SunOS") != -1)) {
521                     return "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
522                 }
523             }
524         }
525         return getCrossPlatformLookAndFeelClassName();
526     }
527
528
529     /**
530      * Returns the name of the <code>LookAndFeel</code> class that implements
531      * the default cross platform look and feel -- the Java
532      * Look and Feel (JLF). If the system property
533      * <code>swing.crossplatformlaf</code> has been
534      * defined, its value will be returned.
535      *
536      * @return a string with the JLF implementation-class
537      * @see #setLookAndFeel
538      * @see #getSystemLookAndFeelClassName
539      */

540     public static String JavaDoc getCrossPlatformLookAndFeelClassName() {
541     String JavaDoc laf = (String JavaDoc)AccessController.doPrivileged(
542                              new GetPropertyAction("swing.crossplatformlaf"));
543         if (laf != null) {
544             return laf;
545         }
546         return "javax.swing.plaf.metal.MetalLookAndFeel";
547     }
548
549
550     /**
551      * Returns the default values for this look and feel.
552      *
553      * @return a <code>UIDefaults</code> object containing the default values
554      */

555     public static UIDefaults JavaDoc getDefaults() {
556         maybeInitialize();
557         return getLAFState().multiUIDefaults;
558     }
559     
560     /**
561      * Returns a drawing font from the defaults table.
562      *
563      * @param key an <code>Object</code> specifying the font
564      * @return the <code>Font</code> object
565      */

566     public static Font JavaDoc getFont(Object JavaDoc key) {
567         return getDefaults().getFont(key);
568     }
569
570     /**
571      * Returns a drawing font from the defaults table that is appropriate
572      * for the given locale.
573      *
574      * @param key an <code>Object</code> specifying the font
575      * @param l the <code>Locale</code> for which the font is desired
576      * @return the <code>Font</code> object
577      * @since 1.4
578      */

579     public static Font JavaDoc getFont(Object JavaDoc key, Locale JavaDoc l) {
580         return getDefaults().getFont(key,l);
581     }
582
583     /**
584      * Returns a drawing color from the defaults table.
585      *
586      * @param key an <code>Object</code> specifying the color
587      * @return the <code>Color</code> object
588      */

589     public static Color JavaDoc getColor(Object JavaDoc key) {
590         return getDefaults().getColor(key);
591     }
592
593     /**
594      * Returns a drawing color from the defaults table that is appropriate
595      * for the given locale.
596      *
597      * @param key an <code>Object</code> specifying the color
598      * @param l the <code>Locale</code> for which the color is desired
599      * @return the <code>Color</code> object
600      * @since 1.4
601      */

602     public static Color JavaDoc getColor(Object JavaDoc key, Locale JavaDoc l) {
603         return getDefaults().getColor(key,l);
604     }
605
606     /**
607      * Returns an <code>Icon</code> from the defaults table.
608      *
609      * @param key an <code>Object</code> specifying the icon
610      * @return the <code>Icon</code> object
611      */

612     public static Icon JavaDoc getIcon(Object JavaDoc key) {
613         return getDefaults().getIcon(key);
614     }
615
616     /**
617      * Returns an <code>Icon</code> from the defaults table that is appropriate
618      * for the given locale.
619      *
620      * @param key an <code>Object</code> specifying the icon
621      * @param l the <code>Locale</code> for which the icon is desired
622      * @return the <code>Icon</code> object
623      * @since 1.4
624      */

625     public static Icon JavaDoc getIcon(Object JavaDoc key, Locale JavaDoc l) {
626         return getDefaults().getIcon(key,l);
627     }
628
629     /**
630      * Returns a border from the defaults table.
631      *
632      * @param key an <code>Object</code> specifying the border
633      * @return the <code>Border</code> object
634      */

635     public static Border JavaDoc getBorder(Object JavaDoc key) {
636         return getDefaults().getBorder(key);
637     }
638
639     /**
640      * Returns a border from the defaults table that is appropriate
641      * for the given locale.
642      *
643      * @param key an <code>Object</code> specifying the border
644      * @param l the <code>Locale</code> for which the border is desired
645      * @return the <code>Border</code> object
646      * @since 1.4
647      */

648     public static Border JavaDoc getBorder(Object JavaDoc key, Locale JavaDoc l) {
649         return getDefaults().getBorder(key,l);
650     }
651
652     /**
653      * Returns a string from the defaults table.
654      *
655      * @param key an <code>Object</code> specifying the string
656      * @return the <code>String</code>
657      */

658     public static String JavaDoc getString(Object JavaDoc key) {
659         return getDefaults().getString(key);
660     }
661
662     /**
663      * Returns a string from the defaults table that is appropriate for the
664      * given locale.
665      *
666      * @param key an <code>Object</code> specifying the string
667      * @param l the <code>Locale</code> for which the string is desired
668      * @return the <code>String</code>
669      */

670     public static String JavaDoc getString(Object JavaDoc key, Locale JavaDoc l) {
671         return getDefaults().getString(key,l);
672     }
673
674     /**
675      * Returns a string from the defaults table that is appropriate for the
676      * given locale.
677      *
678      * @param key an <code>Object</code> specifying the string
679      * @param c Component used to determine Locale, null implies use the
680      * default Locale.
681      * @return the <code>String</code>
682      */

683     static String JavaDoc getString(Object JavaDoc key, Component JavaDoc c) {
684         Locale JavaDoc l = (c == null) ? Locale.getDefault() : c.getLocale();
685         return getString(key, l);
686     }
687
688     /**
689      * Returns an integer from the defaults table.
690      *
691      * @param key an <code>Object</code> specifying the int
692      * @return the int
693      */

694     public static int getInt(Object JavaDoc key) {
695         return getDefaults().getInt(key);
696     }
697
698     /**
699      * Returns an integer from the defaults table that is appropriate
700      * for the given locale.
701      *
702      * @param key an <code>Object</code> specifying the int
703      * @param l the <code>Locale</code> for which the int is desired
704      * @return the int
705      * @since 1.4
706      */

707     public static int getInt(Object JavaDoc key, Locale JavaDoc l) {
708         return getDefaults().getInt(key,l);
709     }
710
711     /**
712      * Returns an integer from the defaults table. If <code>key</code> does
713      * not map to a valid <code>Integer</code>, or can not be convered from
714      * a <code>String</code> to an integer, <code>default</code> is
715      * returned.
716      *
717      * @param key an <code>Object</code> specifying the int
718      * @param defaultValue Returned value if <code>key</code> is not available,
719      * or is not an Integer
720      * @return the int
721      */

722     static int getInt(Object JavaDoc key, int defaultValue) {
723         Object JavaDoc value = UIManager.get(key);
724
725         if (value instanceof Integer JavaDoc) {
726             return ((Integer JavaDoc)value).intValue();
727         }
728         if (value instanceof String JavaDoc) {
729             try {
730                 return Integer.parseInt((String JavaDoc)value);
731             } catch (NumberFormatException JavaDoc nfe) {}
732         }
733         return defaultValue;
734     }
735
736     /**
737      * Returns a boolean from the defaults table which is associated with
738      * the key value. If the key is not found or the key doesn't represent
739      * a boolean value then false will be returned.
740      *
741      * @param key an <code>Object</code> specifying the key for the desired boolean value
742      * @return the boolean value corresponding to the key
743      * @since 1.4
744      */

745     public static boolean getBoolean(Object JavaDoc key) {
746         return getDefaults().getBoolean(key);
747     }
748
749     /**
750      * Returns a boolean from the defaults table which is associated with
751      * the key value and the given <code>Locale</code>. If the key is not
752      * found or the key doesn't represent
753      * a boolean value then false will be returned.
754      *
755      * @param key an <code>Object</code> specifying the key for the desired
756      * boolean value
757      * @param l the <code>Locale</code> for which the boolean is desired
758      * @return the boolean value corresponding to the key
759      * @since 1.4
760      */

761     public static boolean getBoolean(Object JavaDoc key, Locale JavaDoc l) {
762         return getDefaults().getBoolean(key,l);
763     }
764
765     /**
766      * Returns an <code>Insets</code> object from the defaults table.
767      *
768      * @param key an <code>Object</code> specifying the <code>Insets</code> object
769      * @return the <code>Insets</code> object
770      */

771     public static Insets JavaDoc getInsets(Object JavaDoc key) {
772         return getDefaults().getInsets(key);
773     }
774
775     /**
776      * Returns an <code>Insets</code> object from the defaults table that is
777      * appropriate for the given locale.
778      *
779      * @param key an <code>Object</code> specifying the <code>Insets</code> object
780      * @param l the <code>Locale</code> for which the object is desired
781      * @return the <code>Insets</code> object
782      * @since 1.4
783      */

784     public static Insets JavaDoc getInsets(Object JavaDoc key, Locale JavaDoc l) {
785         return getDefaults().getInsets(key,l);
786     }
787
788     /**
789      * Returns a dimension from the defaults table.
790      *
791      * @param key an <code>Object</code> specifying the dimension object
792      * @return the <code>Dimension</code> object
793      */

794     public static Dimension JavaDoc getDimension(Object JavaDoc key) {
795         return getDefaults().getDimension(key);
796     }
797
798     /**
799      * Returns a dimension from the defaults table that is appropriate
800      * for the given locale.
801      *
802      * @param key an <code>Object</code> specifying the dimension object
803      * @param l the <code>Locale</code> for which the object is desired
804      * @return the <code>Dimension</code> object
805      * @since 1.4
806      */

807     public static Dimension JavaDoc getDimension(Object JavaDoc key, Locale JavaDoc l) {
808         return getDefaults().getDimension(key,l);
809     }
810
811     /**
812      * Returns an object from the defaults table.
813      *
814      * @param key an <code>Object</code> specifying the desired object
815      * @return the <code>Object</code>
816      */

817     public static Object JavaDoc get(Object JavaDoc key) {
818         return getDefaults().get(key);
819     }
820
821     /**
822      * Returns an object from the defaults table that is appropriate for
823      * the given locale.
824      *
825      * @param key an <code>Object</code> specifying the desired object
826      * @param l the <code>Locale</code> for which the object is desired
827      * @return the <code>Object</code>
828      */

829     public static Object JavaDoc get(Object JavaDoc key, Locale JavaDoc l) {
830         return getDefaults().get(key,l);
831     }
832
833     /**
834      * Stores an object in the defaults table.
835      *
836      * @param key an <code>Object</code> specifying the retrieval key
837      * @param value the <code>Object</code> to store
838      * @return the <code>Object</code> returned by {@link UIDefaults#put}
839      */

840     public static Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
841         return getDefaults().put(key, value);
842     }
843
844     /**
845      * Returns the L&F object that renders the target component.
846      *
847      * @param target the <code>JComponent</code> to render
848      * @return the <code>ComponentUI</code> object that renders the target component
849      */

850     public static ComponentUI JavaDoc getUI(JComponent JavaDoc target) {
851         maybeInitialize();
852         ComponentUI JavaDoc ui = null;
853         LookAndFeel JavaDoc multiLAF = getLAFState().multiLookAndFeel;
854         if (multiLAF != null) {
855             // This can return null if the multiplexing look and feel
856
// doesn't support a particular UI.
857
ui = multiLAF.getDefaults().getUI(target);
858         }
859         if (ui == null) {
860             ui = getDefaults().getUI(target);
861         }
862         return ui;
863     }
864
865
866     /**
867      * Returns the default values for this look and feel.
868      *
869      * @return an <code>UIDefaults</code> object containing the default values
870      */

871     public static UIDefaults JavaDoc getLookAndFeelDefaults() {
872         maybeInitialize();
873         return getLAFState().getLookAndFeelDefaults();
874     }
875
876     /**
877      * Finds the Multiplexing <code>LookAndFeel</code>.
878      */

879     private static LookAndFeel JavaDoc getMultiLookAndFeel() {
880     LookAndFeel JavaDoc multiLookAndFeel = getLAFState().multiLookAndFeel;
881     if (multiLookAndFeel == null) {
882             String JavaDoc defaultName = "javax.swing.plaf.multi.MultiLookAndFeel";
883             String JavaDoc className = getLAFState().swingProps.getProperty(multiplexingLAFKey, defaultName);
884             try {
885                 Class JavaDoc lnfClass = SwingUtilities.loadSystemClass(className);
886                 multiLookAndFeel = (LookAndFeel JavaDoc)lnfClass.newInstance();
887             } catch (Exception JavaDoc exc) {
888                 System.err.println("UIManager: failed loading " + className);
889             }
890     }
891     return multiLookAndFeel;
892     }
893
894     /**
895      * Adds a <code>LookAndFeel</code> to the list of auxiliary look and feels.
896      * The auxiliary look and feels tell the multiplexing look and feel what
897      * other <code>LookAndFeel</code> classes for a component instance are to be used
898      * in addition to the default <code>LookAndFeel</code> class when creating a
899      * multiplexing UI. The change will only take effect when a new
900      * UI class is created or when the default look and feel is changed
901      * on a component instance.
902      * <p>Note these are not the same as the installed look and feels.
903      *
904      * @param laf the <code>LookAndFeel</code> object
905      * @see #removeAuxiliaryLookAndFeel
906      * @see #setLookAndFeel
907      * @see #getAuxiliaryLookAndFeels
908      * @see #getInstalledLookAndFeels
909      */

910     static public void addAuxiliaryLookAndFeel(LookAndFeel JavaDoc laf) {
911         maybeInitialize();
912
913         if (!laf.isSupportedLookAndFeel()) {
914             // Ideally we would throw an exception here, but it's too late
915
// for that.
916
return;
917         }
918         Vector JavaDoc v = getLAFState().auxLookAndFeels;
919         if (v == null) {
920             v = new Vector JavaDoc();
921         }
922
923     if (!v.contains(laf)) {
924         v.addElement(laf);
925         laf.initialize();
926             getLAFState().auxLookAndFeels = v;
927
928         if (getLAFState().multiLookAndFeel == null) {
929             getLAFState().multiLookAndFeel = getMultiLookAndFeel();
930             }
931     }
932     }
933
934     /**
935      * Removes a <code>LookAndFeel</code> from the list of auxiliary look and feels.
936      * The auxiliary look and feels tell the multiplexing look and feel what
937      * other <code>LookAndFeel</code> classes for a component instance are to be used
938      * in addition to the default <code>LookAndFeel</code> class when creating a
939      * multiplexing UI. The change will only take effect when a new
940      * UI class is created or when the default look and feel is changed
941      * on a component instance.
942      * <p>Note these are not the same as the installed look and feels.
943      * @return true if the <code>LookAndFeel</code> was removed from the list
944      * @see #removeAuxiliaryLookAndFeel
945      * @see #getAuxiliaryLookAndFeels
946      * @see #setLookAndFeel
947      * @see #getInstalledLookAndFeels
948      */

949     static public boolean removeAuxiliaryLookAndFeel(LookAndFeel JavaDoc laf) {
950         maybeInitialize();
951
952     boolean result;
953
954         Vector JavaDoc v = getLAFState().auxLookAndFeels;
955         if ((v == null) || (v.size() == 0)) {
956             return false;
957         }
958     
959     result = v.removeElement(laf);
960     if (result) {
961         if (v.size() == 0) {
962             getLAFState().auxLookAndFeels = null;
963             getLAFState().multiLookAndFeel = null;
964         } else {
965             getLAFState().auxLookAndFeels = v;
966             }
967         }
968     laf.uninitialize();
969
970     return result;
971     }
972
973     /**
974      * Returns the list of auxiliary look and feels (can be <code>null</code>).
975      * The auxiliary look and feels tell the multiplexing look and feel what
976      * other <code>LookAndFeel</code> classes for a component instance are
977      * to be used in addition to the default LookAndFeel class when creating a
978      * multiplexing UI.
979      * <p>Note these are not the same as the installed look and feels.
980      *
981      * @return list of auxiliary <code>LookAndFeel</code>s or <code>null</code>
982      * @see #addAuxiliaryLookAndFeel
983      * @see #removeAuxiliaryLookAndFeel
984      * @see #setLookAndFeel
985      * @see #getInstalledLookAndFeels
986      */

987     static public LookAndFeel JavaDoc[] getAuxiliaryLookAndFeels() {
988         maybeInitialize();
989
990         Vector JavaDoc v = getLAFState().auxLookAndFeels;
991         if ((v == null) || (v.size() == 0)) {
992             return null;
993         }
994         else {
995             LookAndFeel JavaDoc[] rv = new LookAndFeel JavaDoc[v.size()];
996             for (int i = 0; i < rv.length; i++) {
997                 rv[i] = (LookAndFeel JavaDoc)v.elementAt(i);
998             }
999             return rv;
1000        }
1001    }
1002
1003
1004    /**
1005     * Adds a <code>PropertyChangeListener</code> to the listener list.
1006     * The listener is registered for all properties.
1007     *
1008     * @param listener the <code>PropertyChangeListener</code> to be added
1009     * @see java.beans.PropertyChangeSupport
1010     */

1011    public static void addPropertyChangeListener(PropertyChangeListener JavaDoc listener)
1012    {
1013    synchronized (classLock) {
1014        getLAFState().getPropertyChangeSupport(true).
1015                             addPropertyChangeListener(listener);
1016    }
1017    }
1018
1019
1020    /**
1021     * Removes a <code>PropertyChangeListener</code> from the listener list.
1022     * This removes a <code>PropertyChangeListener</code> that was registered
1023     * for all properties.
1024     *
1025     * @param listener the <code>PropertyChangeListener</code> to be removed
1026     * @see java.beans.PropertyChangeSupport
1027     */

1028    public static void removePropertyChangeListener(PropertyChangeListener JavaDoc listener)
1029    {
1030        synchronized (classLock) {
1031        getLAFState().getPropertyChangeSupport(true).
1032                          removePropertyChangeListener(listener);
1033    }
1034    }
1035
1036
1037    /**
1038     * Returns an array of all the <code>PropertyChangeListener</code>s added
1039     * to this UIManager with addPropertyChangeListener().
1040     *
1041     * @return all of the <code>PropertyChangeListener</code>s added or an empty
1042     * array if no listeners have been added
1043     * @since 1.4
1044     */

1045    public static PropertyChangeListener JavaDoc[] getPropertyChangeListeners() {
1046        synchronized(classLock) {
1047            return getLAFState().getPropertyChangeSupport(true).
1048                      getPropertyChangeListeners();
1049        }
1050    }
1051
1052    private static Properties JavaDoc loadSwingProperties()
1053    {
1054    /* Don't bother checking for Swing properties if untrusted, as
1055     * there's no way to look them up without triggering SecurityExceptions.
1056     */

1057        if (UIManager JavaDoc.class.getClassLoader() != null) {
1058        return new Properties JavaDoc();
1059    }
1060    else {
1061        final Properties JavaDoc props = new Properties JavaDoc();
1062
1063            java.security.AccessController.doPrivileged(
1064                new java.security.PrivilegedAction JavaDoc() {
1065                public Object JavaDoc run() {
1066            try {
1067            File JavaDoc file = new File JavaDoc(makeSwingPropertiesFilename());
1068
1069                        if (file.exists()) {
1070                            // InputStream has been buffered in Properties
1071
// class
1072
FileInputStream JavaDoc ins = new FileInputStream JavaDoc(file);
1073                            props.load(ins);
1074                            ins.close();
1075                        }
1076            }
1077            catch (Exception JavaDoc e) {
1078            // No such file, or file is otherwise non-readable.
1079
}
1080
1081            // Check whether any properties were overridden at the
1082
// command line.
1083
checkProperty(props, defaultLAFKey);
1084            checkProperty(props, auxiliaryLAFsKey);
1085            checkProperty(props, multiplexingLAFKey);
1086            checkProperty(props, installedLAFsKey);
1087            checkProperty(props, disableMnemonicKey);
1088                    // Don't care about return value.
1089
return null;
1090        }
1091        });
1092        return props;
1093    }
1094    }
1095
1096    private static void checkProperty(Properties JavaDoc props, String JavaDoc key) {
1097        // No need to do catch the SecurityException here, this runs
1098
// in a doPrivileged.
1099
String JavaDoc value = System.getProperty(key);
1100        if (value != null) {
1101            props.put(key, value);
1102        }
1103    }
1104
1105
1106    /**
1107     * If a swing.properties file exist and it has a swing.installedlafs property
1108     * then initialize the <code>installedLAFs</code> field.
1109     *
1110     * @see #getInstalledLookAndFeels
1111     */

1112    private static void initializeInstalledLAFs(Properties JavaDoc swingProps)
1113    {
1114        String JavaDoc ilafsString = swingProps.getProperty(installedLAFsKey);
1115        if (ilafsString == null) {
1116            return;
1117        }
1118
1119        /* Create a vector that contains the value of the swing.installedlafs
1120         * property. For example given "swing.installedlafs=motif,windows"
1121         * lafs = {"motif", "windows"}.
1122         */

1123        Vector JavaDoc lafs = new Vector JavaDoc();
1124        StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(ilafsString, ",", false);
1125        while (st.hasMoreTokens()) {
1126            lafs.addElement(st.nextToken());
1127        }
1128
1129        /* Look up the name and class for each name in the "swing.installedlafs"
1130         * list. If they both exist then add a LookAndFeelInfo to
1131         * the installedLafs array.
1132         */

1133        Vector JavaDoc ilafs = new Vector JavaDoc(lafs.size());
1134        for(int i = 0; i < lafs.size(); i++) {
1135            String JavaDoc laf = (String JavaDoc)lafs.elementAt(i);
1136            String JavaDoc name = swingProps.getProperty(makeInstalledLAFKey(laf, "name"), laf);
1137            String JavaDoc cls = swingProps.getProperty(makeInstalledLAFKey(laf, "class"));
1138            if (cls != null) {
1139                ilafs.addElement(new LookAndFeelInfo(name, cls));
1140            }
1141        }
1142
1143        installedLAFs = new LookAndFeelInfo[ilafs.size()];
1144        for(int i = 0; i < ilafs.size(); i++) {
1145            installedLAFs[i] = (LookAndFeelInfo)(ilafs.elementAt(i));
1146        }
1147    }
1148
1149
1150    /**
1151     * If the user has specified a default look and feel, use that.
1152     * Otherwise use the look and feel that's native to this platform.
1153     * If this code is called after the application has explicitly
1154     * set it's look and feel, do nothing.
1155     *
1156     * @see #maybeInitialize
1157     */

1158    private static void initializeDefaultLAF(Properties JavaDoc swingProps)
1159    {
1160        if (getLAFState().lookAndFeel != null) {
1161            return;
1162        }
1163
1164        String JavaDoc metalLnf = getCrossPlatformLookAndFeelClassName();
1165        String JavaDoc lnfDefault = metalLnf;
1166
1167        String JavaDoc lnfName = "<undefined>" ;
1168        try {
1169            lnfName = swingProps.getProperty(defaultLAFKey, lnfDefault);
1170            setLookAndFeel(lnfName);
1171        } catch (Exception JavaDoc e) {
1172            try {
1173                lnfName = swingProps.getProperty(defaultLAFKey, metalLnf);
1174                setLookAndFeel(lnfName);
1175            } catch (Exception JavaDoc e2) {
1176                throw new Error JavaDoc("can't load " + lnfName);
1177            }
1178        }
1179    }
1180
1181
1182    private static void initializeAuxiliaryLAFs(Properties JavaDoc swingProps)
1183    {
1184        String JavaDoc auxLookAndFeelNames = swingProps.getProperty(auxiliaryLAFsKey);
1185        if (auxLookAndFeelNames == null) {
1186            return;
1187        }
1188
1189        Vector JavaDoc auxLookAndFeels = new Vector JavaDoc();
1190
1191        StringTokenizer JavaDoc p = new StringTokenizer JavaDoc(auxLookAndFeelNames,",");
1192        String JavaDoc factoryName;
1193
1194        /* Try to load each LookAndFeel subclass in the list.
1195         */

1196
1197        while (p.hasMoreTokens()) {
1198            String JavaDoc className = p.nextToken();
1199            try {
1200                Class JavaDoc lnfClass = SwingUtilities.loadSystemClass(className);
1201        LookAndFeel JavaDoc newLAF = (LookAndFeel JavaDoc)lnfClass.newInstance();
1202        newLAF.initialize();
1203                auxLookAndFeels.addElement(newLAF);
1204            }
1205            catch (Exception JavaDoc e) {
1206                System.err.println("UIManager: failed loading auxiliary look and feel " + className);
1207            }
1208        }
1209
1210        /* If there were problems and no auxiliary look and feels were
1211         * loaded, make sure we reset auxLookAndFeels to null.
1212         * Otherwise, we are going to use the MultiLookAndFeel to get
1213         * all component UI's, so we need to load it now.
1214         */

1215        if (auxLookAndFeels.size() == 0) {
1216            auxLookAndFeels = null;
1217        }
1218        else {
1219        getLAFState().multiLookAndFeel = getMultiLookAndFeel();
1220        if (getLAFState().multiLookAndFeel == null) {
1221                auxLookAndFeels = null;
1222        }
1223        }
1224
1225        getLAFState().auxLookAndFeels = auxLookAndFeels;
1226    }
1227
1228
1229    private static void initializeSystemDefaults(Properties JavaDoc swingProps) {
1230    getLAFState().swingProps = swingProps;
1231    }
1232
1233
1234    /*
1235     * This method is called before any code that depends on the
1236     * <code>AppContext</code> specific LAFState object runs. When the AppContext
1237     * corresponds to a set of applets it's possible for this method
1238     * to be re-entered, which is why we grab a lock before calling
1239     * initialize().
1240     */

1241    private static void maybeInitialize() {
1242    synchronized (classLock) {
1243        if (!getLAFState().initialized) {
1244        getLAFState().initialized = true;
1245        initialize();
1246        }
1247        }
1248    }
1249
1250
1251    /*
1252     * Only called by maybeInitialize().
1253     */

1254    private static void initialize() {
1255        Properties JavaDoc swingProps = loadSwingProperties();
1256        initializeSystemDefaults(swingProps);
1257        initializeDefaultLAF(swingProps);
1258        initializeAuxiliaryLAFs(swingProps);
1259        initializeInstalledLAFs(swingProps);
1260
1261        // Enable the Swing default LayoutManager.
1262
String JavaDoc toolkitName = Toolkit.getDefaultToolkit().getClass().getName();
1263        // don't set default policy if this is XAWT.
1264
if (!"sun.awt.X11.XToolkit".equals(toolkitName)) {
1265            if (FocusManager.isFocusManagerEnabled()) {
1266                KeyboardFocusManager.getCurrentKeyboardFocusManager().
1267                    setDefaultFocusTraversalPolicy(
1268                        new LayoutFocusTraversalPolicy JavaDoc());
1269            }
1270        }
1271        // Install a hook that will be invoked if no one consumes the
1272
// KeyEvent. If the source isn't a JComponent this will process
1273
// key bindings, if the source is a JComponent it implies that
1274
// processKeyEvent was already invoked and thus no need to process
1275
// the bindings again, unless the Component is disabled, in which
1276
// case KeyEvents will no longer be dispatched to it so that we
1277
// handle it here.
1278
KeyboardFocusManager.getCurrentKeyboardFocusManager().
1279                addKeyEventPostProcessor(new KeyEventPostProcessor JavaDoc() {
1280                    public boolean postProcessKeyEvent(KeyEvent JavaDoc e) {
1281                        Component JavaDoc c = e.getComponent();
1282
1283                        if ((!(c instanceof JComponent JavaDoc) ||
1284                             (c != null && !((JComponent JavaDoc)c).isEnabled())) &&
1285                                JComponent.KeyboardState.shouldProcess(e) &&
1286                                SwingUtilities.processKeyBindings(e)) {
1287                            e.consume();
1288                            return true;
1289                        }
1290                        return false;
1291                    }
1292                });
1293    }
1294}
1295
1296
Popular Tags