As you have seen, the visual appearance and behavior of Component
s can be configured by setting properties on each Component
instance. This practice can become very repetitive when dealing with significant numbers of heavily configured Component
s. To alleviate this problem, Echo provides "Styles" which may be configured to describe common property settings and then assigned to multiple Component
s.
Styles are defined using the Style
interface. The Style
interface itself only specifies a few methods to retrieve property values, e.g., getPropertyValue()
and getIndexedPropertyValue()
. The MutableStyle
class provides an implementation of Style
that provides property storage and is suitable for general purpose use. While it is entirely possible to roll your own Style
implementation class, it is normally more sensible to create MutableStyle
objects and assign properties to them.
Style
s may be assigned to multiple Component
s. Setting the Style
of a component will not affect a Component
's internal property settings; the information contained in the Style
will only be used for rendering.
The following example demonstrates a Style
being used by multiple Component
s:
MutableStyle buttonStyle = new MutableStyle(); buttonStyle.setProperty( AbstractButton.PROPERTY_BACKGROUND, Color.GREEN); buttonStyle.setProperty( AbstractButton.PROPERTY_BORDER, new Border(2, Color.GREEN, Border.STYLE_GROOVE)); buttonStyle.setProperty( AbstractButton.PROPERTY_ROLLOVER_ENABLED, Boolean.TRUE); buttonStyle.setProperty( AbstractButton.PROPERTY_ROLLOVER_FOREGROUND, Color.BLUE); Button button1 = new Button("Alpha"); button1.setStyle(buttonStyle); parentComponent.add(button1); Button button2 = new Button("Bravo"); button2.setBackground(Color.YELLOW); button2.setStyle(buttonStyle); parentComponent.add(button2); CheckBox checkBox = new Button("Charlie"); checkBox.setStyle(buttonStyle); parentComponent.add(checkBox);
Property Names: The names of properties used in a style may be specified using constants defined within the Component
class for which the Style
will be used. These property name constants will always start with the prefix "PROPERTY_
" followed by the property name, e.g., PROPERTY_FOREGROUND
or PROPERTY_BORDER
. Properties which do not have a constant with such a prefix, such as "visible" or "locale" cannot be defined using Style
s.
Target Components: The buttonStyle
in the above example is intended to be used by any AbstractButton
. As such, the Style
may be used by any AbstractButton
-derivative, such as Button
and CheckBox
as in the example.
Property Precedence: Note as well that in the code configuring button2
, a property is directly assigned to the Button
. Properties which are directly assigned to a Component
will override those specified in the Style
. Thus, in the above example, button2
would be rendered with a yellow (rather than green) background color.
A StyleSheet
represents a collection of named Style
objects. A single StyleSheet
may be assigned to an ApplicationInstance
. Component
s that are registered to that ApplicationInstance
will then be able to reference named Style
s using String-based identifiers. The Component.setStyleName()
method is used to specify the use of a named Style
in the StyleSheet
by a Component
.
Button button1 = new Button("Alpha"); button1.setStyleName("Default");
StyleSheet
s may be programmatically created by instantiating a MutableStyleSheet
and assigning Style
s to it. When a Style
is added to a MutableStyleSheet
the target Component
base class and a style name must be specified. The following code example demonstrates adding Style
s to a MutableStyleSheet
:
MutableStyleSheet styleSheet = new MutableStyleSheet(); styleSheet.addStyle(AbstractButton.class, "Default", buttonStyle); styleSheet.addStyle(AbstractButton.class, "Special", specialButtonStyle); styleSheet.addStyle(TextComponent.class, "Login", loginFieldStyle);
StyleSheet
s may be defined entirely using XML files. Use of this feature is made at the discretion of the developer; as previously shown, StyleSheet
s can be created entirely without the use of XML if desired.
Loading XML StyleSheets: To load a StyleSheet
from an XML file, the nextapp.echo.app.serial.StyleSheetLoader
class is used. The various load()
methods of this class may be used to create StyleSheet
instances from resources in the CLASSPATH or directly from an InputStream
. The following example shows a StyleSheet
being loaded from a resource in the CLASSPATH and placed in a static constant:
public static final StyleSheet DEFAULT_STYLE_SHEET; static { try { DEFAULT_STYLE_SHEET = StyleSheetLoader.load( "/echo3example/email/resource/style/Default.stylesheet", Thread.currentThread().getContextClassLoader()); } catch (SerialException ex) { throw new RuntimeException(ex); } }