ATTENTION: this is not in v0.7, API not final. See SVN trunk for current implementation and to run example code.
The form layer wraps up the validation manager, form toolkit and form parts into an easy to use package,
integrating it smoothly into the Eclipse world of views, dialogs, wizards, managed forms.
The main concept is the RCPForm. An RCPForm is composed of one or more RCPFormParts,
which corresponds roughly to the UI Forms concept, but adding UI creation and binding to it.
An RCPForm has the states:
This is different to ManagedForm, since a major design flaw of Eclipse ManagedForm and SectionPart is the ui creation in the constructor.
The input for an RCPForm is currently an array of models, each entry corresponds to one form part and is bound against the corresponding form part in the form. There is one ValidationManager per form which creates all bindings, manages the correlation between bindings and form parts and has an overall observable validation state; observable in the sense of databinding means it will fire change notification when state changes.
To embed an RCPForm into Eclipse artefacts like Dialogs, Wizards, Views several wrapper classes exist which do it for you:
All wrapper classes are very easy to use; pass the form in the constructor, at some time set an input, follow the standard usage model of the eclipse artefacts.
See the example application for details how to use them.
To create a form, follow these steps:
start the main method
public static void main(String[] args) { RCPForm form1 = new RCPForm("Sandbox2Part Title", new Sandbox2FormPart()); form1.setInput(new TestModel()); // to embed you would use form1.createUI(parent); // but here we use the convenience method to start a shell form1.startTestShell(); }
See the Example Application for an advanced example.
/** * This is the main class of the example, demonstrating an overview of all features available in * RCPForms. It is a good start to get an idea how to do things using RCPForms. * <p> * * @author vanmeegenm */ public class SandboxStackForm extends RCPForm { /** * Class DateRangeValidator is an example for a validator working on more than one field * * @author Marco van Meegen */ public static final class DateRangeValidator extends AbstractModelValidator { public Object[] getProperties() { return new String[]{AddressModel.P_ValidFrom, AddressModel.P_ValidTo}; } public IStatus validate(Object value) { AddressModel model = (AddressModel) value; IStatus result = ok(); if (model.getValidFrom() != null && model.getValidTo() != null && model.getValidFrom().after(model.getValidTo())) { result = error("From Date must be earlier than To Date"); } return result; } } /** * Constructor for SandboxStackForm */ public SandboxStackForm() { // create form with the given title and form parts super("RCPForm Sandbox Example", new Sandbox2FormPart(), new Sandbox3FormPart(), new SandboxTablePart()); } public void initializeUI() { // in initializeUI the form is created, // input-independent listeners, validators and stuff should be initialized here getValidationManager().addValidator(getSandbox3Part(), new DateRangeValidator()); // initializations which span multiple parts must be done here getSandbox3Part().getEnableButton().getSWTButton().addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { getSandbox2Part().setState(EControlState.ENABLED, !((Button) e.widget).getSelection()); getSandboxTablePart().setState(EControlState.ENABLED, !((Button) e.widget).getSelection()); } }); } public void setFocus() { getSandbox2Part().setFocus(); } private Sandbox2FormPart getSandbox2Part() { return ((Sandbox2FormPart) getPart(0)); } private Sandbox3FormPart getSandbox3Part() { return ((Sandbox3FormPart) getPart(1)); } private SandboxTablePart getSandboxTablePart() { return ((SandboxTablePart) getPart(2)); } /** * creates the models needed for the form and attaches listeners which echo changes to stdout * * @return created models */ public static Object[] createModels() { // and models final TableModel model1 = new TableModel(); final TestModel model2 = new TestModel(); final AddressModel model3 = new AddressModel(); // add some listeners to check how databinding works model2.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { System.out.println("Model2 changed: " + model2); } }); model3.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { System.out.println("Model3 changed: " + model3); } }); model1.getList().addChangeListener(new IChangeListener() { public void handleChange(ChangeEvent event) { System.out.println("Model1 list changed:" + model1); } }); model1.getSelectedList().addChangeListener(new IChangeListener() { public void handleChange(ChangeEvent event) { System.out.println("Model1 checked list changed:" + model1); } }); // set models as input // either create ui first and then set input, or if we use startTestShell(), // we must first set the input Object[] models = new Object[]{model2, model3, model1}; return models; } /** * start the form as SWT application * * @param args ignored */ public static void main(String[] args) { // create form Object[] models = createModels(); // create the form, no ui is created yet final SandboxStackForm rcpForm = new SandboxStackForm(); // set input, since form is not created the input is not bound yet, but saved for createUI() rcpForm.setInput(models); // convenience method, creates a shell and creates the form ui in the shell // since an input has been set before, the form is bound to the model and ready to go rcpForm.startTestShell(); }