Skip to content

Theming

Jannis Weis edited this page May 19, 2020 · 4 revisions

Theming

Note: This page is currently not up to date.

This look and feel supports custom themes where you can customize (almost) everything. A theme consists of two parts. The theme property files and the theme class declaration. A simple example for the latter may look like this.

package my.custom.theme;

public class MyCustomTheme extends Theme {

    @Override
    public String getName() {
        return "MyCustomTheme";
    }

    @Override
    protected String getResourcePath() {
        return "resources/";
    }

    @Override
    public boolean useCustomDecorations() {
        return true;
    }

    @Override
    public boolean useDarkIcons() {
        return true;
    }

    @Override
    protected IconTheme getPresetIconTheme() {
        return IconTheme.NONE;
    }
}

The folder structure would look as follows:

my
└── custom
    └── theme
        ├── MyCustomTheme.java
        └── resources
            ├── MyCustomTheme_defaults.properties
            ├── MyCustomTheme_icons.properties
            └── MyCustomTheme_styleSheet.css

So whats going on here? The getName() function gives the name of the theme used as a prefix to load the property files during setup. To resolve the resource path the getResourcePath() function give the location of the files relative to the package location. The two files MyCustomTheme_defaults.properties and MyCustomTheme_styleSheet.css contain the default values for most of the UI prperties. The latter only being responsible for the values of HTMLEditorKit. Examples for both files can be found here.

You can overwrite whether you wan't to use the custom decorations (if supported on the given platform) by overwriting useCustomDecorations(). useDarkIcons() determines whether the dark or light icon should be used when given an UIAwareIcon. You can use one of the already definite icons sets (dark/light) by returning IconTheme.DARK or IconTheme.LIGHT in getPresetIconTheme(). If you return IconTheme.NONE you need to load a seperate file with the icon colors. Of course you can load your own icons (see below on how to. Also look at Icons)

*_defaults.properties

In this file all the default values that are used throughout the UI can be set. Each ui-class has it's own properties file (see [here]https://github.com/weisJ/darklaf/tree/master/src/main/resources/com/weis/darklaf/properties/ui). Almost all of these values reference a value from the default properties (inidcated by a % prefix).

You will notice that all keys in *_defaults.properties also start with %. This is not strictly necessary but helps the property parser to understand that this value is not a value that needs to be instantiated. (see how values are parsed).

For a simple change of color changing this file will be completely sufficient. However if you wish to have more fine grained control you can change individual values during one of the separate property loading phases. Each phase is housed in it's own method inside the Theme class.

*_icons.properties

This file specifies the colors used for icons.

1. Phase: beforeInstall()

This method is called when the Laf instance is created. In the default i implementation the appropriate theme for ````MetalLookAndFeel`````is set.

2. Phase loadDefaults()

In this phase the values from *_defaults.properties are loaded.

3. Phase loadGlobals()

The third phase loads the global default values. All global values have a key that starts with global.. By default all global values sit in a separate globals.properties file but they can be also declared in the defaults properties files (with the difference that you may not rely on referencing previously declared values). At this point all keys in the defaults of the base look and feel (e.g. MetalLookAndFeel) will be matched against the suffix of the global key (i.e. the part after global.) and have their value replaced accordingly.

Example

The global value global.background = ffffff will match all values of the form *.background and set their value to ffffff.

The globals do not overwrite values that are loaded in subsequent phases.

4. Phase loadUIProperties()

This phase loads all properties needed for the ui classes to function correctly and tells swing to use the correct ui classes. If you wan't to load custom values during this phase you must call super.loadUIProperties() or otherwise the look and feel will be broken.

5. Phase loadIconProperties()

During this phase the file <theme>_icons.propertis is loaded, or one of the pre-set files if given.

6. Phase loadPlatformProperties()

In the last phase platform specific defaults can be loaded.