Thursday, January 21, 2010

Validation overlays

What I mean validation is for example to have an error icon in a corner of a text field if the input is wrong.


Like a year ago I read a serie of articles about validation overlays on Kirill Grouchnikov blog at http://www.pushing-pixels.org/?p=69 that I really encourage you to read to have some information/idea how this can be implemented. I came to the conclusion that there were only easy 2 ways of doing this, using glasspane or jxlayer.
The glasspane suffer a performance issue and by the fact that there is only 1 glasspane per window.
JXlayer only drawback is that you can’t put the icon outside of the component.

One day I noticed that jide provide an easy way to add an overlay component to any component.
There is one problem although with jide you have to override the paintComponent Method(and add the required code) of each component you want to have the overlay component.
That’s a constraint I really didn’t want to deal with to have validation overlays, that’s make the code too complicated/unreadable

If you don’t override the paint method, the error icon won’t get repainted after the overlaid component, so the result is that the error icon will be partially/totally hidden by the overlaid component.




So the idea was to have a way to repaint the error icon each time the overlaid component is painted without to have to override the paintcomponent method of each overlaid component.


I came up with the idea to wrap the jide overlayable component inside a JXLayer, and to call the paint component of the overlay component inside the paint layer of the jxlayer, and Voila! Now we have the better of the 2 worlds: the error icon can be outside out the overlaid component and the error icon will be repainted each time the overlaid component does.


The error icon appears/disappear with a smooth animation as I like it.
The icon is a true component so it can have a tooltip, in our case the tooltip will be the error message.
You can change the default error icon for all or for one component:
ValidationPanelIcon.setDefaultIcon(BufferedImage)
ValidationOverlay.setIcon(BufferedImage newicon)


You can change the default location of the icon:
By changing the values of

ValidationPanelIcon.DEFAULT_XOFFSET
ValidationPanelIcon.DEFAULT_YOFFSET
ValidationPanelIcon.DEFAULT_ICON_LOCATION


Or by calling
ValidationIOverlay.setIconLocation(int xoffset, int yoffset, int location)



As there is a JXlayer in use, why not also us it fully and paint something on the layer?

You can specify a ValidationPaint :
ValidationIOverlay.setPaint(ValidationPaint)


ValidationPaint is an abstact class with the following method:


/**
*
* @param g
* @param msg the list of error message
* @param width width of the layer
* @param height height of the layer
* @param animProgress goes from 0 to 1 and then from 1 to 0, the duration of the animation can be set using ValidationOverlay.setAnimationDuration
*/
public abstract void paint(Graphics2D g, List<String> msg, JXLayer<JComponent> layer, float animProgress);



A default implementation is available :
ValidationPaint.getColorValidationPaint(Color)

This default implementation paint a rectangle over the component of the given color with a blink animation

As an example with a custom ValidationPaint it’s possible to write the error messages directly on the layer





ValidationOverlayFactory

To create the validation component use ValidationOverlayFactory:

createBlinking(T, List<Validator<T>>)
createBlinking(T, Validator<T>)
createBlinkingAndIcon(T, Validator<T>)
createBlinkingAndIconComponent(T, List<Validator<T>>)
createErrorOverlayedIcon(T, List<Validator<T>>)
createErrorOverlayedIcon(T, Validator<T>)


Validator is a simple interface

public interface Validator<T extends JComponent> {
String validate(T comp);
}


The validate method should return the error message or null if no error has been detected.

To execute the validator you have to call
ValidationOverlayFactory.validate(JComponent)

The jcomponent given to this method is your original component on wich you add the overlay


TextValidationOverlayFactory is a facility class to create validation overlaid component for text component, it installs automatically a listener to call ValidationOverlayFactory.check on a text changed.





validation overlays source code here

2 comments:

  1. The source code link is dead. can you provide another link please? Thanks

    ReplyDelete
    Replies
    1. The sourcecode is available here:

      http://kenai.com/projects/mabs-swing/sources/source-code-repository/content/FreeThePixel/src/com/community/xanadu/demo/components/ValidationOverlaysDemoFrame.java

      Delete