Displaying validation error, and beyond, and far beyond
I was reading Kirill Grouchnikov blog  while getting a customer request to implement such a feature. Kirill wrote a series of blogs on how to support validation overlay. He did a great job in explaining different solutions and comparing pros and cons. However he doesn’t seem bother to reach a conclusion. Maybe there isn’t one after all.
No conclusion is certainly not an option for us as this particular customer is depending on a solution.
We have the following criteria in mind for this feature.
1. API ease of use - least code change to add an overlay component
2. API easy to understand
3. The overlay component is a real component, not just a painted image so that user can add mouse listener to it or set tooltip etc.
4. Can be placed beyond the component boundary
5. Handle scroll pane well
6. Support any LookAndFeels without extra code.
7. Can add overlay component to any component
8. Can use any component as the overlay component
We knew many different ways to implement this feature - most of them are pointed out already by Kirill. However, after we looked at the criteria above, we ruled out most of them. JLayeredPane/GlassPane is ruled out because of bullet 5. Overriding paint method approach is ruled out because of bullet 3 and 4. Extending or multiplex L&F approach is ruled out because of bullet 6 and 7. Let’s see what we can come up with.
First, let’s see a few screenshots.
Overlayable with different Swing components.

Overlayable with JTextArea to provude a hint

Overlayable for progress indicator purpose

Overlayble with tooltips

We introduced an Overlayable interface. What overlay means is to put a component over another component. Instead of making every component overlayable, which will change too many classes, we decide to create a default implement that makes a JPanel overlayable. For example, you want to add an overlay component to a check box. You can simply add the check box to this overlayable panel, and then add overlay components to this overlayable panel. It looks like the overlay component is on the check box although it is actually on the check box parent.
Here is an example of an overlay component on a radio button.

The top one shows what it looks like. The icon seems like part of the radio button but it is not. As you can see from the bottom screenshot, the green rectangle is the boundary of the radio button. The red rectangle (plus the green rectangle as the green paints over the red) is the boundary of the overlayable panel. The icon is on the bottom right corner of the overlayable panel, not the radio button.
Now let’s compare the code before and after adding the overlayable.
Before adding the overlay component, we have code like the below. The controlPanel is the panel that contains the radio button.
controlPanel.add(new JRadioButton(”Radio Button”));
If you want to add an icon as overlay component, we need to create a label first.
JLabel info = new JLabel(OverlayableUtils.getPredefinedOverlayIcon(OverlayableIconsFactory.INFO));
Then we need to wrap the radio button to a DefaultOverlayable. We also need to override a method in radio button to repaint the overlay component correctly. The code will be like below. It is a little too complex.
controlPanel.add(new DefaultOverlayable(new JRadioButton(”Radio Button”){
public void repaint(long tm, int x, int y, int width, int height) {
super.repaint(tm, x, y, width, height);
OverlayableUtils.repaintOverlayable(this);
}
}, info, DefaultOverlayable.SOUTH_EAST));
Or, if you use one of the pre-build radio button, you can save the overridden method. OverlayRadioButton is nothing but a JRadioButton that overrides the repaint method as shown above.
controlPanel.add(new DefaultOverlayable(new OverlayRadioButton(”Radio Button”), info, DefaultOverlayable.SOUTH_EAST));
The code is still more complex than the original code. But considering the powerful feature it added, it is worth the added complexity.
We can easily support multiple overlay components. DefaultOverlayable’s constructor can take one overlay component. But you can still add more by calling addOverlayComponent(). For each overlay component, you can control the position, the order relative to other overlay components and visibility independently. removeOverlayComponent() will remove it and getOverlayComponents() will tell you all the overlay components.
We also support overlay component beyond the boundary. Overlayable also has setOverlayLocationInsets(). We noticed many other implementation has the limitation that the overlay component must be within the boundary of the component itself. This is annoying as the overlay component might cover portion of the component. That is why we added this overlayLocationInsets concept. If you want to place the overlay component outside the east border, you just give a positive number on the east edge of the insets. See below for an example. The first one has 0 on the east edge; 5 for the second one and 10 for the last one.

Good or bad? You decide. The source code of all related classes are checked in to JIDE Common Layer at https://jide-oss.dev.java.net. In my opinion, although this design satisfies almost all the criteria I mentioned earlier, it is still not perfect especially we still have to override repaint method. One way to solve it is to provide our own RepaintManager but it will probably make API harder to understand for most developers. If Swing provided a hook into RepaintManager, it would be perfect. So in conclusion, if we would give a rating to this design from 1 to 5 with 5 is the best, I will give 5 for bullet 3 to bullet 8 and give 3 to bullet 1 and 2. There is still room to improve in these two bullets.
 For JIDE Customers, this feature will be part of 2.1.3 version which will be released tomorrow.



David,
To reach a conclusion you need to start with a set of requirements. The validation overlay example that was used in that series was chosen to illustrate the different general techniques. Like you’re saying here, there is no “best general” solution, there is only “best for my needs” solution.
Thanks
Kirill