-
Notifications
You must be signed in to change notification settings - Fork 32
Styles
Elements are styled using a system similar to cascading style sheets. However,
the styles are provided entirely programmatically and instead of using style
names, one uses Styles
instances which contain style configuration.
Styles are used to configure a variety of properties of interface elements. These include the font used to render text, the color of the rendered text, highlight and shadow colors, whether a group aligns its children left, right or center, whether a label aligns its text left, right or center, and so forth.
The Style
class defines properties that are applicable to a variety of
element types (e.g. Style.FONT
). Styles that are applicable to only a single
element type are defined in the element's class (e.g. Group.BACKGROUND
).
See Common Use Cases below for examples of configuring elements with styles.
There are numerous elements that interplay in the resolution of styles: the
type of the element in question (e.g. Button
), the interface hierarchy (e.g.
a Button
, its parent Group
, on up to the Root
), and the state of the
element (e.g. default, disabled, down).
Two classes model the configuration of styles in an interface: Styles
and
Stylesheet
. Styles
defines styles applied to a single user interface
element (see below on how Styles
are applied to multiple elements).
Stylesheet
defines styles that apply to all elements of a given type (e.g.
Button
, Label
, etc.) and can only be configured on Group
elements.
The resolution of a style proceeds as follows:
-
The element's
Styles
instance is checked for the desired style in the element's current state. If a binding is found, it is used. -
If the element is itself a group, step 3 is performed using the element itself, otherwise the element's parent is checked, per the normal step 3 resolution.
-
The
Stylesheet
configured for the element's parent group is checked for a binding for the triple(type, state, style)
(e.g.(Button, down, background)
). If one is found, it is used. -
If the style being sought is inherited, the original element's parent type is next queried for a binding (e.g.
(Element, down, background)
). If no binding is found, the next parent type is checked untilElement
has been checked. If the style being sought is not inherited, only the concrete type of the element will be checked. -
If no binding was found in step 3 and 4, the next parent
Group
will have itsStylesheet
searched for a binding. The search will proceed thusly up to theRoot
group. If no binding is found at theRoot
, a global default (provided by the UI toolkit) will be used.
Though the resolution process may seem a bit complex, in general one uses it in a way that is simple and straightforward. The next section will describe these common use cases.
One will usually configure their Root
element with a Stylesheet
that
configures the styles of all interface elements with the desired look and feel
for the game in question.
Where common special stylings are desired for elements (e.g. title labels), one
will generally configure a Styles
instance as desired for the use case and
configure that on all appropriate elements:
public static final Styles titleStyles = Styles.none().
set(Style.FONT, ForPlay.graphics().createFont("Helvetica", Font.Style.BOLD, 24)).
set(Style.COLOR, 0xFF222222);
Label title = new Label("Awesome Things!");
title.setStyles(titleStyles);
If all of the elements in a particular Group
are meant to be customized in a
particular way, a Stylesheet
can be provided to the Group
when constructed:
Stylesheet sheet = Stylesheet.builder().
add(Button.class, Styles.none().set(Style.FONT, smallFont)).
add(Label.class, Styles.none().set(Style.COLOR, 0xFF99CC99)).
create();
Group group = new Group(layout, sheet);