Substance look and feel - themes overview
At runtime, a control (such as button, scroll bar or slider thumb) can be in three
different visual states:
- active - such as a selected toggle button, pressed checkbox,
default root pane button or a slider thumb that is being rolled over (hovered).
A control in active state will always show its background according to the
currently set theme.
- default (not to be confused with a default root pane button) -
enabled control that is not active. A control (mostly buttons)
may be in default state but not display its background (flat controls).
- disabled - any disabled control (no matter if it's selected).
A control (mostly buttons) may be in disabled state but not display its background
(flat controls).
The following screenshot illustrates three buttons in three different visual states:
A Substance theme is a set of information that allows consistent painting of
controls in different visual states. The
org.jvnet.substance.theme.SubstanceTheme is the base class for
all Substance themes.
A theme uses the underlying color scheme to capture the relevant color
information. All color schemes implement the
org.jvnet.substance.color.ColorScheme interface.
Substance themes can be roughly grouped into three categories:
- simple themes. Such a theme uses a single color scheme for
painting the controls in active visual state. In addition, it uses the predefined metallic and
gray color schemes for painting the controls in default and disabled visual state.
- derived themes. Such a theme is based on another (not necessarily simple)
theme, making some derivation on it:
The derivation usually applies to controls in all
visual states to maintain the painting consistency.
- complex themes. Such a theme is based on a number of other (not
necessarily simple) themes, each one describing a particular component visual state
or application painting.
Substance allows changing theme at runtime, providing a function that retrieves information
on all available themes. In addition, Substance uses plugin mechanism to automatically
discover additional themes at runtime.
Color schemes
A color scheme must implement org.jvnet.substance.color.ColorScheme
interface. This interface defines the following seven functions:
- Color getForegroundColor() - retrieves color for foreground
elements (such as text of a button).
- Color getUltraLightColor() - retrieves ultra-light color.
- Color getExtraLightColor() - retrieves extra-light color.
- Color getLightColor() - retrieves light color.
- Color getMidColor() - retrieves medium color.
- Color getDarkColor() - retrieves dark color.
- Color getUltraDarkColor() - retrieves ultra-dark color.
These functions (except the first) are used at runtime to paint the background of UI
components (depending on their visual state). Note that the colors are used in gradients
and interpolations, so there is no one-to-one mapping chart that defines all the uses of a certain color.
It is recommended to order the colors by brightness, making the getUltraDarkColor()
return the least bright color and getUltraLightColor() return
the brightest color.
Themes
A theme must extend org.jvnet.substance.theme.SubstanceTheme
base class (which is a MetalTheme). The single constructor of SubstanceTheme
gets the following parameters:
- ColorScheme colorScheme - the corresponding color scheme. It will
be used for the painting.
- String displayName - the display name of the theme.
- ThemeKind themeKind - the theme kind (bright, cold, dark, ...). This
indication will be used for computing interpolated colors for various components.
In addition, it is used to compute the correct metallic and gray schemes.
There are three options for using themes in Substance look and feel.
The available core themes are located in org.jvnet.substance.theme
package (see color scheme chart).
The AQUA theme is the default. If you do not use the below options, the AQUA
theme will be used. In order to change the current theme, you can
- Call SubstanceLookAndFeel.setCurrentTheme() with one of the
above themes, for example SubstanceLookAndFeel.setCurrentTheme(new
SubstanceBrownTheme())
- Call SubstanceLookAndFeel.setCurrentTheme() with the fully
qualified name of one of the above themes, for example
SubstanceLookAndFeel.setCurrentTheme("org.jvnet.substance.theme.SubstanceBrownTheme")
- Set substancelaf.theme parameter of the VM, for example
-Dsubstancelaf.theme=org.jvnet.substance.theme.SubstanceBrownTheme
If you use one of the first two options after your application has started,
don't forget to call:
UIManager.setLookAndFeel(new SubstanceLookAndFeel());
SwingUtilities.updateComponentTreeUI(...);
The first call is mandatory in versions 2.2, 2.3 and 3.0. The second call should be
performed on all open frames (you can use Frame.getFrames() function).
Providing custom themes
Substance provides two ways for specifying custom themes.
The first option is by using the SubstanceTheme constructor
as described above. The newly created
SubstanceTheme object can then be used as a parameter
to SubstanceLookAndFeel.setCurrentTheme function.
The second option is to use Substance plugin mechanism that discovers the additional
themes at runtime. This approach is taken by both Substance itself and by the
Substance theme pack subproject. As with
all Substance plugins, you must pack an additional XML configuration file in one of your
runtime jarfiles. The name of this file must be substance-plugin.xml and it must
comply with the following syntax:
<laf-plugin>
additional optional tags
<theme-plugin-class>...</theme-plugin-class>
additional optional tags
</laf-plugin>
The contents of theme-plugin-class tag must be the
fully-qualified class name of a class that implements the
SubstanceThemePlugin interface. This interface specifies a
single function:
public Set<ThemeInfo> getThemes();
The ThemeInfo class contains information on
a single (base or custom) theme. Its single constructor gets the following three parameters:
- String theme display name
- String theme class name
- ThemeKind - bright / cold / dark
In addition, this class provides the setDefault function
that can mark a theme as default.
In case you provide a class that implements the SubstanceThemePlugin
interface (the second option), you can use the setDefault
function of a ThemeInfo class to specify your own
default theme. In case you specify none, AQUA will be taken.
Note that using the second option you may override the color themes supplied
with Substance base package (by specifying the same display name). This
behaviour, however, is not guaranteed to be consistent across various VMs
and class loaders, since the theme plugins are processed in random order.
Retrieving information on themes
All the functions are in SubstanceLookAndFeel
- To retrieve the display name of the current theme use
/**
* Returns the current color theme name.
*
* @return Current color theme name.
*/
public static String getCurrentThemeName()
- To retrieve the current theme use
/**
* Returns the current theme.
*
* @return The current theme.
*/
public static SubstanceTheme getTheme()
- To retrieve information on all available themes use
/**
* Returns all available themes.
*
* @return All available color themes. Key - theme name, value - theme
* information.
*/
public static Map<String, ThemeInfo> getAllThemes()