Menu

ManualLayerForm

Remo

Form Layer

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.

RCPForm

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:

  • created: state after construction, no ui, nothing bound, but you can set an input
  • UI constructed: state after calling createUI(); if an input was set before calling createUI(), it will directly enter the bound state
  • bound: ui is constructed and widgets are bound to an input; with setInput() you can get from UI constructed state to bound state, you can rebind as often as you like

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.

Integration into Eclipse

To embed an RCPForm into Eclipse artefacts like Dialogs, Wizards, Views several wrapper classes exist which do it for you:

  • RCPFormDialog starts a form in a dialog; default behavior is to disable the ok button if the form is invalid
  • RCPFormViewPart creates a view part
  • RCPFormWizardPage

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.

Simple Form Example

To create a form, follow these steps:

  • create a model, preferredly a JavaBean or EMF model (TODO: simple model example)
  • create one or more formparts which constitute your UI (TODO: simple form part example)
  • create a form like shown below
  • 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();
        }
    

Complex Form Example

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();
    }

Related

Documentation: ManualLayers

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.