Supporting GroupLayout baseline

September 8th, 2007

GroupLayout was introduced in the middle of 2005 and later was added to JDK 6.0. It is the default layout manager used by NetBeans UI editor (code-named Matisse), and while the code using the GroupLayout tends to be very verbose and unreadable, the visual results are very pleasing as compared to other core Swing layout managers. For applications that require JDK 5.0, the swing-layout project provides JDK 5.0-compliant implementation.

This layout manager has introduced a concept of baseline that allows aligning components according to the perceived text baseline, instead of lining the components on the top border. This is especially relevant for form-based UIs that have grid-like arrangement of controls. In such UIs, you usually have labels in the first column followed by text fields, check boxes, combos and other controls in the subsequent columns. Here is an example:

As you can see, the alignment is far from perfect. The labels are incorrectly aligned with the text field, the combo and the password field. In addition, the labels are not spaced evenly. The implementation of GroupLayout includes hard-coded computation of baseline offsets for all core Swing components for the major core look-and-feels (Metal, Windows, Aqua and GTK). Here is how the same UI looks under Windows look-and-feel on Vista:

As you can see, the rows are aligned according to the text baseline, and the labels are equally spaced.

While this functionality is available out of the box for the core LAFs that were mentioned above and LAFs that extend those, there are three notable missing LAFs: Basic, Motif and Synth. Here is how the same UI looks under Motif:

What about the other two groups? There are a few third-party look-and-feels that extend either BasicLookAndFeel or SynthLookAndFeel. These include Alloy, Skin, Substance, Napkin, Liquid and Synthetica. Here are a few screenshots of these LAFs (Liquid, Napkin and Synthetica):

Following the request made by one of Substance users, the latest drop of Substance 4.1dev (code-named Lima) includes the new Substance Baselin plugin (that was refactored from the Substance NetBeans module). Once you add the substance-baseline.jar to your classpath, it will add the correct baseline alignment for applications that use GroupLayout from the swing-layout project under JDK 5.0.

Here are the before and after screenshots under Substance:

The license for this plugin is LGPL (the same as for the swing-layout.jar itself).

An astute reader would notice that the current implementation of JDK 5.0-compliant GroupLayout doesn’t provide builtin support for Synth-based LAFs. It would be interesting to see how Nimbus is going to address this issue, especially with the plans to backport it to JDK 5.0.

Look and feel related news

September 7th, 2007

This week is witnessing a more-than-usual level of activity in the look-and-feel department. In addition to my own announcement on the release 4.0 of Substance, there are a few other items.

The first is the announcement from Fred Lavigne (creator of the Skin look-and-feel) on the updates made to the Javootoo site. The new design is much better, and the navigation bar has been reworked as well. Not to mention that the screenshots and the blurbs on the various libraries have been updated to match the latest respective versions. Here’s how Substance page looks like:

Javootoo Substance section

The second announcement comes from Wolfgang Zitzelsberger of Javasoft on the new version of Synthetica look-and-feel. In addition to bugfixes and new client properties, it features a new WhiteVision theme (which uses color combination similar to the Substance Creme skin):

As with all the latest animated themes, this is available under commercial license only.

As a side item, Davide Raccagni has announced a minor release 1.1.1 of his A03 look-and-feel that comes with a version compatible with JDK 5.0. And if you wondered what is the meaning behind the name, go to that link for the explanation.

Update: just as i thought we were done for the week, Jasper posted an entry on Nimbus work in progress:

There’s a new article that has been published today on java.net titled Debugging Swing. It builds on the previous work by Scott Delap and Alex Potochkin to provide even more tools for tracing the EDT violations that can lead to visual artifacts, unresponsive or frozen UIs and infinite painting cycles.

If you’re interested in more articles on Swing, please post your suggestions in the comments. Specifically, i’m looking for the “everyday” problems that you’re facing in the regular business Swing applications. Note that an article scope is too small to talk about architecturing a Swing application, so try to keep it to a specific topic, such as auto-completion support on comboboxes or writing a custom component.

Thanks to Eamonn McManus for his help on JMX-related code and to Chris Adamson for the editing.

This forum posting on the SwingX forum has caught my eye:

Having recently switched my main development box to Linux, I have noticed that swingx Linux support is pretty sparse. […] I have had a little dig, and the main culprit seems to be the LookAndFeelsAddons class, more specifically the getSystemAddonClassName() method which only seems to recognize the OSX and Windows OSs – everything else will be defaulted to a ‘Windows Classic Look and Feel’ ! As a result of this, my JXTaskPanes have no visual shading in either the title panel or the main panel. The weird thing is that JXTitledPane actually looks OK (it uses the correct colours for the title bar gradient).

