home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 November
/
Chip_1998-11_cd.bin
/
tema
/
Cafe
/
jfc.bin
/
UIManager.java
< prev
next >
Wrap
Text File
|
1998-02-26
|
22KB
|
661 lines
/*
* @(#)UIManager.java 1.54 98/02/23
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not disclose
* such Confidential Information and shall use it only in accordance with the
* terms of the license agreement you entered into with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
* OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
* ITS DERIVATIVES.
*
*/
package com.sun.java.swing;
import java.awt.Container;
import java.awt.Window;
import java.awt.Font;
import java.awt.Color;
import com.sun.java.swing.plaf.ComponentUI;
import com.sun.java.swing.border.Border;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.io.File;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* This class keeps track of the current look and feel and its
* defaults.
* <p>
* We manage three levels of defaults: user defaults, look
* and feel defaults, system defaults. A call to UIManager.get()
* checks all three levels in order and returns the first non-null
* value for a key, if any. A call to UIManager.put() just
* affects the user defaults. Note that a call to
* setLookAndFeel() doesn't affect the user defaults, it just
* replaces the middle defaults "level".
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @version 1.54 02/23/98
* @author Thomas Ball
* @author Hans Muller
*/
public class UIManager implements Serializable
{
/**
* This class defines the state managed by the UIManager. For
* Swing applications the fields in this class could just as well
* be static members of UIManager however we give them "AppContext"
* scope instead so that applets (and potentially multiple lightweight
* applications running in a single VM) have their own state. For
* example an applet can it's look and feel, see setLookAndFeel().
* Doing so has no affect on other applets (or the browser).
*/
private static class LAFState
{
private UIDefaults[] tables = new UIDefaults[2];
boolean initialized = false;
MultiUIDefaults multiUIDefaults = new MultiUIDefaults(tables);
LookAndFeel lookAndFeel;
LookAndFeel multiLookAndFeel = null;
Vector auxLookAndFeels = null;
PropertyChangeSupport changeSupport = new PropertyChangeSupport(UIManager.class);
UIDefaults getLookAndFeelDefaults() { return tables[0]; }
void setLookAndFeelDefaults(UIDefaults x) { tables[0] = x; }
UIDefaults getSystemDefaults() { return tables[1]; }
void setSystemDefaults(UIDefaults x) { tables[1] = x; }
}
/**
* The AppContext key for our one LAFState instance.
*/
private static final Object lafStateACKey = new StringBuffer("LookAndFeel State");
/**
* Return the LAFState object, lazily create one if neccessary. All access
* to the LAFState fields is done via this method, e.g.:
* <pre>
* getLAFState().initialized = true;
* </pre>
*/
private static LAFState getLAFState() {
LAFState rv = (LAFState)SwingUtilities.appContextGet(lafStateACKey);
if (rv != null) {
return rv;
}
synchronized(UIManager.class) {
rv = (LAFState)SwingUtilities.appContextGet(lafStateACKey);
if (rv != null) {
return rv;
}
SwingUtilities.appContextPut(lafStateACKey, (rv = new LAFState()));
return rv;
}
}
/* Keys used for the properties file in <java.home>/lib/swing.properties.
* See loadUserProperties(), initialize().
*/
private static final String defaultLAFKey = "swing.defaultlaf";
private static final String auxiliaryLAFsKey = "swing.auxiliarylaf";
private static final String multiplexingLAFKey = "swing.plaf.multiplexinglaf";
private static final String installedLAFsKey = "swing.installedlafs";
/**
* Return a swing.properties file key for the attribute of specified
* look and feel. The attr is either "name" or "class", a typical
* key would be: "swing.installedlaf.windows.name"
*/
private static String makeInstalledLAFKey(String laf, String attr) {
return "swing.installedlaf." + laf + "." + attr;
}
/**
* The filename for swing.properties is a path like this (Unix version):
* <java.home>/lib/swing.properties. This method returns a bogus
* filename if java.home isn't defined.
*/
private static String makeSwingPropertiesFilename() {
String sep = File.separator;
String homeDir = System.getProperty("java.home", "<java.home undefined>");
return homeDir + sep + "lib" + sep + "swing.properties";
}
/**
* Provide a little information about an installed LookAndFeel
* for the sake of configuring a menu or for initial application
* set up.
*
* @see #getInstalledLookAndFeels
* @see LookAndFeel
*/
public static class LookAndFeelInfo {
private String name;
private String className;
public LookAndFeelInfo(String name, String className) {
this.name = name;
this.className = className;
}
/**
* @return a name suitable for a menu or other presentation
* @see LookAndFeel#getName
*/
public String getName() {
return name;
}
/**
* @return the name of the class that implements this LookAndFeel.
* @see LookAndFeel
*/
public String getClassName() {
return className;
}
public String toString() {
return getClass().getName() + "[" + getName() + " " + getClassName() + "]";
}
}
/**
* The default value of installedLAFS is used when no swing.properties
* file is available or if the file doesn't contain a "swing.installedlafs"
* property.
*
* @see #initializeInstalledLAFs
*/
private static LookAndFeelInfo[] installedLAFs = {
new LookAndFeelInfo("Metal", "com.sun.java.swing.plaf.metal.MetalLookAndFeel"),
new LookAndFeelInfo("CDE/Motif", "com.sun.java.swing.plaf.motif.MotifLookAndFeel"),
new LookAndFeelInfo("Windows", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel")
};
/**
* Return an array of objects that provide some information about the
* LookAndFeel implementations that have been installed with this
* java development kit. The LookAndFeel info objects can be used
* by an application to construct a menu of look and feel options for
* the user or to set the look and feel at start up time. Note that
* we do not return the LookAndFeel classes themselves here to avoid the
* cost of unnecessarily loading them.
* <p>
* Given a LookAndFeelInfo object one can set the current look and feel
* like this:
* <pre>
* UIManager.setLookAndFeel(info.getClassName());
* </pre>
*
* @see #setLookAndFeel
*/
public static LookAndFeelInfo[] getInstalledLookAndFeels() {
maybeInitialize();
LookAndFeelInfo[] ilafs = installedLAFs;
LookAndFeelInfo[] rv = new LookAndFeelInfo[ilafs.length];
System.arraycopy(ilafs, 0, rv, 0, ilafs.length);
return rv;
}
/**
* Replaces the current array of installed LookAndFeelInfos.
*
* @see #getInstalledLookAndFeels
*/
public static void setInstalledLookAndFeels(LookAndFeelInfo[] infos)
throws SecurityException
{
LookAndFeelInfo[] newInfos = new LookAndFeelInfo[infos.length];
System.arraycopy(infos, 0, newInfos, 0, infos.length);
installedLAFs = newInfos;
}
/**
* Adds the specified look and feel to the current array and
* then calls setInstalledLookAndFeels.
*
* @see #setInstalledLookAndFeels
*/
public static void installLookAndFeel(LookAndFeelInfo info) {
LookAndFeelInfo[] infos = getInstalledLookAndFeels();
LookAndFeelInfo[] newInfos = new LookAndFeelInfo[infos.length + 1];
System.arraycopy(infos, 0, newInfos, 0, infos.length);
newInfos[infos.length] = info;
setInstalledLookAndFeels(newInfos);
}
public static void installLookAndFeel(String name, String className) {
installLookAndFeel(new LookAndFeelInfo(name, className));
}
/**
* Returns The current default look and feel, or null.
*
* @return The current default look and feel, or null.
* @see #setLookAndFeel
*/
public static LookAndFeel getLookAndFeel() {
maybeInitialize();
return getLAFState().lookAndFeel;
}
/**
* Set the current default look and feel.
* <p>
* This is a JavaBeans bound property.
*
* @exception UnsupportedLookAndFeelException If <code>lnf.isSupportedLookAndFeel()</code> is false.
* @see #getLookAndFeel
*/
public static void setLookAndFeel(LookAndFeel newLookAndFeel)
throws UnsupportedLookAndFeelException
{
if ((newLookAndFeel != null) && !newLookAndFeel.isSupportedLookAndFeel()) {
String s = newLookAndFeel.toString() + " not supported on this platform";
throw new UnsupportedLookAndFeelException(s);
}
LookAndFeel oldLookAndFeel = getLAFState().lookAndFeel;
if (oldLookAndFeel != null) {
oldLookAndFeel.uninitialize();
}
getLAFState().lookAndFeel = newLookAndFeel;
if (newLookAndFeel != null) {
newLookAndFeel.initialize();
getLAFState().setLookAndFeelDefaults(newLookAndFeel.getDefaults());
}
else {
getLAFState().setLookAndFeelDefaults(null);
}
getLAFState().changeSupport.firePropertyChange("lookAndFeel", oldLookAndFeel, newLookAndFeel);
}
/**
* @exception ClassNotFoundException If the LookAndFeel class could not be found.
* @exception InstantiationException If a new instance of the class couldn't be creatd.
* @exception IllegalAccessException If the class or initializer isn't accessible.
* @exception UnsupportedLookAndFeelException If <code>lnf.isSupportedLookAndFeel()</code> is false.
*/
public static void setLookAndFeel(String className)
throws ClassNotFoundException,
InstantiationException,
IllegalAccessException,
UnsupportedLookAndFeelException
{
Class lnfClass = Class.forName(className);
setLookAndFeel((LookAndFeel)(lnfClass.newInstance()));
}
/**
* Returns the name of the LookAndFeel class that implements
* the native systems look and feel if there is one,
* otherwise the name of the default cross platform LookAndFeel
* class.
*
* @see #setLookAndFeel()
* @see #getCrossPlatformLookAndFeelClassName
*/
public static String getSystemLookAndFeelClassName() {
String osName = System.getProperty("os.name");
if (osName != null) {
if (osName.indexOf("Windows") != -1) {
return "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
}
else if (osName.indexOf("Solaris") != -1) {
return "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
}
}
return getCrossPlatformLookAndFeelClassName();
}
/**
* Returns the name of the LookAndFeel class that implements
* the default cross platform look and feel, i.e. the "metal"
* look and feel.
*
* @return "com.sun.java.swing.plaf.metal.MetalLookAndFeel"
* @see #setLookAndFeel()
* @see #getSystemLookAndFeelClassName
*/
public static String getCrossPlatformLookAndFeelClassName() {
return "com.sun.java.swing.plaf.metal.MetalLookAndFeel";
}
public static UIDefaults getDefaults() {
maybeInitialize();
return getLAFState().multiUIDefaults;
}
public static Font getFont(Object key) {
return getDefaults().getFont(key);
}
public static Color getColor(Object key) {
return getDefaults().getColor(key);
}
public static Icon getIcon(Object key) {
return getDefaults().getIcon(key);
}
public static Border getBorder(Object key) {
return getDefaults().getBorder(key);
}
public static String getString(Object key) {
return getDefaults().getString(key);
}
public static Object get(Object key) {
return getDefaults().get(key);
}
public static Object put(Object key, Object value) {
return getDefaults().put(key, value);
}
public static ComponentUI getUI(JComponent target) {
maybeInitialize();
ComponentUI ui = null;
LookAndFeel multiLAF = getLAFState().multiLookAndFeel;
if (multiLAF != null) {
// This can return null if the multiplexing look and feel
// doesn't support a particular UI.
ui = multiLAF.getDefaults().getUI(target);
}
if (ui == null) {
ui = getDefaults().getUI(target);
}
return ui;
}
public static UIDefaults getLookAndFeelDefaults() {
maybeInitialize();
return getLAFState().getLookAndFeelDefaults();
}
/**
* Return the list of auxiliary look and feels (can be null). The
* auxiliary look and feels tell the multiplexing look and feel what
* other LookAndFeel classes for a component instance are to be used
* in addition to the default LookAndFeel class when creating a
* multiplexing UI.
* <p>Note these are not the same as the installed look and feels.
* @see #getInstalledLookAndFeels
*/
static public LookAndFeel[] getAuxiliaryLookAndFeels()
{
maybeInitialize();
Vector v = getLAFState().auxLookAndFeels;
if ((v == null) || (v.size() == 0)) {
return null;
}
else {
LookAndFeel[] rv = new LookAndFeel[v.size()];
for (int i = 0; i < rv.length; i++) {
rv[i] = (LookAndFeel)v.elementAt(i);
}
return rv;
}
}
/**
* Add a PropertyChangeListener to the listener list.
* The listener is registered for all properties.
*
* @param listener The PropertyChangeListener to be added
* @see java.beans.PropertyChangeSupport
*/
public synchronized static void addPropertyChangeListener(PropertyChangeListener listener)
{
getLAFState().changeSupport.addPropertyChangeListener(listener);
}
/**
* Remove a PropertyChangeListener from the listener list.
* This removes a PropertyChangeListener that was registered
* for all properties.
*
* @param listener The PropertyChangeListener to be removed
* @see java.beans.PropertyChangeSupport
*/
public synchronized static void removePropertyChangeListener(PropertyChangeListener listener)
{
getLAFState().changeSupport.removePropertyChangeListener(listener);
}
private static Properties loadSwingProperties()
{
Properties properties = new Properties();
if (UIManager.class.getClassLoader() == null) {
String sep = File.separator;
try {
File propertiesFile = new File(makeSwingPropertiesFilename());
BufferedInputStream ins = new BufferedInputStream(
new FileInputStream(propertiesFile));
properties.load(ins);
ins.close();
}
catch (Exception e) {
properties.clear();
}
}
return properties;
}
/**
* If a swing.properties file exist and it has a swing.installedlafs property
* then initialize the installedLAFs field.
*
* @see #getInstalledLookAndFeels
*/
private static void initializeInstalledLAFs(Properties swingProps)
{
String ilafsString = swingProps.getProperty(installedLAFsKey);
if (ilafsString == null) {
return;
}
/* Create a vector that contains the value of the swing.installedlafs
* property. For example given "swing.installedlafs=motif,windows"
* lafs = {"motif", "windows"}.
*/
Vector lafs = new Vector();
StringTokenizer st = new StringTokenizer(ilafsString, ",", false);
while (st.hasMoreTokens()) {
lafs.addElement(st.nextToken());
}
/* Look up the name and class for each name in the "swing.installedlafs"
* list. If they both exist then add a LookAndFeelInfo to
* the installedLafs array.
*/
Vector ilafs = new Vector(lafs.size());
for(int i = 0; i < lafs.size(); i++) {
String laf = (String)lafs.elementAt(i);
String name = swingProps.getProperty(makeInstalledLAFKey(laf, "name"), laf);
String cls = swingProps.getProperty(makeInstalledLAFKey(laf, "class"));
if (cls != null) {
ilafs.addElement(new LookAndFeelInfo(name, cls));
}
}
installedLAFs = new LookAndFeelInfo[ilafs.size()];
for(int i = 0; i < ilafs.size(); i++) {
installedLAFs[i] = (LookAndFeelInfo)(ilafs.elementAt(i));
}
}
/**
* If the user has specified a default look and feel, use that.
* Otherwise use the look and feel that's native to this platform.
* If this code is called after the application has expclicitly
* set it's look and feel, do nothing.
*
* @see #maybeInitialize
*/
private static void initializeDefaultLAF(Properties swingProps)
{
if (getLAFState().lookAndFeel != null) {
return;
}
String metalLnf = getCrossPlatformLookAndFeelClassName();
String lnfDefault = metalLnf;
String lnfName = "<undefined>" ;
try {
lnfName = swingProps.getProperty(defaultLAFKey, lnfDefault);
Class lnfClass = Class.forName(lnfName);
setLookAndFeel((LookAndFeel)(lnfClass.newInstance()));
} catch (Exception e) {
try {
lnfName = swingProps.getProperty(defaultLAFKey, metalLnf);
Class lnfClass = Class.forName(lnfName);
setLookAndFeel((LookAndFeel)(lnfClass.newInstance()));
} catch (Exception e2) {
throw new Error("can't load " + lnfName);
}
}
}
private static void initializeAuxiliaryLAFs(Properties swingProps)
{
String auxLookAndFeelNames = swingProps.getProperty(auxiliaryLAFsKey);
if (auxLookAndFeelNames == null) {
return;
}
Vector auxLookAndFeels = new Vector();
StringTokenizer p = new StringTokenizer(auxLookAndFeelNames,",");
String factoryName;
/* Try to load each LookAndFeel subclass in the list.
*/
while (p.hasMoreTokens()) {
String className = p.nextToken();
try {
Class lnfClass = Class.forName(className);
auxLookAndFeels.addElement(lnfClass.newInstance());
}
catch (Exception e) {
System.err.println("UIManager: failed loading auxiliary look and feel " + className);
}
}
/* If there were problems and no auxiliary look and feels were
* loaded, make sure we reset auxLookAndFeels to null.
* Otherwise, we are going to use the MultiLookAndFeel to get
* all component UI's, so we need to load it now.
*/
if (auxLookAndFeels.size() == 0) {
auxLookAndFeels = null;
}
else {
String defaultName = "com.sun.java.swing.plaf.multi.MultiLookAndFeel";
String className = swingProps.getProperty(multiplexingLAFKey, defaultName);
try {
Class lnfClass = Class.forName(className);
getLAFState().multiLookAndFeel = (LookAndFeel)lnfClass.newInstance();
}
catch (Exception exc) {
System.err.println("UIManager: failed loading " + className);
auxLookAndFeels = null;
}
}
getLAFState().auxLookAndFeels = auxLookAndFeels;
}
private static void initializeSystemDefaults(Properties swingProps)
{
Object defaults[] = {
"FocusManagerClassName", "com.sun.java.swing.DefaultFocusManager"
};
getLAFState().setSystemDefaults(new UIDefaults(defaults));
}
private static void initialize()
{
Properties swingProps = loadSwingProperties();
initializeSystemDefaults(swingProps);
initializeDefaultLAF(swingProps);
initializeAuxiliaryLAFs(swingProps);
initializeInstalledLAFs(swingProps);
}
synchronized private static void maybeInitialize() {
if (!getLAFState().initialized) {
initialize();
getLAFState().initialized = true;
}
}
}