Friday, June 09, 2006

Decorated Fields in Eclipse

With Eclipse 3.2 a new JFace API is released addressing decorated fields. Everyone knows the little yellow light bulb that comes up if you want to create a new Java type and do not specify any package name.


Also a content assistant is provide that helps you choosing a package name. In Eclipse 3.2 this is now API and developers can use the feature to improve the user experience, especially in the area of validating user input.

I have put some sample code together that simply creates a decorated text field with a message. The user should provide a name. The name must not start with a blank though. In case it does, I show a little error sign that is augmented with a message.


If the user presses F1 in the field a content assitant pops up and proposes funny old german names that even google does not know :)

Here is the code snippet:

// a new shell
Shell shell = new Shell();
shell.setLayout(new FillLayout());
shell.setText("Name");
shell.setBounds(200, 200, 200, 200);

// a parent
Composite parentComposite = new Composite(shell, SWT.NONE);
parentComposite.setLayout(new GridLayout(2, false));

// a label
Label nameLabel = new Label(parentComposite, SWT.NONE);
nameLabel.setText("Type a name:");

// a field
final DecoratedField field = new DecoratedField(parentComposite,
SWT.NONE, new IControlCreator() {

public Control createControl(Composite parent, int style) {
// create a simple text control
Text nameText = new Text(parent, SWT.BORDER);
nameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
return nameText;
}
});
final Text text = (Text) field.getControl();

// create an error decoration
final FieldDecoration decoration = FieldDecorationRegistry.getDefault()
.getFieldDecoration(FieldDecorationRegistry.DEC_ERROR);
decoration.setDescription("A name must not start with a blank.");
field.addFieldDecoration(decoration, SWT.LEFT | SWT.TOP, true);

// create a content proposal provider that simply provides some funny old German
// names
SimpleContentProposalProvider sampleNames = new SimpleContentProposalProvider(
new String[] { "Wernfried", "Irmhelm", "Hernmut", "Gottlob" });
// create a F1 keystroke, this can probably be done more elegant
KeyStroke f1Stroke = null;
try {
f1Stroke = KeyStroke.getInstance("F1");
} catch (ParseException e1) {
// hope the KeyStroke.getInstance() works :)
}

// add a proposal adapter to our text field
ContentProposalAdapter adapter = new ContentProposalAdapter(text,
new TextContentAdapter(), sampleNames, f1Stroke, null);

// react on text changes and show error if needed
text.addModifyListener(new ModifyListener() {

public void modifyText(ModifyEvent e) {
if (text.getText().startsWith(" ")) {
field.showDecoration(decoration);
return;
}
field.hideDecoration(decoration);

}
});
field.hideDecoration(decoration);
shell.open();

The code above really just covers a simple implementation. There is much more behind the concept of decorated fields and much more flexibility. I am planing on writing a more in detail article or HOWTO about decorated fields.