|
A PLAF Lookup Guide for Swing Programmers
By Steve Wilson This article is designed for programmers who need to look up the purpose of one or more functions in this class. It can also give some insight into the design decisions that went into Swing's Pluggable Look and Feel (PLAF) mechanism. |
One of the main responsibilities of a LookAndFeel derived class is to identify the current L&F. The LookAndFeel classes defines three abstract methods that are used to identify a particular L&F. These are:
public abstract String getName(); public abstract String getDescription(); public abstract String getID();
The getName() method is designed to return a string specifying the name of a L&F -- for example "Metal," "Windows," "Joe's Cool Look," or whatever else you want. It's best to keep the name of your L&F short, as it might be used in ListBoxes, or Menus to allow a user to choose a L&F.
The getDescription() method allows a L&F to provide a longer text-based description of itself. So your program can call getDescription() to obtain more information that getName() can return. For example, a look-and-feel might return something like this
"Joe's Cool Look - by Joe - (c) 1998 Joe Inc. All Rights Reserved. http://www.joeinc.com"
The getID() method is a little trickier. It is provided because there are several reasons that one might want to create a L&F. One developer might create a full-blown corporate L&F, while another might just tweak an existing L&F to customize a few components. If you decide to create a custom look-and-feel is that is completely new, custom L&F, getID() should return some unique string to identify itself. If your homemade L&F just customizes a few parts of an existing L&F, getID() generally should return the same string as the L&F you are subclassing.
This approach allows custom third-party components to decide more intelligently how to display themselves. For example, if your L&F is a subclass of the Motif L&F and tweaks only a couple of components, you might not want to override the getID() function at all. Then you could ensure that custom components supplied with special appearances for the Motif L&F would still look correct.
Another key responsibility of any LookAndFeel derived class is to provide information related to platform issues. The LookAndFeel class contains two abstract methods that are designed to provide platform-related information:
public abstract boolean isNativeLookAndFeel();
public abstract boolean isSupportedLookAndFeel();
The isNativeLookAndFeel() method is provided to determine whether a look-and-feel is designed to emulate the current platform. Obtaining this information often involves a runtime query of the system properties. For example, the MotifLookAndFeel class contains the following code:
public boolean isNativeLookAndFeel() {
String osName = System.getProperty("os.name");
return (osName != null) &&
(osName.indexOf("Solaris") != -1);
}
This code snippet returns true if it finds the string Solaris in the string contained in the os.name property. You could write this kind of code for a look-and-feel that's designed to emulate a particular platform (for example, BeOS, GEOS, or Amiga). On the other hand, if you design a cross-platform L&F that doesn't emulate any native OS, isNativeLookAndFeel() should always return false.
The UIManager checks the isSupportedLookAndFeel() method before a look-and-feel is loaded. If isSupportedLookAndFeel() returns false, the L&F hasn't been loaded. There are a number of reasons why a L&F might not want to run on a particular platform. For example, the L&F might not be written in 100% Pure JavaTM; instead, it might depend on platform-specific features. There may also be competitive or legal reasons for restricting the use of a L&F to certain platforms.
One critical responsibility of a LookAndFeel subclass is to create a Defaults Table. In Swing, a Defaults Table is a set of Key-Value pairs stored in a UIDefaultsapi object. The LookAndFeel class defines a single function in charge of creating the defaults table.
public UIDefaults getDefaults()
The defaults table typically consists of three main categories of information:
NOTE: If you are building a special purpose L&F for use with the Multiplexing UI system, then you still need to provide a UI Classmap, but the other two categories of information may not be important. If you are creating a full L&F implementation, you should provide all three types.
The UIClassmap is built of paired Strings. These pairs are used to associate a subclass of JComponent with a subclass of ComponentUI. Components use this mapping to create their associated UI objects. For each subclass of JComponent, there is a unique String tag to describe that component. To construct each tag, the "J" is removed from the name of its component, and a "UI" suffix is added. There are a few exceptions -- caused by the fact that some UI classes don't have corresponding "J" classes (for example, DesktopIconUI) -- but these are exceptions.
The following table presents a list of tags used in Swing 1.1.
|
In a UIClassmap, each entry is composed of a key (one of the tags above) and a value (the fully qualified name of the class which will be used for that component). BasicLookAndFeel provides a special function call initClassDefaults() to assist in building this table. For more information how these values are used, see the archived article titled "A Swing Architecture Overview."
Another part of the defaults table defines SystemColors. The System Colors part of the defaults table consists of a series of key-value pairs that map to entries in the java.awt.SystemColor class. A full-blown L&F usually provides this section of the table, but it could be left out of an L&F that is part of an auxiliary L&F designed for use with the Multiplexing L&F system. Here is a list of the system colors, along with a short description of each entry:
Each entry in this part of the table is composed of a key (one of the strings above) and a value ( a ColorUIResourceapi that describes the color to be used). This BasicLookAndFeel class provides a function called initSystemColorDefaults() to assist in building this section of the defaults table.
The last section of the defaults table consists of a set of Component defaults. These typically consist of the Colors, Fonts, and Icons used in each type of component. A full-blown L&F usually provides this section of the table, but it could be left out of an L&F that is part of an auxiliary L&F designed for use with the Multiplexing L&F system. Each component in your L&F will probably provide several several entries. For example the keys for these entries might look like this:
Each value for an associated key should consist of an object which is a subclass of UIResourceapi (link to UIResource stuff here). This BasicLookAndFeel class provides a function called initComponentDefaults to assist in building this section of the defaults table.
Application developers and L&F developers use the same methods to effect the state of components. The UIResource interface is used to differentiate Colors, Fonts, Borders and other objects created by the L&F from similar objects created by the application developer. Most objects installed by the L&F are "tagged" with the UIResource interface. L&F classes can use the instanceof keyword to determine if a given object was installed by the application or the L&F. Values installed by the application typically take precedence over values installed by the L&F. Note that the UIResource interface defines no methods. UIResource is a pure "tagging" interface.
Several subclasses of UIResource areprovided for the convenience of L&F developers. These include:
UIResource-derived objects are typically stored in the defaults table, which is accessed through the UIManager.
One function is the single bottleneck point for accessing the defaults table:
public static Object get(Object key)
This function returns type Object; however, the UIManager also provides several convenience methods for accessing the defaults table in a type-safe manner. These include:
public static Font getFont(Object key) public static Color getColor(Object key) public static Icon getIcon(Object key) public static Border getBorder(Object key public static Insets getInsets(Object key) public static Dimension getDimension(Object key)
Note that there are two additional functions provided by the UIManager class that are in a slightly different category. While these are type-safe ways to access the defaults table, they do not return subclasses of UIResource.
public static String getString(Object key) public static int getInt(Object key)
These functions don't return UIResource subclasses because both java.lang.String and java.lang.Integer are "final" and cannot be subclassed. That means they cannot be tagged with the UIResource interface. Consequently, L&F developers must use other mechanisms other than the UIResource tag to determine the origin of such objects.
Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.
|
| ||||||||||||