1. Removed runtime enhancement favoring AST based compile-time enhancement (backward compatibility breaking change!)
From the inception of this plugin, all model instances are automatically enhanced during runtime to have the validation capability injected. Since v0.4 an additional AST transformation annotation @Validatable has been added so non-model classes can be annotated to have the same validation capability injected. However since these two approaches work quite differently; one performs meta class based enhancement during runtime, and the other AST based approach performs byte code level enhancement during compile-time. After much discussion we have realized that firstly the on-going effort to make sure two different approaches produce identical result is getting more and more complicated as new feature being introduced to the enhancement logic. Secondly the default runtime enhancement is less flexible and less efficient comparing to the AST based approach. Thus a hard decision was made to drop the support for the auto runtime enhancement for model instances. In other words after upgrading to 0.7 you will need to add @Validatable to all model classes that you want validation feature to be injected.
2. Error Renderers
One of the common challenge we face when building UI using any GUI framework is how to effectively and easily notify the user about errors. Ideally a validation framework should not just help developer define constraints and validation logic but also handle the presentation of the error message automatically with little coding involved. With this vision in mind, also thanks to many useful input and ideas provided by Andres during our discussion, this mechanism called Error Renderer was created in this release as my first attempt to address this challenge with some Groovy/Griffon awesomeness.
Error Renderer can be declared easily by using the additional synthetic attribute 'errorRenderer' introduced in this release. See the following example:
textField(text: bind(target: model, 'email'), errorRenderer:'for: email, styles: [highlight, popup]')
In the above example, two error renderers were declared for the textField widget for the 'email' field in the model. Basically what it means is that if any error was detected for the email field in the model two types of error renderer will be activated to display the error(s). The styles portion of the configuration is optional. If no renderer style is defined, by default highlight renderer will be used. Currently three types of error renderer styles are implemented, I will go through them quickly here.
I. Highlight Error Renderer
This renderer basically change the background color of the component to pink. Mostly it is used for text based input fields. Here is a screen shot of the rendering result.
II. Popup Error Renderer
This renderer display the error message associated with the error using a tooltip-like popup box. Here is a screen shot of the rendering result.
III. On With Error Renderer
This is an invisible renderer that does not render anything itself but switch the component visible attribute on when the error is detected. It is commonly used to display initially invisible custom component when error occurs. This renderer is used in combination of the new errorIcon widget also introduced in this release. Here is a screen shot of it used with errorIcon.
3. New Error Related Widgets
A few simple widgets were also added to this release to reduce the effort required when working errors.
I. Error Messages Widgets
This is basically the old wine in a new bottle. This widget is essentially identical to the ErrorMessagePanel class existed since v0.2 however it is now implemented as a widget to make it easier to use. Usage:
errorMessages(constraints: NORTH, errors: bind(source: model, 'errors'))
II. Error Icon Widgets
As mentioned before this widget is mainly used in combination with the onWithError renderer. This icon widget is initially invisible and will only be turned on by the onWithError renderer. Usage:
errorIcon(errorRenderer:'for: creditCard, styles: [onWithError]')
Currently the error renderer only works with the model instance within a MVC group. Future work is need to support plain POGO annotated with @Validatable.