How to use JFace field editors in a custom dialog
JFace preference pages are easy to create using field editors. The are several editor types available, most consist of a label and one or two controls for displaying and changing a value. E.g., a StringFieldEditor consists of a label and a text field. This article will show how to use JFace field editors in a custom dialog.
Amongst others, there are editors for color, font, and a file path. Field editors can be created using one liners, their layout is managed by the FieldEditorPreferencePage. They work with a preference store to load and save data and have built-in validation. This saves a lot of code when building preference pages, but what about using them outside of preferences?
First off, I haven't found a lot of publications about field editors on the net. There's an old article on eclipse.org that's a good introduction to field editors and is still mostly valid: http://www.eclipse.org/articles/Article-Field-Editors/field_editors.html.
So, let's say we need a dialog for editing the settings of an exporter. It will contain a text field for the exporter arguments and a field for setting the target directory. Here's a screenshot of the final dialog:

To make use of the built-in layout management and validation, field editors have to be used within a FieldEditorPreferencePage. The first thing we'll do is create an empty dialog with such a page:
public class ExporterSettingsDialog extends Dialog {
private String exporterArgs;
private File targetDirectory;
private FieldEditorPreferencePage page;
public ExporterSettingsDialog(Shell parentShell, String exporterArgs, File targetDirectory) {
super(parentShell);
this.exporterArgs = exporterArgs;
this.targetDirectory = targetDirectory;
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText("Export Settings");
newShell.setSize(500, 170);
}
@Override
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
page = new FieldEditorPreferencePage(FieldEditorPreferencePage.GRID) {
@Override
protected void createFieldEditors() {
}
};
page.createControl(composite);
Control pageControl = page.getControl();
pageControl.setLayoutData(new GridData(GridData.FILL_BOTH));
return pageControl;
}
@Override
protected void buttonPressed(int buttonId) {
super.buttonPressed(buttonId);
}
public String getExporterArgs() {
return exporterArgs;
}
public File getTargetDirectory() {
return targetDirectory;
}
}Then we'll add a StringFieldEditor and a DirectoryFieldEditor. Since we don't use a preference store, we have to set the initial values manually and query their values when the OK button is pressed:
private StringFieldEditor exporterArgsEditor;
private DirectoryFieldEditor targetDirectoryEditor;
[...]
protected void createFieldEditors() {
exporterArgsEditor = new StringFieldEditor("", "Exporter arguments:", getFieldEditorParent());
exporterArgsEditor.setStringValue(exporterArgs);
addField(exporterArgsEditor);
targetDirectoryEditor = new DirectoryFieldEditor("", "Target directory:", getFieldEditorParent());
targetDirectoryEditor.setStringValue(targetDirectory.getPath());
addField(targetDirectoryEditor);
}
[...]
protected void buttonPressed(int buttonId) {
if (buttonId == IDialogConstants.OK_ID) {
exporterArgs = exporterArgsEditor.getStringValue();
targetDirectory = new File(targetDirectoryEditor.getStringValue());
}
super.buttonPressed(buttonId);
}This is working nicely so far, with much less code than manually managing labels, text fields, buttons and their layout. You'll notice that the first argument for each editor is an empty string. A field editor expects to be used with a preference store, and the first argument specifies the key to load and save the value of the field editor. Since we don't use a preference store, we just pass an empty string.
The dialog at this point shows "Restore defaults" and "Apply" buttons, which we want to get rid of. To do this, we need to override a method in our FieldEditorPreferencePage:
@Override public void createControl(Composite parentComposite) {
noDefaultAndApplyButton();
super.createControl(parentComposite);
}Validation
The field editors have built-in content validation. We'd like to only enable the OK button of our dialog when an existing target directory is set. Fortunately, the default behaviour of DirectoryFieldEditor.isValid() is to return true only when an existing directory is selected.
Every time the field editors perform a validation, updateApplyButton() in the FieldEditorPreferencePage is called. By overriding it, we can query the validation state by calling isValid() on the page and enable or disable the OK button of the dialog:
@Override
protected void updateApplyButton() {
updateButtons(isValid());
super.updateApplyButton();
}
[...]
@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
updateButtons(page.isValid());
}
private void updateButtons(boolean isValid) {
Button okButton = getButton(IDialogConstants.OK_ID);
if (okButton != null) {
okButton.setEnabled(isValid);
}
}The OK button of our dialog should now only be enabled when an existing directory is selected as the target directory.
There's a bug that StringFieldEditor.isValid() returns false when initialized with an empty string and the user hasn't changed the content of any of the editors. To work around this, we set the content of the exporterArgsEditor to a (non-empty) dummy value before setting the inital value, to trigger an initial validation:
// Set a dummy value before correct value, to trigger an initial validation.
exporterArgsEditor.setStringValue("XXX-dummy-XXX");
exporterArgsEditor.setStringValue(exporterArgs);And that's it! We have a dialog with labels, test fields, a button that pops up a directory chooser, and validation with fairly few lines of code. The full code of the final dialog is attached to this blog post.
Categories
Sophora CMS - A New Take on Content Management
Sophora is optimized to meet the needs of modern companies that produce up-to-date multimedia content on a large scale and that require fast delivery of their content.
Toromiro
Toromiro is a professional tool for the administration and editing of Java Content Repositories (JCR). JCR is powering some of today’s most successful solutions for content management and digital asset management.