One of the rules of good UI design is to use consistent coloring guidelines. One of the many reasons is the accessibility for color-blind users who might not be able to distinguish between light red and light green background for validation indications (reported seven percents of male population of United States can’t distinguish between green and red or see them differently). However, some applications can benefit from using colors to visually distinguish between controls, and one of the users of Substance look-and-feel has recently filed an enhancement to provide support for control colorization (attaching this screenshot as sample of the required UI).
And so, i’ve spent the better portion of the last two weeks on colorization support for the core Swing components. What started out to be an innocent and simple enhancement request turned out to be an excellent opportunity to revisit pretty much the entire Substance codebase, fixing few stray bugs and refactoring some duplicate functionality. This entry shows sample screenshots of colorizing awide variety of core Swing components, with support for SwingX and Flamingo component suites coming in the next release. If you want to play with live demo, click the button below, wait for the application to load, switch to “Colorized” tab, check the “colorize” checkbox and play with the slider (which sets the colorization amount).

And now let’s see some screenshots. Here is a collection of toggle buttons, checkboxes and radio buttons in different states (default, selected, disabled and disabled selected) under Business Black Steel skin:

Now, let’s set the background and foreground colors to some application-specific values and see how these controls look under Metal:

While some states respect the settings (for both background and foreground colors), others don’t. For example, the foreground for disabled is always light gray, the background for selected toggle buttons is always light gray. In addition, the checkmarks for check boxes and radio buttons respect neither custom background nor custom foreground. Let’s try under Windows look-and-feel:

This looks even worse than Metal and much of it is due to the limitations of native look-and-feels as described in this earlier entry. The buttons would be better off ignoring the custom settings at all – disabled foreground text is the same as enabled one, and the background is painted as a rectangular “ghost” border around the buttons.
While Substance hasn’t been much better up until now, the things look different in the latest 4.2dev build. Here are the same controls with 50% colorization:

As you can see, the colors of the original theme are now colorized with the custom background and foreground. The disabled controls still look disabled (colorization is not as strong), and the check marks of radio buttons and check boxes are colorized with the custom foreground colors. In addition, the background of check boxes and radio buttons is not colorized at all. Last but not least, the colorization implementation tries to preserve the brightness levels of the original colors, which results in consistent gradients even for large colorization values.
Let’s see how the same controls look under 25% colorization:

If the application requires more colorization, it can set it to anywhere between 0% and 100%. Here are the same controls under 75% (note that the gradients are still discernible):

Let’s see some other controls being colorized. Here are a few text components:

And a scroll pane with yellow background (propagating to the horizontal scroll bar) and green background on the vertical scroll bar (i still haven’t decided whether the corner should be colorized as well):

What about something a little more complicated such as table? The first row has enabled tables with green and dark green backgrounds, while the second row has the same tables disabled. Note how the background colorization is applied not only to the cells and header cells, but also to the table grid lines:

Another complicated example is a tree. Here, the colorization is applied to the striping, the cells, the tree lines and the tree collapse / expand icons:

Another complicated one is an internal frame. Here is a screenshot of desktop pane with custom blue background with four internal frames, two of them minimized. Note how the custom background of an internal frame is applied to its title pane, the title pane buttons, the frame border and the menu bar (first two apply for the desktop icons as well):

Going back to simpler controls, let’s see some sliders and progress bars:

and compare it with Metal:

The last screenshot shows the colorization of menu items (note how it applies to the text, check marks and the arrow icons):

I’d like to thank Luke Sleeman for creating this enhancement request and providing feedback on the initial implementation. To try it out, run the demo linked above. You can download the latest binaries and sources right here and play with the new SubstanceLookAndFeel.COLORIZATION_FACTOR client property which can be set on UIManager (globally) or on any component (applied to the component and all its children). The value should be a Double in 0.0-1.0 range. All the Substance screenshots in this entry have been taken under JDK 6.0 on Vista, with the Bramble plugin providing native text rendering.
These two features (native text rendering and colorization support) mark the code freeze for new core features in the next Substance release (code-named Memphis). At this point, they have resulted in only 40KB increase in the size of the binary library. The release candidate is scheduled for January 21st, with the release scheduled for February 4th.
Following my entries on platform-specific font policies for Mac and Gnome, one of Substance users stepped up and provided an implementation that makes all Substance-powered Swing application pick the correct font sizes when running under the KDE desktop.
Here is a screenshot of a test application running under KDE desktop with font size of 10 and DPI set to 96:

and here is the same application, running under 120DPI, using font size of 10 except for menus which are configured to use italic 8:

