/*******************************************************************************
* Copyright (c) 2006-2013 The RCP Company and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* The RCP Company - initial API and implementation
*******************************************************************************/
package com.rcpcompany.uibindings.utils;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.eclipse.ui.forms.widgets.TableWrapLayout;
import com.rcpcompany.uibindings.IBindingContext;
import com.rcpcompany.uibindings.IDisposable;
import com.rcpcompany.uibindings.IManager;
import com.rcpcompany.uibindings.IValueBinding;
import com.rcpcompany.uibindings.internal.utils.FormCreator;
/**
* This utility class is used to create complete forms based on the structure of data.
* <p>
* A new child {@link Composite} is created in the specified parent composite. The creation of the
* new child understands the following layouts in the parent: {@link FillLayout}, {@link GridLayout}
* and {@link TableWrapLayout}.
*
* @author Tonny Madsen, The RCP Company
*/
public interface IFormCreator extends IDisposable {
/**
* The factory methods for {@link IFormCreator}.
*/
final class Factory {
private Factory() {
}
/**
* Creates a new form with the specified parent.
*
* @param context the binding context to use or <code>null</code>
* @param obj the current object
* @param toolkit the {@link FormToolkit} to use or <code>null</code>
* @param parent the parent composite of the new form
* @return the created form creator
*/
public static IFormCreator createForm(IBindingContext context, EObject obj, FormToolkit toolkit,
Composite parent) {
return new FormCreator(context, obj, toolkit, parent, null);
}
/**
* Creates a new form with the specified parent.
*
* @param context the binding context to use or <code>null</code>
* @param value the observable value
* @param toolkit the {@link FormToolkit} to use or <code>null</code>
* @param parent the parent composite of the new form
* @return the created form creator
*/
public static IFormCreator createForm(IBindingContext context, IObservableValue value, FormToolkit toolkit,
Composite parent) {
return new FormCreator(context, value, toolkit, parent, null);
}
/**
* Creates a new form with the specified parent.
*
* @param parent the parent composite of the new form
* @return the created form creator
*/
public static IFormCreator createForm(Composite parent) {
return createForm(null, (EObject) null, IManager.Factory.getManager().getFormToolkit(parent), parent);
}
/**
* Creates a new form with the specified parent.
*
* @param context the binding context to use or <code>null</code>
* @param value the observable value for the form
* @param toolkit the {@link FormToolkit} to useor <code>null</code>
* @param parent the parent composite of the new form
* @param formHeader the header text used for the form
* @return the created form creator
*/
public static IFormCreator createScrolledForm(IBindingContext context, IObservableValue value,
FormToolkit toolkit, Composite parent, String formHeader) {
return new FormCreator(context, value, toolkit, parent, formHeader);
}
/**
* Creates a new form with the specified parent.
*
* @param context the binding context to use or <code>null</code>
* @param obj the current object
* @param toolkit the {@link FormToolkit} to use or <code>null</code>
* @param parent the parent composite of the new form
* @param formHeader the header text used for the form
* @return the created form creator
*/
public static IFormCreator createScrolledForm(IBindingContext context, EObject obj, FormToolkit toolkit,
Composite parent, String formHeader) {
return new FormCreator(context, obj, toolkit, parent, formHeader);
}
/**
* Creates a new form with the specified parent.
*
* @param value the observable value for the form
* @param parent the parent composite of the new form
* @param formHeader the header text used for the form
* @return the created form creator
*/
public static IFormCreator createScrolledForm(IObservableValue value, Composite parent, String formHeader) {
return createScrolledForm(null, value, IManager.Factory.getManager().getFormToolkit(parent), parent,
formHeader);
}
/**
* Creates a new form with the specified parent.
*
* @param obj the current object
* @param parent the parent composite of the new form
* @param formHeader the header text used for the form
* @return the created form creator
*/
public static IFormCreator createScrolledForm(EObject obj, Composite parent, String formHeader) {
return createScrolledForm(null, obj, IManager.Factory.getManager().getFormToolkit(parent), parent,
formHeader);
}
/**
* Creates a new form with the specified wizard page.
*
* @param obj the data object of the page
* @param page the wizard page itself
* @param parent the parent composite
* @return the created form creator
*/
public static IFormCreator createWizardPage(EObject obj, WizardPage page, Composite parent) {
return new FormCreator(obj, page, parent);
}
/**
* Creates a new form with the specified wizard page.
*
* @param obj the data object of the page
* @param page the wizard page itself
* @param toolkit the {@link FormToolkit} to use
* @param parent the parent composite
* @return the created form creator
*/
public static IFormCreator createWizardPage(EObject obj, WizardPage page, FormToolkit toolkit, Composite parent) {
return new FormCreator(obj, page, toolkit, parent);
}
}
/**
* Returns the used binding context.
*
* @return the binding context
*/
IBindingContext getContext();
/**
* Returns the scrolled form the heads this form - if defined.
*
* @return the scrolled form
*/
ScrolledForm getScrolledForm();
/**
* Returns the top {@link Composite} of this form creator.
* <p>
* The returned composite will have a {@link TableWrapLayout} with two columns.
* <p>
* Note that this composite need not be the same as the composite used in the factory.
*
* @return the top composite
*/
Composite getTop();
/**
* Returns the form toolkit used by this creator
*
* @return the toolkit
*/
FormToolkit getToolkit();
/**
* Returns the section of this form.
* <p>
* Will be <code>null</code> for "top level" section.
*
* @return the section
*/
Section getSection();
/**
* Finishes the form and all created bindings.
* <p>
* Used to finish the context.
*/
void finish();
/**
* Sets the primary object of the creator for the next set of create methods.
*
* @param object the new main object
*
* @deprecated use {@link #createScrolledForm(EObject, Composite, String)} or
* {@link #createScrolledForm(IObservableValue, Composite, String)}
*/
@Deprecated
void setObject(EObject object);
/**
* Returns the primary object of the creator.
*
* @return the primary object
*
* @deprecated use {@link #getObservableValue()}
*/
@Deprecated
EObject getObject();
/**
* Returns the observable value of the creator.
*
* @return the observable value
*/
IObservableValue getObservableValue();
/**
* Sets whether all binding created by the form is read-only. The default is <code>false</code>.
*
* @param readonly <code>true</code> if all bindings should be read-only
*/
void setReadOnly(boolean readonly);
/**
* Returns whether this form is read-only.
*
* @return <code>true</code> if this form is read-only
*/
boolean isReadOnly();
/**
* Sets the heading of the scrolled form or section that forms the base of this form creator, if
* any.
*
* @param heading the new heading
*/
void setHeading(String heading);
/**
* Creates and returns a new {@link Composite}.
* <p>
* Same as {@link #addComposite(boolean, boolean) <code>addComposite(true, false)</code>}.
* <p>
* The returned composite has a {@link FillLayout}, though this can be changed.
*
* @return the new composite
*/
Composite addComposite();
/**
* Creates and returns a new {@link Composite}.
* <p>
* The returned composite has a {@link FillLayout}, though this can be changed.
*
* @param grabHorizontal whether to grab excess horizontal space in the form
* @param grabVertical whether to grab excess vertical space in the form
*
* @return the new composite
*/
Composite addComposite(boolean grabHorizontal, boolean grabVertical);
/**
* Creates and returns a new table based on a table creator.
*
* @param grabHorizontal TODO
* @param style styles passed to the table creator
*
* @return the new table creator
*
* @deprecated use {@link #addTableCreator(EReference, boolean, int)}
*/
@Deprecated
ITableCreator addTableCreator(boolean grabHorizontal, int style);
/**
* Creates and returns a new table based on a table creator for the current object and the
* specified reference.
*
* @param ref the reference for the table
* @param grabHorizontal TODO
* @param style styles passed to the table creator
* @return the new table creator
*/
ITableCreator addTableCreator(EReference ref, boolean grabHorizontal, int style);
/**
* Adds a new section to the form with the specified label.
*
* @param label the label for the section
* @return a new independent {@link IFormCreator}
*/
IFormCreator addSection(String label);
/**
* Adds a new section to the form with the specified label.
*
* @param label the label for the section
* @param grabVertical <code>true</code> if the new section should grab as space as possible
* vertically
* @return a new independent {@link IFormCreator}
*/
IFormCreator addSection(String label, boolean grabVertical);
/**
* Adds a new section to the form with the specified label.
*
* @param label the label for the section
* @param obj the new observable
* @return a new independent {@link IFormCreator}
*/
IFormCreator addSection(String label, IObservableValue obj, boolean grabVertical);
/**
* Adds a new section to the form with the specified label for the specified base object.
*
* @param label the label for the section
* @param obj the new base object
* @return a new independent {@link IFormCreator}
*/
IFormCreator addSection(String label, EObject obj);
/**
* Adds a new section to the form with the specified label for the specified base observable.
*
* @param label the label for the section
* @param obj the new observable
* @return a new independent {@link IFormCreator}
*
* TODO test
*/
IFormCreator addSection(String label, IObservableValue obj);
/**
* Adds a simple label.
* <p>
* The label is set span the entire width of the form.
*
* @param label the label
*/
void addLabel(String label);
/**
* Adds a label and a constant value.
*
* @param label the label for the constant field
* @param value the value
* @param style additional styles to use for the value Control
*/
void addConstantField(String label, Object value, int style);
/**
* Adds a new label and field for the specified feature.
* <p>
* The text defaults to the default label of the feature
*
* @param feature the feature - of {@link #setObject(EObject) the current main object}
* @return the value binding
*/
IValueBinding addField(EStructuralFeature feature);
/**
* Adds a new observable value for the specified specification.
* <p>
* See {@link IBindingSpec} for a description of the format and use of the specification.
*
* @param spec the specification of the feature
* @return the observable value
*/
IObservableValue getObservableValue(String spec);
/**
* Adds a new observable value for the specified specification based on the specified base
* value.
* <p>
* See {@link IBindingSpec} for a description of the format and use of the specification.
*
* @param base the base value
* @param spec the specification of the feature
* @return the observable value
*/
IObservableValue getObservableValue(IObservableValue base, String spec);
/**
* Adds a new label and field for the specified specification.
* <p>
* See {@link IBindingSpec} for a description of the format and use of the specification.
* <p>
* The text defaults to the default label of the feature
*
* @param spec the specification of the feature to show
* @return the value binding
*/
IValueBinding addField(String spec);
/**
* Adds a new label and field for the specified specification.
* <p>
* See {@link IBindingSpec} for a description of the format and use of the specification.
* <p>
* The text defaults to the default label of the feature
*
* @param value the value that forms the base of the specification
* @param spec the specification of the feature to show
* @return the value binding
*/
IValueBinding addField(IObservableValue value, String spec);
/**
* Adds a new label and field for the specified feature.
* <p>
* The text defaults to the default label of the feature
*
* @param feature the feature - of {@link #setObject(EObject) the current main object}
* @param style additional styles to use for the value Control
* @return the value binding
*/
IValueBinding addField(EStructuralFeature feature, int style);
/**
* Adds a new label and field for the specified feature.
* <p>
* The text defaults to the default label of the feature
*
* @param object the object
* @param feature the feature - of object
* @param style additional styles to use for the value Control
* @return the value binding
*/
IValueBinding addField(EObject object, EStructuralFeature feature, int style);
/**
* Adds a new label and field for the specified observable value.
*
* @param value the observable value to show
* @param style the SWT style to use for the field
* @return the value binding
*/
IValueBinding addField(IObservableValue value, int style);
/**
* Adds a new label and field for the specified feature of the observable value.
*
* @param value the observable value to show
* @param feature the feature
* @param style TODO
* @return the value binding
*
* TODO: test
*/
IValueBinding addField(IObservableValue value, EStructuralFeature feature, int style);
/**
* Creates and returns a new sub-form of this form creator for the specified parent.
*
* @param parent the parent composite of the sub-form
* @return the sub form
*/
IFormCreator subForm(Composite parent);
/**
* Creates and returns a new sub-form of this form creator for the specified parent.
*
* @param parent the parent composite of the sub-form
* @param value the observable value of the sub-form
* @return the sub form
*/
IFormCreator subForm(Composite parent, IObservableValue value);
/**
* Sets the focus of the first field of the form that can accept focus.
*/
void setFocus();
/**
* Adds a separator between sections in this form.
* <p>
* Same as <code>addSeparator(Separator.LINE)</code>.
*/
void addSeparator();
/**
* The possible separator types.
*/
enum Separator {
LINE, MICRO, TINY, SMALL, BIG
}
/**
* Adds a separator between parts this form.
*
* @param type the wanted type of separator
*/
void addSeparator(Separator type);
/**
* Adds all objects messages for the current {@link #getObservableValue()}.
*/
void addObjectMessages();
/**
* Adds all objects messages for the specified {@link #getObservableValue(String)
* getObservableValue(spec)}.
*
* @param spec the specification for the object
*/
void addObjectMessages(String spec);
/**
* Adds all objects messages for the specified value.
*
* @param value the observable value
*/
void addObjectMessages(IObservableValue value);
/**
* Adds a {@link Runnable} that will be run <em>after</em> the form has been finalized.
*
* @param runnable the {@link Runnable} to run
*/
void addFinalizer(Runnable runnable);
/**
* Sets the layout data of the specified control to cover a part of this form.
*
* @param ctl the control
* @param grabHorizontal <code>true</code> if horizontal space should be grabed
* @param grabVertical <code>true</code> if vertical space should be grabed
*/
void setLayoutData(Control ctl, boolean grabHorizontal, boolean grabVertical);
/**
* Splits the current form into a number of parallel forms.
* <p>
* A boolean argument is specified for each column to be added. The boolean specifies whether
* the column should grab space or not. Thus to add three columns, where only the middle column
* should grab space use the call
*
* <pre>
* IFormCreator[] columns = ...addColumns(false, true, false);
* </pre>
*
* @param grab whether the column should grab space or not
* @return the constructed forms
*/
IFormCreator[] addColumns(boolean... grab);
/**
* Splits the current form into a number of parallel forms each formatted according to the
* {@link GridData} object.
* <p>
* A {@link GridData} object is specified for each column to be added.
*
* @param layoutData layout data for the specific column
* @return the constructed forms
*/
IFormCreator[] addColumns(GridData... layoutData);
/**
* Adds a new form chooser based on discriminant in another field.
*
* @param discriminant the discriminator field
* @return the created chooser
*/
IFormChooser addFormChooser(IValueBinding discriminant);
/**
* Adds a new form chooser based on discriminant.
*
* @param discriminant the discriminator
* @return the created chooser
*/
IFormChooser addFormChooser(IObservableValue discriminant);
/**
* Returns whether the created fields in this form creator and all child form are aligned on the
* left edge.
*
* @return <code>true</code> if they are aligned
*/
boolean areFieldsAligned();
/**
* Set whether the created fields in this form creator and all child form are aligned on the
* left edge.
*
* @param align <code>true</code> if they are aligned
*/
void setFieldsAligned(boolean align);
/**
* Returns whether this form is a top-level form or not.
*
* @return true if it is a top-level form
*/
boolean isTopForm();
/**
* Returns a {@link Composite} with {@link TableWrapData} layout.
*
* @return a suitable Composite for the fields
*/
Composite getFieldsComposite();
/**
* Creates a link in this section with the given text.
* <p>
* The link will execute the specified command when pressed.
* <p>
* The given link text must include exactly one <code><a href="..."></code> element where
* the href is a valid Eclipse command as decoded by ICommandService#deserialize(...). E.g. "
* <code>The list can be configured <a href="...">here</a>.</code>"
*
* @param linkText the text for the link
*/
void addCommandLink(String linkText);
}