2 Copyright (C) 2002, 2003, 2004, 2005, 2006, Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java
.awt
.Color
;
42 import java
.awt
.Dimension
;
44 import java
.awt
.Insets
;
45 import java
.beans
.PropertyChangeListener
;
46 import java
.beans
.PropertyChangeSupport
;
47 import java
.io
.Serializable
;
48 import java
.util
.Enumeration
;
49 import java
.util
.Locale
;
51 import javax
.swing
.border
.Border
;
52 import javax
.swing
.plaf
.ComponentUI
;
53 import javax
.swing
.plaf
.metal
.MetalLookAndFeel
;
56 * Manages the current {@link LookAndFeel} and any auxiliary {@link LookAndFeel}
59 public class UIManager
implements Serializable
62 * Represents the basic information about a {@link LookAndFeel} (LAF), so
63 * that a list of installed LAFs can be presented without actually loading
66 public static class LookAndFeelInfo
71 * Creates a new instance.
73 * @param name the look and feel name.
74 * @param clazz the look and feel class name.
76 public LookAndFeelInfo(String name
,
84 * Returns the name of the look and feel.
86 * @return The name of the look and feel.
88 public String
getName()
94 * Returns the fully qualified class name for the {@link LookAndFeel}.
96 * @return The fully qualified class name for the {@link LookAndFeel}.
98 public String
getClassName()
104 * Returns a String representation of the LookAndFeelInfo object.
106 * @return a String representation of the LookAndFeelInfo object
108 public String
toString()
110 StringBuffer s
= new StringBuffer();
111 s
.append(getClass().getName());
115 s
.append(getClassName());
122 * A UIDefaults subclass that multiplexes between itself and a 'fallback'
123 * UIDefaults instance. This is used to protect the L&F UIDefaults from beeing
124 * overwritten by applications.
126 private static class MultiplexUIDefaults
129 private class MultiplexEnumeration
130 implements Enumeration
134 MultiplexEnumeration(Enumeration e1
, Enumeration e2
)
136 enums
= new Enumeration
[]{ e1
, e2
};
140 public boolean hasMoreElements()
142 return enums
[i
].hasMoreElements() || i
< enums
.length
- 1;
145 public Object
nextElement()
147 Object val
= enums
[i
].nextElement();
148 if (! enums
[i
].hasMoreElements() && i
< enums
.length
- 1)
158 * Creates a new <code>MultiplexUIDefaults</code> instance with
159 * <code>d</code> as the fallback defaults.
161 * @param d the fallback defaults (<code>null</code> not permitted).
163 MultiplexUIDefaults(UIDefaults d
)
166 throw new NullPointerException();
170 public Object
get(Object key
)
172 Object val
= super.get(key
);
174 val
= fallback
.get(key
);
178 public Object
get(Object key
, Locale l
)
180 Object val
= super.get(key
, l
);
182 val
= fallback
.get(key
, l
);
186 public Object
remove(Object key
)
188 Object val
= super.remove(key
);
190 val
= fallback
.remove(key
);
196 return super.size() + fallback
.size();
199 public Enumeration
keys()
201 return new MultiplexEnumeration(super.keys(), fallback
.keys());
204 public Enumeration
elements()
206 return new MultiplexEnumeration(super.elements(), fallback
.elements());
210 private static final long serialVersionUID
= -5547433830339189365L;
212 /** The installed look and feel(s). */
213 static LookAndFeelInfo
[] installed
= {
214 new LookAndFeelInfo("Metal", "javax.swing.plaf.metal.MetalLookAndFeel"),
215 new LookAndFeelInfo("GNU", "gnu.javax.swing.plaf.gnu.GNULookAndFeel")
218 /** The installed auxiliary look and feels. */
219 static LookAndFeel
[] auxLookAndFeels
;
221 /** The current look and feel. */
222 static LookAndFeel currentLookAndFeel
;
224 static MultiplexUIDefaults currentUIDefaults
;
226 static UIDefaults lookAndFeelDefaults
;
228 /** Property change listener mechanism. */
229 static PropertyChangeSupport listeners
230 = new PropertyChangeSupport(UIManager
.class);
234 String defaultlaf
= System
.getProperty("swing.defaultlaf");
237 if (defaultlaf
!= null)
239 setLookAndFeel(defaultlaf
);
243 setLookAndFeel(new MetalLookAndFeel());
248 System
.err
.println("cannot initialize Look and Feel: " + defaultlaf
);
249 System
.err
.println("error: " + ex
.toString());
250 ex
.printStackTrace();
251 System
.err
.println("falling back to Metal Look and Feel");
254 setLookAndFeel(new MetalLookAndFeel());
256 catch (Exception ex2
)
258 throw (Error
) new AssertionError("There must be no problem installing"
259 + " the MetalLookAndFeel.")
266 * Creates a new instance of the <code>UIManager</code>. There is no need
267 * to construct an instance of this class, since all methods are static.
275 * Add a <code>PropertyChangeListener</code> to the listener list.
277 * @param listener the listener to add
279 public static void addPropertyChangeListener(PropertyChangeListener listener
)
281 listeners
.addPropertyChangeListener(listener
);
285 * Remove a <code>PropertyChangeListener</code> from the listener list.
287 * @param listener the listener to remove
289 public static void removePropertyChangeListener(PropertyChangeListener
292 listeners
.removePropertyChangeListener(listener
);
296 * Returns an array of all added <code>PropertyChangeListener</code> objects.
298 * @return an array of listeners
302 public static PropertyChangeListener
[] getPropertyChangeListeners()
304 return listeners
.getPropertyChangeListeners();
308 * Add a {@link LookAndFeel} to the list of auxiliary look and feels.
310 * @param laf the auxiliary look and feel (<code>null</code> not permitted).
312 * @throws NullPointerException if <code>laf</code> is <code>null</code>.
314 * @see #getAuxiliaryLookAndFeels()
316 public static void addAuxiliaryLookAndFeel(LookAndFeel laf
)
319 throw new NullPointerException("Null 'laf' argument.");
320 if (auxLookAndFeels
== null)
322 auxLookAndFeels
= new LookAndFeel
[1];
323 auxLookAndFeels
[0] = laf
;
327 LookAndFeel
[] temp
= new LookAndFeel
[auxLookAndFeels
.length
+ 1];
328 System
.arraycopy(auxLookAndFeels
, 0, temp
, 0, auxLookAndFeels
.length
);
329 auxLookAndFeels
= temp
;
330 auxLookAndFeels
[auxLookAndFeels
.length
- 1] = laf
;
334 * Removes a {@link LookAndFeel} (LAF) from the list of auxiliary LAFs.
336 * @param laf the LAF to remove.
338 * @return <code>true</code> if the LAF was removed, and <code>false</code>
341 public static boolean removeAuxiliaryLookAndFeel(LookAndFeel laf
)
343 if (auxLookAndFeels
== null)
345 int count
= auxLookAndFeels
.length
;
346 if (count
== 1 && auxLookAndFeels
[0] == laf
)
348 auxLookAndFeels
= null;
351 for (int i
= 0; i
< count
; i
++)
353 if (auxLookAndFeels
[i
] == laf
)
355 LookAndFeel
[] temp
= new LookAndFeel
[auxLookAndFeels
.length
- 1];
358 System
.arraycopy(auxLookAndFeels
, 1, temp
, 0, count
- 1);
360 else if (i
== count
- 1)
362 System
.arraycopy(auxLookAndFeels
, 0, temp
, 0, count
- 1);
366 System
.arraycopy(auxLookAndFeels
, 0, temp
, 0, i
);
367 System
.arraycopy(auxLookAndFeels
, i
+ 1, temp
, i
,
370 auxLookAndFeels
= temp
;
378 * Returns an array (possibly <code>null</code>) containing the auxiliary
379 * {@link LookAndFeel}s that are in use. These are used by the
380 * {@link javax.swing.plaf.multi.MultiLookAndFeel} class.
382 * @return The auxiliary look and feels (possibly <code>null</code>).
384 * @see #addAuxiliaryLookAndFeel(LookAndFeel)
386 public static LookAndFeel
[] getAuxiliaryLookAndFeels()
388 return auxLookAndFeels
;
392 * Returns an object from the {@link UIDefaults} table for the current
393 * {@link LookAndFeel}.
395 * @param key the key.
397 * @return The object.
399 public static Object
get(Object key
)
401 return getDefaults().get(key
);
405 * Returns an object from the {@link UIDefaults} table for the current
406 * {@link LookAndFeel}.
408 * @param key the key.
410 * @return The object.
414 public static Object
get(Object key
, Locale locale
)
416 return getDefaults().get(key
, locale
);
420 * Returns a boolean value from the defaults table. If there is no value
421 * for the specified key, or the value is not an instance of {@link Boolean},
422 * this method returns <code>false</code>.
424 * @param key the key (<code>null</code> not permitted).
426 * @return The boolean value associated with the specified key.
428 * @throws NullPointerException if <code>key</code> is <code>null</code>.
432 public static boolean getBoolean(Object key
)
434 Object value
= get(key
);
435 if (value
instanceof Boolean
)
436 return ((Boolean
) value
).booleanValue();
441 * Returns a boolean value from the defaults table. If there is no value
442 * for the specified key, or the value is not an instance of {@link Boolean},
443 * this method returns <code>false</code>.
445 * @param key the key (<code>null</code> not permitted).
446 * @param locale the locale.
448 * @return The boolean value associated with the specified key.
450 * @throws NullPointerException if <code>key</code> is <code>null</code>.
454 public static boolean getBoolean(Object key
, Locale locale
)
456 Object value
= get(key
, locale
);
457 if (value
instanceof Boolean
)
458 return ((Boolean
) value
).booleanValue();
463 * Returns a border from the defaults table.
465 * @param key the key (<code>null</code> not permitted).
467 * @return The border associated with the given key, or <code>null</code>.
469 * @throws NullPointerException if <code>key</code> is <code>null</code>.
471 public static Border
getBorder(Object key
)
473 Object value
= get(key
);
474 if (value
instanceof Border
)
475 return (Border
) value
;
480 * Returns a border from the defaults table.
482 * @param key the key (<code>null</code> not permitted).
483 * @param locale the locale.
485 * @return The border associated with the given key, or <code>null</code>.
487 * @throws NullPointerException if <code>key</code> is <code>null</code>.
491 public static Border
getBorder(Object key
, Locale locale
)
493 Object value
= get(key
, locale
);
494 if (value
instanceof Border
)
495 return (Border
) value
;
500 * Returns a drawing color from the defaults table.
502 * @param key the key (<code>null</code> not permitted).
504 * @return The color associated with the given key, or <code>null</code>.
506 * @throws NullPointerException if <code>key</code> is <code>null</code>.
508 public static Color
getColor(Object key
)
510 Object value
= get(key
);
511 if (value
instanceof Color
)
512 return (Color
) value
;
517 * Returns a drawing color from the defaults table.
519 * @param key the key (<code>null</code> not permitted).
520 * @param locale the locale.
522 * @return The color associated with the given key, or <code>null</code>.
524 * @throws NullPointerException if <code>key</code> is <code>null</code>.
528 public static Color
getColor(Object key
, Locale locale
)
530 Object value
= get(key
, locale
);
531 if (value
instanceof Color
)
532 return (Color
) value
;
537 * The fully qualified class name of the cross platform (Metal) look and feel.
538 * This string can be passed to Class.forName()
540 * @return <code>"javax.swing.plaf.metal.MetalLookAndFeel"</code>
542 public static String
getCrossPlatformLookAndFeelClassName()
544 return "javax.swing.plaf.metal.MetalLookAndFeel";
548 * Returns the default values for this look and feel.
550 * @return The {@link UIDefaults} for the current {@link LookAndFeel}.
552 public static UIDefaults
getDefaults()
554 if (currentUIDefaults
== null)
555 currentUIDefaults
= new MultiplexUIDefaults(new UIDefaults());
556 return currentUIDefaults
;
560 * Returns a dimension from the defaults table.
562 * @param key the key (<code>null</code> not permitted).
564 * @return The color associated with the given key, or <code>null</code>.
566 * @throws NullPointerException if <code>key</code> is <code>null</code>.
568 public static Dimension
getDimension(Object key
)
570 Object value
= get(key
);
571 if (value
instanceof Dimension
)
572 return (Dimension
) value
;
577 * Returns a dimension from the defaults table.
579 * @param key the key (<code>null</code> not permitted).
580 * @param locale the locale.
582 * @return The color associated with the given key, or <code>null</code>.
584 * @throws NullPointerException if <code>key</code> is <code>null</code>.
587 public static Dimension
getDimension(Object key
, Locale locale
)
589 Object value
= get(key
, locale
);
590 if (value
instanceof Dimension
)
591 return (Dimension
) value
;
596 * Retrieves a font from the defaults table of the current
599 * @param key an Object that specifies the font. Typically,
600 * this is a String such as
601 * <code>TitledBorder.font</code>.
603 * @return The font associated with the given key, or <code>null</code>.
605 * @throws NullPointerException if <code>key</code> is <code>null</code>.
607 public static Font
getFont(Object key
)
609 Object value
= get(key
);
610 if (value
instanceof Font
)
616 * Retrieves a font from the defaults table of the current
619 * @param key an Object that specifies the font. Typically,
620 * this is a String such as
621 * <code>TitledBorder.font</code>.
622 * @param locale the locale.
624 * @return The font associated with the given key, or <code>null</code>.
626 * @throws NullPointerException if <code>key</code> is <code>null</code>.
630 public static Font
getFont(Object key
, Locale locale
)
632 Object value
= get(key
, locale
);
633 if (value
instanceof Font
)
639 * Returns an icon from the defaults table.
641 * @param key the key (<code>null</code> not permitted).
643 * @return The icon associated with the given key, or <code>null</code>.
645 * @throws NullPointerException if <code>key</code> is <code>null</code>.
647 public static Icon
getIcon(Object key
)
649 Object value
= get(key
);
650 if (value
instanceof Icon
)
656 * Returns an icon from the defaults table.
658 * @param key the key (<code>null</code> not permitted).
659 * @param locale the locale.
661 * @return The icon associated with the given key, or <code>null</code>.
663 * @throws NullPointerException if <code>key</code> is <code>null</code>.
666 public static Icon
getIcon(Object key
, Locale locale
)
668 Object value
= get(key
, locale
);
669 if (value
instanceof Icon
)
675 * Returns an Insets object from the defaults table.
677 * @param key the key (<code>null</code> not permitted).
679 * @return The insets associated with the given key, or <code>null</code>.
681 * @throws NullPointerException if <code>key</code> is <code>null</code>.
683 public static Insets
getInsets(Object key
)
686 if (o
instanceof Insets
)
693 * Returns an Insets object from the defaults table.
695 * @param key the key (<code>null</code> not permitted).
696 * @param locale the locale.
698 * @return The insets associated with the given key, or <code>null</code>.
700 * @throws NullPointerException if <code>key</code> is <code>null</code>.
703 public static Insets
getInsets(Object key
, Locale locale
)
705 Object o
= get(key
, locale
);
706 if (o
instanceof Insets
)
713 * Returns an array containing information about the {@link LookAndFeel}s
714 * that are installed.
716 * @return A list of the look and feels that are available (installed).
718 public static LookAndFeelInfo
[] getInstalledLookAndFeels()
724 * Returns the integer value of the {@link Integer} associated with the
725 * given key. If there is no value, or the value is not an instance of
726 * {@link Integer}, this method returns 0.
728 * @param key the key (<code>null</code> not permitted).
730 * @return The integer value associated with the given key, or 0.
732 public static int getInt(Object key
)
735 if (x
instanceof Integer
)
736 return ((Integer
) x
).intValue();
741 * Returns the integer value of the {@link Integer} associated with the
742 * given key. If there is no value, or the value is not an instance of
743 * {@link Integer}, this method returns 0.
745 * @param key the key (<code>null</code> not permitted).
746 * @param locale the locale.
748 * @return The integer value associated with the given key, or 0.
752 public static int getInt(Object key
, Locale locale
)
754 Object x
= get(key
, locale
);
755 if (x
instanceof Integer
)
756 return ((Integer
) x
).intValue();
761 * Returns the current look and feel (which may be <code>null</code>).
763 * @return The current look and feel.
765 * @see #setLookAndFeel(LookAndFeel)
767 public static LookAndFeel
getLookAndFeel()
769 return currentLookAndFeel
;
773 * Returns the <code>UIDefaults</code> table of the currently active
776 * @return The {@link UIDefaults} for the current {@link LookAndFeel}.
778 public static UIDefaults
getLookAndFeelDefaults()
780 return lookAndFeelDefaults
;
784 * Returns the {@link String} associated with the given key. If the value
785 * is not a {@link String}, this method returns <code>null</code>.
787 * @param key the key (<code>null</code> not permitted).
789 * @return The string associated with the given key, or <code>null</code>.
791 public static String
getString(Object key
)
794 if (s
instanceof String
)
800 * Returns the {@link String} associated with the given key. If the value
801 * is not a {@link String}, this method returns <code>null</code>.
803 * @param key the key (<code>null</code> not permitted).
804 * @param locale the locale.
806 * @return The string associated with the given key, or <code>null</code>.
810 public static String
getString(Object key
, Locale locale
)
812 Object s
= get(key
, locale
);
813 if (s
instanceof String
)
819 * Returns the name of the {@link LookAndFeel} class that implements the
820 * native systems look and feel if there is one, otherwise the name
821 * of the default cross platform LookAndFeel class.
823 * @return The fully qualified class name for the system look and feel.
825 * @see #getCrossPlatformLookAndFeelClassName()
827 public static String
getSystemLookAndFeelClassName()
829 return getCrossPlatformLookAndFeelClassName();
833 * Returns UI delegate from the current {@link LookAndFeel} that renders the
836 * @param target the target component.
838 public static ComponentUI
getUI(JComponent target
)
840 return getDefaults().getUI(target
);
844 * Creates a new look and feel and adds it to the current array.
846 * @param name the look and feel name.
847 * @param className the fully qualified name of the class that implements the
850 public static void installLookAndFeel(String name
, String className
)
852 installLookAndFeel(new LookAndFeelInfo(name
, className
));
856 * Adds the specified look and feel to the current array and then calls
857 * setInstalledLookAndFeels(javax.swing.UIManager.LookAndFeelInfo[]).
859 public static void installLookAndFeel(LookAndFeelInfo info
)
861 LookAndFeelInfo
[] newInstalled
= new LookAndFeelInfo
[installed
.length
+ 1];
862 System
.arraycopy(installed
, 0, newInstalled
, 0, installed
.length
);
863 newInstalled
[newInstalled
.length
- 1] = info
;
864 setInstalledLookAndFeels(newInstalled
);
868 * Stores an object in the defaults table.
870 * @param key the key.
871 * @param value the value.
873 public static Object
put(Object key
, Object value
)
875 return getDefaults().put(key
, value
);
879 * Replaces the current array of installed LookAndFeelInfos.
881 public static void setInstalledLookAndFeels(UIManager
.LookAndFeelInfo
[] infos
)
887 * Sets the current {@link LookAndFeel}.
889 * @param newLookAndFeel the new look and feel (<code>null</code> permitted).
891 * @throws UnsupportedLookAndFeelException if the look and feel is not
892 * supported on the current platform.
894 * @see LookAndFeel#isSupportedLookAndFeel()
896 public static void setLookAndFeel(LookAndFeel newLookAndFeel
)
897 throws UnsupportedLookAndFeelException
899 if (newLookAndFeel
!= null && ! newLookAndFeel
.isSupportedLookAndFeel())
900 throw new UnsupportedLookAndFeelException(newLookAndFeel
.getName()
901 + " not supported on this platform");
902 LookAndFeel oldLookAndFeel
= currentLookAndFeel
;
903 if (oldLookAndFeel
!= null)
904 oldLookAndFeel
.uninitialize();
906 // Set the current default look and feel using a LookAndFeel object.
907 currentLookAndFeel
= newLookAndFeel
;
908 if (newLookAndFeel
!= null)
910 newLookAndFeel
.initialize();
911 lookAndFeelDefaults
= newLookAndFeel
.getDefaults();
912 if (currentUIDefaults
== null)
914 new MultiplexUIDefaults(lookAndFeelDefaults
);
916 currentUIDefaults
.fallback
= lookAndFeelDefaults
;
920 currentUIDefaults
= null;
922 listeners
.firePropertyChange("lookAndFeel", oldLookAndFeel
, newLookAndFeel
);
928 * Set the current default look and feel using a class name.
930 * @param className the look and feel class name.
932 * @throws UnsupportedLookAndFeelException if the look and feel is not
933 * supported on the current platform.
935 * @see LookAndFeel#isSupportedLookAndFeel()
937 public static void setLookAndFeel(String className
)
938 throws ClassNotFoundException
, InstantiationException
, IllegalAccessException
,
939 UnsupportedLookAndFeelException
941 Class c
= Class
.forName(className
, true,
942 Thread
.currentThread().getContextClassLoader());
943 LookAndFeel a
= (LookAndFeel
) c
.newInstance(); // throws class-cast-exception