The current implementation can be found in the CVS repository and was contributed by Paranoid (many thanks). It parses a few configuration files to get the DPI and font settings, providing fallback values in case these can not be found. Give the latest 4.2dev drop a try and let us know if you’re having any problems on KDE desktop.
Two weeks ago i wrote about the first drop of Bramble plugin for Substance look-and-feel, which provides support for native text rendering in Swing applications. Today, it’s time to look at the actual implementation and see how it all works together.
Unlike SWT that passes the painting requests to the underlying native APIs, Swing handles all the painting itself (unless we’re talking about Windows and GTK look-and-feels under Mustang, which have their own set of problems). Swing’s greatest flexibility is in its “layered” approach to rendering the components (see this PDF presentation that shows one of the possible effects that are extremely easy to achieve with Swing UI delegates). Take, for example, painting a button. It’s all done in independent layers which are then composited together using the powerful Java2D APIs:
- Background
- Icon
- Text
- Focus
- Border
What happens when you want to provide custom rendering for one of these layers (text in our case)? Just override the relevant paint method and provide the logic there (not touching any other pixels). Seems easy, but since SWT has its own painting model dictated by the OS, it’s not. The main difference between text rendering in AWT / Java2D and SWT is that the later expects the background pixels to be fully specified (as detailed in this discussion on the platform-swt-dev mailing list and this discussion on the eclipse.swt.forum).
And as it turns out, this complicates the logic of plugging the SWT text rendering into the Swing painting pipeline, but the end result is most certainly worth it. I’ve already posted a few screenshots, and here is one more:

