The
'LookandFeel' Class Reference
A PLAF Lookup Guide for Swing
Programmers
 |
This document is a technical reference for
the LookAndFeel class. It lays out the intended use of various
portions of the LookAndFeel class, but it is not a tutorial
on how to write your own Look and Feel. That will be the topic
of a future article in The Swing Connection.
|
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.

The LookAndFeel Class
The
LookAndFeel class is the staring point for creating your own L&F.
To create your own L&F, you must create a subclass of the LookAndFeel
class.
The LookAndFeel class has three major responsibilities.
These include:
The LookAndFeel class also provides several static
utility functions to assist in some of these tasks. These will be
discussed later in this article.
Identifying
the Look & Feel
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.
Determining Platform Support
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.
Building a Defaults Table
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 UI Classmap
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.
ButtonUI
|
CheckBoxUI
|
ColorChooserUI
|
MenuBarUI
|
MenuUI
|
MenuItemUI
|
CheckBox-
MenuItemUI
|
RadioButton-
MenuItemUI
|
RadioButtonUI
|
ToggleButtonUI
|
PopupMenuUI
|
ProgressBarUI
|
ScrollBarUI
|
ScrollPaneUI
|
SplitPaneUI
|
SliderUI
|
SeparatorUI
|
ToolBarSeparatorUI
|
PopupMenu-
SeparatorUI
|
TabbedPaneUI
|
TextAreaUI
|
TextFieldUI
|
PasswordFieldUI
|
TextPaneUI
|
EditorPaneUI
|
TreeUI
|
LabelUI
|
ListUI
|
ToolBarUI
|
ToolTipUI
|
ComboBoxUI
|
TableUI
|
TableHeaderUI
|
InternalFrameUI
|
StandardDialogUI
|
DesktopPaneUI
|
DesktopIconUI
|
DirectoryPaneUI
|
FileChooserUI
|
OptionPaneUI
|
|
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."
System Colors
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:
- desktop: Color of the desktop background
- activeCaption: Color for captions (title bars) when
they are active.
- activeCaptionText: Text color for text in captions
(title bars).
- activeCaptionBorder: Border color for caption (title
bar) window borders.
- inactiveCaption: Color for captions (title bars) when
not active.
- inactiveCaptionText: Text color for text in inactive
captions (title bars).
- inactiveCaptionBorder: Border color for inactive caption
(title bar) window borders.
- window: Default color for the interior of windows
- windowBorder: Color of the window's border
- windowText: Color of the window's title text
- menu: Background color for menus
- menuText: Text color for menus
- text: Text background color
- textText: Text foreground color
- textHighlight: Text background color when selected
- textHighlightText: Text color when selected
- textInactiveText: Text color when disabled
- control: Default color for controls (buttons, sliders,
etc)
- controlText: Default color for text in controls
- controlHighlight: Specular highlight (opposite of the
shadow)
- controlLtHighlight: Highlight color for controls
- controlShadow: Shadow color for controls
- controlDkShadow: Dark shadow color for controls
- scrollbar: Scrollbar background (usually the "track")
- info: information color (sometimes used for tooltips)
- infoText: information text color (sometimes used for
tooltips)
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.
Component Defaults
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:
- Button.background.
- Button.foreground.
- Button.font.
- Button.border.
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.
UIResources
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:
- ColorUIResource
- FontUIResource
- BorderUIResource
- IconUIResource
- DimensionUIResource
- InsetsUIResource
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 htat 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.
|