[Java] Setting the Window Title Font with the Substance Look and Feel

Fonts for various aspects of the UI is usually by putting the font as a default property in UIManager or UIDefaults. However, there doesn’t seem to be one for the window title. If you were using the Substance look and feel, SubstanceLookAndFeel provides the setFontPolicy(FontPolicy fontPolicy) method. By controlling FontPolicy, you will be able to control the font used for the window title.

Customising the FontSet

FontSet provides Substance with the fonts for various UI components, including the window title. If you want to change only the window title’s font, you need to make sure that the custom FontSet provides the same fonts when the fonts are requested. This can be achieved by delegating to the original FontSet when the other fonts are requested. For example:

public class CustomFontSet implements FontSet {

    /**
     * The delegate that will provide the fonts, other than the window title
     * font.
     */
    private final FontSet delegateFontSet;

    /**
     * The font that will be provided for the title of the window.
     */
    private FontUIResource windowTitleFont;

    /**
     * @param delegateFontSet
     *            provides the fonts other than the one for the window title
     */
    public CustomFontSet(FontSet delegateFontSet) {
        this.delegateFontSet = delegateFontSet;
        this.windowTitleFont = delegateFontSet.getWindowTitleFont();
    }

    /**
     * Sets the font for the window title.
     * 
     * @param titleFont
     *            the font to use
     */
    public void setWindowTitleFont(FontUIResource titleFont) {
        this.windowTitleFont = titleFont;
    }

    @Override
    public FontUIResource getControlFont() {
        return delegateFontSet.getControlFont();
    }

    @Override
    public FontUIResource getMenuFont() {
        return delegateFontSet.getMenuFont();
    }

    @Override
    public FontUIResource getTitleFont() {
        return delegateFontSet.getTitleFont();
    }

    @Override
    public FontUIResource getWindowTitleFont() {
        return windowTitleFont;
    }

    @Override
    public FontUIResource getSmallFont() {
        return delegateFontSet.getSmallFont();
    }

    @Override
    public FontUIResource getMessageFont() {
        return delegateFontSet.getMessageFont();
    }
}

This is how you get the original FontSet and use it for the CustomFontSet:

FontPolicy fontPolicy = SubstanceLookAndFeel.getFontPolicy();
FontSet originalFontSet = fontPolicy.getFontSet("Substance", null);
CustomFontSet fontSet = new CustomFontSet(originalFontSet);

The first argument to FontPolicy.getFontSet (at line 2) tell the policy that it is for the Substance look and feel and second indicates that there are no “super” look and feels to provide defaults for various UI settings. In case you are wondering, I had to examine the source code for SubstanceTitlePane.paintComponent(Graphics) to determine those values.

Providing the Custom Font Set

Next, you will need a custom FontPolicy to provide the custom FontSet. Using a similiar approach to only provide the custom FontSet for Substance:

public class CustomFontPolicy implements FontPolicy {

    /**
     * The {@link FontPolicy} to delegate to when not using the Substance look
     * and feel.
     */
    private final FontPolicy delegatePolicy;

    /**
     * The {@link FontSet} to provide when using the Substance look and feel.
     */
    private final FontSet fontSet;

    /**
     * @param delegatePolicy
     *            the {@link FontPolicy} to delegate to when not using the
     *            substance look and feel
     * @param fontSet
     *            the {@link FontSet} to provide when using the Substance look
     *            and feel
     */
    public CustomFontPolicy(FontPolicy delegatePolicy, FontSet fontSet) {
        this.delegatePolicy = delegatePolicy;
        this.fontSet = fontSet;
    }

    @Override
    public FontSet getFontSet(String lafName, UIDefaults table) {
        if (lafName.equals("Substance") && table == null) {
            return fontSet;
        }
        return delegatePolicy.getFontSet(lafName, table);
    }
}

After that, just set the FontPolicy:

CustomFontPolicy customFontPolicy = new CustomFontPolicy(fontPolicy, fontSet);
SubstanceLookAndFeel.setFontPolicy(customFontPolicy);

Changing the font when the Window is already displayed

If the font is changed when the window is already displayed, be sure to ask Swing to update the component tree UI by calling SwingUtilities.html.updateComponentTreeUI(java.awt.Component) on the window. Without this call, the window title might never get updated.

Using FontSets and FontPolicies to create the font set and policy

If you do not require the require mutability, you should consider using one of the createDefaultFontSet methods in FontSets. This way, you do not need to provide your own FontSet implementation. Similarly, consider if the FontPolicy can be created by createFixedPolicy in FontPolicies will suffice.

Seeing this in Action

You can see this in action by downloading, compiling and running this little demo. It consists of a window with a combo boxes for changing the Substance skin and another for selecting the window title font:

The combo box for choosing the window title font is created by the FrameBuilder.fontSelector method and it uses the CustomFontSet and CustomFontPolicy to provide the font to the Substance look and feel.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: