/*******************************************************************************
 * Copyright (c) 2008 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.ui.internal.widgets;

import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jpt.ui.WidgetFactory;
import org.eclipse.jpt.ui.internal.Tracing;
import org.eclipse.jpt.ui.internal.listeners.SWTPropertyChangeListenerWrapper;
import org.eclipse.jpt.ui.internal.swt.BooleanButtonModelAdapter;
import org.eclipse.jpt.ui.internal.swt.CComboModelAdapter;
import org.eclipse.jpt.ui.internal.swt.ComboModelAdapter;
import org.eclipse.jpt.ui.internal.swt.SpinnerModelAdapter;
import org.eclipse.jpt.ui.internal.swt.TextFieldModelAdapter;
import org.eclipse.jpt.ui.internal.swt.TriStateCheckBoxModelAdapter;
import org.eclipse.jpt.ui.internal.util.ControlAligner;
import org.eclipse.jpt.ui.internal.util.LabeledButton;
import org.eclipse.jpt.ui.internal.util.LabeledControlUpdater;
import org.eclipse.jpt.ui.internal.util.SWTUtil;
import org.eclipse.jpt.utility.internal.ClassTools;
import org.eclipse.jpt.utility.internal.StringConverter;
import org.eclipse.jpt.utility.internal.model.value.SimplePropertyValueModel;
import org.eclipse.jpt.utility.model.Model;
import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
import org.eclipse.jpt.utility.model.listener.PropertyChangeListener;
import org.eclipse.jpt.utility.model.value.ListValueModel;
import org.eclipse.jpt.utility.model.value.PropertyValueModel;
import org.eclipse.jpt.utility.model.value.WritablePropertyValueModel;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.help.IWorkbenchHelpSystem;
import org.eclipse.ui.part.PageBook;

/**
 * The abstract definition of a pane which holds onto a <code>PropertyValueModel</code>
 * that contains the subject of this pane.
 * <p>
 * It also contains convenience methods for building buttons, labels, check
 * boxes, and radio buttons, etc.
 * <p>
 * It is possible to easily listen to any property changes coming from the
 * subject, {@link #addPropertyNames(Collection)} is specify which properties
 * are of interest and {@link #propertyChanged(String)} is used to notify the
 * pane when the property has changed.
 *
 * @see AbstractFormPane
 * @see AbstractDialogPane
 *
 * @version 2.0
 * @since 2.0
 */
@SuppressWarnings("nls")
public abstract class AbstractPane<T extends Model>
{
	/**
	 * The listener registered with the subject in order to be notified when a
	 * property has changed, the property names are determined by
	 * {@link #propertyNames()}.
	 */
	private PropertyChangeListener aspectChangeListener;

	/**
	 * The container of this composite.
	 */
	private Composite container;

	/**
	 *
	 */
	private ArrayList<AbstractPane<?>> internalPanesForEnablementControl;

	/**
	 * The aligner responsible to align the left controls.
	 */
	private ControlAligner leftControlAligner;

	/**
	 * Flag used to stop the circular population of widgets.
	 */
	private boolean populating;

	/**
	 * The aligner responsible to align the left controls.
	 */
	private ControlAligner rightControlAligner;

	/**
	 * This listener is registered with the subject holder in order to
	 * automatically repopulate this pane with the new subject.
	 */
	private PropertyChangeListener subjectChangeListener;

	/**
	 * The subject of this pane.
	 */
	private PropertyValueModel<T> subjectHolder;

	/**
	 * The collection of registered sub-panes will be automatically notified
	 * when listeners need to be engaged or disengaged or when to populate its
	 * widgets.
	 */
	private Collection<AbstractPane<?>> subPanes;

	/**
	 * The factory used to create various common widgets.
	 */
	private WidgetFactory widgetFactory;

	/**
	 * The collection of <code>Control</code>s that are displayed in this pane,
	 * which will have their enablement state updated when
	 * {@link #enableWidgets(boolean)} is called.
	 */
	private ArrayList<Control> widgets;

	/**
	 * Creates a new <code>AbstractSubjectPane</code>.
	 *
	 * @category Constructor
	 */
	@SuppressWarnings("unused")
	private AbstractPane() {
		super();
	}

	/**
	 * Creates a new <code>AbstractSubjectPane</code>.
	 *
	 * @param parentPane The parent pane of this one
	 * @param parent The parent container
	 *
	 * @category Constructor
	 */
	protected AbstractPane(AbstractPane<? extends T> parentPane,
	                       Composite parent) {

		this(parentPane, parent, true);
	}

	/**
	 * Creates a new <code>AbstractSubjectPane</code>.
	 *
	 * @param parentPane The parent container of this one
	 * @param parent The parent container
	 * @param widgetFactory The factory used to create various widgets
	 * @param automaticallyAlignWidgets <code>true</code> to make the widgets
	 * this pane aligned with the widgets of the given parent pane;
	 * <code>false</code> to not align them
	 *
	 * @category Constructor
	 */
	protected AbstractPane(AbstractPane<? extends T> parentPane,
	                       Composite parent,
	                       boolean automaticallyAlignWidgets) {

		this(parentPane,
		     parentPane.getSubjectHolder(),
		     parent,
		     automaticallyAlignWidgets);
	}

	/**
	 * Creates a new <code>AbstractSubjectPane</code>.
	 *
	 * @param parentPane The parent container of this one
	 * @param subjectHolder The holder of this pane's subject
	 * @param parent The parent container
	 *
	 * @category Constructor
	 */
	protected AbstractPane(AbstractPane<?> parentPane,
	                       PropertyValueModel<? extends T> subjectHolder,
	                       Composite parent) {

		this(parentPane, subjectHolder, parent, true);
	}

	/**
	 * Creates a new <code>AbstractSubjectPane</code>.
	 *
	 * @param parentPane The parent container of this one
	 * @param subjectHolder The holder of this pane's subject
	 * @param parent The parent container
	 * @param widgetFactory The factory used to create various widgets
	 * @param automaticallyAlignWidgets <code>true</code> to make the widgets
	 * this pane aligned with the widgets of the given parent pane;
	 * <code>false</code> to not align them
	 *
	 * @category Constructor
	 */
	protected AbstractPane(AbstractPane<?> parentPane,
	                       PropertyValueModel<? extends T> subjectHolder,
	                       Composite parent,
	                       boolean automaticallyAlignWidgets) {

		this(subjectHolder,
		     parent,
		     parentPane.getWidgetFactory());

		initialize(parentPane, automaticallyAlignWidgets);
	}

	/**
	 * Creates a new <code>AbstractSubjectPane</code>.
	 *
	 * @param subjectHolder The holder of this pane's subject
	 * @param parent The parent container
	 * @param widgetFactory The factory used to create various common widgets
	 *
	 * @category Constructor
	 */
	protected AbstractPane(PropertyValueModel<? extends T> subjectHolder,
	                       Composite parent,
	                       WidgetFactory widgetFactory) {

		super();

		this.initialize(subjectHolder, widgetFactory);

		try {
			this.populating = true;

			this.container = this.buildContainer(parent);
			this.initializeLayout(this.container);
		}
		finally {
			this.populating = false;
		}
	}

	/**
	 * Adds the given pane's widgets (those that were registered with its
	 * left <code>ControlAligner</code>) to this pane's left
	 * <code>ControlAligner</code> so that their width can be adjusted to have
	 * the width of the widest widget.
	 *
	 * @param pane The pane containing the widgets to add
	 *
	 * @category Layout
	 */
	protected final void addAlignLeft(AbstractPane<?> container) {
		this.leftControlAligner.add(container.leftControlAligner);
	}

	/**
	 * Adds the given control to the collection of widgets that have their width
	 * adjust with the width of the widest widget. The left alignment is usually
	 * used for labels.
	 *
	 * @param pane The pane to add
	 *
	 * @category Layout
	 */
	protected final void addAlignLeft(Control control) {
		this.leftControlAligner.add(control);
	}

	/**
	 * Adds the given pane's widgets (those that were registered with its
	 * right <code>ControlAligner</code>) to this pane's right
	 * <code>ControlAligner</code> so that their width can be adjusted to have
	 * the width of the widest widget.
	 *
	 * @param pane The pane containing the widgets to add
	 *
	 * @category Layout
	 */
	protected final void addAlignRight(AbstractPane<?> container) {
		this.rightControlAligner.add(container.rightControlAligner);
	}

	/**
	 * Adds the given control to the collection of widgets that have their width
	 * adjust with the width of the widest widget. The left alignment is usually
	 * used for buttons.
	 *
	 * @param pane The pane to add
	 *
	 * @category Layout
	 */
	protected final void addAlignRight(Control control) {
		this.rightControlAligner.add(control);
	}

	/**
	 * Adds the given pane's controls (those that were registered for
	 * alignment) from this pane.
	 *
	 * @param pane The pane containing the widgets to add for
	 * alignment
	 *
	 * @category Layout
	 */
	protected final void addPaneForAlignment(AbstractPane<?> container) {
		addAlignLeft(container);
		addAlignRight(container);
	}

	/**
	 * Adds any property names to the given collection in order to be notified
	 * when the actual property changes in the subject.
	 *
	 * @param propertyNames The collection of property names to register with the
	 * subject
	 */
	protected void addPropertyNames(Collection<String> propertyNames) {
	}

	/**
	 * Indicates that the given <code>Control</code> has its enablement state
	 * managed by this pane, i.e. through {@link #enableWidgets(boolean)}.
	 *
	 * @param control The <code>Control</code> to manage its enablement state
	 * automatically
	 *
	 * @category Layout
	 */
	public final void addToEnablementControl(Control control) {
		control.setData("enablement", null);
	}

	private PropertyChangeListener buildAspectChangeListener() {
		return new SWTPropertyChangeListenerWrapper(buildAspectChangeListener_());
	}

	private PropertyChangeListener buildAspectChangeListener_() {
		return new PropertyChangeListener() {
			public void propertyChanged(PropertyChangeEvent e) {
				//subject() could have changed or is null because of the possibility of
				//"jumping" on the UI thread here and a selection change occuring
				if (e.getSource() == subject()) {
					updatePane(e.getPropertyName());
				}
			}
		};
	}

	/**
	 * Creates a new button using the given information.
	 *
	 * @param parent The parent container
	 * @param buttonText The button's text
	 * @param buttonAction The action to be invoked when the button is pressed
	 * @return The newly created <code>Button</code>
	 *
	 * @category Layout
	 */
	protected final Button buildButton(Composite container,
	                                   String text,
	                                   final Runnable buttonAction) {

		return this.buildButton(container, text, null, buttonAction);
	}

	/**
	 * Creates a new button using the given information.
	 *
	 * @param parent The parent container
	 * @param buttonText The button's text
	 * @param helpId The topic help ID to be registered for the new check box
	 * @param buttonAction The action to be invoked when the button is pressed
	 * @return The newly created <code>Button</code>
	 *
	 * @category Layout
	 */
	protected final Button buildButton(Composite container,
	                                   String text,
	                                   String helpId,
	                                   final Runnable buttonAction) {

		Button button = this.widgetFactory.createButton(container, text);
		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				SWTUtil.asyncExec(buttonAction);
			}
		});

		if (helpId != null) {
			helpSystem().setHelp(button, helpId);
		}

		GridData gridData = new GridData();
		gridData.grabExcessHorizontalSpace = false;
		gridData.horizontalAlignment       = GridData.FILL;
		button.setLayoutData(gridData);

		return button;
	}

	/**
	 * Creates a new non-editable <code>CCombo</code>.
	 *
	 * @param container The parent container
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final CCombo buildCCombo(Composite container) {

		CCombo combo = this.widgetFactory.createCCombo(container);
		combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		return combo;
	}

	/**
	 * Creates a new non-editable <code>CCombo</code>.
	 *
	 * @param container The parent container
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildCCombo(Composite container,
	                                       ListValueModel<V> listHolder,
	                                       WritablePropertyValueModel<V> selectedItemHolder) {

		return this.buildCCombo(
			container,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance()
		);
	}

	/**
	 * Creates a new non-editable <code>CCombo</code>.
	 *
	 * @param container The parent container
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param stringConverter The converter responsible to transform each item
	 * into a string representation
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildCCombo(Composite container,
	                                       ListValueModel<V> listHolder,
	                                       WritablePropertyValueModel<V> selectedItemHolder,
	                                       StringConverter<V> stringConverter) {

		CCombo combo = this.buildCCombo(container);

		CComboModelAdapter.adapt(
			listHolder,
			selectedItemHolder,
			combo,
			stringConverter
		);

		return combo;
	}

	/**
	 * Creates a new <code>ComboViewer</code> using a <code>CCombo</code>.
	 *
	 * @param container The parent container
	 * @param labelProvider The provider responsible to convert the combo's items
	 * into human readable strings
	 * @return The newly created <code>ComboViewer</code>
	 *
	 * @category Layout
	 */
	protected final ComboViewer buildCComboViewer(Composite container,
	                                              IBaseLabelProvider labelProvider) {

		CCombo combo = this.buildCCombo(container);
		ComboViewer viewer = new ComboViewer(combo);
		viewer.setLabelProvider(labelProvider);
		return viewer;
	}

	/**
	 * Creates a new check box using the given information.
	 *
	 * @param parent The parent container
	 * @param buttonText The button's text
	 * @param booleanHolder The holder of the selection state
	 * @return The newly created <code>Button</code>
	 *
	 * @category Layout
	 */
	protected final Button buildCheckBox(Composite parent,
	                                     String buttonText,
	                                     WritablePropertyValueModel<Boolean> booleanHolder) {

		return this.buildCheckBox(parent, buttonText, booleanHolder, null);
	}

	/**
	 * Creates a new check box using the given information.
	 *
	 * @param parent The parent container
	 * @param buttonText The button's text
	 * @param booleanHolder The holder of the selection state
	 * @param helpId The topic help ID to be registered for the new check box
	 * @return The newly created <code>Button</code>
	 *
	 * @category Layout
	 */
	protected final Button buildCheckBox(Composite parent,
	                                     String buttonText,
	                                     WritablePropertyValueModel<Boolean> booleanHolder,
	                                     String helpId) {

		return this.buildToggleButton(
			parent,
			buttonText,
			booleanHolder,
			helpId,
			SWT.CHECK
		);
	}

	/**
	 * Creates a new <code>Section</code> that can be collapsed. A sub-pane is
	 * automatically added as its client and is the returned <code>Composite</code>.
	 *
	 * @param container The container of the new widget
	 * @param sectionText The text of the new section
	 * @return The <code>Section</code>'s sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildCollapsableSection(Composite container,
	                                                  String sectionText) {

		return this.buildCollapsableSection(
			container,
			sectionText,
			new SimplePropertyValueModel<Boolean>(Boolean.FALSE)
		);
	}

	/**
	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
	 * its client and is the returned <code>Composite</code>.
	 *
	 * @param container The container of the new widget
	 * @param sectionText The text of the new section
	 * @param type The type of section to create
	 * @param expandedStateHolder The holder of the boolean that will dictate
	 * when to expand or collapse the section
	 * @return The <code>Section</code>'s sub-pane
	 *
	 * @category Layout
	 */
	private Composite buildCollapsableSection(Composite container,
	                                          String sectionText,
	                                          int type,
	                                          PropertyValueModel<Boolean> expandedStateHolder) {

		Composite subPane = this.buildSection(
			container,
			sectionText,
			ExpandableComposite.TWISTIE | type
		);

		Section section = (Section) subPane.getParent();

		expandedStateHolder.addPropertyChangeListener(
			PropertyValueModel.VALUE,
			buildExpandedStateChangeListener(section)
		);

		section.setExpanded(
			expandedStateHolder.getValue() != null ? expandedStateHolder.getValue() : true
		);

		return subPane;
	}

	/**
	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
	 * its client and is the returned <code>Composite</code>.
	 *
	 * @param container The container of the new widget
	 * @param sectionText The text of the new section
	 * @param expandedStateHolder The holder of the boolean that will dictate
	 * when to expand or collapse the section
	 * @return The <code>Section</code>'s sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildCollapsableSection(Composite container,
	                                                  String sectionText,
	                                                  PropertyValueModel<Boolean> expandedStateHolder) {

		return this.buildCollapsableSection(
			container,
			sectionText,
			ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE,
			expandedStateHolder
		);
	}

	/**
	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
	 * its client which can be typed cast directly as a <code>Composite</code>.
	 *
	 * @param container The container of the new widget
	 * @param sectionText The text of the new section
	 * @param expandedStateHolder The holder of the boolean that will dictate
	 * when to expand or collapse the section
	 * @return The <code>Section</code>'s sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildCollapsableSubSection(Composite container,
	                                          String sectionText,
	                                          PropertyValueModel<Boolean> expandedStateHolder) {

		return this.buildCollapsableSection(
			container,
			sectionText,
			SWT.NULL,
			expandedStateHolder
		);
	}

	/**
	 * Creates a new non-editable <code>Combo</code>.
	 *
	 * @param container The parent container
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final Combo buildCombo(Composite container) {

		Combo combo = this.widgetFactory.createCombo(container);
		combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		return combo;
	}

	/**
	 * Creates a new non-editable <code>Combo</code>.
	 *
	 * @param container The parent container
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildCombo(Composite container,
	                                     ListValueModel<V> listHolder,
	                                     WritablePropertyValueModel<V> selectedItemHolder) {

		return this.buildCombo(
			container,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance()
		);
	}

	/**
	 * Creates a new non-editable <code>Combo</code>.
	 *
	 * @param container The parent container
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param stringConverter The converter responsible to transform each item
	 * into a string representation
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildCombo(Composite container,
	                                     ListValueModel<V> listHolder,
	                                     WritablePropertyValueModel<V> selectedItemHolder,
	                                     StringConverter<V> stringConverter) {

		Combo combo = this.buildCombo(container);

		ComboModelAdapter.adapt(
			listHolder,
			selectedItemHolder,
			combo,
			stringConverter
		);

		return combo;
	}

	/**
	 * Creates a new <code>ComboViewer</code> using a <code>Combo</code>.
	 *
	 * @param container The parent container
	 * @param labelProvider The provider responsible to convert the combo's items
	 * into human readable strings
	 * @return The newly created <code>ComboViewer</code>
	 *
	 * @category Layout
	 */
	protected final ComboViewer buildComboViewer(Composite container,
	                                             IBaseLabelProvider labelProvider) {

		Combo combo = this.buildCombo(container);
		ComboViewer viewer = new ComboViewer(combo);
		viewer.setLabelProvider(labelProvider);
		return viewer;
	}

	/**
	 * Creates the main container of this pane. The layout and layout data are
	 * automatically set.
	 *
	 * @param parent The parent container
	 * @return The newly created <code>Composite</code> that will holds all the
	 * widgets created by this pane through {@link #initializeLayout(Composite)}
	 *
	 * @category Layout
	 */
	protected Composite buildContainer(Composite parent) {
		return this.buildSubPane(parent);
	}

	/**
	 * Creates a new editable <code>CCombo</code>.
	 *
	 * @param container The parent container
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final CCombo buildEditableCCombo(Composite container) {

		CCombo combo = this.widgetFactory.createEditableCCombo(container);
		combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		return combo;
	}

	/**
	 * Creates a new editable <code>CCombo</code>.
	 *
	 * @param container The parent container
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildEditableCCombo(Composite container,
	                                               ListValueModel<V> listHolder,
	                                               WritablePropertyValueModel<V> selectedItemHolder) {

		return this.buildEditableCCombo(
			container,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance()
		);
	}

	/**
	 * Creates a new editable <code>CCombo</code>.
	 *
	 * @param container The parent container
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param stringConverter The converter responsible to transform each item
	 * into a string representation
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildEditableCCombo(Composite container,
	                                               ListValueModel<V> listHolder,
	                                               WritablePropertyValueModel<V> selectedItemHolder,
	                                               StringConverter<V> stringConverter) {

		CCombo combo = this.buildEditableCCombo(container);

		CComboModelAdapter.adapt(
			listHolder,
			selectedItemHolder,
			combo,
			stringConverter
		);

		return combo;
	}

	/**
	 * Creates a new editable <code>ComboViewer</code> using a <code>CCombo</code>.
	 *
	 * @param container The parent container
	 * @param labelProvider The provider responsible to convert the combo's items
	 * into human readable strings
	 * @return The newly created <code>ComboViewer</code>
	 *
	 * @category Layout
	 */
	protected final ComboViewer buildEditableCComboViewer(Composite container,
	                                                      IBaseLabelProvider labelProvider) {

		CCombo combo = this.buildEditableCCombo(container);
		ComboViewer viewer = new ComboViewer(combo);
		viewer.setLabelProvider(labelProvider);
		return viewer;
	}

	/**
	 * Creates a new editable <code>Combo</code>.
	 *
	 * @param container The parent container
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final Combo buildEditableCombo(Composite container) {

		Combo combo = this.widgetFactory.createEditableCombo(container);
		combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		return combo;
	}

	/**
	 * Creates a new editable <code>Combo</code>.
	 *
	 * @param container The parent container
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildEditableCombo(Composite container,
	                                             ListValueModel<V> listHolder,
	                                             WritablePropertyValueModel<V> selectedItemHolder) {

		return this.buildEditableCombo(
			container,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance()
		);
	}

	/**
	 * Creates a new editable <code>Combo</code>.
	 *
	 * @param container The parent container
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param stringConverter The converter responsible to transform each item
	 * into a string representation
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildEditableCombo(Composite container,
	                                             ListValueModel<V> listHolder,
	                                             WritablePropertyValueModel<V> selectedItemHolder,
	                                             StringConverter<V> stringConverter) {

		Combo combo = this.buildEditableCombo(container);

		ComboModelAdapter.adapt(
			listHolder,
			selectedItemHolder,
			combo,
			stringConverter
		);

		return combo;
	}

	/**
	 * Creates a new editable <code>ComboViewer</code> using a <code>Combo</code>.
	 *
	 * @param container The parent container
	 * @param labelProvider The provider responsible to convert the combo's items
	 * into human readable strings
	 * @return The newly created <code>ComboViewer</code>
	 *
	 * @category Layout
	 */
	protected final ComboViewer buildEditableComboViewer(Composite container,
	                                                     IBaseLabelProvider labelProvider) {

		Combo combo = this.buildEditableCombo(container);
		ComboViewer viewer = new ComboViewer(combo);
		viewer.setLabelProvider(labelProvider);
		return viewer;
	}

	private PropertyChangeListener buildExpandedStateChangeListener(final Section section) {
		return new SWTPropertyChangeListenerWrapper(buildExpandedStateChangeListener_(section));
	}

	private PropertyChangeListener buildExpandedStateChangeListener_(final Section section) {
		return new PropertyChangeListener() {
			public void propertyChanged(final PropertyChangeEvent e) {
				Boolean value = (Boolean) e.getNewValue();
				if (value == null) {
					value = Boolean.TRUE;
				}
				section.setExpanded(value);
			}
		};
	}

	/**
	 * Creates a new <code>Hyperlink</code> that will invoked the given
	 * <code>Runnable</code> when selected. The given action is always invoked
	 * from the UI thread.
	 *
	 * @param parent The parent container
	 * @param text The hyperlink's text
	 * @param hyperLinkAction The action to be invoked when the link was selected
	 * return The newly created <code>Hyperlink</code>
	 *
	 * @category Layout
	 */
	protected final Hyperlink buildHyperLink(Composite parent,
	                                         String text,
	                                         final Runnable hyperLinkAction) {

		Hyperlink link = this.widgetFactory.createHyperlink(parent, text);
		this.widgets.add(link);

		link.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseUp(MouseEvent e) {

				Hyperlink hyperLink = (Hyperlink) e.widget;

				if (hyperLink.isEnabled()) {
					SWTUtil.asyncExec(hyperLinkAction);
				}
			}
		});

		return link;
	}

	/**
	 * Creates a new lable using the given information.
	 *
	 * @param parent The parent container
	 * @param labelText The label's text
	 *
	 * @category Layout
	 */
	protected final Label buildLabel(Composite container,
	                                 String labelText) {

		return this.widgetFactory.createLabel(container, labelText);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildLabeledCCombo(Composite container,
	                                              String labelText,
	                                              ListValueModel<V> listHolder,
	                                              WritablePropertyValueModel<V> selectedItemHolder,
	                                              String helpId) {

		return this.buildLabeledCCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance(),
			helpId
		);
	}

	/**
	 * Creates a new container that will have a non-editable combo labeled with
	 * the given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildLabeledCCombo(Composite container,
	                                              String labelText,
	                                              ListValueModel<V> listHolder,
	                                              WritablePropertyValueModel<V> selectedItemHolder,
	                                              StringConverter<V> stringConverter,
	                                              Control rightControl,
	                                              String helpId) {

		CCombo combo = this.buildCCombo(
			container,
			listHolder,
			selectedItemHolder,
			stringConverter
		);

		this.buildLabeledComposite(
			container,
			labelText,
			(combo.getParent() != container) ? combo.getParent() : combo,
			rightControl,
			helpId
		);

		return combo;
	}

	/**
	 * Creates a new container that will have a non-editable combo labeled with
	 * the given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildLabeledCCombo(Composite container,
	                                              String labelText,
	                                              ListValueModel<V> listHolder,
	                                              WritablePropertyValueModel<V> selectedItemHolder,
	                                              StringConverter<V> stringConverter,
	                                              String helpId) {

		return this.buildLabeledCCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			stringConverter,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have a non-editable combo labeled with
	 * the given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param comboListener The listener that will be notified when the selection
	 * changes
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final CCombo buildLabeledCCombo(Composite container,
	                                          String labelText,
	                                          ModifyListener comboListener,
	                                          Control rightControl,
	                                          String helpId) {

		CCombo combo = this.buildCCombo(container);
		combo.addModifyListener(comboListener);

		this.buildLabeledComposite(
			container,
			labelText,
			(combo.getParent() != container) ? combo.getParent() : combo,
			rightControl,
			helpId
		);

		return combo;
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param leftControl The widget shown to the left of the main widget
	 * @param centerControl The main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final CCombo buildLabeledCCombo(Composite container,
	                                          String labelText,
	                                          ModifyListener comboListener,
	                                          String helpId) {

		return this.buildLabeledCCombo(
			container,
			labelText,
			comboListener,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have a non-editable combo labeled with
	 * the given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildLabeledCombo(Composite container,
	                                            String labelText,
	                                            ListValueModel<V> listHolder,
	                                            WritablePropertyValueModel<V> selectedItemHolder,
	                                            Control rightControl,
	                                            String helpId) {

		return this.buildLabeledCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance(),
			rightControl,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildLabeledCombo(Composite container,
	                                            String labelText,
	                                            ListValueModel<V> listHolder,
	                                            WritablePropertyValueModel<V> selectedItemHolder,
	                                            String helpId) {

		return this.buildLabeledCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance(),
			helpId
		);
	}

	/**
	 * Creates a new container that will have a non-editable combo labeled with
	 * the given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildLabeledCombo(Composite container,
	                                            String labelText,
	                                            ListValueModel<V> listHolder,
	                                            WritablePropertyValueModel<V> selectedItemHolder,
	                                            StringConverter<V> stringConverter,
	                                            Control rightControl,
	                                            String helpId) {

		Combo combo = this.buildCombo(
			container,
			listHolder,
			selectedItemHolder,
			stringConverter
		);

		this.buildLabeledComposite(
			container,
			labelText,
			(combo.getParent() != container) ? combo.getParent() : combo,
			rightControl,
			helpId
		);

		return combo;
	}

	/**
	 * Creates a new container that will have a non-editable combo labeled with
	 * the given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildLabeledCombo(Composite container,
	                                            String labelText,
	                                            ListValueModel<V> listHolder,
	                                            WritablePropertyValueModel<V> selectedItemHolder,
	                                            StringConverter<V> stringConverter,
	                                            String helpId) {

		return this.buildLabeledCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			stringConverter,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have a non-editable combo labeled with
	 * the given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param comboListener The listener that will be notified when the selection
	 * changes
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Combo buildLabeledCombo(Composite container,
	                                        String labelText,
	                                        ModifyListener comboListener,
	                                        Control rightControl,
	                                        String helpId) {

		Combo combo = this.buildCombo(container);
		combo.addModifyListener(comboListener);

		this.buildLabeledComposite(
			container,
			labelText,
			(combo.getParent() != container) ? combo.getParent() : combo,
			rightControl,
			helpId
		);

		return combo;
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param leftControl The widget shown to the left of the main widget
	 * @param centerControl The main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Combo buildLabeledCombo(Composite container,
	                                        String labelText,
	                                        ModifyListener comboListener,
	                                        String helpId) {

		return this.buildLabeledCombo(
			container,
			labelText,
			comboListener,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param leftControl The widget shown to the left of the main widget
	 * @param centerControl The main widget
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Composite buildLabeledComposite(Composite container,
	                                                Control leftControl,
	                                                Control centerControl,
	                                                Control rightControl,
	                                                String helpId) {

		// Container for the label and main composite
		container = this.buildSubPane(container, 3, 5, 0, 0, 0);

		// Left control
		GridData gridData = new GridData();
		gridData.horizontalAlignment       = GridData.BEGINNING;
		gridData.grabExcessHorizontalSpace = false;
		leftControl.setLayoutData(gridData);

		// Re-parent the left control to the new sub pane
		leftControl.setParent(container);
		this.leftControlAligner.add(leftControl);
		this.widgets.add(leftControl);

		// Center control
		centerControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		this.widgets.add(centerControl);

		// Re-parent the center control to the new sub pane
		centerControl.setParent(container);

		// Register the help id for the center control
		if (helpId != null) {
			helpSystem().setHelp(centerControl, helpId);
		}

		// Right control
		if (rightControl == null) {
			Composite spacer = this.buildPane(container);
			spacer.setLayout(this.buildSpacerLayout());
			rightControl = spacer;
		}
		else {
			rightControl.setParent(container);

			// Register the help id for the right control
			if (helpId != null) {
				helpSystem().setHelp(rightControl, helpId);
			}
		}

		gridData = new GridData();
		gridData.horizontalAlignment       = GridData.FILL_HORIZONTAL;
		gridData.grabExcessHorizontalSpace = false;

		rightControl.setLayoutData(gridData);
		this.rightControlAligner.add(rightControl);
		this.widgets.add(rightControl);

		return container;
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param label The label used to describe the center control
	 * @param centerControl The main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * control
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Composite buildLabeledComposite(Composite container,
	                                                Control label,
	                                                Control centerControl,
	                                                String helpId) {

		return this.buildLabeledComposite(
			container,
			label,
			centerControl,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param label The label used to describe the center control
	 * @param centerControl The main widget
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Composite buildLabeledComposite(Composite container,
	                                                Label label,
	                                                Control centerControl) {

		return this.buildLabeledComposite(
			container,
			label,
			centerControl,
			null
		);
	}

	/**
	 * Creates a new container that will have the given center composite labeled
	 * with the given label text.
	 *
	 * @param container The parent container
	 * @param labelText The text to label the main composite
	 * @param centerPane The main widget
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Composite buildLabeledComposite(Composite container,
	                                                String labelText,
	                                                AbstractPane<?> centerPane,
	                                                Control rightCentrol,
	                                                String helpId) {

		return this.buildLabeledComposite(
			container,
			labelText,
			centerPane.getControl(),
			rightCentrol,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center composite labeled
	 * with the given label text.
	 *
	 * @param container The parent container
	 * @param labelText The text to label the main composite
	 * @param centerPane The main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Composite buildLabeledComposite(Composite container,
	                                                String labelText,
	                                                AbstractPane<?> centerPane,
	                                                String helpId) {

		return this.buildLabeledComposite(
			container,
			labelText,
			centerPane.getControl(),
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center composite labeled
	 * with the given label text.
	 *
	 * @param container The parent container
	 * @param labelText The text to label the main composite
	 * @param centerControl The main widget
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Composite buildLabeledComposite(Composite container,
	                                                String labelText,
	                                                Control centerControl) {


		return this.buildLabeledComposite(
			container,
			labelText,
			centerControl,
			null,
			null
		);
	}

	/**
	 * Creates a new container that will have the given center composite labeled
	 * with the given label text.
	 *
	 * @param container The parent container
	 * @param labelText The text to label the main composite
	 * @param centerControl The main widget
	 * @param rightControl The control shown to the right of the main widget
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Composite buildLabeledComposite(Composite container,
	                                                String labelText,
	                                                Control centerControl,
	                                                Control rightControl) {


		return this.buildLabeledComposite(
			container,
			labelText,
			centerControl,
			rightControl,
			null
		);
	}

	/**
	 * Creates a new container that will have the given center composite labeled
	 * with the given label text.
	 *
	 * @param container The parent container
	 * @param labelText The text to label the main composite
	 * @param centerControl The main widget
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Composite buildLabeledComposite(Composite container,
	                                                String labelText,
	                                                Control centerControl,
	                                                Control rightCentrol,
	                                                String helpId) {

		return this.buildLabeledComposite(
			container,
			this.buildLabel(container, labelText),
			centerControl,
			rightCentrol,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center composite labeled
	 * with the given label text.
	 *
	 * @param container The parent container
	 * @param labelText The text to label the main composite
	 * @param centerControl The main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Composite buildLabeledComposite(Composite container,
	                                                String labelText,
	                                                Control centerControl,
	                                                String helpId) {

		Label label = this.buildLabel(container, labelText);

		return this.buildLabeledComposite(
			container,
			label,
			centerControl,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildLabeledEditableCCombo(Composite container,
	                                                      String labelText,
	                                                      ListValueModel<V> listHolder,
	                                                      WritablePropertyValueModel<V> selectedItemHolder,
	                                                      Control rightControl,
	                                                      String helpId) {

		return this.buildLabeledEditableCCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance(),
			rightControl,
			helpId
		);
	}

	/**
	 * Creates a new container that will have an editable combo labeled with the
	 * given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildLabeledEditableCCombo(Composite container,
	                                                      String labelText,
	                                                      ListValueModel<V> listHolder,
	                                                      WritablePropertyValueModel<V> selectedItemHolder,
	                                                      String helpId) {

		return this.buildLabeledEditableCCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance(),
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param stringConverter The converter responsible to transform each item
	 * into a string representation
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildLabeledEditableCCombo(Composite container,
	                                                      String labelText,
	                                                      ListValueModel<V> listHolder,
	                                                      WritablePropertyValueModel<V> selectedItemHolder,
	                                                      StringConverter<V> stringConverter,
	                                                      Control rightControl,
	                                                      String helpId) {

		CCombo combo = this.buildEditableCCombo(
			container,
			listHolder,
			selectedItemHolder,
			stringConverter
		);

		this.buildLabeledComposite(
			container,
			labelText,
			(combo.getParent() != container) ? combo.getParent() : combo,
			rightControl,
			helpId
		);

		return combo;
	}

	/**
	 * Creates a new container that will have an editable combo labeled with the
	 * given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param stringConverter The converter responsible to transform each item
	 * into a string representation
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final <V> CCombo buildLabeledEditableCCombo(Composite container,
	                                                      String labelText,
	                                                      ListValueModel<V> listHolder,
	                                                      WritablePropertyValueModel<V> selectedItemHolder,
	                                                      StringConverter<V> stringConverter,
	                                                      String helpId) {

		return this.buildLabeledEditableCCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			stringConverter,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param leftControl The widget shown to the left of the main widget
	 * @param centerControl The main widget
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final CCombo buildLabeledEditableCCombo(Composite container,
	                                                  String labelText,
	                                                  ModifyListener comboListener,
	                                                  Control rightControl,
	                                                  String helpId) {

		CCombo combo = this.buildEditableCCombo(container);
		combo.addModifyListener(comboListener);

		this.buildLabeledComposite(
			container,
			labelText,
			(combo.getParent() != container) ? combo.getParent() : combo,
			rightControl,
			helpId
		);

		return combo;
	}

	/**
	 * Creates a new container that will have an editable combo labeled with the
	 * given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param comboListener The listener that will be notified when the selection
	 * changes
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final CCombo buildLabeledEditableCCombo(Composite container,
	                                                  String labelText,
	                                                  ModifyListener comboListener,
	                                                  String helpId) {

		return this.buildLabeledEditableCCombo(
			container,
			labelText,
			comboListener,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param leftControl The widget shown to the left of the main widget
	 * @param centerControl The main widget
	 * @param labelProvider The provider responsible to convert the combo's items
	 * into human readable strings
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final CCombo buildLabeledEditableCComboViewer(Composite container,
	                                                        String labelText,
	                                                        ModifyListener comboListener,
	                                                        ILabelProvider labelProvider,
	                                                        Control rightControl,
	                                                        String helpId) {

		ComboViewer comboViewer = this.buildEditableCComboViewer(
			container,
			labelProvider
		);

		CCombo combo = comboViewer.getCCombo();
		combo.addModifyListener(comboListener);

		this.buildLabeledComposite(
			container,
			labelText,
			(combo.getParent() != container) ? combo.getParent() : combo,
			rightControl,
			helpId
		);

		return combo;
	}

	/**
	 * Creates a new container that will have an editable combo labeled with the
	 * given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param comboListener The listener that will be notified when the selection
	 * changes
	 * @param labelProvider The provider responsible to convert the combo's items
	 * into human readable strings
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>CCombo</code>
	 *
	 * @category Layout
	 */
	protected final CCombo buildLabeledEditableCComboViewer(Composite container,
	                                                        String labelText,
	                                                        ModifyListener comboListener,
	                                                        ILabelProvider labelProvider,
	                                                        String helpId) {

		return this.buildLabeledEditableCComboViewer(
			container,
			labelText,
			comboListener,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildLabeledEditableCombo(Composite container,
	                                                    String labelText,
	                                                    ListValueModel<V> listHolder,
	                                                    WritablePropertyValueModel<V> selectedItemHolder,
	                                                    Control rightControl,
	                                                    String helpId) {

		return this.buildLabeledEditableCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance(),
			rightControl,
			helpId
		);
	}

	/**
	 * Creates a new container that will have an editable combo labeled with the
	 * given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildLabeledEditableCombo(Composite container,
	                                                    String labelText,
	                                                    ListValueModel<V> listHolder,
	                                                    WritablePropertyValueModel<V> selectedItemHolder,
	                                                    String helpId) {

		return this.buildLabeledEditableCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			StringConverter.Default.<V>instance(),
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param stringConverter The converter responsible to transform each item
	 * into a string representation
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildLabeledEditableCombo(Composite container,
	                                                    String labelText,
	                                                    ListValueModel<V> listHolder,
	                                                    WritablePropertyValueModel<V> selectedItemHolder,
	                                                    StringConverter<V> stringConverter,
	                                                    Control rightControl,
	                                                    String helpId) {

		Combo combo = this.buildEditableCombo(
			container,
			listHolder,
			selectedItemHolder,
			stringConverter
		);

		this.buildLabeledComposite(
			container,
			labelText,
			(combo.getParent() != container) ? combo.getParent() : combo,
			rightControl,
			helpId
		);

		return combo;
	}

	/**
	 * Creates a new container that will have an editable combo labeled with the
	 * given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param listHolder The <code>ListValueHolder</code>
	 * @param selectedItemHolder The holder of the selected item
	 * @param stringConverter The converter responsible to transform each item
	 * into a string representation
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The newly created <code>Combo</code>
	 *
	 * @category Layout
	 */
	protected final <V> Combo buildLabeledEditableCombo(Composite container,
	                                                    String labelText,
	                                                    ListValueModel<V> listHolder,
	                                                    WritablePropertyValueModel<V> selectedItemHolder,
	                                                    StringConverter<V> stringConverter,
	                                                    String helpId) {

		return this.buildLabeledEditableCombo(
			container,
			labelText,
			listHolder,
			selectedItemHolder,
			stringConverter,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have the given center control labeled
	 * with the given label.
	 *
	 * @param container The parent container
	 * @param leftControl The widget shown to the left of the main widget
	 * @param centerControl The main widget
	 * @param rightControl The control shown to the right of the main widget
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Combo buildLabeledEditableCombo(Composite container,
	                                                String labelText,
	                                                ModifyListener comboListener,
	                                                Control rightControl,
	                                                String helpId) {

		Combo combo = this.buildEditableCombo(container);
		combo.addModifyListener(comboListener);

		this.buildLabeledComposite(
			container,
			labelText,
			(combo.getParent() != container) ? combo.getParent() : combo,
			rightControl,
			helpId
		);

		return combo;
	}

	/**
	 * Creates a new container that will have an editable combo labeled with the
	 * given text.
	 *
	 * @param container The parent container
	 * @param labelText The text of the label
	 * @param comboListener The listener that will be notified when the selection
	 * changes
	 * @param helpId The topic help ID to be registered for the given center
	 * compositer
	 * @return The container of the label and the given center control
	 *
	 * @category Layout
	 */
	protected final Combo buildLabeledEditableCombo(Composite container,
	                                                String labelText,
	                                                ModifyListener comboListener,
	                                                String helpId) {

		return this.buildLabeledEditableCombo(
			container,
			labelText,
			comboListener,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text area's label
	 * @param textHolder The holder of the text field's input
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledMultiLineText(Composite container,
	                                               String labelText,
	                                               WritablePropertyValueModel<String> textHolder) {

		return this.buildLabeledMultiLineText(
			container,
			labelText,
			textHolder,
			null
		);
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text area's label
	 * @param textHolder The holder of the text field's input
	 * @param rightControl The widget to be placed to the right of the text area
	 * @param helpId The topic help ID to be registered for the text field
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledMultiLineText(Composite container,
	                                               String labelText,
	                                               WritablePropertyValueModel<String> textHolder,
	                                               Control rightControl,
	                                               String helpId) {

		Text text = this.buildMultiLineText(container, textHolder);

		this.buildLabeledComposite(
			container,
			labelText,
			text,
			rightControl,
			helpId
		);

		return text;
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text area's label
	 * @param textHolder The holder of the text field's input
	 * @param lineCount The number of lines the text area should display
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledMultiLineText(Composite container,
	                                               String labelText,
	                                               WritablePropertyValueModel<String> textHolder,
	                                               int lineCount) {

		return this.buildLabeledMultiLineText(
			container,
			labelText,
			textHolder,
			lineCount,
			null
		);
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text area's label
	 * @param textHolder The holder of the text field's input
	 * @param lineCount The number of lines the text area should display
	 * @param helpId The topic help ID to be registered for the text field
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledMultiLineText(Composite container,
	                                               String labelText,
	                                               WritablePropertyValueModel<String> textHolder,
	                                               int lineCount,
	                                               String helpId) {

		Text text = this.buildMultiLineText(container, textHolder, lineCount);

		container = this.buildLabeledComposite(
			container,
			labelText,
			text,
			helpId
		);

		int textHeight = text.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;

		// Specify the number of lines the text area should display
		GridData gridData = (GridData) text.getLayoutData();
		gridData.heightHint = text.getLineHeight() * lineCount;

		// Move the label to the top of its cell
		Control label = container.getChildren()[0];
		int labelHeight = label.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;

		gridData = (GridData) label.getLayoutData();
		gridData.verticalAlignment = SWT.TOP;
		gridData.verticalIndent   += (Math.abs(textHeight - labelHeight) / 2);

		return text;
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text area's label
	 * @param textHolder The holder of the text field's input
	 * @param helpId The topic help ID to be registered for the text field
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledMultiLineText(Composite container,
	                                               String labelText,
	                                               WritablePropertyValueModel<String> textHolder,
	                                               String helpId) {

		return this.buildLabeledMultiLineText(
			container,
			labelText,
			textHolder,
			3,
			helpId
		);
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledPasswordText(Composite container,
	                                              String labelText,
	                                              WritablePropertyValueModel<String> textHolder) {

		return this.buildLabeledPasswordText(
			container,
			labelText,
			textHolder,
			null
		);
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text field's label
	 * @param rightComponent The component to be placed to the right of the text
	 * field
	 * @param textHolder The holder of the text field's input
	 * @param helpId The topic help ID to be registered for the text field
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledPasswordText(Composite container,
	                                              String labelText,
	                                              WritablePropertyValueModel<String> textHolder,
	                                              Control rightComponent,
	                                              String helpId) {

		Text text = this.buildPasswordText(container, textHolder);

		this.buildLabeledComposite(
			container,
			labelText,
			text,
			rightComponent,
			helpId
		);

		return text;
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @param helpId The topic help ID to be registered for the text field
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledPasswordText(Composite container,
	                                              String labelText,
	                                              WritablePropertyValueModel<String> textHolder,
	                                              String helpId) {

		return this.buildLabeledPasswordText(
			container,
			labelText,
			textHolder,
			null,
			helpId
		);
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @param helpId The topic help ID to be registered for the text field
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledPawordText(Composite container,
	                                            String labelText,
	                                            WritablePropertyValueModel<String> textHolder,
	                                            String helpId) {

		return this.buildLabeledPasswordText(
			container,
			labelText,
			textHolder,
			null,
			helpId
		);
	}

	/**
	 * Creates a new spinner.
	 *
	 * @param parent The parent container
	 * @param labelText The label's text
	 * @param numberHolder The holder of the integer value
	 * @param defaultValue The value shown when the holder has <code>null</code>
	 * @return The newly created <code>Spinner</code>
	 *
	 * @category Layout
	 */
	protected final Spinner buildLabeledSpinner(Composite parent,
	                                            String labelText,
	                                            WritablePropertyValueModel<Integer> numberHolder,
	                                            int defaultValue) {

		return this.buildLabeledSpinner(
			container,
			labelText,
			numberHolder,
			defaultValue,
			0,
			Integer.MAX_VALUE,
			null,
			null
		);
	}

	/**
	 * Creates a new spinner.
	 *
	 * @param parent The parent container
	 * @param labelText The label's text
	 * @param numberHolder The holder of the integer value
	 * @param defaultValue The value shown when the holder has <code>null</code>
	 * @param rightControl The widget to be placed to the right of spinner
	 * @return The newly created <code>Spinner</code>
	 *
	 * @category Layout
	 */
	protected final Spinner buildLabeledSpinner(Composite parent,
	                                            String labelText,
	                                            WritablePropertyValueModel<Integer> numberHolder,
	                                            int defaultValue,
	                                            Control rightControl) {

		return this.buildLabeledSpinner(
			container,
			labelText,
			numberHolder,
			defaultValue,
			0,
			Integer.MAX_VALUE,
			rightControl,
			null
		);
	}

	/**
	 * Creates a new spinner.
	 *
	 * @param parent The parent container
	 * @param labelText The label's text
	 * @param numberHolder The holder of the integer value
	 * @param defaultValue The value shown when the holder has <code>null</code>
	 * @param minimumValue The minimum value that the spinner will allow
	 * @param maximumValue The maximum value that the spinner will allow
	 * @param rightControl The widget to be placed to the right of spinner
	 * @return The newly created <code>Spinner</code>
	 *
	 * @category Layout
	 */
	protected final Spinner buildLabeledSpinner(Composite parent,
	                                            String labelText,
	                                            WritablePropertyValueModel<Integer> numberHolder,
	                                            int defaultValue,
	                                            int minimumValue,
	                                            int maximumValue,
	                                            Control rightControl) {

		return this.buildLabeledSpinner(
			parent,
			labelText,
			numberHolder,
			defaultValue,
			minimumValue,
			maximumValue,
			rightControl,
			null
		);
	}

	/**
	 * Creates a new spinner.
	 *
	 * @param parent The parent container
	 * @param labelText The label's text
	 * @param numberHolder The holder of the integer value
	 * @param defaultValue The value shown when the holder has <code>null</code>
	 * @param minimumValue The minimum value that the spinner will allow
	 * @param maximumValue The maximum value that the spinner will allow
	 * @param rightControl The widget to be placed to the right of spinner
	 * @param helpId The topic help ID to be registered for the spinner
	 * @return The newly created <code>Spinner</code>
	 *
	 * @category Layout
	 */
	protected final Spinner buildLabeledSpinner(Composite parent,
	                                            String labelText,
	                                            WritablePropertyValueModel<Integer> numberHolder,
	                                            int defaultValue,
	                                            int minimumValue,
	                                            int maximumValue,
	                                            Control rightControl,
	                                            String helpId) {

		Spinner spinner = this.buildSpinner(
			parent,
			numberHolder,
			defaultValue,
			minimumValue,
			maximumValue
		);

		buildLabeledComposite(
			parent,
			labelText,
			(spinner.getParent() != parent) ? spinner.getParent() : spinner,
			rightControl,
			helpId
		);

		GridData gridData = (GridData) spinner.getLayoutData();
		gridData.horizontalAlignment = GridData.BEGINNING;

		return spinner;
	}

	/**
	 * Creates a new spinner.
	 *
	 * @param parent The parent container
	 * @param labelText The label's text
	 * @param numberHolder The holder of the integer value
	 * @param defaultValue The value shown when the holder has <code>null</code>
	 * @param minimumValue The minimum value that the spinner will allow
	 * @param maximumValue The maximum value that the spinner will allow
	 * @param helpId The topic help ID to be registered for the spinner
	 * @return The newly created <code>Spinner</code>
	 *
	 * @category Layout
	 */
	protected final Spinner buildLabeledSpinner(Composite parent,
	                                            String labelText,
	                                            WritablePropertyValueModel<Integer> numberHolder,
	                                            int defaultValue,
	                                            int minimumValue,
	                                            int maximumValue,
	                                            String helpId) {

		return this.buildLabeledSpinner(
			parent,
			labelText,
			numberHolder,
			defaultValue,
			0,
			Integer.MAX_VALUE,
			null,
			helpId
		);
	}

	/**
	 * Creates a new spinner.
	 *
	 * @param parent The parent container
	 * @param labelText The label's text
	 * @param numberHolder The holder of the integer value
	 * @param defaultValue The value shown when the holder has <code>null</code>
	 * @param helpId The topic help ID to be registered for the spinner
	 * @return The newly created <code>Spinner</code>
	 *
	 * @category Layout
	 */
	protected final Spinner buildLabeledSpinner(Composite parent,
	                                            String labelText,
	                                            WritablePropertyValueModel<Integer> numberHolder,
	                                            int defaultValue,
	                                            String helpId) {

		return this.buildLabeledSpinner(
			parent,
			labelText,
			numberHolder,
			defaultValue,
			0,
			Integer.MAX_VALUE,
			null,
			null
		);
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledText(Composite container,
	                                      String labelText,
	                                      WritablePropertyValueModel<String> textHolder) {

		return this.buildLabeledText(container, labelText, textHolder, null);
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param labelText The text field's label
	 * @param rightComponent The component to be placed to the right of the text
	 * field
	 * @param textHolder The holder of the text field's input
	 * @param helpId The topic help ID to be registered for the text field
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledText(Composite container,
	                                      String labelText,
	                                      WritablePropertyValueModel<String> textHolder,
	                                      Control rightComponent,
	                                      String helpId) {

		Text text = this.buildText(container);
		TextFieldModelAdapter.adapt(textHolder, text);

		this.buildLabeledComposite(
			container,
			labelText,
			text,
			rightComponent,
			helpId
		);

		return text;
	}

	/**
	 * Creates a new container that will have a text field as the center control
	 * labeled with the given label.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @param helpId The topic help ID to be registered for the text field
	 * @return The newly created <code>Text</code>
	 *
	 * @category Layout
	 */
	protected final Text buildLabeledText(Composite container,
	                                      String labelText,
	                                      WritablePropertyValueModel<String> textHolder,
	                                      String helpId) {

		return this.buildLabeledText(
			container,
			labelText,
			textHolder,
			null,
			helpId
		);
	}

	/**
	 * Creates a new list and notify the given selection holder when the
	 * selection changes. If the selection count is different than one than the
	 * holder will receive <code>null</code>.
	 *
	 * @param container The parent container
	 * @return The newly created <code>List</code>
	 *
	 * @category Layout
	 */
	protected final List buildList(Composite container) {
		return this.buildList(container, (String) null);
	}

	/**
	 * Creates a new list and notify the given selection holder when the
	 * selection changes. If the selection count is different than one than the
	 * holder will receive <code>null</code>.
	 *
	 * @param container The parent container
	 * @param helpId The topic help ID to be registered for the new radio button
	 * @return The newly created <code>List</code>
	 *
	 * @category Layout
	 */
	protected final List buildList(Composite container, String helpId) {

		return this.buildList(
			container,
			new SimplePropertyValueModel<String>(),
			helpId
		);
	}

	/**
	 * Creates a new list and notify the given selection holder when the
	 * selection changes. If the selection count is different than one than the
	 * holder will receive <code>null</code>.
	 *
	 * @param container The parent container
	 * @param selectionHolder The holder of the unique selected item
	 * @return The newly created <code>List</code>
	 *
	 * @category Layout
	 */
	protected final List buildList(Composite container,
	                               WritablePropertyValueModel<String> selectionHolder) {

		return this.buildList(container, selectionHolder, null);
	}

	/**
	 * Creates a new list and notify the given selection holder when the
	 * selection changes. If the selection count is different than one than the
	 * holder will receive <code>null</code>.
	 *
	 * @param container The parent container
	 * @param selectionHolder The holder of the unique selected item
	 * @param helpId The topic help ID to be registered for the new radio button
	 * @return The newly created <code>List</code>
	 *
	 * @category Layout
	 */
	protected final List buildList(Composite container,
	                               WritablePropertyValueModel<String> selectionHolder,
	                               String helpId) {

		List list = this.widgetFactory.createList(
			container,
			SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI
		);

		list.addSelectionListener(buildSelectionListener(selectionHolder));
		list.setLayoutData(new GridData(GridData.FILL_BOTH));
		this.widgets.add(list);

		if (helpId != null) {
			helpSystem().setHelp(list, helpId);
		}

		return list;
	}

	/**
	 * Creates a new lable expanding on multiple lines.
	 *
	 * @param parent The parent container
	 * @param labelText The label's text
	 *
	 * @category Layout
	 */
	protected final void buildMultiLineLabel(Composite container,
	                                         String labelText) {

		this.widgetFactory.createMultiLineLabel(container, labelText);
	}

	/**
	 * Creates a new <code>Text</code> widget that has multiple lines.
	 *
	 * @param container The parent container
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildMultiLineText(Composite container) {
		return this.buildMultiLineText(container, 3, null);
	}

	/**
	 * Creates a new <code>Text</code> widget that has multiple lines.
	 *
	 * @param container The parent container
	 * @param lineCount The number of lines the text area should display
	 * @param helpId The topic help ID to be registered for the new text
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildMultiLineText(Composite container,
	                                        int lineCount,
	                                        String helpId) {

		Text text = this.widgetFactory.createMultiLineText(container);

		GridData gridData   = new GridData(GridData.FILL_HORIZONTAL);
		gridData.heightHint = text.getLineHeight() * lineCount;
		text.setLayoutData(gridData);

		if (helpId != null) {
			helpSystem().setHelp(text, helpId);
		}

		return text;
	}

	/**
	 * Creates a new <code>Text</code> widget that has multiple lines.
	 *
	 * @param container The parent container
	 * @param helpId The topic help ID to be registered for the new text
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildMultiLineText(Composite container, String helpId) {

		return this.buildMultiLineText(container, 3, helpId);
	}

	/**
	 * Creates a new <code>Text</code> widget that has multiple lines.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildMultiLineText(Composite container,
	                                        WritablePropertyValueModel<String> textHolder) {

		return this.buildMultiLineText(container, textHolder, null);
	}

	/**
	 * Creates a new <code>Text</code> widget that has multiple lines.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @param lineCount The number of lines the text area should display
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildMultiLineText(Composite container,
	                                        WritablePropertyValueModel<String> textHolder,
	                                        int lineCount) {

		return this.buildMultiLineText(container, textHolder, lineCount, null);
	}

	/**
	 * Creates a new <code>Text</code> widget that has multiple lines.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @param helpId The topic help ID to be registered for the new text
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildMultiLineText(Composite container,
	                                        WritablePropertyValueModel<String> textHolder,
	                                        int lineCount,
	                                        String helpId) {

		Text text = this.buildMultiLineText(container, lineCount, helpId);
		TextFieldModelAdapter.adapt(textHolder, text);
		return text;
	}

	/**
	 * Creates a new <code>Text</code> widget that has multiple lines.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @param helpId The topic help ID to be registered for the new text
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildMultiLineText(Composite container,
	                                        WritablePropertyValueModel<String> textHolder,
	                                        String helpId) {

		return this.buildMultiLineText(container, textHolder, 3, helpId);
	}

	/**
	 * Creates a new <code>PageBook</code> and set the proper layout and layout
	 * data.
	 *
	 * @param container The parent container
	 * @return The newly created <code>PageBook</code>
	 *
	 * @category Layout
	 */
	protected final PageBook buildPageBook(Composite container) {

		PageBook pageBook = new PageBook(container, SWT.NULL);
		pageBook.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		return pageBook;
	}

	/**
	 * Creates a new container without specifying any layout manager.
	 *
	 * @param container The parent of the new container
	 * @return The newly created <code>Composite</code>
	 *
	 * @category Layout
	 */
	protected final Composite buildPane(Composite parent) {
		return this.widgetFactory.createComposite(parent);
	}

	/**
	 * Creates a new container using the given layout manager.
	 *
	 * @param parent The parent of the new container
	 * @param layout The layout manager of the new container
	 * @return The newly created container
	 *
	 * @category Layout
	 */
	protected final Composite buildPane(Composite container, Layout layout) {

		container = this.widgetFactory.createComposite(container);
		container.setLayout(layout);
		container.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		return container;
	}

	/**
	 * Creates a new <code>Text</code> widget.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildPasswordText(Composite container,
	                                       WritablePropertyValueModel<String> textHolder) {

		Text text = this.widgetFactory.createPasswordText(container);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		TextFieldModelAdapter.adapt(textHolder, text);

		return text;
	}

	/**
	 * Creates a new push button using the given information.
	 *
	 * @param parent The parent container
	 * @param buttonText The button's text
	 * @param buttonAction The action to be invoked when the button is pressed
	 * @return The newly created <code>Button</code>
	 *
	 * @category Layout
	 */
	protected final Button buildPushButton(Composite parent,
	                                       String buttonText,
	                                       final Runnable buttonAction) {

		return this.buildPushButton(parent, buttonText, null, buttonAction);
	}

	/**
	 * Creates a new push button using the given information.
	 *
	 * @param parent The parent container
	 * @param buttonText The button's text
	 * @param buttonAction The action to be invoked when the button is pressed
	 * @param helpId The topic help ID to be registered for the new radio button
	 * @return The newly created <code>Button</code>
	 *
	 * @category Layout
	 */
	protected final Button buildPushButton(Composite parent,
	                                       String buttonText,
	                                       String helpId,
	                                       final Runnable buttonAction) {

		Button button = this.widgetFactory.createPushButton(parent, buttonText);

		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				SWTUtil.asyncExec(buttonAction);
			}
		});

		button.setLayoutData(new GridData());

		if (helpId != null) {
			helpSystem().setHelp(button, helpId);
		}

		return button;
	}

	/**
	 * Creates a new radio button using the given information.
	 *
	 * @param parent The parent container
	 * @param buttonText The button's text
	 * @param booleanHolder The holder of the selection state
	 * @return The newly created <code>Button</code>
	 *
	 * @category Layout
	 */
	protected final Button buildRadioButton(Composite parent,
	                                        String buttonText,
	                                        WritablePropertyValueModel<Boolean> booleanHolder) {

		return this.buildRadioButton(parent, buttonText, booleanHolder, null);
	}

	/**
	 * Creates a new check box using the given information.
	 *
	 * @param parent The parent container
	 * @param buttonText The button's text
	 * @param booleanHolder The holder of the selection state
	 * @param helpId The topic help ID to be registered for the new radio button
	 * @return The newly created <code>Button</code>
	 *
	 * @category Layout
	 */
	protected final Button buildRadioButton(Composite parent,
	                                        String buttonText,
	                                        WritablePropertyValueModel<Boolean> booleanHolder,
	                                        String helpId) {

		return this.buildToggleButton(
			parent,
			buttonText,
			booleanHolder,
			helpId,
			SWT.RADIO
		);
	}

	/**
	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
	 * its client and is the returned <code>Composite</code>.
	 *
	 * @param container The container of the new widget
	 * @param sectionText The text of the new section
	 * @return The <code>Section</code>'s sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildSection(Composite container,
	                                       String sectionText) {

		return this.buildSection(
			container,
			sectionText,
			ExpandableComposite.TITLE_BAR
		);
	}

	/**
	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
	 * its client and is the returned <code>Composite</code>.
	 *
	 * @param container The container of the new widget
	 * @param sectionText The text of the new section
	 * @param type The type of section to create
	 * @param expandedStateHolder The holder of the boolean that will dictate
	 * when to expand or collapse the section
	 * @return The <code>Section</code>'s sub-pane
	 *
	 * @category Layout
	 */
	private Composite buildSection(Composite container,
	                               String sectionText,
	                               int type) {

		return this.buildSection(container, sectionText, null, type);
	}

	/**
	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
	 * its client and is the returned <code>Composite</code>.
	 *
	 * @param container The container of the new widget
	 * @param sectionText The text of the new section
	 * @param description The section's description
	 * @return The <code>Section</code>'s sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildSection(Composite container,
	                                       String sectionText,
	                                       String description) {

		return this.buildSection(
			container,
			sectionText,
			description,
			ExpandableComposite.TITLE_BAR
		);
	}

	/**
	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
	 * its client and is the returned <code>Composite</code>.
	 *
	 * @param container The container of the new widget
	 * @param sectionText The text of the new section
	 * @param description The section's description or <code>null</code> if none
	 * was provider
	 * @param type The type of section to create
	 * @param expandedStateHolder The holder of the boolean that will dictate
	 * when to expand or collapse the section
	 * @return The <code>Section</code>'s sub-pane
	 *
	 * @category Layout
	 */
	private Composite buildSection(Composite container,
	                               String sectionText,
	                               String description,
	                               int type) {

		Section section = this.widgetFactory.createSection(container, type | ((description != null) ? Section.DESCRIPTION : SWT.NULL));
		section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		section.setText(sectionText);
		section.marginWidth  = 0;
		section.marginHeight = 0;

		if (description != null) {
			section.setDescription(description);
		}

		Composite subPane = this.buildSubPane(section);
		section.setClient(subPane);

		return subPane;
	}

	private SelectionListener buildSelectionListener(final WritablePropertyValueModel<String> selectionHolder) {
		return new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				List list = (List) e.widget;
				String[] selectedItems = list.getSelection();
				if ((selectedItems == null) || (selectedItems.length != 1)) {
					selectionHolder.setValue(null);
				}
				else {
					selectionHolder.setValue(selectedItems[0]);
				}
			}
		};
	}

	/**
	 * Creates the layout responsible to compute the size of the spacer created
	 * for the right control when none was given. The spacer helps to align all
	 * the right controls.
	 *
	 * @category Layout
	 */
	private Layout buildSpacerLayout() {
		return new Layout() {
			@Override
			protected Point computeSize(Composite composite,
			                            int widthHint,
			                            int heightHint,
			                            boolean flushCache) {

				return new Point(widthHint, heightHint);
			}

			@Override
			protected void layout(Composite composite, boolean flushCache) {
				GridData data = (GridData) composite.getLayoutData();
				composite.setBounds(0, 0, data.widthHint, data.heightHint);
			}
		};
	}

	/**
	 * Creates a new spinner.
	 *
	 * @param parent The parent container
	 * @param numberHolder The holder of the integer value
	 * @param defaultValue The value shown when the holder has <code>null</code>
	 * @return The newly created <code>Spinner</code>
	 *
	 * @category Layout
	 */
	protected final Spinner buildSpinner(Composite parent,
	                                     WritablePropertyValueModel<Integer> numberHolder,
	                                     int defaultValue) {

		return this.buildSpinner(
			parent,
			numberHolder,
			defaultValue,
			0,
			Integer.MAX_VALUE
		);
	}

	/**
	 * Creates a new spinner.
	 *
	 * @param parent The parent container
	 * @param numberHolder The holder of the integer value
	 * @param defaultValue The value shown when the holder has <code>null</code>
	 * @param minimumValue The minimum value that the spinner will allow
	 * @param maximumValue The maximum value that the spinner will allow
	 * @return The newly created <code>Spinner</code>
	 *
	 * @category Layout
	 */
	protected final Spinner buildSpinner(Composite parent,
	                                     WritablePropertyValueModel<Integer> numberHolder,
	                                     int defaultValue,
	                                     int minimumValue,
	                                     int maximumValue) {

		return this.buildSpinner(
			parent,
			numberHolder,
			defaultValue,
			minimumValue,
			maximumValue,
			null
		);
	}

	/**
	 * Creates a new spinner.
	 *
	 * @param parent The parent container
	 * @param numberHolder The holder of the integer value
	 * @param defaultValue The value shown when the holder has <code>null</code>
	 * @param minimumValue The minimum value that the spinner will allow
	 * @param maximumValue The maximum value that the spinner will allow
	 * @param helpId The topic help ID to be registered for the new button
	 * @return The newly created <code>Spinner</code>
	 *
	 * @category Layout
	 */
	protected final Spinner buildSpinner(Composite parent,
	                                     WritablePropertyValueModel<Integer> numberHolder,
	                                     int defaultValue,
	                                     int minimumValue,
	                                     int maximumValue,
	                                     String helpId) {

		Spinner spinner = this.widgetFactory.createSpinner(parent);
		spinner.setMinimum(minimumValue);
		spinner.setMaximum(maximumValue);
		spinner.setLayoutData(new GridData(GridData.BEGINNING));

		SpinnerModelAdapter.adapt(numberHolder, spinner, defaultValue);

		if (helpId != null) {
			helpSystem().setHelp(spinner, helpId);
		}

		return spinner;
	}

	private PropertyChangeListener buildSubjectChangeListener() {
		return new SWTPropertyChangeListenerWrapper(this.buildSubjectChangeListener_());
	}

	private PropertyChangeListener buildSubjectChangeListener_() {
		return new PropertyChangeListener() {
			@SuppressWarnings("unchecked")
			public void propertyChanged(PropertyChangeEvent e) {
				AbstractPane.this.subjectChanged((T) e.getOldValue(), (T) e.getNewValue());
			}
		};
	}

	/**
	 * Creates a new <code>Composite</code> used as a sub-pane.
	 *
	 * @param container The parent container
	 * @return The newly created <code>Composite</code> used as a sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildSubPane(Composite container) {
		return this.buildSubPane(container, 0);
	}

	/**
	 * Creates a new <code>Composite</code> used as a sub-pane.
	 *
	 * @param container The parent container
	 * @param topMargin The extra spacing to add at the top of the pane
	 * @return The newly created <code>Composite</code> used as a sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildSubPane(Composite container, int topMargin) {
		return this.buildSubPane(container, topMargin, 0);
	}

	/**
	 * Creates a new <code>Composite</code> used as a sub-pane.
	 *
	 * @param container The parent container
	 * @param topMargin The extra spacing to add at the top of the pane
	 * @param leftMargin The extra spacing to add to the left of the pane
	 * @return The newly created <code>Composite</code> used as a sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildSubPane(Composite container,
	                                       int topMargin,
	                                       int leftMargin) {

		return this.buildSubPane(container, topMargin, leftMargin, 0, 0);
	}

	/**
	 * Creates a new <code>Composite</code> used as a sub-pane, the new widget
	 * will have its layout and layout data already initialized, the layout will
	 * be a <code>GridLayout</code> with 1 column.
	 *
	 * @param container The parent container
	 * @param topMargin The extra spacing to add at the top of the pane
	 * @param leftMargin The extra spacing to add to the left of the pane
	 * @param bottomMargin The extra spacing to add at the bottom of the pane
	 * @param rightMargin The extra spacing to add to the right of the pane
	 * @return The newly created <code>Composite</code> used as a sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildSubPane(Composite container,
	                                       int topMargin,
	                                       int leftMargin,
	                                       int bottomMargin,
	                                       int rightMargin) {

		return this.buildSubPane(
			container,
			1,
			topMargin,
			leftMargin,
			bottomMargin,
			rightMargin);
	}

	/**
	 * Creates a new <code>Composite</code> used as a sub-pane, the new widget
	 * will have its layout and layout data already initialized, the layout will
	 * be a <code>GridLayout</code> with 1 column.
	 *
	 * @param container The parent container
	 * @param topMargin The extra spacing to add at the top of the pane
	 * @param leftMargin The extra spacing to add to the left of the pane
	 * @param bottomMargin The extra spacing to add at the bottom of the pane
	 * @param rightMargin The extra spacing to add to the right of the pane
	 * @return The newly created <code>Composite</code> used as a sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildSubPane(Composite container,
	                                       int columnCount,
	                                       int topMargin,
	                                       int leftMargin,
	                                       int bottomMargin,
	                                       int rightMargin) {

		GridLayout layout = new GridLayout(columnCount, false);
		layout.marginHeight = 0;
		layout.marginWidth  = 0;
		layout.marginTop    = topMargin;
		layout.marginLeft   = leftMargin;
		layout.marginBottom = bottomMargin;
		layout.marginRight  = rightMargin;

		container = this.buildPane(container, layout);

		return container;
	}

	/**
	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
	 * its client which can be typed cast directly as a <code>Composite</code>.
	 *
	 * @param container The container of the new widget
	 * @param sectionText The text of the new section
	 * @return The <code>Section</code>'s sub-pane
	 *
	 * @category Layout
	 */
	protected final Composite buildSubSection(Composite container,
	                                          String sectionText) {

		return this.buildCollapsableSubSection(
			container,
			sectionText,
			new SimplePropertyValueModel<Boolean>(Boolean.TRUE)
		);
	}

	/**
	 * Creates a new table.
	 *
	 * @param container The parent container
	 * @return The newly created <code>Table</code>
	 *
	 * @category Layout
	 */
	protected final Table buildTable(Composite container) {
		return this.buildTable(container, null);
	}

	/**
	 * Creates a new table.
	 *
	 * @param container The parent container
	 * @param style The style to apply to the table
	 * @return The newly created <code>Table</code>
	 *
	 * @category Layout
	 */
	protected final Table buildTable(Composite container, int style) {
		return this.buildTable(container, style, null);
	}

	/**
	 * Creates a new table.
	 *
	 * @param container The parent container
	 * @param style The style to apply to the table
	 * @param helpId The topic help ID to be registered for the new table or
	 * <code>null</code> if no help ID is required
	 * @return The newly created <code>Table</code>
	 *
	 * @category Layout
	 */
	protected final Table buildTable(Composite container,
	                                 int style,
	                                 String helpId) {

		Table table = this.widgetFactory.createTable(container, style);
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		GridData gridData   = new GridData(GridData.FILL_BOTH);
		gridData.heightHint = table.getItemHeight() * 4;
		table.setLayoutData(gridData);
		this.widgets.add(table);

		if (helpId != null) {
			helpSystem().setHelp(table, helpId);
		}

		return table;
	}

	/**
	 * Creates a new table.
	 *
	 * @param container The parent container
	 * @param helpId The topic help ID to be registered for the new table or
	 * <code>null</code> if no help ID is required
	 * @return The newly created <code>Table</code>
	 *
	 * @category Layout
	 */
	protected final Table buildTable(Composite container, String helpId) {

		return this.buildTable(
			container,
			SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI,
			helpId
		);
	}

	/**
	 * Creates a new <code>Text</code> widget.
	 *
	 * @param container The parent container
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildText(Composite container) {
		return this.widgetFactory.createText(container);
	}

	/**
	 * Creates a new <code>Text</code> widget.
	 *
	 * @param container The parent container
	 * @param helpId The topic help ID to be registered for the new text
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildText(Composite container, String helpId) {

		Text text = this.widgetFactory.createText(container);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		if (helpId != null) {
			helpSystem().setHelp(text, helpId);
		}

		return text;
	}

	/**
	 * Creates a new <code>Text</code> widget.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildText(Composite container,
	                               WritablePropertyValueModel<String> textHolder) {

		return this.buildText(container, textHolder, null);
	}

	/**
	 * Creates a new <code>Text</code> widget.
	 *
	 * @param container The parent container
	 * @param textHolder The holder of the text field's input
	 * @param helpId The topic help ID to be registered for the new text
	 * @return The newly created <code>Text</code> widget
	 *
	 * @category Layout
	 */
	protected final Text buildText(Composite container,
	                               WritablePropertyValueModel<String> textHolder,
	                               String helpId) {

		Text text = this.widgetFactory.createText(container);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		TextFieldModelAdapter.adapt(textHolder, text);

		if (helpId != null) {
			helpSystem().setHelp(text, helpId);
		}

		return text;
	}

	/**
	 * Creates a new container with a titled border.
	 *
	 * @param title The text of the titled border
	 * @param container The parent container
	 * @return The newly created <code>Composite</code> with a titled border
	 *
	 * @category Layout
	 */
	protected final Group buildTitledPane(Composite container, String title) {
		return this.buildTitledPane(container, title, null);
	}

	/**
	 * Creates a new container with a titled border.
	 *
	 * @param title The text of the titled border
	 * @param container The parent container
	 * @param helpId The topic help ID to be registered for the new group
	 * @return The newly created <code>Composite</code> with a titled border
	 *
	 * @category Layout
	 */
	protected final Group buildTitledPane(Composite container,
	                                      String title,
	                                      String helpId) {

		Group group = this.widgetFactory.createGroup(container, title);
		group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		GridLayout layout = new GridLayout(1, false);
		layout.marginHeight = 0;
		layout.marginWidth  = 0;
		layout.marginTop    = 5;
		layout.marginLeft   = 5;
		layout.marginBottom = 5;
		layout.marginRight  = 5;
		group.setLayout(layout);

		if (helpId != null) {
			helpSystem().setHelp(group, helpId);
		}

		return group;
	}

	/**
	 * Creates a new toggle button (radio button or check box) using the given
	 * information.
	 *
	 * @param parent The parent container
	 * @param buttonText The button's text
	 * @param booleanHolder The holder of the selection state
	 * @param helpId The topic help ID to be registered for the new button
	 * @return The newly created <code>Button</code>
	 *
	 * @category Layout
	 */
	private Button buildToggleButton(Composite parent,
	                                 String buttonText,
	                                 WritablePropertyValueModel<Boolean> booleanHolder,
	                                 String helpId,
	                                 int toggleButtonType) {

		Button button;

		if (toggleButtonType == SWT.PUSH) {
			button = this.widgetFactory.createPushButton(parent, buttonText);
		}
		else if (toggleButtonType == SWT.RADIO) {
			button = this.widgetFactory.createRadioButton(parent, buttonText);
		}
		else if (toggleButtonType == SWT.CHECK) {
			button = this.widgetFactory.createCheckBox(parent, buttonText);
		}
		else {
			button = this.widgetFactory.createButton(parent, buttonText);
		}

		button.setLayoutData(new GridData());
		BooleanButtonModelAdapter.adapt(booleanHolder, button);
		this.widgets.add(button);

		if (helpId != null) {
			helpSystem().setHelp(button, helpId);
		}

		return button;
	}

	/**
	 * Creates a new check box that can have 3 selection states (selected,
	 * unselected and partially selected.
	 *
	 * @param parent The parent container
	 * @param text The button's text
	 * @param booleanHolder The holder of the boolean value where <code>null</code>
	 * means partially selected
	 * @return The newly created <code>TriStateCheckBox</code>
	 *
	 * @category Layout
	 */
	protected final TriStateCheckBox buildTriStateCheckBox(Composite parent,
	                                                       String text,
	                                                       WritablePropertyValueModel<Boolean> booleanHolder) {

		return this.buildTriStateCheckBox(parent, text, booleanHolder, null);
	}

	/**
	 * Creates a new check box that can have 3 selection states (selected,
	 * unselected and partially selected.
	 *
	 * @param parent The parent container
	 * @param text The button's text
	 * @param booleanHolder The holder of the boolean value where <code>null</code>
	 * means partially selected
	 * @param helpId The topic help ID to be registered for the new check box
	 * @return The newly created <code>TriStateCheckBox</code>
	 *
	 * @category Layout
	 */
	protected final TriStateCheckBox buildTriStateCheckBox(Composite parent,
	                                                       String text,
	                                                       WritablePropertyValueModel<Boolean> booleanHolder,
	                                                       String helpId) {

		TriStateCheckBox checkBox = new TriStateCheckBox(
			parent,
			text,
			this.getWidgetFactory()
		);

		TriStateCheckBoxModelAdapter.adapt(
			booleanHolder,
			checkBox
		);

		this.widgets.add(checkBox.getCheckBox());

		if (helpId != null) {
			helpSystem().setHelp(checkBox.getCheckBox(), helpId);
		}

		return checkBox;
	}

	/**
	 * Creates a new check box that can have 3 selection states (selected,
	 * unselected and partially selected.
	 *
	 * @param parent The parent container
	 * @param text The button's text
	 * @param booleanHolder The holder of the boolean value where <code>null</code>
	 * means partially selected
	 * @param stringHolder The holder of the string to put in parenthesis after
	 * the check box's text when it is partially selected
	 * @return The newly created <code>TriStateCheckBox</code>
	 *
	 * @category Layout
	 */
	protected final TriStateCheckBox buildTriStateCheckBoxWithDefault(Composite parent,
	                                                                  String text,
	                                                                  WritablePropertyValueModel<Boolean> booleanHolder,
	                                                                  PropertyValueModel<String> stringHolder) {

		return this.buildTriStateCheckBoxWithDefault(
			parent,
			text,
			booleanHolder,
			stringHolder,
			null
		);
	}

	/**
	 * Creates a new check box that can have 3 selection states (selected,
	 * unselected and partially selected.
	 *
	 * @param parent The parent container
	 * @param text The button's text
	 * @param booleanHolder The holder of the boolean value where <code>null</code>
	 * means partially selected
	 * @param stringHolder The holder of the string to put in parenthesis after
	 * the check box's text when it is partially selected
	 * @param helpId The topic help ID to be registered for the new check box
	 * @return The newly created <code>TriStateCheckBox</code>
	 *
	 * @category Layout
	 */
	protected final TriStateCheckBox buildTriStateCheckBoxWithDefault(Composite parent,
	                                                                  String text,
	                                                                  WritablePropertyValueModel<Boolean> booleanHolder,
	                                                                  PropertyValueModel<String> stringHolder,
	                                                                  String helpId) {

		TriStateCheckBox checkBox = this.buildTriStateCheckBox(
			parent,
			text,
			booleanHolder,
			helpId
		);

		new LabeledControlUpdater(
			new LabeledButton(checkBox.getCheckBox()),
			stringHolder
		);

		return checkBox;
	}

	/**
	 * Uninstalls any listeners from the subject in order to stop being notified
	 * for changes made outside of this panes.
	 *
	 * @category Populate
	 */
	protected void disengageListeners() {

		this.log(Tracing.UI_LAYOUT, "   ->disengageListeners()");

		this.subjectHolder.removePropertyChangeListener(
			PropertyValueModel.VALUE,
			this.subjectChangeListener
		);

		this.disengageListeners(this.subject());

		for (AbstractPane<?> subPane : this.subPanes) {
			subPane.disengageListeners();
		}
	}

	/**
	 * Removes any property change listeners from the given subject.
	 *
	 * @param subject The old subject
	 *
	 * @category Populate
	 */
	protected void disengageListeners(T subject) {
		if (subject != null) {
//			this.log("   ->disengageListeners() from " + subject);

			for (String propertyName : this.propertyNames()) {
				subject.removePropertyChangeListener(propertyName, this.aspectChangeListener);
			}
		}
	}

	/**
	 * Notifies this pane is should dispose itself.
	 *
	 * @category Populate
	 */
	public final void dispose() {
		if (!this.container.isDisposed()) {
			this.log(Tracing.UI_LAYOUT, "dispose()");
			this.performDispose();
			this.disengageListeners();
		}
	}

	/**
	 * Requests this pane to dispose itself.
	 *
	 * @category Populate
	 */
	protected void doDispose() {
		this.log(Tracing.UI_LAYOUT, "   ->doDispose()");

		this.leftControlAligner.dispose();
		this.rightControlAligner.dispose();
	}

	/**
	 * Requests this pane to populate its widgets with the subject's values.
	 *
	 * @category Populate
	 */
	protected void doPopulate() {
		this.log(Tracing.UI_LAYOUT, "   ->doPopulate()");
	}

	/**
	 * Changes the enablement state of the children <code>Control</code>s.
	 *
	 * @param enabled <code>true</code> to enable the widgets or <code>false</code>
	 * to disable them
	 *
	 * @category Layout
	 */
	private void enableChildren(boolean enabled) {

		// Only update the enablement state of the child widgets if this pane
		// has its enablement managed by enableWidgets() (i.e. not done manually)
		if (this.isEnablementManaged(container)) {

			for (Control control : this.widgets) {

				// Make sure to check if the child control doesn't have its
				// enablement state manually managed
				if (this.isEnablementManaged(control)) {
					control.setEnabled(enabled);
				}
			}
		}
	}

	/**
	 * Changes the enablement state of the widgets of this pane.
	 *
	 * @param enabled <code>true</code> to enable the widgets or <code>false</code>
	 * to disable them
	 *
	 * @category Layout
	 */
	public void enableWidgets(boolean enabled) {

		if (!container.isDisposed()) {
			this.enableChildren(enabled);

			for (AbstractPane<?> subPane : this.subPanes) {
				if (this.isPaneEnablementManaged(subPane)) {
					subPane.enableWidgets(enabled);
				}
			}
		}
	}

	/**
	 * Installs the listeners on the subject in order to be notified from changes
	 * made outside of this panes and notifies the sub-panes to do the same.
	 *
	 * @category Populate
	 */
	protected void engageListeners() {

		this.log(Tracing.UI_LAYOUT, "   ->engageListeners()");

		this.engageSubjectHolder();
		this.engageListeners(this.subject());

		for (AbstractPane<?> subPane : this.subPanes) {
			subPane.engageListeners();
		}
	}

	/**
	 * TODO
	 *
	 * @param subject
	 *
	 * @category Populate
	 */
	protected void engageListeners(T subject) {
		if (subject != null) {

//			this.log("   ->engageListeners() on " + subject);

			for (String propertyName : this.propertyNames()) {
				subject.addPropertyChangeListener(propertyName, this.aspectChangeListener);
			}
		}
	}

	private void engageSubjectHolder() {
		this.subjectHolder.addPropertyChangeListener(
			PropertyValueModel.VALUE,
			this.subjectChangeListener
		);
	}

	/**
	 * Returns the main <code>Control</code> of this pane.
	 *
	 * @return The main container
	 *
	 * @category Layout
	 */
	public Composite getControl() {
		return this.container;
	}

	/**
	 * Returns the subject holder used by this pane.
	 *
	 * @return The holder of the subject
	 *
	 * @category Populate
	 */
	protected final PropertyValueModel<T> getSubjectHolder() {
		return this.subjectHolder;
	}

	/**
	 * Returns the factory responsible for creating the widgets.
	 *
	 * @return The factory used by this pane to create the widgets
	 *
	 * @category Layout
	 */
	protected final WidgetFactory getWidgetFactory() {
		return this.widgetFactory;
	}

	/**
	 * Returns the margin taken by a group box, which is the number of pixel the
	 * group box border and its margin takes before displaying its widgets plus
	 * 5 pixels since the widgets inside of the group box and the border should
	 * have that extra 5 pixels.
	 *
	 * @return The width taken by the group box border with its margin
	 *
	 * @category Layout
	 */
	protected final int groupBoxMargin() {
		Group group = this.widgetFactory.createGroup(SWTUtil.getShell(), "");
		Rectangle clientArea = group.getClientArea();
		group.dispose();
		return clientArea.x + 5;
	}

	/**
	 * Returns the helps system.
	 *
	 * @return The platform's help system
	 *
	 * @category Helper
	 */
	protected final IWorkbenchHelpSystem helpSystem() {
		return PlatformUI.getWorkbench().getHelpSystem();
	}

	/**
	 * Initializes this <code>AbstractSubjectPane</code>.
	 *
	 * @category Initialization
	 */
	protected void initialize() {
	}

	/**
	 * Registers this pane with the parent pane.
	 *
	 * @param parentPane The parent pane
	 * @param automaticallyAlignWidgets <code>true</code> to make the widgets
	 * this pane aligned with the widgets of the given parent pane;
	 * <code>false</code> to not align them
	 *
	 * @category Initialization
	 */
	private void initialize(AbstractPane<?> parentPane,
	                        boolean automaticallyAlignWidgets) {

		// Register this pane with the parent pane, it will call the methods
		// automatically (engageListeners(), disengageListeners(), populate(),
		// dispose(), etc)
		parentPane.registerSubPane(this);

		// Align the left and right controls with the controls from the parent
		// pane
		if (automaticallyAlignWidgets) {
			parentPane.leftControlAligner .add(this.leftControlAligner);
			parentPane.rightControlAligner.add(this.rightControlAligner);
		}
	}

	/**
	 * Initializes this <code>AbstractSubjectPane</code>.
	 *
	 * @param subjectHolder The holder of this pane's subject
	 * @param widgetFactory The factory used to create various widgets
	 *
	 * @category Initialization
	 */
	@SuppressWarnings("unchecked")
	private void initialize(PropertyValueModel<? extends T> subjectHolder,
	                        WidgetFactory widgetFactory)
	{
		Assert.isNotNull(subjectHolder, "The subject holder cannot be null");

		this.subjectHolder         = (PropertyValueModel<T>) subjectHolder;
		this.widgetFactory         = widgetFactory;
		this.subPanes              = new ArrayList<AbstractPane<?>>();
		this.widgets               = new ArrayList<Control>();
		this.leftControlAligner    = new ControlAligner();
		this.rightControlAligner   = new ControlAligner();
		this.subjectChangeListener = this.buildSubjectChangeListener();
		this.aspectChangeListener  = this.buildAspectChangeListener();
		this.internalPanesForEnablementControl = new ArrayList<AbstractPane<?>>();

		this.initialize();
	}

	/**
	 * Initializes the layout of this pane.
	 *
	 * @param container The parent container
	 *
	 * @category Layout
	 */
	protected abstract void initializeLayout(Composite container);

	/**
	 * Determines whether the enablement state is managed by this pane or is
	 * manually managed.
	 *
	 * @param control The <code>Control</code> to verify how its enablement state
	 * is managed
	 * @return <code>true</code> if the enablement state can be changed when
	 * {@link #enableWidgets(boolean)} is called; <code>false</code> if its
	 * enablement state is manually changed
	 */
	public final boolean isEnablementManaged(Control control) {
		return control.getData("enablement") != Boolean.FALSE;
	}

	/**
	 * Determines whether the given pane has its enablement state managed by this
	 * pane.
	 *
	 * @param subPane The sub-pane to verify how its enablement state is being
	 * managed
	 * @return <code>true</code> if the sub-pane's enablement state is managed by
	 * this state; <code>false</code> if it's manually managed
	 *
	 * @category Layout
	 */
	private boolean isPaneEnablementManaged(AbstractPane<?> subPane) {

		return // Test 1: This pane is being automatically managed and the
		       // sub-pane was registered has an internal pane, which means its
		       // enablement state is being managed automatically as well. A
		       // sub-pane is managed automatically only when PaneEnabler changes
		       // the enablement management checks
		       this.isEnablementManaged(container) &&
		       this.internalPanesForEnablementControl.contains(subPane) ||

		       // Test 2: Check to see if the pane is automatically managed
		       this.isEnablementManaged(subPane.getControl());
	}

	/**
	 * Determines whether
	 *
	 * @return
	 *
	 * @category Populate
	 */
	protected final boolean isPopulating() {
		return this.populating;
	}

	/**
	 * Logs the given message if the <code>Tracing.DEBUG_LAYOUT</code> is enabled.
	 *
	 * @param flag
	 * @param message The logging message
	 */
	protected void log(String flag, String message) {

		if (Tracing.UI_LAYOUT.equals(flag) &&
		    Tracing.booleanDebugOption(Tracing.UI_LAYOUT)) {

			Class<?> thisClass = getClass();
			String className = ClassTools.shortNameFor(thisClass);

			if (thisClass.isAnonymousClass()) {
				className = className.substring(0, className.indexOf('$'));
				className += "->" + ClassTools.shortNameFor(thisClass.getSuperclass());
			}

			Tracing.log(className + ": " + message);
		}
	}

	/**
	 * Notifies this pane is should dispose itself.
	 *
	 * @category Populate
	 */
	protected void performDispose() {
		this.log(Tracing.UI_LAYOUT, "   ->performDispose()");

		// Dispose this pane
		doDispose();

		// Ask the sub-panes to perform the dispose themselves
		for (AbstractPane<?> subPane : this.subPanes) {
			subPane.performDispose();
		}
	}

	/**
	 * Notifies this pane to populate itself using the subject's information.
	 *
	 * @category Populate
	 */
	public final void populate() {
		if (!this.container.isDisposed()) {
			this.log(Tracing.UI_LAYOUT, "populate()");
			this.engageListeners();
			this.repopulate();
		}
	}

	/**
	 * Notifies the subject's property associated with the given property name
	 * has changed.
	 *
	 * @param propertyName The property name associated with the property change
	 *
	 * @category Populate
	 */
	protected void propertyChanged(String propertyName) {
	}

	/**
	 * Returns the list of names to listen for properties changing from the
	 * subject.
	 *
	 * @return A non-<code>null</code> list of property names
	 *
	 * @category Populate
	 */
	protected Collection<String> propertyNames() {
		ArrayList<String> propertyNames = new ArrayList<String>();
		addPropertyNames(propertyNames);
		return propertyNames;
	}

	/**
	 * Registers another <code>AbstractSubjectPane</code> with this one so it can
	 * be automatically notified about certain events such as engaging or
	 * disengaging the listeners, etc.
	 *
	 * @param subPane The sub-pane to register
	 *
	 * @category Controller
	 */
	protected final void registerSubPane(AbstractPane<?> subPane) {
		this.subPanes.add(subPane);
	}

	/**
	 * Removes the given pane's widgets (those that were registered with
	 * its left <code>ControlAligner</code>) from this pane's left
	 * <code>ControlAligner</code> so that their width will no longer be adjusted
	 * with the width of the widest widget.
	 *
	 * @param pane The pane containing the widgets to remove
	 *
	 * @category Layout
	 */
	protected final void removeAlignLeft(AbstractPane<?> pane) {
		this.leftControlAligner.remove(pane.leftControlAligner);
	}

	/**
	 * Removes the given control from the collection of widgets that are aligned
	 * to have the same width when they are shown to the left side of the 3
	 * widget colums.
	 *
	 * @param pane The pane to remove, its width will no longer be
	 * ajusted to be the width of the longest widget
	 *
	 * @category Layout
	 */
	protected final void removeAlignLeft(Control control) {
		this.leftControlAligner.remove(control);
	}

	/**
	 * Removes the given pane's widgets (those that were registered with
	 * its right <code>ControlAligner</code>) from this pane's right
	 * <code>ControlAligner</code> so that their width will no longer be adjusted
	 * with the width of the widest widget.
	 *
	 * @param pane The pane containing the widgets to remove
	 *
	 * @category Layout
	 */
	protected final void removeAlignRight(AbstractPane<?> pane) {
		this.rightControlAligner.remove(pane.rightControlAligner);
	}

	/**
	 * Removes the given control from the collection of widgets that are aligned
	 * to have the same width when they are shown to the right side of the 3
	 * widget colums.
	 *
	 * @param pane The pane to remove, its width will no longer be
	 * ajusted to be the width of the longest widget
	 *
	 * @category Layout
	 */
	protected final void removeAlignRight(Control control) {
		this.rightControlAligner.remove(control);
	}

	/**
	 * Removes the given <code>AbstractPane</code>'s <code>Control</code> from
	 * having its enablement state managed by this pane. However, if this pane
	 * has its enablement state modified, the given pane will receive that
	 * notification.
	 *
	 * @param pane The pane to have its enablement state not managed by this pane
	 */
	public void removeFromEnablementControl(AbstractPane<?> pane) {
		this.removeFromEnablementControl(pane.getControl());
		this.internalPanesForEnablementControl.add(pane);
	}

	/**
	 * Removes the given <code>Control</code> from having its enablement state
	 * being managed by this pane.
	 *
	 * @param control The <code>Control</code> that has its enablement state
	 * manually controlled
	 */
	public void removeFromEnablementControl(Control control) {
		control.setData("enablement", Boolean.FALSE);
	}

	/**
	 * Removes the given pane's controls (those that were registered for
	 * alignment) from this pane.
	 *
	 * @param pane The pane containing the widgets that no longer
	 * requires their width adjusted with the width of the longest widget
	 *
	 * @category Layout
	 */
	protected final void removePaneForAlignment(AbstractPane<?> pane) {
		removeAlignLeft(pane);
		removeAlignRight(pane);
	}

	/**
	 * This method is called (perhaps internally) when this needs to repopulate
	 * but the object of interest has not changed.
	 *
	 * @category Populate
	 */
	protected final void repopulate() {

		this.log(Tracing.UI_LAYOUT, "   ->repopulate()");

		// Populate this pane
		try {
			setPopulating(true);
			doPopulate();
		}
		finally {
			setPopulating(false);
		}

		// Ask the sub-panes to repopulate themselves
		for (AbstractPane<?> subPane : this.subPanes) {
			subPane.repopulate();
		}
	}

	/**
	 * Determines whether this pane should be repopulate even if the subject if
	 * <code>null</code>.
	 *
	 * @return <code>true</code> is returned by default
	 * @category Populate
	 */
	protected boolean repopulateWithNullSubject() {
		return true;
	}

	/**
	 * Sets the internal flag that is used to determine whether the pane is being
	 * populated or not. During population, it is required to not update the
	 * widgets when the model is updated nor to update the model when the widgets
	 * are being synchronized with the model's values.
	 *
	 * @param populating
	 *
	 * @category Populate
	 */
	protected final void setPopulating(boolean populating) {
		this.populating = populating;
	}

	/**
	 * Either show or hides this pane.
	 *
	 * @param visible The new visibility state
	 */
	public void setVisible(boolean visible) {
		if (!this.container.isDisposed()) {
			this.container.setVisible(visible);
		}
	}

	/**
	 * Returns the nearest <code>Shell</code> displaying the main widget of this
	 * pane.
	 *
	 * @return The nearest window displaying this pane
	 */
	protected final Shell shell() {
		return this.container.getShell();
	}

	/**
	 * Returns the subject of this pane.
	 *
	 * @return The subject if this pane was not disposed; <code>null</code>
	 * if it was
	 *
	 * @category Populate
	 */
	protected T subject() {
		return this.subjectHolder.getValue();
	}

	/**
	 * The subject has changed, disconnects any listeners from the old subject
	 * and connects those listeners onto the new subject.
	 *
	 * @param oldsubject The old subject or <code>null</code> if none was set
	 * @param newSubject The new subject or <code>null</code> if none needs to be
	 * set
	 *
	 * @category Populate
	 */
	protected final void subjectChanged(T oldSubject, T newSubject) {
		if (!this.container.isDisposed()) {

			this.log(Tracing.UI_LAYOUT, "subjectChanged()");
			this.disengageListeners(oldSubject);

			// Only repopulate if it is allowed when the subject is null
			if (newSubject != null ||
			   (newSubject == null && repopulateWithNullSubject()))
			{
				this.repopulate();
			}

			this.engageListeners(newSubject);
		}
	}

	/**
	 * Unregisters the given <code>AbstractSubjectPane</code> from this one so it
	 * can no longer be automatically notified about certain events such as
	 * engaging or disengaging the listeners, etc.
	 *
	 * @param subPane The sub-pane to unregister
	 *
	 * @category Controller
	 */
	protected final void unregisterSubPane(AbstractPane<?> subPane) {
		this.subPanes.remove(subPane);
	}

	private void updatePane(String propertyName) {
		if (!isPopulating() && !container.isDisposed()) {
			populating = true;

			try {
				propertyChanged(propertyName);
			}
			finally {
				populating = false;
			}
		}
	}
}