The first two rows (labels and text fields) are rendered by Swing (Vista + Mustang), while the last two rows are rendered by SWT / native code. While for labels the difference might not be that big, for the digits it is simply staggering (at least for the default Vista Segoe UI font). So, what do we have to do in order to have the native text rendering in Swing?
The current implementation has three stages:
- Filling the component bounds with the background color. The actual color depends on the component kind and component opacity (can come from the parent container).
- Painting all the overlay / highlight layers. List cells have rollover / selection highlights. Text components have multiple highlights depending on the text selection mode.
- Painting all the texts. There can be more than one with different fonts and colors. Menus have the menu text and accelerator text. Sliders have multiple labels. Text components have multiple selected and unselected sections.
The pure Swing implementation doesn’t have to be concerned with combining the results of these three stages together, since Java2D’s drawString method can operate on a translucent / transparent image (with questionable results in some cases, or otherwise there would be no need for this entry). The native text rendering expects all the background pixels to be filled before it can paint the text. Depending on the actual component, this can make the nice and structured Swing UI delegate implementation a little bit more coupled. This is especially true for such complex components as lists, trees, tables, combo boxes, sliders and all types of text components.
In addition to this limitation, there are technical issues with integrating Java2D and SWT rendering. What is the flow here?
- Java2D code paints the component background and overlay / highlight layers on an AWT image
- An SWT image is created from the pixels of the AWT image
- AWT font and color settings are use to create the matching SWT text layout
- SWT text layout is used to paint the text on the SWT image
- Another AWT image is created from the pixels of the SWT image (which at this point contains the background, overlay / highlight layers and the texts)
- This AWT image is painted back on the Java2D Graphics that is passed to the UI delegate
All these steps might add significant overhead to the overall painting performance, especially considering that text elements are pretty much everywhere in a common UI. The first drop that was available two weeks ago had some big performance issues on large lists and tables. This has been addressed by clipping the compositing area to only the necessary rectangle. In addition, there are minor differences between the two UI toolkits. For example, AWT uses pixels and SWT uses points. This means that the font size needs to be converted to maintain the visual results. In addition, most SWT resources need to be explicitly disposed (much like Java’s streams, for example, that need to be explicitly closed).
The components that are supported in the latest drop of Bramble plugin:
- Buttons, toggle buttons, check boxes and radio buttons
- All menu elements, including menus and menu items
- Tabbed panes
- Labels including the default cell renderers for trees, tables, lists and uneditable combo boxes
- Text fields and formatted text fields with simple documents, including default editors for editable combo boxes
- Decorated title panes for frames, dialogs, internal frames and desktop icons
- Slider labels
- Table headers
- Tooltips
- Components from the Flamingo component suite such as command buttons and ribbon
If you’re interested in testing this implementation, you need to do the following:
- Download the substance-bramble.jar here and add it to the classpath of your application.
- Add the org.eclipse.swt.win32 jar to the classpath of your application. Bramble distribution bundles this jar from Eclipse 3.2.1 in the ‘lib’ folder.
- Extract the matching swt-win32.dll and add it to the java.library.path of your runtime configuration. Bramble distribution bundles this DLL from Eclipse 3.2.1 in the ‘lib’ folder.
- Configure your application to run under the latest 4.2dev drop of Substance look and feel.
If you run into any issues with components mentioned above or custom cell renderers / editors, i would be more than interested hearing about it. The plugin is distributed under the Eclipse Public License (EPL).
Lately, there have been quite a few postings on the mailing list of Substance look-and-feel that ask how to change the default animation settings. This can be required for a number of reasons, including performance speedup and proper effects on custom application renderers. Following in the footsteps of the painter primer and skinner primer, the animation primer provides the necessary information that you need to configure custom animation settings for Substance-powered applications.
To bring richer user experience to Swing applications, look-and-feels that use the Laf-Widget library can use its flexible and powerful animation layer. The layer provides support for animating core and custom Swing components, including core animations (such as rollovers and selections), as well as custom animations (such as pulsating border of a focused text component).While the default animation settings (which transitions to animate, the animation speed, the set of components to animate) were selected to provide a consistent and pleasant out-of-the-box visual experience with zero application configuration, some applications might need to configure the animation settings.There are three techniques that the applications can use to change the default animation settings:
<font color="darkblue">org.jvnet.lafwidget.animation.FadeConfigurationManager</font>
<font color="darkblue">org.jvnet.lafwidget.LafWidget.ANIMATION_KIND</font>
<font color="darkblue">META-INF/lafwidget.animations.properties</font>
Using the FadeConfigurationManager API
The <font color="darkblue">org.jvnet.lafwidget.animation.FadeConfigurationManager</font>
is the first way to change the default animation settings. It provides the API to programmatically disable / enable core and custom animations. You can use the various <font color="darkblue">allowFades</font>
and <font color="darkblue">disallowFades</font>
on all controls, on all controls of the specified class or on a specific component. For example, here is how you can remove rollover and selection animations from the specific list:
JList list = ...; // create the list
FadeConfigurationManager.getInstance().disallowFades(FadeKind.ROLLOVER, list);
FadeConfigurationManager.getInstance().disallowFades(FadeKind.SELECTION, list);
where <font color="darkblue">org.jvnet.lafwidget.animation.FadeKind</font>
is an instance of a core or custom animation kind.
Using the LafWidget.ANIMATION_KIND client property
The <font color="darkblue">org.jvnet.lafwidget.LafWidget.ANIMATION_KIND</font>
is client property name for specifying the kind of animation on various components. The value should be one of <font color="darkblue">org.jvnet.lafwidget.utils.LafConstants.AnimationKind</font>
enum. This property can be set either on component or globally on <font color="darkblue">UIManager</font>
.
In order to compute the animation kind for some component, the component’s hierarchy is traversed bottom up. The first component that has this property set, defines the animation kind. Finally, if neither component not its ancestors define this property, the global setting on <font color="darkblue">UIManager</font>
is checked. If there is no global setting, the default <font color="darkblue">LafConstants.AnimationKind.REGULAR</font>
is taken.
The <font color="darkblue">LafConstants.AnimationKind.NONE</font>
value can be used to remove all animations from the specific component (and its children) / globally. Here is how you can remove all the animations from a list:
List list = ...; // create the list
list.putClientProperty(LafWidget.ANIMATION_KIND, AnimationKind.NONE);
Using the META-INF/lafwidget.animations.properties resource file
The final way to configure the default animation settings is to bundle a <font color="darkblue">META-INF/lafwidget.animations.properties</font>
text file with the application. Every line should be a fully qualified class name of a Swing component. At runtime, there will be no animations on a component if it is an instance of that class, an instance of class that is assignable from that class, or has a parent that matches the first two criteria.
Comparing the different techniques
There are different use cases for each one of the techniques.
- The
<font color="darkblue">FadeConfigurationManager</font>
provides a powerful way to allow or disallow the specific animation kind. However, if you want to remove all animations globally or on the specific component, it is better to use <font color="darkblue">LafWidget.ANIMATION_KIND</font>
set to <font color="darkblue">LafConstants.AnimationKind.NONE</font>
.
- If you want to configure the animation speed, you should use the
<font color="darkblue">LafWidget.ANIMATION_KIND</font>
and set it to either a core or a custom <font color="darkblue">LafConstants.AnimationKind</font>
. A custom implementation can provide a non-linear cycle interpolation.
- The
<font color="darkblue">META-INF/lafwidget.animations.properties</font>
should be used when you want to disable animations of all kinds on all instances of the specific components. In the core implementation, it is used to disable all animations from list, tree and table renderers.