Author: dgeraskov
Date: 2009-02-10 10:11:45 -0500 (Tue, 10 Feb 2009)
New Revision: 13560
Added:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AbstractPane.java
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemoveListPane.java
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemovePane.java
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitClassesComposite.java
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitGeneralComposite.java
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitMappingFilesComposite.java
Modified:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/META-INF/MANIFEST.MF
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/internal/persistence/details/HibernatePropertiesComposite.java
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/internal/platform/HibernateUiFactory.java
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/GenerateInitWizardPage.java
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/Messages.java
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/messages.properties
Log:
https://jira.jboss.org/jira/browse/JBIDE-3636
Dali 2.0 and 2.1 at once support.
Modified:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/META-INF/MANIFEST.MF
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/META-INF/MANIFEST.MF 2009-02-10
14:40:40 UTC (rev 13559)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/META-INF/MANIFEST.MF 2009-02-10
15:11:45 UTC (rev 13560)
@@ -1,12 +1,10 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
-Bundle-Name: %Bundle-Name.0
+Bundle-Name: Hibernate Jdt UI
Bundle-SymbolicName: org.jboss.tools.hibernate.jpt.ui;singleton:=true
Bundle-Version: 1.0.0
Bundle-Activator: org.jboss.tools.hibernate.jpt.ui.HibernateJptUIPlugin
Require-Bundle:
- org.eclipse.jpt.ui,
- org.eclipse.jpt.core;bundle-version="2.0.0",
org.hibernate.eclipse.console;bundle-version="3.2.0",
org.hibernate.eclipse;bundle-version="3.2.0",
org.eclipse.debug.core;bundle-version="3.4.0",
@@ -15,9 +13,12 @@
org.eclipse.datatools.connectivity;bundle-version="1.1.0",
org.eclipse.jdt.launching;bundle-version="3.4.0",
org.eclipse.wst.common.project.facet.ui;bundle-version="1.3.0",
- org.eclipse.jpt.utility;bundle-version="1.2.0",
org.eclipse.ui.forms;bundle-version="3.3.100",
- org.jboss.tools.hibernate.jpt.core;bundle-version="1.0.0"
+ org.jboss.tools.hibernate.jpt.core;bundle-version="1.0.0",
+ org.eclipse.ui.ide;bundle-version="3.4.0",
+ org.eclipse.jpt.core,
+ org.eclipse.jpt.ui,
+ org.eclipse.jpt.utility
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Vendor: %Bundle-Vendor.0
Modified:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/internal/persistence/details/HibernatePropertiesComposite.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/internal/persistence/details/HibernatePropertiesComposite.java 2009-02-10
14:40:40 UTC (rev 13559)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/internal/persistence/details/HibernatePropertiesComposite.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -19,7 +19,6 @@
import org.eclipse.jpt.ui.WidgetFactory;
import org.eclipse.jpt.ui.details.JpaPageComposite;
import org.eclipse.jpt.ui.internal.listeners.SWTPropertyChangeListenerWrapper;
-import org.eclipse.jpt.ui.internal.widgets.AbstractFormPane;
import org.eclipse.jpt.utility.internal.model.value.PropertyAspectAdapter;
import org.eclipse.jpt.utility.internal.model.value.SimpleListValueModel;
import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
@@ -35,13 +34,14 @@
import org.hibernate.eclipse.console.utils.DriverClassHelpers;
import org.hibernate.eclipse.launch.PathHelper;
import
org.jboss.tools.hibernate.jpt.core.internal.context.basic.BasicHibernateProperties;
+import org.jboss.tools.hibernate.jpt.ui.xpl.AbstractPane;
/**
* @author Dmitry Geraskov
*
*/
-public class HibernatePropertiesComposite extends
AbstractFormPane<BasicHibernateProperties> implements
- JpaPageComposite<PersistenceUnit> {
+public class HibernatePropertiesComposite extends
AbstractPane<BasicHibernateProperties> implements
+ JpaPageComposite {
private Text cfgFile;
Modified:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/internal/platform/HibernateUiFactory.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/internal/platform/HibernateUiFactory.java 2009-02-10
14:40:40 UTC (rev 13559)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/internal/platform/HibernateUiFactory.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -8,7 +8,6 @@
import org.eclipse.jpt.ui.details.JpaPageComposite;
import org.eclipse.jpt.ui.internal.GenericJpaUiFactory;
import
org.eclipse.jpt.ui.internal.persistence.details.PersistenceUnitConnectionComposite;
-import org.eclipse.jpt.ui.internal.persistence.details.PersistenceUnitGeneralComposite;
import
org.eclipse.jpt.ui.internal.persistence.details.PersistenceUnitPropertiesComposite;
import org.eclipse.jpt.utility.internal.model.value.TransformationPropertyValueModel;
import org.eclipse.jpt.utility.model.value.PropertyValueModel;
@@ -16,14 +15,16 @@
import org.jboss.tools.hibernate.jpt.core.internal.context.HibernatePersistenceUnit;
import
org.jboss.tools.hibernate.jpt.core.internal.context.basic.BasicHibernateProperties;
import
org.jboss.tools.hibernate.jpt.ui.internal.persistence.details.HibernatePropertiesComposite;
+import org.jboss.tools.hibernate.jpt.ui.xpl.PersistenceUnitGeneralComposite;
public class HibernateUiFactory extends GenericJpaUiFactory {
- public ListIterator<JpaPageComposite<PersistenceUnit>>
createPersistenceUnitComposites(
+ public ListIterator createPersistenceUnitComposites(
PropertyValueModel<PersistenceUnit> subjectHolder, Composite parent,
WidgetFactory widgetFactory) {
- ArrayList<JpaPageComposite<PersistenceUnit>> pages = new
ArrayList<JpaPageComposite<PersistenceUnit>>(1);
+ ArrayList<JpaPageComposite> pages = new ArrayList<JpaPageComposite>(1);
+ //replaced from Dali 2.0
pages.add(new PersistenceUnitGeneralComposite(subjectHolder, parent, widgetFactory));
pages.add(new PersistenceUnitConnectionComposite(subjectHolder, parent,
widgetFactory));
pages.add(new PersistenceUnitPropertiesComposite(subjectHolder, parent,
widgetFactory));
Modified:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/GenerateInitWizardPage.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/GenerateInitWizardPage.java 2009-02-10
14:40:40 UTC (rev 13559)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/GenerateInitWizardPage.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -166,11 +166,11 @@
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = numColumns;
dbGroup.setLayoutData(gd);
- dbGroup.setText(JptUiMessages.DatabaseReconnectWizardPage_database);
+ dbGroup.setText(Messages.databaseSettings);
//****************************connection profile*****************
connectionProfileName = new ComboDialogField(SWT.READ_ONLY);
- connectionProfileName.setLabelText(JptUiMessages.DatabaseReconnectWizardPage_connection);
+ connectionProfileName.setLabelText(Messages.databaseSettings_connection);
connectionProfileName.setItems(dtpConnectionProfileNames());
@@ -195,7 +195,7 @@
// TODO Auto-generated method stub
}});
- schemaName.setLabelText(JptUiMessages.DatabaseReconnectWizardPage_schema);
+ schemaName.setLabelText(Messages.databaseShema);
schemaName.setButtonLabel("Refresh");
Control[] controls = schemaName.doFillIntoGrid(dbGroup, numColumns);
// Hack to tell the text field to stretch!
Modified:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/Messages.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/Messages.java 2009-02-10
14:40:40 UTC (rev 13559)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/Messages.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -24,6 +24,9 @@
public static String title;
public static String selectName;
public static String wizardMessage;
+ public static String databaseSettings;
+ public static String databaseSettings_connection;
+ public static String databaseShema;
static {
// initialize resource bundle
Modified:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/messages.properties
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/messages.properties 2009-02-10
14:40:40 UTC (rev 13559)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/wizard/messages.properties 2009-02-10
15:11:45 UTC (rev 13560)
@@ -3,3 +3,6 @@
selectName=Create default Console Configuration
title=Use existing console configuration or connection profile for database connection
wizardMessage=Enter console configuration name if you want to create new one for selected
project.
+databaseSettings=Database Settings
+databaseSettings_connection=Database Connection
+databaseShema=Schema
\ No newline at end of file
Added:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AbstractPane.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AbstractPane.java
(rev 0)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AbstractPane.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -0,0 +1,4426 @@
+/*******************************************************************************
+ * 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
+ * Dmitry Geraskov, Exadel Inc. - Extracted from Dali 2.0 to protect from changes.
+ ******************************************************************************/
+package org.jboss.tools.hibernate.jpt.ui.xpl;
+
+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.ui.internal.widgets.TriStateCheckBox;
+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;
+ }
+ }
+ }
+}
\ No newline at end of file
Property changes on:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AbstractPane.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Author Id Revision Date
Name: svn:eol-style
+ native
Added:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemoveListPane.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemoveListPane.java
(rev 0)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemoveListPane.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -0,0 +1,548 @@
+/*******************************************************************************
+ * 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
+ * Dmitry Geraskov, Exadel Inc. - Extracted from Dali 2.0 to protect from changes.
+ ******************************************************************************/
+package org.jboss.tools.hibernate.jpt.ui.xpl;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jpt.ui.internal.listeners.SWTListChangeListenerWrapper;
+import org.eclipse.jpt.ui.internal.listeners.SWTPropertyChangeListenerWrapper;
+import org.eclipse.jpt.ui.internal.swt.ColumnAdapter;
+import org.eclipse.jpt.ui.internal.swt.TableModelAdapter;
+import org.eclipse.jpt.ui.internal.swt.TableModelAdapter.SelectionChangeEvent;
+import org.eclipse.jpt.ui.internal.swt.TableModelAdapter.SelectionChangeListener;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.jpt.utility.internal.model.value.SimplePropertyValueModel;
+import org.eclipse.jpt.utility.internal.model.value.swing.ObjectListSelectionModel;
+import org.eclipse.jpt.utility.model.Model;
+import org.eclipse.jpt.utility.model.event.ListChangeEvent;
+import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
+import org.eclipse.jpt.utility.model.listener.ListChangeListener;
+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.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * This implementation of the <code>AddRemovePane</code> uses a
<code>Table</code>
+ * as its main widget, a <code>List</code> can't be used because it
doesn't
+ * support showing images. However, the table is displayed like a list.
+ * <p>
+ * Here the layot of this pane:
+ * <pre>
+ * -----------------------------------------------------------------------------
+ * | ------------------------------------------------------------- ----------- |
+ * | | Item 1 | | Add... | |
+ * | | ... | ----------- |
+ * | | Item n | ----------- |
+ * | | | | Edit... | |
+ * | | | ----------- |
+ * | | | ----------- |
+ * | | | | Remove | |
+ * | | | ----------- |
+ * | ------------------------------------------------------------- |
+ *
-----------------------------------------------------------------------------</pre>
+ *
+ * @version 2.0
+ * @since 1.0
+ */
+@SuppressWarnings("nls")
+public class AddRemoveListPane<T extends Model> extends AddRemovePane<T>
+{
+ /**
+ * Flag used to prevent circular
+ */
+ private boolean locked;
+
+ /**
+ * The main widget of this add/remove pane.
+ */
+ private Table table;
+
+ /**
+ * Creates a new <code>AddRemoveListPane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param parent The parent container
+ * @param adapter
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the table holder's items
+ */
+ public AddRemoveListPane(AbstractPane<? extends T> parentPane,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ ILabelProvider labelProvider) {
+
+ super(parentPane,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider);
+ }
+
+ /**
+ * Creates a new <code>AddRemoveListPane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param parent The parent container
+ * @param adapter
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the table holder's items
+ * @param helpId The topic help ID to be registered with this pane
+ */
+ public AddRemoveListPane(AbstractPane<? extends T> parentPane,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ ILabelProvider labelProvider,
+ String helpId) {
+
+ super(parentPane,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ helpId);
+ }
+
+ /**
+ * Creates a new <code>AddRemoveListPane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param subjectHolder The holder of the subject
+ * @param adapter
+ * @param parent The parent container
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the table holder's items
+ */
+ public AddRemoveListPane(AbstractPane<?> parentPane,
+ PropertyValueModel<? extends T> subjectHolder,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ ILabelProvider labelProvider) {
+
+ super(parentPane,
+ subjectHolder,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider);
+ }
+
+ /**
+ * Creates a new <code>AddRemoveListPane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param subjectHolder The holder of the subject
+ * @param adapter
+ * @param parent The parent container
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the table holder's items
+ * @param helpId The topic help ID to be registered with this pane
+ */
+ public AddRemoveListPane(AbstractPane<?> parentPane,
+ PropertyValueModel<? extends T> subjectHolder,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ ILabelProvider labelProvider,
+ String helpId) {
+
+ super(parentPane,
+ subjectHolder,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ helpId);
+ }
+
+ private ColumnAdapter<Object> buildColumnAdapter() {
+ return new ColumnAdapter<Object>() {
+ public WritablePropertyValueModel<?>[] cellModels(Object subject) {
+ WritablePropertyValueModel<?>[] valueHolders = new
WritablePropertyValueModel<?>[1];
+ valueHolders[0] = new SimplePropertyValueModel<Object>(subject);
+ return valueHolders;
+ }
+
+ public int columnCount() {
+ return 1;
+ }
+
+ public String columnName(int columnIndex) {
+ return "";
+ }
+ };
+ }
+
+ private ListChangeListener buildListChangeListener() {
+ return new SWTListChangeListenerWrapper(buildListChangeListener_());
+ }
+
+ private ListChangeListener buildListChangeListener_() {
+ return new ListChangeListener() {
+ public void itemsAdded(ListChangeEvent e) {
+ if (!table.isDisposed()) {
+ table.getParent().layout();
+ }
+ }
+
+ public void itemsMoved(ListChangeEvent e) {
+ if (!table.isDisposed()) {
+ table.getParent().layout();
+ }
+ }
+
+ public void itemsRemoved(ListChangeEvent e) {
+ if (!table.isDisposed()) {
+ table.getParent().layout();
+ }
+ }
+
+ public void itemsReplaced(ListChangeEvent e) {
+ if (!table.isDisposed()) {
+ table.getParent().layout();
+ }
+ }
+
+ public void listChanged(ListChangeEvent e) {
+ if (!table.isDisposed()) {
+ table.getParent().layout();
+ }
+ }
+
+ public void listCleared(ListChangeEvent e) {
+ if (!table.isDisposed()) {
+ table.getParent().layout();
+ }
+ }
+ };
+ }
+
+ private SimplePropertyValueModel<Object> buildSelectedItemHolder() {
+ return new SimplePropertyValueModel<Object>();
+ }
+
+ private PropertyChangeListener buildSelectedItemPropertyChangeListener() {
+ return new SWTPropertyChangeListenerWrapper(
+ buildSelectedItemPropertyChangeListener_()
+ );
+ }
+
+ private PropertyChangeListener buildSelectedItemPropertyChangeListener_() {
+ return new PropertyChangeListener() {
+ public void propertyChanged(PropertyChangeEvent e) {
+ if (table.isDisposed()) {
+ return;
+ }
+
+ if (!locked) {
+ locked = true;
+
+ try {
+ Object value = e.getNewValue();
+ getSelectionModel().setSelectedValue(e.getNewValue());
+ int index = -1;
+
+ if (value != null) {
+ index = CollectionTools.indexOf(getListHolder().iterator(), value);
+ }
+
+ table.select(index);
+ updateButtons();
+ }
+ finally {
+ locked = false;
+ }
+ }
+ }
+ };
+ }
+
+ private SelectionChangeListener<Object> buildSelectionListener() {
+ return new SelectionChangeListener<Object>() {
+ public void selectionChanged(SelectionChangeEvent<Object> e) {
+ AddRemoveListPane.this.selectionChanged();
+ }
+ };
+ }
+
+ private Composite buildTableContainer(Composite container) {
+
+ container = buildPane(container, buildTableContainerLayout());
+ container.setLayoutData(new GridData(GridData.FILL_BOTH));
+ return container;
+ }
+
+ private Layout buildTableContainerLayout() {
+ return new Layout() {
+ @Override
+ protected Point computeSize(Composite composite,
+ int widthHint,
+ int heightHint,
+ boolean flushCache) {
+
+ Table table = (Table) composite.getChildren()[0];
+ packColumn(table);
+
+ // Calculate the table size and adjust it with the hints
+ Point size = table.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+
+ if (widthHint != SWT.DEFAULT) {
+ size.x = widthHint;
+ }
+
+ if (heightHint != SWT.DEFAULT) {
+ size.y = heightHint;
+ }
+
+ return size;
+ }
+
+ private boolean isVerticalScrollbarBarVisible(Table table,
+ Rectangle clientArea) {
+
+ // Get the height of all the rows
+ int height = table.getItemCount() * table.getItemHeight();
+
+ // Remove the border from the height
+ height += (table.getBorderWidth() * 2);
+
+ return (clientArea.height < height);
+ }
+
+ @Override
+ protected void layout(Composite composite, boolean flushCache) {
+
+ Rectangle bounds = composite.getClientArea();
+
+ if (bounds.width > 0) {
+
+ Table table = (Table) composite.getChildren()[0];
+ table.setBounds(0, 0, bounds.width, bounds.height);
+
+ updateTableColumnWidth(
+ table,
+ bounds.width,
+ isVerticalScrollbarBarVisible(table, bounds)
+ );
+ }
+ }
+
+ private void packColumn(Table table) {
+
+ TableColumn tableColumn = table.getColumn(0);
+
+ table.setRedraw(false);
+ table.setLayoutDeferred(true);
+ tableColumn.pack();
+ table.setLayoutDeferred(false);
+ table.setRedraw(true);
+
+ // Cache the column width so it can be used in
+ // updateTableColumnWidth() when determine which width to use
+ table.setData(
+ "column.width",
+ Integer.valueOf(tableColumn.getWidth())
+ );
+ }
+
+ private void updateTableColumnWidth(Table table,
+ int width,
+ boolean verticalScrollbarBarVisible) {
+
+ // Remove the border from the width
+ width -= (table.getBorderWidth() * 2);
+
+ // Remove the scrollbar from the width if it is shown
+ if (verticalScrollbarBarVisible) {
+ width -= table.getVerticalBar().getSize().x;
+ }
+
+ TableColumn tableColumn = table.getColumn(0);
+
+ // Retrieve the cached column width, which is required for
+ // determining which width to use (the column width or the
+ // calculated width)
+ Integer columnWitdh = (Integer) table.getData("column.width");
+
+ // Use the calculated width if the column is smaller, otherwise
+ // use the column width and a horizontal scroll bar will show up
+ width = Math.max(width, columnWitdh);
+
+ // Adjust the column width
+ tableColumn.setWidth(width);
+ }
+ };
+ }
+
+ private ITableLabelProvider buiTableLabelProvider(IBaseLabelProvider labelProvider) {
+ return new TableLabelProvider((ILabelProvider) labelProvider);
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ public Table getMainControl() {
+ return table;
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void initializeMainComposite(Composite container,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?>
selectedItemHolder,
+ IBaseLabelProvider labelProvider,
+ String helpId) {
+
+ table = buildTable(
+ buildTableContainer(container),
+ SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI,
+ helpId
+ );
+
+ removeFromEnablementControl(table);
+
+ TableModelAdapter model = TableModelAdapter.adapt(
+ (ListValueModel<Object>) listHolder,
+ buildSelectedItemHolder(),
+ table,
+ buildColumnAdapter(),
+ buiTableLabelProvider(labelProvider)
+ );
+
+ model.addSelectionChangeListener(buildSelectionListener());
+
+ selectedItemHolder.addPropertyChangeListener(
+ PropertyValueModel.VALUE,
+ buildSelectedItemPropertyChangeListener()
+ );
+
+ listHolder.addListChangeListener(
+ ListValueModel.LIST_VALUES,
+ buildListChangeListener()
+ );
+
+ initializeTable(table);
+ }
+
+ /**
+ * Initializes the given table, which acts like a list in our case.
+ *
+ * @param table The main widget of this pane
+ */
+ protected void initializeTable(Table table) {
+
+ table.setData("column.width", new Integer(0));
+ table.setHeaderVisible(false);
+ table.setLinesVisible(false);
+ }
+
+ /**
+ * The selection has changed, update (1) the selected item holder, (2) the
+ * selection model and (3) the buttons.
+ */
+ private void selectionChanged() {
+
+ if (locked) {
+ return;
+ }
+
+ locked = true;
+
+ try {
+ WritablePropertyValueModel<Object> selectedItemHolder =
getSelectedItemHolder();
+ ObjectListSelectionModel selectionModel = getSelectionModel();
+ int selectionCount = table.getSelectionCount();
+
+ if (selectionCount == 0) {
+ selectedItemHolder.setValue(null);
+ selectionModel.clearSelection();
+ }
+ else if (selectionCount != 1) {
+ selectedItemHolder.setValue(null);
+ selectionModel.clearSelection();
+
+ for (int index : table.getSelectionIndices()) {
+ selectionModel.addSelectionInterval(index, index);
+ }
+ }
+ else {
+ int selectedIndex = table.getSelectionIndex();
+ Object selectedItem = getListHolder().get(selectedIndex);
+
+ selectedItemHolder.setValue(selectedItem);
+ selectionModel.setSelectedValue(selectedItem);
+ }
+
+ updateButtons();
+ }
+ finally {
+ locked = false;
+ }
+ }
+
+ /**
+ * This label provider simply delegates the rendering to the provided
+ * <code>ILabelProvider</code>.
+ */
+ private class TableLabelProvider extends LabelProvider
+ implements ITableLabelProvider {
+
+ private ILabelProvider labelProvider;
+
+ TableLabelProvider(ILabelProvider labelProvider) {
+ super();
+ this.labelProvider = labelProvider;
+ }
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ return labelProvider.getImage(element);
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ return labelProvider.getText(element);
+ }
+ }
+}
\ No newline at end of file
Property changes on:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemoveListPane.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Author Id Revision Date
Name: svn:eol-style
+ native
Added:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemovePane.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemovePane.java
(rev 0)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemovePane.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -0,0 +1,862 @@
+/*******************************************************************************
+ * 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
+ * Dmitry Geraskov, Exadel Inc. - Extracted from Dali 2.0 to protect from changes.
+ ******************************************************************************/
+package org.jboss.tools.hibernate.jpt.ui.xpl;
+
+import java.util.Arrays;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jpt.ui.internal.JptUiMessages;
+import org.eclipse.jpt.ui.internal.listeners.SWTListChangeListenerWrapper;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.jpt.utility.internal.model.value.swing.ListModelAdapter;
+import org.eclipse.jpt.utility.internal.model.value.swing.ObjectListSelectionModel;
+import org.eclipse.jpt.utility.model.Model;
+import org.eclipse.jpt.utility.model.event.ListChangeEvent;
+import org.eclipse.jpt.utility.model.listener.ListChangeListener;
+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.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * The abstract definition of a pane that has buttons for adding, removing and
+ * possibly editing the items.
+ *
+ * @see AddRemoveListPane
+ *
+ * @version 1.0
+ * @since 2.0
+ */
+public abstract class AddRemovePane<T extends Model> extends AbstractPane<T>
+{
+ private Adapter adapter;
+ private Button addButton;
+ private Composite container;
+ private boolean enabled;
+ private IBaseLabelProvider labelProvider;
+ private ListValueModel<?> listHolder;
+ private Button optionalButton;
+ private Button removeButton;
+ private WritablePropertyValueModel<Object> selectedItemHolder;
+ private ObjectListSelectionModel selectionModel;
+
+ /**
+ * Creates a new <code>AddRemovePane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param parent The parent container
+ * @param adapter This <code>Adapter</code> is used to dictacte the
behavior
+ * of this <code>AddRemovePane</code> and by delegating to it some of the
+ * behavior
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the list holder's items
+ */
+ protected AddRemovePane(AbstractPane<? extends T> parentPane,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ IBaseLabelProvider labelProvider) {
+
+ this(parentPane,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ null);
+ }
+
+ /**
+ * Creates a new <code>AddRemovePane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param parent The parent container
+ * @param adapter This <code>Adapter</code> is used to dictacte the
behavior
+ * of this <code>AddRemovePane</code> and by delegating to it some of the
+ * behavior
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the list holder's items
+ * @param helpId The topic help ID to be registered with this pane
+ */
+ protected AddRemovePane(AbstractPane<? extends T> parentPane,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ IBaseLabelProvider labelProvider,
+ String helpId) {
+
+ super(parentPane, parent);
+
+ initialize(
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider
+ );
+
+ initializeLayout(
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ helpId
+ );
+ }
+
+ /**
+ * Creates a new <code>AddRemovePane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param subjectHolder The holder of the subject
+ * @param adapter This <code>Adapter</code> is used to dictacte the
behavior
+ * of this <code>AddRemovePane</code> and by delegating to it some of the
+ * behavior
+ * @param parent The parent container
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the list holder's items
+ */
+ protected AddRemovePane(AbstractPane<?> parentPane,
+ PropertyValueModel<? extends T> subjectHolder,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ IBaseLabelProvider labelProvider) {
+
+ this(parentPane,
+ subjectHolder,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ null);
+ }
+
+ /**
+ * Creates a new <code>AddRemovePane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param subjectHolder The holder of the subject
+ * @param adapter This <code>Adapter</code> is used to dictacte the
behavior
+ * of this <code>AddRemovePane</code> and by delegating to it some of the
+ * behavior
+ * @param parent The parent container
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the list holder's items
+ * @param helpId The topic help ID to be registered with this pane
+ */
+ protected AddRemovePane(AbstractPane<?> parentPane,
+ PropertyValueModel<? extends T> subjectHolder,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ IBaseLabelProvider labelProvider,
+ String helpId) {
+
+ super(parentPane, subjectHolder, parent);
+
+ initialize(
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider
+ );
+
+ initializeLayout(
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ helpId
+ );
+ }
+
+ /**
+ * Gives the possibility to add buttons after the Add button and before the
+ * optional button.
+ *
+ * @param container The parent container
+ * @param helpId The topic help ID to be registered with the buttons
+ *
+ * @category Layout
+ */
+ protected void addCustomButtonAfterAddButton(Composite container,
+ String helpId) {
+ }
+
+ /**
+ * Gives the possibility to add buttons after the optional button and before
+ * the Remove button.
+ *
+ * @param container The parent container
+ * @param helpId The topic help ID to be registered with the buttons
+ *
+ * @category Layout
+ */
+ protected void addCustomButtonAfterOptionalButton(Composite container,
+ String helpId) {
+ }
+
+ /**
+ * @category Add
+ */
+ protected void addItem() {
+ adapter.addNewItem(selectionModel);
+ }
+
+ /**
+ * @category Initialize
+ */
+ protected Adapter buildAdapter() {
+ return adapter;
+ }
+
+ /**
+ * @category Add
+ */
+ protected Button buildAddButton(Composite parent) {
+ return buildButton(
+ parent,
+ adapter.addButtonText(),
+ buildAddItemAction()
+ );
+ }
+
+ /**
+ * @category Add
+ */
+ private Runnable buildAddItemAction() {
+ return new Runnable() {
+ public void run() {
+ AddRemovePane.this.addItem();
+ }
+ };
+ }
+
+ private ListChangeListener buildListChangeListener() {
+ return new SWTListChangeListenerWrapper(buildListChangeListener_());
+ }
+
+ private ListChangeListener buildListChangeListener_() {
+ return new ListChangeListener() {
+
+ public void itemsAdded(ListChangeEvent e) {
+ }
+
+ public void itemsMoved(ListChangeEvent e) {
+ }
+
+ public void itemsRemoved(ListChangeEvent e) {
+ Object selectedItem = selectedItemHolder.getValue();
+
+ if (selectedItem == null) {
+ updateButtons();
+ return;
+ }
+
+ if (CollectionTools.contains(e.items(), selectedItem)) {
+ selectedItemHolder.setValue(null);
+ updateButtons();
+ }
+ }
+
+ public void itemsReplaced(ListChangeEvent e) {
+ }
+
+ public void listChanged(ListChangeEvent e) {
+ }
+
+ public void listCleared(ListChangeEvent e) {
+ selectedItemHolder.setValue(null);
+ updateButtons();
+ }
+ };
+ }
+
+ /**
+ * @category Option
+ */
+ private Runnable buildOptionalAction() {
+ return new Runnable() {
+ public void run() {
+ AddRemovePane.this.editItem();
+ }
+ };
+ }
+
+ /**
+ * @category Option
+ */
+ protected Button buildOptionalButton(Composite container) {
+ return buildButton(
+ container,
+ adapter.optionalButtonText(),
+ buildOptionalAction()
+ );
+ }
+
+ /**
+ * @category Add
+ */
+ protected Button buildRemoveButton(Composite parent) {
+ return buildButton(
+ parent,
+ adapter.removeButtonText(),
+ buildRemoveItemsAction()
+ );
+ }
+
+ /**
+ * @category Remove
+ */
+ private Runnable buildRemoveItemsAction() {
+ return new Runnable() {
+ public void run() {
+ AddRemovePane.this.removeItems();
+ }
+ };
+ }
+
+ protected ObjectListSelectionModel buildRowSelectionModel(ListValueModel<?>
listModel) {
+ return new ObjectListSelectionModel(new ListModelAdapter(listModel));
+ }
+
+ /**
+ * @category Option
+ */
+ protected void editItem() {
+ this.adapter.optionOnSelection(getSelectionModel());
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ public void enableWidgets(boolean enabled) {
+
+ super.enableWidgets(enabled);
+ this.enabled = enabled;
+
+ if (!this.getMainControl().isDisposed()) {
+ this.getMainControl().setEnabled(enabled);
+ }
+
+ this.updateButtons();
+ }
+
+ protected final Composite getContainer() {
+ return container;
+ }
+
+ protected IBaseLabelProvider getLabelProvider() {
+ return labelProvider;
+ }
+
+ protected final ListValueModel<?> getListHolder() {
+ return listHolder;
+ }
+
+ /**
+ * Returns
+ *
+ * @return
+ */
+ public abstract Composite getMainControl();
+
+ protected final WritablePropertyValueModel<Object> getSelectedItemHolder() {
+ return selectedItemHolder;
+ }
+
+ public final ObjectListSelectionModel getSelectionModel() {
+ return selectionModel;
+ }
+
+ /**
+ * Initializes this add/remove pane.
+ *
+ * @param adapter This <code>Adapter</code> is used to dictacte the
behavior
+ * of this <code>AddRemovePane</code> and by delegating to it some of the
+ * behavior
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the list holder's items
+ *
+ * @category Initialization
+ */
+ @SuppressWarnings("unchecked")
+ protected void initialize(Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ IBaseLabelProvider labelProvider)
+ {
+ this.listHolder = listHolder;
+ this.labelProvider = labelProvider;
+ this.adapter = (adapter == null) ? buildAdapter() : adapter;
+ this.selectedItemHolder = (WritablePropertyValueModel<Object>)
selectedItemHolder;
+ this.selectionModel = new ObjectListSelectionModel(new
ListModelAdapter(listHolder));
+
+ this.listHolder.addListChangeListener(
+ ListValueModel.LIST_VALUES,
+ buildListChangeListener()
+ );
+ }
+
+ /**
+ * Initializes the pane containing the buttons (Add, optional (if required)
+ * and Remove).
+ *
+ * @param container The parent container
+ * @param helpId The topic help ID to be registered with the buttons
+ *
+ * @category Layout
+ */
+ protected void initializeButtonPane(Composite container, String helpId) {
+
+ container = buildSubPane(container);
+
+ GridData gridData = new GridData();
+ gridData.grabExcessVerticalSpace = true;
+ gridData.verticalAlignment = SWT.TOP;
+ container.setLayoutData(gridData);
+
+ // Add button
+ addButton = buildAddButton(container);
+ addAlignRight(addButton);
+ removeFromEnablementControl(addButton);
+
+ // Custom button
+ addCustomButtonAfterAddButton(container, helpId);
+
+ // Optional button
+ if (adapter.hasOptionalButton()) {
+ optionalButton = buildOptionalButton(container);
+ removeFromEnablementControl(optionalButton);
+ addAlignRight(optionalButton);
+ }
+
+ // Custom button
+ addCustomButtonAfterOptionalButton(container, helpId);
+
+ // Remove button
+ removeButton = buildRemoveButton(container);
+ removeFromEnablementControl(removeButton);
+ addAlignRight(removeButton);
+
+ // Update the help topic ID
+ if (helpId != null) {
+ helpSystem().setHelp(addButton, helpId);
+ helpSystem().setHelp(removeButton, helpId);
+
+ if (optionalButton != null) {
+ helpSystem().setHelp(optionalButton, helpId);
+ }
+ }
+ }
+
+ /**
+ * Initializes this add/remove pane by creating the widgets. The subclass is
+ * required to build the main widget.
+ *
+ * @param adapter This <code>Adapter</code> is used to dictacte the
behavior
+ * of this <code>AddRemovePane</code> and by delegating to it some of the
+ * behavior
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the list holder's items
+ * @param helpId The topic help ID to be registered with this pane
+ *
+ * @category Layout
+ */
+ protected void initializeLayout(Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ IBaseLabelProvider labelProvider,
+ String helpId) {
+
+ initializeMainComposite(
+ container,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ helpId);
+
+ initializeButtonPane(container, helpId);
+ enableWidgets(subject() != null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void initializeLayout(Composite container) {
+ this.container = buildSubPane(container, 2, 0, 0, 0, 0);
+ }
+
+ /**
+ * Initializes the main widget of this add/remove pane.
+ *
+ * @param container The parent container
+ * @param adapter This <code>Adapter</code> is used to dictacte the
behavior
+ * of this <code>AddRemovePane</code> and by delegating to it some of the
+ * behavior
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the list holder's items
+ * @param helpId The topic help ID to be registered with this pane or
+ * <code>null</code> if it was not specified
+ *
+ * @category Layout
+ */
+ protected abstract void initializeMainComposite(Composite container,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?>
selectedItemHolder,
+ IBaseLabelProvider labelProvider,
+ String helpId);
+
+ /**
+ * @category Remove
+ */
+ protected void removeItems() {
+
+ // Keep track of the selected indices so we can select an item
+ // before the lowest index
+ int[] indices = selectionModel.selectedIndices();
+ Arrays.sort(indices);
+
+ // Notify the adapter to remove the selected items
+ adapter.removeSelectedItems(selectionModel);
+
+ // Select a new item
+ if (getListHolder().size() > 0) {
+ int index = Math.min(indices[0], getListHolder().size() - 1);
+ Object item = getListHolder().get(index);
+ selectedItemHolder.setValue(item);
+ }
+ // The list is empty, clear the value
+ else {
+ selectedItemHolder.setValue(null);
+ }
+ }
+
+ /**
+ * Selects the given value, which can be <code>null</code>.
+ *
+ * @param value The new selected value
+ */
+ public void setSelectedItem(Object value) {
+ selectedItemHolder.setValue(value);
+ }
+
+ /**
+ * @category UpdateButtons
+ */
+ protected void updateAddButton(Button addButton) {
+ addButton.setEnabled(
+ enabled &&
+ subject() != null
+ );
+ }
+
+ /**
+ * @category UpdateButtons
+ */
+ protected void updateButtons() {
+ if (!container.isDisposed()) {
+ updateAddButton(addButton);
+ updateRemoveButton(removeButton);
+ updateOptionalButton(optionalButton);
+ }
+ }
+
+ /**
+ * @category UpdateButtons
+ */
+ protected void updateOptionalButton(Button optionalButton) {
+ if (optionalButton != null) {
+ optionalButton.setEnabled(
+ enabled &&
+ adapter.enableOptionOnSelectionChange(selectionModel)
+ );
+ }
+ }
+
+ /**
+ * @category UpdateButtons
+ */
+ protected void updateRemoveButton(Button removeButton) {
+ removeButton.setEnabled(
+ enabled &&
+ adapter.enableRemoveOnSelectionChange(selectionModel)
+ );
+ }
+
+ /**
+ * An abstract implementation of <code>Adapter</code>.
+ */
+ public static abstract class AbstractAdapter implements Adapter {
+
+ /**
+ * The text of the add button.
+ */
+ private String addButtonText;
+
+ /**
+ * Determines whether the optional button should be shown or not.
+ */
+ private boolean hasOptionalButton;
+
+ /**
+ * The text of the optional button, if used.
+ */
+ private String optionalButtonText;
+
+ /**
+ * The text of the remove button.
+ */
+ private String removeButtonText;
+
+ /**
+ * Creates a new <code>AbstractAdapter</code> with default text for the
+ * add and remove buttons.
+ */
+ public AbstractAdapter() {
+ this(JptUiMessages.AddRemovePane_AddButtonText,
+ JptUiMessages.AddRemovePane_RemoveButtonText);
+ }
+
+ /**
+ * Creates a new <code>AbstractAdapter</code> with default text for the
+ * add and remove buttons.
+ *
+ * @param hasOptionalButton <code>true</code> to show an optional button
+ * and to use the behavior related to the optional button;
+ * <code>false</code> to not use it
+ */
+ public AbstractAdapter(boolean hasOptionalButton) {
+ this();
+ this.setHasOptionalButton(hasOptionalButton);
+ }
+
+ /**
+ * Creates a new <code>AbstractAdapter</code> with default text for the
+ * add and remove buttons.
+ *
+ * @param optionalButtonText The text of the optional button, which means
+ * the optional button will be shown
+ */
+ public AbstractAdapter(String optionalButtonText) {
+ this(true);
+ this.setOptionalButtonText(optionalButtonText);
+ }
+
+ /**
+ * Creates a new <code>AbstractAdapter</code>.
+ *
+ * @param addButtonText The add button's text
+ * @param removeButtonText The remove button's text
+ */
+ public AbstractAdapter(String addButtonText,
+ String removeButtonText) {
+
+ super();
+ this.addButtonText = addButtonText;
+ this.removeButtonText = removeButtonText;
+ }
+
+ /**
+ * Creates a new <code>AbstractAdapter</code>.
+ *
+ * @param addButtonText The add button's text
+ * @param removeButtonText The remove button's text
+ * @param optionalButtonText The text of the optional button, which means
+ * the optional button will be shown
+ */
+ public AbstractAdapter(String addButtonText,
+ String removeButtonText,
+ String optionalButtonText) {
+
+ this(optionalButtonText);
+ this.setAddButtonText(addButtonText);
+ this.setRemoveButtonText(removeButtonText);
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ public String addButtonText() {
+ return addButtonText;
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ public boolean enableOptionOnSelectionChange(ObjectListSelectionModel
listSelectionModel) {
+ return listSelectionModel.selectedValuesSize() == 1;
+ }
+
+ public boolean enableRemoveOnSelectionChange(ObjectListSelectionModel
listSelectionModel) {
+ return listSelectionModel.selectedValue() != null;
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ public boolean hasOptionalButton() {
+ return hasOptionalButton;
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ public String optionalButtonText() {
+ return optionalButtonText;
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ public void optionOnSelection(ObjectListSelectionModel listSelectionModel) {
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ public String removeButtonText() {
+ return removeButtonText;
+ }
+
+ /**
+ * Changes the text of the add button. This method has to be called before
+ * the <code>AddRemoveListPane</code> is initialized.
+ *
+ * @param addButtonText The add button's text
+ */
+ public void setAddButtonText(String addButtonText) {
+ this.addButtonText = addButtonText;
+ }
+
+ /**
+ * Changes the state of the optional button, meaning if it should be shown
+ * between the add and remove buttons or not.
+ *
+ * @param hasOptionalButton <code>true</code> to show an optional button
+ * and to use the behavior related to the optional button;
+ * <code>false</code> to not use it
+ */
+ public void setHasOptionalButton(boolean hasOptionalButton) {
+ this.hasOptionalButton = hasOptionalButton;
+ }
+
+ /**
+ * Changes the text of the optional button. This method has to be called
+ * before the <code>AddRemoveListPane</code> is initialized. This does not
+ * make the optional button visible.
+ *
+ * @param optionalButtonText The optional button's text
+ */
+ public void setOptionalButtonText(String optionalButtonText) {
+ this.optionalButtonText = optionalButtonText;
+ }
+
+ /**
+ * Changes the text of the remove button. This method has to be called
+ * before the <code>AddRemoveListPane</code> is initialized.
+ *
+ * @param removeButtonText The remove button's text
+ */
+ public void setRemoveButtonText(String removeButtonText) {
+ this.removeButtonText = removeButtonText;
+ }
+ }
+
+ /**
+ * This adapter is used to perform the actual action when adding a new item
+ * or removing the selected items. It is possible to add an optional button.
+ */
+ public static interface Adapter {
+
+ /**
+ * The add button's text.
+ *
+ * @return The text shown on the add button
+ */
+ String addButtonText();
+
+ /**
+ * Invoked when the user selects the Add button.
+ */
+ void addNewItem(ObjectListSelectionModel listSelectionModel);
+
+ /**
+ * Invoked when selection changes. Implementation dictates whether button
+ * should be enabled.
+ */
+ boolean enableOptionOnSelectionChange(ObjectListSelectionModel listSelectionModel);
+
+ /**
+ * Invoked when selection changes. Implementation dictates whether remove button
+ * should be enabled.
+ */
+ boolean enableRemoveOnSelectionChange(ObjectListSelectionModel listSelectionModel);
+
+ /**
+ * Determines whether an optional button should be added between the add
+ * and remove buttons.
+ *
+ * @return <code>true</code> to show an optional button and to use the
+ * behavior related to the optional button; <code>false</code> to not use
+ * it
+ */
+ boolean hasOptionalButton();
+
+ /**
+ * Resource string key for the optional button.
+ */
+ String optionalButtonText();
+
+ /**
+ * Invoked when the user selects the optional button
+ */
+ void optionOnSelection(ObjectListSelectionModel listSelectionModel);
+
+ /**
+ * The remove button's text.
+ *
+ * @return The text shown on the remove button
+ */
+ String removeButtonText();
+
+ /**
+ * Invoked when the user selects the Remove button.
+ */
+ void removeSelectedItems(ObjectListSelectionModel listSelectionModel);
+ }
+}
\ No newline at end of file
Property changes on:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/AddRemovePane.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Author Id Revision Date
Name: svn:eol-style
+ native
Added:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitClassesComposite.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitClassesComposite.java
(rev 0)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitClassesComposite.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -0,0 +1,393 @@
+/*******************************************************************************
+ * 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
+ * Dmitry Geraskov, Exadel Inc. - Extracted from Dali 2.0 to protect from changes.
+ ******************************************************************************/
+package org.jboss.tools.hibernate.jpt.ui.xpl;
+
+import java.util.ListIterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.ui.IJavaElementSearchConstants;
+import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jpt.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.core.context.persistence.ClassRef;
+import org.eclipse.jpt.core.context.persistence.PersistenceUnit;
+import org.eclipse.jpt.ui.JptUiPlugin;
+import org.eclipse.jpt.ui.internal.JpaMappingImageHelper;
+import org.eclipse.jpt.ui.internal.JptUiIcons;
+import org.eclipse.jpt.ui.internal.JptUiMessages;
+import org.eclipse.jpt.ui.internal.persistence.JptUiPersistenceMessages;
+import org.eclipse.jpt.utility.internal.model.value.ItemPropertyListValueModelAdapter;
+import org.eclipse.jpt.utility.internal.model.value.ListAspectAdapter;
+import org.eclipse.jpt.utility.internal.model.value.PropertyAspectAdapter;
+import org.eclipse.jpt.utility.internal.model.value.SimplePropertyValueModel;
+import org.eclipse.jpt.utility.internal.model.value.TransformationPropertyValueModel;
+import org.eclipse.jpt.utility.internal.model.value.swing.ObjectListSelectionModel;
+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.osgi.util.NLS;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.SelectionDialog;
+import org.eclipse.ui.progress.IProgressService;
+import org.jboss.tools.hibernate.jpt.ui.HibernateJptUIPlugin;
+import org.jboss.tools.hibernate.jpt.ui.xpl.AddRemovePane.Adapter;
+
+/**
+ * Here the layout of this pane:
+ * <pre>
+ * -----------------------------------------------------------------------------
+ * | |
+ * | Description |
+ * | |
+ * | ------------------------------------------------------------------------- |
+ * | | | |
+ * | | AddRemoveListPane | |
+ * | | | |
+ * | ------------------------------------------------------------------------- |
+ * | |
+ * | x Exclude Unlisted Mapped Classes |
+ * | |
+ *
-----------------------------------------------------------------------------</pre>
+ *
+ * @see PersistenceUnit
+ * @see PersistenceUnitGeneralComposite - The parent container
+ * @see AddRemoveListPane
+ *
+ * @version 2.0
+ * @since 2.0
+ */
+@SuppressWarnings("nls")
+public class PersistenceUnitClassesComposite extends AbstractPane<PersistenceUnit>
+{
+ /**
+ * Creates a new <code>PersistenceUnitMappedClassesComposite</code>.
+ *
+ * @param parentPane The parent pane of this one
+ * @param parent The parent container
+ */
+ public PersistenceUnitClassesComposite(AbstractPane<? extends PersistenceUnit>
parentPane,
+ Composite parent) {
+
+ super(parentPane, parent);
+ }
+
+ private void addMappedClass(ObjectListSelectionModel listSelectionModel) {
+
+ IType type = chooseType();
+
+ if (type != null) {
+ ClassRef classRef = subject().addSpecifiedClassRef();
+ classRef.setClassName(type.getFullyQualifiedName('.'));
+ listSelectionModel.setSelectedValue(classRef);
+ }
+ }
+
+ private Adapter buildAdapter() {
+ return new AddRemoveListPane.AbstractAdapter() {
+ public void addNewItem(ObjectListSelectionModel listSelectionModel) {
+ addMappedClass(listSelectionModel);
+ }
+
+ @Override
+ public boolean enableOptionOnSelectionChange(ObjectListSelectionModel
listSelectionModel) {
+ if (!super.enableOptionOnSelectionChange(listSelectionModel)) {
+ return false;
+ }
+
+ return findType((ClassRef) listSelectionModel.selectedValue()) != null;
+ }
+
+ @Override
+ public boolean hasOptionalButton() {
+ return true;
+ }
+
+ @Override
+ public String optionalButtonText() {
+ return JptUiPersistenceMessages.PersistenceUnitClassesComposite_open;
+ }
+
+ @Override
+ public void optionOnSelection(ObjectListSelectionModel listSelectionModel) {
+ openMappedClass((ClassRef) listSelectionModel.selectedValue());
+ }
+
+ public void removeSelectedItems(ObjectListSelectionModel listSelectionModel) {
+ for (Object item : listSelectionModel.selectedValues()) {
+ subject().removeSpecifiedClassRef((ClassRef) item);
+ }
+ }
+ };
+ }
+
+ private WritablePropertyValueModel<Boolean>
buildExcludeUnlistedMappedClassesHolder() {
+ return new PropertyAspectAdapter<PersistenceUnit, Boolean>(
+ getSubjectHolder(),
+ "defaultExcludeUnlistedClasses",
+ "specifiedExcludeUnlistedClasses")
+ {
+ @Override
+ protected Boolean buildValue_() {
+ return subject.getSpecifiedExcludeUnlistedClasses();
+ }
+
+ @Override
+ protected void setValue_(Boolean value) {
+ subject.setSpecifiedExcludeUnlistedClasses(value);
+ }
+
+ @Override
+ protected void subjectChanged() {
+ Object oldValue = this.getValue();
+ super.subjectChanged();
+ Object newValue = this.getValue();
+
+ // Make sure the default value is appended to the text
+ if (oldValue == newValue && newValue == null) {
+ this.fireAspectChange(Boolean.TRUE, newValue);
+ }
+ }
+ };
+ }
+
+ private PropertyValueModel<String> buildExcludeUnlistedMappedClassesStringHolder()
{
+
+ return new TransformationPropertyValueModel<Boolean,
String>(buildExcludeUnlistedMappedClassesHolder()) {
+
+ @Override
+ protected String transform(Boolean value) {
+
+ if ((subject() != null) && (value == null)) {
+
+ Boolean defaultValue = subject().getDefaultExcludeUnlistedClasses();
+
+ if (defaultValue != null) {
+
+ String defaultStringValue = defaultValue ? JptUiPersistenceMessages.Boolean_True :
+ JptUiPersistenceMessages.Boolean_False;
+
+ return NLS.bind(
+ JptUiPersistenceMessages.PersistenceUnitClassesComposite_excludeUnlistedMappedClassesWithDefault,
+ defaultStringValue
+ );
+ }
+ }
+
+ return
JptUiPersistenceMessages.PersistenceUnitClassesComposite_excludeUnlistedMappedClasses;
+ }
+ };
+ }
+
+ private ILabelProvider buildLabelProvider() {
+ return new LabelProvider() {
+ @Override
+ public Image getImage(Object element) {
+ ClassRef classRef = (ClassRef) element;
+ JavaPersistentType persistentType = classRef.getJavaPersistentType();
+ Image image = null;
+
+ if (persistentType != null) {
+ image = JpaMappingImageHelper.imageForTypeMapping(persistentType.getMappingKey());
+ }
+
+ if (image != null) {
+ return image;
+ }
+
+ return JptUiPlugin.getImage(JptUiIcons.WARNING);
+ }
+
+ @Override
+ public String getText(Object element) {
+ ClassRef classRef = (ClassRef) element;
+ String name = classRef.getClassName();
+
+ if (name == null) {
+ name =
JptUiPersistenceMessages.PersistenceUnitClassesComposite_mappedClassesNoName;
+ }
+
+ return name;
+ }
+ };
+ }
+
+ private ListValueModel<ClassRef> buildItemListHolder() {
+ return new ItemPropertyListValueModelAdapter<ClassRef>(
+ buildListHolder(),
+ ClassRef.JAVA_PERSISTENT_TYPE_PROPERTY,
+ ClassRef.CLASS_NAME_PROPERTY
+ );
+ }
+
+ private ListValueModel<ClassRef> buildListHolder() {
+ return new ListAspectAdapter<PersistenceUnit, ClassRef>(getSubjectHolder(),
"specifiedClassRefs") {
+ @Override
+ protected ListIterator<ClassRef> listIterator_() {
+ return subject.specifiedClassRefs();
+ }
+
+ @Override
+ protected int size_() {
+ return subject.specifiedClassRefsSize();
+ }
+ };
+ }
+
+ private WritablePropertyValueModel<ClassRef> buildSelectedItemHolder() {
+ return new SimplePropertyValueModel<ClassRef>();
+ }
+
+ /**
+ * Prompts the user the Open Type dialog.
+ *
+ * @return Either the selected type or <code>null</code> if the user
+ * cancelled the dialog
+ */
+ private IType chooseType() {
+
+ IPackageFragmentRoot root = packageFragmentRoot();
+
+ if (root == null) {
+ return null;
+ }
+
+ IJavaElement[] elements = new IJavaElement[] { root.getJavaProject() };
+ IJavaSearchScope scope = SearchEngine.createJavaSearchScope(elements);
+ IProgressService service = PlatformUI.getWorkbench().getProgressService();
+ SelectionDialog typeSelectionDialog;
+
+ try {
+ typeSelectionDialog = JavaUI.createTypeDialog(
+ shell(),
+ service,
+ scope,
+ IJavaElementSearchConstants.CONSIDER_CLASSES,
+ false,
+ ""
+ );
+ }
+ catch (JavaModelException e) {
+ JptUiPlugin.log(e);
+ return null;
+ }
+
+ typeSelectionDialog.setTitle(JptUiMessages.ClassChooserPane_dialogTitle);
+ typeSelectionDialog.setMessage(JptUiMessages.ClassChooserPane_dialogMessage);
+
+ if (typeSelectionDialog.open() == Window.OK) {
+ return (IType) typeSelectionDialog.getResult()[0];
+ }
+
+ return null;
+ }
+
+ private IType findType(ClassRef classRef) {
+ String className = classRef.getClassName();
+
+ if (className != null) {
+ try {
+ return subject().getJpaProject().getJavaProject().findType(className);
+ }
+ catch (JavaModelException e) {
+ JptUiPlugin.log(e);
+ }
+ }
+
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ protected void initializeLayout(Composite container) {
+
+ // Description
+ buildMultiLineLabel(
+ container,
+ JptUiPersistenceMessages.PersistenceUnitClassesComposite_description
+ );
+
+ // List pane
+ new AddRemoveListPane<PersistenceUnit>(
+ this,
+ container,
+ buildAdapter(),
+ buildItemListHolder(),
+ buildSelectedItemHolder(),
+ buildLabelProvider()
+ )
+ {
+ @Override
+ protected void initializeTable(Table table) {
+ super.initializeTable(table);
+
+ Composite container = table.getParent();
+ GridData gridData = (GridData) container.getLayoutData();
+ gridData.heightHint = 75;
+ }
+ };
+
+ buildTriStateCheckBoxWithDefault(
+ container,
+ JptUiPersistenceMessages.PersistenceUnitClassesComposite_excludeUnlistedMappedClasses,
+ buildExcludeUnlistedMappedClassesHolder(),
+ buildExcludeUnlistedMappedClassesStringHolder()
+ );
+ }
+
+ private void openMappedClass(ClassRef classRef) {
+
+ IType type = findType(classRef);
+
+ if (type != null) {
+ try {
+ IJavaElement javaElement = type.getParent();
+ JavaUI.openInEditor(javaElement, true, true);
+ }
+ catch (PartInitException e) {
+ JptUiPlugin.log(e);
+ }
+ catch (JavaModelException e) {
+ JptUiPlugin.log(e);
+ }
+ }
+ }
+
+ private IPackageFragmentRoot packageFragmentRoot() {
+ IProject project = subject().getJpaProject().getProject();
+ IJavaProject root = JavaCore.create(project);
+
+ try {
+ return root.getAllPackageFragmentRoots()[0];
+ }
+ catch (JavaModelException e) {
+ JptUiPlugin.log(e);
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
Property changes on:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitClassesComposite.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Author Id Revision Date
Name: svn:eol-style
+ native
Added:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitGeneralComposite.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitGeneralComposite.java
(rev 0)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitGeneralComposite.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * 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
+ * Dmitry Geraskov, Exadel Inc. - Extracted from Dali 2.0 to protect from changes.
+ ******************************************************************************/
+package org.jboss.tools.hibernate.jpt.ui.xpl;
+
+import org.eclipse.jpt.core.context.persistence.PersistenceUnit;
+import org.eclipse.jpt.ui.WidgetFactory;
+import org.eclipse.jpt.ui.details.JpaPageComposite;
+import org.eclipse.jpt.ui.internal.JpaHelpContextIds;
+import org.eclipse.jpt.ui.internal.persistence.JptUiPersistenceMessages;
+import org.eclipse.jpt.ui.internal.persistence.details.PersistenceUnitJarFilesComposite;
+import org.eclipse.jpt.utility.internal.model.value.PropertyAspectAdapter;
+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.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * Here the layout of this pane:
+ * <pre>
+ * -----------------------------------------------------------------------------
+ * | |
+ * | - General --------------------------------------------------------------- |
+ * | ------------------------------------------------- |
+ * | Name: | I | |
+ * | ------------------------------------------------- |
+ * | ------------------------------------------------- |
+ * | Persistence Provider: | |v| |
+ * | ------------------------------------------------- |
+ * | |
+ * | |
+ * | - Mapped Classes -------------------------------------------------------- |
+ * | |
+ * | Description |
+ * | |
+ * | ----------------------------------------------------------------------- |
+ * | | | |
+ * | | PersistenceUnitMappedClassesComposite | |
+ * | | | |
+ * | ----------------------------------------------------------------------- |
+ * | |
+ * | |
+ * | - XML Mapping Files ----------------------------------------------------- |
+ * | |
+ * | Description |
+ * | |
+ * | ----------------------------------------------------------------------- |
+ * | | | |
+ * | | PersistenceUnitMappingFilesComposite | |
+ * | | | |
+ * | ----------------------------------------------------------------------- |
+ *
-----------------------------------------------------------------------------</pre>
+ *
+ * @see PersistenceUnit
+ * @see PersistenceUnitJarFilesComposite
+ * @see PersistenceUnitMappedClassesComposite
+ * @see PersistenceUnitMappingFilesComposite
+ *
+ * @version 2.0
+ * @since 2.0
+ */
+public class PersistenceUnitGeneralComposite extends AbstractPane<PersistenceUnit>
+ implements JpaPageComposite
+{
+ /**
+ * Creates a new <code>PersistenceUnitGeneralComposite</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
+ */
+ public PersistenceUnitGeneralComposite(PropertyValueModel<PersistenceUnit>
subjectHolder,
+ Composite container,
+ WidgetFactory widgetFactory) {
+
+ super(subjectHolder, container, widgetFactory);
+ }
+
+// private void initializeJavaArchivesPane(Composite container) {
+//
+// container = buildSection(
+// container,
+// JptUiPersistenceMessages.PersistenceUnitComposite_javaArchives
+// );
+//
+// new PersistenceUnitJavaArchivesComposite(this, container);
+// }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ protected Composite buildContainer(Composite parent) {
+
+ GridLayout layout = new GridLayout(1, true);
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.marginTop = 0;
+ layout.marginLeft = 0;
+ layout.marginBottom = 0;
+ layout.marginRight = 0;
+ layout.verticalSpacing = 15;
+
+ Composite container = buildPane(parent, layout);
+ updateGridData(container);
+
+ return container;
+ }
+
+ private WritablePropertyValueModel<String> buildPersistenceProviderHolder() {
+ return new PropertyAspectAdapter<PersistenceUnit, String>(getSubjectHolder(),
PersistenceUnit.PROVIDER_PROPERTY) {
+ @Override
+ protected String buildValue_() {
+ return subject.getProvider();
+ }
+
+ @Override
+ protected void setValue_(String value) {
+ if (value.length() == 0) {
+ value = null;
+ }
+ subject.setProvider(value);
+ }
+ };
+ }
+
+ private WritablePropertyValueModel<String> buildPersistenceUnitNameHolder() {
+ return new PropertyAspectAdapter<PersistenceUnit, String>(getSubjectHolder(),
PersistenceUnit.NAME_PROPERTY) {
+ @Override
+ protected String buildValue_() {
+ return subject.getName();
+ }
+
+ @Override
+ protected void setValue_(String value) {
+ subject.setName(value);
+ }
+ };
+ }
+
+ private WritablePropertyValueModel<String> buildPersistenceUnitDescriptionHolder()
{
+ return new PropertyAspectAdapter<PersistenceUnit, String>(getSubjectHolder(),
PersistenceUnit.DESCRIPTION_PROPERTY) {
+ @Override
+ protected String buildValue_() {
+ return subject.getDescription();
+ }
+
+ @Override
+ protected void setValue_(String value) {
+ if (value.length() == 0) {
+ value = null;
+ }
+ subject.setDescription(value);
+ }
+ };
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ public String getHelpID() {
+ return JpaHelpContextIds.PERSISTENCE_UNIT_GENERAL;
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ public Image getPageImage() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ public String getPageText() {
+ return JptUiPersistenceMessages.PersistenceUnitGeneralComposite_general;
+ }
+
+ private void initializeGeneralPane(Composite container) {
+
+ container = buildSection(
+ container,
+ JptUiPersistenceMessages.PersistenceUnitGeneralComposite_general
+ );
+
+ // Name widgets
+ buildLabeledText(
+ container,
+ JptUiPersistenceMessages.PersistenceUnitGeneralComposite_name,
+ buildPersistenceUnitNameHolder()
+ );
+
+ // Persistence Provider widgets
+ buildLabeledText(
+ container,
+ JptUiPersistenceMessages.PersistenceUnitGeneralComposite_persistenceProvider,
+ buildPersistenceProviderHolder()
+ );
+
+ // Description widgets
+ buildLabeledText(
+ container,
+ JptUiPersistenceMessages.PersistenceUnitGeneralComposite_description,
+ buildPersistenceUnitDescriptionHolder()
+ );
+ }
+
+ private void initializeJPAMappingDescriptorsPane(Composite container) {
+
+ container = buildSection(
+ container,
+ JptUiPersistenceMessages.PersistenceUnitGeneralComposite_jpaMappingDescriptors,
+ JptUiPersistenceMessages.PersistenceUnitGeneralComposite_jpaMappingDescriptors_description
+ );
+
+ updateGridData(container);
+ updateGridData(container.getParent());
+
+ new PersistenceUnitMappingFilesComposite(this, container);
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ protected void initializeLayout(Composite container) {
+
+ initializeGeneralPane(container);
+ initializeMappedClassesPane(container);
+ initializeJPAMappingDescriptorsPane(container);
+// initializeJavaArchivesPane(container);
+
+ }
+
+ private void initializeMappedClassesPane(Composite container) {
+
+ container = buildSection(
+ container,
+ JptUiPersistenceMessages.PersistenceUnitGeneralComposite_mappedClasses
+ );
+
+ updateGridData(container);
+ updateGridData(container.getParent());
+
+ new PersistenceUnitClassesComposite(this, container);
+ }
+
+ private void updateGridData(Composite container) {
+
+ GridData gridData = new GridData();
+ gridData.grabExcessHorizontalSpace = true;
+ gridData.grabExcessVerticalSpace = true;
+ gridData.horizontalAlignment = SWT.FILL;
+ gridData.verticalAlignment = SWT.FILL;
+ container.setLayoutData(gridData);
+ }
+}
Property changes on:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitGeneralComposite.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Author Id Revision Date
Name: svn:eol-style
+ native
Added:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitMappingFilesComposite.java
===================================================================
---
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitMappingFilesComposite.java
(rev 0)
+++
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitMappingFilesComposite.java 2009-02-10
15:11:45 UTC (rev 13560)
@@ -0,0 +1,448 @@
+/*******************************************************************************
+ * 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
+ * Dmitry Geraskov, Exadel Inc. - Extracted from Dali 2.0 to protect from changes.
+ ******************************************************************************/
+package org.jboss.tools.hibernate.jpt.ui.xpl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.ListIterator;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jpt.core.context.persistence.MappingFileRef;
+import org.eclipse.jpt.core.context.persistence.PersistenceUnit;
+import org.eclipse.jpt.core.internal.resource.orm.translators.OrmXmlMapper;
+import org.eclipse.jpt.ui.JptUiPlugin;
+import org.eclipse.jpt.ui.internal.JptUiIcons;
+import org.eclipse.jpt.ui.internal.persistence.JptUiPersistenceMessages;
+import org.eclipse.jpt.ui.internal.util.SWTUtil;
+import org.eclipse.jpt.ui.internal.widgets.PostExecution;
+import org.eclipse.jpt.utility.internal.model.value.ItemPropertyListValueModelAdapter;
+import org.eclipse.jpt.utility.internal.model.value.ListAspectAdapter;
+import org.eclipse.jpt.utility.internal.model.value.SimplePropertyValueModel;
+import org.eclipse.jpt.utility.internal.model.value.swing.ObjectListSelectionModel;
+import org.eclipse.jpt.utility.model.value.ListValueModel;
+import org.eclipse.jpt.utility.model.value.WritablePropertyValueModel;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
+import org.eclipse.ui.dialogs.ISelectionStatusValidator;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.views.navigator.ResourceComparator;
+import org.jboss.tools.hibernate.jpt.ui.HibernateJptUIPlugin;
+import org.jboss.tools.hibernate.jpt.ui.xpl.AddRemovePane.Adapter;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Here the layout of this pane:
+ * <pre>
+ * -----------------------------------------------------------------------------
+ * | ------------------------------------------------------------------------- |
+ * | | | |
+ * | | AddRemoveListPane | |
+ * | | | |
+ * | ------------------------------------------------------------------------- |
+ *
-----------------------------------------------------------------------------</pre>
+ *
+ * @see PersistenceUnit
+ * @see PersistenceUnitGeneralComposite - The parent container
+ * @see AddRemoveListPane
+ *
+ * @version 2.0
+ * @since 2.0
+ */
+@SuppressWarnings("nls")
+public class PersistenceUnitMappingFilesComposite extends
AbstractPane<PersistenceUnit>
+{
+ /**
+ * Creates a new <code>PersistenceUnitMappingFilesComposite</code>.
+ *
+ * @param parentPane The parent pane of this one
+ * @param parent The parent container
+ */
+ public PersistenceUnitMappingFilesComposite(AbstractPane<? extends
PersistenceUnit> parentPane,
+ Composite parent) {
+
+ super(parentPane, parent);
+ }
+
+ /**
+ * Prompts a dialog showing a tree structure of the source paths where the
+ * only files shown are JPA mapping descriptors file. The XML file has to be
+ * an XML file with the root tag: <entity-mappings>.
+ *
+ * @param listSelectionModel The selection model used to select the new files
+ */
+ private void addJPAMappingDescriptor(ObjectListSelectionModel listSelectionModel) {
+
+ IProject project = subject().getJpaProject().getProject();
+
+ ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(
+ shell(),
+ new WorkbenchLabelProvider(),
+ new WorkbenchContentProvider()
+ );
+
+ dialog.setHelpAvailable(false);
+ dialog.setValidator(buildValidator());
+ dialog.setTitle(JptUiPersistenceMessages.PersistenceUnitMappingFilesComposite_mappingFileDialog_title);
+ dialog.setMessage(JptUiPersistenceMessages.PersistenceUnitMappingFilesComposite_mappingFileDialog_message);
+ dialog.addFilter(new XmlFileViewerFilter(subject().getJpaProject().getJavaProject()));
+ dialog.setInput(project);
+ dialog.setComparator(new ResourceComparator(ResourceComparator.NAME));
+
+ SWTUtil.show(
+ dialog,
+ buildSelectionDialogPostExecution(listSelectionModel)
+ );
+ }
+
+ private Adapter buildAdapter() {
+ return new AddRemoveListPane.AbstractAdapter() {
+ public void addNewItem(ObjectListSelectionModel listSelectionModel) {
+ addJPAMappingDescriptor(listSelectionModel);
+ }
+
+ public void removeSelectedItems(ObjectListSelectionModel listSelectionModel) {
+ for (Object item : listSelectionModel.selectedValues()) {
+ subject().removeSpecifiedMappingFileRef((MappingFileRef) item);
+ }
+ }
+ };
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ protected Composite buildContainer(Composite parent) {
+
+ GridLayout layout = new GridLayout(1, true);
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.marginTop = 0;
+ layout.marginLeft = 0;
+ layout.marginBottom = 0;
+ layout.marginRight = 0;
+
+ Composite container = buildPane(parent, layout);
+ updateGridData(container);
+
+ return container;
+ }
+
+ private ListValueModel<MappingFileRef> buildItemListHolder() {
+ return new ItemPropertyListValueModelAdapter<MappingFileRef>(
+ buildListHolder(),
+ MappingFileRef.FILE_NAME_PROPERTY
+ );
+ }
+
+ private ILabelProvider buildLabelProvider() {
+ return new LabelProvider() {
+ @Override
+ public Image getImage(Object element) {
+ return JptUiPlugin.getImage(JptUiIcons.MAPPING_FILE_REF);
+ }
+
+ @Override
+ public String getText(Object element) {
+ MappingFileRef mappingFileRef = (MappingFileRef) element;
+ String name = mappingFileRef.getFileName();
+
+ if (name == null) {
+ name = JptUiPersistenceMessages.PersistenceUnitMappingFilesComposite_ormNoName;
+ }
+
+ return name;
+ }
+ };
+ }
+
+ private ListValueModel<MappingFileRef> buildListHolder() {
+ return new ListAspectAdapter<PersistenceUnit, MappingFileRef>(getSubjectHolder(),
"specifiedMappingFileRefs") {
+ @Override
+ protected ListIterator<MappingFileRef> listIterator_() {
+ return subject.specifiedMappingFileRefs();
+ }
+
+ @Override
+ protected int size_() {
+ return subject.specifiedMappingFileRefsSize();
+ }
+ };
+ }
+
+ private WritablePropertyValueModel<MappingFileRef> buildSelectedItemHolder() {
+ return new SimplePropertyValueModel<MappingFileRef>();
+ }
+
+ private PostExecution<ElementTreeSelectionDialog>
buildSelectionDialogPostExecution(final ObjectListSelectionModel listSelectionModel) {
+ return new PostExecution<ElementTreeSelectionDialog>() {
+ public void execute(ElementTreeSelectionDialog dialog) {
+
+ if (dialog.getReturnCode() == IDialogConstants.CANCEL_ID) {
+ return;
+ }
+
+ int index = subject().specifiedMappingFileRefsSize();
+
+ for (Object result : dialog.getResult()) {
+ IFile file = (IFile) result;
+ IPath filePath = removeSourcePath(file);
+
+ MappingFileRef mappingFileRef = subject().addSpecifiedMappingFileRef(index++);
+ mappingFileRef.setFileName(filePath.toPortableString());
+
+ listSelectionModel.addSelectedValue(mappingFileRef);
+ }
+ }
+ };
+ }
+
+ private ISelectionStatusValidator buildValidator() {
+ return new ISelectionStatusValidator() {
+ public IStatus validate(Object[] selection) {
+
+ if (selection.length == 0) {
+ return new Status(IStatus.ERROR, JptUiPlugin.PLUGIN_ID, "");
+ }
+
+ for (Object item : selection) {
+ if (item instanceof IFolder) {
+ return new Status(IStatus.ERROR, JptUiPlugin.PLUGIN_ID, "");
+ }
+ }
+
+ return new Status(IStatus.OK, JptUiPlugin.PLUGIN_ID, "");
+ }
+ };
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ protected void initializeLayout(Composite container) {
+
+ // List pane
+ new AddRemoveListPane<PersistenceUnit>(
+ this,
+ container,
+ buildAdapter(),
+ buildItemListHolder(),
+ buildSelectedItemHolder(),
+ buildLabelProvider()
+ ) {
+ @Override
+ protected Composite buildContainer(Composite parent) {
+ parent = super.buildContainer(parent);
+ updateGridData(parent);
+ return parent;
+ }
+
+ @Override
+ protected void initializeLayout(Composite container) {
+ super.initializeLayout(container);
+ updateGridData(getContainer());
+ }
+ };
+ }
+
+ /**
+ * Returns the path of the given file excluding the source folder.
+ *
+ * @param file The file to retrieve its path minus the source folder
+ * @return The relative path of the given path, the path is relative to the
+ * source path
+ */
+ private IPath removeSourcePath(IFile file) {
+ IJavaProject javaProject = subject().getJpaProject().getJavaProject();
+ IPath filePath = file.getProjectRelativePath();
+
+ try {
+ for (IClasspathEntry entry : javaProject.getRawClasspath()) {
+
+ // Only check for source paths
+ if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+
+ // Retrieve the source path relative to the project
+ IPath sourcePath = entry.getPath().removeFirstSegments(1);
+
+ // Check to see if the file path starts with the source path
+ if (sourcePath.isPrefixOf(filePath)) {
+ int count = sourcePath.segmentCount();
+ filePath = filePath.removeFirstSegments(count);
+ break;
+ }
+ }
+ }
+ }
+ catch (JavaModelException e) {
+ JptUiPlugin.log(e);
+ }
+
+ return filePath;
+ }
+
+ private void updateGridData(Composite container) {
+
+ GridData gridData = new GridData();
+ gridData.grabExcessHorizontalSpace = true;
+ gridData.grabExcessVerticalSpace = true;
+ gridData.horizontalAlignment = SWT.FILL;
+ gridData.verticalAlignment = SWT.FILL;
+ container.setLayoutData(gridData);
+ }
+
+ //TODO might we want to do this with content-types instead? is there
+ //the potential that an extender could hae a mapping file that doesn't have
+ //entity-mappings as the root node??
+ /**
+ * This handler is responsible to parse the root tag (local name) only.
+ */
+ private static class SAXHandler extends DefaultHandler {
+
+ private String rootTagName;
+
+ public String getRootTagName() {
+ return rootTagName;
+ }
+
+ @Override
+ public InputSource resolveEntity(String publicId,
+ String systemId) throws IOException, SAXException {
+
+ InputSource inputSource = new InputSource();
+ inputSource.setByteStream(new ByteArrayInputStream(new byte[0]));
+ return inputSource;
+ }
+
+ @Override
+ public void startElement(String uri,
+ String localName,
+ String name,
+ Attributes attributes) throws SAXException {
+
+ this.rootTagName = name;
+ throw new SAXException();
+ }
+ }
+
+ /**
+ * This filter will deny showing any file that are not XML files or folders
+ * that don't contain any XML files in its sub-hierarchy. The XML files are
+ * partially parsed to only accept JPA mapping descriptors.
+ */
+ private static class XmlFileViewerFilter extends ViewerFilter {
+
+ private final IJavaProject javaProject;
+
+ XmlFileViewerFilter(IJavaProject javaProject) {
+ super();
+ this.javaProject = javaProject;
+ }
+
+ /**
+ * Determines whether the given file (an XML file) is a JPA mapping
+ * descriptor file. It has to be a valid XML file with a root element
+ * named "entity-mappings".
+ *
+ * @param file The file to parse and see if it's a mapping descriptor file
+ * @return <code>true</code> if the given file is a valid XML file with a
+ * root element named "entity-mappings"; <code>false</code> in
any other
+ * case
+ */
+ private boolean isMappingFile(IFile file) {
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ SAXParser saxParser = factory.newSAXParser();
+ SAXHandler handler = new SAXHandler();
+ try {
+ saxParser.parse(file.getRawLocationURI().toURL().openStream(), handler);
+ }
+ catch (Exception e) {
+ // Ignore since it's caused by SAXHandler to stop the parsing
+ // the moment the local name is retrieved
+ }
+ return OrmXmlMapper.ENTITY_MAPPINGS.equalsIgnoreCase(handler.getRootTagName());
+ }
+ catch (Exception e) {
+ JptUiPlugin.log(e);
+ return false;
+ }
+ }
+
+ private boolean isXmlFile(IFile file) {
+ return "xml".equalsIgnoreCase(file.getFileExtension());
+ }
+
+ @Override
+ public boolean select(Viewer viewer,
+ Object parentElement,
+ Object element) {
+
+ if (element instanceof IFile) {
+ IFile file = (IFile) element;
+ return isXmlFile(file) && isMappingFile(file);
+ }
+ else if (element instanceof IFolder) {
+ IFolder folder = (IFolder) element;
+
+ try {
+ for (IClasspathEntry entry : javaProject.getRawClasspath()) {
+ if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ if (!entry.getPath().isPrefixOf(folder.getFullPath().makeRelative()))
+ return false;
+ }
+ }
+
+ for (IResource resource : folder.members()) {
+ if (select(viewer, folder, resource)) {
+ return true;
+ }
+ }
+ }
+ catch (JavaModelException e) {
+ JptUiPlugin.log(e.getStatus());
+ }
+ catch (CoreException e) {
+ JptUiPlugin.log(e.getStatus());
+ }
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
Property changes on:
trunk/hibernatetools/plugins/org.jboss.tools.hibernate.jpt.ui/src/org/jboss/tools/hibernate/jpt/ui/xpl/PersistenceUnitMappingFilesComposite.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Author Id Revision Date
Name: svn:eol-style
+ native