Tuesday, February 19, 2013

Centering SWT ColorDialog

SWT includes ColorDialog class which exposes the native color dialog. Unfortunately, the dialog opens in the upper-left corner of the parent shell and there is no API to change this behavior. Fortunately, there is a trick that can be used to center the dialog instead.

final Shell parent = ...
final Rectangle bounds = parent.getBounds();

// There is no means to compute the size of the color dialog. In the following
// computations, measurements of the dialog on Windows 7 are used.

final int x = bounds.x + bounds.width / 2 - 120;       
final int y = bounds.y + bounds.height / 2 - 170;      

final Shell shell = new Shell( parent );
    shell.setBounds( x, y, 0, 0 );
    final ColorDialog dialog = new ColorDialog( shell );
    dialog.setText( ... dialog title ... );
    dialog.setRGB( ... initial color ... );
    final RGB pickedColor = dialog.open();
    if( pickedColor != null )

The same trick can be used for centering other native dialogs exposed by SWT.

Monday, February 18, 2013

Use EL for Sapphire Validation

Sapphire includes a number of annotations (such as @Required and @NumericRange) that allow the developer to declaratively specify semantics which the framework translates to validation. If the provided annotations are not sufficient, the developer can implement ValidationService directly.

In a recent review of a large Sapphire project, I noticed that a fair number of custom ValidationService implementations were implementing rather simple semantics. Many of these semantics could be easily expressed using Sapphire Expression Language, leading to a model that is easier to understand and maintain. Now that’s possible in the latest Sapphire 0.7 build.

// *** Min ***

@Type( base = Integer.class )
@DefaultValue( text = "0" )
@Validation( rule = "${ Min <= Max }", message = "Must not be larger than max." )

ValueProperty PROP_MIN = new ValueProperty( TYPE, "Min" );

Value<Integer> getMin();
void setMin( String value );
void setMin( Integer value );

// *** Max ***

@Type( base = Integer.class )
@DefaultValue( text = "0" )
@Validation( rule = "${ Max >= Min }", message = "Must not be smaller than min." )

ValueProperty PROP_MAX = new ValueProperty( TYPE, "Max" );

Value<Integer> getMax();
void setMax( String value );
void setMax( Integer value );

The new @Validation annotation has an optional severity attributes that allows the developer to choose between error and warning severity for the validation problem. Multiple validations can be specified by using @Validations annotation that simply holds a set of @Validation annotations.