And here is what Richard Bair (the lead of SwingX project) had to say:

The answer may not be very simple either. Since GTK is skinnable, we have to decide how to go about writing UI delegates for these things. Some things like JXStatusBar may have an equivilent type of component in GTK (not sure) which means we’d want to hook into the GTKLookAndFeel somehow to get the right painting code from the OS. Not sure if there is public API in GTKLookAndFeel to do that. And worse for those components that are more custom, like JXMonthView. How do we know what colors to use? I guess it depends on whether GTKLookAndFeel gives us any hints. Adding support to LookAndFeelAddons for Linux/Solaris is the easy bit. Figuring out what to do about it is quite a bit more complicated.

And this brought me back to think about the whole native-vs-cross platform debate that surges every few months in different Swing forums and blogs (with some taking very extreme stance). In this entry, however, i want to compare the implementation costs of these two approaches (and please don’t start flamewars in the comments on which one is better from the user perspective – this entry is about the implementation and not about the visual result).

First announced more than two years ago, the implementation of two core Swing look-and-feels (Windows and GTK) has moved from emulation to using native APIs. As Chet says on his blog

In Java SE 6, the Swing native look & feel for both Windows and GTK was re-written to use the native platform rendering engine to draw Swing widgets. Instead of our old approach of using the native resources and doing our own rendering, we actually call the native rendering system to draw the widgets for us (on Windows, this is done through the UXTheme API). This means that we are finally able to achieve true native fidelity for these components because, by definition, our components are drawn in the same way that the native components are. Not only did this fix corner cases for our XP look & feel, we also made our native look & feel work successfully on Vista.

Hooray going forward? 100% native fidelity for Swing applications running under XP and Vista? 100% native fidelity for Swing applications running under the next Windows release without any change to JRE? Not really. The devil is, as always, in the little details. So, what are they?

Native APIs change. As Chet mentions, Vista draws some components in different ways, so the code for those is different for XP and Vista. Who knows what will be in the next Windows release? Of course, Microsoft is committed to support the old APIs, but it doesn’t mean that the visual results are the same.

Native animations work on native controls. Since Swing controls are lightweight, they are just a bunch of pixels as far as the OS is concerned. This means that Swing has to emulate the animations for the specific OS. In Windows LAF this is done in the AnimationController class that tries to mimic different transitions on various controls. It also makes some assumptions on the native implementation (it assumes that the animations are linear which may not hold in the next Windows releases).

Native painting works on native controls. As with the previous bullet, this means that Windows LAF implementation must map the control state (rollover, pressed, selected, armed, enabled) to the matching OS control state (the later is passed to the native API that computes the colors that match the state). Vista defines over 50 different control states. The next Windows release may define more.

Texts are painted by the Java rasterizer. Many have complained about the rendering quality of default Windows fonts (Tahoma on XP and Segoe UI on Vista), and Karsten Lentzsch even went as far as this:

As a result of this bug [6449753], I consider using the SWT in high-fidelity Swing design to catch up with ClearType (XP) and ClearType (Vista).

Note that this might get better or worse with replacing the existing font rasterizer with FreeType in JDK 7.0.

Native painting supports only native controls. This actually brings me to the forum posting that i quoted in the beginning. With a lot of development going into comprehensive component suites such as JIDE and SwingX, how would one paint controls that have no direct OS counterparts? While in some cases you can address this by “stitching” together background tiles, what would you do with more complex controls such as Office 2007 ribbon, especially if you want to support all OS themes in Windows and GTK?

Native painting is harder to debug. Once you cross the line between Java and native calls, the debugging becomes more complicated. Now you’re dealing with JNI, native methods, possible leaks of native resources etc. On the other hand, the painting implementation itself is done on the OS level, which in most cases would mean less color-level bugs that you need to worry about (as long as you send the right parameters to the native methods).

Native painting is only painting. Java still needs to emulate the “feel” part of the controls. Since all the event handling is done by Java, it needs to “recreate” the keyboard and mouse user interaction with the component (which is just a bunch of pixels as far as the OS is concerned). When the next OS version adds new behavior (feel), Swing needs to add it explicitly.

As you can see, there are quite a few reasons why there are still bugs in the JDK 6.0 implementation of Windows and GTK LAFs. You also might consider these if your requirement is to have “absolute native fidelity” for your Swing application (whatever that means and once again, please don’t start a flamewar that there is no such thing as a native application since Microsoft breaks their own guidelines all the time). Note that this doesn’t mean that you should ditch Swing and move to SWT (or to native code for that matter). It’s just all those implementation quirks lurking just beneath the surface that might rear their ugly head and bite you at a very inopportune time.