diff options
Diffstat (limited to 'plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse')
155 files changed, 23082 insertions, 0 deletions
diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/Activator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/Activator.java new file mode 100644 index 00000000000..fe1993a263b --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/Activator.java @@ -0,0 +1,188 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.papyrus.infra.core.log.LogHelper; +import org.eclipse.papyrus.infra.widgets.util.ImageDescriptorManager; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + /** + * The plug-in ID + */ + public static final String PLUGIN_ID = "org.eclipse.papyrus.infra.widgets"; //$NON-NLS-1$ + + /** + * The shared instance + */ + private static Activator plugin; + + /** + * The logger for this plugin + */ + public static LogHelper log; + + /** + * The logger for this plugin + */ + public ImageDescriptorManager imageDescriptorManager; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + log = new LogHelper(plugin); + imageDescriptorManager = new ImageDescriptorManager(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + log = null; + imageDescriptorManager.reset(); + imageDescriptorManager = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + /** + * Returns the image at the given path from this plugin + * + * @param path + * the path of the image to be displayed + * @return The Image at the given location, or null if it couldn't be found + */ + public Image getImage(String path) { + return getImage(PLUGIN_ID, path); + } + + /** + * Returns the image from the given image descriptor + * + * @param pluginId + * The plugin in which the image is located + * @param path + * The path to the image from the plugin + * @return + * The Image at the given location, or null if it couldn't be found + */ + public Image getImage(String pluginId, String path) { + final ImageRegistry registry = getImageRegistry(); + String key = pluginId + "/" + path; //$NON-NLS-1$ + Image image = registry.get(key); + if (image == null) { + registry.put(key, AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, path)); + image = registry.get(key); + } + return image; + } + + public Image getImage(ImageDescriptor descriptor) { + final ImageRegistry registry = getImageRegistry(); + if (imageDescriptorManager == null || registry == null) { + return null; // should never happen => is set to null when activator is not started + } + String key = imageDescriptorManager.getKey(descriptor); + Image image = registry.get(key); + if (image == null) { + registry.put(key, descriptor); + image = registry.get(key); + } + return image; + } + + /** + * Returns the image from the given image location + * + * @param pluginId + * The plugin in which the image is located + * @param path + * The path to the image from the plugin + * @return + * The Image Descriptor at the given location, or null if it + * couldn't be found + */ + public ImageDescriptor getImageDescriptor(String pluginId, String path) { + final ImageRegistry registry = getImageRegistry(); + String key = pluginId + "/" + path; //$NON-NLS-1$ + ImageDescriptor descriptor = registry.getDescriptor(key); + if (descriptor == null) { + registry.put(key, AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, path)); + descriptor = registry.getDescriptor(key); + } + return descriptor; + } + + /** + * Returns the image descriptor at the given path from this plugin + * + * @param path + * the path of the image to be displayed + * @return The ImageDescriptor at the given location, or null if it couldn't be found + */ + public ImageDescriptor getImageDescriptor(String path) { + return getImageDescriptor(PLUGIN_ID, path); + } + + /** + * Returns the image from the given path + * + * @param imagePath + * The path of the image, in the form /<plug-in ID>/<path to the image> + * @return + * The Image at the given location, or null if none was found + */ + public Image getImageFromPlugin(String imagePath) { + if (imagePath.startsWith("/")) { //$NON-NLS-1$ + String pluginId, path; + imagePath = imagePath.substring(1, imagePath.length()); + pluginId = imagePath.substring(0, imagePath.indexOf("/")); //$NON-NLS-1$ + path = imagePath.substring(imagePath.indexOf("/"), imagePath.length()); //$NON-NLS-1$ + return getImage(pluginId, path); + } else { + return getImage(imagePath); + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/BooleanEditionFactory.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/BooleanEditionFactory.java new file mode 100644 index 00000000000..1ac8e433d49 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/BooleanEditionFactory.java @@ -0,0 +1,85 @@ +/***************************************************************************** + * Copyright (c) 2013, 2014 CEA LIST and others. + * + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.creation; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.papyrus.infra.widgets.validator.BooleanInputValidator; +import org.eclipse.swt.widgets.Control; + +/** + * The factory for the boolean + * + * @author Vincent Lorenzo + * + */ +public class BooleanEditionFactory extends StringEditionFactory { + /** + * + * Constructor. + * + */ + public BooleanEditionFactory() { + this(new BooleanInputValidator()); + } + + /** + * + * Constructor. + * + * @param validator + * The InputValidator used to check the entered String + */ + public BooleanEditionFactory(IInputValidator validator) { + super(validator); + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing a Boolean + * @param label + * The Label used to describe the kind of value being edited + * @param validator + * The validator used to check the Booleans being edited + */ + public BooleanEditionFactory(String title, String label, IInputValidator validator) { + super(title, label, validator); + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing a Boolean + * @param label + * The Label used to describe the kind of value being edited + */ + public BooleanEditionFactory(String title, String label) { + super(title, label, new BooleanInputValidator()); + } + + @Override + public Object createObject(Control widget, Object context) { + String txt = super.createObject(widget, context).toString(); + if (txt != null) { + return Boolean.parseBoolean(txt); + } + return null; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IAtomicOperationExecutor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IAtomicOperationExecutor.java new file mode 100644 index 00000000000..304150f7449 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IAtomicOperationExecutor.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.widgets.creation; + +import java.util.concurrent.Callable; + +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.papyrus.infra.widgets.Activator; + + +/** + * An interface that ensures execution of model changes as an atomic unit that is potentially undoable and redoable, such as on a "command stack" + * (whatever form it may take). + */ +public interface IAtomicOperationExecutor { + + IAtomicOperationExecutor DEFAULT = new Default(); + + /** + * Execute a runnable (an operation returning no result). + * + * @param operation + * the operation to execute + * @param label + * an optional label to associate with the operation for presentation in, for example, the Edit menu's Undo/Redo operations + */ + void execute(Runnable operation, String label); + + /** + * Execute a callable (an operation returning a result). + * + * @param operation + * the operation to execute + * @param label + * an optional label to associate with the operation for presentation in, for example, the Edit menu's Undo/Redo operations + * @return the {@code operation}'s result + */ + <V> V execute(Callable<V> operation, String label); + + // + // Nested types + // + + class Default implements IAtomicOperationExecutor { + + @Override + public void execute(final Runnable operation, String label) { + try { + operation.run(); + } catch (OperationCanceledException e) { + // We cannot really implement cancel because there is not command/transaction to roll back + } + } + + @Override + public <V> V execute(final Callable<V> operation, String label) { + class CallableWrapper implements Runnable { + + V result; + + @Override + public void run() { + try { + result = operation.call(); + } catch (OperationCanceledException e) { + // Don't trap this one + throw e; + } catch (Exception e) { + Activator.log.error("Callable operation failed.", e); //$NON-NLS-1$ + throw new OperationCanceledException(); // roll back + } + } + } + + CallableWrapper wrapper = new CallableWrapper(); + + execute(wrapper, label); + + return wrapper.result; + } + + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IntegerEditionFactory.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IntegerEditionFactory.java new file mode 100644 index 00000000000..ea94a8e7cf9 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/IntegerEditionFactory.java @@ -0,0 +1,80 @@ +/***************************************************************************** + * Copyright (c) 2013, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.creation; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.papyrus.infra.widgets.validator.IntegerInputValidator; +import org.eclipse.swt.widgets.Control; + + +public class IntegerEditionFactory extends StringEditionFactory { + + /** + * + * Constructor. + * + */ + public IntegerEditionFactory() { + this(new IntegerInputValidator()); + } + + /** + * + * Constructor. + * + * @param validator + * The InputValidator used to check the entered Integer + */ + public IntegerEditionFactory(IInputValidator validator) { + super(validator); + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing an Integer + * @param label + * The Label used to describe the kind of value being edited + * @param validator + * The validator used to check the Integers being edited + */ + + public IntegerEditionFactory(String title, String label, IInputValidator validator) { + super(title, label, validator); + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing a Integer + * @param label + * The Label used to describe the kind of value being edited + */ + public IntegerEditionFactory(String title, String label) { + this(title, label, new IntegerInputValidator()); + } + + @Override + public Object createObject(Control widget, Object context) { + String txt = super.createObject(widget, context).toString(); + if (txt != null) { + return Integer.parseInt(txt); + } + return null; + } +}
\ No newline at end of file diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/RealEditionFactory.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/RealEditionFactory.java new file mode 100644 index 00000000000..a1360c0a079 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/RealEditionFactory.java @@ -0,0 +1,77 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.creation; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.papyrus.infra.widgets.validator.RealInputValidator; + +/** + * The factory for real + * + * @author Vincent Lorenzo + * + */ +public class RealEditionFactory extends StringEditionFactory { + + /** + * + * Constructor. + * + */ + public RealEditionFactory() { + this(new RealInputValidator()); + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing a real + * @param label + * The Label used to describe the kind of value being edited + */ + public RealEditionFactory(String title, String label) { + this(title, label, new RealInputValidator()); + } + + /** + * + * Constructor. + * + * @param validator + * The InputValidator used to check the entered Real + */ + public RealEditionFactory(IInputValidator validator) { + super(validator); + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing a Real + * @param label + * The Label used to describe the kind of value being edited + * @param validator + * The validator used to check the Reals being edited + */ + public RealEditionFactory(String title, String label, IInputValidator validator) { + super(title, label, validator); + } + + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/ReferenceValueFactory.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/ReferenceValueFactory.java new file mode 100644 index 00000000000..b58b0af45f9 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/ReferenceValueFactory.java @@ -0,0 +1,96 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.creation; + +import java.util.Collection; + +import org.eclipse.swt.widgets.Control; + +/** + * A Factory for instantiating new Objects (Typically, from an Editor, although it could be + * used elsewhere) + * The caller of this Factory is responsible for storing the objects. However, in some cases, + * the objects must be created in a specific parent, which is different than the Source object + * Typically, it may happen that we need to reference an object that hasn't been yet created. If this + * reference is the container of the object, it isn't a problem, but sometime it is not it's container. + * In this case, it's the responsibility of the Factory to create the object in its container. The + * caller will then refer it from wherever it needs it. + * + * @author Camille Letavernier + */ +public interface ReferenceValueFactory { + + /** + * Indicates if this factory can create new instances + * + * @return + * True if the factory can create a new object + */ + public boolean canCreateObject(); + + /** + * Creates a new Object + * The widget Control can be used to display a dialog if additional + * information is needed to create the object (e.g. the users needs + * to input a name) + * This method is used to create objects that <b>won't necessarily</b> be attached + * to a parent (For example, the user can start creating an object, then cancel the operation : + * the Java Object will therefore be created, but won't be attached to anything, and then will + * be garbage collected). That's why this method should *not* attach the object to the given source. + * + * @param widget + * The widget calling this factory. It can be used for example to retrieve + * the Display for opening a Dialog + * @param context + * The object being edited, in which context the new object is to be created and which will as a result have a reference to the new object. + * If there is no context object (creation of a free-floating object) or it cannot be determined, this may be {@code null} + * @return + * The newly created object, or null if no object has been created + */ + public Object createObject(Control widget, Object context); + + /** + * The objects have been validated (For example, the user pressed "Ok") + * This method should attach the objects where they belong. + * Note however that the newly created objects will automatically be attached + * to their source. If the source is their container, then this method should probably + * not do anything. However, if the source is a simple reference, this method should + * attach these objects to their container. + * + * @param objectsToValidate + * The newly created objects that need to be validated + * @return + * The validated objects + */ + public Collection<Object> validateObjects(Collection<Object> objectsToValidate); + + /** + * Indicates if this factory can edit an object + * + * @return + * True if the Factory can edit an object + */ + public boolean canEdit(); + + /** + * Starts the edition of the given object + * + * @param widget + * The widget calling the factory. May be used for example to retrieve the shell for opening a Dialog. + * @param object + * The object to edit + * @return the edited object, or null if the object has been edited "in place" + */ + public Object edit(Control widget, Object object); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/StringEditionFactory.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/StringEditionFactory.java new file mode 100644 index 00000000000..0b845e24275 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/StringEditionFactory.java @@ -0,0 +1,162 @@ +/***************************************************************************** + * Copyright (c) 2011, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.creation; + +import java.util.Collection; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.window.Window; +import org.eclipse.papyrus.infra.widgets.editors.InputDialog; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.widgets.Control; + +/** + * A ValueFactory for editing Strings + * + * @author Camille Letavernier + * + */ +public class StringEditionFactory implements ReferenceValueFactory { + + private String title = Messages.StringEditionFactory_EnterANewValue; + + private String label = Messages.StringEditionFactory_EnterANewValue; + + private IInputValidator validator; + + private IStaticContentProvider contentProvider; + + /** + * + * Constructor. + * + */ + public StringEditionFactory() { + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing a String + * @param label + * The Label used to describe the kind of value being edited + */ + public StringEditionFactory(String title, String label) { + this.title = title; + this.label = label; + } + + /** + * + * Constructor. + * + * @param validator + * The InputValidator used to check the entered String + */ + public StringEditionFactory(IInputValidator validator) { + this.validator = validator; + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing a String + * @param label + * The Label used to describe the kind of value being edited + * @param validator + * The validator used to check the Strings being edited + */ + public StringEditionFactory(String title, String label, IInputValidator validator) { + this.title = title; + this.label = label; + this.validator = validator; + } + + @Override + public boolean canCreateObject() { + return true; + } + + @Override + public Object createObject(Control widget, Object context) { + InputDialog dialog = new InputDialog(widget.getShell(), title, label, "", validator); //$NON-NLS-1$ + if (contentProvider != null) { + dialog.setContentProvider(contentProvider); + } + + int result = dialog.open(); + if (result == Window.OK) { + String newValue = dialog.getText(); + return newValue; + } + + return null; + } + + @Override + public Collection<Object> validateObjects(Collection<Object> objectsToValidate) { + return objectsToValidate; + } + + @Override + public boolean canEdit() { + return true; + } + + @Override + public Object edit(Control widget, Object object) { + if (!(object instanceof String)) { + return object; + } + + InputDialog dialog = new InputDialog(widget.getShell(), title, label, (String) object, validator); + if (contentProvider != null) { + dialog.setContentProvider(contentProvider); + } + + int result = dialog.open(); + if (result == Window.OK) { + String newValue = dialog.getText(); + return newValue; + } + + return object; + } + + /** + * Sets the Validator for this factory + * + * @param validator + * The InputValidator to be used to check the input String + */ + public void setValidator(IInputValidator validator) { + this.validator = validator; + } + + /** + * Sets the content provider for this edition factory. The ContentProvider is used + * to suggest values to the user. + * + * @param provider + * The provider which will make suggestions to the user + */ + public void setContentProvider(IStaticContentProvider provider) { + this.contentProvider = provider; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/UnlimitedNaturalEditionFactory.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/UnlimitedNaturalEditionFactory.java new file mode 100644 index 00000000000..d9265e67e75 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/creation/UnlimitedNaturalEditionFactory.java @@ -0,0 +1,88 @@ +/***************************************************************************** + * Copyright (c) 2013, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.creation; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.papyrus.infra.widgets.validator.UnlimitedNaturalInputValidator; +import org.eclipse.papyrus.infra.widgets.validator.UnlimitedNaturalValidator; +import org.eclipse.swt.widgets.Control; + +/** + * + * The factory for UnlimitedNatural + * + */ +public class UnlimitedNaturalEditionFactory extends StringEditionFactory { + + /** + * + * Constructor. + * + */ + public UnlimitedNaturalEditionFactory() { + this(new UnlimitedNaturalInputValidator()); + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing an UnlimitedNatural + * @param label + * The Label used to describe the kind of value being edited + */ + public UnlimitedNaturalEditionFactory(String title, String label) { + super(title, label, new UnlimitedNaturalInputValidator()); + } + + /** + * + * Constructor. + * + * @param validator + * The InputValidator used to check the entered UnlimitedNatural + */ + public UnlimitedNaturalEditionFactory(IInputValidator validator) { + super(validator); + } + + /** + * + * Constructor. + * + * @param title + * The title of the dialog opened by this factory when editing a UnlimitedNatural + * @param label + * The Label used to describe the kind of value being edited + * @param validator + * The validator used to check the UnlimitedNaturals being edited + */ + public UnlimitedNaturalEditionFactory(String title, String label, IInputValidator validator) { + super(title, label, validator); + } + + @Override + public Object createObject(Control widget, Object context) { + String txt = super.createObject(widget, context).toString(); + if (UnlimitedNaturalValidator.INFINITE_STAR.equals(txt)) { + txt = UnlimitedNaturalValidator.INFINITE_MINUS_ONE; + } + if (txt != null) { + return Integer.parseInt(txt); + } + return null; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CLabelObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CLabelObservableValue.java new file mode 100644 index 00000000000..c653eedd906 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CLabelObservableValue.java @@ -0,0 +1,121 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.databinding; + +import org.eclipse.core.databinding.observable.value.AbstractObservableValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.swt.custom.CLabel; + +/** + * An IObservableValue to edit a CLabel (Text + Image), based on a LabelProvider + * It supports AggregatedObservable + * + * @author Camille Letavernier + */ +public class CLabelObservableValue extends AbstractObservableValue { + + /** + * The observed CLabel + */ + protected CLabel label; + + /** + * The current value + */ + protected Object currentValue; + + /** + * The LabelProvider used to define the CLabel's text and image, + * based on the current value + */ + protected ILabelProvider labelProvider; + + /** + * If the CLabel may represent more than one value, + * use an AggregatedObservable + * + * May be null + */ + protected AggregatedObservable aggregated; + + /** + * Constructor + * + * @param label + * The observed CLabel + * @param modelObservable + * The Model IObservable + */ + public CLabelObservableValue(CLabel label, IObservableValue modelObservable) { + this(label, modelObservable, null); + } + + /** + * Constructor + * + * @param label + * The observed CLabel + * @param modelObservable + * The Model IObservable + * @param labelProvider + * The LabelProvider used to define the CLabel's text/image from the current value + */ + public CLabelObservableValue(CLabel label, IObservableValue modelObservable, ILabelProvider labelProvider) { + this.label = label; + setLabelProvider(labelProvider); + if (modelObservable instanceof AggregatedObservable) { + this.aggregated = (AggregatedObservable) modelObservable; + } + } + + /** + * @param labelProvider + * The LabelProvider used to define the CLabel's text and image, + * based on the current value + */ + public void setLabelProvider(ILabelProvider labelProvider) { + if (labelProvider != null) { + this.labelProvider = labelProvider; + } else { + this.labelProvider = new LabelProvider(); + } + } + + @Override + public Object getValueType() { + return Object.class; + } + + @Override + protected Object doGetValue() { + return currentValue; + } + + @Override + protected void doSetValue(Object value) { + this.currentValue = value; + if (aggregated != null && aggregated.hasDifferentValues()) { + label.setText(Messages.ReferenceDialogObservable_Unchanged); + label.setImage(null); + } else if (currentValue == null) { + label.setText(Messages.ReferenceDialog_Unset); + label.setImage(null); + } else { + label.setText(labelProvider.getText(value)); + label.setImage(labelProvider.getImage(value)); + } + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/ComboObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/ComboObservableValue.java new file mode 100644 index 00000000000..4b6821538bd --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/ComboObservableValue.java @@ -0,0 +1,135 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.databinding; + +import org.eclipse.core.databinding.observable.value.AbstractObservableValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.ValueDiff; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable; +import org.eclipse.papyrus.infra.widgets.providers.ComboLabelProvider; +import org.eclipse.papyrus.infra.widgets.providers.UnchangedObject; +import org.eclipse.papyrus.infra.widgets.providers.UnsetObject; + +/** + * An ObservableValue for a ComboViewer, with support for AggregatedObservable + * + * @author Camille Letavernier + */ +public class ComboObservableValue extends AbstractObservableValue implements ISelectionChangedListener { + + /** + * The Observed ComboViewer + */ + protected ComboViewer viewer; + + /** + * The current value + */ + protected Object currentValue; + + /** + * If the Combo may represent more than one value, + * use an AggregatedObservable + * + * May be null + */ + protected AggregatedObservable modelProperty; + + /** + * + * @param viewer + * The observed ComboViewer + * @param modelProperty + * The Model IObservable + */ + public ComboObservableValue(ComboViewer viewer, IObservableValue modelProperty) { + this.viewer = viewer; + viewer.setLabelProvider(new ComboLabelProvider(viewer.getLabelProvider())); + if (modelProperty instanceof AggregatedObservable) { + this.modelProperty = (AggregatedObservable) modelProperty; + } + viewer.addSelectionChangedListener(this); + } + + @Override + public Object getValueType() { + return Object.class; + } + + @Override + protected Object doGetValue() { + ISelection selection = viewer.getSelection(); + if (!selection.isEmpty() && selection instanceof IStructuredSelection) { + IStructuredSelection structuredSelection = (IStructuredSelection) selection; + Object firstElement = structuredSelection.getFirstElement(); + if (firstElement == UnsetObject.instance) { + return null; + } + if (firstElement == UnchangedObject.instance) { + return null; + } + return firstElement; + } + + return null; + } + + @Override + protected void doSetValue(Object value) { + currentValue = value; + + if (modelProperty != null && modelProperty.hasDifferentValues()) { + viewer.setSelection(new StructuredSelection(UnchangedObject.instance)); + } else if (value == null) { + viewer.setSelection(new StructuredSelection(UnsetObject.instance)); + } else { + viewer.setSelection(new StructuredSelection(value)); + } + } + + @Override + public synchronized void dispose() { + viewer.removeSelectionChangedListener(this); + super.dispose(); + } + + @Override + public void selectionChanged(SelectionChangedEvent event) { + if (((IStructuredSelection) event.getSelection()).getFirstElement() != UnchangedObject.instance) { + + final Object oldValue = currentValue; + final Object newValue = doGetValue(); + currentValue = newValue; + + fireValueChange(new ValueDiff() { + + @Override + public Object getOldValue() { + return oldValue; + } + + @Override + public Object getNewValue() { + return newValue; + } + + }); + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CompletionStyledTextMultiReferenceDialogObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CompletionStyledTextMultiReferenceDialogObservableValue.java new file mode 100644 index 00000000000..33e481ba136 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CompletionStyledTextMultiReferenceDialogObservableValue.java @@ -0,0 +1,86 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.databinding; + +import java.util.Collection; + +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Control; + +/** + * @author Vincent Lorenzo + * + */ +public class CompletionStyledTextMultiReferenceDialogObservableValue extends CompletionStyledTextObservableValue { + + /** + * the styled text with completion reference dialog + */ + private Control referenceDialog; + + /** + * the IObservable list + */ + private IObservableList list; + + /** + * @param dialog + * The observed StyledTextReferenceDialog + * @param styledText + * The observed StyledText + * @param modelObservable + * The Model IObservable + * @param eventType + * The eventType to listen to. When the event is fired by the Text + * widget, this IObservableValue will fire a ChangeEvent + */ + public CompletionStyledTextMultiReferenceDialogObservableValue(Control dialog, StyledText styledText, IObservableList modelObservable, int eventType) { + super(styledText, null, eventType); + this.referenceDialog = dialog; + list = modelObservable; + } + + + /** + * + * @see org.eclipse.papyrus.infra.widgets.databinding.StyledTextObservableValue#doSetValue(java.lang.Object) + * + * @param value + */ + @Override + protected void doSetValue(Object value) { + super.doSetValue(value); + referenceDialog.update(); + } + + /** + * @see org.eclipse.papyrus.infra.widgets.databinding.CompletionStyledTextObservableValue#doGetValue() + * + * @return + */ + @Override + protected Object doGetValue() { + Object newValues = super.doGetValue(); + if (newValues instanceof Collection<?>) { + if (!list.equals(newValues)) { + list.clear(); + list.addAll((Collection<?>) newValues); + } + }else if(newValues==null){ + list.clear(); + } + return newValues; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CompletionStyledTextObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CompletionStyledTextObservableValue.java new file mode 100644 index 00000000000..7a6eb78f706 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CompletionStyledTextObservableValue.java @@ -0,0 +1,121 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.databinding; + +import java.util.List; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.ValueDiff; +import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter; +import org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Event; + +public class CompletionStyledTextObservableValue extends StyledTextObservableValue implements ISetPapyrusConverter { + + /** + * The name resolution helper shared with the widget + */ + protected IPapyrusConverter parser; + + /** + * + * Constructor. + * + * @param text + * @param modelProperty + * @param eventType + */ + public CompletionStyledTextObservableValue(StyledText text, IObservableValue modelProperty, int eventType) { + super(text, modelProperty, eventType); + + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.databinding.StyledTextObservableValue#doSetValue(java.lang.Object) + * + * @param value + */ + @Override + protected void doSetValue(Object value) { + String editValue = parser.canonicalToEditValue(value, 0); + if (editValue instanceof String) { + super.doSetValue(editValue); + } else { + super.doSetValue(value); + } + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.databinding.StyledTextObservableValue#doGetValue() + * + * @return² + */ + @Override + protected Object doGetValue() { + Object newValue = super.doGetValue(); + if (newValue instanceof String) { + if (IPapyrusConverter.UNDEFINED_VALUE.equals(newValue)) { + return null; + } + Object result = this.parser.editToCanonicalValue((String) newValue, 0); + return result; + } + return null; + } + + /** + * @see org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter#setPapyrusConverter(org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter) + * + * @param parser + */ + @Override + public void setPapyrusConverter(IPapyrusConverter parser) { + this.parser = parser; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) + */ + @Override + public void handleEvent(final Event event) { + + final Object oldValue = currentValue; + final Object newValue = getValue(); + // if (newValue == null) { + // return; + // } + currentValue = newValue; + + if ((eventType & event.type) != 0) { + fireValueChange(new ValueDiff() { + + @Override + public Object getOldValue() { + return oldValue; + } + + @Override + public Object getNewValue() { + return newValue; + } + + }); + } + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CompletionStyledTextReferenceDialogObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CompletionStyledTextReferenceDialogObservableValue.java new file mode 100644 index 00000000000..ef22a7ba233 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/CompletionStyledTextReferenceDialogObservableValue.java @@ -0,0 +1,68 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.databinding; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.papyrus.infra.widgets.editors.CompletionStyledTextReferenceDialog; +import org.eclipse.swt.custom.StyledText; + +/** + * @author VL222926 + * + */ +public class CompletionStyledTextReferenceDialogObservableValue extends CompletionStyledTextObservableValue { + + /** + * the styled text with completion reference dialog + */ + private CompletionStyledTextReferenceDialog referenceDialog; + + /** + * @param dialog + * The observed StyledTextReferenceDialog + * @param styledText + * The observed StyledText + * @param modelObservable + * The Model IObservable + * @param eventType + * The eventType to listen to. When the event is fired by the Text + * widget, this IObservableValue will fire a ChangeEvent + */ + public CompletionStyledTextReferenceDialogObservableValue(CompletionStyledTextReferenceDialog dialog, StyledText styledText, IObservableValue modelObservable, int eventType) { + super(styledText, modelObservable, eventType); + this.referenceDialog = dialog; + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.databinding.StyledTextObservableValue#doSetValue(java.lang.Object) + * + * @param value + */ + @Override + protected void doSetValue(Object value) { + super.doSetValue(value); + referenceDialog.update(); + } + + /** + * @see org.eclipse.papyrus.infra.widgets.databinding.CompletionStyledTextObservableValue#doGetValue() + * + * @return + */ + @Override + protected Object doGetValue() { + return super.doGetValue(); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/GrayedCheckboxObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/GrayedCheckboxObservableValue.java new file mode 100644 index 00000000000..2e40f91e770 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/GrayedCheckboxObservableValue.java @@ -0,0 +1,114 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.databinding; + +import org.eclipse.core.databinding.observable.value.AbstractObservableValue; +import org.eclipse.core.databinding.observable.value.ValueDiff; +import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; + +/** + * An ObservableValue for {@link Button}s with the {@link SWT.CHECK} style + * Allows the checkbox to take four states ; one for each possible combination + * of {@link Button#getSelection()} and {@link Button#getGrayed()} + * + * @author Camille Letavernier + */ +public class GrayedCheckboxObservableValue extends AbstractObservableValue implements SelectionListener { + + private Button checkbox; + + private Boolean currentValue; + + private AggregatedObservable aggregated; + + /** + * Constructor + * + * @param checkbox + * The observed checkbox + * @param aggregated + * The Observable aggregating the various observable booleans + */ + public GrayedCheckboxObservableValue(Button checkbox, AggregatedObservable aggregated) { + this.checkbox = checkbox; + this.checkbox.addSelectionListener(this); + this.aggregated = aggregated; + } + + @Override + public Object getValueType() { + return Object.class; // Can be either Boolean or BooleanWithDefaultState + } + + @Override + protected Boolean doGetValue() { + return checkbox.getSelection(); + } + + @Override + protected void doSetValue(Object value) { + if (aggregated.hasDifferentValues()) { + checkbox.setSelection(true); + checkbox.setGrayed(true); + return; + } else { + checkbox.setGrayed(false); + } + + if (value instanceof Boolean) { + Boolean booleanValue = (Boolean) value; + checkbox.setSelection(booleanValue); + + this.currentValue = booleanValue; + } else if (value == null) { + checkbox.setSelection(false); + } + } + + @Override + public synchronized void dispose() { + checkbox.removeSelectionListener(this); + super.dispose(); + } + + @Override + public void widgetSelected(SelectionEvent e) { + final Boolean oldValue = currentValue; + final Boolean newValue = checkbox.getSelection(); + + currentValue = newValue; + checkbox.setGrayed(false); + + fireValueChange(new ValueDiff() { + + @Override + public Object getOldValue() { + return oldValue; + } + + @Override + public Object getNewValue() { + return newValue; + } + }); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/ReferenceDialogObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/ReferenceDialogObservableValue.java new file mode 100644 index 00000000000..21c70b3f2d3 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/ReferenceDialogObservableValue.java @@ -0,0 +1,63 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.databinding; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.editors.ReferenceDialog; +import org.eclipse.swt.custom.CLabel; + + +/** + * An ObservableValue for ReferenceDialog widget (Which displays + * the current value with a CLabel) + * + * @author Camille Letavernier + */ +public class ReferenceDialogObservableValue extends CLabelObservableValue { + + private ReferenceDialog referenceDialog; + + /** + * @param dialog + * The observed ReferenceDialog + * @param label + * The observed CLabel (Should correspond to dialog#currentValueLabel) + * @param modelObservable + * The Model IObservable + */ + public ReferenceDialogObservableValue(ReferenceDialog dialog, CLabel label, IObservableValue modelObservable) { + this(dialog, label, modelObservable, null); + } + + /** + * @param dialog + * The observed ReferenceDialog + * @param label + * The observed CLabel (Should correspond to dialog#currentValueLabel) + * @param modelObservable + * The Model IObservable + * @param labelProvider + * The LabelProvider used to define the CLabel's text/image from the current value + */ + public ReferenceDialogObservableValue(ReferenceDialog dialog, CLabel label, IObservableValue modelObservable, ILabelProvider labelProvider) { + super(label, modelObservable, labelProvider); + this.referenceDialog = dialog; + } + + @Override + protected void doSetValue(Object value) { + super.doSetValue(value); + referenceDialog.update(); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/StyledTextObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/StyledTextObservableValue.java new file mode 100644 index 00000000000..19ab83c7351 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/StyledTextObservableValue.java @@ -0,0 +1,152 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.databinding; + +import org.eclipse.core.databinding.observable.value.AbstractObservableValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.ValueDiff; +import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable; +import org.eclipse.papyrus.infra.widgets.providers.UnchangedObject; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; + +/** + * An ObservableValue for StyledText field, with support for AggregatedObservable + * + * @author Vincent Lorenzo + */ +public class StyledTextObservableValue extends AbstractObservableValue implements Listener { + + /** + * The styled text. + */ + protected StyledText text; + + /** + * The event type used by the styled text. + */ + protected int eventType; + + /** + * The current value. + */ + protected Object currentValue; + + /** + * If the Text field may represent more than one value, + * use an AggregatedObservable. + * + * May be null. + */ + protected AggregatedObservable modelProperty; + + /** + * Constructor + * + * @param text + * The Text field to observe + * @param modelProperty + * The model IObservableValue + * @param eventType + * The eventType to listen to. When the event is fired by the Text + * widget, this IObservableValue will fire a ChangeEvent + */ + public StyledTextObservableValue(final StyledText text, final IObservableValue modelProperty, final int eventType) { + this.text = text; + this.eventType = eventType; + if (modelProperty instanceof AggregatedObservable) { + this.modelProperty = (AggregatedObservable) modelProperty; + } + this.text.addListener(eventType, this); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.core.databinding.observable.value.IObservableValue#getValueType() + */ + @Override + public Object getValueType() { + return String.class; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#doGetValue() + */ + @Override + protected Object doGetValue() { + if (UnchangedObject.instance.toString().equals(text.getText())) { + return null; + } else { + return text.getText(); + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#doSetValue(java.lang.Object) + */ + @Override + protected void doSetValue(final Object value) { + if (modelProperty != null && modelProperty.hasDifferentValues()) { + this.text.setText(UnchangedObject.instance.toString()); + this.currentValue = UnchangedObject.instance; + } else { + if (value instanceof String) { + this.text.setText((String) value); + this.currentValue = value; + } else if (value == null) { + this.text.setText(""); //$NON-NLS-1$ + this.currentValue = null; + } + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) + */ + @Override + public void handleEvent(final Event event) { + + final Object oldValue = currentValue; + final Object newValue = getValue(); + if (newValue == null) { + return; + } + currentValue = newValue; + + if ((eventType & event.type) != 0) { + fireValueChange(new ValueDiff() { + + @Override + public Object getOldValue() { + return oldValue; + } + + @Override + public Object getNewValue() { + return newValue; + } + + }); + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/StyledTextReferenceDialogObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/StyledTextReferenceDialogObservableValue.java new file mode 100644 index 00000000000..eb77f7e30d1 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/StyledTextReferenceDialogObservableValue.java @@ -0,0 +1,91 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST. + * + * 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: + * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue@all4tec.net - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.databinding; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.papyrus.infra.widgets.editors.AbstractValueEditor; +import org.eclipse.papyrus.infra.widgets.providers.UnchangedObject; +import org.eclipse.swt.custom.StyledText; + +/** + * An ObservableValue for ReferenceDialog widget (Which displays + * the current value with a CLabel) + */ +public class StyledTextReferenceDialogObservableValue extends StyledTextObservableValue { + + /** + * The value editor. + */ + private AbstractValueEditor referenceDialog; + + /** + * The label provider used to get the text value. + */ + private ILabelProvider labelProvider; + + /** + * @param dialog + * The observed StyledTextReferenceDialog + * @param styledText + * The observed StyledText + * @param modelObservable + * The Model IObservable + * @param eventType + * The eventType to listen to. When the event is fired by the Text + * widget, this IObservableValue will fire a ChangeEvent + * @param labelProvider + * The label provider + */ + public StyledTextReferenceDialogObservableValue(final AbstractValueEditor dialog, final StyledText styledText, final IObservableValue modelObservable, final int eventType, final ILabelProvider labelProvider) { + super(styledText, modelObservable, eventType); + this.referenceDialog = dialog; + this.labelProvider = labelProvider; + } + + /** + * Set the label provider. + * + * @param labelProvider + * The LabelProvider used to define the CLabel's text and image, + * based on the current value + */ + public void setLabelProvider(ILabelProvider labelProvider) { + if (labelProvider != null) { + this.labelProvider = labelProvider; + } else { + this.labelProvider = new LabelProvider(); + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.databinding.StyledTextObservableValue#doSetValue(java.lang.Object) + */ + @Override + protected void doSetValue(final Object value) { + if (null != modelProperty && modelProperty.hasDifferentValues()) { + this.text.setText(UnchangedObject.instance.toString()); + this.currentValue = UnchangedObject.instance; + } else if (value instanceof String) { + this.text.setText((String) value); + this.currentValue = value; + } else { + this.text.setText(labelProvider.getText(value)); + this.currentValue = value; + } + referenceDialog.update(); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/TextObservableValue.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/TextObservableValue.java new file mode 100644 index 00000000000..823931e278b --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/databinding/TextObservableValue.java @@ -0,0 +1,118 @@ +package org.eclipse.papyrus.infra.widgets.databinding; + +import org.eclipse.core.databinding.observable.value.AbstractObservableValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.ValueDiff; +import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable; +import org.eclipse.papyrus.infra.widgets.providers.UnchangedObject; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + + +/** + * An ObservableValue for Text field, with support for AggregatedObservable + * + * @author Camille Letavernier + */ +public class TextObservableValue extends AbstractObservableValue implements Listener { + + private Text text; + + private int eventType; + + private Object currentValue; + + /** + * If the Text field may represent more than one value, + * use an AggregatedObservable + * + * May be null + */ + protected AggregatedObservable modelProperty; + + /** + * Constructor + * + * @param text + * The Text field to observe + * @param modelProperty + * The model IObservableValue + * @param eventType + * The eventType to listen to. When the event is fired by the Text + * widget, this IObservableValue will fire a ChangeEvent + */ + public TextObservableValue(Text text, IObservableValue modelProperty, int eventType) { + this.text = text; + this.eventType = eventType; + if (modelProperty instanceof AggregatedObservable) { + this.modelProperty = (AggregatedObservable) modelProperty; + } + this.text.addListener(eventType, this); + } + + @Override + public Object getValueType() { + return String.class; + } + + @Override + protected Object doGetValue() { + if (this.text == null || this.text.isDisposed()) { + return null; + } + + if (UnchangedObject.instance.toString().equals(text.getText())) { + return null; + } else { + return text.getText(); + } + } + + @Override + protected void doSetValue(Object value) { + if (modelProperty != null && modelProperty.hasDifferentValues()) { + this.text.setText(UnchangedObject.instance.toString()); + this.currentValue = UnchangedObject.instance; + } else { + if (value instanceof String) { + this.text.setText((String) value); + this.currentValue = value; + } else if (value == null) { + this.text.setText(""); //$NON-NLS-1$ + this.currentValue = null; + } + } + } + + @Override + public void handleEvent(Event event) { + if (this.text == null || this.text.isDisposed()) { + return; + } + + final Object oldValue = currentValue; + final Object newValue = getValue(); + if (newValue == null) { + return; + } + currentValue = newValue; + + if ((eventType & event.type) != 0) { + fireValueChange(new ValueDiff() { + + @Override + public Object getOldValue() { + return oldValue; + } + + @Override + public Object getNewValue() { + return newValue; + } + + }); + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractEditor.java new file mode 100644 index 00000000000..badc5aa8d51 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractEditor.java @@ -0,0 +1,509 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + * Christian W. Damus (CEA) - bug 402525 + * Christian W. Damus (CEA) - bug 435420 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.core.databinding.Binding; +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.Platform; +import org.eclipse.papyrus.infra.widgets.creation.IAtomicOperationExecutor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory; + +/** + * An Abstract class to represent Editors. + * An editor is a Composite, containing a label and one + * or more controls. The label may be null. + * The controls are specified by the implementations + * of this abstract class. + * + * @author Camille Letavernier + */ +// FIXME: The composite widget hides access to the encapsulated widget(s). +// Thus, it is not possible to add custom listeners on the editors +// We should forward the listeners to the encapsulated (this.addListener(int, Listener) -> getMainWidget().addListener(int, Listener)) +// Problem: some widgets have more than one "main widget" (e.g. EnumRadio). +public abstract class AbstractEditor extends Composite implements DisposeListener { + + /** + * The label for this editor. May be null. + */ + protected Label label; + + /** + * The label value for this editor + */ + protected String labelText; + + /** + * The set of elements listening on changes from this editor + */ + protected Set<ICommitListener> commitListeners = new LinkedHashSet<ICommitListener>(); + + /** + * The binding between the model object and the widget + */ + protected Binding binding; + + /** + * The toolTipText associated to this editor + */ + protected String toolTipText; + + protected DataBindingContext dbc; + + /** + * The factory for creating all the editors with a common style + */ + public static final TabbedPropertySheetWidgetFactory factory = new TabbedPropertySheetWidgetFactory(); + + static { + factory.setBackground(null); + factory.setBorderStyle(SWT.BORDER); // This seems to be used only by the FormToolKit factory, we still need to force it for the CLabel or CCombo widgets + } + + /** + * + * Constructor. Constructs an editor without a label + * + * @param parent + * The composite in which this editor should be created + */ + protected AbstractEditor(Composite parent) { + this(parent, SWT.NONE, null); + } + + /** + * + * Constructor. Constructs an editor without a label + * + * @param parent + * The composite in which this editor should be created + * @param style + * The style of this editor's main composite + */ + protected AbstractEditor(Composite parent, int style) { + this(parent, style, null); + } + + /** + * + * Constructor. Constructs an editor with a label + * + * @param parent + * The composite in which this editor should be created + * @param label + * The label that will be displayed for this editor, or null + * if no label should be displayed + */ + protected AbstractEditor(Composite parent, String label) { + this(parent, SWT.NONE, label); + } + + /** + * + * Constructor. Constructs an editor with a label + * + * @param parent + * The composite in which this editor should be created + * @param style + * The style of this editor's main composite + * @param label + * The label that will be displayed for this editor, or null + * if no label should be displayed + */ + protected AbstractEditor(Composite parent, int style, String label) { + super(parent, style); + GridLayout layout = new GridLayout(1, false); + setLayout(layout); + if (label != null) { + createLabel(label); + } + parent.addDisposeListener(this); + } + + /** + * Creates the label widget with the given text + * + * @param text + * The text to be displayed on the label + */ + protected void createLabel(String text) { + label = factory.createLabel(this, text); + label.setLayoutData(getLabelLayoutData()); + if (toolTipText != null) { + label.setToolTipText(toolTipText); + } + ((GridLayout) getLayout()).numColumns++; + } + + /** + * @return The default layoutData for the label + */ + protected GridData getLabelLayoutData() { + GridData data = new GridData(); + data.widthHint = 120; + data.verticalAlignment = SWT.CENTER; + return data; + } + + /** + * This method should be called by subclasses to get the default layoutData + * for a control in this editor. + * + * @return The default layoutData for the main control + */ + protected GridData getDefaultLayoutData() { + GridData data = new GridData(SWT.FILL, SWT.BEGINNING, true, false); + return data; + } + + /** + * Changes the text label for this editor. This method is available + * only when the editor has been constructed with a label. + * + * @param label + * The new text for this editor's label + */ + public void setLabel(String label) { + this.labelText = label; + + if (this.label != null) { + this.label.setText(label); + } else { + createLabel(label); + this.label.moveAbove(getChildren()[0]); + } + } + + /** + * Show or delete the Label Widget. + * + * @param displayLabel + */ + public void setDisplayLabel(boolean displayLabel) { + if (displayLabel) { + setLabel(labelText); + } else { + if (this.label != null) { + this.label.dispose(); + ((GridLayout) getLayout()).numColumns--; + } + } + } + + /** + * Adds a commit listener to this editor. A Commit event is + * fired when a modification occurs on this editor. + * + * @param listener + * The commit listener to add to this editor + */ + public void addCommitListener(ICommitListener listener) { + commitListeners.add(listener); + } + + /** + * Removes a commit listener from this editor. + * + * @param listener + * The commit listener to remove from this editor + */ + public void removeCommitListener(ICommitListener listener) { + commitListeners.remove(listener); + } + + /** + * Informs the commit listeners that a modification occured + */ + protected void commit() { + for (ICommitListener listener : commitListeners) { + listener.commit(this); + + } + + + } + + /** + * Gets the BindingContext associated to the editors + * + * @return + */ + protected DataBindingContext getBindingContext() { + if (dbc == null) { + dbc = new DataBindingContext(); + } + return dbc; + } + + + /** + * Sets the converters to convert data from Model to Target (Widget), + * and from Widget to Model + * + * @param targetToModel + * @param modelToTarget + */ + abstract public void setConverters(IConverter targetToModel, IConverter modelToTarget); + + + /** + * Binds the Widget Observable to the Model observable property, + * using the specified converters when available + */ + abstract protected void doBinding(); + + /** + * @return the type of objects that this widget can edit + */ + public abstract Object getEditableType(); + + /** + * Marks this editor as being read-only. The value of a read-only + * editor cannot be changed by the editor itself. + * + * @param readOnly + */ + public abstract void setReadOnly(boolean readOnly); + + /** + * Tests whether this editor is read-only or not + * + * @return + * True if the editor is read-only + */ + public abstract boolean isReadOnly(); + + /** + * Indicates that this editor should notify its commit listeners + * when the given control looses the Focus + * + * @param control + * The control on which a FocusListener should be added, + * to notify the CommitListeners + */ + protected void setCommitOnFocusLost(Control control) { + control.addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + commit(); + } + + }); + } + + /** + * Forces the refresh of the widget's value + */ + public void refreshValue() { + if (binding != null) { + binding.updateModelToTarget(); + } + + } + + public void refreshModel() { + if (binding != null) { + binding.updateTargetToModel(); + } + + } + + /** + * Sets the given toolTip to the label + * + * @param text + * The new label's tooltip + */ + protected void setLabelToolTipText(String text) { + toolTipText = text; + if (label != null && !label.isDisposed()) { + label.setToolTipText(text); + } + } + + /** + * Excludes or includes the given control from the layout + * + * @param control + * The control to exclude or include + * @param exclude + * If true, the control will be excluded ; otherwise, it will be included + */ + protected void setExclusion(Control control, boolean exclude) { + if (control.getLayoutData() == null) { + GridData data = new GridData(); + control.setLayoutData(data); + } + + GridData data = (GridData) control.getLayoutData(); + + if (data.exclude != exclude) { + data.exclude = exclude; + GridLayout layout = (GridLayout) control.getParent().getLayout(); + if (exclude) { + layout.numColumns--; + } else { + layout.numColumns++; + } + } + } + + + @Override + public void widgetDisposed(DisposeEvent e) { + dispose(); + } + + public void changeColorField() { + + } + + + /** + * Obtains the most appropriate operation executor for the object being edited. + * + * @param context + * the object being edited + * @return the executor to use to run operations (never {@code null}) + */ + public IAtomicOperationExecutor getOperationExecutor(Object context) { + IAtomicOperationExecutor result; + if (context instanceof IAdaptable) { + result = ((IAdaptable) context).getAdapter(IAtomicOperationExecutor.class); + } else if (context != null) { + result = Platform.getAdapterManager().getAdapter(context, IAtomicOperationExecutor.class); + } else { + // We can't adapt null, of course, so we will have to settle for the default executor + result = null; + } + + if (result == null) { + result = IAtomicOperationExecutor.DEFAULT; + } + + return result; + } + + /** + * A hook to call when a control is accepting a focus that is sensitive to glitches in focus management + * on the current SWT platform. + * + * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=435420">bug 435420</a> + */ + protected final void acceptingFocus() { + // On SWT/Cocoa, veto attempts to give focus to any other control for the current event-loop iteration + FocusVeto.vetoFocus(this); + } + + /** + * Queries the model element that I edit. + * + * @return the contextual model element + */ + protected abstract Object getContextElement(); + + // + // Nested types + // + + /** + * A utility that implements a bug in the SWT implementation on Cocoa, in which responder-chain management + * while a {@link CCombo} is trying to accept focus in a Property Sheet that currently does not have focus + * results in the text contents of some unrelated {@link Text} widget being presented in the {@code CCombo}'s + * text field. + * + * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=435420">bug 435420</a> + */ + static class FocusVeto { + + // Only engage this work-around on the Cocoa implementation of SWT because it actually results in + // editable CCombos not getting keyboard focus when initially clicked if the Property Sheet is not + // yet active + private static final boolean IS_SWT_COCOA = Platform.WS_COCOA.equals(Platform.getWS()); + + private final Control focusControl; + + private FocusVeto(Control focusControl) { + this.focusControl = focusControl; + final Shell shell = focusControl.getShell(); + + focusControl.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + + removeFocusVeto(shell, FocusVeto.this); + + if (!FocusVeto.this.focusControl.isDisposed() && !FocusVeto.this.focusControl.isFocusControl()) { + FocusVeto.this.focusControl.setFocus(); + } + } + }); + } + + Control getFocusControl() { + return focusControl; + } + + static Control getFocusVetoControl(Control context) { + FocusVeto veto = IS_SWT_COCOA ? getFocusVeto(context.getShell()) : null; + return (veto == null) ? null : veto.getFocusControl(); + } + + static void vetoFocus(Control focusControl) { + if (IS_SWT_COCOA) { + Shell shell = focusControl.getShell(); + FocusVeto current = getFocusVeto(shell); + if (current == null) { + setFocusVeto(shell, new FocusVeto(focusControl)); + } + } + } + + static FocusVeto getFocusVeto(Shell shell) { + return (FocusVeto) shell.getData(FocusVeto.class.getName()); + } + + static void setFocusVeto(Shell shell, FocusVeto focusVeto) { + shell.setData(FocusVeto.class.getName(), focusVeto); + } + + static void removeFocusVeto(Shell shell, FocusVeto focusVeto) { + if (getFocusVeto(shell) == focusVeto) { + shell.setData(FocusVeto.class.getName(), null); + } + } + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractListEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractListEditor.java new file mode 100644 index 00000000000..652cfc03880 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractListEditor.java @@ -0,0 +1,155 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.UpdateListStrategy; +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.core.databinding.observable.IObserving; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.swt.widgets.Composite; + +/** + * An abstract class to represent List Editors. + * List editors are based on the Eclipse Databinding Framework + * They take {@link IObservableList}s as Input + * + * @author Camille Letavernier + * + */ +public abstract class AbstractListEditor extends AbstractEditor { + + /** + * The IObservableList associated to the model property + */ + protected IObservableList modelProperty; + + /** + * The UpdateStrategy for binding data from widget to model + */ + protected UpdateListStrategy targetToModelStrategy; + + /** + * The UpdateStrategy for binding data from model to widget + */ + protected UpdateListStrategy modelToTargetStrategy; + + /** + * The IObservableList associated to the widget + */ + protected IObservableList widgetObservable; + + protected AbstractListEditor(Composite parent) { + super(parent); + } + + protected AbstractListEditor(Composite parent, int style, String label) { + super(parent, style, label); + } + + protected AbstractListEditor(Composite parent, int style) { + super(parent, style); + } + + protected AbstractListEditor(Composite parent, String label) { + super(parent, label); + } + + /** + * Sets this editor's IObservableList associated to the widget property + * + * @param widgetObservable + * @param targetToModel + * the IConverter to convert data from Widget to Model + * @param modelToTarget + * the IConverter to convert data from Model to Widget + */ + protected void setWidgetObservable(IObservableList widgetObservable, IConverter targetToModel, IConverter modelToTarget) { + this.widgetObservable = widgetObservable; + setConverters(targetToModel, modelToTarget); + } + + /** + * Sets this editor's IObservableList associated to the widget property + * + * @param widgetObservable + */ + protected void setWidgetObservable(IObservableList widgetObservable) { + this.widgetObservable = widgetObservable; + } + + /** + * Sets this editor's IObservableList associated to the model property, + * and binds it to the Editor's Widget + * + * @param modelProperty + */ + public void setModelObservable(IObservableList modelProperty) { + this.modelProperty = modelProperty; + doBinding(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setConverters(IConverter targetToModel, IConverter modelToTarget) { + if (targetToModelStrategy == null) { + targetToModelStrategy = new UpdateListStrategy(); + } + if (modelToTargetStrategy == null) { + modelToTargetStrategy = new UpdateListStrategy(); + } + + targetToModelStrategy.setConverter(targetToModel); + modelToTargetStrategy.setConverter(modelToTarget); + } + + /** + * Sets the UpdateStrategies for databinding between the widget and the model + * + * @param targetToModelStrategy + * The widget to model Update strategy + * @param modelToTargetStrategy + * The model to widget Update strategy + */ + public void setUpdateStrategies(UpdateListStrategy targetToModelStrategy, UpdateListStrategy modelToTargetStrategy) { + this.targetToModelStrategy = targetToModelStrategy; + this.modelToTargetStrategy = modelToTargetStrategy; + } + + /** + * Binds the Widget Observable to the Model observable property, + * using the specified converters or Update strategies when available + * + * When overriding this method, you should also override {@link #refreshValue()} + * + * @see org.eclipse.papyrus.infra.widgets.AbstractEditor#doBinding() + */ + @Override + protected void doBinding() { + + if (modelProperty == null || widgetObservable == null) { + return; + } + + binding = getBindingContext().bindList(widgetObservable, modelProperty, targetToModelStrategy, modelToTargetStrategy); + } + + @Override + protected Object getContextElement() { + // Our observables for features of EMF objects are expected to implement IObserving because + // the observe the value of the object's feature + return (modelProperty instanceof IObserving) ? ((IObserving) modelProperty).getObserved() : null; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractReferenceDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractReferenceDialog.java new file mode 100644 index 00000000000..70ef6df522c --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractReferenceDialog.java @@ -0,0 +1,182 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST. + * + * 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: + * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue@all4tec.net - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.widgets.Composite; + +/** + * This class allow to define a reference value editor. + */ +public abstract class AbstractReferenceDialog extends AbstractValueEditor implements IReferenceValueEditor { + + /** + * Boolean to detect direct creation. + */ + protected boolean directCreation; + + /** + * Indicates whether the widget requires a value or not. If it is mandatory, + * it cannot delete/unset its value + */ + protected boolean mandatory; + + /** + * Boolean to determinate if the editors are read-only. + */ + protected boolean readOnly; + + + /** + * Constructor. + * + * @param parent + * The parent composite. + */ + protected AbstractReferenceDialog(final Composite parent) { + super(parent); + } + + /** + * Constructor. + * + * @param parent + * The parent composite. + * @param style + * The style. + * @param label + * The label. + */ + protected AbstractReferenceDialog(final Composite parent, final int style, final String label) { + super(parent, style, label); + } + + /** + * Constructor. + * + * @param parent + * The parent composite. + * @param style + * The style. + */ + protected AbstractReferenceDialog(final Composite parent, final int style) { + super(parent, style); + } + + /** + * Constructor. + * + * @param parent + * The parent composite. + * @param label + * The label. + */ + protected AbstractReferenceDialog(final Composite parent, final String label) { + super(parent, label); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.IReferenceValueEditor#setContentProvider(org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider) + */ + @Override + public abstract void setContentProvider(final IStaticContentProvider provider); + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.IReferenceValueEditor#setLabelProvider(org.eclipse.jface.viewers.ILabelProvider) + */ + @Override + public abstract void setLabelProvider(final ILabelProvider provider); + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.IReferenceValueEditor#setValueFactory(org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory) + */ + @Override + public abstract void setValueFactory(final ReferenceValueFactory factory); + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.IReferenceValueEditor#updateControls() + */ + @Override + public abstract void updateControls(); + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.IReferenceValueEditor#setDirectCreation(boolean) + */ + @Override + public void setDirectCreation(final boolean directCreation) { + this.directCreation = directCreation; + updateControls(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.IReferenceValueEditor#setMandatory(boolean) + */ + @Override + public void setMandatory(final boolean mandatory) { + this.mandatory = mandatory; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractValueEditor#getValue() + */ + @Override + public abstract Object getValue(); + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractEditor#getEditableType() + */ + @Override + public Object getEditableType() { + return Object.class; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractEditor#setReadOnly(boolean) + */ + @Override + public void setReadOnly(final boolean readOnly) { + this.readOnly = readOnly; + updateControls(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractEditor#isReadOnly() + */ + @Override + public boolean isReadOnly() { + return readOnly; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractValueEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractValueEditor.java new file mode 100644 index 00000000000..2cbb8b44e2f --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/AbstractValueEditor.java @@ -0,0 +1,299 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + * Christian W. Damus (CEA) - bug 402525 + * Mickaël ADAM (ALL4TEC) mickael.adam@all4tec.net - bug 435415 + * Christian W. Damus (CEA) - bug 417409 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.core.databinding.observable.IObserving; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.IValueChangeListener; +import org.eclipse.core.databinding.observable.value.ValueChangeEvent; +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.papyrus.infra.widgets.validator.AbstractValidator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; + +/** + * An abstract class to represent Single-value Editors. Single-value editors are + * based on the Eclipse Databinding Framework They take {@link IObservableValue} s as Input + * + * @author Camille Letavernier + * + */ +public abstract class AbstractValueEditor extends AbstractEditor { + + /** + * The IObservableValue associated to the model property + */ + protected IObservableValue modelProperty; + + /** + * The IObservableValue associated to the widget + */ + protected IObservableValue widgetObservable; + + /** + * The UpdateStrategy for binding data from widget to model + */ + protected UpdateValueStrategy targetToModelStrategy; + + /** + * The UpdateStrategy for binding data from model to widget + */ + protected UpdateValueStrategy modelToTargetStrategy; + + /** + * the Validator for the target + */ + protected AbstractValidator targetValidator; + + /** + * the Validator for the model + */ + protected IValidator modelValidator; + + protected boolean errorBinding = false; + + protected ControlDecoration controlDecoration; + + protected static final Color VALID = new Color(Display.getCurrent(), 144, 238, 144); // CSS LightGreen + + protected static final Color DEFAULT = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE); + + protected static final Color EDIT = new Color(Display.getCurrent(), 255, 204, 153); // Orange + + protected static final Color ERROR = new Color(Display.getCurrent(), 255, 153, 153); // Red + + private boolean initialValidation; + + protected AbstractValueEditor(Composite parent) { + super(parent); + } + + protected AbstractValueEditor(Composite parent, int style, String label) { + super(parent, style, label); + } + + protected AbstractValueEditor(Composite parent, int style) { + super(parent, style); + } + + protected AbstractValueEditor(Composite parent, String label) { + super(parent, label); + } + + /** + * Sets this editor's IObservableValue associated to the widget property + * + * @param widgetObservable + * @param targetToModel + * the IConverter to convert data from Widget to Model + * @param modelToTarget + * the IConverter to convert data from Model to Widget + */ + protected void setWidgetObservable(IObservableValue widgetObservable, IConverter targetToModel, IConverter modelToTarget) { + this.widgetObservable = widgetObservable; + setConverters(targetToModel, modelToTarget); + } + + /** + * Sets this editor's widgetObservable + * + * @param widgetObservable + * The widget observable value + * @param commitOnChange + * If true, CommitListeners will be notified when the widget + * observable changes + */ + protected void setWidgetObservable(IObservableValue widgetObservable, boolean commitOnChange) { + this.widgetObservable = widgetObservable; + if (commitOnChange) { + this.widgetObservable.addChangeListener(new IChangeListener() { + + @Override + public void handleChange(ChangeEvent event) { + commit(); + } + }); + } + } + + /** + * Sets this editor's IObservableValue associated to the widget property + * + * @param widgetObservable + */ + protected void setWidgetObservable(IObservableValue widgetObservable) { + setWidgetObservable(widgetObservable, false); + } + + /** + * Sets this editor's IObservableValue associated to the model property, and + * binds it to the Editor's Widget + * + * @param modelProperty + */ + public void setModelObservable(IObservableValue modelProperty) { + this.modelProperty = modelProperty; + doBinding(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setConverters(IConverter targetToModel, IConverter modelToTarget) { + if (targetToModelStrategy == null) { + targetToModelStrategy = new UpdateValueStrategy(); + } + if (modelToTargetStrategy == null) { + modelToTargetStrategy = new UpdateValueStrategy(); + } + targetToModelStrategy.setConverter(targetToModel); + modelToTargetStrategy.setConverter(modelToTarget); + } + + /** + * Sets the UpdateStrategies for databinding between the widget and the + * model + * + * @param targetToModelStrategy + * The widget to model Update strategy + * @param modelToTargetStrategy + * The model to widget Update strategy + */ + public void setUpdateStrategies(UpdateValueStrategy targetToModelStrategy, UpdateValueStrategy modelToTargetStrategy) { + this.targetToModelStrategy = targetToModelStrategy; + this.modelToTargetStrategy = modelToTargetStrategy; + } + + /** + * Binds the Widget Observable to the Model observable property, using the + * specified converters or Update strategies when available + * + * When overriding this method, you should also override {@link #refreshValue()} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractEditor#doBinding() + */ + @Override + protected void doBinding() { + if (modelProperty == null || widgetObservable == null) { + return; + } + setBinding(); + } + + /** + * Returns the value from the widget May be used even when the Model + * Observable is not set + * + * @return The current value for this editor + */ + public abstract Object getValue(); + + /** + * Initialize binding + */ + private void setBinding() { + binding = getBindingContext().bindValue(widgetObservable, modelProperty, targetToModelStrategy, modelToTargetStrategy); + binding.getValidationStatus().addValueChangeListener(new IValueChangeListener() { + + @Override + public void handleValueChange(ValueChangeEvent event) { + // Don't handle validation changes if we don't have a validator, because then it could only be green and it isn't useful. + // Also, if we're showing in a dialog, then our widget may have been disposed already if we're validating a change applied + // by hitting the OK button + if ((modelValidator) != null) { + // Check if the widget is disposed before isReadOnly() to avoid NPE + if (!AbstractValueEditor.this.isDisposed() && !isReadOnly()) { // Bug 434787 : Shouldn't not execute the timer thread if the widget is disposed + IStatus status = (IStatus) binding.getValidationStatus().getValue(); // Bug 435415 : Update the status only if the widget isn't disposed + updateStatus(status); + + // Don't kick the colour if we're just doing the initial validation to show the decoration. + // Only trigger the colours on user-initiated edits + if (!initialValidation) { + changeColorField(); + } + } + } + } + + }); + } + + public void updateStatus(IStatus status) { + } + + /** + * Set the target to model Strategy to after get validation + * + * @param targetToModelValidator + */ + public void setTargetAfterGetValidator(AbstractValidator targetToModelValidator) { + if (targetToModelValidator != null) { + targetToModelStrategy.setAfterGetValidator(targetToModelValidator); + } + } + + /** + * Set the model strategy with After get validation + * Set the target strategy with before set validation + * + * @param modelValidator + */ + public void setModelValidator(IValidator targetToModelValidator) { + this.modelValidator = targetToModelValidator; + targetToModelStrategy.setBeforeSetValidator(targetToModelValidator); + modelToTargetStrategy.setAfterGetValidator(targetToModelValidator); + + if ((binding != null) && (this.modelValidator != null)) { + final boolean wasInitialValidation = initialValidation; + initialValidation = true; + + try { + binding.validateModelToTarget(); + } finally { + initialValidation = wasInitialValidation; + } + } + } + + /** + * Initialize both strategies with default values + */ + public void setStrategies() { + if (modelToTargetStrategy == null) { + modelToTargetStrategy = new UpdateValueStrategy(); + } + if (targetToModelStrategy == null) { + targetToModelStrategy = new UpdateValueStrategy(); + } + } + + @Override + protected Object getContextElement() { + // Our observables for features of EMF objects are expected to implement IObserving because + // the observe the value of the object's feature + return (modelProperty instanceof IObserving) ? ((IObserving) modelProperty).getObserved() : null; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanCheckbox.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanCheckbox.java new file mode 100644 index 00000000000..31298ad2376 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanCheckbox.java @@ -0,0 +1,144 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable; +import org.eclipse.papyrus.infra.widgets.databinding.GrayedCheckboxObservableValue; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +/** + * A Property Editor representing a Boolean value + * as a Checkbox. + * + * @author Camille Letavernier + */ +public class BooleanCheckbox extends AbstractValueEditor { + + private final Button checkbox; + + private AggregatedObservable aggregated; + + + /** + * + * Constructor. Creates a new Property Editor for a Boolean + * value, represented as a Checkbox. + * + * @param parent + * This editor's parent composite + * @param style + * The style applied to this editor's checkbox + */ + public BooleanCheckbox(Composite parent, int style) { + this(parent, style, null); + } + + /** + * + * Constructor. Creates a new Property Editor for a Boolean + * value, represented as a Checkbox, with the given label + * + * @param parent + * This editor's parent composite + * @param style + * The style applied to this editor's checkbox + * @param label + * The label for this editor + */ + public BooleanCheckbox(Composite parent, int style, String label) { + super(parent); + checkbox = factory.createButton(this, label, SWT.CHECK | style); + + IObservableValue widgetObservable = WidgetProperties.selection().observe(checkbox); + setWidgetObservable(widgetObservable, true); + GridData gridData = getDefaultLayoutData(); + checkbox.setLayoutData(gridData); + gridData.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + + + } + + @Override + public void setModelObservable(IObservableValue modelProperty) { + IObservableValue newWidgetObservable; + + if (this.widgetObservable != null) { + this.widgetObservable.dispose(); + } + + if (modelProperty instanceof AggregatedObservable) { + this.aggregated = (AggregatedObservable) modelProperty; + newWidgetObservable = new GrayedCheckboxObservableValue(checkbox, aggregated); + } else { + newWidgetObservable = WidgetProperties.selection().observe(checkbox); + } + setWidgetObservable(newWidgetObservable, true); + super.setModelObservable(modelProperty); + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Boolean.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Boolean getValue() { + return checkbox.getSelection(); + } + + @Override + public void setReadOnly(boolean readOnly) { + checkbox.setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return !checkbox.isEnabled(); + } + + @Override + public void setToolTipText(String text) { + checkbox.setToolTipText(text); + super.setLabelToolTipText(text); + } + + @Override + public void setLabel(String label) { + checkbox.setText(label); + } + + /** + * Sets this widget's value + * + * @param selected + * Whether the checkbox should be selected or not + */ + public void setValue(Boolean selected) { + if (modelProperty != null) { + modelProperty.setValue(selected); + } + widgetObservable.setValue(selected); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanCombo.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanCombo.java new file mode 100644 index 00000000000..4672085f927 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanCombo.java @@ -0,0 +1,144 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.jface.databinding.viewers.ViewerProperties; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.infra.widgets.providers.AbstractStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Composite; + +/** + * An editor representing a boolean value as a combo box, with + * two options (true / false) + * + * @author Camille Letavernier + * + */ +public class BooleanCombo extends AbstractValueEditor { + + private ComboViewer viewer; + + /** + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + */ + public BooleanCombo(Composite parent) { + this(parent, SWT.NONE, null); + } + + /** + * + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + * @param style + * The style of this editor's CCombo + * @param label + * This editor's label + */ + public BooleanCombo(Composite parent, int style, String label) { + super(parent, style, label); + CCombo combo = factory.createCCombo(this, style | SWT.BORDER); + combo.setBackground(new Color(combo.getDisplay(), 255, 255, 255)); + combo.setLayoutData(getDefaultLayoutData()); + combo.setEditable(false); + viewer = createComboViewer(combo); + + viewer.setContentProvider(new EncapsulatedContentProvider(new AbstractStaticContentProvider() { + + @Override + public Object[] getElements() { + return new Boolean[] { Boolean.TRUE, Boolean.FALSE }; + } + })); + + viewer.setInput(""); //$NON-NLS-1$ + + setWidgetObservable(ViewerProperties.singleSelection().observe(viewer)); + + setCommitOnFocusLost(combo); + + } + + /** + * Creates the combo viewer + * + * @param combo + * The parent combo + * @return the combo viewer. + */ + protected ComboViewer createComboViewer(CCombo combo) { + return new ComboViewer(combo); + } + + /** + * + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + * @param style + * The style of this editor's CCombo + */ + public BooleanCombo(Composite parent, int style) { + this(parent, style, null); + } + + /** + * + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + * @param label + * This editor's label + */ + public BooleanCombo(Composite parent, String label) { + this(parent, SWT.NONE, label); + } + + @Override + public Object getValue() { + return ((StructuredSelection) viewer.getSelection()).getFirstElement(); + } + + @Override + public Object getEditableType() { + return Boolean.class; + } + + @Override + public void setReadOnly(boolean readOnly) { + viewer.getCCombo().setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return !viewer.getCCombo().isEnabled(); + } + + @Override + public void setToolTipText(String text) { + viewer.getCCombo().setToolTipText(text); + super.setLabelToolTipText(text); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanRadio.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanRadio.java new file mode 100644 index 00000000000..9b9ba41f4f9 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanRadio.java @@ -0,0 +1,144 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.SelectObservableValue; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +/** + * A Property Editor representing a Boolean value + * as a Radio, with two options (true/false). + * + * @author Camille Letavernier + * + */ +public class BooleanRadio extends AbstractValueEditor { + + /** + * The "true" radio button + */ + protected Button trueRadio; + + /** + * The "false" radio button + */ + protected Button falseRadio; + + private ControlDecoration controlDecoration; + + + /** + * + * Constructor. Creates a new Property Editor for a Boolean + * value, represented by two radio buttons. + * + * @param parent + * This editor's parent composite + * @param style + * The style applied to this editor's radio buttons + */ + public BooleanRadio(Composite parent, int style) { + this(parent, style, null); + } + + /** + * + * Constructor. Creates a new Property Editor for a Boolean + * value, represented by two radio buttons. + * + * @param parent + * This editor's parent composite + * @param style + * The style applied to this editor's radio buttons + * @param label + * The label for this editor + */ + public BooleanRadio(Composite parent, int style, String label) { + super(parent, label); + + ((GridLayout) getLayout()).numColumns = 3; + + trueRadio = factory.createButton(this, "true", style | SWT.RADIO); //$NON-NLS-1$ + trueRadio.setBackground(this.getBackground()); // For Radio buttons, we need to force the color + + falseRadio = factory.createButton(this, "false", style | SWT.RADIO); //$NON-NLS-1$ + falseRadio.setBackground(this.getBackground()); // For Radio buttons, we need to force the color + + setWidgetObservable(getObservable(), true); + controlDecoration = new ControlDecoration(trueRadio, SWT.TOP | SWT.LEFT); + GridData gridData = new GridData(); + trueRadio.setLayoutData(gridData); + falseRadio.setLayoutData(gridData); + gridData.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + } + + /** + * Defines a single observable value, encapsulating the ones + * from each radio button (true / false) + * + * @return The encapsulating observable value + */ + private IObservableValue getObservable() { + IObservableValue trueObservable = WidgetProperties.selection().observe(trueRadio); + IObservableValue falseObservable = WidgetProperties.selection().observe(falseRadio); + + SelectObservableValue observable = new SelectObservableValue(); + observable.addOption(true, trueObservable); + observable.addOption(false, falseObservable); + + return observable; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Boolean.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Boolean getValue() { + return trueRadio.getSelection(); + } + + @Override + public void setReadOnly(boolean readOnly) { + trueRadio.setEnabled(!readOnly); + falseRadio.setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return !trueRadio.isEnabled() || !falseRadio.isEnabled(); + } + + @Override + public void setToolTipText(String text) { + trueRadio.setToolTipText(text); + falseRadio.setToolTipText(text); + super.setLabelToolTipText(text); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanToggle.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanToggle.java new file mode 100644 index 00000000000..64207141577 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BooleanToggle.java @@ -0,0 +1,179 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +/** + * A widget to represent boolean values as a Toggle Button. + * The Button may have either an Icon or a Text + * + * @author Camille Letavernier + * + */ +public class BooleanToggle extends AbstractValueEditor { + + private Button toggleButton; + private ControlDecoration controlDecoration; + + private BooleanToggle(Composite parent, int style, String label, Image image, String text) { + super(parent, SWT.NONE, label); + + toggleButton = factory.createButton(this, null, style | SWT.TOGGLE); + setWidgetObservable(WidgetProperties.selection().observe(toggleButton)); + setCommitOnFocusLost(toggleButton); + GridData gridData = new GridData(); + toggleButton.setLayoutData(gridData); + + toggleButton.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + commit(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + }); + + setText(text); + setImage(image); + gridData.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + + controlDecoration = new ControlDecoration(toggleButton, SWT.TOP | SWT.LEFT); + } + + public BooleanToggle(Composite parent, int style, String label, String text) { + this(parent, style, label, null, text); + } + + public BooleanToggle(Composite parent, int style, String label, Image image) { + this(parent, style, label, image, null); + } + + public BooleanToggle(Composite parent) { + this(parent, SWT.NONE, null, null, null); + } + + public BooleanToggle(Composite parent, int style) { + this(parent, style, null, null, null); + } + + /** + * Sets this button's text + * + * @param text + * The text to set to this button + */ + public void setText(String text) { + if (text != null) { + toggleButton.setText(text); + } + } + + /** + * Sets this button's image + * + * @param image + * The image to set to this button + */ + public void setImage(Image image) { + if (image != null) { + toggleButton.setImage(image); + } + } + + @Override + public Boolean getValue() { + return toggleButton.getSelection(); + } + + @Override + public Object getEditableType() { + return Boolean.class; + } + + @Override + public void setReadOnly(boolean readOnly) { + toggleButton.setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return !toggleButton.isEnabled(); + } + + @Override + public void setToolTipText(String text) { + toggleButton.setToolTipText(text); + setLabelToolTipText(text); + } + + /** + * Indicates whether this button should be selected or not + * + * @param isActive + * If true, the button will be selected + */ + public void setValue(boolean isActive) { + toggleButton.setSelection(isActive); + } + + @Override + public void updateStatus(IStatus status) { + // nothing + switch (status.getSeverity()) { + case IStatus.OK: + controlDecoration.hide(); + break; + case IStatus.WARNING: + FieldDecoration warning = FieldDecorationRegistry.getDefault() + .getFieldDecoration(FieldDecorationRegistry.DEC_WARNING); + controlDecoration.setImage(warning.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + case IStatus.ERROR: + FieldDecoration error = FieldDecorationRegistry.getDefault() + .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); + controlDecoration.setImage(error.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + default: + controlDecoration.hide(); + break; + } + } + + @Override + public void changeColorField() { + + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BrowseFileEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BrowseFileEditor.java new file mode 100644 index 00000000000..854a6e094a8 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/BrowseFileEditor.java @@ -0,0 +1,408 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * 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: + * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + + + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService; +import org.eclipse.papyrus.infra.services.labelprovider.service.impl.LabelProviderServiceImpl; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.WorkspaceContentProvider; +import org.eclipse.papyrus.infra.widgets.util.FileUtil; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; + + +/** + * Specific String editor to select a file with unique button. + * + * @author gpascual + * + */ +public class BrowseFileEditor extends StringEditor { + + /** Unique button with associated menu to choice where file will be selected. */ + private Button button = null; + + /** List of accepted file extensions. */ + private List<String> filterExtensions = new ArrayList<String>(); + + /** List of accepted names. */ + private List<String> filterNames = new ArrayList<String>(); + + /** Attribute to allow file from workspace. */ + private boolean allowWorkspace = true; + + /** Attribute to allow file from file system. */ + private boolean allowFileSystem = true; + + /** Attribute for writing rights. */ + private boolean readOnly = false; + + /** Menu of file system. */ + private MenuItem fileSystemMenuItem = null; + + /** Menu of workspace. */ + private MenuItem workspaceMenuItem = null; + + /** + * Default constructor. + * + * @param parent + * the parent + * @param style + * the style + */ + public BrowseFileEditor(Composite parent, int style) { + super(parent, style); + ((GridLayout) getLayout()).numColumns++; + button = factory.createButton(this, Messages.StringFileSelector_Browse, SWT.PUSH); + button.setLayoutData(new GridData()); + + + final Menu browseMenu = createButtonMenu(); + + + + // Display menu when user select button + button.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + browseMenu.setVisible(true); + } + }); + + } + + + /** + * Creates the button menu. + * + * @return the menu + */ + private Menu createButtonMenu() { + final Menu browseMenu = new Menu(button); + + // Add file system menu + fileSystemMenuItem = new MenuItem(browseMenu, SWT.NONE); + fileSystemMenuItem.setText("File system"); + fileSystemMenuItem.addSelectionListener(new SelectionAdapter() { + + + + @Override + public void widgetSelected(SelectionEvent e) { + File file = getFile(text.getText()); + + FileDialog dialog = new FileDialog(getShell()); + if (labelText != null) { + dialog.setText(labelText); + } + dialog.setFileName(file.getAbsolutePath()); + dialog.setFilterExtensions(filterExtensions.toArray(new String[filterExtensions.size()])); + dialog.setFilterNames(filterNames.toArray(new String[filterNames.size()])); + String result = dialog.open(); + if (result == null) { // Cancel + return; + } + setResult(result); + } + }); + + // Add workspace menu + workspaceMenuItem = new MenuItem(browseMenu, SWT.NONE); + workspaceMenuItem.setText("Workspace"); + workspaceMenuItem.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + LabelProviderService labelProviderService = new LabelProviderServiceImpl(); + try { + labelProviderService.startService(); + } catch (ServiceException ex) { + Activator.log.error(ex); + } + + ILabelProvider labelProvider = labelProviderService.getLabelProvider(); + + IFile currentFile = getIFile(text.getText()); + + TreeSelectorDialog dialog = new TreeSelectorDialog(getShell()); + if (labelText != null) { + dialog.setTitle(labelText); + } + + WorkspaceContentProvider contentProvider = new WorkspaceContentProvider(); + + if (!(filterExtensions.isEmpty() || filterNames.isEmpty())) { + // The filters have been defined + contentProvider.setExtensionFilters(new LinkedHashMap<String, String>()); // Reset the default filters + + // Use our own filters + for (int i = 0; i < Math.min(filterNames.size(), filterExtensions.size()); i++) { + contentProvider.addExtensionFilter(filterExtensions.get(i), filterNames.get(i)); + } + } + + dialog.setContentProvider(contentProvider); + dialog.setLabelProvider(labelProvider); + + + if (currentFile != null && currentFile.exists()) { + dialog.setInitialSelections(new IFile[] { currentFile }); + } + + int code = dialog.open(); + if (code == Window.OK) { + Object[] result = dialog.getResult(); + if (result.length > 0) { + Object file = result[0]; + if (file instanceof IFile) { + setResult((IFile) file); + } + } + } + } + }); + + return browseMenu; + } + + + /** + * Sets the result. + * + * @param file + * the new result + */ + protected void setResult(IFile file) { + text.setText(file.getFullPath().toString()); + notifyChange(); + } + + /** + * Sets the result. + * + * @param file + * the new result + */ + protected void setResult(File file) { + text.setText(file.getAbsolutePath()); + notifyChange(); + } + + /** + * Sets the result. + * + * @param path + * the new result + */ + protected void setResult(String path) { + text.setText(path); + notifyChange(); + } + + /** + * Gets the file. + * + * @param path + * the path + * @return the i file + */ + protected IFile getIFile(String path) { + return FileUtil.getIFile(path); + } + + /** + * Gets the file. + * + * @param path + * the path + * @return the file + */ + protected File getFile(String path) { + return FileUtil.getFile(path); + } + + /** + * Sets the filters. + * + * @param filterExtensions + * the filter extensions + * @param filterNames + * the filter names + */ + public void setFilters(String[] filterExtensions, String[] filterNames) { + if (filterExtensions.length != filterNames.length) { + // This is a simple warning. Only valid filters will be retained. + Activator.log.warn("FilterExtensions and FilterNames do not match"); + } + + setFilterNames(getFilterLabels(filterNames, filterExtensions)); + setFilterExtensions(filterExtensions); + } + + /** + * Gets the filter labels. + * + * @param filterNames + * the filter names + * @param filterExtensions + * the filter extensions + * @return the filter labels + */ + protected String[] getFilterLabels(String[] filterNames, String[] filterExtensions) { + int size = Math.min(filterNames.length, filterExtensions.length); + String[] filters = new String[size]; + for (int i = 0; i < size; i++) { + filters[i] = filterNames[i] + " (" + filterExtensions[i] + ")"; + } + return filters; + } + + /** + * Sets the filter extensions. + * + * @param filterExtensions + * the new filter extensions + */ + public void setFilterExtensions(String[] filterExtensions) { + this.filterExtensions = Arrays.asList(filterExtensions); + } + + /** + * Sets the filter names. + * + * @param filterNames + * the new filter names + */ + public void setFilterNames(String[] filterNames) { + this.filterNames = Arrays.asList(filterNames); + } + + /** + * Adds the filtered extension. + * + * @param filteredExtension + * the filtered extension + * @param filterName + * the filter name + */ + public void addFilteredExtension(String filteredExtension, String filterName) { + if (filteredExtension != null) { + if (filterName == null) { + filterName = filteredExtension; + } + + filterExtensions.add(filteredExtension); + filterNames.add(filterName); + } + } + + /** + * @see org.eclipse.papyrus.infra.widgets.editors.StringEditor#getEditableType() + * + * @return + */ + + @Override + public Object getEditableType() { + return String.class; + } + + /** + * @see org.eclipse.papyrus.infra.widgets.editors.StringEditor#setReadOnly(boolean) + * + * @param readOnly + */ + + @Override + public void setReadOnly(boolean readOnly) { + super.setReadOnly(readOnly); + this.readOnly = readOnly; + updateButtons(); + } + + /** + * Sets the allow workspace. + * + * @param allowWorkspace + * the new allow workspace + */ + public void setAllowWorkspace(boolean allowWorkspace) { + this.allowWorkspace = allowWorkspace; + updateButtons(); + } + + /** + * Sets the allow file system. + * + * @param allowFileSystem + * the new allow file system + */ + public void setAllowFileSystem(boolean allowFileSystem) { + + this.allowFileSystem = allowFileSystem; + updateButtons(); + } + + /** + * Sets the button label. + * + * @param label + * the new button label + */ + public void setButtonLabel(String label) { + button.setText(label); + } + + /** + * Gets the button label. + * + * @return the button label + */ + public String getButtonLabel() { + return button.getText(); + } + + /** + * Update buttons. + */ + private void updateButtons() { + boolean enableWorkspace = !readOnly && allowWorkspace; + boolean enableFileSystem = !readOnly && allowFileSystem; + // ((GridData)browseWorkspace.getLayoutData()).exclude = !allowWorkspace; + // ((GridData)browse.getLayoutData()).exclude = !allowFileSystem; + fileSystemMenuItem.setEnabled(enableWorkspace); + workspaceMenuItem.setEnabled(enableFileSystem); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleIntegerEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleIntegerEditor.java new file mode 100644 index 00000000000..c281c5697be --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleIntegerEditor.java @@ -0,0 +1,73 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.papyrus.infra.widgets.selectors.IntegerSelector; +import org.eclipse.swt.widgets.Composite; + +/** + * A compact editor for multivalued Integer attributes + * + * @author Camille Letavernier + * + */ +public class CompactMultipleIntegerEditor extends CompactMultipleValueEditor { + + /** + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + * @param style + * The value label's style + */ + public CompactMultipleIntegerEditor(Composite parent, int style) { + this(parent, style, true, false, DEFAULT_VALUE_SEPARATOR, null); + } + + /** + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + * @param style + * The value label's style + * @param ordered + * True if the values should be ordered + * @param unique + * True if the values should be unique + */ + public CompactMultipleIntegerEditor(Composite parent, int style, boolean ordered, boolean unique) { + this(parent, style, ordered, unique, DEFAULT_VALUE_SEPARATOR, null); + } + + /** + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + * @param style + * The value label's style + * @param ordered + * True if the values should be ordered + * @param unique + * True if the values should be unique + * @param separator + * The String used to separate the different values in the value label + * @param label + * The editor's label + */ + public CompactMultipleIntegerEditor(Composite parent, int style, boolean ordered, boolean unique, String separator, String label) { + super(parent, style, new IntegerSelector(), ordered, unique, separator, label); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleReferenceEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleReferenceEditor.java new file mode 100644 index 00000000000..25591a493b8 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleReferenceEditor.java @@ -0,0 +1,86 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.selectors.ReferenceSelector; +import org.eclipse.swt.widgets.Composite; + +/** + * A Property Editor representing a MultipleReference + * as a label with the selected values. If the list + * of values is too long, it gets truncated. + * The values can be edited via a selection dialog. + * This widget is useful when there is not much vertical space available, + * and a MultipleReferenceEditor can not be used. + * + * @author Camille Letavernier + * + */ +public class CompactMultipleReferenceEditor extends CompactMultipleValueEditor { + + /** + * The selector for the available values + */ + protected ReferenceSelector selector; + + /** + * + * Constructor. + * + * @param parent + * The widget in which this editor is created + * @param style + * The style for this editor's control + */ + public CompactMultipleReferenceEditor(Composite parent, int style) { + this(parent, style, true, false); + } + + /** + * + * Constructor. + * + * @param parent + * The widget in which this editor is created + * @param style + * The style for this editor's control + * @param ordered + * True if the multivalued property is ordered + * @param unique + * True if the multivalued property needs unique values + */ + public CompactMultipleReferenceEditor(Composite parent, int style, boolean ordered, boolean unique) { + super(parent, style, new ReferenceSelector(unique), ordered, unique); + this.selector = (ReferenceSelector) super.selector; + } + + /** + * Sets the Content and Label providers for this widget. + * + * The label provider is used in each place where the values can + * be displayed + * The content provider is used to display the items that can be selected + * + * @param contentProvider + * The content provider for this widget + * @param labelProvider + * The label provider for this widget + */ + public void setProviders(IStaticContentProvider contentProvider, ILabelProvider labelProvider) { + selector.setContentProvider(contentProvider); + selector.setLabelProvider(labelProvider); + super.setLabelProvider(labelProvider); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleStringEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleStringEditor.java new file mode 100644 index 00000000000..e9c958f2c6d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleStringEditor.java @@ -0,0 +1,73 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.papyrus.infra.widgets.selectors.StringSelector; +import org.eclipse.swt.widgets.Composite; + +/** + * A compact editor for multivalued String attributes + * + * @author Camille Letavernier + * + */ +public class CompactMultipleStringEditor extends CompactMultipleValueEditor { + + /** + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + * @param style + * The value label's style + */ + public CompactMultipleStringEditor(Composite parent, int style) { + this(parent, style, true, false, DEFAULT_VALUE_SEPARATOR, null); + } + + /** + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + * @param style + * The value label's style + * @param ordered + * True if the values should be ordered + * @param unique + * True if the values should be unique + */ + public CompactMultipleStringEditor(Composite parent, int style, boolean ordered, boolean unique) { + this(parent, style, ordered, unique, DEFAULT_VALUE_SEPARATOR, null); + } + + /** + * Constructor. + * + * @param parent + * The Composite widget in which this editor will be displayed + * @param style + * The value label's style + * @param ordered + * True if the values should be ordered + * @param unique + * True if the values should be unique + * @param separator + * The String used to separate the different values in the value label + * @param label + * The editor's label + */ + public CompactMultipleStringEditor(Composite parent, int style, boolean ordered, boolean unique, String separator, String label) { + super(parent, style, new StringSelector(), ordered, unique, separator, label); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleValueEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleValueEditor.java new file mode 100644 index 00000000000..c17a3329f04 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompactMultipleValueEditor.java @@ -0,0 +1,288 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +/** + * A Property Editor representing a multivalued property as a label with the + * selected values. If the list of values is too long, it is truncated. The + * values can be edited via a selection dialog. This widget is useful when there + * is not much vertical space available, and a MultipleValueEditor can not be + * used. + */ +public class CompactMultipleValueEditor extends AbstractListEditor implements IChangeListener, DisposeListener, SelectionListener { + + /** + * The default value separator in the value label + */ + protected static final String DEFAULT_VALUE_SEPARATOR = ", "; //$NON-NLS-1$ + + /** + * The label for displayed the selected values + */ + protected Label valueLabel; + + /** + * The button to open a dialog for editing the values + */ + protected Button edit; + + /** + * The label provider for this editor. Also used by the dialog. + */ + protected ILabelProvider labelProvider; + + /** + * The string used for separating values in the value label + */ + protected String separator; + + /** + * The Dialog displayed when adding new elements + */ + protected MultipleValueSelectorDialog dialog; + + /** + * The element selector for the dialog + */ + protected IElementSelector selector; + + /** + * + * Constructor. + * + * @param parent + * The widget in which this editor is created + * @param style + * The style for this editor's control + * @param selector + * The IElementSelector for this editor's selection dialog + */ + public CompactMultipleValueEditor(Composite parent, int style, IElementSelector selector) { + this(parent, style, selector, false, false, DEFAULT_VALUE_SEPARATOR, null); + } + + /** + * + * Constructor. + * + * @param parent + * The widget in which this editor is created + * @param style + * The style for this editor's control + * @param selector + * The element selector to be used in the selection dialog + * @param ordered + * True if the multivalued property is ordered + * @param unique + * True if the multivalued property needs unique values + */ + public CompactMultipleValueEditor(Composite parent, int style, IElementSelector selector, boolean ordered, boolean unique) { + this(parent, style, selector, ordered, unique, DEFAULT_VALUE_SEPARATOR, null); + } + + /** + * + * Constructor. + * + * @param parent + * The widget in which this editor is created + * @param style + * The style for this editor's control + * @param selector + * The element selector to be used in the selection dialog + * @param ordered + * True if the multivalued property is ordered + * @param unique + * True if the multivalued property needs unique values + * @param separator + * The string used to separate values in the display label + * @param label + * The label for this editor + */ + public CompactMultipleValueEditor(Composite parent, int style, IElementSelector selector, boolean ordered, boolean unique, String separator, String label) { + super(parent, label); + + ((GridLayout) getLayout()).numColumns = 3; + + valueLabel = factory.createLabel(this, null, style); + valueLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + edit = new Button(this, SWT.PUSH); + edit.setText("..."); //$NON-NLS-1$ + edit.addSelectionListener(this); + edit.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); + + this.selector = selector; + dialog = new MultipleValueSelectorDialog(parent.getShell(), selector, unique); + + labelProvider = new LabelProvider(); + this.separator = separator; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Collection.class; + } + + /** + * {@inheritDoc} + */ + @Override + protected void doBinding() { + // We don't do a real Databinding in this case + modelProperty.addChangeListener(this); + handleChange(null); + } + + /** + * Sets the label provider for this editor + * + * @param provider + * The label provider for this editor + */ + public void setLabelProvider(ILabelProvider provider) { + dialog.setLabelProvider(provider); + this.labelProvider = provider; + } + + /** + * Refreshes the Label when a change occurs on the ObservableList + * + * @see org.eclipse.core.databinding.observable.IChangeListener#handleChange(org.eclipse.core.databinding.observable.ChangeEvent) + * + * @param event + */ + @Override + public void handleChange(ChangeEvent event) { + if (modelProperty != null) { + + List<String> labels = new LinkedList<String>(); + for (Object element : modelProperty) { + labels.add(labelProvider.getText(element)); + } + + valueLabel.setText(createValueLabel(labels)); + } + } + + /** + * Creates the text for the value label of this editor + * + * @param labels + * The labels for each selected element + * @return The concatenated label + */ + protected String createValueLabel(List<String> labels) { + if (labels.size() == 0) { + return ""; //$NON-NLS-1$ + } + + String result = labels.get(0); + for (int i = 1; i < labels.size(); i++) { + result += separator + labels.get(i); + } + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public void dispose() { + if (modelProperty != null) { + modelProperty.removeChangeListener(this); + } + super.dispose(); + } + + /** + * {@inheritDoc} Handles the event when the edit button is pressed + */ + @Override + public void widgetSelected(SelectionEvent e) { + dialog.setContextElement(getContextElement()); + dialog.setInitialSelections(modelProperty.toArray()); + int returnCode = dialog.open(); + if (returnCode == Window.CANCEL) { + return; + } + + modelProperty.clear(); + + Object[] result = dialog.getResult(); + if (result == null) { + return; + } + + java.util.List<Object> resultElements = new LinkedList<Object>(); + for (Object r : result) { + resultElements.add(r); + } + + modelProperty.addAll(resultElements); + } + + /** + * {@inheritDoc} Ignored + */ + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + + @Override + public void setReadOnly(boolean readOnly) { + valueLabel.setEnabled(!readOnly); + edit.setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return !valueLabel.isEnabled() || !edit.isEnabled(); + } + + @Override + public void setToolTipText(String text) { + valueLabel.setToolTipText(text); + super.setLabelToolTipText(text); + } + + @Override + public void refreshValue() { + handleChange(null); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompletionStyledTextMultipleReferenceEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompletionStyledTextMultipleReferenceEditor.java new file mode 100644 index 00000000000..7103ed3b46e --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompletionStyledTextMultipleReferenceEditor.java @@ -0,0 +1,128 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.papyrus.infra.widgets.databinding.CompletionStyledTextMultiReferenceDialogObservableValue; +import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter; +import org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; + +/** + * + * + * An editor for multivalued references, with a string editor in addition. This editor should be used when + * there is enough vertical space available. If the vertical space is limited, + * CompactMultipleReferenceEditor should be used instead. + * + * @author Vincent Lorenzo + * + */ +public class CompletionStyledTextMultipleReferenceEditor extends MultipleReferenceEditor implements ISetPapyrusConverter { + + /** + * the embedded string editor + */ + private CompletionStyledTextStringEditor editor; + + /** + * the converter to use + */ + private IPapyrusConverter converter; + + /** + * + * Constructor. + * + * @param parent + * @param style + * @param ordered + * @param unique + * @param label + */ + public CompletionStyledTextMultipleReferenceEditor(Composite parent, int style, boolean ordered, boolean unique, String label) { + super(parent, style, ordered, unique, label); + addStyledTextSection(parent, style); + } + + /** + * + * Constructor. + * + * @param parent + * @param style + * @param label + */ + public CompletionStyledTextMultipleReferenceEditor(Composite parent, int style, String label) { + super(parent, style, label); + addStyledTextSection(parent, style); + } + + /** + * + * Constructor. + * + * @param parent + * @param style + */ + public CompletionStyledTextMultipleReferenceEditor(Composite parent, int style) { + super(parent, style); + addStyledTextSection(parent, style); + } + + /** + * + * @param parent + * @param style + */ + protected void addStyledTextSection(Composite parent, int style) { + editor = new CompletionStyledTextStringEditor(this, style | SWT.BORDER); + GridData treeData = new GridData(SWT.FILL, SWT.FILL, true, true); + treeData.horizontalSpan = 2; + editor.setLayoutData(treeData); + } + + + /** + * @see org.eclipse.papyrus.infra.widgets.editors.MultipleValueEditor#setModelObservable(org.eclipse.core.databinding.observable.list.IObservableList) + * + * @param modelProperty + */ + @Override + public void setModelObservable(IObservableList modelProperty) { + super.setModelObservable(modelProperty); + CompletionStyledTextMultiReferenceDialogObservableValue styledTextObservable = new CompletionStyledTextMultiReferenceDialogObservableValue(editor, editor.getText(), modelProperty, SWT.FocusOut); + styledTextObservable.setPapyrusConverter(converter); + styledTextObservable.addChangeListener(new IChangeListener() { + + @Override + public void handleChange(org.eclipse.core.databinding.observable.ChangeEvent event) { + commit(); + } + }); + editor.setValue(modelProperty); + } + + /** + * @see org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter#setPapyrusConverter(org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter) + * + * @param converter + */ + @Override + public void setPapyrusConverter(IPapyrusConverter converter) { + this.converter = converter; + this.editor.setPapyrusConverter(converter); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompletionStyledTextReferenceDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompletionStyledTextReferenceDialog.java new file mode 100644 index 00000000000..8c7847d3b0a --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompletionStyledTextReferenceDialog.java @@ -0,0 +1,82 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.papyrus.infra.widgets.databinding.CompletionStyledTextReferenceDialogObservableValue; +import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter; +import org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +/** + * @author Vincent Lorenzo + * + */ +public class CompletionStyledTextReferenceDialog extends StyledTextReferenceDialog implements ISetPapyrusConverter { + /** + * the content assist helper used for the completion + */ + protected IPapyrusConverter parser; + + /** + * + * Constructor. + * + * @param parent + * @param style + */ + public CompletionStyledTextReferenceDialog(Composite parent, int style) { + super(parent, style); + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.editors.StyledTextReferenceDialog#createStyledTextStringEditor(org.eclipse.swt.widgets.Composite, java.lang.String, int) + * + * @param parent + * @param initialValue + * @param style + * @return + */ + protected StyledTextStringEditor createStyledTextStringEditor(Composite parent, String initialValue, int style) { + StyledTextStringEditor editor = new CompletionStyledTextStringEditor(parent, style); + editor.setValue(initialValue); + return editor; + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.editors.StyledTextReferenceDialog#createWidgetObservable(org.eclipse.core.databinding.observable.value.IObservableValue) + * + * @param modelProperty + * @return + */ + protected IObservableValue createWidgetObservable(IObservableValue modelProperty) { + CompletionStyledTextReferenceDialogObservableValue val = new CompletionStyledTextReferenceDialogObservableValue(this, this.styledTextStringEditor.getText(), modelProperty, SWT.FocusOut); + val.setPapyrusConverter(parser); + return val; + } + + /** + * @see org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter#setPapyrusConverter(org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter) + * + * @param parser + */ + @Override + public void setPapyrusConverter(IPapyrusConverter parser) { + this.parser = parser; + ((CompletionStyledTextStringEditor) styledTextStringEditor).setPapyrusConverter(parser); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompletionStyledTextStringEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompletionStyledTextStringEditor.java new file mode 100644 index 00000000000..367b67aa907 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/CompletionStyledTextStringEditor.java @@ -0,0 +1,175 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Collection; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter; +import org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter; +import org.eclipse.papyrus.infra.widgets.validator.AbstractValidator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; + +/** + * @author Vincent Lorenzo + * + */ +public class CompletionStyledTextStringEditor extends StyledTextStringEditor implements ISetPapyrusConverter { + + /** + * This wrapper provides a text field with completion + */ + private StringEditorWithCompletionWrapper wrapper; + + /** + * the parser to use + */ + protected IPapyrusConverter parser; + + /** + * + * Constructor. + * + * @param parent + * @param style + * @param heighHint + * @param widthHint + */ + public CompletionStyledTextStringEditor(Composite parent, int style, int heighHint, int widthHint) { + super(parent, style, heighHint, widthHint); + createReferenceTargetValidator(); + } + + /** + * + * Constructor. + * + * @param parent + * @param style + * @param label + * @param heighHint + * @param widthHint + */ + public CompletionStyledTextStringEditor(Composite parent, int style, String label, int heighHint, int widthHint) { + super(parent, style, label, heighHint, widthHint); + createReferenceTargetValidator(); + } + + /** + * + * Constructor. + * + * @param parent + * @param style + * @param label + */ + public CompletionStyledTextStringEditor(Composite parent, int style, String label) { + super(parent, style, label); + createReferenceTargetValidator(); + } + + + + /** + * @see org.eclipse.papyrus.infra.widgets.editors.StyledTextStringEditor#setValue(java.lang.Object) + * + * @param value + */ + @Override + public void setValue(Object value) { + if (parser != null && value instanceof Collection<?>) { + String val = parser.canonicalToEditValue(value, 0); + super.setValue(val); + } else { + super.setValue(value); + } + } + + /** + * + * Constructor. + * + * @param parent + * @param style + */ + public CompletionStyledTextStringEditor(Composite parent, int style) { + super(parent, style); + createReferenceTargetValidator(); + } + + protected void notifyChange() { + + text.notifyListeners(SWT.FocusOut, new Event()); + + // added to update the status when we use the completion + if (targetValidator != null) { + IStatus status = targetValidator.validate(text.getText()); + updateStatus(status); + } + commit(); + changeColorField(); + } + + /** + * create the validator for the text field + */ + protected void createReferenceTargetValidator() { + targetValidator = new AbstractValidator() { + + @Override + public IStatus validate(Object value) { + if (parser == null) { + return Status.OK_STATUS; + } + if (value instanceof String) { + return parser.isValidEditString((String) value); + } + // not possible + return new Status(IStatus.ERROR, org.eclipse.papyrus.infra.widgets.Activator.PLUGIN_ID, "Impossible case"); //$NON-NLS-1$ + } + }; + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.editors.StyledTextStringEditor#createStyledText(org.eclipse.swt.widgets.Composite, java.lang.String, int) + * + * @param parent + * @param value + * @param style + * @return + */ + @Override + public StyledText createStyledText(Composite parent, String value, int style) { + this.wrapper = new StringEditorWithCompletionWrapper(parent, style); + return wrapper.getTextWidget(); + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter#setPapyrusConverter(org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter) + * + * @param parser + */ + public void setPapyrusConverter(IPapyrusConverter parser) { + this.parser = parser; + this.wrapper.setPapyrusConverter(parser); + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/DoubleEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/DoubleEditor.java new file mode 100644 index 00000000000..d76d447681b --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/DoubleEditor.java @@ -0,0 +1,120 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + + +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.validator.RealValidator; +import org.eclipse.swt.widgets.Composite; + + +/** + * An editor representing a float value as a text box + * + * @author Camille Letavernier + */ +public class DoubleEditor extends StringEditor { + + private IConverter targetToModelConverter; + + /** + * + * Constructs an Editor for a Double value. The widget is a Text field. + * + * @param parent + * The Composite in which the editor is created + * @param style + * The Text's style + */ + public DoubleEditor(Composite parent, int style) { + super(parent, style); + + targetValidator = new RealValidator(); + targetToModelConverter = new IConverter() { + + @Override + public Object getFromType() { + return String.class; + } + + @Override + public Object getToType() { + return Double.class; + } + + @Override + public Double convert(Object fromObject) { + if (fromObject instanceof String) { + String newString = ((String) fromObject) + .replaceAll(" ", ""); //$NON-NLS-1$ //$NON-NLS-2$ + try { + return Double.parseDouble(newString); + } catch (NumberFormatException ex) { + Activator.log.error(ex); + return null; + } + } + return null; + } + + }; + + IConverter doubleToString = new IConverter() { + + @Override + public Object getFromType() { + return Double.class; + } + + @Override + public Object getToType() { + return String.class; + } + + @Override + public Object convert(Object fromObject) { + if (fromObject instanceof Double) { + return Double.toString((Double) fromObject); + } + return ""; //$NON-NLS-1$ + } + }; + setValidateOnDelay(true); + setConverters(targetToModelConverter, doubleToString); + setTargetAfterGetValidator(targetValidator); + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Double.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Double getValue() { + try { + return (Double) targetToModelConverter.convert(super.getValue()); + } catch (Exception ex) { + Activator.log.error(ex); + return null; + } + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/EditorParentComposite.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/EditorParentComposite.java new file mode 100644 index 00000000000..515a0c110a6 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/EditorParentComposite.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + + +/** + * The top parent composite for the assembly of tabbed property sheet pages based on the XWT properties model. + * Amongst other possible services, this composite works around problems in focus management on some platforms. + */ +public class EditorParentComposite extends Composite { + + public EditorParentComposite(Composite parent, int style) { + super(parent, style); + } + + @Override + public boolean setFocus() { + Control focusVetoControl = AbstractEditor.FocusVeto.getFocusVetoControl(this); + + if (focusVetoControl != null) { + // Don't let me or another control within me take focus + return false; + } + + return super.setFocus(); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/EnumCombo.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/EnumCombo.java new file mode 100644 index 00000000000..4b22a020676 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/EnumCombo.java @@ -0,0 +1,53 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.swt.widgets.Composite; + +/** + * An editor representing an Enumeration as a Combo + * This Editor needs a ContentProvider describing the Enumerated values, + * and an optional label provider + * + * @author Camille Letavernier + */ +public class EnumCombo extends ReferenceCombo { + + /** + * + * Constructs an editor for an Enumeration. The widget is a CCombo. + * + * @param parent + * The composite is which this editor is created + * @param style + * The CCombo's style + */ + public EnumCombo(Composite parent, int style) { + super(parent, style); + } + + /** + * + * Constructs an editor for an Enumeration. The widget is a CCombo. + * + * @param parent + * The composite is which this editor is created + * @param style + * The CCombo's style + * @param label + * The editor's label + */ + public EnumCombo(Composite parent, int style, String label) { + super(parent, style, label); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/EnumRadio.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/EnumRadio.java new file mode 100644 index 00000000000..5543eaa68d3 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/EnumRadio.java @@ -0,0 +1,261 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.SelectObservableValue; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.MapLabelProvider; +import org.eclipse.papyrus.infra.widgets.providers.StaticContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** + * An editor representing an Enumeration as a list of Radio Buttons + * If there are many possible values, it is probably more judicious to use an + * EnumCombo. + * This Editor needs a ContentProvider describing the Enumerated values, + * and an optional label provider. + * + * @author Camille Letavernier + * + * @see EnumCombo + */ +public class EnumRadio extends AbstractValueEditor { + + protected IStaticContentProvider contentProvider; + + protected Composite buttonsArea; + + protected ILabelProvider labelProvider = new LabelProvider(); + + protected final Map<Button, Object> values = new HashMap<Button, Object>(); + + protected int numColumns = -1; + + private ControlDecoration controlDecoration; + + public EnumRadio(Composite parent, int style) { + this(parent, SWT.NONE, null); + } + + public EnumRadio(Composite parent, int style, String label) { + super(parent, style, label); + buttonsArea = factory.createComposite(this); + GridData gridData = getDefaultLayoutData(); + buttonsArea.setLayoutData(gridData); + GridLayout layout = new GridLayout(1, true); + layout.marginWidth = 0; + layout.marginHeight = 0; + buttonsArea.setLayout(layout); + factory.createCLabel(buttonsArea, Messages.EnumRadio_NoValue); + controlDecoration = new ControlDecoration(buttonsArea, SWT.TOP | SWT.LEFT); + gridData.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + + } + + + /** + * Sets the content provider for this editor. The Content provider should + * specify the values that can be set for this property + * + * @param contentProvider + * The Content provider returning the available values for this editor + * @param labelProvider + * The label provider returning a label for each value of the + * content provider. If null, a default label provider will be used + */ + public void setProviders(IStaticContentProvider contentProvider, ILabelProvider labelProvider) { + this.contentProvider = contentProvider; + if (labelProvider != null) { + this.labelProvider = labelProvider; + } + + disposeButtons(); + if (widgetObservable != null) { + widgetObservable.dispose(); + } + + SelectObservableValue observable = new SelectObservableValue(); + for (Object value : contentProvider.getElements()) { + Button button = factory.createButton(buttonsArea, labelProvider.getText(value), SWT.RADIO); + button.setBackground(buttonsArea.getBackground()); // For Radio buttons, we need to force the color + button.setData(value); + button.setToolTipText(toolTipText); + IObservableValue buttonObservable = WidgetProperties.selection().observe(button); + observable.addOption(value, buttonObservable); + + values.put(button, value); + } + + setWidgetObservable(observable, true); + updateLayout(); + + doBinding(); + } + + protected void disposeButtons() { + for (Control control : buttonsArea.getChildren()) { + control.dispose(); + } + if (binding != null) { + binding.dispose(); + } + values.clear(); + } + + /** + * Sets the max number of elements per line for this editor + * + * @param numColumns + * The max number of elements per line. May be -1 if there should + * be a single line of elements + */ + public void setNumColumns(int numColumns) { + this.numColumns = numColumns; + updateLayout(); + } + + private void updateLayout() { + GridLayout gridLayout = (GridLayout) buttonsArea.getLayout(); + gridLayout.numColumns = numColumns > 0 ? numColumns : values.size(); + gridLayout.makeColumnsEqualWidth = numColumns > 0; + + updateLabelLayout(); + } + + private void updateLabelLayout() { + if (label == null || label.isDisposed()) { + return; + } + + if (numColumns == -1) { + ((GridData) label.getLayoutData()).verticalAlignment = SWT.CENTER; + } else { + ((GridData) label.getLayoutData()).verticalAlignment = SWT.BEGINNING; + } + } + + @Override + protected void createLabel(String label) { + super.createLabel(label); + updateLabelLayout(); + } + + @Override + public Object getValue() { + for (Button button : values.keySet()) { + if (button.getSelection()) { + return values.get(button); + } + } + return null; + } + + @Override + public Object getEditableType() { + return Object.class; + } + + @Override + public void setReadOnly(boolean readOnly) { + for (Button button : values.keySet()) { + button.setEnabled(!readOnly); + } + buttonsArea.setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return !buttonsArea.isEnabled(); + } + + @Override + public void setToolTipText(String text) { + for (Button button : values.keySet()) { + button.setToolTipText(text); + } + super.setLabelToolTipText(text); + } + + public void setValue(Object value) { + if (modelProperty != null) { + modelProperty.setValue(value); + } + if (widgetObservable != null) { + widgetObservable.setValue(value); + } else { + for (Button button : values.keySet()) { + if (values.get(button) == value) { + button.setSelection(true); + return; + } + } + } + } + + /** + * Use a Map instead of content providers to define the selectable elements + * The keys are the semantic objects (contentProvider), and the values are + * the labels (labelProvider) + * + * @param objectsAndLabels + */ + public void setEnumValues(Map<Object, String> objectsAndLabels) { + StaticContentProvider provider = new StaticContentProvider(objectsAndLabels.keySet().toArray()); + LabelProvider labelProvider = new MapLabelProvider(objectsAndLabels); + setProviders(provider, labelProvider); + } + + @Override + public void updateStatus(IStatus status) { + switch (status.getSeverity()) { + case IStatus.OK: + controlDecoration.hide(); + break; + case IStatus.WARNING: + FieldDecoration warning = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_WARNING); + controlDecoration.setImage(warning.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + case IStatus.ERROR: + FieldDecoration error = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); + controlDecoration.setImage(error.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + default: + controlDecoration.hide(); + break; + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/FloatEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/FloatEditor.java new file mode 100644 index 00000000000..cef28a4785e --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/FloatEditor.java @@ -0,0 +1,69 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Locale; + +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.core.databinding.conversion.NumberToStringConverter; +import org.eclipse.core.databinding.conversion.StringToNumberConverter; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.swt.widgets.Composite; + +import com.ibm.icu.text.NumberFormat; + +/** + * An editor representing a float value as a text box + * + * @author Camille Letavernier + */ +public class FloatEditor extends StringEditor { + + private IConverter targetToModelConverter; + + /** + * + * Constructs an Editor for a Float value. The widget is a Text field. + * + * @param parent + * The Composite in which the editor is created + * @param style + * The Text's style + */ + public FloatEditor(Composite parent, int style) { + super(parent, style); + + targetToModelConverter = StringToNumberConverter.toFloat(NumberFormat.getInstance(Locale.ENGLISH), true); + setConverters(targetToModelConverter, NumberToStringConverter.fromFloat(NumberFormat.getInstance(Locale.ENGLISH), true)); + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Float.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Float getValue() { + try { + return (Float) targetToModelConverter.convert(super.getValue()); + } catch (Exception ex) { + Activator.log.error(ex); + return null; + } + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ICommitListener.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ICommitListener.java new file mode 100644 index 00000000000..8ac36a3d56f --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ICommitListener.java @@ -0,0 +1,35 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.observable.IObservable; + + +/** + * An interface for listening "Commit" events on Editors + * This is used to implement transactions when using some editors (Especially {@link MultipleValueEditor}s) + * When using a CommitListener, the {@link IObservable} should not directly execute + * commands when its methods are called, but instead wait for a commit event. + * + * @author Camille Letavernier + */ +public interface ICommitListener { + + /** + * Indicates that the implementer should apply the list of operations + * received since the last commit + * + * @param editor + * The editor that sent the commit event + */ + public void commit(AbstractEditor editor); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IElementSelectionListener.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IElementSelectionListener.java new file mode 100644 index 00000000000..d4acffd0630 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IElementSelectionListener.java @@ -0,0 +1,18 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + + +public interface IElementSelectionListener { + + public void addElements(Object[] elements); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IElementSelector.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IElementSelector.java new file mode 100644 index 00000000000..7af7f758a53 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IElementSelector.java @@ -0,0 +1,84 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.swt.widgets.Composite; + +/** + * An interface for defining widgets that can return + * some values. + * + * @author Camille Letavernier + * + */ +public interface IElementSelector { + + /** + * + * @return The currently selected elements + */ + public Object[] getSelectedElements(); + + /** + * Sets the elements that have already been chosen. + * + * @param elements + */ + public void setSelectedElements(Object[] elements); + + /** + * + * @return all displayed elements. If the widget uses a filter, + * only the filtered elements should be returned + */ + public Object[] getAllElements(); + + /** + * Creates the widgets to display this selector + * + * @param parent + */ + public void createControls(Composite parent); + + /** + * Handles the "newObjectCreated" event + * + * @param newObject + * The object that has been created + */ + public void newObjectCreated(Object newObject); + + /** + * Clears this selector. Removes all temporary elements that + * may have been created. + */ + public void clearTemporaryElements(); + + /** + * Adds a new listener to this selector. + * The selector can inform the listener that new elements have + * been selected + * + * @param listener + */ + public void addElementSelectionListener(IElementSelectionListener listener); + + /** + * Removes the element selection listener + * + * @param listener + * + * @see {@link #addElementSelectionListener(IElementSelectionListener)} + */ + public void removeElementSelectionListener(IElementSelectionListener listener); + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IReferenceValueEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IReferenceValueEditor.java new file mode 100644 index 00000000000..a546674dfea --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IReferenceValueEditor.java @@ -0,0 +1,83 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST. + * + * 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: + * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue@all4tec.net - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; + +/** + * This interface allow to define the reference value editor methods to implements. + */ +public interface IReferenceValueEditor { + + /** + * Updates the buttons' status + */ + void updateControls(); + + /** + * Updates the displayed label for the current value + */ + void updateLabel(); + + /** + * Sets the Content provider for this editor + * + * @param provider + * The content provider used to retrieve the possible values for this Reference. + */ + void setContentProvider(final IStaticContentProvider provider); + + /** + * Sets the Label provider for this editor If the label provider is null, a + * default one will be used. The same label provider is used for both the + * editor's label and the selection dialog. + * + * @param provider + * The label provider. + */ + void setLabelProvider(final ILabelProvider provider); + + /** + * Sets the factory. + * + * @param factory + * The reference value factory. + */ + void setValueFactory(final ReferenceValueFactory factory); + + /** + * Sets the direct creation value. + * + * @param directCreation + * Boolean to determinate the direct creation value. + */ + void setDirectCreation(final boolean directCreation); + + /** + * Sets the mandatory. + * + * @param mandatory + * The mandatory boolean value. + */ + void setMandatory(final boolean mandatory); + + /** + * Sets the read only value. + * + * @param readOnly + * The read only value. + */ + void setReadOnly(final boolean readOnly); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ITreeSelectorDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ITreeSelectorDialog.java new file mode 100644 index 00000000000..1a15448fd5f --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ITreeSelectorDialog.java @@ -0,0 +1,89 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.List; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IHierarchicContentProvider; + + + +public interface ITreeSelectorDialog { + + /** + * Sets the label provider for this dialog + * + * @param provider + */ + public void setLabelProvider(ILabelProvider provider); + + /** + * Sets the ContentProvider for this dialog + * The ContentProvider may be a {@link IHierarchicContentProvider} + * + * @param provider + * The content provider for this dialog. May be a {@link IHierarchicContentProvider} + */ + public void setContentProvider(ITreeContentProvider provider); + + /** + * Sets the description for this Dialog. The description is displayed on + * top of the dialog + * + * @param description + * The description for this dialog + */ + public void setDescription(String description); + + /** + * Sets the input object for this dialog's TreeViewer + * + * @param input + */ + public void setInput(Object input); + + /** + * Sets the initial selected value for this dialog + * + * @param singletonList + */ + public void setInitialElementSelections(List selectedElements); + + + /** + * Opens the dialog's window, and returns its return code + * + * @return the return code + * + * @see #create() + */ + public int open(); + + /** + * Returns the list of selections made by the user, or <code>null</code> if the selection was canceled. + * + * @return the array of selected elements, or <code>null</code> if Cancel + * was pressed + */ + public Object[] getResult(); + + /** + * Sets the title for this dialog. + * + * @param title + * the title + */ + public void setTitle(String label); + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/InputDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/InputDialog.java new file mode 100644 index 00000000000..3dd10d27407 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/InputDialog.java @@ -0,0 +1,220 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + + +import java.util.Collections; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.SelectionDialog; + +/** + * A Dialog used to input a String. The dialog uses a IInputValidator + * to check the string, and can display an error message. + * + * @author Camille Letavernier + */ +public class InputDialog extends SelectionDialog { + + /** + * The initial value for the string + */ + protected String initialValue; + + /** + * The string validator + */ + protected IInputValidator validator; + + /** + * The label used to display the error message + */ + protected Label errorLabel; + + /** + * The label used to display the error icon + */ + protected Label errorImage; + + /** + * The text widget used to input a new string + */ + protected AbstractValueEditor editor; + + /** + * The dialog's title + */ + protected String title; + + /** + * The label describing the kind of text to input + */ + protected String labelText; + + /** + * The content provider used to suggest predefined values to the user + */ + protected IStaticContentProvider contentProvider; + + /** + * + * Constructor. + * + * @param parentShell + * The shell in which the dialog will be opened + * @param title + * The dialog's title + * @param initialValue + * The dialog's initial value + * @param validator + * The validator used to check the input string + */ + public InputDialog(Shell parentShell, String title, String label, String initialValue, IInputValidator validator) { + super(parentShell); + this.initialValue = initialValue; + this.validator = validator; + this.title = title; + this.labelText = label; + } + + @Override + protected Composite getDialogArea() { + return (Composite) super.getDialogArea(); + } + + @Override + public void create() { + super.create(); + + ((GridLayout) getDialogArea().getLayout()).numColumns = 2; + + errorImage = new Label(getDialogArea(), SWT.NONE); + errorImage.setImage(Activator.getDefault().getImage("/icons/error.gif")); //$NON-NLS-1$ + + errorLabel = new Label(getDialogArea(), SWT.NONE); + errorLabel.setVisible(false); + + Label label = new Label(getDialogArea(), SWT.None); + if (labelText != null) { + label.setText(labelText); + } + label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); + + if (contentProvider != null) { + editor = new StringCombo(getDialogArea(), SWT.BORDER); + ((StringCombo) editor).setValue(initialValue); + ((StringCombo) editor).setContentProvider(contentProvider); + } else { + editor = new StringEditor(getDialogArea(), SWT.BORDER) { + + // FIXME: The StringEditor (Or one of its superclasses) should be responsible for forwarding this call + @Override + public void addKeyListener(KeyListener keyListener) { + super.text.addKeyListener(keyListener); + } + }; + + ((StringEditor) editor).setValue(initialValue); + } + // input = new Text(getDialogArea(), SWT.BORDER); + // input.setText(initialValue); + editor.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); + + editor.addKeyListener(new KeyListener() { + + @Override + public void keyPressed(KeyEvent e) { + // Nothing + } + + @Override + public void keyReleased(KeyEvent e) { + validate(); + } + + }); + + getShell().setImage(Activator.getDefault().getImage("/icons/papyrus.png")); //$NON-NLS-1$ + + if (title != null) { + getShell().setText(title); + } + + validate(); + getShell().pack(); + } + + /** + * Validates the current string. If the string isn't valid, + * and error message will be displayed. + */ + protected void validate() { + if (validator == null) { + errorLabel.setVisible(false); + errorImage.setVisible(false); + getOkButton().setEnabled(true); + return; + } + + String errorMessage = validator.isValid((String) editor.getValue()); + if (errorMessage == null) { + errorLabel.setVisible(false); + errorImage.setVisible(false); + getOkButton().setEnabled(true); + } else { + errorLabel.setText(errorMessage); + errorLabel.setVisible(true); + errorImage.setVisible(true); + getOkButton().setEnabled(false); + } + + getDialogArea().layout(true); + } + + @Override + protected void okPressed() { + setResult(Collections.singletonList((String) editor.getValue())); + super.okPressed(); + } + + /** + * @return the input text from this dialog, or null + * if the dialog has been canceled + */ + public String getText() { + Object[] result = getResult(); + if (result == null || result.length == 0) { + return null; + } + return (String) result[0]; + } + + /** + * Sets a content provider to suggest predefined values to the user + * + * @param contentProvider + */ + public void setContentProvider(IStaticContentProvider contentProvider) { + this.contentProvider = contentProvider; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/InputDialogWithLocation.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/InputDialogWithLocation.java new file mode 100644 index 00000000000..72de46c05a4 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/InputDialogWithLocation.java @@ -0,0 +1,72 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Shell; + +/** + * The developper can define the location of this input dialog + * + * @author vl222926 + * + */ +public class InputDialogWithLocation extends InputDialog { + + /** + * the location wanted to display the dialog + */ + private Point location; + + /** + * + * Constructor. + * + * @see InputDialog#InputDialog(Shell, String, String, String, IInputValidator) + * @param parentShell + * @param title + * @param label + * @param initialValue + * @param validator + * @param dialogLocation + * the location to use for the dialog + */ + public InputDialogWithLocation(Shell parentShell, String title, String label, String initialValue, IInputValidator validator, final Point dialogLocation) { + super(parentShell, title, label, initialValue, validator); + this.location = dialogLocation; + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.editors.InputDialog#create() + * + */ + @Override + public void create() { + super.create(); + // adapted code from AbstractStyleEditorDialog in nattable plugin + if (location != null) { + if (location.x < getParentShell().getDisplay().getBounds().x) { + location.x = getParentShell().getDisplay().getBounds().x; + } else if (location.x + getShell().getBounds().width > getParentShell().getDisplay().getBounds().x + getParentShell().getDisplay().getBounds().width) { + location.x = getParentShell().getDisplay().getBounds().x + getParentShell().getDisplay().getBounds().width - getShell().getBounds().width; + } + if (location.y + getShell().getBounds().height > getParentShell().getDisplay().getBounds().y + getParentShell().getDisplay().getBounds().height) { + location.y = getParentShell().getDisplay().getBounds().y + getParentShell().getDisplay().getBounds().height - getShell().getBounds().height; + } + } + getShell().setLocation(location); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IntegerEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IntegerEditor.java new file mode 100644 index 00000000000..ea6c89d4478 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IntegerEditor.java @@ -0,0 +1,146 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.core.databinding.conversion.StringToNumberConverter; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.validator.IntegerValidator; +import org.eclipse.swt.widgets.Composite; + +/** + * A Property Editor representing an Integer value as a text box. + * + * @author Camille Letavernier + * + */ +public class IntegerEditor extends StringEditor { + + /** + * The IConverter for converting data from the widget to the model + */ + private IConverter targetToModelConverter; + + + /** + * Constructs an editor for Integer values. The widget is a Text field. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The Text's style + */ + public IntegerEditor(Composite parent, int style) { + this(parent, style, null); + } + + /** + * Constructs an editor for Integer values. The widget is a Text field. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The Text's style + * @param label + * The editor's label + */ + public IntegerEditor(Composite parent, int style, String label) { + super(parent, style, label); + + targetValidator = new IntegerValidator(); + + targetToModelConverter = new IConverter() { + + @Override + public Object getToType() { + return Integer.class; + } + + @Override + public Object getFromType() { + return String.class; + } + + @Override + public Integer convert(Object fromObject) { + if (fromObject instanceof String) { + String newString = ((String) fromObject).replaceAll(" ", ""); //$NON-NLS-1$ //$NON-NLS-2$ + try { + Integer i = (Integer) StringToNumberConverter.toInteger(false).convert(newString); + return i; + } catch (Exception ex) { + + } + + } + + return null; + } + }; + + IConverter integerToString = new IConverter() { + + @Override + public Object getToType() { + return String.class; + } + + @Override + public Object getFromType() { + return Integer.class; + } + + @Override + public Object convert(Object fromObject) { + + if (fromObject instanceof Integer) { + return Integer.toString((Integer) fromObject); + } + errorBinding = true; + return ""; //$NON-NLS-1$ + } + + }; + setValidateOnDelay(true); + setConverters(targetToModelConverter, integerToString); + setTargetAfterGetValidator(targetValidator); + + } + + + + + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Integer.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Integer getValue() { + try { + + return (Integer) targetToModelConverter.convert(super.getValue()); + } catch (Exception ex) { + Activator.log.error(ex); + return null; + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IntegerMask.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IntegerMask.java new file mode 100644 index 00000000000..de609cd4b74 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IntegerMask.java @@ -0,0 +1,216 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +public class IntegerMask extends AbstractValueEditor implements SelectionListener, IChangeListener, DisposeListener { + + private Button[] checkboxes; + + private int currentValue; + + private final Composite checkboxContainer; + + private boolean refreshCheckboxes = true; + + public IntegerMask(final Composite parent, final int style) { + super(parent, style); + checkboxContainer = new Composite(this, style); + checkboxContainer.setLayoutData(getDefaultLayoutData()); + checkboxContainer.setLayout(new GridLayout(2, true)); + checkboxContainer.addDisposeListener(this); + } + + @Override + protected GridData getLabelLayoutData() { + GridData data = super.getLabelLayoutData(); + data.verticalAlignment = SWT.BEGINNING; + return data; + } + + @Override + public Object getValue() { + int totalValue = 0; + for (Button button : checkboxes) { + int value = (Integer) button.getData("IntValue"); //$NON-NLS-1$ + if (button.getSelection()) { + totalValue |= value; + } + } + return totalValue; + } + + @Override + public void dispose() { + if (modelProperty != null) { + modelProperty.removeChangeListener(this); + } + super.dispose(); + } + + @Override + public Object getEditableType() { + return Integer.class; + } + + @Override + public void setReadOnly(final boolean readOnly) { + // TODO Auto-generated method stub + + } + + @Override + public boolean isReadOnly() { + // TODO Auto-generated method stub + return false; + } + + public void setMasks(final String[] values) { + Map<Integer, String> masks = new HashMap<Integer, String>(); + int intValue = 1; + for (String value : values) { + masks.put(intValue, value); + intValue <<= 1; + } + setMasks(masks); + } + + public void setMasks(final Map<Integer, String> values) { + if (values.size() > 32) { + StringLabel label = new StringLabel(checkboxContainer, SWT.NONE); + label.getValueLabel().setImage(Activator.getDefault().getImage("/icons/error.gif")); //$NON-NLS-1$ + label.getValueLabel().setText(Messages.IntegerMask_ErrorTooManyValues); + checkboxes = new Button[0]; + } else { + if (checkboxes != null) { + disposeCheckboxes(); + } + + checkboxes = new Button[values.size()]; + + int i = 0; + for (Entry<Integer, String> mask : values.entrySet()) { + int intValue = mask.getKey(); + String value = mask.getValue(); + checkboxes[i] = new Button(checkboxContainer, SWT.CHECK); + checkboxes[i].setText(value); + checkboxes[i].setData("IntValue", intValue); //$NON-NLS-1$ + checkboxes[i].addSelectionListener(this); + i++; + } + } + } + + protected void disposeCheckboxes() { + for (Button button : checkboxes) { + button.removeSelectionListener(this); + button.dispose(); + } + } + + public void setNumColumns(final int numColumns) { + ((GridLayout) checkboxContainer.getLayout()).numColumns = numColumns; + checkboxContainer.layout(); + layout(); + } + + @Override + public void doBinding() { + // We don't do a real databinding here + modelProperty.addChangeListener(this); + + refreshCheckboxes(); + } + + protected void refreshCheckboxes() { + if (!refreshCheckboxes) { + return; + } + + int totalValue = getCurrentValue(); + for (Button button : checkboxes) { + int value = (Integer) button.getData("IntValue"); //$NON-NLS-1$ + button.setSelection((totalValue & value) != 0); + } + } + + @Override + public void setToolTipText(final String text) { + super.setLabelToolTipText(text); + } + + @Override + public void widgetSelected(final SelectionEvent e) { + Button button = (Button) e.widget; + int value = (Integer) button.getData("IntValue"); //$NON-NLS-1$ + int totalValue = getCurrentValue(); + if (button.getSelection()) { + totalValue |= value; + } else { + totalValue &= ~value; + } + setCurrentValue(totalValue); + } + + protected void setCurrentValue(final int value) { + if (modelProperty != null) { + refreshCheckboxes = false; + modelProperty.setValue(value); + refreshCheckboxes = true; + } + currentValue = value; + + commit(); + } + + protected Integer getCurrentValue() { + if (modelProperty != null) { + Object value = modelProperty.getValue(); + return value == null ? 0 : (Integer) value; + } else { + return currentValue; + } + } + + @Override + public void widgetDefaultSelected(final SelectionEvent e) { + // Nothing + } + + public int getNumColumns() { + return ((GridLayout) checkboxContainer.getLayout()).numColumns; + } + + @Override + public void handleChange(final ChangeEvent event) { + refreshCheckboxes(); + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IntegerSpinner.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IntegerSpinner.java new file mode 100644 index 00000000000..defe38a6ce7 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/IntegerSpinner.java @@ -0,0 +1,325 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Timer; +import java.util.TimerTask; + +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.core.databinding.conversion.StringToNumberConverter; +import org.eclipse.core.databinding.observable.value.AbstractObservableValue; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Spinner; + +/** + * A widget for editing Integer values with a SWT Spinner + * + * @author Camille Letavernier + * + * @see Spinner + */ +public class IntegerSpinner extends AbstractValueEditor implements KeyListener, ModifyListener { + + /** + * The SWT Spinner + */ + protected Spinner spinner; + + /** + * The String to Integer converter + */ + protected IConverter targetToModelConverter; + + + private Timer timer; + + private TimerTask changeColorTask; + + /** + * Constructor. + * + * @param parent + * The Composite in which the editor will be created + * @param style + * The SWT style to apply + */ + public IntegerSpinner(Composite parent, int style) { + super(parent, style); + spinner = createSpinner(); + + setWidgetObservable(new AbstractObservableValue() { + + @Override + public Object getValueType() { + return Integer.class; + } + + @Override + protected Integer doGetValue() { + return (Integer) targetToModelConverter.convert(spinner.getText()); + } + + @Override + protected void doSetValue(Object value) { + spinner.setSelection((Integer) value); + } + + }); + + spinner.addKeyListener(this); + spinner.addModifyListener(this); + setCommitOnFocusLost(spinner); + + GridData gridData = getDefaultLayoutData(); + spinner.setLayoutData(gridData); + gridData.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + targetToModelConverter = StringToNumberConverter.toInteger(false); + controlDecoration = new ControlDecoration(spinner, SWT.LEFT | SWT.LEFT); + } + + /** + * Creates the Spinner + * + * @return the Spinner + */ + protected Spinner createSpinner() { + return new Spinner(this, factory.getBorderStyle()); + } + + @Override + public void doBinding() { + + spinner.addFocusListener(new FocusListener() { + + @Override + public void focusGained(FocusEvent e) { + // Nothing + } + + @Override + public void focusLost(FocusEvent e) { + binding.updateTargetToModel(); + } + + }); + + super.doBinding(); + } + + @Override + public Object getValue() { + String value = spinner.getText(); + return targetToModelConverter.convert(value); + } + + @Override + public Object getEditableType() { + return Integer.class; + } + + @Override + public void setReadOnly(boolean readOnly) { + spinner.setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return !spinner.isEnabled(); + } + + @Override + public void setToolTipText(String text) { + spinner.setToolTipText(text); + super.setLabelToolTipText(text); + } + + /** + * Sets the minimum value for the spinner + * + * @param minimum + * @see Spinner#setMinimum(int) + */ + public void setMinimum(int minimum) { + spinner.setMinimum(minimum); + } + + /** + * Sets the maximum value for the spinner + * + * @param maximum + * @see Spinner#setMaximum(int) + */ + public void setMaximum(int maximum) { + spinner.setMaximum(maximum); + } + + /** + * Sets the increment value for the spinner + * + * @param increment + * @see Spinner#setIncrement(int) + */ + public void setIncrement(int increment) { + spinner.setIncrement(increment); + } + + @Override + public void keyPressed(KeyEvent e) { + + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) { + notifyChange(); + } + + } + + protected void notifyChange() { + spinner.notifyListeners(SWT.FocusOut, new Event()); + commit(); + } + + @Override + public void updateStatus(IStatus status) { + switch (status.getSeverity()) { + case IStatus.OK: + controlDecoration.hide(); + break; + case IStatus.WARNING: + FieldDecoration warning = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_WARNING); + controlDecoration.setImage(warning.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + case IStatus.ERROR: + FieldDecoration error = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); + controlDecoration.setImage(error.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + default: + controlDecoration.hide(); + break; + } + } + + private void cancelCurrentTask() { + if (changeColorTask != null) { + changeColorTask.cancel(); + } + } + + @Override + public void changeColorField() { + if (timer == null) { + timer = new Timer(true); + } + + cancelCurrentTask(); + changeColorTask = new TimerTask() { + + @Override + public void run() { + IntegerSpinner.this.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if (!spinner.isDisposed()) { + spinner.setBackground(DEFAULT); + spinner.update(); + } + } + + + }); + } + }; + if (errorBinding) { + spinner.setBackground(ERROR); + spinner.update(); + } else { + IStatus status = (IStatus) binding.getValidationStatus().getValue(); + switch (status.getSeverity()) { + case IStatus.OK: + case IStatus.WARNING: + timer.schedule(changeColorTask, 600); + spinner.setBackground(VALID); + spinner.update(); + break; + case IStatus.ERROR: + spinner.setBackground(ERROR); + spinner.update(); + break; + } + } + } + + @Override + public void dispose() { + if (changeColorTask != null) { + changeColorTask.cancel(); + changeColorTask = null; + } + if (timer != null) { + timer.cancel(); + timer = null; + } + super.dispose(); + } + + /** + * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) + * + * @param e + */ + + @Override + public void modifyText(ModifyEvent e) { + if (modelProperty == null) { + return; + } + + if (modelProperty.getValue() != null) { + if (!isReadOnly() && !modelProperty.getValue().toString().equals(spinner.getText())) { + spinner.setBackground(EDIT); + } else { + spinner.setBackground(DEFAULT); + } + } else { + if (spinner.getText().equals("")) { + spinner.setBackground(DEFAULT); + } else { + spinner.setBackground(EDIT); + } + } + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/LongEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/LongEditor.java new file mode 100644 index 00000000000..b11e57372e9 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/LongEditor.java @@ -0,0 +1,53 @@ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Locale; + +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.core.databinding.conversion.NumberToStringConverter; +import org.eclipse.core.databinding.conversion.StringToNumberConverter; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.swt.widgets.Composite; + +import com.ibm.icu.text.NumberFormat; + +public class LongEditor extends StringEditor { + + private IConverter targetToModelConverter; + + /** + * + * Constructs an Editor for a Long value. The widget is a Text field. + * + * @param parent + * The Composite in which the editor is created + * @param style + * The Text's style + */ + public LongEditor(Composite parent, int style) { + super(parent, style); + + targetToModelConverter = StringToNumberConverter.toLong(NumberFormat.getInstance(Locale.ENGLISH), true); + setConverters(targetToModelConverter, NumberToStringConverter.fromLong(NumberFormat.getInstance(Locale.ENGLISH), true)); + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Long.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Long getValue() { + try { + return (Long) targetToModelConverter.convert(super.getValue()); + } catch (Exception ex) { + Activator.log.error(ex); + return null; + } + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleDoubleEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleDoubleEditor.java new file mode 100644 index 00000000000..bae688415de --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleDoubleEditor.java @@ -0,0 +1,70 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * 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: + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + + +import org.eclipse.papyrus.infra.widgets.selectors.RealSelector; +import org.eclipse.swt.widgets.Composite; + + +public class MultipleDoubleEditor extends MultipleStringEditor { + + /** + * Constructs an Editor for multiple double values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + */ + public MultipleDoubleEditor(Composite parent, int style) { + super(parent, style, new RealSelector()); + } + + /** + * Constructs an Editor for multiple double values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param label + * The editor's label + */ + public MultipleDoubleEditor(Composite parent, int style, String label) { + super(parent, style, new RealSelector(), label); + } + + /** + * Constructs an Editor for multiple double values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param ordered + * Indicates if the values should be ordered. If true, the up/down controls will be activated + * @param unique + * Indicates if the values should be unique. + * @param label + * The editor's label + */ + public MultipleDoubleEditor(Composite parent, int style, boolean ordered, boolean unique, String label) { + super(parent, style, new RealSelector(), ordered, unique, label); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleIntegerEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleIntegerEditor.java new file mode 100644 index 00000000000..4b3604e4af6 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleIntegerEditor.java @@ -0,0 +1,75 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.papyrus.infra.widgets.selectors.IntegerSelector; +import org.eclipse.swt.widgets.Composite; + +/** + * An editor for multivalued Integer attributes + * + * @author Camille Letavernier + * + */ +public class MultipleIntegerEditor extends MultipleStringEditor { + + /** + * Constructs an Editor for multiple Integer values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + */ + public MultipleIntegerEditor(Composite parent, int style) { + super(parent, style, new IntegerSelector()); + } + + /** + * Constructs an Editor for multiple Integer values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param label + * The editor's label + */ + public MultipleIntegerEditor(Composite parent, int style, String label) { + super(parent, style, new IntegerSelector(), label); + } + + /** + * Constructs an Editor for multiple Integer values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param ordered + * Indicates if the values should be ordered. If true, the up/down controls will be activated + * @param unique + * Indicates if the values should be unique. + * @param label + * The editor's label + */ + public MultipleIntegerEditor(Composite parent, int style, boolean ordered, boolean unique, String label) { + super(parent, style, new IntegerSelector(), ordered, unique, label); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleReferenceEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleReferenceEditor.java new file mode 100644 index 00000000000..7330d044179 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleReferenceEditor.java @@ -0,0 +1,115 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.providers.EmptyContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.WrappedLabelProvider; +import org.eclipse.papyrus.infra.widgets.selectors.ReferenceSelector; +import org.eclipse.swt.widgets.Composite; + +/** + * An editor for multivalued references. This editor should be used when + * there is enough vertical space available. If the vertical space is limited, + * CompactMultipleReferenceEditor should be used instead. + * + * @author Camille Letavernier + * + */ +public class MultipleReferenceEditor extends MultipleValueEditor { + + /** + * The element selector for the available values + */ + protected ReferenceSelector selector; + + protected IStaticContentProvider contentProvider; + + /** + * + * Constructor. + * + * @param parent + * The composite in which this editor is created + * @param style + * The style for this editor's list + * @param ordered + * True if the list should be ordered + * @param unique + * True if the list values should be unique + * @param label + * The label for this editor + */ + public MultipleReferenceEditor(Composite parent, int style, boolean ordered, boolean unique, String label) { + super(parent, style, new ReferenceSelector(unique), ordered, unique, label); + this.selector = (ReferenceSelector) super.selector; + // Default providers + setProviders(EmptyContentProvider.instance, new WrappedLabelProvider()); + } + + /** + * + * Constructor. + * + * @param parent + * The composite in which this editor is created + * @param style + * The style for this editor's list + * @param label + * The label for this editor + */ + public MultipleReferenceEditor(Composite parent, int style, String label) { + this(parent, style, false, false, label); + } + + /** + * + * Constructor. + * + * @param parent + * The composite in which this editor is created + * @param style + * The style for this editor's list + */ + public MultipleReferenceEditor(Composite parent, int style) { + this(parent, style, false, false, null); + } + + /** + * Sets the Content and Label providers for this editor + * + * @param contentProvider + * The content provider describing the elements that can be selected + * @param labelProvider + * The label provider for the elements + */ + public void setProviders(IStaticContentProvider contentProvider, ILabelProvider labelProvider) { + Assert.isNotNull(contentProvider, "The content provider should be defined"); //$NON-NLS-1$ + + this.contentProvider = contentProvider; + + selector.setContentProvider(contentProvider); + + if (labelProvider != null) { + selector.setLabelProvider(labelProvider); + super.setLabelProvider(labelProvider); + } + } + + @Override + public void setUnique(boolean unique) { + selector.setUnique(unique); + super.setUnique(unique); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleStringEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleStringEditor.java new file mode 100644 index 00000000000..ade19dcc579 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleStringEditor.java @@ -0,0 +1,181 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.papyrus.infra.widgets.creation.StringEditionFactory; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.selectors.StandardSelector; +import org.eclipse.papyrus.infra.widgets.selectors.StringSelector; +import org.eclipse.swt.widgets.Composite; + + +/** + * An editor for multivalued String attributes + * + * @author Camille Letavernier + * + */ +public class MultipleStringEditor extends MultipleValueEditor { + + /** + * Constructs an Editor for multiple String values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + */ + public MultipleStringEditor(Composite parent, int style) { + super(parent, style, new StringSelector()); + init(); + } + + public MultipleStringEditor(Composite parent, int style, boolean multiline) { + super(parent, style, new StringSelector(multiline)); + init(); + } + + /** + * Constructs an Editor for multiple String values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param ordered + * Indicates if the values should be ordered. If true, the up/down controls will be activated + * @param unique + * Indicates if the values should be unique. + */ + public MultipleStringEditor(Composite parent, int style, boolean ordered, boolean unique) { + super(parent, style, new StringSelector(), ordered, unique, null); + init(); + } + + /** + * Constructs an Editor for multiple String values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param ordered + * Indicates if the values should be ordered. If true, the up/down controls will be activated + * @param unique + * Indicates if the values should be unique. + * @param label + * The editor's label + */ + public MultipleStringEditor(Composite parent, int style, boolean ordered, boolean unique, String label) { + super(parent, style, new StringSelector(), ordered, unique, label); + init(); + } + + /** + * Constructs an Editor for multiple String values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param selector + * The Element selector for the dialog's left-pane. Used to select values or enter new ones. + * @param ordered + * Indicates if the values should be ordered. If true, the up/down controls will be activated + * @param unique + * Indicates if the values should be unique. + * @param label + * The editor's label + */ + public MultipleStringEditor(Composite parent, int style, IElementSelector selector, boolean ordered, boolean unique, String label) { + super(parent, style, selector, ordered, unique, label); + init(); + } + + /** + * Constructs an Editor for multiple Integer values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param selector + * The Element selector for the dialog's left-pane. Used to select values or enter new ones. + */ + public MultipleStringEditor(Composite parent, int style, IElementSelector selector) { + super(parent, style, selector); + init(); + } + + /** + * Constructs an Editor for multiple String values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param selector + * The Element selector for the dialog's left-pane. Used to select values or enter new ones. + * @param label + * The editor's label + */ + public MultipleStringEditor(Composite parent, int style, IElementSelector selector, String label) { + super(parent, style, selector, label); + init(); + } + + /** + * Constructs an Editor for multiple String values + * The widget is a List, with controls to move values up/down, add values + * and remove values. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The List's style + * @param label + * The editor's label + */ + public MultipleStringEditor(Composite parent, int style, String label) { + super(parent, style, new StringSelector(), label); + init(); + } + + private void init() { + setFactory(new StringEditionFactory()); + } + + public void setContentProvider(final IStaticContentProvider provider) { + IElementSelector selector = new StandardSelector(StringCombo.class) { + + @Override + public void createControls(Composite parent) { + super.createControls(parent); + ((StringCombo) editor).setProviders(provider, null); + } + }; + setSelector(selector); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleStringFileEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleStringFileEditor.java new file mode 100644 index 00000000000..f69aa41b8ca --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleStringFileEditor.java @@ -0,0 +1,228 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService; +import org.eclipse.papyrus.infra.services.labelprovider.service.impl.LabelProviderServiceImpl; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.WorkspaceContentProvider; +import org.eclipse.papyrus.infra.widgets.selectors.NullSelector; +import org.eclipse.papyrus.infra.widgets.selectors.ReferenceSelector; +import org.eclipse.papyrus.infra.widgets.util.FileUtil; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.FileDialog; + +/** + * A Widget for editing multi-valued Strings with File paths + * The file paths may be absolute (FileSystem paths) or relative to the workspace (Workspace paths) + * + * @author Camille Letavernier + */ +public class MultipleStringFileEditor extends MultipleValueEditor { + + protected boolean allowBrowseWorkspace = true; + + protected boolean allowBrowseFileSystem = true; + + protected Button browseFileSystem; + + protected Button browseWorkspace; + + protected final List<String> filterNames; + + protected final List<String> filterExtensions; + + public static final String browseWorkspaceIcon = "icons/browse-workspace_12x12.png"; //$NON-NLS-1$ + + public static final String browseFileSystemIcon = "icons/browse-filesystem_12x12.png"; //$NON-NLS-1$ + + public MultipleStringFileEditor(Composite parent, int style) { + super(parent, style, NullSelector.instance); + setDirectCreation(true); + + filterNames = new LinkedList<String>(); + filterExtensions = new LinkedList<String>(); + } + + @Override + protected void createListControls() { + super.createListControls(); + add.dispose(); + edit.dispose(); + + browseFileSystem = createButton(Activator.getDefault().getImageFromPlugin(browseFileSystemIcon), Messages.MultipleStringFileEditor_0); + browseWorkspace = createButton(Activator.getDefault().getImageFromPlugin(browseWorkspaceIcon), Messages.MultipleStringFileEditor_1); + + browseWorkspace.moveAbove(remove); + browseFileSystem.moveAbove(remove); + } + + @Override + public void setDirectCreation(boolean directCreation) { + super.setDirectCreation(true); // Always true + } + + @Override + protected void updateControls() { + remove.setEnabled(!readOnly); + up.setEnabled(ordered && !readOnly); + down.setEnabled(ordered && !readOnly); + + browseWorkspace.setEnabled(allowBrowseWorkspace && !readOnly); + browseFileSystem.setEnabled(allowBrowseFileSystem && !readOnly); + } + + public void allowBrowseWorkspace(boolean allowBrowseWorkspace) { + this.allowBrowseWorkspace = allowBrowseWorkspace; + } + + public void allowBrowseFileSystem(boolean allowBrowseFileSystem) { + this.allowBrowseFileSystem = allowBrowseFileSystem; + } + + /** + * Handle events occuring on controls + * + * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) + * + * @param e + */ + @Override + public void widgetSelected(SelectionEvent e) { + super.widgetSelected(e); + if (e.widget == browseFileSystem) { + browseFileSystem(); + } else if (e.widget == browseWorkspace) { + browseWorkspace(); + } + } + + protected void browseFileSystem() { + // File file = FileUtil.getFile(text.getText()); + + FileDialog dialog = new FileDialog(getShell(), SWT.MULTI | SWT.OPEN); + dialog.setFilterExtensions(filterExtensions.toArray(new String[filterExtensions.size()])); + dialog.setFilterNames(filterNames.toArray(new String[filterNames.size()])); + if (dialog.open() != null) { + List<String> filePathList = new ArrayList<String>(modelProperty.size() + dialog.getFileNames().length); + filePathList.addAll(modelProperty); + + for (String fileName : dialog.getFileNames()) { + filePathList.add(dialog.getFilterPath() + File.separator + fileName); + } + + modelProperty.clear(); + modelProperty.addAll(filePathList); + commit(); + } + } + + protected void browseWorkspace() { + LabelProviderService labelProviderService = new LabelProviderServiceImpl(); + try { + labelProviderService.startService(); + } catch (ServiceException ex) { + Activator.log.error(ex); + } + + ILabelProvider labelProvider = labelProviderService.getLabelProvider(); + + ReferenceSelector selector = new ReferenceSelector(); + selector.setLabelProvider(labelProvider); + + + // Prepare the WorkspaceContentProvider and use the right filters + WorkspaceContentProvider contentProvider = new WorkspaceContentProvider(); + + contentProvider.setExtensionFilters(new LinkedHashMap<String, String>()); // Reset the default filters + for (int i = 0; i < Math.min(filterNames.size(), filterExtensions.size()); i++) { + contentProvider.addExtensionFilter(filterExtensions.get(i), filterNames.get(i)); + } + + selector.setContentProvider(contentProvider); + + + MultipleValueSelectorDialog dialog = new MultipleValueSelectorDialog(getShell(), selector); + if (labelText != null) { + dialog.setTitle(labelText); + } + + dialog.setLabelProvider(labelProvider); + + dialog.setOrdered(true); + dialog.setUnique(true); + selector.setUnique(true); + + int code = dialog.open(); + if (code == Window.OK) { + Object[] result = dialog.getResult(); + if (result.length > 0) { + List<String> filePathResult = new ArrayList<String>(result.length + modelProperty.size()); + filePathResult.addAll(modelProperty); + for (Object file : result) { + if (file instanceof IFile) { + filePathResult.add(FileUtil.getPath((IFile) file, false)); + } + } + modelProperty.clear(); + modelProperty.addAll(filePathResult); + commit(); + } + } + } + + public void setFilters(String[] filterExtensions, String[] filterNames) { + if (filterExtensions.length != filterNames.length) { + // This is a simple warning. Only valid filters will be retained. + Activator.log.warn(Messages.MultipleStringFileEditor_2); + } + + setFilterNames(getFilterLabels(filterNames, filterExtensions)); + setFilterExtensions(filterExtensions); + } + + protected String[] getFilterLabels(String[] filterNames, String[] filterExtensions) { + int size = Math.min(filterNames.length, filterExtensions.length); + String[] filters = new String[size]; + for (int i = 0; i < size; i++) { + filters[i] = filterNames[i] + " (" + filterExtensions[i] + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } + return filters; + } + + public void setFilterExtensions(String[] filterExtensions) { + this.filterExtensions.clear(); + this.filterExtensions.addAll(Arrays.asList(filterExtensions)); + } + + public void setFilterNames(String[] filterNames) { + this.filterNames.clear(); + this.filterNames.addAll(Arrays.asList(filterNames)); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueEditor.java new file mode 100644 index 00000000000..26dce0a5897 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueEditor.java @@ -0,0 +1,725 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * Christian W. Damus - bug 399859 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Arrays; +import java.util.Collection; + +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.TreeCollectionContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; + +/** + * An editor for multivalued fields. + * + * @author Camille Letavernier + * + */ +public class MultipleValueEditor extends AbstractListEditor implements SelectionListener, IChangeListener, DisposeListener { + + public static final int MANY = -1; + + /** + * The viewer displaying the current values from + * the model + */ + protected TreeViewer treeViewer; + + /** + * The tree associated to the viewer + */ + protected Tree tree; + + /** + * A Composite containing the different control buttons + * (Add, remove, ...) + */ + protected Composite controlsSection; + + /** + * The Add control + */ + protected Button add; + + /** + * The Remove control + */ + protected Button remove; + + /** + * The Up control + */ + protected Button up; + + /** + * The Down control + */ + protected Button down; + + /** + * The edit control + */ + protected Button edit; + + /** + * The element selector for this editor's dialog + */ + protected IElementSelector selector; + + /** + * Indicates whether the underlying is ordered + */ + protected boolean ordered; + + /** + * Indicates whether the underlying contains unique values + */ + protected boolean unique; + + /** + * The factory for creating and editing values from + * this editor + */ + protected ReferenceValueFactory referenceFactory; + + /** + * Indicates if this editor is readOnly + */ + protected boolean readOnly; + + private boolean directCreation; + + /** + * Indicates the maximum number of values selected. + */ + protected int upperBound; + + + /** + * + * Constructor. + * + * @param parent + * The Composite in which this Editor should be displayed + * @param style + * This editor's tree style + * @param selector + * The element selector for this editor's dialog + * @param ordered + * Specify if the observed collection is ordered. If true, Up and Down controls are displayed. + * @param unique + * Specify if the observed collection values are unique. + * @param label + * The label for this editor. If null, the label isn't created. + */ + public MultipleValueEditor(Composite parent, int style, IElementSelector selector, boolean ordered, boolean unique, String label) { + this(parent, style, selector, ordered, unique, label, MANY); + } + + /** + * + * Constructor. + * + * @param parent + * The Composite in which this Editor should be displayed + * @param style + * This editor's tree style + * @param selector + * The element selector for this editor's dialog + * @param ordered + * Specify if the observed collection is ordered. If true, Up and Down controls are displayed. + * @param unique + * Specify if the observed collection values are unique. + * @param label + * The label for this editor. If null, the label isn't created. + * @param upperBound + * The maximum number of values that must appear. + */ + public MultipleValueEditor(Composite parent, int style, IElementSelector selector, boolean ordered, boolean unique, String label, int upperBound) { + super(parent, label); + Assert.isNotNull(selector, "The Element Selector must be specified for a MultipleValueEditor"); //$NON-NLS-1$ + + setLayout(new GridLayout(label == null ? 1 : 2, false)); + + controlsSection = new Composite(this, SWT.NONE); + controlsSection.setLayout(new FillLayout()); + controlsSection.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); + + tree = new Tree(this, style | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.FULL_SELECTION); + GridData treeData = new GridData(SWT.FILL, SWT.FILL, true, true); + treeData.horizontalSpan = 2; + treeData.minimumHeight = 80; + tree.setLayoutData(treeData); + + tree.addSelectionListener(this); + + treeViewer = new TreeViewer(tree); + treeViewer.setContentProvider(TreeCollectionContentProvider.instance); + + createListControls(); + + this.selector = selector; + + setLabelProvider(new LabelProvider()); + setUpperBound(upperBound); + this.ordered = ordered; + this.unique = unique; + updateControls(); + } + + /** + * Creates the dialog for this editor + * + * @param parent + * The Composite in which the dialog should be displayed + * @param selector + * The element selector for this dialog + * @param ordered + * Specify if the observed collection is ordered. If true, Up and Down controls are displayed. + * @param unique + * Specify if the observed collection values are unique. + * @param label + * The editor's label. + * @return The new dialog for this editor + */ + protected MultipleValueSelectorDialog createMultipleValueSelectorDialog(Composite parent, IElementSelector selector, boolean ordered, boolean unique, String label) { + return new MultipleValueSelectorDialog(parent.getShell(), selector, label, unique, ordered); + } + + @Override + protected GridData getLabelLayoutData() { + GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false); + return data; + } + + public void setSelector(IElementSelector selector) { + this.selector = selector; + } + + protected void updateControls() { + + boolean enableAddAction = true; + if (directCreation) { + if (referenceFactory == null || !referenceFactory.canCreateObject()) { + enableAddAction = false; + } + } + + add.setEnabled(!readOnly && enableAddAction); + remove.setEnabled(!readOnly); + up.setEnabled(ordered && !readOnly); + down.setEnabled(ordered && !readOnly); + + if (edit != null) { + edit.setEnabled(this.referenceFactory != null && referenceFactory.canEdit() && !readOnly); + } + + if (modelProperty != null && this.upperBound != MANY) { + if (modelProperty.size() >= this.upperBound) { + add.setEnabled(false); + } + } + + } + + /** + * + * Constructor. + * + * @param parent + * The Composite in which this Editor should be displayed + * @param style + * This editor's tree style + * @param selector + * The element selector for this editor's dialog + * @param ordered + * Specify if the observed collection is ordered. If true, Up and Down controls are displayed + */ + public MultipleValueEditor(Composite parent, int style, IElementSelector selector, boolean ordered) { + this(parent, style, selector, ordered, false, null); + } + + /** + * + * Constructor. + * + * @param parent + * The Composite in which this Editor should be displayed + * @param style + * This editor's tree style + * @param selector + * The element selector for this editor's dialog + */ + public MultipleValueEditor(Composite parent, int style, IElementSelector selector) { + this(parent, style, selector, false, false, null); + } + + /** + * + * Constructor. + * + * @param parent + * The Composite in which this Editor should be displayed + * @param style + * This editor's tree style + * @param selector + * The element selector for this editor's dialog + * @param label + * The label for this Editor + */ + public MultipleValueEditor(Composite parent, int style, IElementSelector selector, String label) { + this(parent, style, selector, false, false, label); + } + + /** + * Sets the label provider for this editor + * + * @param labelProvider + * The label provider for this editor + */ + public void setLabelProvider(IBaseLabelProvider labelProvider) { + treeViewer.setLabelProvider(labelProvider); + } + + /** + * {@inheritDoc} + */ + @Override + protected void doBinding() { + // We don't do a real Databinding in this case + treeViewer.setInput(modelProperty); + modelProperty.addChangeListener(this); + } + + /** + * @param ordered + */ + public void setOrdered(boolean ordered) { + this.ordered = ordered; + + updateControls(); + } + + /** + * @param unique + */ + public void setUnique(boolean unique) { + this.unique = unique; + + updateControls(); + } + + /** + * Creates the Add/Remove controls, + * and the Up/Down controls if the collection is ordered + * + * @param ordered + */ + protected void createListControls() { + up = createButton(Activator.getDefault().getImage("/icons/Up_12x12.gif"), Messages.MultipleValueEditor_MoveSelectedElementsUp); //$NON-NLS-1$ + down = createButton(Activator.getDefault().getImage("/icons/Down_12x12.gif"), Messages.MultipleValueEditor_MoveSelectedElementsDown); //$NON-NLS-1$ + add = createButton(Activator.getDefault().getImage("/icons/Add_12x12.gif"), Messages.MultipleValueEditor_AddElements); //$NON-NLS-1$ + remove = createButton(Activator.getDefault().getImage("/icons/Delete_12x12.gif"), Messages.MultipleValueEditor_RemoveSelectedElements); //$NON-NLS-1$ + edit = createButton(Activator.getDefault().getImage("/icons/Edit_12x12.gif"), Messages.MultipleValueEditor_EditSelectedValue); //$NON-NLS-1$ + } + + protected Button createButton(Image image, String toolTipText) { + Button button = new Button(controlsSection, SWT.PUSH); + button.setImage(image); + button.addSelectionListener(this); + button.setToolTipText(toolTipText); + return button; + } + + @Override + public Object getEditableType() { + return Collection.class; + } + + /** + * Handle events occuring on controls + * + * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) + * + * @param e + */ + @Override + public void widgetSelected(SelectionEvent e) { + if (e.widget == null) { + return; + } + if (e.widget == add) { + if (this.upperBound == MANY || modelProperty.size() < this.upperBound) { + addAction(); + } + } else if (e.widget == remove) { + removeAction(); + } else if (e.widget == up) { + upAction(); + } else if (e.widget == down) { + downAction(); + } else if (e.widget == edit) { + editAction(); + } + + updateBoutons(); + } + + /** + * Handle add Action + */ + protected void addAction() { + final Object context = getContextElement(); + + if (directCreation) { + if (referenceFactory != null && referenceFactory.canCreateObject()) { + getOperationExecutor(context).execute(new Runnable() { + + @Override + public void run() { + Object newElement = referenceFactory.createObject(MultipleValueEditor.this, context); + if (newElement != null) { + modelProperty.add(newElement); + commit(); + } + } + }, NLS.bind(Messages.MultipleValueEditor_addOperation, labelText)); + } + + return; + } + + getOperationExecutor(context).execute(new Runnable() { + + @Override + public void run() { + String dialogLabel = label == null ? null : label.getText(); + MultipleValueSelectorDialog dialog = createMultipleValueSelectorDialog(getParent(), selector, ordered, unique, dialogLabel); + dialog.setLabelProvider((ILabelProvider) treeViewer.getLabelProvider()); + dialog.setFactory(referenceFactory); + dialog.setUpperBound(upperBound); + dialog.setContextElement(context); + + if (modelProperty != null) { + dialog.setInitialSelections(modelProperty.toArray()); + } else { + dialog.setInitialSelections(new Object[0]); + } + + int returnCode = dialog.open(); + if (returnCode == Window.CANCEL) { + // Clear out the element selector in case we open this dialog again + selector.clearTemporaryElements(); + + // Roll back whatever has been done, so far + throw new OperationCanceledException(); + } + + modelProperty.clear(); + + Object[] result = dialog.getResult(); + if (result == null) { + return; + } + + modelProperty.addAll(Arrays.asList(result)); + + commit(); + } + }, NLS.bind(Messages.MultipleValueEditor_addOperation, labelText)); + } + + @Override + protected void commit() { + super.commit(); + if (!isDisposed()) { + treeViewer.refresh(); + } + } + + /** + * Handle remove Action + */ + protected void removeAction() { + IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); + for (Object value : selection.toArray()) { + modelProperty.remove(value); + } + treeViewer.setSelection(null); + + commit(); + } + + /** + * Handle up Action + */ + protected void upAction() { + IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); + for (Object o : selection.toArray()) { + int oldIndex = modelProperty.indexOf(o); + if (oldIndex > 0) { + modelProperty.move(oldIndex, oldIndex - 1); + } + } + + IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray()); + treeViewer.setSelection(selectionCopy); + + commit(); + } + + /** + * Handle down Action + */ + protected void downAction() { + IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); + + int maxIndex = modelProperty.size() - 1; + + Object[] selectionArray = selection.toArray(); + for (int i = selectionArray.length - 1; i >= 0; i--) { + Object o = selectionArray[i]; + int oldIndex = modelProperty.indexOf(o); + if (oldIndex < maxIndex) { + modelProperty.move(oldIndex, oldIndex + 1); + } + } + + IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray()); + treeViewer.setSelection(selectionCopy); + + commit(); + } + + /** + * Handle edit Action + */ + protected void editAction() { + IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); + + if (selection.size() != 1) { + return; + } + + TreeItem selectedItem = treeViewer.getTree().getSelection()[0]; + Tree parentTree = selectedItem.getParent(); + + final int index = parentTree.indexOf(selectedItem); + final Object currentValue = selection.getFirstElement(); + + getOperationExecutor(currentValue).execute(new Runnable() { + + @SuppressWarnings("unchecked") + @Override + public void run() { + Object newValue = referenceFactory.edit(MultipleValueEditor.this.edit, currentValue); + + if (newValue != currentValue && newValue != null) { + modelProperty.remove(index); + modelProperty.add(index, newValue); + + // commit(); // The commit only occurs in the case where we modify the list (We don't commit direct edition on objects) + } + + commit(); + } + }, NLS.bind(Messages.MultipleValueEditor_editOperation, labelText)); + } + + /** + * Sets the {@link ReferenceValueFactory} for this editor. The {@link ReferenceValueFactory} is used to create + * new instances and edit existing ones. + * + * @param factory + * The {@link ReferenceValueFactory} to be used by this editor + */ + public void setFactory(ReferenceValueFactory factory) { + this.referenceFactory = factory; + updateControls(); + } + + /** + * {@inheritDoc} + */ + @Override + public void widgetDefaultSelected(SelectionEvent e) { + if ((e.widget == tree) && (edit != null) && edit.isEnabled()) { + editAction(); + } + } + + /** + * Gets the tree viewer associated to this editor + * + * @return the tree viewer associated to this editor + */ + public TreeViewer getViewer() { + return treeViewer; + } + + /** + * Refreshes the viewer when a change occurs on the ObservableList + * TODO : Problem : a change occurring on an element of the list is not sent here + * TODO : When undoing a command, the change event is not received (Although it modifies the list itself) + * + * @see org.eclipse.core.databinding.observable.IChangeListener#handleChange(org.eclipse.core.databinding.observable.ChangeEvent) + * + * @param event + */ + @Override + public void handleChange(ChangeEvent event) { + if (!isDisposed()) { + treeViewer.refresh(); + } + } + + @Override + public void dispose() { + if (modelProperty != null) { + modelProperty.removeChangeListener(this); + } + super.dispose(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + updateControls(); + // tree.setEnabled(!readOnly); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isReadOnly() { + return !tree.isEnabled(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setLabel(String label) { + if (this.label == null) { + setLayout(new GridLayout(2, false)); + } + super.setLabel(label); + } + + @Override + public void setToolTipText(String text) { + tree.setToolTipText(text); + super.setLabelToolTipText(text); + } + + @Override + public void setModelObservable(IObservableList modelProperty) { + super.setModelObservable(modelProperty); + updateControls(); + } + + @Override + public void refreshValue() { + treeViewer.refresh(); + } + + /** + * Sets the direct creation mode. + * If direct creation is set to true, the {@link ReferenceValueFactory#createObject(org.eclipse.swt.widgets.Control)} method will be called when + * to add button is pressed. + * Otherwise, the dialog will be used. + * + * @param directCreation + */ + public void setDirectCreation(boolean directCreation) { + this.directCreation = directCreation; + updateControls(); + } + + /** + * Adds a ISelectionChangedListener to this widget + * + * @param listener + */ + public void addSelectionChangedListener(ISelectionChangedListener listener) { + treeViewer.addSelectionChangedListener(listener); + } + + /** + * Removes a ISelectionChangedListener from this widget + * + * @param listener + */ + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + treeViewer.removeSelectionChangedListener(listener); + } + + /** + * Set the maximum number of values selected. + * + * @param upperBound + */ + public void setUpperBound(int upperBound) { + this.upperBound = upperBound; + } + + public void updateBoutons() { + /* Disable the button 'add' if the upperBound is reached */ + if (this.upperBound != MANY) { + if (modelProperty.size() >= this.upperBound) { + add.setEnabled(false); + } else { + add.setEnabled(true); + } + } + } + + @Override + public void changeColorField() { + // nothing to do here + + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectionDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectionDialog.java new file mode 100644 index 00000000000..acab12ca40b --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectionDialog.java @@ -0,0 +1,315 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Adapted code from MultipleValueSelectorDialog + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.List; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.util.ValueUtils; +import org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWidget; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.SelectionDialog; + +/** + * Object Chooser. Defines a standard popup for selecting + * multiple values. If this dialog is used to select or create model + * elements to be added to or removed from some element that is being + * edited, then it is important to {@linkplain #setContextElement(Object) set that contextual element} in this dialog. + * + * @author Vincent Lorenzo + * + * @see #setContextElement(Object) + * + */ +public class MultipleValueSelectionDialog extends SelectionDialog { + + /** + * the widget providing the contents of the dialog + */ + protected MultipleValueSelectionWidget widget; + + /** + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + */ + public MultipleValueSelectionDialog(Shell parentShell, IElementSelector selector) { + this(parentShell, selector, null, false, false); + } + + /** + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + * @param title + * The title of this dialog + */ + public MultipleValueSelectionDialog(Shell parentShell, IElementSelector selector, String title) { + this(parentShell, selector, title, false, false); + } + + /** + * + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + * @param unique + * True if the values returned by this dialog should be unique + */ + public MultipleValueSelectionDialog(Shell parentShell, IElementSelector selector, boolean unique) { + this(parentShell, selector, null, unique, false); + } + + /** + * + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + * @param title + * The title of this dialog + * @param unique + * True if the values returned by this dialog should be unique + */ + public MultipleValueSelectionDialog(Shell parentShell, IElementSelector selector, String title, boolean unique, boolean ordered) { + this(parentShell, selector, title, unique, false, ValueUtils.MANY); + } + + /** + * + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + * @param title + * The title of this dialog + * @param unique + * True if the values returned by this dialog should be unique + * @param upperBound + * The maximum number of values selected. + */ + public MultipleValueSelectionDialog(Shell parentShell, IElementSelector selector, String title, boolean unique, boolean ordered, int upperBound) { + super(parentShell); + Assert.isNotNull(selector, "The element selector should be defined"); //$NON-NLS-1$ + setHelpAvailable(false); + setTitle(title); + this.widget = createWidget(selector, unique, ordered, upperBound); + } + + /** + * + * @param selector + * The element selector used by this dialog + * @param unique + * True if the values returned by this dialog should be unique + * @param ordered + * <code>true</code> if the edited feature is ordered + * @param upperBound + * The maximum number of values selected. + */ + protected MultipleValueSelectionWidget createWidget(IElementSelector selector, boolean unique, boolean ordered, int upperBound) { + return new MultipleValueSelectionWidget(selector, unique, ordered, upperBound); + } + + /** + * + * @see org.eclipse.ui.dialogs.SelectionDialog#configureShell(org.eclipse.swt.widgets.Shell) + * + * @param shell + */ + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setImage(org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage("/icons/papyrus.png")); //$NON-NLS-1$ + } + + /** + * @see org.eclipse.ui.dialogs.SelectionDialog#setInitialElementSelections(java.util.List) + * + * @param selectedElements + */ + @Override + public void setInitialElementSelections(@SuppressWarnings("rawtypes") List selectedElements) { + super.setInitialElementSelections(selectedElements); + widget.setInitialSelections(getInitialElementSelections()); + } + + + /** + * @see org.eclipse.ui.dialogs.SelectionDialog#setInitialSelections(java.lang.Object[]) + * + * @param selectedElements + */ + @Override + public void setInitialSelections(Object[] selectedElements) { + super.setInitialSelections(selectedElements); + widget.setInitialSelections(getInitialElementSelections()); + } + + /** + * {@inheritDoc} + */ + @Override + public void create() { + super.create(); + createDialogContents(); + getShell().pack(); + + this.widget.updateControls(); + + } + + /** + * Create the contents of the dialog + */ + protected void createDialogContents() { + Composite parent = getDialogArea(); + this.widget.create(parent); + } + + /** + * {@inheritDoc} + */ + @Override + protected Composite getDialogArea() { + return (Composite) super.getDialogArea(); + } + + + /** + * Sets the {@link ReferenceValueFactory} for this editor. The {@link ReferenceValueFactory} is used to create + * new instances and edit existing ones. + * + * @param factory + * The {@link ReferenceValueFactory} to be used by this editor + */ + public void setFactory(ReferenceValueFactory factory) { + this.widget.setFactory(factory); + } + + /** + * + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + * + */ + @Override + protected void okPressed() { + setResult(this.widget.getSelection()); + super.okPressed(); + } + + /** + * Indicates if the selected values should be unique (According to Object.equals()) + * + * @param unique + */ + public void setUnique(boolean unique) { + this.widget.setUnique(unique); + } + + /** + * Indicates if the selected elements should be ordered + * + * @param ordered + */ + public void setOrdered(boolean ordered) { + this.widget.setOrdered(ordered); + } + + /** + * Set the selector to use + * + * @param selector + * the selector to use in the dialog + */ + public void setSelector(IElementSelector selector) { + this.widget.setSelector(selector); + } + + /** + * Set the maximum number of values selected. + * + * @param upperBound + */ + public void setUpperBound(int upperBound) { + this.widget.setUpperBound(upperBound); + } + + /** + * Sets the optional context of the element that is being edited, in which others will be added and removed. + * + * @param contextElement + * the model element that is being edited + */ + public void setContextElement(Object contextElement) { + this.widget.setContextElement(contextElement); + } + + /** + * Queries the optional context of the element that is being edited, in which others will be added and removed. + * + * @return the model element that is being edited + */ + public Object getContextElement() { + return this.widget.getContextElement(); + } + + /** + * + * @see org.eclipse.jface.dialogs.Dialog#close() + * + * @return + */ + @Override + public boolean close() { + if (this.widget != null) { + this.widget.dispose(); + } + return super.close(); + } + + /** + * Sets the label provider used to display the selected elements + * + * @param labelProvider + */ + public void setLabelProvider(ILabelProvider labelProvider) { + this.widget.setLabelProvider(labelProvider); + } + + /** + * + * @return + * the widget + */ + protected MultipleValueSelectionWidget getWidget() { + return this.widget; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectionWithCheckBoxDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectionWithCheckBoxDialog.java new file mode 100644 index 00000000000..78b7823878f --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectionWithCheckBoxDialog.java @@ -0,0 +1,158 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWidget; +import org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWithCheckboxWidget; +import org.eclipse.swt.widgets.Shell; + +/** + * This dialog adds a checkbox at the end of the {@link MultipleValueSelectorDialog} + * + * @author vl222926 + * + */ +public class MultipleValueSelectionWithCheckBoxDialog extends MultipleValueSelectionDialog { + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + * @param unique + */ + public MultipleValueSelectionWithCheckBoxDialog(Shell parentShell, IElementSelector selector, boolean unique) { + super(parentShell, selector, unique); + } + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + * @param title + * @param unique + * @param ordered + * @param upperBound + */ + public MultipleValueSelectionWithCheckBoxDialog(Shell parentShell, IElementSelector selector, String title, boolean unique, boolean ordered, int upperBound) { + super(parentShell, selector, title, unique, ordered, upperBound); + } + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + * @param title + * @param unique + * @param ordered + */ + public MultipleValueSelectionWithCheckBoxDialog(Shell parentShell, IElementSelector selector, String title, boolean unique, boolean ordered) { + super(parentShell, selector, title, unique, ordered); + } + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + * @param title + */ + public MultipleValueSelectionWithCheckBoxDialog(Shell parentShell, IElementSelector selector, String title) { + super(parentShell, selector, title); + } + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + */ + public MultipleValueSelectionWithCheckBoxDialog(Shell parentShell, IElementSelector selector) { + super(parentShell, selector); + } + + /** + * @see org.eclipse.papyrus.infra.widgets.editors.MultipleValueSelectionDialog#createWidget(org.eclipse.papyrus.infra.widgets.editors.IElementSelector, boolean, boolean, int) + * + * @param selector + * @param unique + * @param ordered + * @param upperbound + * @return + */ + @Override + protected MultipleValueSelectionWidget createWidget(IElementSelector selector, boolean unique, boolean ordered, int upperbound) { + return new MultipleValueSelectionWithCheckboxWidget(selector, unique, ordered, upperbound); + } + + /** + * + * @return + * the widget + */ + /** + * @see org.eclipse.papyrus.infra.widgets.editors.MultipleValueSelectionDialog#getWidget() + * + * @return + */ + @Override + protected MultipleValueSelectionWithCheckboxWidget getWidget() { + return (MultipleValueSelectionWithCheckboxWidget) super.getWidget(); + } + + /** + * + * @param text + * the text to display near the checkbox + * @param tooltip + * the tooltip to display for the checkbox + * @param isChecked + * the initial state of the checkbox + */ + public void setCheckBoxValues(final String text, final String tooltip, final boolean isChecked) { + MultipleValueSelectionWithCheckboxWidget w = getWidget(); + w.setCheckBoxValues(text, tooltip, isChecked); + } + + /** + * this method allows to display or hide the checkbox + */ + public void setDisplayCheckBox(boolean displayCheckBox) { + getWidget().setDisplayCheckBox(displayCheckBox); + } + + /** + * + * @return + * the state of the checkbox button + */ + public boolean isChecked() { + return getWidget().isChecked(); + } + + /** + * + * @return <code>true</code> if the checkbox must be displayed + */ + public boolean isDisplayingCheckBox() { + return getWidget().isDisplayingCheckBox(); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialog.java new file mode 100644 index 00000000000..64256737146 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialog.java @@ -0,0 +1,777 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + * Christian W. Damus (CEA) - bug 402525 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.Set; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.CollectionContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.dialogs.SelectionDialog; + +/** + * Object Chooser. Defines a standard popup for selecting + * multiple values. If this dialog is used to select or create model + * elements to be added to or removed from some element that is being + * edited, then it is important to {@linkplain #setContextElement(Object) set that contextual element} in this dialog. + * + * @author Camille Letavernier + * + * @see #setContextElement(Object) + * + * @deprecated use MultipleValueSelectionDialog instead + * @since Papyrus 1.1 + */ +@Deprecated +public class MultipleValueSelectorDialog extends SelectionDialog implements ISelectionChangedListener, IDoubleClickListener, IElementSelectionListener, SelectionListener { + + public static final int MANY = -1; + + /** + * The object selector + */ + protected IElementSelector selector; + + /** + * The SWT Composite in which the selector is drawn + */ + protected Composite selectorSection; + + /** + * The add/remove/addAll buttons section + */ + protected Composite buttonsSection; + + /** + * The up/down buttons section + */ + protected Composite rightButtonsSection; + + /** + * The listViewer for chosen elements + */ + protected StructuredViewer selectedElementsViewer; + + /** + * The list for chosen elements + */ + protected Tree selectedElements; + + /** + * The add action button + */ + protected Button add; + + /** + * The create action button + */ + protected Button create; + + /** + * The delete action button + */ + protected Button delete; + + /** + * The remove action button + */ + protected Button remove; + + /** + * The add all action button + */ + protected Button addAll; + + /** + * The remove all action button + */ + protected Button removeAll; + + /** + * the up action button + */ + protected Button up; + + /** + * the down action button + */ + protected Button down; + + /** + * The label provider for the listViewer of chosen elements + */ + protected ILabelProvider labelProvider; + + /** + * The currently chosen elements + */ + protected final Collection<Object> allElements; + + /** + * Indicates if the values should be unique (according to Object.equals()) + */ + protected boolean unique; + + /** + * Indicates if the list is ordered + */ + protected boolean ordered; + + /** + * The factory for creating new elements + */ + protected ReferenceValueFactory factory; + + /** + * The model element being edited (if any), to which elements are to be added or removed. + */ + protected Object contextElement; + + /** + * The list of newly created objects + */ + protected Set<Object> newObjects = new HashSet<Object>(); + + + /** + * The maximum number of values selected. + */ + protected int upperBound; + + /** + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + */ + public MultipleValueSelectorDialog(Shell parentShell, IElementSelector selector) { + this(parentShell, selector, null, false, false); + } + + /** + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + * @param title + * The title of this dialog + */ + public MultipleValueSelectorDialog(Shell parentShell, IElementSelector selector, String title) { + this(parentShell, selector, title, false, false); + } + + /** + * + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + * @param unique + * True if the values returned by this dialog should be unique + */ + public MultipleValueSelectorDialog(Shell parentShell, IElementSelector selector, boolean unique) { + this(parentShell, selector, null, unique, false); + } + + /** + * + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + * @param title + * The title of this dialog + * @param unique + * True if the values returned by this dialog should be unique + */ + public MultipleValueSelectorDialog(Shell parentShell, IElementSelector selector, String title, boolean unique, boolean ordered) { + this(parentShell, selector, title, unique, false, MANY); + } + + /** + * + * Constructor. + * + * @param parentShell + * The shell in which this dialog should be opened + * @param selector + * The element selector used by this dialog + * @param title + * The title of this dialog + * @param unique + * True if the values returned by this dialog should be unique + * @param upperBound + * The maximum number of values selected. + */ + public MultipleValueSelectorDialog(Shell parentShell, IElementSelector selector, String title, boolean unique, boolean ordered, int upperBound) { + super(parentShell); + Assert.isNotNull(selector, "The element selector should be defined"); //$NON-NLS-1$ + this.selector = selector; + allElements = unique ? new LinkedHashSet<Object>() : new LinkedList<Object>(); + setHelpAvailable(false); + setTitle(title); + this.unique = unique; + this.ordered = ordered; + this.upperBound = upperBound; + selector.addElementSelectionListener(this); + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setImage(Activator.getDefault().getImage("/icons/papyrus.png")); //$NON-NLS-1$ + } + + + /** + * {@inheritDoc} + */ + @Override + public void create() { + super.create(); + createDialogContents(); + getShell().pack(); + + updateControls(); + } + + /** + * Create the contents of the dialog + */ + protected void createDialogContents() { + Composite parent = getDialogArea(); + GridLayout layout = (GridLayout) parent.getLayout(); + layout.numColumns = 2; + layout.makeColumnsEqualWidth = true; + + Composite selectorPane = new Composite(parent, SWT.NONE); + selectorPane.setLayout(new GridLayout(2, false)); + selectorPane.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + Composite selectedPane = new Composite(parent, SWT.NONE); + selectedPane.setLayout(new GridLayout(2, false)); + selectedPane.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + createSelectorSection(selectorPane); + createControlsSection(selectorPane); + createListSection(selectedPane); + createRightButtonsSection(selectedPane); + } + + /** + * {@inheritDoc} + */ + @Override + protected Composite getDialogArea() { + return (Composite) super.getDialogArea(); + } + + /** + * Creates the selector section + * + * @param parent + * The composite in which the section is created + */ + private void createSelectorSection(Composite parent) { + selectorSection = new Composite(parent, SWT.NONE); + selectorSection.setLayout(new FillLayout()); + selectorSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + selector.createControls(selectorSection); + } + + /** + * Creates the main controls section (Add, remove, Add all, remove all) + * + * @param parent + * The composite in which the section is created + */ + private void createControlsSection(Composite parent) { + buttonsSection = new Composite(parent, SWT.NONE); + buttonsSection.setLayout(new GridLayout(1, true)); + + add = new Button(buttonsSection, SWT.PUSH); + add.setImage(Activator.getDefault().getImage("/icons/arrow_right.gif")); //$NON-NLS-1$ + add.addSelectionListener(this); + add.setToolTipText(Messages.MultipleValueSelectorDialog_AddSelectedElements); + + remove = new Button(buttonsSection, SWT.PUSH); + remove.setImage(Activator.getDefault().getImage("/icons/arrow_left.gif")); //$NON-NLS-1$ + remove.addSelectionListener(this); + remove.setToolTipText(Messages.MultipleValueEditor_RemoveSelectedElements); + + addAll = new Button(buttonsSection, SWT.PUSH); + addAll.setImage(Activator.getDefault().getImage("/icons/arrow_double.gif")); //$NON-NLS-1$ + addAll.addSelectionListener(this); + addAll.setToolTipText(Messages.MultipleValueSelectorDialog_AddAllElements); + + /* Disable the bouton 'addAll' if currently chosen elements is greater than the maximum number of values selected */ + if (this.upperBound != MANY && allElements.size() > this.upperBound) { + addAll.setEnabled(false); + } + + + removeAll = new Button(buttonsSection, SWT.PUSH); + removeAll.setImage(Activator.getDefault().getImage("/icons/arrow_left_double.gif")); //$NON-NLS-1$ + removeAll.addSelectionListener(this); + removeAll.setToolTipText(Messages.MultipleValueSelectorDialog_RemoveAllElements); + } + + /** + * Creates the list displaying the currently selected elements + * + * @param parent + * The composite in which the section is created + */ + private void createListSection(Composite parent) { + + selectedElements = new Tree(parent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + // selectedElements.addSelectionListener(this); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + selectedElements.setLayoutData(data); + selectedElementsViewer = new TreeViewer(selectedElements); + + selectedElementsViewer.addSelectionChangedListener(this); + selectedElementsViewer.addDoubleClickListener(this); + + selectedElementsViewer.setContentProvider(CollectionContentProvider.instance); + + if (labelProvider != null) { + selectedElementsViewer.setLabelProvider(labelProvider); + } + + selectedElementsViewer.setInput(allElements); + selector.setSelectedElements(allElements.toArray()); + } + + /** + * Creates the up/down controls section + * + * @param parent + * The composite in which the section is created + */ + private void createRightButtonsSection(Composite parent) { + rightButtonsSection = new Composite(parent, SWT.NONE); + rightButtonsSection.setLayout(new GridLayout(1, true)); + + up = new Button(rightButtonsSection, SWT.PUSH); + up.setImage(Activator.getDefault().getImage("/icons/Up_12x12.gif")); //$NON-NLS-1$ + up.addSelectionListener(this); + up.setToolTipText(Messages.MultipleValueEditor_MoveSelectedElementsUp); + + down = new Button(rightButtonsSection, SWT.PUSH); + down.setImage(Activator.getDefault().getImage("/icons/Down_12x12.gif")); //$NON-NLS-1$ + down.addSelectionListener(this); + down.setToolTipText(Messages.MultipleValueEditor_MoveSelectedElementsDown); + + create = new Button(rightButtonsSection, SWT.PUSH); + create.setImage(Activator.getDefault().getImage("/icons/Add_12x12.gif")); //$NON-NLS-1$ + create.addSelectionListener(this); + create.setToolTipText(Messages.MultipleValueSelectorDialog_CreateNewElement); + + delete = new Button(rightButtonsSection, SWT.PUSH); + delete.setImage(Activator.getDefault().getImage("/icons/Delete_12x12.gif")); //$NON-NLS-1$ + delete.addSelectionListener(this); + delete.setToolTipText(Messages.MultipleValueSelectorDialog_DeleteNewElement); + delete.setEnabled(false); + } + + /** + * Sets the label provider used to display the selected elements + * + * @param labelProvider + */ + public void setLabelProvider(ILabelProvider labelProvider) { + this.labelProvider = labelProvider; + } + + /** + * {@inheritDoc} Handles the events on one of the control buttons + * + * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) + * + * @param e + * The event that occurred + */ + @Override + public void widgetSelected(SelectionEvent e) { + if (e.widget == add) { + addAction(); + } else if (e.widget == remove) { + removeAction(); + } else if (e.widget == addAll) { + addAllAction(); + } else if (e.widget == removeAll) { + removeAllAction(); + } else if (e.widget == up) { + upAction(); + } else if (e.widget == down) { + downAction(); + } else if (e.widget == create) { + createAction(); + } + + updateControls(); + } + + /** + * Sets the {@link ReferenceValueFactory} for this editor. The {@link ReferenceValueFactory} is used to create + * new instances and edit existing ones. + * + * @param factory + * The {@link ReferenceValueFactory} to be used by this editor + */ + public void setFactory(ReferenceValueFactory factory) { + this.factory = factory; + updateControls(); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public int open() { + allElements.clear(); + allElements.addAll(getInitialElementSelections()); + return super.open(); + } + + /** + * Handles the "Add" action + */ + protected void addAction() { + Object[] elements = selector.getSelectedElements(); + addElements(elements); + } + + /** + * Handles the "Up" action + */ + protected void upAction() { + IStructuredSelection selection = (IStructuredSelection) selectedElementsViewer.getSelection(); + + // We need a list to move objects. LinkedHashSet can't do that + java.util.List<Object> list = new LinkedList<Object>(allElements); + for (Object o : selection.toArray()) { + int oldIndex = list.indexOf(o); + if (oldIndex > 0) { + move(list, oldIndex, oldIndex - 1); + } + } + + allElements.clear(); + allElements.addAll(list); + + IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray()); + selectedElementsViewer.setSelection(selectionCopy); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Down" action + */ + protected void downAction() { + IStructuredSelection selection = (IStructuredSelection) selectedElementsViewer.getSelection(); + + // We need a list to move objects. LinkedHashSet can't do that + java.util.List<Object> list = new LinkedList<Object>(allElements); + + int maxIndex = list.size() - 1; + + Object[] selectionArray = selection.toArray(); + for (int i = selectionArray.length - 1; i >= 0; i--) { + Object o = selectionArray[i]; + int oldIndex = list.indexOf(o); + if (oldIndex < maxIndex) { + move(list, oldIndex, oldIndex + 1); + } + } + + allElements.clear(); + allElements.addAll(list); + + IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray()); + selectedElementsViewer.setSelection(selectionCopy); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Create" action + */ + protected void createAction() { + if (factory == null) { + return; + } + + Object newObject; + + try { + newObject = factory.createObject(this.create, contextElement); + } catch (OperationCanceledException e) { + // The user cancelled and we rolled back pending model changes + newObject = null; + } + + if (newObject == null) { + return; + } + + newObjects.add(newObject); + selector.newObjectCreated(newObject); + + Object[] createdObjects = new Object[] { newObject }; + addElements(createdObjects); + + selector.setSelectedElements(allElements.toArray()); + } + + /** + * Moves an element from oldIndex to newIndex + * + * @param list + * The list in which to move the object + * @param oldIndex + * @param newIndex + */ + private void move(java.util.List<Object> list, int oldIndex, int newIndex) { + int size = list.size(); + + if (oldIndex < 0 || oldIndex >= size) { + throw new IndexOutOfBoundsException("oldIndex: " + oldIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ + } + if (newIndex < 0 || newIndex >= size) { + throw new IndexOutOfBoundsException("newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ + } + Object element = list.remove(oldIndex); + list.add(newIndex, element); + } + + /** + * Handles the "Remove" action + */ + protected void removeAction() { + IStructuredSelection selection = (IStructuredSelection) selectedElementsViewer.getSelection(); + if (selection.isEmpty()) { + return; + } + + for (Object element : selection.toArray()) { + allElements.remove(element); + } + + selector.setSelectedElements(allElements.toArray()); + selectedElementsViewer.setSelection(null); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Delete" action + */ + protected void deleteAction() { + // nothing to do here + } + + /** + * Handles the "Remove all" action + */ + protected void removeAllAction() { + allElements.clear(); + selector.setSelectedElements(new Object[0]); + selectedElementsViewer.setSelection(null); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Add All" action + */ + protected void addAllAction() { + Object[] elements = selector.getAllElements(); + addElements(elements); + } + + /** + * Adds the specified elements to the currently selected elements (For + * "Add" and "Add all" actions) + * + * @param elements + * The elements to be added + */ + @Override + public void addElements(Object[] elements) { + if (elements != null) { + allElements.addAll(Arrays.asList(elements)); + selectedElementsViewer.refresh(); + } + } + + @Override + protected void okPressed() { + if (factory != null) { + java.util.List<Object> objectsToValidate = new LinkedList<Object>(); + for (Object object : newObjects) { + if (allElements.contains(object)) { + objectsToValidate.add(object); + } + } + factory.validateObjects(objectsToValidate); + selector.clearTemporaryElements(); + } + + setResult(new LinkedList<Object>(allElements)); + + super.okPressed(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing (see #doubleClick()) + } + + /** + * Indicates if the selected values should be unique (According to Object.equals()) + * + * @param unique + */ + public void setUnique(boolean unique) { + this.unique = unique; + updateControls(); + } + + /** + * Indicates if the selected elements should be ordered + * + * @param ordered + */ + public void setOrdered(boolean ordered) { + this.ordered = ordered; + updateControls(); + } + + private void updateControls() { + updateControl(up, ordered); + updateControl(down, ordered); + updateControl(create, this.factory != null && this.factory.canCreateObject()); + + /* Disable the bouton 'add' if the upperBound is reached */ + boolean canAdd = true; + if (this.upperBound != MANY) { + if (allElements.size() >= this.upperBound) { + canAdd = false; + } + } + updateControl(add, canAdd); + } + + private void updateControl(Control control, boolean enabled) { + if (control != null) { + control.setEnabled(enabled); + } + } + + public void setSelector(IElementSelector selector) { + this.selector = selector; + } + + /** + * Set the maximum number of values selected. + * + * @param upperBound + */ + public void setUpperBound(int upperBound) { + this.upperBound = upperBound; + } + + /** + * Sets the optional context of the element that is being edited, in which others will be added and removed. + * + * @param contextElement + * the model element that is being edited + */ + public void setContextElement(Object contextElement) { + this.contextElement = contextElement; + } + + /** + * Queries the optional context of the element that is being edited, in which others will be added and removed. + * + * @return the model element that is being edited + */ + public Object getContextElement() { + return contextElement; + } + + @Override + public boolean close() { + selector.removeElementSelectionListener(this); + return super.close(); + } + + /** + * {@inheritDoc} + * + * Handles double click event on the right-panel tree viewer {@link #selectedElementsViewer} + * + */ + @Override + public void doubleClick(DoubleClickEvent event) { + removeAction(); + } + + /** + * {@inheritDoc} + * + * Handles selection change event on the right-panel tree viewer {@link #selectedElementsViewer} + */ + @Override + public void selectionChanged(SelectionChangedEvent event) { + updateControls(); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialogWithCheckBox.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialogWithCheckBox.java new file mode 100644 index 00000000000..7d52b37c49b --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultipleValueSelectorDialogWithCheckBox.java @@ -0,0 +1,180 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; + +/** + * This dialog adds a checkbox at the end of the {@link MultipleValueSelectorDialog} + * + * @author vl222926 + * + * @deprecated use {@link MultipleValueSelectionWithCheckBoxDialog} instead + * @since Papyrus 1.1.0 + */ +@Deprecated +public class MultipleValueSelectorDialogWithCheckBox extends MultipleValueSelectorDialog { + + /** boolean indicating if the checkbox is checked */ + protected boolean isChecked; + + /** The text to display for the checkbox */ + protected String text; + + /** the tooltip to display for the checkbox */ + protected String tooltip; + + /** indicates if the checkbox must be displayed or not */ + protected boolean displayCheckBox = true; + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + * @param unique + */ + public MultipleValueSelectorDialogWithCheckBox(Shell parentShell, IElementSelector selector, boolean unique) { + super(parentShell, selector, unique); + } + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + * @param title + * @param unique + * @param ordered + * @param upperBound + */ + public MultipleValueSelectorDialogWithCheckBox(Shell parentShell, IElementSelector selector, String title, boolean unique, boolean ordered, int upperBound) { + super(parentShell, selector, title, unique, ordered, upperBound); + } + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + * @param title + * @param unique + * @param ordered + */ + public MultipleValueSelectorDialogWithCheckBox(Shell parentShell, IElementSelector selector, String title, boolean unique, boolean ordered) { + super(parentShell, selector, title, unique, ordered); + } + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + * @param title + */ + public MultipleValueSelectorDialogWithCheckBox(Shell parentShell, IElementSelector selector, String title) { + super(parentShell, selector, title); + } + + /** + * + * Constructor. + * + * @param parentShell + * @param selector + */ + public MultipleValueSelectorDialogWithCheckBox(Shell parentShell, IElementSelector selector) { + super(parentShell, selector); + } + + /** + * + * @param text + * the text to display near the checkbox + * @param tooltip + * the tooltip to display for the checkbox + * @param isChecked + * the initial state of the checkbox + */ + public void setCheckBoxValues(final String text, final String tooltip, final boolean isChecked) { + this.text = text; + this.tooltip = tooltip; + this.isChecked = isChecked; + } + + /** + * this method allows to display or hide the checkbox + */ + public void setDisplayCheckBox(boolean displayCheckBox) { + this.displayCheckBox = displayCheckBox; + } + + /** + * + * @return + * <code>true</code> if the disalog is displaying the checkbox + */ + public boolean isDisplayingCheckBox() { + return this.displayCheckBox; + } + + /** + * We Add a checkbox at the end of the dialog + * + * @see org.eclipse.papyrus.infra.widgets.editors.MultipleValueSelectorDialog#createDialogContents() + * + */ + @Override + protected void createDialogContents() { + super.createDialogContents(); + if (this.displayCheckBox) { + final Composite parent = getDialogArea(); + final Button button = new Button(parent, SWT.CHECK); + button.setText(this.text); + button.setToolTipText(this.tooltip); + button.setSelection(this.isChecked); + final SelectionListener listener = new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + isChecked = button.getSelection(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }; + button.addSelectionListener(listener); + } + } + + + /** + * + * @return + * the state of the checkbox button + */ + public boolean isChecked() { + return this.isChecked; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultiplicityDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultiplicityDialog.java new file mode 100644 index 00000000000..d110af0edff --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/MultiplicityDialog.java @@ -0,0 +1,626 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST. + * + * 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: + * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue@all4tec.net - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.List; + +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.util.MultiplicityConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Widget; + +/** + * The multiplicity dialog which allow to define 2 'modes' : The simple mode with a string combo editor and the advanced with 2 editors of ValueSpecification. + */ +public class MultiplicityDialog extends AbstractValueEditor implements SelectionListener, IChangeListener { + + /** + * The string combo index in the list of editors. + */ + protected static final int MULTIPLICITY_STRING_COMBO_INDEX = 0; + + /** + * The lower value editor index in the list of editors. + */ + protected static final int MULTIPLICITY_LOWER_VALUE_INDEX = 1; + + /** + * The upper value editor index in the list of editors. + */ + protected static final int MULTIPLICITY_UPPER_VALUE_INDEX = 2; + + + /** + * The stack layout for the 'mode' of editor to display. + */ + protected StackLayout stackLayout; + + /** + * The string combo editor for the 'simple' mode. + */ + protected StringCombo stringComboEditor; + + /** + * The parent stack layout composite. + */ + protected Composite stackLayoutComposite; + + /** + * The composite which contains the 'advanced' mode editors. + */ + protected Composite doubleEditorsComposite; + + /** + * The lower value specification editor. + */ + protected AbstractReferenceDialog lowerValueEditor; + + /** + * The upper value specification editor. + */ + protected AbstractReferenceDialog upperValueEditor; + + /** + * The switch editors button. + */ + protected Button switchEditorsButton; + + /** + * Boolean to determinate if the editors are read-only. + */ + protected boolean readOnly; + + /** + * The preference store. + */ + protected IPreferenceStore preferenceStore; + + + /** + * Constructor. + * + * @param parent + * The parent composite. + * @param style + * The style. + */ + public MultiplicityDialog(final Composite parent, final int style) { + this(parent, style, null); + } + + /** + * Constructor. + * + * @param parent + * The parent composite. + * @param style + * The style. + * @param preferenceStore + * The preference store. + */ + public MultiplicityDialog(final Composite parent, final int style, final IPreferenceStore preferenceStore) { + super(parent, style); + + // Create the stack layout composite + stackLayout = new StackLayout(); + stackLayoutComposite = new Composite(this, style); + stackLayoutComposite.setLayout(stackLayout); + stackLayoutComposite.setLayoutData(getDefaultLayoutData()); + + // Create the string combo editor + stringComboEditor = new StringCombo(stackLayoutComposite, style) { + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo#doBinding() + */ + @Override + protected void doBinding() { + setWidgetObservable(getObservableValue()); + super.doBinding(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractValueEditor#setModelObservable(org.eclipse.core.databinding.observable.value.IObservableValue) + */ + @Override + public void setModelObservable(IObservableValue modelProperty) { + this.modelProperty = modelProperty; + setWidgetObservable(getObservableValue()); + super.setModelObservable(modelProperty); + updateControls(); + } + }; + stringComboEditor.setLayoutData(getDefaultLayoutData()); + + // Create the composite which contains the lower and the upper value specification editors + doubleEditorsComposite = new Composite(stackLayoutComposite, style); + final GridLayout layout = new GridLayout(2, true); + // Manage the height and the width (for a better visualization) + layout.marginWidth = 0; + layout.marginHeight = 0; + doubleEditorsComposite.setLayout(layout); + doubleEditorsComposite.setLayoutData(getDefaultLayoutData()); + + // Create the lower ValueSpecification editor + lowerValueEditor = createLowerValueSpecificationEditor(doubleEditorsComposite, style); + lowerValueEditor.setLayoutData(getDefaultLayoutData()); + + // Create the upper ValueSpecification editor + upperValueEditor = createUpperValueSpecificationEditor(doubleEditorsComposite, style); + upperValueEditor.setLayoutData(getDefaultLayoutData()); + + // Add a property change listener on the preference + this.preferenceStore = preferenceStore; + if (null != preferenceStore) { + this.preferenceStore.addPropertyChangeListener(new IPropertyChangeListener() { + + @Override + public void propertyChange(final PropertyChangeEvent event) { + displayTopControl(); + } + }); + } + + displayTopControl(); + + createButtons(); + updateControls(); + } + + /** + * This allow to create the lower ValueSpecification editor. + * + * @param parent + * The parent composite + * @param style + * The style. + * @return The create lower ValueSpecification editor. + */ + protected AbstractReferenceDialog createLowerValueSpecificationEditor(final Composite parent, final int style) { + return createValueSpecificationEditor(parent, style); + } + + /** + * This allow to create the upper ValueSpecification editor. + * + * @param parent + * The parent composite + * @param style + * The style. + * @return The create upper ValueSpecification editor. + */ + protected AbstractReferenceDialog createUpperValueSpecificationEditor(final Composite parent, final int style) { + return createValueSpecificationEditor(parent, style); + } + + /** + * This allow to create the ValueSpecification editor. + * + * @param parent + * The parent composite + * @param style + * The style. + * @return The create ValueSpecification editor. + */ + protected AbstractReferenceDialog createValueSpecificationEditor(final Composite parent, final int style) { + return new ReferenceDialog(parent, style); + } + + /** + * This allow to create the buttons. + */ + protected void createButtons() { + ((GridLayout) getLayout()).numColumns++; + + switchEditorsButton = factory.createButton(this, null, SWT.PUSH); + switchEditorsButton.setImage(Activator.getDefault().getImage("/icons/Switch_12x12.gif")); //$NON-NLS-1$ + switchEditorsButton.setToolTipText(Messages.MultiplicityReferenceDialog_SwitchEditors); + switchEditorsButton.addSelectionListener(this); + } + + /** + * This allow to manage the stack layout top control displayed. + */ + protected void displayTopControl() { + final String multiplicityEditorMode = preferenceStore.getString(MultiplicityConstants.MULTIPLICITY_EDITOR_MODE); + if (null != preferenceStore && null != multiplicityEditorMode) { + // If the advanced mode is used, display the double editors composite, else use the simple mode with the string combo + stackLayout.topControl = multiplicityEditorMode.equals(MultiplicityConstants.ADVANCED_MODE) ? doubleEditorsComposite : stringComboEditor; + } else { + if (null == stackLayout.topControl) { + stackLayout.topControl = stringComboEditor; + } + } + + if (!stackLayoutComposite.isDisposed()) { + stackLayoutComposite.layout(); + } + setReadOnly(readOnly); + } + + /** + * This allow to define the switch action for the switch buttons. + */ + protected void switchAction() { + if (null != preferenceStore) { + if (stackLayout.topControl.equals(stringComboEditor)) { + preferenceStore.setValue(MultiplicityConstants.MULTIPLICITY_EDITOR_MODE, MultiplicityConstants.ADVANCED_MODE); + } else { + preferenceStore.setValue(MultiplicityConstants.MULTIPLICITY_EDITOR_MODE, MultiplicityConstants.SIMPLE_MODE); + } + } else { + stackLayout.topControl = stackLayout.topControl.equals(stringComboEditor) ? doubleEditorsComposite : stringComboEditor; + } + // Refresh the read only value (because the lower and upper values must be different and multiplicity may not be update by simple editor) + displayTopControl(); + } + + /** + * Updates the displayed label for the current value + */ + protected void updateLabels() { + lowerValueEditor.updateLabel(); + upperValueEditor.updateLabel(); + } + + /** + * This allow to update the controls. + */ + protected void updateControls() { + if (stackLayout.topControl.equals(stringComboEditor)) { + if (!stringComboEditor.isDisposed()) { + stringComboEditor.updateControls(); + } + } else { + if (!lowerValueEditor.isDisposed()) { + lowerValueEditor.updateControls(); + } + + if (!upperValueEditor.isDisposed()) { + upperValueEditor.updateControls(); + } + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.widgets.Control#update() + */ + @Override + public void update() { + super.update(); + if (stackLayout.topControl.equals(stringComboEditor)) { + if (!stringComboEditor.isDisposed()) { + stringComboEditor.update(); + } + } else { + if (!lowerValueEditor.isDisposed()) { + lowerValueEditor.update(); + } + + if (!upperValueEditor.isDisposed()) { + upperValueEditor.update(); + } + } + updateControls(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractListEditor#doBinding() + */ + @Override + protected void doBinding() { + super.doBinding(); + if (null != stringComboEditor) { + stringComboEditor.doBinding(); + } + if (null != lowerValueEditor) { + lowerValueEditor.doBinding(); + } + if (null != upperValueEditor) { + upperValueEditor.doBinding(); + } + modelProperty.addChangeListener(this); + } + + /** + * Sets the content providers. + * + * @param providers + * The content providers for each editor. + */ + public void setContentProviders(final List<IStaticContentProvider> providers) { + stringComboEditor.setContentProvider(getObjectFromList(providers, MULTIPLICITY_STRING_COMBO_INDEX)); + lowerValueEditor.setContentProvider(getObjectFromList(providers, MULTIPLICITY_LOWER_VALUE_INDEX)); + upperValueEditor.setContentProvider(getObjectFromList(providers, MULTIPLICITY_UPPER_VALUE_INDEX)); + } + + /** + * Sets the label providers. + * + * @param providers + * The label providers for each editor. + */ + public void setLabelProviders(final List<ILabelProvider> providers) { + stringComboEditor.setLabelProvider(getObjectFromList(providers, MULTIPLICITY_STRING_COMBO_INDEX)); + lowerValueEditor.setLabelProvider(getObjectFromList(providers, MULTIPLICITY_LOWER_VALUE_INDEX)); + upperValueEditor.setLabelProvider(getObjectFromList(providers, MULTIPLICITY_UPPER_VALUE_INDEX)); + + updateControls(); + updateLabels(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractEditor#getEditableType() + */ + @Override + public Object getEditableType() { + return Object.class; + } + + /** + * This allow to define if the string combo can be edited. + * + * @return <code>true</code> if the string combo can be edited, <code>false</code> otherwise. + */ + protected boolean canEditStringCombo() { + return true; + } + + /** + * This allow to define if the lower value can be edited. + * + * @return <code>true</code> if the lower value can be edited, <code>false</code> otherwise. + */ + protected boolean canEditLowerValue() { + return true; + } + + /** + * This allow to define if the upper value can be edited. + * + * @return <code>true</code> if the upper value can be edited, <code>false</code> otherwise. + */ + protected boolean canEditUpperValue() { + return true; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractListEditor#setModelObservable(org.eclipse.core.databinding.observable.list.IObservableList) + */ + @Override + public void setModelObservable(final IObservableValue modelProperty) { + setWidgetObservable(modelProperty); + setEditorsModelObservable(modelProperty); + super.setModelObservable(modelProperty); + + updateControls(); + updateLabels(); + } + + /** + * Sets the model properties for the editors. + * + * @param modelProperty + * The observable value. + */ + protected void setEditorsModelObservable(final IObservableValue modelProperty) { + if (null != modelProperty && modelProperty.getValue() instanceof List<?>) { + final Object stringComboObservableValue = getObjectFromList((List<?>) modelProperty.getValue(), MULTIPLICITY_STRING_COMBO_INDEX); + if (stringComboObservableValue instanceof IObservableValue) { + stringComboEditor.setModelObservable((IObservableValue) stringComboObservableValue); + } + final Object lowerValueObservableValue = getObjectFromList((List<?>) modelProperty.getValue(), MULTIPLICITY_LOWER_VALUE_INDEX); + if (lowerValueObservableValue instanceof IObservableValue) { + lowerValueEditor.setModelObservable((IObservableValue) lowerValueObservableValue); + } + final Object upperValueObservableValue = getObjectFromList((List<?>) modelProperty.getValue(), MULTIPLICITY_UPPER_VALUE_INDEX); + if (upperValueObservableValue instanceof IObservableValue) { + upperValueEditor.setModelObservable((IObservableValue) upperValueObservableValue); + } + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.widgets.Control#setToolTipText(java.lang.String) + */ + @Override + public void setToolTipText(String text) { + stringComboEditor.setToolTipText(text); + lowerValueEditor.setToolTipText(Messages.MultiplicityReferenceDialog_LowerValueToolTip); + upperValueEditor.setToolTipText(Messages.MultiplicityReferenceDialog_UpperValueToolTip); + } + + /** + * Sets the value factories. + * + * @param factories + * The Reference Value factories. + */ + public void setValueFactories(final List<ReferenceValueFactory> factories) { + lowerValueEditor.setValueFactory(getObjectFromList(factories, MULTIPLICITY_LOWER_VALUE_INDEX)); + upperValueEditor.setValueFactory(getObjectFromList(factories, MULTIPLICITY_UPPER_VALUE_INDEX)); + updateControls(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractEditor#setReadOnly(boolean) + */ + @Override + public void setReadOnly(final boolean readOnly) { + this.readOnly = readOnly; + if (stackLayout.topControl.equals(stringComboEditor)) { + if (!stringComboEditor.isDisposed()) { + stringComboEditor.setReadOnly(readOnly || !canEditStringCombo()); + } + } else { + if (!lowerValueEditor.isDisposed()) { + lowerValueEditor.setReadOnly(readOnly || !canEditLowerValue()); + } + if (!upperValueEditor.isDisposed()) { + upperValueEditor.setReadOnly(readOnly || !canEditUpperValue()); + } + } + updateControls(); + } + + /** + * This allow to set the direct creation of the lower and the upper value editors. + * + * @param directCreation + * The direct creation value. + */ + public void setDirectCreation(final boolean directCreation) { + lowerValueEditor.setDirectCreation(directCreation); + upperValueEditor.setDirectCreation(directCreation); + updateControls(); + } + + /** + * This allow to set the mandatory of the lower and the upper value editors. + * + * @param mandatory + * The mandatory value. + */ + public void setMandatory(final boolean mandatory) { + lowerValueEditor.setMandatory(mandatory); + upperValueEditor.setMandatory(mandatory); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractEditor#isReadOnly() + */ + @Override + public boolean isReadOnly() { + return readOnly; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetSelected(final SelectionEvent e) { + Widget widget = e.widget; + if (widget == switchEditorsButton) { + switchAction(); + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetDefaultSelected(final SelectionEvent e) { + // Nothing + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.widgets.Widget#dispose() + */ + @Override + public void dispose() { + if (null != stringComboEditor) { + stringComboEditor.dispose(); + } + if (null != lowerValueEditor) { + lowerValueEditor.dispose(); + } + if (null != upperValueEditor) { + upperValueEditor.dispose(); + } + super.dispose(); + } + + /** + * Get the object index from the list of objects. + * + * @param listObjects + * The list of objects. + * @param index + * The index object to get. + * @return The object at the index position or <code>null</code>. + */ + protected <T> T getObjectFromList(final List<T> listObjects, final int index) { + T object = null; + if (null != listObjects && !listObjects.isEmpty()) { + if (listObjects.size() > index) { + object = listObjects.get(index); + } + } + return object; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractValueEditor#getValue() + */ + @Override + public Object getValue() { + return modelProperty.getValue(); + } + + /** + * Redefine this method to re-affect the correct observable value to each editors. + * {@inheritDoc} + * + * @see org.eclipse.core.databinding.observable.IChangeListener#handleChange(org.eclipse.core.databinding.observable.ChangeEvent) + */ + @Override + public void handleChange(final ChangeEvent event) { + // Only refresh the model observables and the read only value + setEditorsModelObservable(modelProperty); + setReadOnly(readOnly); + // The others variables (labelProviders, contentProviders, mandatory and directCreation) don't need to change + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceCombo.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceCombo.java new file mode 100644 index 00000000000..10cfb693326 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceCombo.java @@ -0,0 +1,330 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + * Christian W. Damus (CEA) - bug 435420 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable; +import org.eclipse.papyrus.infra.widgets.databinding.ComboObservableValue; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.UnchangedObject; +import org.eclipse.papyrus.infra.widgets.providers.UnsetObject; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; + + +/** + * An editor representing a single reference as a Combo Box + * This Editor needs a ContentProvider and a LabelProvider, + * describing the objects that can be referred by this property + * + * @author Camille Letavernier + * + */ +public class ReferenceCombo extends AbstractValueEditor { // implements SelectionListener { + + /** + * The viewer displaying the available values from the model + */ + protected ComboViewer viewer; + + /** + * The combo used to select the reference + */ + protected CCombo combo; + + protected boolean unsettable; + + // protected Button unset; + + protected EncapsulatedContentProvider contentProvider; + + + /** + * + * Constructor. + * + * @param parent + * The Composite in which this editor is diplayed + * @param style + * The style for this editor's combo + */ + public ReferenceCombo(Composite parent, int style) { + this(parent, style, null); + } + + /** + * + * Constructor. + * + * @param parent + * The Composite in which this editor is diplayed + * @param style + * The style for this editor's combo + * @param label + * The label for this editor + */ + public ReferenceCombo(Composite parent, int style, String label) { + super(parent, label); + + combo = factory.createCCombo(this, style | SWT.BORDER); + combo.setBackground(new Color(combo.getDisplay(), 255, 255, 255)); + combo.setLayoutData(getDefaultLayoutData()); + combo.setEditable(false); + + viewer = new ComboViewer(combo); + + // unset = new Button(this, SWT.PUSH); + // unset.setImage(Activator.getDefault().getImage("/icons/Delete_12x12.gif")); //$NON-NLS-1$ + // unset.setToolTipText("Unset the current value"); + // unset.addSelectionListener(this); + + ((GridLayout) getLayout()).numColumns++; + + setCommitOnFocusLost(combo); + controlDecoration = new ControlDecoration(combo, SWT.TOP | SWT.LEFT); + GridData gridData = getDefaultLayoutData(); + combo.setLayoutData(gridData); + gridData.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + + combo.addFocusListener(new FocusAdapter() { + + @Override + public void focusGained(FocusEvent paramFocusEvent) { + acceptingFocus(); + } + }); + } + + /** + * Sets the Content and Label providers for this editor + * + * @param contentProvider + * + * @param labelProvider + */ + public void setProviders(IStaticContentProvider contentProvider, ILabelProvider labelProvider) { + Assert.isNotNull(contentProvider, "The content provider should not be null"); //$NON-NLS-1$ + setContentProvider(contentProvider); + + if (labelProvider != null) { + setLabelProvider(labelProvider); + } + } + + /** + * Sets the content provider for this combo. The Content provider should + * specify the objects that can be referred by this property + * + * @param provider + */ + public void setContentProvider(IStaticContentProvider provider) { + this.contentProvider = new EncapsulatedContentProvider(provider); + viewer.setContentProvider(contentProvider); + viewer.setInput(""); //$NON-NLS-1$ + updateControls(); + doBinding(); + } + + @Override + protected void doBinding() { + if (contentProvider == null || modelProperty == null) { + return; + } + + if (widgetObservable == null) { + setWidgetObservable(getObservableValue(), true); + } + + if (modelProperty instanceof AggregatedObservable) { + if (((AggregatedObservable) modelProperty).hasDifferentValues()) { + contentProvider.addTemporaryElement(UnchangedObject.instance); + viewer.refresh(); + } + } + super.doBinding(); + } + + protected IObservableValue getObservableValue() { + return new ComboObservableValue(viewer, modelProperty); + } + + /** + * The Label provider associated to the available objects that + * can be referred by this property + * + * @param provider + */ + public void setLabelProvider(ILabelProvider provider) { + viewer.setLabelProvider(provider); + } + + /** + * Retrieves the ComboViewer associated to this Editor + * + * @return + * The ComboViewer associated to this editor + */ + public ComboViewer getViewer() { + return viewer; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Object.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getValue() { + IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); + if (selection.isEmpty()) { + return null; + } + return selection.getFirstElement(); + } + + /** + * Sets the value for this widget + * + * @param value + */ + public void setValue(Object value) { + if (value == null) { + viewer.setSelection(new StructuredSelection()); + } else { + viewer.setSelection(new StructuredSelection(value), true); + } + } + + @Override + public void setReadOnly(boolean readOnly) { + combo.setEnabled(!readOnly); + updateControls(); + } + + @Override + public boolean isReadOnly() { + return !combo.isEnabled(); + } + + @Override + public void setToolTipText(String text) { + combo.setToolTipText(text); + super.setLabelToolTipText(text); + } + + public void setUnsettable(boolean unsettable) { + this.unsettable = unsettable; + updateControls(); + } + + /** + * Updates the controls display + */ + protected void updateControls() { + // setExclusion(unset, !unsettable); + + // if(isReadOnly() && unsettable) { + // unset.setEnabled(false); + // } + + if (contentProvider != null) { + if (unsettable) { + contentProvider.addTemporaryElement(UnsetObject.instance); + } else { + contentProvider.removeTemporaryElement(UnsetObject.instance); + } + viewer.refresh(); + } + } + + /** + * Changes the viewer for this editor. + * The viewer should use a CCombo + * + * @param comboViewer + */ + public void setViewer(ComboViewer comboViewer) { + this.viewer = comboViewer; + this.combo = viewer.getCCombo(); + } + + // FIXME error avec multiplicit� nulllpointerexception l285 + @Override + public void updateStatus(IStatus status) { + switch (status.getSeverity()) { + case IStatus.OK: + controlDecoration.hide(); + break; + case IStatus.WARNING: + FieldDecoration warning = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_WARNING); + controlDecoration.setImage(warning.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + case IStatus.ERROR: + FieldDecoration error = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); + controlDecoration.setImage(error.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + default: + controlDecoration.hide(); + break; + } + + + } + + // protected void unsetAction() { + // viewer.setSelection(StructuredSelection.EMPTY); + // if(modelProperty != null) { + // modelProperty.setValue(null); + // } + // } + + // public void widgetSelected(SelectionEvent e) { + // if(e.widget == unset) { + // unsetAction(); + // } + // } + + // public void widgetDefaultSelected(SelectionEvent e) { + // //Nothing + // } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceDialog.java new file mode 100644 index 00000000000..95775b4483d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/ReferenceDialog.java @@ -0,0 +1,616 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + * Christian W. Damus (CEA) - bug 402525 + * Christian W. Damus (CEA) - bug 443497 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.databinding.CLabelObservableValue; +import org.eclipse.papyrus.infra.widgets.databinding.ReferenceDialogObservableValue; +import org.eclipse.papyrus.infra.widgets.databinding.StyledTextReferenceDialogObservableValue; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IAdaptableContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Widget; + +/** + * An editor representing a single reference as a Label A filtered selection + * dialog is used to edit the value. Also offers support for unsetting the + * value. This Editor needs a ContentProvider, and may use an optional + * LabelProvider, describing the objects that can be referred by this property + * + * @author Camille Letavernier + * + */ +public class ReferenceDialog extends AbstractReferenceDialog implements SelectionListener { + + /** + * The CLabel displaying the current value + */ + protected final CLabel currentValueLabel; + + /** + * The Button used to browse the available values + */ + protected Button browseValuesButton; + + /** + * The Button used to create a new instance + */ + protected Button createInstanceButton; + + /** + * The Button used to edit the current object + */ + protected Button editInstanceButton; + + /** + * The Button used to unset the current value + */ + protected Button unsetButton; + + /** + * The label provider used to display the values in both the label and the + * selection dialog + */ + protected ILabelProvider labelProvider; + + /** + * The content provider, providing the different possible values for the + * input object + */ + protected IStaticContentProvider contentProvider; + + /** + * The dialog used to select the value + */ + protected final ITreeSelectorDialog dialog; + + /** + * The current value for this editor + */ + protected Object value; + + /** + * The factory used to create or edit objects directly from this editor + */ + protected ReferenceValueFactory valueFactory; + + private boolean directCreation; + + private ControlDecoration controlDecoration; + + protected boolean error = false; + + private Timer timer; + + private TimerTask changeColorTask; + + private boolean edit = false; + + /** + * + * Constructs a new ReferenceDialog in the given parent Composite. The style + * will be applied to the CLabel displaying the current value. + * + * @param parent + * @param style + */ + public ReferenceDialog(Composite parent, int style) { + super(parent, style); + GridData gridData = getDefaultLayoutData(); + + currentValueLabel = factory.createCLabel(this, null, factory.getBorderStyle() | style); + currentValueLabel.setLayoutData(gridData); + currentValueLabel.addMouseListener(new MouseListener() { + + @Override + public void mouseDoubleClick(MouseEvent e) { + editAction(); // TODO : Try to determine whether the double + // click should call the edit, create or browse + // action + // e.g. if the value is null, try to browse. If we cannot + // browse, try to create an instance. + } + + @Override + public void mouseDown(MouseEvent e) { + // Nothing + } + + @Override + public void mouseUp(MouseEvent e) { + // Nothing + } + + }); + + dialog = createDialog(parent.getShell()); + + createButtons(); + updateControls(); + controlDecoration = new ControlDecoration(currentValueLabel, SWT.TOP | SWT.LEFT); + + gridData.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + } + + protected ITreeSelectorDialog createDialog(Shell shell) { + return new TreeSelectorDialog(shell); + } + + protected void createButtons() { + ((GridLayout) getLayout()).numColumns += 4; + + browseValuesButton = factory.createButton(this, null, SWT.PUSH); + browseValuesButton.setImage(Activator.getDefault().getImage("/icons/browse_12x12.gif")); //$NON-NLS-1$ + browseValuesButton.setToolTipText(Messages.ReferenceDialog_EditValue); + browseValuesButton.addSelectionListener(this); + + createInstanceButton = factory.createButton(this, null, SWT.PUSH); + createInstanceButton.setImage(Activator.getDefault().getImage("/icons/Add_12x12.gif")); //$NON-NLS-1$ + createInstanceButton.setToolTipText(Messages.ReferenceDialog_CreateANewObject); + createInstanceButton.addSelectionListener(this); + + editInstanceButton = factory.createButton(this, null, SWT.PUSH); + editInstanceButton.setImage(Activator.getDefault().getImage("/icons/Edit_12x12.gif")); //$NON-NLS-1$ + editInstanceButton.setToolTipText(Messages.ReferenceDialog_EditTheCurrentValue); + editInstanceButton.addSelectionListener(this); + + unsetButton = factory.createButton(this, null, SWT.PUSH); + unsetButton.setImage(Activator.getDefault().getImage("/icons/Delete_12x12.gif")); //$NON-NLS-1$ + unsetButton.setToolTipText(Messages.ReferenceDialog_UnsetValue); + unsetButton.addSelectionListener(this); + } + + /** + * The action executed when the "browse" button is selected Choose a value + * from a selection of already created objects + */ + protected void browseAction() { + setInitialSelection(Collections.singletonList(getValue())); + int result = dialog.open(); + if (result == Window.OK) { + Object[] newValue = dialog.getResult(); + if (newValue == null) { + return; + } + + if (newValue.length == 0) { + setValue(null); + } else { + Object value = newValue[0]; + if (contentProvider instanceof IAdaptableContentProvider) { + + value = ((IAdaptableContentProvider) contentProvider).getAdaptedValue(value); + } + setValue(value); + } + } + } + + /** + * The action executed when the "create" button is selected Create a new + * instance and assign it to this reference + */ + protected void createAction() { + if (valueFactory != null && valueFactory.canCreateObject()) { + final Object context = getContextElement(); + getOperationExecutor(context).execute(new Runnable() { + + @Override + public void run() { + Object value = valueFactory.createObject(createInstanceButton, context); + if (value == null) { + // Cancel the operation + throw new OperationCanceledException(); + } + Collection<Object> validatedObjects = valueFactory.validateObjects(Collections.singleton(value)); + if (!validatedObjects.isEmpty()) { + setValue(validatedObjects.iterator().next()); + } + } + }, NLS.bind(Messages.ReferenceDialog_setOperation, labelText)); + } + } + + /** + * The action executed when the "edit" button is selected Edits the object + * that is currently selected + */ + protected void editAction() { + currentValueLabel.setBackground(EDIT); + edit = true; + final Object currentValue = getValue(); + if (currentValue != null && valueFactory != null && valueFactory.canEdit()) { + getOperationExecutor(currentValue).execute(new Runnable() { + + @Override + public void run() { + Object newValue = valueFactory.edit(editInstanceButton, currentValue); + + // Per the contract of ReferenceValueFactory::edit(), a null return means the object was edited "in place." + // In that case, there is nothing further to do + if ((newValue != null) && (newValue != currentValue)) { + setValue(newValue); + } + + updateLabel(); + } + }, NLS.bind(Messages.ReferenceDialog_editOperation, labelText)); + } + } + + /** + * The action executed when the "unset" button is selected Sets the current + * reference to null + */ + protected void unsetAction() { + setValue(null); + } + + /** + * Updates the displayed label for the current value + */ + @Override + public void updateLabel() { + if (binding != null) { + binding.updateModelToTarget(); + + } else { + if (null != labelProvider) { + currentValueLabel.setImage(labelProvider.getImage(getValue())); + currentValueLabel.setText(labelProvider.getText(getValue())); + } + } + } + + /** + * Sets the Content provider for this editor + * + * @param provider + * The content provider used to retrieve the possible values for + * this Reference + */ + @Override + public void setContentProvider(IStaticContentProvider provider) { + dialog.setContentProvider(new EncapsulatedContentProvider(provider)); + if (getValue() != null) { + setInitialSelection(Collections.singletonList(getValue())); + } + + this.contentProvider = provider; + } + + /** + * Sets the Label provider for this editor If the label provider is null, a + * default one will be used. The same label provider is used for both the + * editor's label and the selection dialog. + * + * @param provider + * The label provider + */ + @Override + public void setLabelProvider(ILabelProvider provider) { + if (provider == null) { + setLabelProvider(new LabelProvider()); + return; + } + + dialog.setLabelProvider(provider); + this.labelProvider = provider; + if (widgetObservable != null) { + ((CLabelObservableValue) widgetObservable).setLabelProvider(labelProvider); + } + updateLabel(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setLabel(String label) { + super.setLabel(label); + dialog.setTitle(label); + } + + /** + * {@inheritDoc} + */ + @Override + public Object getValue() { + if (modelProperty != null) { + return modelProperty.getValue(); + } + return value; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Object.class; + } + + /** + * {@inheritDoc} + */ + @Override + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + updateControls(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isReadOnly() { + return !currentValueLabel.isEnabled(); + } + + /** + * {@inheritDoc} + */ + @Override + protected void doBinding() { + super.doBinding(); + } + + protected void setInitialSelection(List<?> initialValues) { + dialog.setInitialElementSelections(initialValues); + } + + @Override + public void setModelObservable(IObservableValue modelProperty) { + setWidgetObservable(createWidgetObservable(modelProperty)); + super.setModelObservable(modelProperty); + updateControls(); + } + + /** + * This allow to create the widget observable value. + * + * @param modelProperty + * The current observable value. + * @return The created {@link StyledTextReferenceDialogObservableValue}. + */ + protected IObservableValue createWidgetObservable(final IObservableValue modelProperty) { + return new ReferenceDialogObservableValue(this, this.currentValueLabel, modelProperty, labelProvider); + } + + @Override + public void setToolTipText(String text) { + super.setLabelToolTipText(text); + currentValueLabel.setToolTipText(text); + } + + @Override + public void setValueFactory(ReferenceValueFactory factory) { + valueFactory = factory; + updateControls(); + } + + @Override + public void widgetSelected(SelectionEvent e) { + Widget widget = e.widget; + if (widget == browseValuesButton) { + browseAction(); + } else if (widget == createInstanceButton) { + createAction(); + } else if (widget == editInstanceButton) { + editAction(); + } else if (widget == unsetButton) { + unsetAction(); + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + + /** + * Updates the buttons' status + */ + @Override + public void updateControls() { + // Check if the edit & create buttons should be displayed + boolean exclude = valueFactory == null || !valueFactory.canCreateObject(); + setExclusion(editInstanceButton, exclude); + setExclusion(createInstanceButton, exclude); + + setExclusion(browseValuesButton, directCreation); + + browseValuesButton.setEnabled(!readOnly); + + // If they are displayed, check if they should be enabled + if (!exclude) { + editInstanceButton.setEnabled(valueFactory != null && valueFactory.canEdit() && getValue() != null); + createInstanceButton.setEnabled(valueFactory != null && valueFactory.canCreateObject() && !readOnly); + } + + // Do not display unset if the value is mandatory + setExclusion(unsetButton, mandatory); + if (!mandatory) { + boolean enabled = !readOnly; + enabled = enabled && getValue() != null; + + unsetButton.setEnabled(enabled); + } + } + + @Override + public void update() { + super.update(); + updateControls(); + } + + @Override + public void setDirectCreation(boolean directCreation) { + this.directCreation = directCreation; + updateControls(); + } + + public void setValue(Object value) { + this.value = value; + try { + if (modelProperty != null) { + modelProperty.setValue(value); + error = false; + } + } catch (Exception e) { + error = true; + + } + + updateControls(); + updateLabel(); + commit(); + } + + /** + * @see org.eclipse.jface.viewers.StructuredViewer#setInput(Object) + * @param input + */ + public void setInput(Object input) { + this.dialog.setInput(input); + } + + @Override + public void setMandatory(boolean mandatory) { + this.mandatory = mandatory; + } + + @Override + public void updateStatus(IStatus status) { + + if (error) { + FieldDecoration error = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); + controlDecoration.setImage(error.getImage()); + controlDecoration.showHoverText(Messages.ReferenceDialog_0); + controlDecoration.setDescriptionText(Messages.ReferenceDialog_1); + controlDecoration.show(); + currentValueLabel.setBackground(ERROR); + currentValueLabel.update(); + + + } else { + controlDecoration.hide(); + } + } + + @Override + public void dispose() { + if (changeColorTask != null) { + changeColorTask.cancel(); + } + if (timer != null) { + timer.cancel(); + } + super.dispose(); + } + + private void cancelCurrentTask() { + if (changeColorTask != null) { + changeColorTask.cancel(); + } + } + + @Override + public void changeColorField() { + if (!error & !edit) { + + if (timer == null) { + timer = new Timer(true); + } + + cancelCurrentTask(); + changeColorTask = new TimerTask() { + + @Override + public void run() { + if (ReferenceDialog.this.isDisposed()) { + return; + } + ReferenceDialog.this.getDisplay().syncExec(new Runnable() { + + @Override + public void run() { + if (ReferenceDialog.this.isDisposed()) {// Bug 434787 : Shouldn't not execute the timer thread if the widget is disposed + return; + } + currentValueLabel.setBackground(DEFAULT); + currentValueLabel.update(); + } + + + }); + } + }; + + if (errorBinding) { + currentValueLabel.setBackground(ERROR); + currentValueLabel.update(); + } else { + IStatus status = (IStatus) binding.getValidationStatus().getValue(); + switch (status.getSeverity()) { + case IStatus.OK: + case IStatus.WARNING: + timer.schedule(changeColorTask, 600); + currentValueLabel.setBackground(VALID); + currentValueLabel.update(); + break; + case IStatus.ERROR: + currentValueLabel.setBackground(ERROR); + currentValueLabel.update(); + break; + + } + } + } else { + currentValueLabel.setBackground(DEFAULT); + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/SelectionEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/SelectionEditor.java new file mode 100644 index 00000000000..e385f80a43d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/SelectionEditor.java @@ -0,0 +1,543 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedList; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ListViewer; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.CollectionContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.List; + +/** + * + * This class provides an editor to select easily elements + * In the left side, we have the possible element to select and in the right side, we have the current selection + * Moreover, its possible to add a Button to provide some action. Often this button shall be used to create new element + * + */ +public class SelectionEditor extends Composite implements SelectionListener { + + /** the initial selection */ + protected final java.util.List<Object> initialSelection; + + /** The object selector */ + private IElementSelector selector; + + /** The SWT Composite in which the selector is drawn */ + protected Composite selectorSection; + + /** The message section */ + protected Composite messageSection; + + /** The additional button section */ + protected Composite createAdditionalButtonSection; + + /** The up/down buttons section */ + protected Composite rightButtonsSection; + + /** The listViewer for chosen elements */ + protected ListViewer selectedElementsViewer; + + /** The list for chosen elements */ + protected List selectedElements; + + /** The add action button */ + private Button add; + + /** The remove action button */ + private Button remove; + + /** The add all action button */ + private Button addAll; + + /** The remove all action button */ + private Button removeAll; + + /** the up action button */ + private Button up; + + /** the down action button */ + private Button down; + + /** The label provider for the listViewer of chosen elements */ + private ILabelProvider labelProvider; + + /** The currently chosen elements */ + protected final Collection<Object> currentSelection; + + /** the listener for the additional button */ + private SelectionListener additionalButtonSelectionListener; + + /** the message for the editor */ + private String message; + + + /* + * This dialog can provide a Button to do some optional action + */ + + /** Indicates if the dialog provides a button */ + private boolean withAdditionalButton = false; + + /** the label of the button */ + private String additionalButtonLabel = null; + + /** the button */ + private Button additionalButton; + + /** The add/remove/addAll buttons section */ + protected Composite buttonSection; + + /** + * + * Constructor. + * + * @param parent + * the parent of this composite + * @param selector + * the selector + * @param labelProvider + * the label provider + * @param initialSelection + * the initial selection + */ + public SelectionEditor(Composite parent, IElementSelector selector, ILabelProvider labelProvider, java.util.List<Object> initialSelection) { + super(parent, SWT.NONE); + this.selector = selector; + this.labelProvider = labelProvider; + this.initialSelection = new ArrayList<Object>(); + for (Object current : initialSelection) { + this.initialSelection.add(current); + } + currentSelection = initialSelection; + } + + /** + * This methods create this editor + */ + public void create() { + Composite parent = this; + GridLayout layout = new GridLayout(1, true); + GridData data = new GridData(); + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + parent.setLayout(layout); + createMessageSection(parent); + createBody(parent); + createCreateButtonSection(parent); + } + + /** + * This method create the body of the editor : + * <ul> + * <li>the selector</li> + * <li>the list</li> + * <li>the buttons Add, AddAll, Remove, RemoveAll, Up, Down</li> + * </ul> + * + * @param parent + * the parent composite + */ + protected void createBody(Composite parent) { + + Composite par = new Composite(parent, SWT.NONE); + createSelectorSection(par); + createControlsSection(par); + createListSection(par); + createRightButtonsSection(par); + GridLayout layout = new GridLayout(); + layout.makeColumnsEqualWidth = false; + layout.numColumns = 4; + par.setLayout(layout); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + par.setLayoutData(data); + + } + + /** + * Creates the Message section + * + * @param parent + * the parent of the {@link Composite} + */ + protected void createMessageSection(Composite parent) { + messageSection = new Composite(parent, SWT.NONE); + Label label = new Label(messageSection, SWT.NONE); + label.setText(message); + messageSection.setLayout(new FillLayout(SWT.HORIZONTAL)); + } + + /** + * Creates the button section + * + * @param parent + * the parent of the {@link Composite} + */ + protected void createCreateButtonSection(Composite parent) { + if (this.withAdditionalButton) { + buttonSection = new Composite(parent, SWT.NONE); + additionalButton = new Button(buttonSection, SWT.PUSH); + if (additionalButtonLabel != null) { + additionalButton.setText(additionalButtonLabel); + } + buttonSection.setLayout(new FillLayout()); + this.additionalButton.addSelectionListener(additionalButtonSelectionListener); + } + } + + /** + * Creates the selector section + * + * @param parent + * The composite in which the section is created + */ + protected void createSelectorSection(Composite parent) { + selectorSection = new Composite(parent, SWT.NONE); + selectorSection.setLayout(new FillLayout()); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 400; + + // data.exclude = true; + selectorSection.setLayoutData(data); + selector.createControls(selectorSection); + + } + + /** + * Creates the main controls section (Add, remove, Add all, remove all) + * + * @param parent + * The composite in which the section is created + */ + protected void createControlsSection(Composite parent) { + buttonSection = new Composite(parent, SWT.NONE); + buttonSection.setLayout(new GridLayout(1, true)); + + add = new Button(buttonSection, SWT.PUSH); + add.setImage(Activator.getDefault().getImage("/icons/arrow_right.gif")); //$NON-NLS-1$ + add.addSelectionListener(this); + add.setToolTipText(Messages.MultipleValueSelectorDialog_AddSelectedElements); + + remove = new Button(buttonSection, SWT.PUSH); + remove.setImage(Activator.getDefault().getImage("/icons/arrow_left.gif")); //$NON-NLS-1$ + remove.addSelectionListener(this); + remove.setToolTipText(Messages.MultipleValueEditor_RemoveSelectedElements); + + addAll = new Button(buttonSection, SWT.PUSH); + addAll.setImage(Activator.getDefault().getImage("/icons/arrow_double.gif")); //$NON-NLS-1$ + addAll.addSelectionListener(this); + addAll.setToolTipText(Messages.MultipleValueSelectorDialog_AddAllElements); + + removeAll = new Button(buttonSection, SWT.PUSH); + removeAll.setImage(Activator.getDefault().getImage("/icons/arrow_left_double.gif")); //$NON-NLS-1$ + removeAll.addSelectionListener(this); + removeAll.setToolTipText(Messages.MultipleValueSelectorDialog_RemoveAllElements); + } + + + /** + * Creates the list displaying the currently selected elements + * + * @param parent + * The composite in which the section is created + */ + protected void createListSection(Composite parent) { + Composite listSection = new Composite(parent, SWT.NONE); + selectedElements = new List(listSection, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 400; + listSection.setLayout(new FillLayout()); + listSection.setLayoutData(data); + + selectedElementsViewer = new ListViewer(selectedElements); + + selectedElementsViewer.setContentProvider(CollectionContentProvider.instance); + + if (labelProvider != null) { + selectedElementsViewer.setLabelProvider(labelProvider); + } + + selectedElementsViewer.setInput(currentSelection); + selector.setSelectedElements(currentSelection.toArray()); + + } + + /** + * Creates the up/down controls section + * + * @param parent + * The composite in which the section is created + */ + protected void createRightButtonsSection(Composite parent) { + rightButtonsSection = new Composite(parent, SWT.NONE); + rightButtonsSection.setLayout(new GridLayout(1, true)); + + up = new Button(rightButtonsSection, SWT.PUSH); + up.setImage(Activator.getDefault().getImage("/icons/Up_12x12.gif")); //$NON-NLS-1$ + up.addSelectionListener(this); + up.setToolTipText(Messages.MultipleValueEditor_MoveSelectedElementsUp); + + down = new Button(rightButtonsSection, SWT.PUSH); + down.setImage(Activator.getDefault().getImage("/icons/Down_12x12.gif")); //$NON-NLS-1$ + down.addSelectionListener(this); + down.setToolTipText(Messages.MultipleValueEditor_MoveSelectedElementsDown); + } + + + + /** + * {@inheritDoc} Handles the events on one of the control buttons + * + * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) + * + * @param e + * The event that occurred + */ + @Override + public void widgetSelected(SelectionEvent e) { + if (e.widget == add) { + addAction(); + } else if (e.widget == remove) { + removeAction(); + } else if (e.widget == addAll) { + addAllAction(); + } else if (e.widget == removeAll) { + removeAllAction(); + } else if (e.widget == up) { + upAction(); + } else if (e.widget == down) { + downAction(); + } + } + + /** + * Handles the "Add" action + */ + protected void addAction() { + Object[] elements = selector.getSelectedElements(); + addElements(elements); + } + + /** + * Handles the "Up" action + */ + protected void upAction() { + IStructuredSelection selection = (IStructuredSelection) selectedElementsViewer.getSelection(); + + // We need a list to move objects. LinkedHashSet can't do that + java.util.List<Object> list = new LinkedList<Object>(currentSelection); + for (Object o : selection.toArray()) { + int oldIndex = list.indexOf(o); + if (oldIndex > 0) { + move(list, oldIndex, oldIndex - 1); + } + } + + currentSelection.clear(); + currentSelection.addAll(list); + + IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray()); + selectedElementsViewer.setSelection(selectionCopy); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Down" action + */ + protected void downAction() { + IStructuredSelection selection = (IStructuredSelection) selectedElementsViewer.getSelection(); + + // We need a list to move objects. LinkedHashSet can't do that + java.util.List<Object> list = new LinkedList<Object>(currentSelection); + + int maxIndex = list.size() - 1; + + Object[] selectionArray = selection.toArray(); + for (int i = selectionArray.length - 1; i >= 0; i--) { + Object o = selectionArray[i]; + int oldIndex = list.indexOf(o); + if (oldIndex < maxIndex) { + move(list, oldIndex, oldIndex + 1); + } + } + + currentSelection.clear(); + currentSelection.addAll(list); + + IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray()); + selectedElementsViewer.setSelection(selectionCopy); + selectedElementsViewer.refresh(); + } + + /** + * Moves an element from oldIndex to newIndex + * + * @param list + * The list in which to move the object + * @param oldIndex + * @param newIndex + */ + protected void move(java.util.List<Object> list, int oldIndex, int newIndex) { + int size = list.size(); + + if (oldIndex < 0 || oldIndex >= size) + { + throw new IndexOutOfBoundsException("oldIndex: " + oldIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ + } + if (newIndex < 0 || newIndex >= size) + { + throw new IndexOutOfBoundsException("newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ + } + Object element = list.remove(oldIndex); + list.add(newIndex, element); + } + + /** + * Handles the "Remove" action + */ + protected void removeAction() { + IStructuredSelection selection = (IStructuredSelection) selectedElementsViewer.getSelection(); + if (selection.isEmpty()) { + return; + } + + for (Object element : selection.toArray()) { + currentSelection.remove(element); + } + + selector.setSelectedElements(currentSelection.toArray()); + selectedElementsViewer.setSelection(null); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Remove all" action + */ + protected void removeAllAction() { + currentSelection.clear(); + selector.setSelectedElements(new Object[0]); + selectedElementsViewer.setSelection(null); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Add All" action + */ + protected void addAllAction() { + Object[] elements = selector.getAllElements(); + addElements(elements); + } + + /** + * Adds the specified elements to the currently selected elements (For + * "Add" and "Add all" actions) + * + * @param elements + * The elements to be added + */ + protected void addElements(Object[] elements) { + if (elements != null) { + currentSelection.addAll(Arrays.asList(elements)); + selectedElementsViewer.refresh(); + } + } + + + /** + * + * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent) + * + * @param e + */ + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing to do + } + + public void setAdditionalButton(boolean withAdditionalButton, String messageButton, SelectionListener listener) { + this.withAdditionalButton = withAdditionalButton; + this.additionalButtonLabel = messageButton; + this.additionalButtonSelectionListener = listener; + } + + /** + * Set the message displayed by the Editor + * + * @param string + * the message displayed by the editor + */ + public void setMessage(String string) { + this.message = string; + } + + /** + * Returns all selected elements + * + * @return + * all selected elements + */ + public Collection<?> getSelectedElements() { + return currentSelection; + } + + + /** + * Returns the list of the elements to remove + * + * @return + * the list of the elements to remove + */ + public java.util.List<Object> getElementToRemove() { + java.util.List<Object> removedObject = new ArrayList<Object>(); + for (Object current : this.initialSelection) { + if (!getSelectedElements().contains(current)) { + removedObject.add(current); + } + } + return removedObject; + } + + /** + * Returns the list of the elements to add + * + * @return + * the list of the elements to add + */ + public java.util.List<Object> getElementToAdd() { + java.util.List<Object> addedObject = new ArrayList<Object>(); + for (Object current : getSelectedElements()) { + if (!this.initialSelection.contains(current)) { + addedObject.add(current); + } + } + return addedObject; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/SelectionMenu.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/SelectionMenu.java new file mode 100644 index 00000000000..22a624ecf77 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/SelectionMenu.java @@ -0,0 +1,291 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Shuai Li (CEA LIST) shuai.li@cea.fr - SelectionMenu#refresh method + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; + +/** + * A basic menu which proposes a list of choices. + * + * Implementation is based on a JFace TableViewer + * + * Typical usage: JDT-like Ctrl + Click (Navigation) + * + * @author Camille Letavernier + * + */ +public class SelectionMenu { + + private ILabelProvider labelProvider; + + private IStructuredContentProvider contentProvider; + + private Shell parentShell; + + private Point location; + + private Object input; + + private Shell shell; + + private TableViewer tableViewer; + + private ISelectionChangedListener selectionChangedListener; + + private List<ISelectionChangedListener> selectionChangedListeners; + + private KeyListener keyListener; + + private List<KeyListener> keyListeners; + + private MouseTrackListener mouseTrackListener; + + private List<MouseTrackListener> mouseTrackListeners; + + public SelectionMenu(Shell parentShell) { + this(parentShell, parentShell.getDisplay().getCursorLocation()); + } + + public SelectionMenu(Shell parentShell, Object source) { + if (source instanceof TableViewer && parentShell != null) { + TableViewer tableViewer = (TableViewer) source; + + // Get the cell's y position (we can't use the getCell(Point location) method) + int selectionIndex = tableViewer.getTable().getSelectionIndex(); + int cellHeight = tableViewer.getTable().getItem(selectionIndex).getBounds().height; + int y = tableViewer.getTable().getShell().getLocation().y; + y += selectionIndex * cellHeight; + + // Get the cell's x position and append by the table's width + //int width= tableViewer.getTable().getSize().x; + int width = tableViewer.getTable().getShell().getBounds().width; + int x = tableViewer.getTable().getShell().getLocation().x + width; + + Point location = new Point(x, y); + init(parentShell, location, -1, 0); + return; + } + + init(parentShell, parentShell.getDisplay().getCursorLocation(), 1, 1); + } + + public SelectionMenu(Shell parentShell, Object source, Point cursorPosition) { + if (source instanceof Table && parentShell != null && cursorPosition != null) { + Table table = (Table) source; + + TableItem item = table.getItem(cursorPosition); + + if (item != null) { + int selectionIndex = 0; + for (Object tableItem : table.getItems()) { + if (tableItem.equals(item)) { + break; + } + selectionIndex++; + } + + int cellHeight = item.getBounds().height; + int y = table.getShell().getLocation().y; + y += selectionIndex * cellHeight; + + // Get the cell's x position and append by the table's width + //int width= tableViewer.getTable().getSize().x; + int width = table.getShell().getBounds().width; + int x = table.getShell().getLocation().x + width; + + Point location = new Point(x, y); + init(parentShell, location, -1, 0); + return; + } + } + + init(parentShell, parentShell.getDisplay().getCursorLocation(), 1, 1); + } + + public SelectionMenu(Shell parentShell, Point location) { + init(parentShell, location, 1, 1); + } + + protected void init(Shell parentShell, Point location, int xOffset, int yOffset) { + // Move the shell so that it doesn't open under the mouse + // The hovered element can still be selected + location.x += xOffset; + location.y += yOffset; + + this.parentShell = parentShell; + this.location = location; + labelProvider = new LabelProvider(); + + selectionChangedListeners = new LinkedList<ISelectionChangedListener>(); + selectionChangedListener = new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + for (ISelectionChangedListener listener : selectionChangedListeners) { + listener.selectionChanged(event); + } + } + }; + + keyListeners = new LinkedList<KeyListener>(); + keyListener = new KeyListener() { + @Override + public void keyPressed(KeyEvent event) { + for (KeyListener listener : keyListeners) { + listener.keyPressed(event); + } + } + + @Override + public void keyReleased(KeyEvent event) { + for (KeyListener listener : keyListeners) { + listener.keyReleased(event); + } + } + }; + + mouseTrackListeners = new LinkedList<MouseTrackListener>(); + mouseTrackListener = new MouseTrackListener() { + @Override + public void mouseEnter(MouseEvent event) { + for (MouseTrackListener mouseTrackListener : mouseTrackListeners) { + mouseTrackListener.mouseEnter(event); + } + } + + @Override + public void mouseExit(MouseEvent event) { + for (MouseTrackListener mouseTrackListener : mouseTrackListeners) { + mouseTrackListener.mouseExit(event); + } + } + + @Override + public void mouseHover(MouseEvent event) { + for (MouseTrackListener mouseTrackListener : mouseTrackListeners) { + mouseTrackListener.mouseHover(event); + } + } + }; + } + + public void open() { + // Shell background and background + shell = new Shell(parentShell, SWT.NONE); + shell.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_WHITE)); + shell.setBackgroundMode(SWT.INHERIT_DEFAULT); + /*GridLayout gridLayout = new GridLayout(1, false); + gridLayout.marginWidth = 5; + gridLayout.marginHeight = 5; + shell.setLayout(gridLayout);*/ + shell.setLayout(new GridLayout(1, false)); + + // TableViewer for menu items + tableViewer = new TableViewer(shell, SWT.NO_SCROLL); + tableViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + tableViewer.setContentProvider(contentProvider); + tableViewer.setLabelProvider(labelProvider); + ColumnViewerToolTipSupport.enableFor(tableViewer); + tableViewer.setInput(input); + + // Listeners + tableViewer.addSelectionChangedListener(selectionChangedListener); + tableViewer.getTable().addKeyListener(keyListener); + tableViewer.getTable().addMouseTrackListener(mouseTrackListener); + + // Open + shell.setLocation(location); + shell.pack(); + shell.open(); + + + } + + public void refresh() { + tableViewer.refresh(); + shell.pack(); + } + + public void dispose() { + if (tableViewer != null) { + tableViewer.removeSelectionChangedListener(selectionChangedListener); + } + + if (tableViewer.getTable() != null) { + tableViewer.getTable().removeKeyListener(keyListener); + } + + if (shell != null) { + shell.dispose(); + } + } + + public void setContentProvider(IStructuredContentProvider provider) { + this.contentProvider = provider; + } + + public void setInput(Object input) { + this.input = input; + } + + public void setLabelProvider(ILabelProvider labelProvider) { + this.labelProvider = labelProvider; + } + + public void addSelectionChangedListener(ISelectionChangedListener listener) { + this.selectionChangedListeners.add(listener); + } + + public void addKeyListener(KeyListener listener) { + this.keyListeners.add(listener); + } + + public void addMouseTrackListener(MouseTrackListener listener) { + this.mouseTrackListeners.add(listener); + } + + public Shell getShell() { + return shell; + } + + public void setShell(Shell shell) { + this.shell = shell; + } + + public Shell getParentShell() { + return parentShell; + } + + public TableViewer getTableViewer() { + return tableViewer; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringCombo.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringCombo.java new file mode 100644 index 00000000000..6234e5db3b6 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringCombo.java @@ -0,0 +1,241 @@ +/***************************************************************************** + * Copyright (c) 2011, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + * Christian W. Damus (CEA) - bug 436072 + * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue@all4tec.net- Bug 446865 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.observable.value.AbstractObservableValue; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.ValueDiff; +import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.UnchangedObject; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Composite; + +/** + * A Widget for editing a String with an editable combo. + * The combo proposes a set of default values. + * + * @author Camille Letavernier + */ +public class StringCombo extends ReferenceCombo { + + /** + * Constructor. + * + * @param parent + * The parent composite. + * @param style + * The style used. + */ + public StringCombo(final Composite parent, final int style) { + super(parent, style); + combo.setEditable(true); + } + + /** + * Constructor. + * + * @param parent + * The parent composite. + * @param style + * The style used. + * @param label + * The initial label. + */ + public StringCombo(final Composite parent, final int style, final String label) { + super(parent, style, label); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo#getEditableType() + */ + @Override + public Object getEditableType() { + return String.class; + } + + /** + * Sets the content provider for this combo. The Content provider should + * specify the objects that can be referred by this property + * + * @param provider + * The provider. + */ + @Override + public void setContentProvider(IStaticContentProvider provider) { + if (provider != null) { + contentProvider = new EncapsulatedContentProvider(provider); + viewer.setContentProvider(contentProvider); + viewer.setInput(""); //$NON-NLS-1$ + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo#getObservableValue() + */ + @Override + protected IObservableValue getObservableValue() { + return new CComboObservableValue(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo#getValue() + */ + @Override + public String getValue() { + // See Bug 359835 : The ComboViewer doesn't support custom values + // We can't rely on the ComboViewer#getSelection() method + return combo.getText(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo#setValue(java.lang.Object) + */ + @Override + public void setValue(Object value) { + // See Bug 359835 : The ComboViewer doesn't support custom values + // We can't rely on the ComboViewer#setSelection() method + if (value instanceof String) { + combo.setText((String) value); + } else { + combo.setText(""); //$NON-NLS-1$ + } + } + + /** + * Updates the controls display. + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo#updateControls() + */ + @Override + protected void updateControls() { + // See Bug 359835 : The ComboViewer doesn't support custom values + String value = getValue(); + super.updateControls(); + setValue(value); + } + + class CComboObservableValue extends AbstractObservableValue implements SelectionListener, KeyListener, FocusListener { + + private String previousValue; + + public CComboObservableValue() { + previousValue = combo.getText(); + combo.addSelectionListener(this); // Selection change + combo.addKeyListener(this); // Enter pressed + combo.addFocusListener(this); // Focus lost + } + + @Override + public Object getValueType() { + return String.class; + } + + @Override + protected String doGetValue() { + return combo.getText(); + } + + @Override + protected void doSetValue(Object value) { + if (modelProperty instanceof AggregatedObservable && ((AggregatedObservable) modelProperty).hasDifferentValues()) { + combo.setText(UnchangedObject.instance.toString()); + } else if (value instanceof String) { + // This is the new baseline value (coming from the model) against which to compare a future edit by the user + previousValue = (String) value; + combo.setText(previousValue); + } + } + + // Enter pressed + @Override + public void keyReleased(KeyEvent e) { + if ((e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) && e.stateMask == SWT.NONE) { + maybeFireChange(); + e.doit = false; // Stops the propagation of the event + } + } + + // Selection change + @Override + public void widgetSelected(SelectionEvent e) { + maybeFireChange(); + } + + // Focus lost + @Override + public void focusLost(FocusEvent e) { + maybeFireChange(); + } + + void maybeFireChange() { + // Only report a change if there is actually a change, otherwise we get a no-op command that dirties the editor + final String currentValue = doGetValue(); + if ((currentValue == null) ? previousValue != null : !currentValue.equals(previousValue)) { + doFireChange(); + } + } + + private void doFireChange() { + final String oldValue = previousValue; + final String currentValue = previousValue = doGetValue(); + fireValueChange(new ValueDiff() { + + @Override + public Object getOldValue() { + return oldValue; + } + + @Override + public Object getNewValue() { + return currentValue; + } + }); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + + @Override + public void focusGained(FocusEvent e) { + // Nothing + } + + @Override + public void keyPressed(KeyEvent e) { + // Nothing + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditor.java new file mode 100644 index 00000000000..1b3cdb80c4f --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditor.java @@ -0,0 +1,480 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Timer; +import java.util.TimerTask; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.papyrus.infra.widgets.databinding.TextObservableValue; +import org.eclipse.papyrus.infra.widgets.selectors.StringSelector; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Text; + +/** + * A Property Editor representing a single-line or multi-line String value as a + * Text. This editor's content is validated when the focus is lost, or, if the + * editor is single-line, when the Carriage Return is pressed. For a multi-line + * editor, ctrl+enter will also validate the editor's content. + * + * @see SWT#MULTI + * + * @author Camille Letavernier + */ +public class StringEditor extends AbstractValueEditor implements KeyListener, ModifyListener { + + /** + * The text box for editing this editor's value + */ + protected final Text text; + + private int delay = 600; + + private boolean validateOnDelay = false; + + private Timer timer; + + private TimerTask currentValidateTask; + + private TimerTask changeColorTask; + + private final static int DEFAULT_HEIGHT_HINT = 55; + + private final static int DEFAULT_WIDTH_HINT = 100; + + + /** + * + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + */ + public StringEditor(Composite parent, int style) { + this(parent, style, null, DEFAULT_HEIGHT_HINT, DEFAULT_WIDTH_HINT); + + } + + /** + * + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + * @param label + * The label for this editor + */ + public StringEditor(Composite parent, int style, String label) { + this(parent, style, label, DEFAULT_HEIGHT_HINT, DEFAULT_WIDTH_HINT); + } + + /** + * + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + * @param heighHint + * Height hint of the text area in multiline mode + * @param widthHint + * Width hint of the text area in multiline mode + */ + public StringEditor(Composite parent, int style, int heighHint, int widthHint) { + this(parent, style, null, heighHint, widthHint); + } + + /** + * + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + * @param label + * The label for this editor + * @param heighHint + * Height hint of the text area in multiline mode + * @param widthHint + * Width hint of the text area in multiline mode + */ + public StringEditor(Composite parent, int style, String label, int heighHint, int widthHint) { + super(parent, label); + + GridData data = getDefaultLayoutData(); + data.grabExcessVerticalSpace = true; + data.grabExcessHorizontalSpace = true; + data.verticalAlignment = SWT.FILL; + + if ((style & SWT.MULTI) != 0) { + data.minimumHeight = heighHint; + data.minimumWidth = widthHint; + style = style | SWT.V_SCROLL; + } + + text = factory.createText(this, null, style); + text.setLayoutData(data); + + if (label != null) { + super.label.setLayoutData(getLabelLayoutData()); + + } + text.addKeyListener(this); + text.addModifyListener(this); + setCommitOnFocusLost(text); + controlDecoration = new ControlDecoration(text, SWT.LEFT | SWT.TOP); + controlDecoration.hide(); + data.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + pack(); + + } + + @Override + protected GridData getLabelLayoutData() { + GridData result = super.getLabelLayoutData(); + if (text != null) { + if ((text.getStyle() & SWT.MULTI) != 0) { + result.verticalAlignment = SWT.BEGINNING; + } + } + return result; + } + + /** + * Ignored + */ + @Override + public void keyPressed(KeyEvent e) { + // Nothing + + + + } + + /** + * Validates this editor when one of the following events occur : - CR + * released - Keypad CR released - Ctrl + [CR | Keypad CR] released + * + * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent) + * + * @param e + */ + // TODO : we should prevent the \n from being written when validating the + // multi-line field with Ctrl + CR + @Override + public void keyReleased(KeyEvent e) { + // We listen on Carriage Return or Ctrl+ Carriage return, depending on + // whether the editor is single- or multi-line + if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) { + if ((text.getStyle() & SWT.MULTI) == 0) { // Single-line : Enter + if (e.stateMask == SWT.NONE) { + notifyChange(); + } + } else { // Multi-line : Ctrl+Enter + if (e.stateMask == SWT.CTRL) { + String str = text.getText(); + if (str.endsWith(StringSelector.LINE_SEPARATOR)) { + int newLength = str.length() - StringSelector.LINE_SEPARATOR.length(); + text.setText(str.substring(0, newLength)); + text.setSelection(newLength); + } + notifyChange(); + } + } + } + + + } + + @Override + public void setModelObservable(IObservableValue observable) { + setWidgetObservable(new TextObservableValue(text, observable, SWT.FocusOut), true); + super.setModelObservable(observable); + + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return String.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getValue() { + return text.getText(); + } + + @Override + public void setReadOnly(boolean readOnly) { + text.setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return !text.isEnabled(); + } + + protected void notifyChange() { + + text.notifyListeners(SWT.FocusOut, new Event()); + commit(); + changeColorField(); + } + + @Override + public void setToolTipText(String tooltip) { + text.setToolTipText(tooltip); + super.setLabelToolTipText(tooltip); + } + + /** + * Sets the current text value for this editor + * + * @param value + */ + public void setValue(Object value) { + if (value instanceof String) { + this.text.setText((String) value); + } else { + this.text.setText(""); //$NON-NLS-1$; + } + } + + /** + * Indicates that this editor should be automatically validated after a + * timer. + * + * @param validateOnDelay + */ + public void setValidateOnDelay(boolean validateOnDelay) { + this.validateOnDelay = validateOnDelay; + + if (validateOnDelay) { + text.addModifyListener(this); + } else { + text.removeModifyListener(this); + cancelCurrentTask(); + } + } + + /** + * Indicates that this editor should be automatically validated after the + * given timer + * + * @param millis + * The delay after which the editor should be automatically + * validated, in milliseconds. The default is 600ms + */ + public void setValidateOnDelay(int millis) { + this.delay = millis; + setValidateOnDelay(true); + if (delay == 0) { + cancelCurrentTask(); + } + } + + private void cancelCurrentTask() { + if (currentValidateTask != null) { + currentValidateTask.cancel(); + currentValidateTask = null; + } + } + + /** + * {@inheritDoc} + */ + + @Override + public void modifyText(ModifyEvent e) { + + // SWT Thread + if (validateOnDelay) { + if (delay == 0) { + commit(); // Direct commit on edition, to avoid creating useless + // threads + + return; + } + + if (timer == null) { + timer = new Timer(true); + } + + cancelCurrentTask(); + currentValidateTask = new TimerTask() { + + // Timer thread + @Override + public void run() { + StringEditor.this.getDisplay().syncExec(new Runnable() { + + // SWT Thread + @Override + public void run() { + + commit(); + } + }); + } + }; + timer.schedule(currentValidateTask, delay); + } + if (targetValidator != null) { + IStatus status = targetValidator.validate(text.getText()); + updateStatus(status); + } + if (modelValidator != null) { + IStatus status = modelValidator.validate(text.getText()); + updateStatus(status); + if (binding == null) { + update(); + } + } + + if (modelProperty != null) { // Bug 433169: The widget may be used without an Observable Value (setValue + getValue) + if (modelProperty.getValue() != null) { + if (!isReadOnly() && !modelProperty.getValue().toString().equals(text.getText())) { + text.setBackground(EDIT); + } else { + text.setBackground(DEFAULT); + } + } else { + if (text.getText().equals("")) { + text.setBackground(DEFAULT); + } else { + text.setBackground(EDIT); + } + } + } + } + + @Override + public void dispose() { + cancelCurrentTask(); + cancelChangeColorTask(); + if (timer != null) { + timer.cancel(); + timer = null; + } + super.dispose(); + } + + public Text getText() { + return text; + } + + @Override + public void updateStatus(IStatus status) { + switch (status.getSeverity()) { + case IStatus.OK: + controlDecoration.hide(); + break; + case IStatus.WARNING: + FieldDecoration warning = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_WARNING); + controlDecoration.setImage(warning.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + case IStatus.ERROR: + FieldDecoration error = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); + controlDecoration.setImage(error.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + default: + controlDecoration.hide(); + break; + } + + } + + @Override + public void changeColorField() { + if (binding != null) { + + if (timer == null) { + timer = new Timer(true); + } + + cancelChangeColorTask(); + changeColorTask = new TimerTask() { + + @Override + public void run() { + if (StringEditor.this.isDisposed()) { + return; + } + StringEditor.this.getDisplay().syncExec(new Runnable() { + + @Override + public void run() { + text.setBackground(DEFAULT); + text.update(); + } + }); + } + }; + if (errorBinding) { + text.setBackground(ERROR); + text.update(); + } else { + IStatus status = (IStatus) binding.getValidationStatus().getValue(); + switch (status.getSeverity()) { + case IStatus.OK: + case IStatus.WARNING: + timer.schedule(changeColorTask, 600); + text.setBackground(VALID); + text.update(); + break; + case IStatus.ERROR: + text.setBackground(ERROR); + text.update(); + break; + + } + } + } + } + + private void cancelChangeColorTask() { + if (changeColorTask != null) { + changeColorTask.cancel(); + changeColorTask = null; + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditorWithCompletionWrapper.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditorWithCompletionWrapper.java new file mode 100644 index 00000000000..7de49d963cc --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditorWithCompletionWrapper.java @@ -0,0 +1,200 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.TextViewer; +import org.eclipse.jface.text.contentassist.ContentAssistEvent; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.ICompletionListener; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter; +import org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; + +/** + * @author Vincent Lorenzo + * + * This class allows to build a StyledText widget allowing the completion + * + */ +public class StringEditorWithCompletionWrapper implements ISetPapyrusConverter{ + + /** + * the parser used to convert object to string and string to object + */ + public IPapyrusConverter parser; + + /** + * boolean indicating if the content assist popup is opened + */ + private boolean delayedIsOpen = false; + + /** + * the text viewer + */ + private TextViewer textViewer; + + /** + * + * Constructor. + * + * @param parent + * the parent to use to create the TextWidget + * @param helper + * the helper to use to find the elements by their name + */ + public StringEditorWithCompletionWrapper(Composite parent, IPapyrusConverter parser) { + setPapyrusConverter(parser); + buildControls(parent, SWT.NONE); + } + + /** + * + * Constructor. + * + * @param parent + * the parent to use to create the TextWidget + * @param helper + * the helper to use to find the elements by their name + */ + public StringEditorWithCompletionWrapper(Composite parent, int style, IPapyrusConverter parser) { + setPapyrusConverter(parser); + buildControls(parent, style); + } + + /** + * + * Constructor. + * + * @param parent + * the parent to use to create the TextWidget + * @param helper + * the helper to use to find the elements by their name + */ + public StringEditorWithCompletionWrapper(Composite parent, int style) { + buildControls(parent, style); + } + + + /** + * + * @return + * the text viewer used + */ + public TextViewer getTextViewer() { + return this.textViewer; + } + + /** + * + * @return + * the styled text used or <code>null</code> + */ + public StyledText getTextWidget() { + if (this.textViewer != null) { + return this.textViewer.getTextWidget(); + } + return null; + } + + + /** + * + * @return + * <code>true</code> if the content assist is currently opened + */ + public boolean isContentAssistOpened() { + return delayedIsOpen; + } + + private ContentAssistant assistant; + + private IContentAssistProcessor processor; + + private void buildControls(Composite parent, int style) { + // setLayout(new FillLayout()); + textViewer = new TextViewer(parent, SWT.SINGLE | SWT.V_SCROLL | style); + + textViewer.setDocument(new Document()); + + this.assistant = new ContentAssistant(); + + + if (parser != null) { + this.processor = parser.getCompletionProcessor(null); + assistant.setContentAssistProcessor(this.processor, IDocument.DEFAULT_CONTENT_TYPE); + } + + assistant.install(textViewer); + assistant.addCompletionListener(new ICompletionListener() { + + @Override + public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) { + + } + + @Override + public void assistSessionStarted(ContentAssistEvent event) { + // reset open status asynchronously. + Display.getDefault().asyncExec(new Runnable() { + + public void run() { + delayedIsOpen = true; + } + }); + } + + @Override + public void assistSessionEnded(ContentAssistEvent event) { + // reset open status asynchronously. + Display.getDefault().asyncExec(new Runnable() { + + public void run() { + delayedIsOpen = false; + } + }); + + } + }); + textViewer.getControl().addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (SWT.CTRL == e.stateMask && SWT.SPACE == e.character) { + assistant.showPossibleCompletions(); + } + } + }); + } + + /** + * @see org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter#setPapyrusConverter(org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter) + * + * @param parser + */ + @Override + public void setPapyrusConverter(IPapyrusConverter parser) { + this.parser = parser; + if (parser != null && assistant!=null && processor==null) { + this.processor = parser.getCompletionProcessor(null); + assistant.setContentAssistProcessor(this.processor, IDocument.DEFAULT_CONTENT_TYPE); + } + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringFileSelector.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringFileSelector.java new file mode 100644 index 00000000000..941c2711c9e --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringFileSelector.java @@ -0,0 +1,244 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.io.File; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService; +import org.eclipse.papyrus.infra.services.labelprovider.service.impl.LabelProviderServiceImpl; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.WorkspaceContentProvider; +import org.eclipse.papyrus.infra.widgets.util.FileUtil; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.FileDialog; + +/** + * A Widget for editing Strings with File paths + * The file paths may be absolute (FileSystem paths) or relative to the workspace (Workspace paths) + * + * @author Camille Letavernier + */ +public class StringFileSelector extends StringEditor { + + private Button browse; + + private Button browseWorkspace; + + private List<String> filterNames; + + private List<String> filterExtensions; + + private boolean allowWorkspace = true, allowFileSystem = true; + + private boolean readOnly = false; + + public StringFileSelector(Composite parent, int style) { + super(parent, style); + ((GridLayout) getLayout()).numColumns = 5; + + browse = factory.createButton(this, Messages.StringFileSelector_Browse, SWT.PUSH); + browse.setLayoutData(new GridData()); + browseWorkspace = factory.createButton(this, Messages.StringFileSelector_BrowseWorkspace, SWT.PUSH); + browseWorkspace.setLayoutData(new GridData()); + + filterNames = new LinkedList<String>(); + filterExtensions = new LinkedList<String>(); + + browse.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + File file = FileUtil.getFile(text.getText()); + + FileDialog dialog = new FileDialog(getShell()); + if (labelText != null) { + dialog.setText(labelText); + } + dialog.setFileName(file.getAbsolutePath()); + dialog.setFilterExtensions(filterExtensions.toArray(new String[filterExtensions.size()])); + dialog.setFilterNames(filterNames.toArray(new String[filterNames.size()])); + String result = dialog.open(); + if (result == null) { // Cancel + return; + } + setResult(result); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + + }); + + browseWorkspace.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + LabelProviderService labelProviderService = new LabelProviderServiceImpl(); + try { + labelProviderService.startService(); + } catch (ServiceException ex) { + Activator.log.error(ex); + } + + ILabelProvider labelProvider = labelProviderService.getLabelProvider(); + + IFile currentFile = FileUtil.getIFile(text.getText()); + + TreeSelectorDialog dialog = new TreeSelectorDialog(getShell()); + if (labelText != null) { + dialog.setTitle(labelText); + } + + WorkspaceContentProvider contentProvider = new WorkspaceContentProvider(); + + if (!(filterExtensions.isEmpty() || filterNames.isEmpty())) { + // The filters have been defined + contentProvider.setExtensionFilters(new LinkedHashMap<String, String>()); // Reset the default filters + + // Use our own filters + for (int i = 0; i < Math.min(filterNames.size(), filterExtensions.size()); i++) { + contentProvider.addExtensionFilter(filterExtensions.get(i), filterNames.get(i)); + } + } + + dialog.setContentProvider(contentProvider); + dialog.setLabelProvider(labelProvider); + + + if (currentFile != null && currentFile.exists()) { + dialog.setInitialSelections(new IFile[] { currentFile }); + } + + int code = dialog.open(); + if (code == Window.OK) { + Object[] result = dialog.getResult(); + if (result.length > 0) { + Object file = result[0]; + if (file instanceof IFile) { + setResult((IFile) file); + } + } + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing + } + + }); + } + + protected void setResult(IFile file) { + text.setText(file.getFullPath().toString()); + notifyChange(); + } + + protected void setResult(File file) { + text.setText(file.getAbsolutePath()); + notifyChange(); + } + + protected void setResult(String path) { + text.setText(path); + notifyChange(); + } + + public void setFilters(String[] filterExtensions, String[] filterNames) { + if (filterExtensions.length != filterNames.length) { + // This is a simple warning. Only valid filters will be retained. + Activator.log.warn(Messages.StringFileSelector_0); + } + + setFilterNames(getFilterLabels(filterNames, filterExtensions)); + setFilterExtensions(filterExtensions); + } + + protected String[] getFilterLabels(String[] filterNames, String[] filterExtensions) { + int size = Math.min(filterNames.length, filterExtensions.length); + String[] filters = new String[size]; + for (int i = 0; i < size; i++) { + filters[i] = filterNames[i] + " (" + filterExtensions[i] + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } + return filters; + } + + public void setFilterExtensions(String[] filterExtensions) { + this.filterExtensions = Arrays.asList(filterExtensions); + } + + public void setFilterNames(String[] filterNames) { + this.filterNames = Arrays.asList(filterNames); + } + + public void addFilteredExtension(String filteredExtension, String filterName) { + if (filteredExtension != null) { + if (filterName == null) { + filterName = filteredExtension; + } + + filterExtensions.add(filteredExtension); + filterNames.add(filterName); + } + } + + @Override + public Object getEditableType() { + return String.class; + } + + @Override + public void setReadOnly(boolean readOnly) { + super.setReadOnly(readOnly); + this.readOnly = readOnly; + updateButtons(); + } + + public void setAllowWorkspace(boolean allowWorkspace) { + this.allowWorkspace = allowWorkspace; + updateButtons(); + } + + public void setAllowFileSystem(boolean allowFileSystem) { + + this.allowFileSystem = allowFileSystem; + updateButtons(); + } + + private void updateButtons() { + boolean enableWorkspace = !readOnly && allowWorkspace; + boolean enableFileSystem = !readOnly && allowFileSystem; + // ((GridData)browseWorkspace.getLayoutData()).exclude = !allowWorkspace; + // ((GridData)browse.getLayoutData()).exclude = !allowFileSystem; + browseWorkspace.setEnabled(enableWorkspace); + browse.setEnabled(enableFileSystem); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringLabel.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringLabel.java new file mode 100644 index 00000000000..28b1e0bd892 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringLabel.java @@ -0,0 +1,161 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Thibault Le Ouay t.leouay@sherpa-eng.com - Add binding implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; + +/** + * A Read only widget to display Strings as a CLabel. + * May also be used to display an Object with an ILabelProvider + * + * @author Camille Letavernier + */ +public class StringLabel extends AbstractValueEditor implements IChangeListener { + + private final CLabel valueLabel; + + private ILabelProvider labelProvider; + + private Object value; + + /** + * Constructor. + * + * @param parent + * The Composite widget in which this editor is created + * @param style + * The style to be applied to this editor's CLabel + */ + public StringLabel(final Composite parent, final int style) { + super(parent, style); + this.valueLabel = factory.createCLabel(this, "", style); //$NON-NLS-1$ + this.valueLabel.setLayoutData(getDefaultLayoutData()); + this.labelProvider = new LabelProvider(); + } + + /** + * @return + * The CLabel used to display this editor's value + */ + public CLabel getValueLabel() { + return this.valueLabel; + } + + /** + * Sets the label provider for this editor. Useful when the value is not a + * String + * + * @param labelProvider + * The Label provider used to display the current value + */ + public void setLabelProvider(final ILabelProvider labelProvider) { + if (labelProvider == null) { + return; + } + + this.labelProvider = labelProvider; + if (this.binding != null) { + this.binding.updateModelToTarget(); + } + } + + @Override + public void doBinding() { + // We don't do a real databinding here + this.modelProperty.addChangeListener(this); + valueLabel.addDisposeListener(this); + updateLabel(); + } + + /** + * Updates the CLabel's display + */ + protected void updateLabel() { + if (valueLabel.isDisposed()) { + Activator.log.warn("Widget is disposed"); //$NON-NLS-1$ + return; + } + + Object value = getValue(); + + String text = this.labelProvider.getText(value); + Image image = this.labelProvider.getImage(value); + + this.valueLabel.setText(text); + this.valueLabel.setImage(image); + } + + @Override + public Object getValue() { + if (modelProperty != null) { + return modelProperty.getValue(); + } + return value; + } + + public void setValue(Object value) { + if (modelProperty != null) { + modelProperty.setValue(value); + } + this.value = value; + + updateLabel(); + } + + @Override + public Object getEditableType() { + return String.class; + } + + @Override + public void setReadOnly(final boolean readOnly) { + // Nothing + } + + @Override + public boolean isReadOnly() { + return !this.valueLabel.isEnabled(); + } + + @Override + public void setToolTipText(final String text) { + this.valueLabel.setToolTipText(text); + super.setLabelToolTipText(text); + } + + @Override + public void handleChange(final ChangeEvent event) { + updateLabel(); + } + + @Override + public void dispose() { + if (this.modelProperty != null) { + this.modelProperty.removeChangeListener(this); + } + super.dispose(); + } + + @Override + public void refreshValue() { + updateLabel(); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringMask.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringMask.java new file mode 100644 index 00000000000..7ab1b6f7bc1 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringMask.java @@ -0,0 +1,222 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.core.databinding.observable.ChangeEvent; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +/** + * A Widget to manipulate a list of values. + * + * The widget is configured with a Map of (String, String) entries (Key -> Label). + * It returns the list of selected keys. + * + * @author Camille Letavernier + */ +public class StringMask extends AbstractListEditor implements SelectionListener, IChangeListener, DisposeListener { + + private Button[] checkboxes; + + private Collection<String> currentValue; + + private final Composite checkboxContainer; + + private boolean refreshCheckboxes = true; + + private boolean isReadOnly = false; + + public static final String DATA_KEY = "stringValue"; //$NON-NLS-1$ + + public StringMask(final Composite parent, final int style) { + super(parent, style); + checkboxContainer = new Composite(this, style); + checkboxContainer.setLayoutData(getDefaultLayoutData()); + checkboxContainer.setLayout(new GridLayout(2, true)); + checkboxContainer.addDisposeListener(this); + } + + @Override + protected GridData getLabelLayoutData() { + GridData data = super.getLabelLayoutData(); + data.verticalAlignment = SWT.BEGINNING; + return data; + } + + public Collection<String> getValue() { + Set<String> values = new HashSet<String>(); + for (Button button : checkboxes) { + if (button.getSelection()) { + String value = (String) button.getData(DATA_KEY); + values.add(value); + } + } + return values; + } + + @Override + public void dispose() { + if (modelProperty != null) { + modelProperty.removeChangeListener(this); + } + super.dispose(); + } + + @Override + public Object getEditableType() { + return String.class; + } + + @Override + public void setReadOnly(final boolean readOnly) { + this.isReadOnly = readOnly; + for (Button button : checkboxes) { + button.setEnabled(!readOnly); + } + } + + @Override + public boolean isReadOnly() { + return isReadOnly; + } + + public void setMasks(final Map<String, String> values) { + if (checkboxes != null) { + disposeCheckboxes(); + } + + checkboxes = new Button[values.size()]; + + int i = 0; + for (Entry<String, String> mask : values.entrySet()) { + String stringValue = mask.getKey(); + String label = mask.getValue(); + + checkboxes[i] = new Button(checkboxContainer, SWT.CHECK); + checkboxes[i].setText(label); + checkboxes[i].setData(DATA_KEY, stringValue); + checkboxes[i].addSelectionListener(this); + checkboxes[i].setToolTipText(stringValue); + i++; + } + } + + protected void disposeCheckboxes() { + for (Button button : checkboxes) { + button.removeSelectionListener(this); + button.dispose(); + } + } + + public void setNumColumns(final int numColumns) { + ((GridLayout) checkboxContainer.getLayout()).numColumns = numColumns; + checkboxContainer.layout(); + layout(); + } + + @Override + public void doBinding() { + // We don't do a real databinding here + modelProperty.addChangeListener(this); + + refreshCheckboxes(); + } + + protected void refreshCheckboxes() { + if (!refreshCheckboxes) { + return; + } + + Collection<String> values = getCurrentValue(); + for (Button button : checkboxes) { + String value = (String) button.getData(DATA_KEY); + button.setSelection(values.contains(value)); + } + } + + @Override + public void setToolTipText(final String text) { + super.setLabelToolTipText(text); + } + + @Override + public void widgetSelected(final SelectionEvent e) { + Button button = (Button) e.widget; + String value = (String) button.getData(DATA_KEY); + Collection<String> values = new HashSet<String>(getCurrentValue()); + if (button.getSelection()) { + values.add(value); + } else { + values.remove(value); + } + setCurrentValue(values); + } + + protected void setCurrentValue(final Collection<String> values) { + if (modelProperty != null) { + refreshCheckboxes = false; + modelProperty.clear(); + modelProperty.addAll(values); + refreshCheckboxes = true; + } + currentValue = values; + + commit(); + } + + protected Collection<String> getCurrentValue() { + if (modelProperty != null) { + return modelProperty; + } else { + return currentValue; + } + } + + @Override + public void widgetDefaultSelected(final SelectionEvent e) { + // Nothing + } + + public int getNumColumns() { + return ((GridLayout) checkboxContainer.getLayout()).numColumns; + } + + @Override + public void handleChange(final ChangeEvent event) { + refreshCheckboxes(); + } + + /** + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractEditor#changeColorField() + * + */ + + @Override + public void changeColorField() { + // TODO Auto-generated method stub + + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StyledTextReferenceDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StyledTextReferenceDialog.java new file mode 100644 index 00000000000..9206ebbec79 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StyledTextReferenceDialog.java @@ -0,0 +1,744 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Nicolas FAUVERGUE (ALL4TEC� nicolas.fauvergue@all4tec.net - Bug 459747 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.databinding.StyledTextReferenceDialogObservableValue; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IAdaptableContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.validator.AbstractValidator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Widget; + +/** + * An editor representing a single reference as a String Editor. A filtered selection + * dialog is used to edit the value. Also offers support for unsetting the + * value. This Editor needs a ContentProvider, and may use an optional + * LabelProvider, describing the objects that can be referred by this property + * + * @author Vincent Lorenzo + * + * Duplicated code from {@link ReferenceDialog}, replacing CLabel by {@link StyledTextStringEditor} + * + */ +public class StyledTextReferenceDialog extends AbstractReferenceDialog implements SelectionListener { + + /** + * The styled text displaying the current value + */ + protected final StyledTextStringEditor styledTextStringEditor; + + /** + * The Button used to browse the available values + */ + protected Button browseValuesButton; + + /** + * The Button used to create a new instance + */ + protected Button createInstanceButton; + + /** + * The Button used to edit the current object + */ + protected Button editInstanceButton; + + /** + * The Button used to unset the current value + */ + protected Button unsetButton; + + /** + * The label provider used to display the values in both the label and the + * selection dialog + */ + protected ILabelProvider labelProvider; + + /** + * The content provider, providing the different possible values for the + * input object + */ + protected IStaticContentProvider contentProvider; + + /** + * The dialog used to select the value + */ + protected final ITreeSelectorDialog dialog; + + /** + * The current value for this editor + */ + protected Object value; + + /** + * The factory used to create or edit objects directly from this editor + */ + protected ReferenceValueFactory valueFactory; + + /** + * Boolean to detect direct creation. + */ + private boolean directCreation; + + /** + * Determinate if an error occurred. + */ + protected boolean error = false; + + /** + * The timer. + */ + private Timer timer; + + /** + * The timer tack for the change color. + */ + private TimerTask changeColorTask; + + /** + * Determinate if an edit occurred. + */ + private boolean edit = false; + + /** + * Constructs a new ReferenceDialog in the given parent Composite. The style + * will be applied to the syled text displaying the current value. + * + * @param parent + * The parent composite. + * @param style + * The style of the styled text. + */ + public StyledTextReferenceDialog(final Composite parent, final int style) { + this(parent, style, null); + } + + /** + * Constructs a new ReferenceDialog in the given parent Composite. The style will be applied to the styled text displaying the current value. This constructor manage the value validator. + * + * @param parent + * The parent composite. + * @param style + * The style of the styled text. + * @param targetValidator + * The validator used for the styled text. + */ + public StyledTextReferenceDialog(final Composite parent, final int style, final AbstractValidator targetValidator) { + super(parent, style); + this.targetValidator = targetValidator; + GridData gridData = getDefaultLayoutData(); + + styledTextStringEditor = createStyledTextStringEditor(this, null, factory.getBorderStyle() | style); + styledTextStringEditor.setLayoutData(gridData); + styledTextStringEditor.addMouseListener(new MouseListener() { + + @Override + public void mouseDoubleClick(MouseEvent e) { + editAction(); // TODO : Try to determine whether the double + // click should call the edit, create or browse action + // e.g. if the value is null, try to browse. If we cannot + // browse, try to create an instance. + } + + @Override + public void mouseDown(MouseEvent e) { + // Nothing + } + + @Override + public void mouseUp(MouseEvent e) { + // Nothing + } + + }); + + dialog = createDialog(parent.getShell()); + + createButtons(); + updateControls(); + controlDecoration = new ControlDecoration(styledTextStringEditor, SWT.TOP | SWT.LEFT); + + gridData.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + } + + /** + * This allow to create the styled text editor. + * + * @param parent + * The parent composite. + * @param initialValue + * The initial value of the styled text. + * @param style + * The style of the styled text. + * @return The created {@link StyledTextStringEditor}. + */ + protected StyledTextStringEditor createStyledTextStringEditor(final Composite parent, final String initialValue, final int style) { + StyledTextStringEditor editor = new StyledTextStringEditor(parent, style, targetValidator); + editor.setValue(initialValue); + return editor; + } + + /** + * This allow to create the dialog. + * + * @param shell + * The current shell. + * @return The created {@link ITreeSelectorDialog}. + */ + protected ITreeSelectorDialog createDialog(final Shell shell) { + return new TreeSelectorDialog(shell); + } + + /** + * This allow to create the buttons of the reference dialog (browse, create, edit and unset). + */ + protected void createButtons() { + ((GridLayout) getLayout()).numColumns += 4; + + browseValuesButton = factory.createButton(this, null, SWT.PUSH); + browseValuesButton.setImage(Activator.getDefault().getImage("/icons/browse_12x12.gif")); //$NON-NLS-1$ + browseValuesButton.setToolTipText(Messages.ReferenceDialog_EditValue); + browseValuesButton.addSelectionListener(this); + + createInstanceButton = factory.createButton(this, null, SWT.PUSH); + createInstanceButton.setImage(Activator.getDefault().getImage("/icons/Add_12x12.gif")); //$NON-NLS-1$ + createInstanceButton.setToolTipText(Messages.ReferenceDialog_CreateANewObject); + createInstanceButton.addSelectionListener(this); + + editInstanceButton = factory.createButton(this, null, SWT.PUSH); + editInstanceButton.setImage(Activator.getDefault().getImage("/icons/Edit_12x12.gif")); //$NON-NLS-1$ + editInstanceButton.setToolTipText(Messages.ReferenceDialog_EditTheCurrentValue); + editInstanceButton.addSelectionListener(this); + + unsetButton = factory.createButton(this, null, SWT.PUSH); + unsetButton.setImage(Activator.getDefault().getImage("/icons/Delete_12x12.gif")); //$NON-NLS-1$ + unsetButton.setToolTipText(Messages.ReferenceDialog_UnsetValue); + unsetButton.addSelectionListener(this); + } + + /** + * The action executed when the "browse" button is selected Choose a value + * from a selection of already created objects + */ + protected void browseAction() { + setInitialSelection(Collections.singletonList(getValue())); + int result = dialog.open(); + if (result == Window.OK) { + Object[] newValue = dialog.getResult(); + if (newValue == null) { + return; + } + + if (newValue.length == 0) { + setValue(null); + } else { + Object value = newValue[0]; + if (contentProvider instanceof IAdaptableContentProvider) { + + value = ((IAdaptableContentProvider) contentProvider).getAdaptedValue(value); + } + setValue(value); + styledTextStringEditor.setValue(labelProvider.getText(newValue)); + } + } + } + + /** + * The action executed when the "create" button is selected Create a new + * instance and assign it to this reference + */ + protected void createAction() { + if (valueFactory != null && valueFactory.canCreateObject()) { + final Object context = getContextElement(); + getOperationExecutor(context).execute(new Runnable() { + + @Override + public void run() { + Object value = valueFactory.createObject(createInstanceButton, context); + if (value == null) { + // Cancel the operation + throw new OperationCanceledException(); + } + Collection<Object> validatedObjects = valueFactory.validateObjects(Collections.singleton(value)); + if (!validatedObjects.isEmpty()) { + final Object newValue = validatedObjects.iterator().next(); + setValue(newValue); + styledTextStringEditor.setValue(labelProvider.getText(newValue)); + } + } + }, NLS.bind(Messages.ReferenceDialog_setOperation, labelText)); + } + } + + /** + * The action executed when the "edit" button is selected Edits the object + * that is currently selected + */ + protected void editAction() { + styledTextStringEditor.setBackground(EDIT); + edit = true; + final Object currentValue = getValue(); + if (currentValue != null && valueFactory != null && valueFactory.canEdit()) { + getOperationExecutor(currentValue).execute(new Runnable() { + + @Override + public void run() { + Object newValue = valueFactory.edit(editInstanceButton, currentValue); + + // Per the contract of ReferenceValueFactory::edit(), a null return means the object was edited "in place." + // In that case, there is nothing further to do + if (newValue != null) { + setValue(newValue); + styledTextStringEditor.setValue(labelProvider.getText(newValue)); + } + + updateLabel(); + } + }, NLS.bind(Messages.ReferenceDialog_editOperation, labelText)); + } + } + + /** + * The action executed when the "unset" button is selected Sets the current + * reference to null + */ + protected void unsetAction() { + setValue(null); + } + + /** + * Updates the displayed label for the current value + */ + @Override + public void updateLabel() { + if (binding != null) { + binding.updateModelToTarget(); + } else { + if (null != labelProvider) { + styledTextStringEditor.setValue(labelProvider.getText(getValue())); + } + } + } + + /** + * Sets the Content provider for this editor + * + * @param provider + * The content provider used to retrieve the possible values for + * this Reference + */ + @Override + public void setContentProvider(final IStaticContentProvider provider) { + dialog.setContentProvider(new EncapsulatedContentProvider(provider)); + if (getValue() != null) { + setInitialSelection(Collections.singletonList(getValue())); + } + + this.contentProvider = provider; + } + + /** + * Sets the Label provider for this editor If the label provider is null, a + * default one will be used. The same label provider is used for both the + * editor's label and the selection dialog. + * + * @param provider + * The label provider + */ + @Override + public void setLabelProvider(final ILabelProvider provider) { + if (provider == null) { + setLabelProvider(new LabelProvider()); + return; + } + + dialog.setLabelProvider(provider); + this.labelProvider = provider; + if (widgetObservable != null) { + ((StyledTextReferenceDialogObservableValue) widgetObservable).setLabelProvider(labelProvider); + } + updateLabel(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setLabel(final String label) { + super.setLabel(label); + dialog.setTitle(label); + } + + /** + * {@inheritDoc} + */ + @Override + public Object getValue() { + if (modelProperty != null) { + return modelProperty.getValue(); + } + return value; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Object.class; + } + + /** + * {@inheritDoc} + */ + @Override + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + updateControls(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isReadOnly() { + return !styledTextStringEditor.isEnabled(); + } + + /** + * Set the initial selection. + * + * @param initialValues + * The list of possible values. + */ + protected void setInitialSelection(final List<?> initialValues) { + dialog.setInitialElementSelections(initialValues); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractValueEditor#setModelObservable(org.eclipse.core.databinding.observable.value.IObservableValue) + */ + @Override + public void setModelObservable(final IObservableValue modelProperty) { + setWidgetObservable(createWidgetObservable(modelProperty)); + super.setModelObservable(modelProperty); + this.styledTextStringEditor.setModelObservable(modelProperty); + + updateControls(); + } + + /** + * This allow to create the widget observable value. + * + * @param modelProperty + * The current observable value. + * @return The created {@link StyledTextReferenceDialogObservableValue}. + */ + protected IObservableValue createWidgetObservable(final IObservableValue modelProperty) { + return new StyledTextReferenceDialogObservableValue(this, this.styledTextStringEditor.getText(), modelProperty, SWT.FocusOut, labelProvider); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.widgets.Control#setToolTipText(java.lang.String) + */ + @Override + public void setToolTipText(final String text) { + super.setLabelToolTipText(text); + styledTextStringEditor.setToolTipText(text); + } + + /** + * Set the factory. + * + * @param factory + * The reference value factory. + */ + @Override + public void setValueFactory(final ReferenceValueFactory factory) { + valueFactory = factory; + updateControls(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetSelected(final SelectionEvent e) { + Widget widget = e.widget; + if (widget == browseValuesButton) { + browseAction(); + } else if (widget == createInstanceButton) { + createAction(); + } else if (widget == editInstanceButton) { + editAction(); + } else if (widget == unsetButton) { + unsetAction(); + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetDefaultSelected(final SelectionEvent e) { + // Nothing + } + + /** + * Updates the buttons' status + */ + @Override + public void updateControls() { + // Check if the edit & create buttons should be displayed + boolean exclude = valueFactory == null || !valueFactory.canCreateObject(); + setExclusion(editInstanceButton, exclude); + setExclusion(createInstanceButton, exclude); + + setExclusion(browseValuesButton, directCreation); + + browseValuesButton.setEnabled(!readOnly); + + // If they are displayed, check if they should be enabled + if (!exclude) { + editInstanceButton.setEnabled(valueFactory != null && valueFactory.canEdit() && getValue() != null); + createInstanceButton.setEnabled(valueFactory != null && valueFactory.canCreateObject() && !readOnly); + } + + // Do not display unset if the value is mandatory + setExclusion(unsetButton, mandatory); + if (!mandatory) { + boolean enabled = !readOnly; + enabled = enabled && getValue() != null; + + unsetButton.setEnabled(enabled); + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.widgets.Control#update() + */ + @Override + public void update() { + super.update(); + updateControls(); + } + + /** + * Set the direct creation value. + * + * @param directCreation + * Boolean to determinate the direct creation value. + */ + @Override + public void setDirectCreation(final boolean directCreation) { + this.directCreation = directCreation; + updateControls(); + } + + /** + * Set the value. + * + * @param value + * The value object. + */ + public void setValue(final Object value) { + this.value = value; + try { + if (modelProperty != null) { + modelProperty.setValue(value); + error = false; + } + } catch (Exception e) { + error = true; + + } + + updateControls(); + updateLabel(); + commit(); + } + + /** + * @see org.eclipse.jface.viewers.StructuredViewer#setInput(Object) + * @param input + * The current input; + */ + public void setInput(final Object input) { + this.dialog.setInput(input); + } + + /** + * Set the mandatory. + * + * @param mandatory + * The mandatory boolean value. + */ + @Override + public void setMandatory(final boolean mandatory) { + this.mandatory = mandatory; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractValueEditor#updateStatus(org.eclipse.core.runtime.IStatus) + */ + @Override + public void updateStatus(final IStatus status) { + + if (error) { + FieldDecoration error = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); + controlDecoration.setImage(error.getImage()); + controlDecoration.showHoverText(Messages.ReferenceDialog_0); + controlDecoration.setDescriptionText(Messages.ReferenceDialog_1); + controlDecoration.show(); + styledTextStringEditor.setBackground(ERROR); + styledTextStringEditor.update(); + + + } else { + controlDecoration.hide(); + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.swt.widgets.Widget#dispose() + */ + @Override + public void dispose() { + if (null != changeColorTask) { + changeColorTask.cancel(); + } + if (null != timer) { + timer.cancel(); + } + if (null != styledTextStringEditor) { + styledTextStringEditor.dispose(); + } + super.dispose(); + } + + /** + * This allow to react of cancel of the current task. + */ + private void cancelCurrentTask() { + if (changeColorTask != null) { + changeColorTask.cancel(); + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.papyrus.infra.widgets.editors.AbstractEditor#changeColorField() + */ + @Override + public void changeColorField() { + if (!error & !edit) { + + if (null == timer) { + timer = new Timer(true); + } + + cancelCurrentTask(); + changeColorTask = new TimerTask() { + + @Override + public void run() { + if (StyledTextReferenceDialog.this.isDisposed()) { + return; + } + StyledTextReferenceDialog.this.getDisplay().syncExec(new Runnable() { + + @Override + public void run() { + if (StyledTextReferenceDialog.this.isDisposed()) {// Bug 434787 : Shouldn't not execute the timer thread if the widget is disposed + return; + } + styledTextStringEditor.setBackground(DEFAULT); + styledTextStringEditor.update(); + } + + + }); + } + }; + + if (errorBinding) { + styledTextStringEditor.setBackground(ERROR); + styledTextStringEditor.update(); + } else { + IStatus status = (IStatus) binding.getValidationStatus().getValue(); + switch (status.getSeverity()) { + case IStatus.OK: + case IStatus.WARNING: + timer.schedule(changeColorTask, 600); + styledTextStringEditor.setBackground(VALID); + styledTextStringEditor.update(); + break; + case IStatus.ERROR: + styledTextStringEditor.setBackground(ERROR); + styledTextStringEditor.update(); + break; + + } + } + } else { + styledTextStringEditor.setBackground(DEFAULT); + styledTextStringEditor.update(); + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StyledTextStringEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StyledTextStringEditor.java new file mode 100644 index 00000000000..becc57dd823 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StyledTextStringEditor.java @@ -0,0 +1,573 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue@all4tec.net - Bug 446865 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + + +import java.util.Timer; +import java.util.TimerTask; + +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.papyrus.infra.widgets.databinding.StyledTextObservableValue; +import org.eclipse.papyrus.infra.widgets.selectors.StringSelector; +import org.eclipse.papyrus.infra.widgets.validator.AbstractValidator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; + +/** + * A Property Editor representing a single-line or multi-line String value as a + * Text. This editor's content is validated when the focus is lost, or, if the + * editor is single-line, when the Carriage Return is pressed. For a multi-line + * editor, ctrl+enter will also validate the editor's content. + * + * @see SWT#MULTI + * + * @author Vincent Lorenzo, adapted code from {@link StringEditor} + */ +public class StyledTextStringEditor extends AbstractValueEditor implements KeyListener, ModifyListener { + + /** + * The text box for editing this editor's value + */ + protected final StyledText text; + + private int delay = 600; + + private boolean validateOnDelay = false; + + private Timer timer; + + private TimerTask currentValidateTask; + + private TimerTask changeColorTask; + + private final static int DEFAULT_HEIGHT_HINT = 55; + + private final static int DEFAULT_WIDTH_HINT = 100; + + + /** + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + */ + public StyledTextStringEditor(Composite parent, int style) { + this(parent, style, null, DEFAULT_HEIGHT_HINT, DEFAULT_WIDTH_HINT); + } + + /** + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + * @param targetValidator + * The validator used for the styled text. + */ + public StyledTextStringEditor(final Composite parent, final int style, final AbstractValidator targetValidator) { + this(parent, style, null, DEFAULT_HEIGHT_HINT, DEFAULT_WIDTH_HINT, targetValidator); + } + + /** + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + * @param label + * The label for this editor + */ + public StyledTextStringEditor(Composite parent, int style, String label) { + this(parent, style, label, DEFAULT_HEIGHT_HINT, DEFAULT_WIDTH_HINT); + } + + /** + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + * @param label + * The label for this editor + * @param targetValidator + * The validator used for the styled text. + */ + public StyledTextStringEditor(final Composite parent, final int style, final String label, final AbstractValidator targetValidator) { + this(parent, style, label, DEFAULT_HEIGHT_HINT, DEFAULT_WIDTH_HINT, targetValidator); + } + + /** + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + * @param heighHint + * Height hint of the text area in multiline mode + * @param widthHint + * Width hint of the text area in multiline mode + */ + public StyledTextStringEditor(Composite parent, int style, int heighHint, int widthHint) { + this(parent, style, null, heighHint, widthHint); + } + + /** + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + * @param label + * The label for this editor + * @param heighHint + * Height hint of the text area in multiline mode + * @param widthHint + * Width hint of the text area in multiline mode + */ + public StyledTextStringEditor(Composite parent, int style, String label, int heighHint, int widthHint) { + this(parent, style, label, heighHint, widthHint, null); + } + + /** + * Constructor. + * + * @param parent + * The composite in which this editor should be displayed + * @param style + * The style for this editor's text box + * @param label + * The label for this editor + * @param heighHint + * Height hint of the text area in multiline mode + * @param widthHint + * Width hint of the text area in multiline mode + * @param targetValidator + * The validator used for the styled text. + */ + public StyledTextStringEditor(final Composite parent, final int style, final String label, final int heighHint, final int widthHint, final AbstractValidator targetValidator) { + super(parent, label); + + this.targetValidator = targetValidator; + + GridData data = getDefaultLayoutData(); + data.grabExcessVerticalSpace = true; + data.grabExcessHorizontalSpace = true; + data.verticalAlignment = SWT.FILL; + data.horizontalAlignment = SWT.FILL; + int styledTextStyle = style; + if ((style & SWT.MULTI) != 0) { + data.minimumHeight = heighHint; + data.minimumWidth = widthHint; + styledTextStyle = style | SWT.V_SCROLL; + } + + text = createStyledText(this, null, styledTextStyle); + text.setLayoutData(data); + + if (label != null) { + super.label.setLayoutData(getLabelLayoutData()); + + } + text.addKeyListener(this); + text.addModifyListener(this); + setCommitOnFocusLost(text); + controlDecoration = new ControlDecoration(text, SWT.LEFT | SWT.TOP); + controlDecoration.hide(); + + // we ignore the indentation + // data.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(); + + // we remove the margin + GridLayout layout = (GridLayout) this.getLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + + pack(); + } + + + /** + * Creates a styled text as a part of the form. + * + * @param parent + * the text parent + * @param value + * the text initial value + * @param style + * the text style + * @return the styled text widget + */ + public StyledText createStyledText(Composite parent, String value, int style) { + StyledText txt = new StyledText(parent, style); + txt.setText(value); + return txt; + } + + + @Override + protected GridData getLabelLayoutData() { + GridData result = super.getLabelLayoutData(); + if (text != null) { + if ((text.getStyle() & SWT.MULTI) != 0) { + result.verticalAlignment = SWT.BEGINNING; + } + } + return result; + } + + /** + * Ignored + */ + @Override + public void keyPressed(KeyEvent e) { + // Nothing + } + + /** + * Validates this editor when one of the following events occur : - CR + * released - Keypad CR released - Ctrl + [CR | Keypad CR] released + * + * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent) + * + * @param e + */ + // TODO : we should prevent the \n from being written when validating the + // multi-line field with Ctrl + CR + @Override + public void keyReleased(KeyEvent e) { + // We listen on Carriage Return or Ctrl+ Carriage return, depending on + // whether the editor is single- or multi-line + if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) { + if ((text.getStyle() & SWT.MULTI) == 0) { // Single-line : Enter + if (e.stateMask == SWT.NONE) { + notifyChange(); + } + } else { // Multi-line : Ctrl+Enter + if (e.stateMask == SWT.CTRL) { + String str = text.getText(); + if (str.endsWith(StringSelector.LINE_SEPARATOR)) { + int newLength = str.length() - StringSelector.LINE_SEPARATOR.length(); + text.setText(str.substring(0, newLength)); + text.setSelection(newLength); + } + notifyChange(); + } + } + } + + + } + + @Override + public void setModelObservable(IObservableValue observable) { + setWidgetObservable(new StyledTextObservableValue(text, observable, SWT.FocusOut), true); + super.setModelObservable(observable); + + } + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return String.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getValue() { + return text.getText(); + } + + @Override + public void setReadOnly(boolean readOnly) { + text.setEnabled(!readOnly); + } + + @Override + public boolean isReadOnly() { + return !text.isEnabled(); + } + + protected void notifyChange() { + + text.notifyListeners(SWT.FocusOut, new Event()); + commit(); + changeColorField(); + } + + @Override + public void setToolTipText(String tooltip) { + text.setToolTipText(tooltip); + super.setLabelToolTipText(tooltip); + } + + /** + * Sets the current text value for this editor + * + * @param value + */ + public void setValue(Object value) { + if (value instanceof String) { + this.text.setText((String) value); + } else { + this.text.setText(""); //$NON-NLS-1$ + } + } + + /** + * Indicates that this editor should be automatically validated after a + * timer. + * + * @param validateOnDelay + */ + public void setValidateOnDelay(boolean validateOnDelay) { + this.validateOnDelay = validateOnDelay; + + if (validateOnDelay) { + text.addModifyListener(this); + } else { + text.removeModifyListener(this); + cancelCurrentTask(); + } + } + + /** + * Indicates that this editor should be automatically validated after the + * given timer + * + * @param millis + * The delay after which the editor should be automatically + * validated, in milliseconds. The default is 600ms + */ + public void setValidateOnDelay(int millis) { + this.delay = millis; + setValidateOnDelay(true); + if (delay == 0) { + cancelCurrentTask(); + } + } + + private void cancelCurrentTask() { + if (currentValidateTask != null) { + currentValidateTask.cancel(); + currentValidateTask = null; + } + } + + /** + * {@inheritDoc} + */ + + @Override + public void modifyText(ModifyEvent e) { + // SWT Thread + if (validateOnDelay) { + if (delay == 0) { + commit(); // Direct commit on edition, to avoid creating useless + // threads + + return; + } + + if (timer == null) { + timer = new Timer(true); + } + + cancelCurrentTask(); + currentValidateTask = new TimerTask() { + + // Timer thread + @Override + public void run() { + StyledTextStringEditor.this.getDisplay().syncExec(new Runnable() { + + // SWT Thread + @Override + public void run() { + + commit(); + } + }); + } + }; + timer.schedule(currentValidateTask, delay); + } + if (targetValidator != null) { + IStatus status = targetValidator.validate(getTextToValidate()); + updateStatus(status); + } + if (modelValidator != null) { + IStatus status = modelValidator.validate(getTextToValidate()); + updateStatus(status); + if (binding == null) { + update(); + } + } + + if (modelProperty != null) { // Bug 433169: The widget may be used without an Observable Value (setValue + getValue) + if (modelProperty.getValue() != null) { + if (!isReadOnly() && !modelProperty.getValue().toString().equals(text.getText())) { + text.setBackground(EDIT); + } else { + text.setBackground(DEFAULT); + } + } else { + if (text.getText().equals("")) { + text.setBackground(DEFAULT); + } else { + text.setBackground(EDIT); + } + } + } + } + + /** + * Gets the string to validate. + * + * @return The string text to validate. + */ + protected String getTextToValidate() { + return text.getText(); + } + + @Override + public void dispose() { + cancelCurrentTask(); + cancelChangeColorTask(); + if (timer != null) { + timer.cancel(); + timer = null; + } + super.dispose(); + } + + public StyledText getText() { + return text; + } + + @Override + public void updateStatus(IStatus status) { + if(!isDisposed()){ + switch (status.getSeverity()) { + case IStatus.OK: + controlDecoration.hide(); + break; + case IStatus.WARNING: + FieldDecoration warning = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_WARNING); + controlDecoration.setImage(warning.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + case IStatus.ERROR: + FieldDecoration error = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); + controlDecoration.setImage(error.getImage()); + controlDecoration.showHoverText(status.getMessage()); + controlDecoration.setDescriptionText(status.getMessage()); + controlDecoration.show(); + break; + default: + controlDecoration.hide(); + break; + } + } + } + + @Override + public void changeColorField() { + if (binding != null) { + + if (timer == null) { + timer = new Timer(true); + } + + cancelChangeColorTask(); + changeColorTask = new TimerTask() { + + @Override + public void run() { + if (StyledTextStringEditor.this.isDisposed()) { + return; + } + StyledTextStringEditor.this.getDisplay().syncExec(new Runnable() { + + @Override + public void run() { + if(!text.isDisposed()){ + text.setBackground(DEFAULT); + text.update(); + } + } + }); + } + }; + if (errorBinding) { + if(!text.isDisposed()){ + text.setBackground(ERROR); + text.update(); + } + } else { + IStatus status = (IStatus) binding.getValidationStatus().getValue(); + switch (status.getSeverity()) { + case IStatus.OK: + case IStatus.WARNING: + timer.schedule(changeColorTask, 600); + if(!text.isDisposed()){ + text.setBackground(VALID); + text.update(); + } + break; + case IStatus.ERROR: + if(!text.isDisposed()){ + text.setBackground(ERROR); + text.update(); + } + break; + + } + } + } + } + + private void cancelChangeColorTask() { + if (changeColorTask != null) { + changeColorTask.cancel(); + changeColorTask = null; + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/TreeSelectorDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/TreeSelectorDialog.java new file mode 100644 index 00000000000..6d09eb33775 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/TreeSelectorDialog.java @@ -0,0 +1,270 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 408491 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.providers.IAdaptableContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IGraphicalContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IHierarchicContentProvider; +import org.eclipse.papyrus.infra.widgets.util.IRevealSemanticElement; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.SelectionDialog; + +/** + * A Dialog for selecting values. The values are displayed as a Tree. If only + * some of the values of this Tree should be selectable, you should pass a {@link IHierarchicContentProvider} to this dialog. + * + * @author Camille Letavernier + * + */ +public class TreeSelectorDialog extends SelectionDialog implements ITreeSelectorDialog { + + private ILabelProvider labelProvider; + + private ITreeContentProvider contentProvider; + + private TreeViewer treeViewer; + + private String description; + + private Label descriptionLabel; + + private Object input = null; + + private final Set<ICommitListener> commitListeners = new HashSet<ICommitListener>(); + + /** + * + * Constructor. + * + * @param parentShell + * The parent shell in which this dialog will be opened + */ + public TreeSelectorDialog(Shell parentShell) { + super(parentShell); + } + + /** + * Sets the label provider for this dialog + * + * @param provider + */ + @Override + public void setLabelProvider(ILabelProvider provider) { + labelProvider = provider; + if (treeViewer != null) { + treeViewer.setLabelProvider(labelProvider); + } + } + + /** + * Sets the ContentProvider for this dialog + * The ContentProvider may be a {@link IHierarchicContentProvider} + * + * @param provider + * The content provider for this dialog. May be a {@link IHierarchicContentProvider} + */ + @Override + public void setContentProvider(ITreeContentProvider provider) { + contentProvider = provider; + if (treeViewer != null) { + initViewerAndProvider(); + } + if (contentProvider instanceof ICommitListener) { + commitListeners.add((ICommitListener) contentProvider); + } + } + + protected void initViewerAndProvider() { + treeViewer.setContentProvider(contentProvider); + if (treeViewer.getInput() == null) { + doSetInput(); + } + } + + @Override + protected Composite getDialogArea() { + return (Composite) super.getDialogArea(); + } + + @Override + public void create() { + super.create(); + + descriptionLabel = new Label(getDialogArea(), SWT.WRAP); + descriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + if (description != null) { + descriptionLabel.setText(description); + } + + treeViewer = new TreeViewer(getDialogArea(), SWT.BORDER); + // treeViewer.setFilters(new ViewerFilter[]{ new PatternFilter() }); + + if (labelProvider != null) { + treeViewer.setLabelProvider(labelProvider); + } + if (contentProvider != null) { + initViewerAndProvider(); + } + + treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + ISelection selection = event.getSelection(); + + Object selectedElement = null; + if (selection instanceof IStructuredSelection && !selection.isEmpty()) { + IStructuredSelection sSelection = (IStructuredSelection) selection; + selectedElement = sSelection.getFirstElement(); + } + + if (contentProvider instanceof IHierarchicContentProvider) { + boolean isValidValue = ((IHierarchicContentProvider) contentProvider).isValidValue(selectedElement); + if (contentProvider instanceof IAdaptableContentProvider) { + selectedElement = ((IAdaptableContentProvider) contentProvider).getAdaptedValue(selectedElement); + } + if (isValidValue) { + setResult(Collections.singletonList(selectedElement)); + } else { + setResult(Collections.EMPTY_LIST); + } + getOkButton().setEnabled(isValidValue); + } + } + }); + + treeViewer.addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(DoubleClickEvent event) { + if (getOkButton().isEnabled()) { + okPressed(); + } + } + + }); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.minimumHeight = 300; + data.minimumWidth = 300; + treeViewer.getTree().setLayoutData(data); + + if (contentProvider instanceof IGraphicalContentProvider) { + IGraphicalContentProvider graphicalContentProvider = (IGraphicalContentProvider) contentProvider; + + Composite beforeTreeComposite = new Composite(getDialogArea(), SWT.NONE); + beforeTreeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + beforeTreeComposite.setLayout(new FillLayout()); + graphicalContentProvider.createBefore(beforeTreeComposite); + + beforeTreeComposite.moveAbove(treeViewer.getTree()); + + Composite afterTreeComposite = new Composite(getDialogArea(), SWT.NONE); + afterTreeComposite.setLayout(new FillLayout()); + afterTreeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + graphicalContentProvider.createAfter(afterTreeComposite); + } + + List<?> initialSelection = getInitialElementSelections(); + if (contentProvider instanceof IRevealSemanticElement) { + ((IRevealSemanticElement) contentProvider).revealSemanticElement(initialSelection); + } else if (!initialSelection.isEmpty()) { + // FIXME : When we use an EncapsulatedContentProvider, we'll not get into this case, + // even if the encapsulated provider is not a IRevealSemanticElement + treeViewer.setSelection(new StructuredSelection(initialSelection.get(0)), true); + } + + getShell().setDefaultButton(null); + getButton(OK).setFocus(); + getShell().setImage(Activator.getDefault().getImage("/icons/papyrus.png")); //$NON-NLS-1$ + getShell().pack(); + + } + + /** + * Sets the description for this Dialog. The description is displayed on + * top of the dialog + * + * @param description + * The description for this dialog + */ + @Override + public void setDescription(String description) { + this.description = description; + + if ((descriptionLabel != null) && !descriptionLabel.isDisposed()) { + descriptionLabel.setText(description == null ? "" : description); //$NON-NLS-1$ + } + } + + /** + * Get the TreeViewer used by this dialog + * + * @return + * The TreeViewer associated to this dialog + */ + protected TreeViewer getViewer() { + return treeViewer; + } + + /** + * Sets the input object for this dialog's TreeViewer + * + * @param input + */ + @Override + public void setInput(Object input) { + this.input = input; + } + + private void doSetInput() { + if (input == null) { + // Default non-null input for IStaticContentProvider (input-independent) + treeViewer.setInput(""); //$NON-NLS-1$ + } else { + treeViewer.setInput(input); + } + } + + @Override + public void okPressed() { + for (ICommitListener listener : commitListeners) { + listener.commit(null); + } + super.okPressed(); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/TwoInputDialog.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/TwoInputDialog.java new file mode 100644 index 00000000000..cab1ce17e24 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/TwoInputDialog.java @@ -0,0 +1,134 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * This Dialog provides 2 texts field. It was created to be used during the table creation. + * It doesn't provide validator for the second field. + * + * + */ +public class TwoInputDialog extends InputDialog { + + /** widget for the second value */ + private Text text_2; + + /** the second values */ + private String value_2; + + /** the message for the second Text */ + protected String message_2; + + /** + * + * Constructor. + * + * @param parentShell + * the parent shell + * @param dialogTitle + * the dialog title + * @param message1 + * the first message for the dialog + * @param message2 + * the second message for the dialog + * @param initialValue1 + * the first initial value + * @param initialValue2 + * the second initial value + * @param validator + * the validator + */ + public TwoInputDialog(Shell parentShell, String dialogTitle, String message1, String message2, String initialValue1, String initialValue2, IInputValidator validator) { + super(parentShell, dialogTitle, message1, initialValue1, validator); + this.message_2 = message2; + this.value_2 = initialValue2; + } + + /** + * Create the second Text Area + * + * @see org.eclipse.jface.dialogs.InputDialog#createDialogArea(org.eclipse.swt.widgets.Composite) + * + * @param parent + * @return + */ + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + if (message_2 != null) { + Label label = new Label(composite, SWT.WRAP); + label.setText(message_2); + GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER); + data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH); + label.setLayoutData(data); + label.setFont(parent.getFont()); + } + text_2 = new Text(composite, getInputTextStyle()); + text_2.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); + applyDialogFont(composite); + return composite; + } + + /** + * + * @see org.eclipse.jface.dialogs.InputDialog#buttonPressed(int) + * + * @param buttonId + */ + @Override + protected void buttonPressed(int buttonId) { + if (buttonId == IDialogConstants.OK_ID) { + this.value_2 = this.text_2.getText(); + } else { + this.value_2 = null; + } + super.buttonPressed(buttonId); + } + + /** + * + * @see org.eclipse.jface.dialogs.InputDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) + * + * @param parent + */ + @Override + protected void createButtonsForButtonBar(Composite parent) { + super.createButtonsForButtonBar(parent); + if (value_2 != null) { + text_2.setText(value_2); + } + } + + /** + * Getter for {@link #value_2} + * + * @return + * the description for the table + */ + public String getValue_2() { + return this.value_2; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/UnlimitedNaturalEditor.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/UnlimitedNaturalEditor.java new file mode 100644 index 00000000000..35aa1aa7b42 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/UnlimitedNaturalEditor.java @@ -0,0 +1,125 @@ +package org.eclipse.papyrus.infra.widgets.editors; + +import org.eclipse.core.databinding.conversion.IConverter; +import org.eclipse.core.databinding.conversion.StringToNumberConverter; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.validator.UnlimitedNaturalValidator; +import org.eclipse.swt.widgets.Composite; + +public class UnlimitedNaturalEditor extends StringEditor { + /** + * The IConverter for converting data from the widget to the model + */ + private IConverter targetToModelConverter; + + /** + * Constructs an editor for Integer values. The widget is a Text field. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The Text's style + */ + public UnlimitedNaturalEditor(Composite parent, int style) { + this(parent, style, null); + } + + /** + * Constructs an editor for Integer values. The widget is a Text field. + * + * @param parent + * The Composite in which this editor is created + * @param style + * The Text's style + * @param label + * The editor's label + */ + public UnlimitedNaturalEditor(Composite parent, int style, String label) { + super(parent, style, label); + + targetValidator = new UnlimitedNaturalValidator(); + + targetToModelConverter = new IConverter() { + + @Override + public Object getToType() { + return Integer.class; + } + + @Override + public Object getFromType() { + return String.class; + } + + @Override + public Integer convert(Object fromObject) { + if (fromObject instanceof String) { + String newString = ((String) fromObject).replaceAll(" ", ""); //$NON-NLS-1$ //$NON-NLS-2$ + if (newString.equals("*")) + { + return -1; + } + return (Integer) StringToNumberConverter.toInteger(false).convert(newString); + } + return 0; + } + }; + + IConverter integerToString = new IConverter() { + + @Override + public Object getToType() { + return String.class; + } + + @Override + public Object getFromType() { + return Integer.class; + } + + @Override + public Object convert(Object fromObject) { + if (fromObject instanceof Integer) { + if (((Integer) fromObject).intValue() == -1) { + return "*"; //$NON-NLS-1$ + } + return Integer.toString((Integer) fromObject); + } + return ""; //$NON-NLS-1$ + } + }; + setValidateOnDelay(true); + + setConverters(targetToModelConverter, integerToString); + setTargetAfterGetValidator(targetValidator); + + } + + + + /** + * {@inheritDoc} + */ + @Override + public Object getEditableType() { + return Integer.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Integer getValue() { + try { + + return (Integer) targetToModelConverter.convert(super.getValue()); + } catch (Exception ex) { + Activator.log.error(ex); + return null; + } + } + + + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/Messages.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/Messages.java new file mode 100644 index 00000000000..9cc4b1d79c0 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/Messages.java @@ -0,0 +1,141 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus (CEA) - bug 402525 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.messages; + +import org.eclipse.osgi.util.NLS; + +/** + * The Class Messages. + */ +public class Messages extends NLS { + + /** The Constant BUNDLE_NAME. */ + private static final String BUNDLE_NAME = "org.eclipse.papyrus.infra.widgets.messages.messages"; //$NON-NLS-1$ + + public static String BooleanInputValidator_NotABoolean; + + public static String IntegerInputValidator_NotAnIntegerMessage; + + public static String RealInputValidator_NotaRealMessage; + + public static String UnlimitedNaturalInputValidator_NotAnUnlimitedNaturalMessage; + + public static String MultipleStringFileEditor_0; + + public static String MultipleStringFileEditor_1; + + public static String MultipleStringFileEditor_2; + + public static String MultipleValueEditAndSelectionWidget_EditSelectedElement; + + /** The Multiple value editor_ add elements. */ + public static String MultipleValueEditor_AddElements; + + public static String MultipleValueEditor_addOperation; + + public static String MultipleValueEditor_editOperation; + + /** The Multiple value editor_ edit selected value */ + public static String MultipleValueEditor_EditSelectedValue; + + /** The Multiple value editor_ move selected elements down. */ + public static String MultipleValueEditor_MoveSelectedElementsDown; + + /** The Multiple value editor_ move selected elements up. */ + public static String MultipleValueEditor_MoveSelectedElementsUp; + + /** The Multiple value editor_ remove selected elements. */ + public static String MultipleValueEditor_RemoveSelectedElements; + + /** The Multiple value selector dialog_ add all elements. */ + public static String MultipleValueSelectorDialog_AddAllElements; + + /** The Multiple value selector dialog_ add selected elements. */ + public static String MultipleValueSelectorDialog_AddSelectedElements; + + /** The Multiple value selector dialog_ create new element */ + public static String MultipleValueSelectorDialog_CreateNewElement; + + /** The Multiple value selector dialog_ delete new element */ + public static String MultipleValueSelectorDialog_DeleteNewElement; + + /** The Multiple value selector dialog_ remove all elements. */ + public static String MultipleValueSelectorDialog_RemoveAllElements; + + public static String ReferenceDialog_0; + + public static String ReferenceDialog_1; + + public static String ReferenceDialog_CreateANewObject; + + public static String ReferenceDialog_editOperation; + + public static String ReferenceDialog_EditTheCurrentValue; + + /** The Reference dialog_ edit value */ + public static String ReferenceDialog_EditValue; + + /** The Reference dialog_ select value */ + public static String ReferenceDialog_SelectValue; + + public static String ReferenceDialog_setOperation; + + /** The Reference dialog_ unset */ + public static String ReferenceDialog_Unset; + + /** The Reference dialog_ edit unset value */ + public static String ReferenceDialog_UnsetValue; + + /** Indicates that a list of elements have different values for the given property (Multi-selection) */ + public static String ReferenceDialogObservable_Unchanged; + + /** The switch editors label for Multiplicity reference dialog. */ + public static String MultiplicityReferenceDialog_SwitchEditors; + + /** The lower value tool tip for Multiplicity reference dialog. */ + public static String MultiplicityReferenceDialog_LowerValueToolTip; + + /** The upper value tool tip for Multiplicity reference dialog. */ + public static String MultiplicityReferenceDialog_UpperValueToolTip; + + /** the Enum radio_ no value */ + public static String EnumRadio_NoValue; + + public static String FlattenableRestrictedFilteredContentProvider_AllPossibleContentsMessage; + + public static String FlattenableRestrictedFilteredContentProvider_FlatViewMessage; + + public static String IntegerMask_ErrorTooManyValues; + + public static String ProviderBasedBrowseStrategy_0; + + public static String StringEditionFactory_EnterANewValue; + + public static String StringFileSelector_0; + + public static String StringFileSelector_Browse; + + public static String StringFileSelector_BrowseWorkspace; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + /** + * Instantiates a new messages. + */ + private Messages() { + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/messages.properties b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/messages.properties new file mode 100644 index 00000000000..2aa21d64ea1 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/messages/messages.properties @@ -0,0 +1,57 @@ +############################################################################### +# Copyright (c) 2010, 2014 CEA LIST and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation +# Christian W. Damus (CEA) - bug 402525 +# +############################################################################### + +BooleanInputValidator_NotABoolean=The actual entry is not a Boolean. +IntegerInputValidator_NotAnIntegerMessage=The actual entry is not an Integer. +RealInputValidator_NotaRealMessage=The actual entry is not a Real. +UnlimitedNaturalInputValidator_NotAnUnlimitedNaturalMessage=The actual entry is not an UnlimitedNatural. An UnlimitedNatural must be either -1, * or >= 0 +MultipleStringFileEditor_0=Browse file system +MultipleStringFileEditor_1=Browse workspace +MultipleStringFileEditor_2=FilterExtensions and FilterNames do not match +MultipleValueEditAndSelectionWidget_EditSelectedElement=Edit selected Element +MultipleValueEditor_AddElements=Add elements +MultipleValueEditor_addOperation=Add {0} +MultipleValueEditor_editOperation=Edit {0} +MultipleValueEditor_EditSelectedValue=Edit the selected value +MultipleValueEditor_MoveSelectedElementsDown=Move selected elements down +MultipleValueEditor_MoveSelectedElementsUp=Move selected elements up +MultipleValueEditor_RemoveSelectedElements=Remove selected elements +MultipleValueSelectorDialog_AddAllElements=Add all elements +MultipleValueSelectorDialog_AddSelectedElements=Add selected elements +MultipleValueSelectorDialog_RemoveAllElements=Remove all elements +MultipleValueSelectorDialog_CreateNewElement=Create a new element +MultipleValueSelectorDialog_DeleteNewElement=Deletes a newly created element +ReferenceDialog_0=An error occured while setting the value. +ReferenceDialog_1=An error occured while setting the value. +ReferenceDialog_CreateANewObject=Create a new object +ReferenceDialog_editOperation=Edit {0} +ReferenceDialog_EditTheCurrentValue=Edit the current value +ReferenceDialog_EditValue=Edit the reference value +ReferenceDialog_SelectValue=Select the value for this reference +ReferenceDialog_setOperation=Set {0} +ReferenceDialog_Unset=<Undefined> +ReferenceDialog_UnsetValue=Unset the reference value +ReferenceDialogObservable_Unchanged=<Unchanged> +MultiplicityReferenceDialog_SwitchEditors=Switch editors +MultiplicityReferenceDialog_LowerValueToolTip=Lower ValueSpecification +MultiplicityReferenceDialog_UpperValueToolTip=Upper ValueSpecification +EnumRadio_NoValue=There is no value to select +FlattenableRestrictedFilteredContentProvider_AllPossibleContentsMessage=Show all possible values +FlattenableRestrictedFilteredContentProvider_FlatViewMessage=Flat View +StringEditionFactory_EnterANewValue=Enter the new value +StringFileSelector_0=FilterExtensions and FilterNames do not match +StringFileSelector_Browse=Browse +StringFileSelector_BrowseWorkspace=Browse workspace +IntegerMask_ErrorTooManyValues=The mask-based integer editor cannot be used with more than 32 values +ProviderBasedBrowseStrategy_0=The provider has not been initialized diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractFilteredContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractFilteredContentProvider.java new file mode 100644 index 00000000000..7b3ca25ce68 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractFilteredContentProvider.java @@ -0,0 +1,106 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.StringEditor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + + +/** + * A generic implementation for a IGraphicalContentProvider. + * This class doesn't provide any element, and should be extended. + * + * It implements a filter for List or Tree elements, based on the label + * provided by the viewer's label provider (Or Object#toString() if the viewer + * doesn't have a label provider). + * + * A Text widget is added before the display control to insert the filter + * pattern. An element is matched if at least one of these conditions is + * matched : + * - The element's name matches the pattern + * - One of the element's children matches the pattern + * - One of the element's parent matches the pattern + * + * The elements' hierarchy is obtained via the viewer's ContentProvider. + * + * @author Camille Letavernier + */ +// TODO : Encapsulate a IStructuredContentProvider and make this class concrete +public abstract class AbstractFilteredContentProvider implements IGraphicalContentProvider { + + protected StructuredViewer viewer; + + private StringEditor filterPattern; + + private PatternViewerFilter filter; + + public static final String BASE_PATTERN = "*"; //$NON-NLS-1$ + + protected boolean showIfHasVisibleParent = false; + + @Override + public void dispose() { + // Nothing + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + if (viewer instanceof StructuredViewer) { + this.viewer = (StructuredViewer) viewer; + updateFilter(); + } + } + + private void updateFilter() { + if (this.viewer != null && filterPattern != null) { + this.viewer.setFilters(new ViewerFilter[] { filter }); + } + } + + @Override + public void createBefore(Composite parent) { + filterPattern = new StringEditor(parent, SWT.NONE, "Filter : "); //$NON-NLS-1$ + filterPattern.setValidateOnDelay(true); + filterPattern.setValue(BASE_PATTERN); + filter = getViewerFilter(); + filterPattern.addCommitListener(new ICommitListener() { + + @Override + public void commit(AbstractEditor editor) { + filter.setPattern((String) filterPattern.getValue()); + viewer.refresh(); + } + + }); + updateFilter(); + } + + @Override + public void createAfter(Composite parent) { + // Nothing + } + + protected PatternViewerFilter getViewerFilter() { + PatternViewerFilter filter = new PatternViewerFilter(); + filter.setStrict(false); + filter.setPattern(BASE_PATTERN); + filter.setShowIfHasVisibleParent(showIfHasVisibleParent); + return filter; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractRestrictedContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractRestrictedContentProvider.java new file mode 100644 index 00000000000..975d647d439 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractRestrictedContentProvider.java @@ -0,0 +1,111 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * 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: + * Juan Cadavid (CEA LIST) juan.cadavid@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.Viewer; + +/** + * Abstract Implementation for {@link IRestrictedContentProvider} + * + * @author JC236769 + * + */ +public abstract class AbstractRestrictedContentProvider implements IRestrictedContentProvider { + + /** + * flag to indicate the useage of the restriction in the content provider + */ + private boolean isRestricted; + + /** + * if <code>false</code> the inherited features will be displayed + */ + private boolean ignoreInheritedFeatures; + + /** + * + * Constructor. + * + * @param isRestricted + */ + public AbstractRestrictedContentProvider(final boolean isRestricted) { + this.isRestricted = isRestricted; + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IRestrictedContentProvider#setRestriction(boolean) + * + * @param isRestricted + */ + @Override + public final void setRestriction(boolean isRestricted) { + this.isRestricted = isRestricted; + } + + /** + * + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + * + * @param viewer + * @param oldInput + * @param newInput + */ + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + } + + /** + * + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + * + */ + @Override + public void dispose() { + + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IInheritedElementContentProvider#setIgnoreInheritedElements(boolean) + * + * @param ignoreInheritedElements + */ + @Override + public void setIgnoreInheritedElements(boolean ignoreInheritedElements) { + this.ignoreInheritedFeatures = ignoreInheritedElements; + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IInheritedElementContentProvider#isIgnoringInheritedElements() + * + * @return + */ + @Override + public boolean isIgnoringInheritedElements() { + return this.ignoreInheritedFeatures; + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IRestrictedContentProvider#isRestricted() + * + * @return + */ + @Override + public boolean isRestricted() { + return this.isRestricted; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractStaticContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractStaticContentProvider.java new file mode 100644 index 00000000000..3f41f74abc8 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractStaticContentProvider.java @@ -0,0 +1,39 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.Viewer; + +/** + * An empty implementation of IStaticContentProvider + * + * @author Camille Letavernier + * + */ +public abstract class AbstractStaticContentProvider implements IStaticContentProvider { + + @Override + public void dispose() { + // Nothing + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // Nothing + } + + @Override + public Object[] getElements(Object inputElement) { + return getElements(); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractTreeFilter.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractTreeFilter.java new file mode 100644 index 00000000000..6d1a42c2492 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/AbstractTreeFilter.java @@ -0,0 +1,182 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.papyrus.infra.widgets.strategy.IStrategyBasedContentProvider; +import org.eclipse.papyrus.infra.widgets.strategy.ProviderBasedBrowseStrategy; +import org.eclipse.papyrus.infra.widgets.strategy.TreeBrowseStrategy; + +/** + * An abstract ViewerFilter for TreeViewers. + * + * You should extend this class whenever you want to implement a filter + * for a Tree. An element is visible : + * - If the method isVisible() returns true + * - If one of its children is visible + * - Optionally, if one of its parents is visible ({@link #showIfHasVisibleParent}) + * + * This class can implements a cache, which should be cleaned each time + * a parameter influencing the result of the {@link #isVisible(Viewer, Object, Object)} method is changed ({@link #clearCache()}). + * + * @author Camille Letavernier + */ +public abstract class AbstractTreeFilter extends ViewerFilter { + + /** + * If set to true, the results of the filter will be cached, to improve + * performance. + * + * Implementers are responsible of cleaning the cache (by calling {@link #clearCache()} when the result of the filter on a given + * element might change. + * + * For example, a string-pattern-based filter should clear the cache when + * the pattern changes. The viewer should also be refreshed. + */ + protected boolean useCache = true; + + /** + * Indicates if an element should be visible when one its parents is visible. + * This may be useful, for example, when you want to display all the contents + * of a given package, by entering a filter that will match this package. + */ + protected boolean showIfHasVisibleParent = false; + + /** + * Cache + */ + protected final Map<Object, Boolean> visibleElement = new HashMap<Object, Boolean>(); + + /** + * Cache + */ + protected final Map<Object, Boolean> visibleParent = new HashMap<Object, Boolean>(); + + /** + * Cache + */ + protected final Map<Object, Boolean> visibleChild = new HashMap<Object, Boolean>(); + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + + TreeBrowseStrategy strategy = null; + + if (viewer instanceof StructuredViewer) { + IContentProvider baseContentProvider = ((StructuredViewer) viewer).getContentProvider(); + if (baseContentProvider instanceof IStrategyBasedContentProvider) { + strategy = ((IStrategyBasedContentProvider) baseContentProvider).getRevealStrategy(); + } + + if (strategy == null && baseContentProvider instanceof ITreeContentProvider) { + strategy = new ProviderBasedBrowseStrategy((ITreeContentProvider) baseContentProvider); + } + } + + if (strategy == null) { // The contentProvider is not a TreeContentProvider + return isVisible(viewer, parentElement, element); + } + + return select(viewer, parentElement, element, strategy); + } + + protected boolean select(Viewer viewer, Object parentElement, Object element, TreeBrowseStrategy strategy) { + Set<Object> visitedChildren = new HashSet<Object>(); + Set<Object> visitedParents = new HashSet<Object>(); + if (useCache && visibleElement.containsKey(element)) { + return visibleElement.get(element); + } + + boolean isVisible = isVisible(viewer, parentElement, element) || hasOneVisibleChild(viewer, element, strategy, visitedChildren); + + if (showIfHasVisibleParent) { + isVisible = isVisible || hasOneVisibleParent(viewer, element, strategy, visitedParents); + } + + if (useCache) { + visibleElement.put(element, isVisible); + } + + return isVisible; + } + + protected boolean hasOneVisibleChild(Viewer viewer, Object element, TreeBrowseStrategy strategy, Set<Object> visitedElements) { + // TODO : separate this method in -hasOneVisibleChild() and #doHasOneVisibleChild(), to handle the cache management in a private method, + // while letting the opportunity to override the method + if (useCache && visibleChild.containsKey(element)) { + return visibleChild.get(element); + } + + boolean result = false; + if (!visitedElements.contains(element)) { + visitedElements.add(element); + + for (Object childElement : strategy.getChildren(element)) { + if (isVisible(viewer, element, childElement) || hasOneVisibleChild(viewer, childElement, strategy, visitedElements)) { + result = true; + break; + } + } + } + + if (useCache) { + visibleChild.put(element, result); + } + return result; + } + + protected boolean hasOneVisibleParent(Viewer viewer, Object element, TreeBrowseStrategy strategy, Set<Object> visitedElements) { + if (useCache && visibleParent.containsKey(element)) { + return visibleParent.get(element); + } + + boolean result = false; + if (!visitedElements.contains(element)) { + + visitedElements.add(element); + + Object parentElement = strategy.getParent(element); + if (parentElement == element || parentElement == null) { + result = isVisible(viewer, parentElement, element); + } else { + result = isVisible(viewer, null, parentElement) || hasOneVisibleParent(viewer, parentElement, strategy, visitedElements); + } + } + + if (useCache) { + visibleParent.put(element, result); + } + + return result; + } + + protected void clearCache() { + visibleElement.clear(); + visibleParent.clear(); + visibleChild.clear(); + } + + public abstract boolean isVisible(Viewer viewer, Object parentElement, Object element); + + public void setShowIfHasVisibleParent(boolean showIfHasVisibleParent) { + this.showIfHasVisibleParent = showIfHasVisibleParent; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/CollectionContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/CollectionContentProvider.java new file mode 100644 index 00000000000..44f3743b265 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/CollectionContentProvider.java @@ -0,0 +1,86 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.Collection; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** + * A Content Provider converting the input list to an array containing the same elements + * + * @author Camille Letavernier + * + */ +public class CollectionContentProvider implements ITreeContentProvider { + + private CollectionContentProvider() { + + } + + /** + * {@inheritDoc} + */ + @Override + public void dispose() { + // Nothing + } + + /** + * {@inheritDoc} + */ + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // Nothing + } + + /** + * Converts the input List to an Array containing the same elements + * + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + * + * @param inputElement + * @return + * The Array containing the input elements + */ + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof Collection) { + return ((Collection<?>) inputElement).toArray(); + } else if (inputElement instanceof Object[]) { + return (Object[]) inputElement; + } + + return new Object[] {}; + } + + /** + * The Singleton instance + */ + public static final CollectionContentProvider instance = new CollectionContentProvider(); + + @Override + public Object[] getChildren(Object parentElement) { + return new Object[0]; // Flat tree + } + + @Override + public Object getParent(Object element) { + return null; // Flat tree + } + + @Override + public boolean hasChildren(Object element) { + return false; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/ComboLabelProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/ComboLabelProvider.java new file mode 100644 index 00000000000..67b65053a55 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/ComboLabelProvider.java @@ -0,0 +1,43 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; + + +public class ComboLabelProvider extends LabelProvider { + + private ILabelProvider labelProvider; + + public ComboLabelProvider(IBaseLabelProvider encapsulated) { + this.labelProvider = (ILabelProvider) encapsulated; + } + + @Override + public String getText(Object value) { + if (value == UnsetObject.instance || value == UnchangedObject.instance) { + return value.toString(); + } + return labelProvider.getText(value); + } + + @Override + public Image getImage(Object value) { + if (value == UnsetObject.instance || value == UnchangedObject.instance) { + return null; + } + return labelProvider.getImage(value); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/CompositeContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/CompositeContentProvider.java new file mode 100644 index 00000000000..91bd6ae32ce --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/CompositeContentProvider.java @@ -0,0 +1,103 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + + +public class CompositeContentProvider implements ICompositeContentProvider { + + private final List<ITreeContentProvider> contentProviders; + + public CompositeContentProvider() { + contentProviders = new LinkedList<ITreeContentProvider>(); + } + + @Override + public Object[] getElements(Object inputElement) { + List<Object> result = new LinkedList<Object>(); + for (ITreeContentProvider provider : contentProviders) { + result.addAll(Arrays.asList(provider.getElements(inputElement))); + } + return result.toArray(); + } + + @Override + public Object[] getChildren(Object parentElement) { + List<Object> result = new LinkedList<Object>(); + for (ITreeContentProvider provider : contentProviders) { + result.addAll(Arrays.asList(provider.getChildren(parentElement))); + } + return result.toArray(); + } + + @Override + public Object getParent(Object element) { + for (ITreeContentProvider provider : contentProviders) { + Object parent = provider.getParent(element); + if (parent != null) { + return parent; + } + } + return null; + } + + @Override + public boolean hasChildren(Object element) { + return getChildren(element).length > 0; + } + + @Override + public void dispose() { + for (ITreeContentProvider provider : contentProviders) { + provider.dispose(); + } + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + for (ITreeContentProvider provider : contentProviders) { + provider.inputChanged(viewer, oldInput, newInput); + } + } + + @Override + public boolean isValidValue(Object element) { + for (ITreeContentProvider provider : contentProviders) { + if (provider instanceof IHierarchicContentProvider) { + if (((IHierarchicContentProvider) provider).isValidValue(element)) { + return true; + } + } else { + return true; // For non-hierarchic content providers, isValidValue is always true + } + } + + return false; + } + + @Override + public void appendContentProvider(ITreeContentProvider treeContentProvider) { + contentProviders.add(treeContentProvider); + } + + public List<ITreeContentProvider> getContentProviders() { + return contentProviders; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/CompoundFilteredRestrictedContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/CompoundFilteredRestrictedContentProvider.java new file mode 100644 index 00000000000..9a72314334f --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/CompoundFilteredRestrictedContentProvider.java @@ -0,0 +1,149 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * 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: + * Juan Cadavid (CEA LIST) juan.cadavid@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +/** + * This class allows to use several content provider for the same widget + * + restriction behavior see {@link IRestrictedContentProvider} documentation + * + * @author JC236769 + * + */ +public class CompoundFilteredRestrictedContentProvider extends AbstractFilteredContentProvider implements IRestrictedContentProvider { + + private List<IRestrictedContentProvider> encapsulatedContentProviders = new ArrayList<IRestrictedContentProvider>(); + + public boolean add(IRestrictedContentProvider o) { + if (o != null) { + return encapsulatedContentProviders.add(o); + } + return false; + } + + + @Override + public Object[] getElements(Object inputElement) { + Collection<Object> asList = new HashSet<Object>(); + + for (IRestrictedContentProvider encapsulatedContentProvider : encapsulatedContentProviders) { + Object[] directElements = encapsulatedContentProvider.getElements(inputElement); + asList.addAll(Arrays.asList(directElements)); + } + return asList.toArray(); + } + + + @Override + public Object[] getChildren(Object parentElement) { + Collection<Object> asList = new HashSet<Object>(); + + for (IRestrictedContentProvider encapsulatedContentProvider : encapsulatedContentProviders) { + Object[] directElements = encapsulatedContentProvider.getChildren(parentElement); + if (directElements != null && directElements.length != 0) { + asList.addAll(Arrays.asList(directElements)); + } + } + return asList.toArray(); + } + + + @Override + public Object getParent(Object element) { + for (IRestrictedContentProvider encapsulatedContentProvider : encapsulatedContentProviders) { + Object parent = encapsulatedContentProvider.getParent(element); + if (parent != null) { + return parent; + } + } + return null; + } + + @Override + public boolean hasChildren(Object element) { + return true; + } + + + + @Override + public void dispose() { + super.dispose(); + this.encapsulatedContentProviders.clear(); + } + + @Override + public void setRestriction(boolean isRestricted) { + for (IRestrictedContentProvider current : encapsulatedContentProviders) { + current.setRestriction(isRestricted); + } + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IRestrictedContentProvider#isRestricted() + * + * @return + */ + @Override + public boolean isRestricted() { + if (!encapsulatedContentProviders.isEmpty()) { + return encapsulatedContentProviders.get(0).isRestricted(); + } + throw new UnsupportedOperationException(); + } + + @Override + public boolean isValidValue(Object element) { + boolean result = false; + for (final IRestrictedContentProvider current : encapsulatedContentProviders) { + result = result || current.isValidValue(element); + } + return result; + } + + @Override + public Object[] getElements() { + return getElements(null); + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IInheritedElementContentProvider#setIgnoreInheritedElements(boolean) + * + * @param ignoreInheritedElements + */ + @Override + public void setIgnoreInheritedElements(boolean ignoreInheritedElements) { + for (final IRestrictedContentProvider current : encapsulatedContentProviders) { + current.setIgnoreInheritedElements(ignoreInheritedElements); + } + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IInheritedElementContentProvider#isIgnoringInheritedElements() + * + * @return + */ + @Override + public boolean isIgnoringInheritedElements() { + return encapsulatedContentProviders.get(0).isIgnoringInheritedElements();// the value is the same for all encapsulated content provider + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/DelegatingLabelProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/DelegatingLabelProvider.java new file mode 100644 index 00000000000..cdfdef64464 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/DelegatingLabelProvider.java @@ -0,0 +1,125 @@ +/***************************************************************************** + * Copyright (c) 2013, 2014 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * Christian W. Damus - bug 399859 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.LabelProviderChangedEvent; +import org.eclipse.swt.graphics.Image; + +/** + * A label provider that delegates to some other label provider with the + * possibility of overriding certain labels. + */ +public class DelegatingLabelProvider + extends LabelProvider { + + private final ILabelProvider delegate; + private ILabelProviderListener forwardingListener; + + public DelegatingLabelProvider(ILabelProvider delegate) { + super(); + + this.delegate = delegate; + + delegate.addListener(getForwardingListener()); + } + + @Override + public Image getImage(Object element) { + Image result = customGetImage(element); + if (result == null) { + result = delegatedGetImage(element); + } + return result; + } + + /** + * Overridden in subclasses to provide custom images for certain {@code element}s. + * + * @param element + * an element + * @return the custom image, or {@code null} to delegate + */ + protected Image customGetImage(Object element) { + return null; + } + + protected Image delegatedGetImage(Object element) { + return delegate.getImage(element); + } + + @Override + public String getText(Object element) { + String result = customGetText(element); + if (result == null) { + result = delegatedGetText(element); + } + return result; + } + + /** + * Overridden in subclasses to provide custom text for certain {@code element}s. + * + * @param element + * an element + * @return the custom text, or {@code null} to delegate + */ + protected String customGetText(Object element) { + return null; + } + + protected String delegatedGetText(Object element) { + return delegate.getText(element); + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return delegate.isLabelProperty(element, property); + } + + @Override + public void addListener(ILabelProviderListener listener) { + delegate.addListener(listener); + } + + @Override + public void removeListener(ILabelProviderListener listener) { + delegate.removeListener(listener); + } + + /** + * Disposes my delegate. + */ + @Override + public void dispose() { + delegate.removeListener(getForwardingListener()); + delegate.dispose(); + } + + private ILabelProviderListener getForwardingListener() { + if (forwardingListener == null) { + forwardingListener = new ILabelProviderListener() { + + @Override + public void labelProviderChanged(LabelProviderChangedEvent event) { + fireLabelProviderChanged(new LabelProviderChangedEvent(DelegatingLabelProvider.this, event.getElements())); + } + }; + } + + return forwardingListener; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/DelegatingStyledLabelProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/DelegatingStyledLabelProvider.java new file mode 100644 index 00000000000..b08a0ac5b89 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/DelegatingStyledLabelProvider.java @@ -0,0 +1,61 @@ +/***************************************************************************** + * Copyright (c) 2014 Christian W. Damus and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.StyledString; + +/** + * A styled label provider that delegates to another styled label provider with the option to override certain labels. + */ +public class DelegatingStyledLabelProvider extends DelegatingLabelProvider implements IStyledLabelProvider { + + private final IStyledLabelProvider delegate; + + public DelegatingStyledLabelProvider(ILabelProvider delegate) { + super(delegate); + + if (!(delegate instanceof IStyledLabelProvider)) { + throw new IllegalArgumentException("delegate is not a styled label provider"); //$NON-NLS-1$ + } + + this.delegate = (IStyledLabelProvider) delegate; + } + + @Override + public StyledString getStyledText(Object element) { + StyledString result = customGetStyledText(element); + if (result == null) { + result = delegatedGetStyledText(element); + } + return result; + } + + /** + * Override in subclasses to return custom styled text to override the delegate. + * The default implementation simply returns {@code null}. + * + * @param element + * an element for which to provide styled text + * @return the custom styled text, or {@code null} to delegate + */ + protected StyledString customGetStyledText(Object element) { + return null; + } + + protected final StyledString delegatedGetStyledText(Object element) { + return delegate.getStyledText(element); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EmptyContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EmptyContentProvider.java new file mode 100644 index 00000000000..c0e8ec807f6 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EmptyContentProvider.java @@ -0,0 +1,45 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + + +/** + * A ContentProvider returning empty collections + * + * @author Camille Letavernier + * + */ +public class EmptyContentProvider extends AbstractStaticContentProvider { + + /** + * Singleton instance + */ + public static final EmptyContentProvider instance = new EmptyContentProvider(); + + private final Object[] value = new Object[0]; + + private EmptyContentProvider() { + + } + + /** + * @see org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider#getElements() + * + * @return + * an empty array + */ + @Override + public Object[] getElements() { + return value; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EncapsulatedContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EncapsulatedContentProvider.java new file mode 100644 index 00000000000..db678c08437 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/EncapsulatedContentProvider.java @@ -0,0 +1,305 @@ +/***************************************************************************** + * Copyright (c) 2010, 2014 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 455075 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.papyrus.infra.tools.util.ListHelper; +import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.strategy.IStrategyBasedContentProvider; +import org.eclipse.papyrus.infra.widgets.strategy.TreeBrowseStrategy; +import org.eclipse.papyrus.infra.widgets.util.IRevealSemanticElement; +import org.eclipse.swt.widgets.Composite; + +/** + * A ContentProvider encapsulate another ContentProvider. + * This class implements all Papyrus interfaces extending IContentProvider, + * and is thus compatible with all papyrus tools, even if the encapsulated + * provider is not. + * + * Moreover, the Encapsulated provider can handle temporary elements. + * + * @author Camille Letavernier + * + */ +// TODO : Move the temporary elements feature to another class. +// This feature is only used by multi-reference dialogs +public class EncapsulatedContentProvider implements IHierarchicContentProvider, IGraphicalContentProvider, ICommitListener, IAdaptableContentProvider, IRevealSemanticElement, IStrategyBasedContentProvider, IStaticContentProvider { + + /** + * The encapsulated static content provider + */ + protected IStructuredContentProvider encapsulated; + + /** + * The set of temporaryElements, which are added from outside this ContentProvider + */ + private Set<Object> temporaryElements = new LinkedHashSet<Object>(); + + /** + * + * Constructor. + * + * @param encapsulated + * The encapsulated content provider, to which all calls will be forwarded + */ + public EncapsulatedContentProvider(IStructuredContentProvider encapsulated) { + this.encapsulated = encapsulated; + } + + /** + * + * Constructor. + * + */ + protected EncapsulatedContentProvider() { + } + + /** + * Returns all elements known by this ContentProvider. This is the union of + * the objects returned by the wrapped StaticContentProvider and the temporary + * elements, which are not known by the wrapped provider. + * + * @param elements + * The Object[] returned by the encapsulated provider + * @return + * All elements known by this ContentProvider + */ + private Object[] getAllElements(Object[] elements) { + if (temporaryElements.isEmpty()) { + return elements; + } + + List<Object> result = ListHelper.asList(elements); + result.addAll(temporaryElements); + return result.toArray(); + } + + /** + * {@inheritDoc} + */ + @Override + public void dispose() { + // encapsulated.dispose(); + // encapsulated = null; + } + + /** + * Updates me to encapsulate a new {@code delegate}. If it makes sense for a particular instance, this may + * collapse any chain of providers that are exactly of {@link EncapsulatedContentProvider} type (not some + * subclass that may have different behaviour). If it is necessary to delegate to another encapsulated + * instance as is, then simply assign the protected {@link #encapsulated} field. + * + * @param delegate + * my new delegate, or {@code null} to simply forget the previous delegate + */ + protected void encapsulate(IStructuredContentProvider delegate) { + while ((delegate != null) && (delegate.getClass() == EncapsulatedContentProvider.class)) { + delegate = ((EncapsulatedContentProvider) delegate).encapsulated; + } + + this.encapsulated = delegate; + } + + protected void addViewerFilter(StructuredViewer viewer, ViewerFilter filter) { + Set<ViewerFilter> currentFilters = new LinkedHashSet<ViewerFilter>(Arrays.asList(viewer.getFilters())); + currentFilters.add(filter); + viewer.setFilters(currentFilters.toArray(new ViewerFilter[currentFilters.size()])); + } + + /** + * {@inheritDoc} + */ + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + if (encapsulated != null) { + encapsulated.inputChanged(viewer, oldInput, newInput); + } + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getElements(Object inputElement) { + if (encapsulated == null) { + return new Object[0]; + } + return getAllElements(encapsulated.getElements(inputElement)); + } + + /** + * Gets the elements for this content provider + * + * @return + * all elements from the wrapped ContentProvider + */ + @Override + public Object[] getElements() { + if (encapsulated instanceof IStaticContentProvider) { + return getAllElements(((IStaticContentProvider) encapsulated).getElements()); + } + return getElements(null); + } + + /** + * Adds a Temporary element to this ContentProvider + * + * @param newObject + * The temporary element to be added + */ + public void addTemporaryElement(Object newObject) { + temporaryElements.add(newObject); + } + + /** + * Removes a Temporary element from this ContentProvider + * + * @param removeObject + * The temporary element to remove + */ + public void removeTemporaryElement(Object removeObject) { + temporaryElements.remove(removeObject); + } + + /** + * Clears all temporary elements from this content provider + */ + public void clearTemporaryElements() { + temporaryElements.clear(); + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getChildren(Object parentElement) { + if (encapsulated instanceof ITreeContentProvider) { + return ((ITreeContentProvider) encapsulated).getChildren(parentElement); + } else { + return new Object[0]; + } + } + + /** + * {@inheritDoc} + */ + @Override + public Object getParent(Object element) { + if (encapsulated instanceof ITreeContentProvider) { + return ((ITreeContentProvider) encapsulated).getParent(element); + } else { + return null; + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasChildren(Object element) { + if (encapsulated instanceof ITreeContentProvider) { + return ((ITreeContentProvider) encapsulated).hasChildren(element); + } else { + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isValidValue(Object element) { + if (encapsulated instanceof IHierarchicContentProvider) { + return ((IHierarchicContentProvider) encapsulated).isValidValue(element); + } else { + return true; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void createBefore(Composite parent) { + if (encapsulated instanceof IGraphicalContentProvider) { + ((IGraphicalContentProvider) encapsulated).createBefore(parent); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void createAfter(Composite parent) { + if (encapsulated instanceof IGraphicalContentProvider) { + ((IGraphicalContentProvider) encapsulated).createAfter(parent); + } + } + + @Override + public void commit(AbstractEditor editor) { + if (encapsulated instanceof ICommitListener) { + ((ICommitListener) encapsulated).commit(editor); + } + } + + @Override + public Object getAdaptedValue(Object selection) { + if (encapsulated instanceof IAdaptableContentProvider) { + return ((IAdaptableContentProvider) encapsulated).getAdaptedValue(selection); + } + return selection; + } + + @Override + public void revealSemanticElement(List<?> elementList) { + if (encapsulated instanceof IRevealSemanticElement) { + ((IRevealSemanticElement) encapsulated).revealSemanticElement(elementList); + } else if (encapsulated instanceof CompositeContentProvider) { + if (((CompositeContentProvider) encapsulated).getContentProviders() != null) { + for (ITreeContentProvider contentProvider : ((CompositeContentProvider) encapsulated).getContentProviders()) { + if (contentProvider instanceof IRevealSemanticElement) { + ((IRevealSemanticElement) contentProvider).revealSemanticElement(elementList); + } + } + } + } + } + + @Override + public TreeBrowseStrategy getBrowseStrategy() { + if (encapsulated instanceof IStrategyBasedContentProvider) { + return ((IStrategyBasedContentProvider) encapsulated).getBrowseStrategy(); + } + return null; + } + + @Override + public TreeBrowseStrategy getRevealStrategy() { + if (encapsulated instanceof IStrategyBasedContentProvider) { + return ((IStrategyBasedContentProvider) encapsulated).getRevealStrategy(); + } + return null; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/FileExtensions.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/FileExtensions.java new file mode 100644 index 00000000000..230efa8981d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/FileExtensions.java @@ -0,0 +1,48 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Standard file extensions used in Papyrus + * + * @author Camille Letavernier + * + */ +public class FileExtensions { + + public static final Map<String, String> umlExtensions = new LinkedHashMap<String, String>(); + + public static final Map<String, String> umlProfileExtensions = new LinkedHashMap<String, String>(); + + public static final Map<String, String> cssStylesheetsExtension = new LinkedHashMap<String, String>(); + + public static final Map<String, String> allFilesExtensions = new LinkedHashMap<String, String>(); + + static { + umlExtensions.put("*.uml", "UML (*.uml)"); //$NON-NLS-1$ //$NON-NLS-2$ + umlExtensions.put("*.profile.uml", "UML Profiles (*.profile.uml)"); //$NON-NLS-1$ //$NON-NLS-2$ + + umlProfileExtensions.put("*.profile.uml", "UML Profiles (*.profile.uml)"); //$NON-NLS-1$ //$NON-NLS-2$ + umlProfileExtensions.put("*.uml", "UML (*.uml)"); //$NON-NLS-1$ //$NON-NLS-2$ + + cssStylesheetsExtension.put("*.css", "CSS Stylesheets (*.css)"); //$NON-NLS-1$ //$NON-NLS-2$ + + allFilesExtensions.put("*", "All (*)"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/FilteredContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/FilteredContentProvider.java new file mode 100644 index 00000000000..a400c8bbf91 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/FilteredContentProvider.java @@ -0,0 +1,107 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.StringEditor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + + +/** + * A generic implementation for a IGraphicalContentProvider. + * This class doesn't provide any element, and should be extended. + * + * It implements a filter for List or Tree elements, based on the label + * provided by the viewer's label provider (Or Object#toString() if the viewer + * doesn't have a label provider). + * + * A Text widget is added before the display control to insert the filter + * pattern. An element is matched if at least one of these conditions is + * matched : + * - The element's name matches the pattern + * - One of the element's children matches the pattern + * - One of the element's parent matches the pattern + * + * The elements' hierarchy is obtained via the viewer's ContentProvider. + * + * @author Camille Letavernier + */ +public class FilteredContentProvider extends EncapsulatedContentProvider { + + protected StructuredViewer viewer; + + private StringEditor filterPattern; + + private PatternViewerFilter filter; + + public static final String BASE_PATTERN = "*"; //$NON-NLS-1$ + + protected boolean showIfHasVisibleParent = false; + + public FilteredContentProvider(IStructuredContentProvider encapsulated) { + super(encapsulated); + } + + public FilteredContentProvider() { + super(); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + super.inputChanged(viewer, oldInput, newInput); + if (viewer instanceof StructuredViewer) { + this.viewer = (StructuredViewer) viewer; + updateFilter(); + } + } + + private void updateFilter() { + if (this.viewer != null && filterPattern != null) { + addViewerFilter(viewer, filter); + } + } + + @Override + public void createBefore(Composite parent) { + super.createBefore(parent); + filterPattern = new StringEditor(parent, SWT.NONE, "Filter: "); + filterPattern.setValidateOnDelay(true); + filterPattern.setValue(BASE_PATTERN); + filter = getViewerFilter(); + filterPattern.addCommitListener(new ICommitListener() { + + @Override + public void commit(AbstractEditor editor) { + filter.setPattern((String) filterPattern.getValue()); + if (viewer != null) { + viewer.refresh(); + } + } + + }); + updateFilter(); + } + + protected PatternViewerFilter getViewerFilter() { + PatternViewerFilter filter = new PatternViewerFilter(); + filter.setStrict(false); + filter.setPattern(BASE_PATTERN); + filter.setShowIfHasVisibleParent(showIfHasVisibleParent); + return filter; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/FlattenableRestrictedFilteredContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/FlattenableRestrictedFilteredContentProvider.java new file mode 100644 index 00000000000..cc79b0ba368 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/FlattenableRestrictedFilteredContentProvider.java @@ -0,0 +1,203 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * 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: + * Juan Cadavid (CEA LIST) juan.cadavid@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.selectors.ReferenceSelector; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +/** + * + * @author JC236769 + * + */ +public class FlattenableRestrictedFilteredContentProvider extends AbstractFilteredContentProvider implements IStaticContentProvider, IRestrictedContentProvider, IFlattenableContentProvider { + + private boolean isFlat = false; + + private ReferenceSelector selector; + + protected IRestrictedContentProvider provider; + + protected HierarchicToFlatContentProvider flatProvider; + + /** + * + * Constructor. + * + * @param provider + * the encapsulated content provider + * @param selector + * the reference selector (we need it to refresh it) + */ + public FlattenableRestrictedFilteredContentProvider(IRestrictedContentProvider provider, ReferenceSelector selector) { + this.provider = provider; + flatProvider = new HierarchicToFlatContentProvider(provider); + this.selector = selector; + } + + /** + * Add 2 checkboxes to the dialog + * + * @see org.eclipse.papyrus.infra.widgets.providers.AbstractFilteredContentProvider#createAfter(org.eclipse.swt.widgets.Composite) + * + * @param parent + */ + @Override + public void createAfter(final Composite parent) { + + super.createAfter(parent); + Composite checkboxSection = new Composite(parent, SWT.NONE); + checkboxSection.setLayout(new FillLayout(SWT.VERTICAL)); + final Button onlyCurrentContainersCheckbox = new Button(checkboxSection, SWT.CHECK); + onlyCurrentContainersCheckbox.setText(Messages.FlattenableRestrictedFilteredContentProvider_AllPossibleContentsMessage); + + final Button showFlatListOfFeaturesCheckbox = new Button(checkboxSection, SWT.CHECK); + showFlatListOfFeaturesCheckbox.setText(Messages.FlattenableRestrictedFilteredContentProvider_FlatViewMessage); + onlyCurrentContainersCheckbox.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + setRestriction(!onlyCurrentContainersCheckbox.getSelection()); + viewer.refresh(); + selector.refresh(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + + } + }); + showFlatListOfFeaturesCheckbox.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + + setFlat(showFlatListOfFeaturesCheckbox.getSelection()); + viewer.refresh(); + selector.refresh(); + + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + + } + }); + } + + @Override + public Object[] getElements(Object inputElement) { + if (isFlat) { + return flatProvider.getElements(inputElement); + } + return provider.getElements(inputElement); + } + + @Override + public void dispose() { + flatProvider.dispose(); + provider.dispose(); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + super.inputChanged(viewer, oldInput, newInput); + flatProvider.inputChanged(viewer, oldInput, newInput); + provider.inputChanged(viewer, oldInput, newInput); + } + + @Override + public boolean isValidValue(Object element) { + return provider.isValidValue(element); + } + + @Override + public Object[] getChildren(Object parentElement) { + if (isFlat) { + return new Object[0]; + } + return provider.getChildren(parentElement); + } + + @Override + public Object getParent(Object element) { + if (isFlat) { + return null; + } + return provider.getParent(element); + } + + @Override + public boolean hasChildren(Object element) { + if (isFlat) { + return false; + } + return provider.hasChildren(element); + } + + @Override + public void setRestriction(boolean isRestricted) { + provider.setRestriction(isRestricted); + } + + @Override + public void setFlat(boolean flat) { + this.isFlat = flat; + + } + + @Override + public Object[] getElements() { + return null; + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IInheritedElementContentProvider#setIgnoreInheritedElements(boolean) + * + * @param ignoreInheritedElements + */ + @Override + public void setIgnoreInheritedElements(boolean ignoreInheritedElements) { + provider.setIgnoreInheritedElements(ignoreInheritedElements); + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IInheritedElementContentProvider#isIgnoringInheritedElements() + * + * @return + */ + @Override + public boolean isIgnoringInheritedElements() { + return provider.isIgnoringInheritedElements(); + } + + /** + * + * @see org.eclipse.papyrus.infra.widgets.providers.IRestrictedContentProvider#isRestricted() + * + * @return + */ + @Override + public boolean isRestricted() { + return provider.isRestricted(); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/HierarchicToFlatContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/HierarchicToFlatContentProvider.java new file mode 100644 index 00000000000..75b7a51b148 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/HierarchicToFlatContentProvider.java @@ -0,0 +1,87 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.jface.viewers.Viewer; + +//FIXME : Adapt this code to TreeBrowseStrategy +public class HierarchicToFlatContentProvider extends TreeToFlatContentProvider { + + protected IHierarchicContentProvider contentProvider; + + public HierarchicToFlatContentProvider(IHierarchicContentProvider provider) { + super(provider); + if (!(provider instanceof IStaticContentProvider)) { + throw new IllegalArgumentException(); + } + contentProvider = provider; + } + + @Override + public void dispose() { + contentProvider.dispose(); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + super.inputChanged(viewer, oldInput, newInput); + contentProvider.inputChanged(viewer, oldInput, newInput); + } + + @Override + protected Collection<Object> getElementsList() { + Collection<Object> result = new LinkedHashSet<Object>(); + Set<Object> browsedElements = new HashSet<Object>(); + + for (Object root : ((IStaticContentProvider) contentProvider).getElements()) { + if (exploreBranch(null, root)) { + if (contentProvider.isValidValue(root)) { + result.add(getValue(root)); + } + getElementsList(root, result, browsedElements); + } + } + + return result; + } + + @Override + protected void getElementsList(Object parent, Collection<Object> result, Set<Object> browsedElements) { + if (!browsedElements.add(parent)) { + return; + } + + Object[] children = contentProvider.getChildren(parent); + if (children == null) { + return; + } + + for (Object child : children) { + Object childValue = getValue(child); + if (result.contains(childValue)) { + continue; // Avoid infinite recursion + } + if (exploreBranch(parent, child)) { + if (contentProvider.isValidValue(child)) { + result.add(childValue); + } + getElementsList(child, result, browsedElements); + } + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IAdaptableContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IAdaptableContentProvider.java new file mode 100644 index 00000000000..a277766a9a9 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IAdaptableContentProvider.java @@ -0,0 +1,42 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.IStructuredContentProvider; + +/** + * A content provider that can be adapted from container value + * to semantic value. Useful when you want to display wrapped + * values, but still keep an access to the actual semantic values + * + * @author Camille Letavernier + */ +public interface IAdaptableContentProvider extends IStructuredContentProvider { + + /** + * Returns the semantic Object contained in the given selection + * + * @param containerElement + * @return + * The semantic element contained in the given containerElement + */ + public Object getAdaptedValue(Object containerElement); + + /** + * Return an object wrapping the given semanticElement + * + * @param semanticElement + * @return + * The container object wrapping the semantic element + */ + // public Object getContainerValue(Object semanticElement); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/ICompositeContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/ICompositeContentProvider.java new file mode 100644 index 00000000000..0804e6efaa9 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/ICompositeContentProvider.java @@ -0,0 +1,22 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.ITreeContentProvider; + + +public interface ICompositeContentProvider extends IHierarchicContentProvider { + + public void appendContentProvider(ITreeContentProvider treeContentProvider); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IFlattenableContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IFlattenableContentProvider.java new file mode 100644 index 00000000000..cd274e712f2 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IFlattenableContentProvider.java @@ -0,0 +1,27 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * 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: + * Juan Cadavid (CEA LIST) juan.cadavid@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +/** + * + * Interfaces for a content provider which can be flat or not + * + */ +public interface IFlattenableContentProvider { + + /** + * + * @param isFlat + * <code>true</code> if we display the possible value as a flat view + */ + public void setFlat(boolean isFlat); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IGraphicalContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IGraphicalContentProvider.java new file mode 100644 index 00000000000..8015b5db800 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IGraphicalContentProvider.java @@ -0,0 +1,41 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.swt.widgets.Composite; + +/** + * An interface for implementing a ContentProvider which requires + * graphical elements for features such as filters. + * + * @author Camille Letavernier + * + */ +public interface IGraphicalContentProvider extends IContentProvider { + + /** + * Create graphical elements, which will appear before the widget + * used to display the provided elements + * + * @param parent + */ + public abstract void createBefore(Composite parent); + + /** + * Create graphical elements, which will appear after the widget + * used to display the provided elements + * + * @param parent + */ + public abstract void createAfter(Composite parent); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IHierarchicContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IHierarchicContentProvider.java new file mode 100644 index 00000000000..7da7d3b9d55 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IHierarchicContentProvider.java @@ -0,0 +1,38 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.ITreeContentProvider; + +/** + * A Hierarchic content provider. In some cases, we want to be able to display + * elements as a Tree, but we are only interested in some specific elements. + * The other ones are displayed only to show the hierarchy. + * This interface allows the user to specify which elements he is interested + * in. + * + * @author Camille Letavernier + * + */ +public interface IHierarchicContentProvider extends ITreeContentProvider { + + /** + * Indicates if the given is a valid value. Only valid values can be + * chosen. + * + * @param element + * The element to test + * @return + * True if the element is a valid value + */ + public boolean isValidValue(Object element); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IInheritedElementContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IInheritedElementContentProvider.java new file mode 100644 index 00000000000..130ec453193 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IInheritedElementContentProvider.java @@ -0,0 +1,39 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.IStructuredContentProvider; + +/** + * This interface + * + * @author vl222926 + * + */ +public interface IInheritedElementContentProvider extends IStructuredContentProvider { + + /** + * + * @param ignoreInheritedElements + * if <code>true</code> the inherited elements won't be returned + */ + public void setIgnoreInheritedElements(final boolean ignoreInheritedElements); + + /** + * + * @return + * <code>true</code> if the content provider is ignoring the inherited elements + */ + public boolean isIgnoringInheritedElements(); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IRestrictedContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IRestrictedContentProvider.java new file mode 100644 index 00000000000..ed7333329ff --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IRestrictedContentProvider.java @@ -0,0 +1,40 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * 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: + * Juan Cadavid (CEA LIST) juan.cadavid@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + + +/** + * Add a boolean to choose the display mode : + * <ul> + * <li>display all possible values according to the model (restricted==false)</li> + * <li>display all possible values according to current edited object (restricted==true)</li> + * </ul> + * + * @author JC236769 + * + */ +public interface IRestrictedContentProvider extends IHierarchicContentProvider, IStaticContentProvider, IInheritedElementContentProvider { + + /** + * + * @param isRestricted + */ + public void setRestriction(boolean isRestricted); + + /** + * + * @return + * <code>true</code> if the content provider is restricted + */ + public boolean isRestricted(); + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IStaticContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IStaticContentProvider.java new file mode 100644 index 00000000000..75b726009e0 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/IStaticContentProvider.java @@ -0,0 +1,33 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.IStructuredContentProvider; + +/** + * A ContentProvider which returns values that don't depend + * on an input value + * + * In most cases, you should extend the Abstract implementation {@link AbstractStaticContentProvider} + * + * @author Camille Letavernier + * + * @see AbstractStaticContentProvider + * + */ +public interface IStaticContentProvider extends IStructuredContentProvider { + + /** + * @return the elements provided by this class + */ + public Object[] getElements(); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/MapLabelProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/MapLabelProvider.java new file mode 100644 index 00000000000..43c3a4ad795 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/MapLabelProvider.java @@ -0,0 +1,25 @@ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.Map; + +import org.eclipse.jface.viewers.LabelProvider; + +/** + * A LabelProvider based on a Map + * + * @author Camille Letavernier + */ +public class MapLabelProvider extends LabelProvider { + + protected final Map<Object, String> objectsToLabels; + + public MapLabelProvider(Map<Object, String> objectsToLabels) { + this.objectsToLabels = objectsToLabels; + } + + @Override + public String getText(Object element) { + return objectsToLabels.get(element); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/PatternViewerFilter.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/PatternViewerFilter.java new file mode 100644 index 00000000000..ee7080a20f4 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/PatternViewerFilter.java @@ -0,0 +1,83 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.ui.internal.misc.StringMatcher; + +/** + * A ViewerFilter which can be used to match a pattern. + * + * The pattern accepts wildcards (* and ?), and ; as a pattern-separator + * + * For example: + * foo;bar will match either "foo" or "bar" + * foo* will match "foobar" + * + * @author Camille Letavernier + * + */ +public class PatternViewerFilter extends AbstractTreeFilter { + + private StringMatcher[] validPatterns = new StringMatcher[] { new StringMatcher("*", true, false) }; + + private String currentPattern; + + private boolean strict = false; + + /** + * If the pattern is not strict, wildcards (*) will be added at the beginning and the end of the pattern + * The pattern foo becomes equivalent to *foo* + * + * @param strict + */ + public void setStrict(boolean strict) { + this.strict = strict; + } + + public void setPattern(String value) { + if (value.equals(currentPattern)) { + return; + } + + currentPattern = value; + + String[] patterns = value.split(";"); + this.validPatterns = new StringMatcher[patterns.length]; + int i = 0; + for (String pattern : patterns) { + if (!strict) { + pattern = "*" + pattern.trim() + "*"; + } + validPatterns[i++] = new StringMatcher(pattern, true, false); + } + + clearCache(); + } + + @Override + public boolean isVisible(Viewer viewer, Object parentElement, Object element) { + IBaseLabelProvider labelProvider = ((StructuredViewer) viewer).getLabelProvider(); + if (labelProvider instanceof ILabelProvider) { + for (StringMatcher pattern : validPatterns) { + if (pattern.match(((ILabelProvider) labelProvider).getText(element))) { + return true; + } + } + } + return false; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/SemanticWorkspaceContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/SemanticWorkspaceContentProvider.java new file mode 100644 index 00000000000..41a41e2fe65 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/SemanticWorkspaceContentProvider.java @@ -0,0 +1,151 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.papyrus.infra.tools.util.ListHelper; +import org.eclipse.papyrus.infra.widgets.Activator; + +import com.ibm.icu.text.Collator; + +/** + * A ContentProvider for resources located in the current workspace + * + * @author Camille Letavernier + */ +public class SemanticWorkspaceContentProvider extends AbstractStaticContentProvider implements IHierarchicContentProvider { + + /** + * Constructor + */ + public SemanticWorkspaceContentProvider() { + + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getElements() { + try { + return filterAccessibleElements(ResourcesPlugin.getWorkspace().getRoot().members()); + } catch (Exception ex) { + Activator.log.error(ex); + return new Object[0]; + } + } + + protected Object[] filterAccessibleElements(IResource[] members) { + List<IResource> accessibleElements = ListHelper.asList(members); + + Iterator<IResource> resourceIterator = accessibleElements.iterator(); + while (resourceIterator.hasNext()) { + IResource resource = resourceIterator.next(); + if (!resource.isAccessible()) { + resourceIterator.remove(); + } + } + + Collections.sort(accessibleElements, resourceComparator); + + return accessibleElements.toArray(); + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof IContainer) { + try { + IResource[] members = ((IContainer) parentElement).members(); + + return filterAccessibleElements(members); + } catch (CoreException ex) { + Activator.log.error(ex); + } + } + return new Object[0]; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getParent(Object element) { + if (element instanceof IContainer) { + return ((IContainer) element).getParent(); + } + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasChildren(Object element) { + return getChildren(element).length > 0; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isValidValue(Object element) { + return !(element instanceof IWorkspaceRoot); + } + + /** + * Compares two resources (IResource) + */ + private static final Comparator<IResource> resourceComparator = createComparator(); + + private static Comparator<IResource> createComparator() { + final int folderTypes = IResource.FOLDER | IResource.PROJECT | IResource.ROOT; + return new Comparator<IResource>() { + + @Override + public int compare(IResource resource1, IResource resource2) { + int typeCompare = compareType(resource1, resource2); + if (typeCompare == 0) { + return compareName(resource1, resource2); + } + return typeCompare; + } + + private int compareType(IResource resource1, IResource resource2) { + if (resource1.getType() == resource2.getType()) { + return 0; + } + if ((resource1.getType() & folderTypes) > (resource2.getType() & folderTypes)) { + return -1; + } else { + return 1; + } + } + + private int compareName(IResource resource1, IResource resource2) { + return Collator.getInstance().compare(resource1.getName(), resource2.getName()); + } + + }; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/StaticContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/StaticContentProvider.java new file mode 100644 index 00000000000..171aaf58450 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/StaticContentProvider.java @@ -0,0 +1,75 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.Viewer; + +/** + * Default implementation of IStaticContentProvider, creating a ContentProvider + * from an Array of objects. + * + * @author Camille Letavernier + * + */ +public class StaticContentProvider extends AbstractStaticContentProvider { + + /** + * The elements for this content provider + */ + private Object[] elements; + + /** + * The JFace viewer on which this content provider is applied + */ + private Viewer viewer; + + /** + * + * Constructor. Creates a new ContentProvider with the given elements + * + * @param elements + * The elements known by this ContentProvider + */ + public StaticContentProvider(Object[] elements) { + this.elements = elements; + } + + /** + * Changes the elements known by this ContentProvider + * + * @param elements + * The elements known by this ContentProvider + */ + public void setElements(Object[] elements) { + this.elements = elements; + if (viewer != null) { + viewer.refresh(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + this.viewer = viewer; + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getElements() { + return elements; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/TreeCollectionContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/TreeCollectionContentProvider.java new file mode 100644 index 00000000000..73deef70ce1 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/TreeCollectionContentProvider.java @@ -0,0 +1,73 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.Collection; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + + +public class TreeCollectionContentProvider implements ITreeContentProvider { + + private TreeCollectionContentProvider() { + + } + + @Override + public Object[] getChildren(Object parentElement) { + return new Object[0]; + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public boolean hasChildren(Object element) { + return false; + } + + public static final TreeCollectionContentProvider instance = new TreeCollectionContentProvider(); + + @Override + public void dispose() { + // Nothing + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // Nothing + } + + /** + * Converts the input List to an Array containing the same elements + * + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + * + * @param inputElement + * @return + * The Array containing the input elements + */ + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof Collection) { + return ((Collection<?>) inputElement).toArray(); + } else if (inputElement instanceof Object[]) { + return (Object[]) inputElement; + } + + return new Object[] {}; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/TreeToFlatContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/TreeToFlatContentProvider.java new file mode 100644 index 00000000000..680cb658b10 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/TreeToFlatContentProvider.java @@ -0,0 +1,112 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +//FIXME : Adapt this code to TreeBrowseStrategy +public class TreeToFlatContentProvider extends AbstractStaticContentProvider { + + private ITreeContentProvider contentProvider; + + private StructuredViewer viewer; + + public TreeToFlatContentProvider(ITreeContentProvider provider) { + if (!(provider instanceof IStaticContentProvider)) { + throw new IllegalArgumentException(); + } + this.contentProvider = provider; + } + + @Override + public void dispose() { + contentProvider.dispose(); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + if (viewer instanceof StructuredViewer) { + this.viewer = (StructuredViewer) viewer; + } + + contentProvider.inputChanged(viewer, oldInput, newInput); + } + + @Override + public Object[] getElements() { + return getElementsList().toArray(); + } + + /** + * Returns the concrete value from the given Object + * For example, if the content provider is an IAdaptableContentProvider, + * returns the adapted value. + * + * @param value + * @return + */ + protected Object getValue(Object value) { + if (contentProvider instanceof IAdaptableContentProvider) { + return ((IAdaptableContentProvider) contentProvider).getAdaptedValue(value); + } else { + return value; + } + } + + protected boolean exploreBranch(Object parentElement, Object element) { + if (viewer == null) { + return true; + } + + for (ViewerFilter filter : viewer.getFilters()) { + if (!filter.select(viewer, parentElement, element)) { + return false; + } + } + + return true; + } + + protected Collection<Object> getElementsList() { + Collection<Object> result = new LinkedHashSet<Object>(); + Set<Object> browsedElements = new HashSet<Object>(); + + for (Object root : ((IStaticContentProvider) contentProvider).getElements()) { + if (exploreBranch(null, root)) { + result.add(root); + getElementsList(root, result, browsedElements); + } + } + + return result; + } + + protected void getElementsList(Object parent, Collection<Object> result, Set<Object> browsedElements) { + for (Object child : contentProvider.getChildren(parent)) { + Object childValue = getValue(child); + if (!result.contains(childValue)) { // Avoid infinite recursion + result.add(childValue); + if (exploreBranch(parent, child)) { + getElementsList(child, result, browsedElements); + } + } + } + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/UnchangedObject.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/UnchangedObject.java new file mode 100644 index 00000000000..a6369991fa1 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/UnchangedObject.java @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.papyrus.infra.widgets.messages.Messages; + + +public class UnchangedObject { + + private UnchangedObject() { + + } + + @Override + public String toString() { + return Messages.ReferenceDialogObservable_Unchanged; + } + + public static final UnchangedObject instance = new UnchangedObject(); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/UnsetObject.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/UnsetObject.java new file mode 100644 index 00000000000..897a36d56a1 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/UnsetObject.java @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.papyrus.infra.widgets.messages.Messages; + + +public class UnsetObject { + + @Override + public String toString() { + return Messages.ReferenceDialog_Unset; + } + + private UnsetObject() { + + } + + public static final UnsetObject instance = new UnsetObject(); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/WorkbenchFilteredLabelProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/WorkbenchFilteredLabelProvider.java new file mode 100644 index 00000000000..39b05f847ab --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/WorkbenchFilteredLabelProvider.java @@ -0,0 +1,70 @@ +/***************************************************************************** + * Copyright (c) 2012, 2015 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 469188 + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.papyrus.infra.services.labelprovider.service.IFilteredLabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.model.WorkbenchLabelProvider; + + +/** + * A LabelProvider contribution to handle Workspace elements + * + * @author Camille Letavernier + */ +public class WorkbenchFilteredLabelProvider extends LabelProvider implements IFilteredLabelProvider { + + private final ILabelProvider workbenchLabelProvider; + + public WorkbenchFilteredLabelProvider() { + workbenchLabelProvider = WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider(); + } + + @Override + public String getText(Object element) { + return workbenchLabelProvider.getText(unwrapSelection(element)); + } + + @Override + public Image getImage(Object element) { + return workbenchLabelProvider.getImage(unwrapSelection(element)); + } + + @Override + public boolean accept(Object element) { + return unwrapSelection(element) instanceof IResource; + } + + /** + * Unwraps a single selection to get the element inside it. + * + * @param selection + * @return + */ + Object unwrapSelection(Object possibleSelection) { + Object result = possibleSelection; + + if (possibleSelection instanceof IStructuredSelection) { + IStructuredSelection selection = (IStructuredSelection) possibleSelection; + if (selection.size() == 1) { + result = selection.getFirstElement(); + } + } + + return result; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/WorkspaceContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/WorkspaceContentProvider.java new file mode 100644 index 00000000000..1562e0ea009 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/WorkspaceContentProvider.java @@ -0,0 +1,135 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.papyrus.infra.widgets.strategy.ProviderBasedBrowseStrategy; +import org.eclipse.papyrus.infra.widgets.strategy.StrategyBasedContentProvider; +import org.eclipse.papyrus.infra.widgets.strategy.TreeBrowseStrategy; +import org.eclipse.papyrus.infra.widgets.strategy.WorkspaceRevealStrategy; +import org.eclipse.swt.widgets.Composite; + + +/** + * A Workspace content provider with search possibilities and filters (By file name and by file extension) + * + * @author Camille Letavernier + */ +public class WorkspaceContentProvider extends EncapsulatedContentProvider { + + private Map<String, String> extensionFilters = new LinkedHashMap<String, String>(); + + private PatternViewerFilter extensionViewerFilter = new PatternViewerFilter(); + + private ISelectionChangedListener extensionFiltersListener = new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + + String patternString = "*"; + if (!event.getSelection().isEmpty()) { + patternString = (String) ((IStructuredSelection) event.getSelection()).getFirstElement(); + } + extensionViewerFilter.setPattern(patternString); + viewer.refresh(); + } + }; + + protected StructuredViewer viewer; + + /** + * Constructor + */ + public WorkspaceContentProvider() { + super(); + this.encapsulated = encapsulateProvider(getSemanticProvider()); + extensionFilters.put("*", "All (*)"); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + super.inputChanged(viewer, oldInput, newInput); + + if (viewer instanceof StructuredViewer) { + this.viewer = (StructuredViewer) viewer; + addViewerFilter(this.viewer, extensionViewerFilter); + } + } + + protected static IHierarchicContentProvider getSemanticProvider() { + return new SemanticWorkspaceContentProvider(); + } + + public void setExtensionFilters(Map<String, String> extensionFilters) { + this.extensionFilters = extensionFilters; + } + + public void addExtensionFilter(String pattern, String label) { + this.extensionFilters.put(pattern, label); + } + + protected IStructuredContentProvider encapsulateProvider(IHierarchicContentProvider provider) { + TreeBrowseStrategy browseStrategy = new ProviderBasedBrowseStrategy(provider); + TreeBrowseStrategy revealStrategy = new WorkspaceRevealStrategy(provider); + StrategyBasedContentProvider strategyProvider = new StrategyBasedContentProvider(browseStrategy, revealStrategy); + + + EncapsulatedContentProvider graphicalProvider = new ExtensionFilteredContentProvider(strategyProvider); + + return graphicalProvider; + } + + private class ExtensionFilteredContentProvider extends FilteredContentProvider { + + public ExtensionFilteredContentProvider(IHierarchicContentProvider semanticProvider) { + super(semanticProvider); + } + + @Override + public void createAfter(Composite parent) { + super.createAfter(parent); + ComboViewer extensionFiltersViewer = new ComboViewer(parent); + + extensionFiltersViewer.setContentProvider(CollectionContentProvider.instance); + extensionFiltersViewer.setLabelProvider(new LabelProvider() { + + @Override + public String getText(Object element) { + if (extensionFilters.containsKey(element)) { + return extensionFilters.get(element); + } else { + return super.getText(element); + } + } + }); + + extensionFiltersViewer.addSelectionChangedListener(extensionFiltersListener); + + extensionFiltersViewer.setInput(extensionFilters.keySet()); + if (!extensionFilters.isEmpty()) { + extensionFiltersViewer.setSelection(new StructuredSelection(extensionFilters.keySet().iterator().next())); + } + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/WrappedLabelProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/WrappedLabelProvider.java new file mode 100644 index 00000000000..0b6d84d2160 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/providers/WrappedLabelProvider.java @@ -0,0 +1,121 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.providers; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.swt.graphics.Image; + +/** + * A mutable wrapper for {@link ILabelProvider}s + * May be used when you need to instantiate a component with a labelProvider, + * and you don't have one yet. + * If there is no wrapped label provider, the default toString method will be called + * on non-null objects. + * + * @author Camille Letavernier + * + */ +public class WrappedLabelProvider implements ILabelProvider { + + /** + * The wrapped LabelProvider + */ + private ILabelProvider labelProvider; + + /** + * Constructs a new empty Label provider wrapper. + */ + public WrappedLabelProvider() { + + } + + /** + * + * Constructs a new Label provider, wrapping the specified label provider. + * + * @param provider + * The wrapped label provider + */ + public WrappedLabelProvider(ILabelProvider provider) { + this.labelProvider = provider; + } + + /** + * Changes the wrapped label provider + * + * @param provider + * The new wrapped label provider + */ + public void setLabelProvider(ILabelProvider provider) { + this.labelProvider = provider; + } + + /** + * {@inheritDoc} + */ + @Override + public void addListener(ILabelProviderListener listener) { + // Nothing + } + + /** + * {@inheritDoc} + */ + @Override + public void dispose() { + // Nothing + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLabelProperty(Object element, String property) { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void removeListener(ILabelProviderListener listener) { + // Nothing + } + + /** + * {@inheritDoc} + */ + @Override + public Image getImage(Object element) { + if (labelProvider != null) { + return labelProvider.getImage(element); + } + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public String getText(Object element) { + if (labelProvider != null) { + return labelProvider.getText(element); + } + if (element == null) + { + return "null"; //$NON-NLS-1$ + } + return element.toString(); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/BooleanSelector.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/BooleanSelector.java new file mode 100644 index 00000000000..76e56655549 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/BooleanSelector.java @@ -0,0 +1,49 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.selectors; + +import org.eclipse.papyrus.infra.tools.util.BooleanHelper; + + + +/** + * A Selector for Integer values + * + * @author Camille Letavernier + * + */ +public class BooleanSelector extends StringSelector { + + /** + * Constructs a Selector for Integer values + */ + public BooleanSelector() { + super(); + } + + /** + * {@inheritDoc} + */ + @Override + public Boolean[] getSelectedElements() { + Boolean[] result = new Boolean[0]; + try { + if (BooleanHelper.isBoolean(text.getText())) { + result = new Boolean[] { new Boolean(text.getText()) }; + text.setText(""); //$NON-NLS-1$ + } + } catch (NumberFormatException ex) { + // nothing to do + } + return result; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/IntegerSelector.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/IntegerSelector.java new file mode 100644 index 00000000000..d53f22ef52b --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/IntegerSelector.java @@ -0,0 +1,44 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.selectors; + + +/** + * A Selector for Integer values + * + * @author Camille Letavernier + * + */ +public class IntegerSelector extends StringSelector { + + /** + * Constructs a Selector for Integer values + */ + public IntegerSelector() { + super(); + } + + /** + * {@inheritDoc} + */ + @Override + public Integer[] getSelectedElements() { + Integer[] result; + try { + result = new Integer[] { Integer.parseInt(text.getText()) }; + text.setText(""); //$NON-NLS-1$ + } catch (NumberFormatException ex) { + result = new Integer[0]; + } + return result; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/NullSelector.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/NullSelector.java new file mode 100644 index 00000000000..e8d764bfe34 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/NullSelector.java @@ -0,0 +1,61 @@ +package org.eclipse.papyrus.infra.widgets.selectors; + +import org.eclipse.papyrus.infra.widgets.editors.IElementSelectionListener; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelector; +import org.eclipse.swt.widgets.Composite; + +/** + * A Null implementation of the IElementSelector interface + * + * @author Camille Letavernier + * + */ +public class NullSelector implements IElementSelector { + + private NullSelector() { + + } + + @Override + public Object[] getSelectedElements() { + return new Object[0]; + } + + @Override + public void setSelectedElements(Object[] elements) { + // Nothing + } + + @Override + public Object[] getAllElements() { + return new Object[0]; + } + + @Override + public void createControls(Composite parent) { + // Nothing + } + + @Override + public void newObjectCreated(Object newObject) { + // Nothing + } + + @Override + public void clearTemporaryElements() { + // Nothing + } + + @Override + public void addElementSelectionListener(IElementSelectionListener listener) { + // Nothing + } + + @Override + public void removeElementSelectionListener(IElementSelectionListener listener) { + // Nothing + } + + public final static NullSelector instance = new NullSelector(); + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/RealSelector.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/RealSelector.java new file mode 100644 index 00000000000..b12922c959e --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/RealSelector.java @@ -0,0 +1,44 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.selectors; + + +/** + * A Selector for Real values + * + * @author Vincent Lorenzo + * + */ +public class RealSelector extends StringSelector { + + /** + * Constructs a Selector for Real values + */ + public RealSelector() { + super(); + } + + /** + * {@inheritDoc} + */ + @Override + public Double[] getSelectedElements() { + Double[] result; + try { + result = new Double[] { Double.parseDouble((text.getText())) }; + text.setText(""); //$NON-NLS-1$ + } catch (NumberFormatException ex) { + result = new Double[0]; + } + return result; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/ReferenceSelector.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/ReferenceSelector.java new file mode 100644 index 00000000000..9522a9364c0 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/ReferenceSelector.java @@ -0,0 +1,436 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.selectors; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelectionListener; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelector; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IGraphicalContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider; +import org.eclipse.papyrus.infra.widgets.strategy.ProviderBasedBrowseStrategy; +import org.eclipse.papyrus.infra.widgets.strategy.StrategyBasedContentProvider; +import org.eclipse.papyrus.infra.widgets.strategy.TreeBrowseStrategy; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.dialogs.PatternFilter; + + +/** + * A Selector for Multiple Reference values, with a filter + * + * This selector is compatible with {@link org.eclipse.papyrus.infra.widgets.providers.IAdaptableContentProvider} + * + * @author Camille Letavernier + * + */ +public class ReferenceSelector implements IElementSelector { + + /** + * The tree viewer + */ + protected TreeViewer treeViewer; + + /** + * The content provider, returning the available reference values + */ + protected EncapsulatedContentProvider contentProvider; + + /** + * The content provider, returning the available reference labels + */ + protected ILabelProvider labelProvider; + + /** + * Indicates if the reference values should be unique + */ + protected boolean unique; + + /** + * Indicates if this selector should be able to return more than one value + * at a time. + */ + protected boolean multiSelection; + + + protected final List<ICommitListener> commitListeners; + + + private Set<IElementSelectionListener> elementSelectionListeners = new HashSet<IElementSelectionListener>(); + + /** + * The set of selected elements. If the selector is marked as "unique", + * these elements will be filtered in the Tree. + * + * The Elements are in their container form + */ + protected Set<Object> selectedElements = new HashSet<Object>(); + + /** + * + * Constructor. + * + * @param unique + * Indicates if the values are unique. If true, they are removed + * from the list when they are chosen + */ + public ReferenceSelector(boolean unique) { + this.unique = unique; + this.multiSelection = true; + commitListeners = new LinkedList<ICommitListener>(); + } + + /** + * + * Constructor. + * Builds a new ReferenceSelector for a single element + * + */ + public ReferenceSelector() { + this(false); + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getSelectedElements() { + ISelection selection = treeViewer.getSelection(); + + if (selection instanceof IStructuredSelection) { + Object[] containerElementsToMove = getElementsToMove(((IStructuredSelection) selection).toArray()); + Object[] semanticElementsToMove = getSemanticElements(containerElementsToMove); + addSelectedElements(semanticElementsToMove); + return semanticElementsToMove; + } + + return new Object[0]; + } + + /** + * This method is used for handling correctly the IAdaptableContentProvider + * The objects can be in two different forms : + * - The semantic element + * - The container element + * + * This methods returns an array of semantic elements from an array of + * container elements. This is useful for retrieving the semantic elements + * from a viewer's selection when the viewer uses an IAdaptableContentProvider + * + * @param containerElements + * The array of elements wrapped in their container + * @return + * The array of semantic elements to be converted + * + * @see #getContainerElements(Object[]) + * @see org.eclipse.papyrus.infra.widgets.providers.IAdaptableContentProvider + */ + private Object[] getSemanticElements(Object[] containerElements) { + Object[] semanticElements = new Object[containerElements.length]; + int i = 0; + for (Object containerElement : containerElements) { + semanticElements[i++] = contentProvider.getAdaptedValue(containerElement); + } + return semanticElements; + } + + /** + * Filters the selection to return only the objects that can + * be selected, according to the content provider. + * + * @param selection + * The input array to filter + * @return + * The filtered array + * + * @see org.eclipse.papyrus.infra.widgets.providers.IHierarchicContentProvider#isValidValue(Object) + */ + protected Object[] getElementsToMove(Object[] selection) { + List<Object> elementsToMove = new LinkedList<Object>(); + + for (Object element : selection) { + if (contentProvider.isValidValue(element)) { + elementsToMove.add(element); + } + } + + notifyCommitListeners(); + return elementsToMove.toArray(); + } + + /** + * Adds elements to the list of selected elements. If the values are + * unique, the specified elements won't be displayed + * + * @param elements + */ + private void addSelectedElements(Object[] semanticElements) { + if (semanticElements.length > 0) { + selectedElements.addAll(Arrays.asList(semanticElements)); + refresh(); + } + } + + /** + * Returns all the elements that are currently displayed, i.e. matching + * the filter + * + * {@link IElementSelector#getAllElements()} + * + * @return all elements matching the filter + */ + @Override + public Object[] getAllElements() { + // There is no way to retrieve the filteredElements on a FList + // We can only retrieve the selected ones + // Fix : we select everything, then we return the selection + if (contentProvider == null) { + return new Object[0]; + } + + Collection<Object> visibleElements = new LinkedList<Object>(); + for (TreeItem rootItem : treeViewer.getTree().getItems()) { + visibleElements.add(getElement(rootItem)); + if (rootItem.getExpanded()) { + fillVisibleElements(rootItem, visibleElements); + } + } + + Object[] containerElementsToMove = getElementsToMove(visibleElements.toArray()); + Object[] semanticElementsToMove = getSemanticElements(containerElementsToMove); + addSelectedElements(semanticElementsToMove); + + return semanticElementsToMove; + } + + private void fillVisibleElements(TreeItem item, Collection<Object> visibleElements) { + for (TreeItem childItem : item.getItems()) { + visibleElements.add(getElement(childItem)); + if (childItem.getExpanded()) { + fillVisibleElements(childItem, visibleElements); + } + } + } + + private Object getElement(TreeItem item) { + return item.getData(); + } + + /** + * Sets the list of selected elements. If the values are + * unique, the specified elements won't be displayed + * + * @param elements + */ + @Override + public void setSelectedElements(Object[] semanticElements) { + selectedElements.clear(); + selectedElements.addAll(Arrays.asList(semanticElements)); + refresh(); + } + + @Override + public void newObjectCreated(Object newObject) { + contentProvider.addTemporaryElement(newObject); + refresh(); + } + + @Override + public void clearTemporaryElements() { + contentProvider.clearTemporaryElements(); + } + + /** + * Refreshes this selector's {@link org.eclipse.swt.widgets.List} + */ + public void refresh() { + ((SelectionFilteredBrowseStrategy) contentProvider.getBrowseStrategy()).refresh(); + treeViewer.refresh(); + } + + /** + * Sets this selector's label provider. The label provider is used + * to display the reference values + * + * @param labelProvider + */ + public void setLabelProvider(ILabelProvider labelProvider) { + this.labelProvider = labelProvider; + if (treeViewer != null) { + treeViewer.setLabelProvider(labelProvider); + } + } + + /** + * Sets this selector's content provider. The content provider + * is used to select the available values for this property + * + * @param staticContentProvider + */ + public void setContentProvider(IStaticContentProvider staticContentProvider) { + + ITreeContentProvider provider = new EncapsulatedContentProvider(staticContentProvider); + + TreeBrowseStrategy filteredBrowseStrategy = new SelectionFilteredBrowseStrategy(provider); + + TreeBrowseStrategy revealBrowseStrategy = new ProviderBasedBrowseStrategy(provider); + + this.contentProvider = new StrategyBasedContentProvider(filteredBrowseStrategy, revealBrowseStrategy); + + if (treeViewer != null) { + treeViewer.setContentProvider(contentProvider); + treeViewer.setInput(""); //$NON-NLS-1$ + } + + if (contentProvider instanceof ICommitListener) { + commitListeners.add(contentProvider); + } + } + + /** + * Strategy to hide tree elements which are already selected, when the selector is defined as unique + * + * @author Camille Letavernier + * + */ + private class SelectionFilteredBrowseStrategy extends ProviderBasedBrowseStrategy { + + public SelectionFilteredBrowseStrategy(ITreeContentProvider provider) { + super(provider); + } + + @Override + public boolean isValidValue(Object element) { + if (!unique) { + return super.isValidValue(element); + } + + if (!super.isValidValue(element)) { + return false; + } + + return !selectedElements.contains(getAdaptedValue(element)); + } + + public void refresh() { + if (unique) { + clearCache(); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void createControls(Composite parent) { + Composite content = new Composite(parent, SWT.NONE); + content.setLayout(new GridLayout(1, true)); + + treeViewer = new TreeViewer(content, SWT.BORDER | SWT.MULTI); + treeViewer.setFilters(new ViewerFilter[] { new PatternFilter() }); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.minimumHeight = 300; + data.minimumWidth = 300; + treeViewer.getTree().setLayoutData(data); + + if (labelProvider != null) { + treeViewer.setLabelProvider(labelProvider); + } + + if (contentProvider != null) { + treeViewer.setContentProvider(contentProvider); + treeViewer.setInput(""); //$NON-NLS-1$ + } + + if (contentProvider instanceof IGraphicalContentProvider) { + IGraphicalContentProvider graphicalContentProvider = contentProvider; + + Composite beforeTreeComposite = new Composite(content, SWT.NONE); + beforeTreeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + FillLayout layout = new FillLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + beforeTreeComposite.setLayout(layout); + graphicalContentProvider.createBefore(beforeTreeComposite); + + beforeTreeComposite.moveAbove(treeViewer.getTree()); + + Composite afterTreeComposite = new Composite(content, SWT.NONE); + layout = new FillLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + afterTreeComposite.setLayout(layout); + afterTreeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + graphicalContentProvider.createAfter(afterTreeComposite); + } + + // Adds double-click support + treeViewer.addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(DoubleClickEvent event) { + if (!elementSelectionListeners.isEmpty()) { + Object[] selectedElements = getSelectedElements(); + if (selectedElements.length > 0) { + notifyCommitListeners(); + for (IElementSelectionListener listener : elementSelectionListeners) { + listener.addElements(selectedElements); + } + } + } + } + + }); + } + + public void setUnique(boolean unique) { + this.unique = unique; + } + + @Override + public void addElementSelectionListener(IElementSelectionListener listener) { + elementSelectionListeners.add(listener); + } + + @Override + public void removeElementSelectionListener(IElementSelectionListener listener) { + elementSelectionListeners.remove(listener); + } + + protected void notifyCommitListeners() { + for (ICommitListener commitListener : commitListeners) { + commitListener.commit(null); + } + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/StandardSelector.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/StandardSelector.java new file mode 100644 index 00000000000..5601f20141d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/StandardSelector.java @@ -0,0 +1,138 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.selectors; + +import java.lang.reflect.Constructor; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; +import org.eclipse.papyrus.infra.widgets.editors.AbstractValueEditor; +import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelectionListener; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelector; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +/** + * Creates an element selector from an AbstractValueEditor. This class is a + * generic implementation for element selectors. + * + * @author Camille Letavernier + * + */ +public class StandardSelector implements IElementSelector { + + /** + * The AbstractValueEditor class used for instantiating this selector + */ + protected Class<? extends AbstractValueEditor> editorClass; + + /** + * The AbstractValueEditor used by this selector + */ + protected AbstractValueEditor editor; + + protected Set<IElementSelectionListener> elementSelectionListeners = new HashSet<IElementSelectionListener>(); + + /** + * Instantiates this selector, using the specified editor class + * + * @param editorClass + * The AbstractValueEditor Class used to instantiate this selector + */ + public StandardSelector(Class<? extends AbstractValueEditor> editorClass) { + Assert.isNotNull(editorClass, "The StandardSelector editor class should not be null"); //$NON-NLS-1$ + this.editorClass = editorClass; + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getSelectedElements() { + Object value = editor.getValue(); + if (value == null) { + return new Object[] {}; + } + + return new Object[] { value }; + } + + /** + * Ignored. The generic selectors can't be filtered. + */ + @Override + public void setSelectedElements(Object[] elements) { + // Ignored + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getAllElements() { + return getSelectedElements(); + } + + /** + * {@inheritDoc} + * + * The control for this selector is obtained by instantiating the generic class with a parent + * composite and a default style + */ + @Override + public void createControls(Composite parent) { + try { + Constructor<? extends AbstractValueEditor> construct = editorClass.getDeclaredConstructor(Composite.class, Integer.TYPE); + editor = construct.newInstance(parent, SWT.BORDER); + editor.addCommitListener(new ICommitListener() { + + @Override + public void commit(AbstractEditor editor) { + if (!elementSelectionListeners.isEmpty()) { + Object value = StandardSelector.this.editor.getValue(); + for (IElementSelectionListener listener : elementSelectionListeners) { + listener.addElements(new Object[] { value }); + } + } + } + + }); + } catch (Exception ex) { + Activator.log.error(ex); + } + } + + @Override + public void newObjectCreated(Object newObject) { + // Ignored + } + + @Override + public void clearTemporaryElements() { + // Ignored + } + + @Override + public void addElementSelectionListener(IElementSelectionListener listener) { + elementSelectionListeners.add(listener); + } + + @Override + public void removeElementSelectionListener(IElementSelectionListener listener) { + elementSelectionListeners.remove(listener); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/StringSelector.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/StringSelector.java new file mode 100644 index 00000000000..8df015f9b6f --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/selectors/StringSelector.java @@ -0,0 +1,155 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.selectors; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.papyrus.infra.widgets.editors.IElementSelectionListener; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelector; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; + +/** + * A selector for String values, or values that can be represented + * as text in general. + * Displays a field where the user can enter the new values. + * The field can be multiline or single line + * + * @author Camille Letavernier + * + */ +public class StringSelector implements IElementSelector { + + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + /** + * The text box used to enter a value for this selector + */ + protected Text text; + + /** + * Indicates if this StringSelector is multiline + */ + protected boolean multiline; + + protected Set<IElementSelectionListener> elementSelectionListeners = new HashSet<IElementSelectionListener>(); + + /** + * Constructs a single-line String Selector + */ + public StringSelector() { + this(false); + } + + /** + * Constructs a String Selector + * + * @param multiline + * True if the string values can contain more than one line + */ + public StringSelector(boolean multiline) { + this.multiline = multiline; + } + + /** + * Returns a single-element array containing the current text + * + * {@link IElementSelector#getSelectedElements()} + */ + @Override + public Object[] getSelectedElements() { + String[] result = new String[] { text.getText() }; + text.setText(""); //$NON-NLS-1$ + return result; + } + + /** + * Ignored + */ + @Override + public void setSelectedElements(Object[] elements) { + // Nothing + } + + /** + * {@inheritDoc} + */ + @Override + public void createControls(Composite parent) { + text = new Text(parent, SWT.MULTI | SWT.BORDER); + text.addKeyListener(new KeyListener() { + + @Override + public void keyPressed(KeyEvent e) { + // Nothing + } + + @Override + public void keyReleased(KeyEvent e) { + if ((e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) && ((e.stateMask == SWT.NONE && !multiline) || ((e.stateMask & SWT.CTRL) != 0 && multiline))) { + if (!elementSelectionListeners.isEmpty()) { + String str = (String) getSelectedElements()[0]; + if (str.endsWith(LINE_SEPARATOR)) { + str = str.substring(0, str.length() - LINE_SEPARATOR.length()); + } + if (!"".equals(str)) { //$NON-NLS-1$ + for (IElementSelectionListener listener : elementSelectionListeners) { + listener.addElements(new Object[] { str }); + } + } + } + } + } + + }); + } + + /** + * Returns the same value as getSelectedElements + * + * {@link IElementSelector#getAllElements()} + */ + @Override + public Object[] getAllElements() { + return getSelectedElements(); + } + + /** + * {@inheritDoc} + */ + @Override + public void newObjectCreated(Object newObject) { + // Ignored + } + + /** + * {@inheritDoc} + */ + @Override + public void clearTemporaryElements() { + // Ignored + } + + @Override + public void addElementSelectionListener(IElementSelectionListener listener) { + elementSelectionListeners.add(listener); + } + + @Override + public void removeElementSelectionListener(IElementSelectionListener listener) { + elementSelectionListeners.remove(listener); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/AbstractTreeBrowseStrategy.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/AbstractTreeBrowseStrategy.java new file mode 100644 index 00000000000..84fc6cb48f8 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/AbstractTreeBrowseStrategy.java @@ -0,0 +1,34 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.strategy; + +import java.util.List; + +import org.eclipse.jface.viewers.Viewer; + + +public abstract class AbstractTreeBrowseStrategy implements TreeBrowseStrategy { + + @Override + public void dispose() { + // Nothing + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // Nothing + } + + @Override + abstract public void revealSemanticElement(List<?> elementsList); + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/IStrategyBasedContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/IStrategyBasedContentProvider.java new file mode 100644 index 00000000000..672e1e85f54 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/IStrategyBasedContentProvider.java @@ -0,0 +1,22 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.strategy; + +import org.eclipse.jface.viewers.IStructuredContentProvider; + + +public interface IStrategyBasedContentProvider extends IStructuredContentProvider { + + public TreeBrowseStrategy getBrowseStrategy(); + + public TreeBrowseStrategy getRevealStrategy(); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/ProviderBasedBrowseStrategy.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/ProviderBasedBrowseStrategy.java new file mode 100644 index 00000000000..9d2136f32c7 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/ProviderBasedBrowseStrategy.java @@ -0,0 +1,179 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.strategy; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.papyrus.infra.tools.util.ListHelper; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; +import org.eclipse.papyrus.infra.widgets.providers.IHierarchicContentProvider; + + +public class ProviderBasedBrowseStrategy extends EncapsulatedContentProvider implements TreeBrowseStrategy { + + protected ITreeContentProvider provider; + + protected boolean filterElements = false; + + protected final Map<Object, Boolean> cache = new HashMap<Object, Boolean>(); + + protected final Map<Object, Boolean> visibleChildCache = new HashMap<Object, Boolean>(); + + public ProviderBasedBrowseStrategy(ITreeContentProvider provider) { + setProvider(provider); + } + + public ProviderBasedBrowseStrategy() { + + } + + public void setProvider(ITreeContentProvider provider) { + encapsulated = provider; + this.provider = provider; + filterElements = provider instanceof IHierarchicContentProvider; + clearCache(); + } + + @Override + public Object[] getElements() { + return getValidElements(super.getElements()); + } + + @Override + public Object[] getElements(Object inputElement) { + return getValidElements(super.getElements(inputElement)); + } + + /** + * Filters the valid root elements, ie. the root elements containing + * at least one valid child (Or being valid themselves) + * + * @param roots + * @return + */ + protected Object[] getValidElements(Object[] roots) { + if (filterElements) { + List<Object> rootsList = ListHelper.asList(roots); + Iterator<?> iterator = rootsList.iterator(); + while (iterator.hasNext()) { + if (!isValid(iterator.next(), new HashSet<Object>())) { + iterator.remove(); + } + } + return rootsList.toArray(); + } + + return roots; + } + + @Override + public Object[] getChildren(Object parent) { + if (provider == null) { + Activator.log.warn("The provider has not been initialized"); + return new Object[0]; + } + + return getValidElements(super.getChildren(parent)); + } + + @Override + public boolean hasChildren(Object parent) { + // May be expensive + return getChildren(parent).length > 0; + } + + protected boolean isValid(Object containerElement, Set<Object> visitedElements) { + if (!cache.containsKey(containerElement)) { + boolean isVisible; + + if (browseElement(containerElement)) { + isVisible = isValidValue(containerElement) || hasOneVisibleChild(containerElement, visitedElements); + } else { + isVisible = false; + } + + cache.put(containerElement, isVisible); + } + return cache.get(containerElement); + } + + protected boolean browseElement(Object containerElement) { + return true; + } + + protected boolean hasOneVisibleChild(Object element, Set<Object> visitedElements) { + if (!visibleChildCache.containsKey(element)) { + boolean result = false; + if (visitedElements.add(getAdaptedValue(element))) { + for (Object child : super.getChildren(element)) { + if (isValid(child, visitedElements)) { + result = true; + break; + } + } + } + + visibleChildCache.put(element, result); + } + return visibleChildCache.get(element); + } + + @Override + public TreePath findPath(Object semanticElement, Object[] rootElements) { + return TreePath.EMPTY; // TODO : Naive search + } + + protected void clearCache() { + cache.clear(); + visibleChildCache.clear(); + } + + @Override + public void dispose() { + super.dispose(); + clearCache(); + } + + /** + * {@inheritDoc} + * + * The basic implementation is a naive tree search + * + * @param elementToReveal + */ + @Override + public void revealSemanticElement(List<?> elementsToReveal) { + if (viewer != null) { + // FIXME: TreeViewers cannot do this search when the items have not yet be expanded. + // We need to search on the ContentProvider and pass a TreeSelection to the viewer + viewer.setSelection(new StructuredSelection(elementsToReveal), true); + } + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + super.inputChanged(viewer, oldInput, newInput); + this.viewer = viewer; + } + + protected Viewer viewer; +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/StrategyBasedContentProvider.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/StrategyBasedContentProvider.java new file mode 100644 index 00000000000..c32540fa59e --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/StrategyBasedContentProvider.java @@ -0,0 +1,100 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.strategy; + +import java.util.List; + +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider; + +public class StrategyBasedContentProvider extends EncapsulatedContentProvider { + + protected TreeBrowseStrategy browseStrategy; + + protected TreeBrowseStrategy revealStrategy; + + protected StructuredViewer viewer; + + public StrategyBasedContentProvider(TreeBrowseStrategy browseStrategy, TreeBrowseStrategy revealStrategy) { + setRevealStrategy(revealStrategy); + setBrowseStrategy(browseStrategy); + } + + public void setBrowseStrategy(TreeBrowseStrategy strategy) { + if (strategy != null) { + browseStrategy = strategy; + encapsulated = browseStrategy; + } + } + + public void setRevealStrategy(TreeBrowseStrategy strategy) { + if (strategy != null) { + revealStrategy = strategy; + } + } + + @Override + public void dispose() { + super.dispose(); + if (browseStrategy != null) { + browseStrategy.dispose(); + } + if (revealStrategy != null) { + revealStrategy.dispose(); + } + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + super.inputChanged(viewer, oldInput, newInput); + if (viewer instanceof StructuredViewer) { + this.viewer = (StructuredViewer) viewer; + } else { + this.viewer = null; + } + + revealStrategy.inputChanged(viewer, oldInput, newInput); + browseStrategy.inputChanged(viewer, oldInput, newInput); + } + + /** + * {@inheritDoc} + * + * Reveals and selects the given semantic elements + */ + @Override + public void revealSemanticElement(List<?> semanticElementsList) { + revealStrategy.revealSemanticElement(semanticElementsList); + // List<Object> containerElements = new LinkedList<Object>(); + // + // for(Object semanticElement : semanticElementsList) { + // TreePath path = revealStrategy.findPath(semanticElement, getElements(viewer.getInput())); + // if(path.getSegmentCount() > 0) { + // viewer.reveal(path); + // containerElements.add(path.getLastSegment()); + // } + // } + // + // viewer.setSelection(new StructuredSelection(containerElements)); + } + + @Override + public TreeBrowseStrategy getBrowseStrategy() { + return browseStrategy; + } + + @Override + public TreeBrowseStrategy getRevealStrategy() { + return revealStrategy; + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/TreeBrowseStrategy.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/TreeBrowseStrategy.java new file mode 100644 index 00000000000..5d66c6f5262 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/TreeBrowseStrategy.java @@ -0,0 +1,39 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.strategy; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.papyrus.infra.widgets.util.IRevealSemanticElement; + + +/** + * An interface to define a strategy for browsing a Tree + * + * @author Camille Letavernier + */ +public interface TreeBrowseStrategy extends ITreeContentProvider, IRevealSemanticElement { + + /** + * Finds a path to the given element + * + * @param element + * The semanticElement to find + * @parem input + * The root Elements + * @return + * @deprecated See {@link #revealSemanticElement(java.util.List)} instead + */ + @Deprecated + public TreePath findPath(Object semanticElement, Object[] roots); + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/WorkspaceRevealStrategy.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/WorkspaceRevealStrategy.java new file mode 100644 index 00000000000..f08c5a76ddf --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/strategy/WorkspaceRevealStrategy.java @@ -0,0 +1,77 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.strategy; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; + +/** + * A Strategy to search for a Resource in the Workspace + * + * @author Camille Letavernier + * + */ +public class WorkspaceRevealStrategy extends ProviderBasedBrowseStrategy { + + public WorkspaceRevealStrategy(ITreeContentProvider provider) { + super(provider); + } + + public WorkspaceRevealStrategy() { + super(); + } + + @Override + public void revealSemanticElement(List<?> elementsToReveal) { + if (viewer instanceof TreeViewer) { + TreeViewer treeViewer = (TreeViewer) viewer; + TreePath[] paths = new TreePath[elementsToReveal.size()]; + int i = 0; + + List<?> roots = Arrays.asList(getElements()); + + for (Object elementToReveal : elementsToReveal) { + LinkedList<IResource> segments = new LinkedList<IResource>(); + + if (elementToReveal instanceof IResource) { + IResource currentElement = (IResource) elementToReveal; + + segments.add(currentElement); + + currentElement = currentElement.getParent(); + while (currentElement != null) { + segments.addFirst(currentElement); + + if (roots.contains(currentElement)) { + break; // If the tree root is not the Workspace Root, stop now + } + currentElement = currentElement.getParent(); + } + } + + paths[i++] = new TreePath(segments.toArray()); + } + + TreeSelection selection = new TreeSelection(paths); + treeViewer.setSelection(selection, true); + } else { + super.revealSemanticElement(elementsToReveal); + } + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/DoNothingCompletionProposal.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/DoNothingCompletionProposal.java new file mode 100644 index 00000000000..b37f22846f5 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/DoNothingCompletionProposal.java @@ -0,0 +1,146 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.util; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; + +/** + * @author VL222926 + * + */ +public class DoNothingCompletionProposal implements ICompletionProposal { + /** The string to be displayed in the completion proposal popup. */ + private String fDisplayString; + /** The replacement string. */ + private String fReplacementString; + /** The replacement offset. */ + private int fReplacementOffset; + // /** The replacement length. */ + private int fReplacementLength; + /** The cursor position after this proposal has been applied. */ + private int fCursorPosition; + /** The image to be displayed in the completion proposal popup. */ + private Image fImage; + /** The context information of this proposal. */ + private IContextInformation fContextInformation; + /** The additional info of this proposal. */ + private String fAdditionalProposalInfo; + + /** + * Creates a new completion proposal based on the provided information. The replacement string is + * considered being the display string too. All remaining fields are set to <code>null</code>. + * + * @param replacementString + * the actual string to be inserted into the document + * @param replacementOffset + * the offset of the text to be replaced + * @param replacementLength + * the length of the text to be replaced + * @param cursorPosition + * the position of the cursor following the insert relative to replacementOffset + */ + public DoNothingCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition) { + this(replacementString, replacementOffset, replacementLength, cursorPosition, null, null, null, null); + } + + /** + * Creates a new completion proposal. All fields are initialized based on the provided information. + * + * @param replacementString + * the actual string to be inserted into the document + * @param replacementOffset + * the offset of the text to be replaced + * @param replacementLength + * the length of the text to be replaced + * @param cursorPosition + * the position of the cursor following the insert relative to replacementOffset + * @param image + * the image to display for this proposal + * @param displayString + * the string to be displayed for the proposal + * @param contextInformation + * the context information associated with this proposal + * @param additionalProposalInfo + * the additional information associated with this proposal + */ + public DoNothingCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo) { + Assert.isNotNull(replacementString); + Assert.isTrue(replacementOffset >= 0); + Assert.isTrue(replacementLength >= 0); + Assert.isTrue(cursorPosition >= 0); + + fReplacementString = replacementString; + fReplacementOffset = replacementOffset; + fReplacementLength = replacementLength; + fCursorPosition = cursorPosition; + fImage = image; + fDisplayString = displayString; + fContextInformation = contextInformation; + fAdditionalProposalInfo = additionalProposalInfo; + } + + /** + * + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) + * + * @param document + */ + public void apply(IDocument document) { + // nothing to do + } + + /* + * @see ICompletionProposal#getSelection(IDocument) + */ + public Point getSelection(IDocument document) { + return new Point(fReplacementOffset + fCursorPosition, 0); + } + + /* + * @see ICompletionProposal#getContextInformation() + */ + public IContextInformation getContextInformation() { + return fContextInformation; + } + + /* + * @see ICompletionProposal#getImage() + */ + public Image getImage() { + return fImage; + + } + + /* + * @see ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + if (fDisplayString != null) + return fDisplayString; + return fReplacementString; + } + + /* + * @see ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + return fAdditionalProposalInfo; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/FileUtil.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/FileUtil.java new file mode 100644 index 00000000000..13831478833 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/FileUtil.java @@ -0,0 +1,112 @@ +/***************************************************************************** + * Copyright (c) 2011 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.util; + +import java.io.File; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.editors.StringFileSelector; + +/** + * A helper class for resolving files and path, either in the workspace or + * on the File system + * + * @author Camille Letavernier + * @see StringFileSelector + */ +public class FileUtil { + + /** + * Returns the path to the IFile. If absolute is true, returns the path + * from the FileSystem. Otherwise, returns the path from the workspace. + * + * @param file + * @param absolute + * @return + */ + public static String getPath(IFile file, boolean absolute) { + if (absolute) { + return file.getLocation().toString(); + } + return file.getFullPath().toString(); + } + + /** + * Returns the IFile (Workspace file) from the given location. + * The location may be either absolute (From the FileSystem) or + * relative to the workspace root. + * + * @param location + * @return + */ + public static IFile getIFile(String location) { + // Search the file in the workspace + IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot(); + IPath path = new Path(location); + IFile currentFile = null; + try { + currentFile = workspace.getFile(path); + } catch (IllegalArgumentException ex) { + // Ignore + } + + // Then search it on the disk + if (currentFile == null || !currentFile.exists()) { + currentFile = workspace.getFileForLocation(path); + } + + return currentFile; + } + + /** + * Returns the Java File from the given location. + * The location may be either absolute (From the FileSystem) or + * relative to the workspace root. + * + * @param location + * @return + */ + public static File getFile(String location) { + IFile iFile = getIFile(location); + if (iFile == null || !iFile.exists()) { + return new File(location); + } + + return new File(iFile.getLocationURI()); + } + + /** + * Returns the Java File from the given location. + * The location is relative to the workspace root. + * + * @param location + * @return + */ + public static File getWorkspaceFile(String location) { + IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot(); + IPath path = new Path(location); + IFile currentFile = null; + try { + currentFile = workspace.getFile(path); + } catch (IllegalArgumentException ex) { + Activator.log.error(ex); + return null; + } + + return currentFile.getLocation().toFile(); + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/INameResolutionHelper.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/INameResolutionHelper.java new file mode 100644 index 00000000000..727c9c6b46e --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/INameResolutionHelper.java @@ -0,0 +1,50 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.util; + +import java.util.List; + +/** + * Common interface to use to find elements from a given string + * + */ +public interface INameResolutionHelper { + + /** + * + * @param aString + * a string + * @return + * all elements whose the name starts with this string, or all found element if the string is <code>null</code> or empty + */ + public List<?> getMatchingElements(final String aString); + + /** + * + * @param aString + * a string + * @return + * all elements which have the wanted string as (qualified) name + */ + public List<?> getElementsByName(final String aString); + + + /** + * @param namedElement + * @return + * the shortest qualified to use for the element + */ + public List<String> getShortestQualifiedNames(Object element); + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/IPapyrusConverter.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/IPapyrusConverter.java new file mode 100644 index 00000000000..0d24d7b1d9b --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/IPapyrusConverter.java @@ -0,0 +1,164 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.util; + +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; + +/** + * @author VL222926 + * + * This class provides method to convert Object to a string to edit or a string to display and vice-versa from a string to edit or to display to the real object + * + */ +public interface IPapyrusConverter extends INameResolutionHelper { + + // the previous regex,which did not allow to get 'Class, when the user asked for the completion and + // PLEASE DO NOT ERASE THIS COMMENT + // public static final String FIND_PART_NAME_REGEX = "([^'\\x2C]+)|('[^']+')"; //$NON-NLS-1$ + + /** + * regex used to parse string on , and ',': + */ + public static final String FIND_PART_NAME_REGEX = "([^'\\x2C]+)|('[^']+')|('(([^']*[\\x2C][^']*)))"; //$NON-NLS-1$ + + /** + * the string delimiter + */ + public static final String STRING_DELIMITER = "\'"; //$NON-NLS-1$ + + /** + * the string separator for multivalued properties + */ + public static final String STRING_SEPARATOR = ","; //$NON-NLS-1$ + + /** + * the string used for <code>null</code> value + */ + public static final String UNDEFINED_VALUE = "<Undefined>";//$NON-NLS-1$ + + /** + * add this string to the suggestions when there are more than {@link #MAX_ELEMENTS_TO_DISPLAY} + */ + public static final String MORE_ELEMENTS = "...";//$NON-NLS-1$ + + /** + * empty string + */ + public static final String EMPTY_STRING = "";//$NON-NLS-1$ + + /** + * + * @param multiValueAsString + * the full String write in the StyledText + * @return + * a map with the name of the elements as value and the start and the end index of the name in the typed text as key + */ + public Map<List<Integer>, String> getSubStringsWithTheirPositions(String multiValueAsString); + + /** + * + * @param multiValueAsString + * a string + * @return + * all substring according to the applied regex + */ + public List<String> splitFullStringToSubElementString(String multiValueAsString); + + /** + * + * @param aString + * a string + * @return + * a istatus indicating if the string is valid or not + */ + public IStatus isValidEditString(String aString); + + /** + * Returns the parser's content assist processor + * + * @param element + * the element + * @return the content assist processor + */ + public IContentAssistProcessor getCompletionProcessor(IAdaptable element); + + + /** + * + * @param object + * an object + * @param flag + * a flag which could be used for for the name qualification for example + * @return + * the string to display (label) representing the object + */ + public String canonicalToDisplayValue(Object object, int flag); + + /** + * + * @param object + * an object + * @param flag + * a flag which could be used for for the name qualification for example + * @return + * the string to edit (label) representing the object + */ + public String canonicalToEditValue(Object object, int flag); + + /** + * + * @param string + * a display string + * @param flag + * a flag which could be used for for the name qualification for example + * @return + * the object represented by the displayed string + */ + public Object displayToCanonicalValue(String string, int flag); + + /** + * + * @param string + * an edited string + * @param flag + * a flag which could be used for for the name qualification for example + * @return + * the object represented by the edited string + */ + public Object editToCanonicalValue(String string, int flag); + + /** + * + * @param string + * an edited string + * @return + * the the equivalent string to use for edition + */ + public String editToDisplayValue(String string); + + /** + * + * @param string + * a displayed string + * @return + * the the equivalent string to use for + */ + public String displayToEditValue(String string); + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/IRevealSemanticElement.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/IRevealSemanticElement.java new file mode 100644 index 00000000000..9b42bdd5de5 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/IRevealSemanticElement.java @@ -0,0 +1,34 @@ +/***************************************************************************** + * Copyright (c) 2010 CEA LIST. + * + * + * 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: + * Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation + */ +package org.eclipse.papyrus.infra.widgets.util; + +import java.util.List; + +/** + * this interface is used to reveal element that are given in parameter. Example + * of the use case: the class that implements this interface can be a diagram + * that select all editparts that are linked to the given list of semantic + * element + * + */ +public interface IRevealSemanticElement { + + /** + * reveal all elements that represent an element in the given list. + * + * @param elementList + * list of semantic element that we want to reveal, <B> cannot be + * null</B> + */ + public void revealSemanticElement(List<?> elementList); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ISetNameResolutionHelper.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ISetNameResolutionHelper.java new file mode 100644 index 00000000000..104bfabd7df --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ISetNameResolutionHelper.java @@ -0,0 +1,30 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.util; + +import org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper; + +/** + * Interface used to declare a ISNameResolutionHelper + * + */ +public interface ISetNameResolutionHelper { + + /** + * + * @param helper + * a name resolution helper + */ + public void setNameResolutionHelper(INameResolutionHelper helper); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ISetPapyrusConverter.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ISetPapyrusConverter.java new file mode 100644 index 00000000000..4da7e5a75eb --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ISetPapyrusConverter.java @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.util; + +/** + * @author Vincent Lorenzo + * + */ +public interface ISetPapyrusConverter { + + /** + * + * @param converter + * the papyrus converter to use + */ + public void setPapyrusConverter(IPapyrusConverter converter); + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ImageConstants.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ImageConstants.java new file mode 100644 index 00000000000..742698a5a4d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ImageConstants.java @@ -0,0 +1,40 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.util; + +/** + * @author VL222926 + * + */ +public class ImageConstants { + + /** + * Constructor. + * + */ + private ImageConstants() { + // to prevent instanciation + } + + /** + * the local path to get the papyrus icon + */ + public static final String PAPYRUS_ICON_PATH = "/icons/papyrus.png"; //$NON-NLS-1$ + + /** + * the local path to get the edit icon in 12x12 + */ + public static final String EDIT_12_12_ICON_PATH = "/icons/Edit_12x12.gif";//$NON-NLS-1$ + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ImageDescriptorManager.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ImageDescriptorManager.java new file mode 100644 index 00000000000..31c5cfbc3e5 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ImageDescriptorManager.java @@ -0,0 +1,40 @@ +/** + * + */ +package org.eclipse.papyrus.infra.widgets.util; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.resource.ImageDescriptor; + +/** + * Manager for ImageDescriptor by keys + */ +public class ImageDescriptorManager { + + protected Map<ImageDescriptor, String> imageDescriptor2Key = new HashMap<ImageDescriptor, String>(); + + protected int value; + + public void reset() { + imageDescriptor2Key.clear(); + } + + public String getKey(ImageDescriptor descriptor) { + String key = null; + if (!imageDescriptor2Key.containsKey(descriptor)) { + key = computeKey(descriptor); + imageDescriptor2Key.put(descriptor, key); + } else { + key = imageDescriptor2Key.get(descriptor); + } + return key; + } + + protected String computeKey(ImageDescriptor descriptor) { + return "" + descriptor.hashCode(); + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/MultiplicityConstants.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/MultiplicityConstants.java new file mode 100644 index 00000000000..69b6372375d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/MultiplicityConstants.java @@ -0,0 +1,45 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST. + * + * 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: + * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue@all4tec.net - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.util; + +/** + * The multiplicity constants. + */ +public interface MultiplicityConstants { + + /** + * The multiplicity editor preference identifier. + */ + public static final String MULTIPLICITY_EDITOR_MODE = "multiplicityEditorMode"; //$NON-NLS-1$ + + /** + * The simple mode preference identifier. + */ + public static final String SIMPLE_MODE = "simpleMode"; //$NON-NLS-1$ + + /** + * The simple mode text value display. + */ + public static final String SIMPLE_MODE_TEXT_VALUE = "Simple mode"; //$NON-NLS-1$ + + /** + * The advanced mode preference identifier. + */ + public static final String ADVANCED_MODE = "advanceMode"; //$NON-NLS-1$ + + /** + * The advanced mode text value display. + */ + public static final String ADVANCED_MODE_TEXT_VALUE = "Advanced mode"; //$NON-NLS-1$ + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/NavigationTarget.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/NavigationTarget.java new file mode 100644 index 00000000000..4cf5461ddf0 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/NavigationTarget.java @@ -0,0 +1,47 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.util; + +import java.util.Collection; + +/** + * This interface is used to select and reveal element that are given in parameter. Example + * of the use case: the class that implements this interface can be a diagram + * that select all editparts that are linked to the given list of elements. + * + * The element parameter can be either a semantic element (Which will likely be wrapped + * in a graphical element such as an EditPart), or a notation element (Such as a GMF notation::View) + */ +public interface NavigationTarget { + + /** + * Select and reveal the given element. Element may be either a semantic element (e.g. a uml::Class) + * or a graphical element (e.g. GMF notation::View) + * + * @param element + * @return + * True if the element has been selected, false otherwise + */ + public boolean revealElement(Object element); + + /** + * Select and reveal the given elements. Elements may be either semantic elements (e.g. uml::Class) + * or graphical elements (e.g. GMF notation::View) + * + * @param elements + * @return + * True if the elements have been selected, false otherwise + */ + public boolean revealElement(Collection<?> elements); +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/PopupButtonMenu.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/PopupButtonMenu.java new file mode 100644 index 00000000000..78ea06876d4 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/PopupButtonMenu.java @@ -0,0 +1,88 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.util; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Menu; + + +/** + * A pop-up menu to attach to buttons, which presents a flat menu of actions for the user to choose from. + */ +public class PopupButtonMenu { + + private final Button button; + + private MenuManager menu; + + + /** + * Initializes me with a button on which to present the pop-up menu. + * + * @param button + * the button on which I attach a pop-up menu + */ + public PopupButtonMenu(Button button) { + this.button = button; + + initialize(); + } + + /** + * Add an action to the drop-down menu. Note that this explicitly excludes nested menu structures. + * + * @param action + * an action to add to the menu + */ + public void addAction(IAction action) { + menu.add(action); + } + + private void initialize() { + menu = new MenuManager(); + + button.addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + if (menu != null) { + menu.dispose(); + menu = null; + } + } + }); + + button.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + showMenu(e.x, e.y); + } + }); + } + + private void showMenu(int x, int y) { + if (menu != null) { + Menu menu = this.menu.createContextMenu(button); + // don't set the menu as the button's context menu! We don't want right-click to show it + + menu.setLocation(button.toDisplay(x, y)); + menu.setVisible(true); + } + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/RevealResultCommand.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/RevealResultCommand.java new file mode 100644 index 00000000000..eb020577ef4 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/RevealResultCommand.java @@ -0,0 +1,220 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST, Christian W. Damus, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.fr - Initial API and implementation + * Christian W. Damus - bug 436954 + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.util; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.command.CommandWrapper; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IViewPart; + +/** + * Wrapper to reveal the results (using with reveal semantic protocol) after a command in View. + * + * @author Gabriel Pascual + */ +public class RevealResultCommand extends CommandWrapper { + + /** The view part. */ + private IViewPart viewPart = null; + + /** The source object. */ + private Object sourceObject = null; + + /** The reveal all results. */ + private boolean revealAllResults = false; + + /** + * Constructor. + * + * @param command + */ + public RevealResultCommand(Command command, IViewPart part, Object editObject) { + super(command); + viewPart = part; + sourceObject = editObject; + } + + /** + * Sets the reveal all results. + * + * @param revealAllResults + * the revealAllResults to set + */ + private void setRevealAllResults(boolean revealAllResults) { + this.revealAllResults = revealAllResults; + } + + /** + * Wrap. + * + * @param command + * the command + * @param part + * the part + * @param container + * the container + * @param revealAllResults + * the reveal all results + * @return the command + */ + public static Command wrap(Command command, IViewPart part, EObject container, boolean revealAllResults) { + RevealResultCommand wrappedCommand = new RevealResultCommand(command, part, container); + wrappedCommand.setRevealAllResults(revealAllResults); + return wrappedCommand; + } + + /** + * Wrap. + * + * @param command + * the command + * @param part + * the part + * @param container + * the container + * @return the command + */ + public static Command wrap(Command command, IViewPart part, EObject container) { + return new RevealResultCommand(command, part, container); + } + + /** + * Wrap. + * + * @param command + * the command + * @param part + * the part + * @return the command + */ + public static Command wrap(Command command, IViewPart part) { + return wrap(command, part, null); + } + + /** + * @see org.eclipse.emf.common.command.CommandWrapper#execute() + * + */ + @Override + public void execute() { + + super.execute(); + selectResult(); + } + + /** + * @see org.eclipse.emf.common.command.CommandWrapper#undo() + * + */ + @Override + public void undo() { + super.undo(); + selectSource(); + } + + /** + * @see org.eclipse.emf.common.command.CommandWrapper#redo() + * + */ + @Override + public void redo() { + super.redo(); + selectResult(); + } + + /** + * Reveal target. + * + * @param target + * the target + */ + private void revealTarget(final List<?> target) { + Display.getCurrent().asyncExec(new Runnable() { + + @Override + public void run() { + + if (viewPart instanceof IRevealSemanticElement) { + ((IRevealSemanticElement) viewPart).revealSemanticElement(target); + + } + + } + }); + } + + /** + * Select command result. + */ + private void selectResult() { + Collection<?> results = getResultsCommand(); + if (!results.isEmpty()) { + if (revealAllResults) { + revealTarget(Arrays.asList(results.toArray())); + + } else { + + + Iterator<?> resultIterator = results.iterator(); + + // Get first result + final Object result = resultIterator.next(); + revealTarget(Arrays.asList(new Object[] { result })); + } + + } + } + + /** + * Gets the results command. + * + * @return the results command + */ + private Collection<?> getResultsCommand() { + + // Get results list + Collection<?> resultsCommand = getResult(); + if (getResult().isEmpty()) { + + // Get affected objects list if it is not a command with result + resultsCommand = getAffectedObjects(); + } + + return resultsCommand; + } + + /** + * Select source. + */ + private void selectSource() { + + if (sourceObject != null) { + revealTarget(Arrays.asList(new Object[] { sourceObject })); + + } else if (!getAffectedObjects().isEmpty()) { + + // Try with the affected objects + revealTarget(Arrays.asList(getAffectedObjects().toArray())); + } + } + + +}
\ No newline at end of file diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/RevealSemanticElementWrapper.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/RevealSemanticElementWrapper.java new file mode 100644 index 00000000000..855ff9f5661 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/RevealSemanticElementWrapper.java @@ -0,0 +1,45 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.util; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; + +/** + * A wrapper to convert a IRevealSemanticElement to an INavigationTarget + * + * @author Camille Letavernier + * + */ +public class RevealSemanticElementWrapper implements NavigationTarget { + + private final IRevealSemanticElement revealSemanticElement; + + public RevealSemanticElementWrapper(IRevealSemanticElement revealSemanticElement) { + this.revealSemanticElement = revealSemanticElement; + } + + @Override + public boolean revealElement(Object element) { + return revealElement(Collections.singletonList(element)); + } + + @Override + public boolean revealElement(Collection<?> elements) { + revealSemanticElement.revealSemanticElement(new LinkedList<Object>(elements)); + return false; + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ValueUtils.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ValueUtils.java new file mode 100644 index 00000000000..208d533a677 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/ValueUtils.java @@ -0,0 +1,34 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.util; + +/** + * @author VL222926 + * + */ +public class ValueUtils { + + /** + * Constructor. + * + */ + private ValueUtils() { + // to prevent instanciation + } + + /** + * value used to identify feature with multiplicity to * + */ + public static final int MANY = -1; +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/AbstractValidator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/AbstractValidator.java new file mode 100644 index 00000000000..d21390be40d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/AbstractValidator.java @@ -0,0 +1,48 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.papyrus.infra.widgets.Activator; + +/** + * An abstract implementation of the IValidator interface + * + * @author Camille Letavernier + * + */ +public abstract class AbstractValidator implements IValidator { + + protected String pluginId; + + public void setPluginID(String pluginId) { + this.pluginId = pluginId; + } + + protected IStatus error(String message) { + return new Status(IStatus.ERROR, getPluginId(), message); + } + + public String getPluginId() { + if (pluginId == null) { + return Activator.PLUGIN_ID; + } else { + return pluginId; + } + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/BooleanInputValidator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/BooleanInputValidator.java new file mode 100644 index 00000000000..d1354a53d3d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/BooleanInputValidator.java @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + + +/** + * InputValidator for boolean + * + * @author Vincent Lorenzo + * + */ +public class BooleanInputValidator extends InputValidatorWrapper { + + public BooleanInputValidator() { + super(new BooleanValidator()); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/BooleanValidator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/BooleanValidator.java new file mode 100644 index 00000000000..26ef894a65c --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/BooleanValidator.java @@ -0,0 +1,51 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Modification to match IValidator + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.papyrus.infra.tools.util.BooleanHelper; +import org.eclipse.papyrus.infra.widgets.messages.Messages; + +/** + * InputValidator for boolean + * + * @author Vincent Lorenzo + * + */ +public class BooleanValidator extends AbstractValidator { + + + /** + * + * @param newValue + * @return {@link Status#OK_STATUS} if the newValue is valid and {@link IStatus#ERROR} when newValue is + * invalid + */ + @Override + public IStatus validate(Object newValue) { + if (newValue instanceof Boolean) { + return Status.OK_STATUS; + } + + if (newValue instanceof String && BooleanHelper.isBoolean((String) newValue)) { + return Status.OK_STATUS; + } + + return error(Messages.BooleanInputValidator_NotABoolean); + + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/InputValidatorWrapper.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/InputValidatorWrapper.java new file mode 100644 index 00000000000..0a23bbde936 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/InputValidatorWrapper.java @@ -0,0 +1,45 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.dialogs.IInputValidator; + +/** + * A Wrapper for IValidator to IInputValidator + * + * @author Camille Letavernier + */ +public class InputValidatorWrapper implements IInputValidator { + + protected IValidator validator; + + public InputValidatorWrapper(IValidator validator) { + Assert.isNotNull(validator); + this.validator = validator; + } + + @Override + public String isValid(String newText) { + IStatus status = validator.validate(newText); + if (status.isOK()) { + return null; + } + + return status.getMessage(); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/IntegerInputValidator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/IntegerInputValidator.java new file mode 100644 index 00000000000..2292a1f00a6 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/IntegerInputValidator.java @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + + + +/** + * Validator for Integer + * + */ +public class IntegerInputValidator extends InputValidatorWrapper { + + + public IntegerInputValidator() { + super(new IntegerValidator()); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/IntegerValidator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/IntegerValidator.java new file mode 100644 index 00000000000..aedb919bea9 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/IntegerValidator.java @@ -0,0 +1,55 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Modification to match IValidator + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.papyrus.infra.widgets.messages.Messages; + +/** + * InputValidator for Integer + * + * @author Vincent Lorenzo + * + */ +public class IntegerValidator extends AbstractValidator { + + + /** + * + * @param newValue + * @return {@link Status#OK_STATUS} if the newValue is valid and {@link IStatus#ERROR} when newValue is + * invalid + */ + @Override + public IStatus validate(Object newValue) { + if (newValue instanceof Integer) { + return Status.OK_STATUS; + } + + if (newValue instanceof String) { + try { + Integer.parseInt((String) newValue); + return Status.OK_STATUS; + } catch (NumberFormatException ex) { + return error(Messages.IntegerInputValidator_NotAnIntegerMessage); + } + } + + return error(Messages.IntegerInputValidator_NotAnIntegerMessage); + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/RealInputValidator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/RealInputValidator.java new file mode 100644 index 00000000000..db187dfbd6d --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/RealInputValidator.java @@ -0,0 +1,26 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + + +/** + * Validator for the Real + */ +public class RealInputValidator extends InputValidatorWrapper { + + public RealInputValidator() { + super(new RealValidator()); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/RealValidator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/RealValidator.java new file mode 100644 index 00000000000..eda02e90576 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/RealValidator.java @@ -0,0 +1,52 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Modification to match IValidator + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.papyrus.infra.widgets.messages.Messages; + +/** + * Validator for the Real + */ +public class RealValidator extends AbstractValidator { + + + /** + * + * @param newValue + * @return {@link Status#OK_STATUS} if the newValue is valid and {@link IStatus#ERROR} when newValue is + * invalid + */ + @Override + public IStatus validate(Object newValue) { + if (newValue instanceof Double) { + return Status.OK_STATUS; + } + + if (newValue instanceof String) { + try { + Double.parseDouble((String) newValue); + return Status.OK_STATUS; + } catch (NumberFormatException ex) { + return error(Messages.RealInputValidator_NotaRealMessage); + } + } + + return error(Messages.RealInputValidator_NotaRealMessage); + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/UnlimitedNaturalInputValidator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/UnlimitedNaturalInputValidator.java new file mode 100644 index 00000000000..0d25097e25e --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/UnlimitedNaturalInputValidator.java @@ -0,0 +1,26 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + + +/** + * Validator for the UnlimitedNaturalEditor. It accepts "-1", "*" and all integer >=0 + */ +public class UnlimitedNaturalInputValidator extends InputValidatorWrapper { + + public UnlimitedNaturalInputValidator() { + super(new UnlimitedNaturalValidator()); + } + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/UnlimitedNaturalValidator.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/UnlimitedNaturalValidator.java new file mode 100644 index 00000000000..1b62638959f --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/validator/UnlimitedNaturalValidator.java @@ -0,0 +1,100 @@ +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Modification to match IValidator + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.widgets.validator; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.papyrus.infra.widgets.messages.Messages; + +/** + * Validator for the UnlimitedNaturalEditor. It accepts "-1", "*" and all integer >=0 + */ +public class UnlimitedNaturalValidator extends AbstractValidator { + + + public static final String INFINITE_STAR = "*"; //$NON-NLS-1$ + + public static final String INFINITE_MINUS_ONE = "-1"; //$NON-NLS-1$ + + + /** + * @see org.eclipse.jface.dialogs.IInputValidator#isValid(java.lang.String) + * + * @param newText + * @return <code>null</code> if the newText is valid an error message when newText is + * invalid + */ + public String isValid(String newText) { + if (INFINITE_STAR.equals(newText) || INFINITE_MINUS_ONE.equals(newText)) { + return null; + } + boolean isValid = true; + try { + Integer myUnlimitedNatural = Integer.valueOf(newText); + if (myUnlimitedNatural < -1) { + isValid = false; + } + } catch (NumberFormatException e) { + isValid = false; + } + + if (!isValid) { + return Messages.UnlimitedNaturalInputValidator_NotAnUnlimitedNaturalMessage; + } + return null; + } + + /** + * + * @param newValue + * @return {@link Status#OK_STATUS} if the newValue is valid and {@link IStatus#ERROR} when newValue is + * invalid + */ + @Override + public IStatus validate(Object newValue) { + if (newValue instanceof Integer) { + int value = (Integer) newValue; + if (value == -1 || value >= 0) { + return Status.OK_STATUS; + } + } + + if (newValue instanceof String) { + String newText = (String) newValue; + + if (INFINITE_STAR.equals(newText) || INFINITE_MINUS_ONE.equals(newText)) { + return Status.OK_STATUS; + } + + boolean isValid = true; + try { + Integer myUnlimitedNatural = Integer.parseInt(newText); + if (myUnlimitedNatural < -1) { + isValid = false; + } + } catch (NumberFormatException e) { + isValid = false; + } + + if (isValid) { + return Status.OK_STATUS; + } + } + + return error(Messages.UnlimitedNaturalInputValidator_NotAnUnlimitedNaturalMessage); + } + + +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/widgets/MultipleValueEditAndSelectionWidget.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/widgets/MultipleValueEditAndSelectionWidget.java new file mode 100644 index 00000000000..7d91e2d5e21 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/widgets/MultipleValueEditAndSelectionWidget.java @@ -0,0 +1,168 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.widgets; + +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelector; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.util.ImageConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +/** + * @author VL222926 + * + */ +public class MultipleValueEditAndSelectionWidget extends MultipleValueSelectionWidget { + + /** + * if <code>true</code> the edition button will be displayed + */ + private boolean allowEdition; + + + /** + * The edit action button + */ + protected Button edit; + + /** + * Constructor. + * + * @param selector + */ + public MultipleValueEditAndSelectionWidget(IElementSelector selector) { + super(selector); + } + + /** + * Constructor. + * + * @param selector + * @param unique + */ + public MultipleValueEditAndSelectionWidget(IElementSelector selector, boolean unique) { + super(selector, unique); + } + + /** + * Constructor. + * + * @param selector + * @param unique + * @param ordered + */ + public MultipleValueEditAndSelectionWidget(IElementSelector selector, boolean unique, boolean ordered) { + super(selector, unique, ordered); + } + + /** + * Constructor. + * + * @param selector + * @param unique + * @param ordered + * @param upperBound + */ + public MultipleValueEditAndSelectionWidget(IElementSelector selector, boolean unique, boolean ordered, int upperBound) { + super(selector, unique, ordered, upperBound); + } + + /** + * @see org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWidget#init() + * + */ + @Override + protected void init() { + super.init(); + // please, keep the default value to false + this.allowEdition = false; + } + + /** + * @return the allowEdition + */ + public boolean isAllowEdition() { + return allowEdition; + } + + /** + * @param allowEdition + * the allowEdition to set + */ + public void setAllowEdition(boolean allowEdition) { + this.allowEdition = allowEdition; + } + + /** + * @see org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWidget#createRightButtonsSection(org.eclipse.swt.widgets.Composite) + * + * @param parent + */ + @Override + protected void createRightButtonsSection(Composite parent) { + super.createRightButtonsSection(parent); + if (isAllowEdition()) { + this.edit = new Button(rightButtonsSection, SWT.PUSH); + edit.setImage(Activator.getDefault().getImage(ImageConstants.EDIT_12_12_ICON_PATH)); //$NON-NLS-1$ + edit.addSelectionListener(this); + edit.setToolTipText(Messages.MultipleValueEditAndSelectionWidget_EditSelectedElement); + } + } + + /** + * @see org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWidget#updateControls() + * + */ + @Override + public void updateControls() { + super.updateControls(); + if(allowEdition){ + updateControl(edit, this.factory!=null && this.factory.canEdit()); + } + + } + + /** + * @see org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWidget#widgetSelected(org.eclipse.swt.events.SelectionEvent) + * + * @param e + */ + @Override + public void widgetSelected(SelectionEvent e) { + if (edit != null && e.widget == edit) { + edit(); + this.selectedElementsViewer.refresh(); + } + super.widgetSelected(e); + } + + /** + * + * @return + * <code>true</code> if the selected element can be edited + */ + protected boolean canEdit() { + return allowEdition && this.factory.canEdit(); + } + + /** + * edit the selected element + */ + protected void edit() { + // nothing to do here + } +} diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/widgets/MultipleValueSelectionWidget.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/widgets/MultipleValueSelectionWidget.java new file mode 100644 index 00000000000..eecf456c52a --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/widgets/MultipleValueSelectionWidget.java @@ -0,0 +1,822 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Adapted code from Camille Letavernier (CEA LIST) in MultipleValueSelectorDialog + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.widgets; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelectionListener; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelector; +import org.eclipse.papyrus.infra.widgets.messages.Messages; +import org.eclipse.papyrus.infra.widgets.providers.CollectionContentProvider; +import org.eclipse.papyrus.infra.widgets.util.ValueUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.services.IDisposable; + +/** + * @author VL222926 + * Class extracted from MultipleValueSelectorDialog + * + */ +public class MultipleValueSelectionWidget implements ISelectionChangedListener, IDoubleClickListener, IElementSelectionListener, SelectionListener, IDisposable { + + /** + * The object selector + */ + protected IElementSelector selector; + + /** + * The SWT Composite in which the selector is drawn + */ + protected Composite selectorSection; + + /** + * The add/remove/addAll buttons section + */ + protected Composite buttonsSection; + + /** + * The up/down buttons section + */ + protected Composite rightButtonsSection; + + /** + * The listViewer for chosen elements + */ + protected TreeViewer selectedElementsViewer; + + /** + * The list for chosen elements + */ + protected Tree selectedElements; + + /** + * The add action button + */ + protected Button add; + + /** + * The create action button + */ + protected Button create; + + /** + * The delete action button + */ + protected Button delete; + + /** + * The remove action button + */ + protected Button remove; + + /** + * The add all action button + */ + protected Button addAll; + + /** + * The remove all action button + */ + protected Button removeAll; + + /** + * the up action button + */ + protected Button up; + + /** + * the down action button + */ + protected Button down; + + /** + * The label provider for the listViewer of chosen elements + */ + protected ILabelProvider labelProvider; + + /** + * The currently chosen elements + */ + protected final Collection<Object> allElements; + + /** + * Indicates if the values should be unique (according to Object.equals()) + */ + protected boolean unique; + + /** + * Indicates if the list is ordered + */ + protected boolean ordered; + + /** + * The factory for creating new elements + */ + protected ReferenceValueFactory factory; + + /** + * The model element being edited (if any), to which elements are to be added or removed. + */ + protected Object contextElement; + + /** + * The list of newly created objects + */ + protected Set<Object> newObjects = new HashSet<Object>(); + + + /** + * The maximum number of values selected. + */ + protected int upperBound; + + /** + * the initial selection + */ + protected List<?> initialSelection; + + /** + * Constructor. + * + * @param selector + * The element selector used by this dialog + */ + public MultipleValueSelectionWidget(IElementSelector selector) { + this(selector, false, false); + } + + /** + * + * Constructor. + * + * @param selector + * The element selector used by this dialog + * @param unique + * True if the values returned by this dialog should be unique + */ + public MultipleValueSelectionWidget(IElementSelector selector, boolean unique) { + this(selector, unique, false); + } + + /** + * + * Constructor. + * + * @param selector + * The element selector used by this dialog + * @param unique + * True if the values returned by this dialog should be unique + */ + public MultipleValueSelectionWidget(IElementSelector selector, boolean unique, boolean ordered) { + this(selector, unique, false, ValueUtils.MANY); + } + + /** + * + * Constructor. + * + * @param selector + * The element selector used by this dialog + * @param unique + * True if the values returned by this dialog should be unique + * @param upperBound + * The maximum number of values selected. + */ + public MultipleValueSelectionWidget(IElementSelector selector, boolean unique, boolean ordered, int upperBound) { + Assert.isNotNull(selector, "The element selector should be defined"); //$NON-NLS-1$ + this.selector = selector; + allElements = unique ? new LinkedHashSet<Object>() : new LinkedList<Object>(); + this.unique = unique; + this.ordered = ordered; + this.upperBound = upperBound; + selector.addElementSelectionListener(this); + init(); + } + + /** + * initialize the widget if required + */ + protected void init() { + // nothing to do + } + + /** + * Create the contents of the dialog + * + * @return + * the the composite which encapsulate all the sub composite + */ + public final Composite create(Composite composite) { + Composite parent = createContents(composite); + updateControls(); + return parent; + } + + /** + * Create the contents of the dialog + * + * @return + * the the composite which encapsulate all the sub composite + */ + protected Composite createContents(Composite parent) { + Object parentLayout = parent.getLayout(); + GridLayout layout = null; + if (parentLayout instanceof GridLayout) { + layout = (GridLayout) parentLayout; + } else { + parent = new Composite(parent, SWT.NONE); + layout = new GridLayout(); + parent.setLayout(layout); + } + + layout.numColumns = 2; + layout.makeColumnsEqualWidth = true; + + Composite selectorPane = new Composite(parent, SWT.NONE); + selectorPane.setLayout(new GridLayout(2, false)); + selectorPane.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + Composite selectedPane = new Composite(parent, SWT.NONE); + selectedPane.setLayout(new GridLayout(2, false)); + selectedPane.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + createSelectorSection(selectorPane); + createControlsSection(selectorPane); + createListSection(selectedPane); + createRightButtonsSection(selectedPane); + + allElements.clear(); + allElements.addAll(getInitialElementSelections()); + return parent; + } + + + + + public void setInitialSelections(List<?> selectedElements) { + this.initialSelection = selectedElements; + allElements.clear(); + allElements.addAll(getInitialElementSelections()); + } + + /** + * @return + */ + private Collection<? extends Object> getInitialElementSelections() { + if (this.initialSelection == null) { + return Collections.emptyList(); + } + return this.initialSelection; + } + + /** + * Creates the selector section + * + * @param parent + * The composite in which the section is created + */ + private void createSelectorSection(Composite parent) { + selectorSection = new Composite(parent, SWT.NONE); + selectorSection.setLayout(new FillLayout()); + selectorSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + selector.createControls(selectorSection); + } + + /** + * Creates the main controls section (Add, remove, Add all, remove all) + * + * @param parent + * The composite in which the section is created + */ + private void createControlsSection(Composite parent) { + buttonsSection = new Composite(parent, SWT.NONE); + buttonsSection.setLayout(new GridLayout(1, true)); + + add = new Button(buttonsSection, SWT.PUSH); + add.setImage(Activator.getDefault().getImage("/icons/arrow_right.gif")); //$NON-NLS-1$ + add.addSelectionListener(this); + add.setToolTipText(Messages.MultipleValueSelectorDialog_AddSelectedElements); + + remove = new Button(buttonsSection, SWT.PUSH); + remove.setImage(Activator.getDefault().getImage("/icons/arrow_left.gif")); //$NON-NLS-1$ + remove.addSelectionListener(this); + remove.setToolTipText(Messages.MultipleValueEditor_RemoveSelectedElements); + + addAll = new Button(buttonsSection, SWT.PUSH); + addAll.setImage(Activator.getDefault().getImage("/icons/arrow_double.gif")); //$NON-NLS-1$ + addAll.addSelectionListener(this); + addAll.setToolTipText(Messages.MultipleValueSelectorDialog_AddAllElements); + + /* Disable the bouton 'addAll' if currently chosen elements is greater than the maximum number of values selected */ + if (this.upperBound != ValueUtils.MANY && allElements.size() > this.upperBound) { + addAll.setEnabled(false); + } + + + removeAll = new Button(buttonsSection, SWT.PUSH); + removeAll.setImage(Activator.getDefault().getImage("/icons/arrow_left_double.gif")); //$NON-NLS-1$ + removeAll.addSelectionListener(this); + removeAll.setToolTipText(Messages.MultipleValueSelectorDialog_RemoveAllElements); + } + + /** + * Creates the list displaying the currently selected elements + * + * @param parent + * The composite in which the section is created + */ + private void createListSection(Composite parent) { + + selectedElements = new Tree(parent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + // selectedElements.addSelectionListener(this); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + selectedElements.setLayoutData(data); + selectedElementsViewer = new TreeViewer(selectedElements); + + selectedElementsViewer.addSelectionChangedListener(this); + selectedElementsViewer.addDoubleClickListener(this); + + selectedElementsViewer.setContentProvider(createListSectionContentProvider()); + + if (labelProvider != null) { + selectedElementsViewer.setLabelProvider(labelProvider); + } + + selectedElementsViewer.setInput(allElements); + selector.setSelectedElements(allElements.toArray()); + } + + /** + * + * @see org.eclipse.papyrus.infra.nattable.wizard.pages.MultipleValueSelectionWizard#createListSectionContentProvider() + * + * @return + * the content provider to use in the list section (right part) + */ + protected IContentProvider createListSectionContentProvider() { + return CollectionContentProvider.instance; + } + + /** + * Creates the up/down controls section + * + * @param parent + * The composite in which the section is created + */ + protected void createRightButtonsSection(Composite parent) { + rightButtonsSection = new Composite(parent, SWT.NONE); + rightButtonsSection.setLayout(new GridLayout(1, true)); + + up = new Button(rightButtonsSection, SWT.PUSH); + up.setImage(Activator.getDefault().getImage("/icons/Up_12x12.gif")); //$NON-NLS-1$ + up.addSelectionListener(this); + up.setToolTipText(Messages.MultipleValueEditor_MoveSelectedElementsUp); + + down = new Button(rightButtonsSection, SWT.PUSH); + down.setImage(Activator.getDefault().getImage("/icons/Down_12x12.gif")); //$NON-NLS-1$ + down.addSelectionListener(this); + down.setToolTipText(Messages.MultipleValueEditor_MoveSelectedElementsDown); + + create = new Button(rightButtonsSection, SWT.PUSH); + create.setImage(Activator.getDefault().getImage("/icons/Add_12x12.gif")); //$NON-NLS-1$ + create.addSelectionListener(this); + create.setToolTipText(Messages.MultipleValueSelectorDialog_CreateNewElement); + + delete = new Button(rightButtonsSection, SWT.PUSH); + delete.setImage(Activator.getDefault().getImage("/icons/Delete_12x12.gif")); //$NON-NLS-1$ + delete.addSelectionListener(this); + delete.setToolTipText(Messages.MultipleValueSelectorDialog_DeleteNewElement); + delete.setEnabled(false); + } + + /** + * Sets the label provider used to display the selected elements + * + * @param labelProvider + */ + public void setLabelProvider(ILabelProvider labelProvider) { + this.labelProvider = labelProvider; + } + + /** + * {@inheritDoc} Handles the events on one of the control buttons + * + * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) + * + * @param e + * The event that occurred + */ + @Override + public void widgetSelected(SelectionEvent e) { + if (e.widget == add) { + addAction(); + } else if (e.widget == remove) { + removeAction(); + } else if (e.widget == addAll) { + addAllAction(); + } else if (e.widget == removeAll) { + removeAllAction(); + } else if (e.widget == up) { + upAction(); + } else if (e.widget == down) { + downAction(); + } else if (e.widget == create) { + createAction(); + } else if (e.widget == delete) { + deleteAction(); + } + + updateControls(); + } + + /** + * Sets the {@link ReferenceValueFactory} for this editor. The {@link ReferenceValueFactory} is used to create + * new instances and edit existing ones. + * + * @param factory + * The {@link ReferenceValueFactory} to be used by this editor + */ + public void setFactory(ReferenceValueFactory factory) { + this.factory = factory; + updateControls(); + } + + /** + * Handles the "Add" action + */ + protected void addAction() { + Object[] elements = selector.getSelectedElements(); + addElements(elements); + } + + /** + * Handles the "Up" action + */ + protected void upAction() { + IStructuredSelection selection = (IStructuredSelection) selectedElementsViewer.getSelection(); + + // We need a list to move objects. LinkedHashSet can't do that + java.util.List<Object> list = new LinkedList<Object>(allElements); + for (Object o : selection.toArray()) { + int oldIndex = list.indexOf(o); + if (oldIndex > 0) { + move(list, oldIndex, oldIndex - 1); + } + } + + allElements.clear(); + allElements.addAll(list); + + IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray()); + selectedElementsViewer.setSelection(selectionCopy); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Down" action + */ + protected void downAction() { + IStructuredSelection selection = (IStructuredSelection) selectedElementsViewer.getSelection(); + + // We need a list to move objects. LinkedHashSet can't do that + java.util.List<Object> list = new LinkedList<Object>(allElements); + + int maxIndex = list.size() - 1; + + Object[] selectionArray = selection.toArray(); + for (int i = selectionArray.length - 1; i >= 0; i--) { + Object o = selectionArray[i]; + int oldIndex = list.indexOf(o); + if (oldIndex < maxIndex) { + move(list, oldIndex, oldIndex + 1); + } + } + + allElements.clear(); + allElements.addAll(list); + + IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray()); + selectedElementsViewer.setSelection(selectionCopy); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Create" action + */ + protected void createAction() { + if (factory == null) { + return; + } + + Object newObject; + + try { + newObject = factory.createObject(this.create, this.contextElement); + } catch (OperationCanceledException e) { + // The user cancelled and we rolled back pending model changes + newObject = null; + } + + if (newObject == null) { + return; + } + + newObjects.add(newObject); + selector.newObjectCreated(newObject); + + Object[] createdObjects = new Object[] { newObject }; + addElements(createdObjects); + + selector.setSelectedElements(allElements.toArray()); + } + + + /** + * Moves an element from oldIndex to newIndex + * + * @param list + * The list in which to move the object + * @param oldIndex + * @param newIndex + */ + private void move(java.util.List<Object> list, int oldIndex, int newIndex) { + int size = list.size(); + + if (oldIndex < 0 || oldIndex >= size) { + throw new IndexOutOfBoundsException("oldIndex: " + oldIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ + } + if (newIndex < 0 || newIndex >= size) { + throw new IndexOutOfBoundsException("newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ + } + Object element = list.remove(oldIndex); + list.add(newIndex, element); + } + + /** + * Handles the "Remove" action + */ + protected void removeAction() { + if (canRemove()) { + IStructuredSelection selection = (IStructuredSelection) selectedElementsViewer.getSelection(); + if (selection.isEmpty()) { + return; + } + + for (Object element : selection.toArray()) { + allElements.remove(element); + } + + selector.setSelectedElements(allElements.toArray()); + selectedElementsViewer.setSelection(null); + selectedElementsViewer.refresh(); + } + } + + /** + * Handles the "Delete" action + */ + protected void deleteAction() { + // nothing to do here + } + + /** + * Handles the "Remove all" action + */ + protected void removeAllAction() { + allElements.clear(); + selector.setSelectedElements(new Object[0]); + selectedElementsViewer.setSelection(null); + selectedElementsViewer.refresh(); + } + + /** + * Handles the "Add All" action + */ + protected void addAllAction() { + Object[] elements = selector.getAllElements(); + addElements(elements); + } + + /** + * Adds the specified elements to the currently selected elements (For + * "Add" and "Add all" actions) + * + * @param elements + * The elements to be added + */ + @Override + public void addElements(Object[] elements) { + if (elements != null) { + allElements.addAll(Arrays.asList(elements)); + selectedElementsViewer.refresh(); + } + } + + public List<Object> getSelection() { + if (factory != null) { + java.util.List<Object> objectsToValidate = new LinkedList<Object>(); + for (Object object : newObjects) { + if (allElements.contains(object)) { + objectsToValidate.add(object); + } + } + factory.validateObjects(objectsToValidate); + selector.clearTemporaryElements(); + } + return new LinkedList<Object>(allElements); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // Nothing (see #doubleClick()) + } + + /** + * Indicates if the selected values should be unique (According to Object.equals()) + * + * @param unique + */ + public void setUnique(boolean unique) { + this.unique = unique; + updateControls(); + } + + /** + * Indicates if the selected elements should be ordered + * + * @param ordered + */ + public void setOrdered(boolean ordered) { + this.ordered = ordered; + updateControls(); + } + + public void updateControls() { + updateControl(up, ordered && canMove(true)); + updateControl(down, ordered && canMove(false)); + updateControl(create, this.factory != null && this.factory.canCreateObject()); + updateControl(add, canAdd()); + updateControl(delete, canDelete()); + } + + /** + * @return + */ + protected boolean canDelete() { + return true; + } + + /** + * + * @param up + * if <code>true</code> we try to move the element to the up, if <code>false</code> we try to move the element to the down + * @return + * <code>true</code> if the element can be moved + */ + protected boolean canMove(boolean up) { + return ordered; + } + + /** + * + * @return + * <code>true</code> if we can add elements + */ + protected boolean canAdd() { + /* Disable the bouton 'add' if the upperBound is reached */ + boolean canAdd = true; + if (this.upperBound != ValueUtils.MANY) { + if (allElements.size() >= this.upperBound) { + canAdd = false; + } + } + return canAdd; + } + + protected void updateControl(Control control, boolean enabled) { + if (control != null) { + control.setEnabled(enabled); + } + } + + public void setSelector(IElementSelector selector) { + this.selector = selector; + } + + /** + * Set the maximum number of values selected. + * + * @param upperBound + */ + public void setUpperBound(int upperBound) { + this.upperBound = upperBound; + } + + /** + * Sets the optional context of the element that is being edited, in which others will be added and removed. + * + * @param contextElement + * the model element that is being edited + */ + public void setContextElement(Object contextElement) { + this.contextElement = contextElement; + } + + /** + * Queries the optional context of the element that is being edited, in which others will be added and removed. + * + * @return the model element that is being edited + */ + public Object getContextElement() { + return contextElement; + } + + /** + * {@inheritDoc} + * + * Handles double click event on the right-panel tree viewer {@link #selectedElementsViewer} + * + */ + @Override + public void doubleClick(DoubleClickEvent event) { + removeAction(); + } + + /** + * + * @return + * <code>true</code> if the selected elements can be removed (moved from right to left) + */ + protected boolean canRemove() { + return true; + } + + /** + * {@inheritDoc} + * + * Handles selection change event on the right-panel tree viewer {@link #selectedElementsViewer} + */ + @Override + public void selectionChanged(SelectionChangedEvent event) { + updateControls(); + } + + /** + * @see org.eclipse.ui.services.IDisposable#dispose() + * + */ + @Override + public void dispose() { + selector.removeElementSelectionListener(this); + } + + /** + * + * @return + * the initial selection + */ + protected List<?> getInitialSelection() { + return this.initialSelection; + } +}
\ No newline at end of file diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/widgets/MultipleValueSelectionWithCheckboxWidget.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/widgets/MultipleValueSelectionWithCheckboxWidget.java new file mode 100644 index 00000000000..dc5b301e481 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/widgets/MultipleValueSelectionWithCheckboxWidget.java @@ -0,0 +1,168 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * Adapted code from Camille Letavernier (CEA LIST) in MultipleValueSelectorDialog + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.widgets; + +import org.eclipse.papyrus.infra.widgets.editors.IElementSelector; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + + +/** + * @author VL222926 + * + * + */ +public class MultipleValueSelectionWithCheckboxWidget extends MultipleValueEditAndSelectionWidget { + + /** boolean indicating if the checkbox is checked */ + protected boolean isChecked; + + /** The text to display for the checkbox */ + protected String text; + + /** the tooltip to display for the checkbox */ + protected String tooltip; + + /** indicates if the checkbox must be displayed or not */ + protected boolean displayCheckBox = true; + + protected Button checkBox; + /** + * the checkbox listener + */ + protected SelectionListener checkboxListener; + + /** + * Constructor. + * + * @param selector + * @param unique + * @param ordered + * @param upperBound + */ + public MultipleValueSelectionWithCheckboxWidget(IElementSelector selector, boolean unique, boolean ordered, int upperBound) { + super(selector, unique, ordered, upperBound); + } + + /** + * Constructor. + * + * @param selector + * @param unique + * @param ordered + */ + public MultipleValueSelectionWithCheckboxWidget(IElementSelector selector, boolean unique, boolean ordered) { + super(selector, unique, ordered); + } + + /** + * Constructor. + * + * @param selector + * @param unique + */ + public MultipleValueSelectionWithCheckboxWidget(IElementSelector selector, boolean unique) { + super(selector, unique); + } + + /** + * Constructor. + * + * @param selector + */ + public MultipleValueSelectionWithCheckboxWidget(IElementSelector selector) { + super(selector); + } + + /** + * @param text + * @param tooltip + * @param isChecked + */ + public void setCheckBoxValues(String text, String tooltip, boolean isChecked) { + this.text = text; + this.tooltip = tooltip; + this.isChecked = isChecked; + } + + /** + * @return + * <code>true</code> if the additional checkbox is checked + */ + public boolean isChecked() { + return this.isChecked; + } + + /** + * @param displayCheckBox + * <code>true</code> if the additional checkbox must be displayed + */ + public void setDisplayCheckBox(boolean displayCheckBox) { + this.displayCheckBox = displayCheckBox; + } + + /** + * + * @return <code>true</code> if the checkbox must be displayed + */ + public boolean isDisplayingCheckBox() { + return this.displayCheckBox; + } + + /** + * @see org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWidget#createContents(org.eclipse.swt.widgets.Composite) + * + * @param parent + */ + @Override + protected Composite createContents(Composite parent) { + Composite comp = super.createContents(parent); + if (this.displayCheckBox) { + this.checkBox = new Button(parent, SWT.CHECK); + this.checkBox.setText(this.text); + this.checkBox.setToolTipText(this.tooltip); + this.checkBox.setSelection(this.isChecked); + this.checkboxListener = + new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + isChecked = MultipleValueSelectionWithCheckboxWidget.this.checkBox.getSelection(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }; + this.checkBox.addSelectionListener(this.checkboxListener); + } + return comp; + } + + /** + * @see org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWidget#dispose() + * + */ + @Override + public void dispose() { + if (this.checkboxListener != null && this.checkBox != null) { + this.checkBox.removeSelectionListener(this.checkboxListener); + } + super.dispose(); + } +}
\ No newline at end of file diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/wizard/pages/MultipleValueEditAndSelectionWizardPage.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/wizard/pages/MultipleValueEditAndSelectionWizardPage.java new file mode 100644 index 00000000000..8815c446a53 --- /dev/null +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/wizard/pages/MultipleValueEditAndSelectionWizardPage.java @@ -0,0 +1,263 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.widgets.wizard.pages; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.papyrus.infra.widgets.Activator; +import org.eclipse.papyrus.infra.widgets.creation.ReferenceValueFactory; +import org.eclipse.papyrus.infra.widgets.editors.IElementSelector; +import org.eclipse.papyrus.infra.widgets.util.ImageConstants; +import org.eclipse.papyrus.infra.widgets.util.ValueUtils; +import org.eclipse.papyrus.infra.widgets.widgets.MultipleValueSelectionWidget; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +/** + * @author VL222926 + * + */ +public class MultipleValueEditAndSelectionWizardPage extends WizardPage { + + /** + * the widget displayed in this dialog + */ + private MultipleValueSelectionWidget widget; + /** + * The list of newly created objects + */ + protected Set<Object> newObjects = new HashSet<Object>(); + + /** + * Constructor. + * + * @param pageName + * the name of the wizard page + * @param title + * the title of the page + * @param titleImage + * the image to use in the title + * @param selector + * The element selector used by this dialog + */ + public MultipleValueEditAndSelectionWizardPage(String pageName, String title, ImageDescriptor titleImage, IElementSelector selector) { + this(pageName, title, titleImage, selector, false, false); + } + + /** + * + * Constructor. + * + * @param pageName + * the name of the wizard page + * @param title + * the title of the page + * @param titleImage + * the image to use in the title + * @param selector + * The element selector used by this dialog + * @param unique + * True if the values returned by this dialog should be unique + */ + public MultipleValueEditAndSelectionWizardPage(String pageName, String title, ImageDescriptor titleImage, IElementSelector selector, boolean unique) { + this(pageName, title, titleImage, selector, unique, false); + } + + /** + * + * Constructor. + * + * @param pageName + * the name of the wizard page + * @param title + * the title of the page + * @param titleImage + * the image to use in the title + * @param selector + * The element selector used by this dialog + * @param unique + * True if the values returned by this dialog should be unique + */ + public MultipleValueEditAndSelectionWizardPage(String pageName, String title, ImageDescriptor titleImage, IElementSelector selector, boolean unique, boolean ordered) { + this(pageName, title, titleImage, selector, unique, false, ValueUtils.MANY); + } + + /** + * + * Constructor. + * + * @param pageName + * the name of the wizard page + * @param title + * the title of the page + * @param titleImage + * the image to use in the title + * @param selector + * The element selector used by this dialog + * @param unique + * True if the values returned by this dialog should be unique + * @param upperBound + * The maximum number of values selected. + */ + public MultipleValueEditAndSelectionWizardPage(String pageName, String title, ImageDescriptor titleImage, IElementSelector selector, boolean unique, boolean ordered, int upperBound) { + super(pageName, title, titleImage); + this.widget = createWidget(selector, unique, ordered, upperBound); + } + + /** + * + * @param selector + * @param unique + * @param ordered + * @param upperBound + * @return + */ + protected MultipleValueSelectionWidget createWidget(IElementSelector selector, boolean unique, boolean ordered, int upperBound) { + return new MultipleValueSelectionWidget(selector, unique, ordered, upperBound); + } + + /** + * Sets the label provider used to display the selected elements + * + * @param labelProvider + */ + public void setLabelProvider(ILabelProvider labelProvider) { + this.widget.setLabelProvider(labelProvider); + } + + + /** + * Sets the {@link ReferenceValueFactory} for this editor. The {@link ReferenceValueFactory} is used to create + * new instances and edit existing ones. + * + * @param factory + * The {@link ReferenceValueFactory} to be used by this editor + */ + public void setFactory(ReferenceValueFactory factory) { + this.widget.setFactory(factory); + } + + /** + * Indicates if the selected values should be unique (According to Object.equals()) + * + * @param unique + */ + public void setUnique(boolean unique) { + this.widget.setUnique(unique); + } + + /** + * Indicates if the selected elements should be ordered + * + * @param ordered + */ + public void setOrdered(boolean ordered) { + this.widget.setOrdered(ordered); + } + + /** + * + * @param selector + */ + public void setSelector(IElementSelector selector) { + this.widget.setSelector(selector); + } + + /** + * Set the maximum number of values selected. + * + * @param upperBound + */ + public void setUpperBound(int upperBound) { + this.widget.setUpperBound(upperBound); + } + + /** + * Sets the optional context of the element that is being edited, in which others will be added and removed. + * + * @param contextElement + * the model element that is being edited + */ + public void setContextElement(Object contextElement) { + this.widget.setContextElement(contextElement); + } + + /** + * Queries the optional context of the element that is being edited, in which others will be added and removed. + * + * @return the model element that is being edited + */ + public Object getContextElement() { + return this.widget.getContextElement(); + } + + + /** + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + * + * @param arg0 + */ + @Override + public void createControl(Composite arg0) { + Control ctrl = this.widget.create(arg0); + getShell().pack(); + this.widget.updateControls(); + setControl(ctrl); + } + + /** + * @param arrayList + */ + public void setInitialElementSelections(List<Object> arrayList) { + this.widget.setInitialSelections(arrayList); + } + + /** + * @see org.eclipse.jface.dialogs.DialogPage#dispose() + * + */ + @Override + public void dispose() { + this.widget.dispose(); + super.dispose(); + } + + /** + * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean) + * + * @param visible + */ + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + getControl().setVisible(visible); + this.widget.updateControls(); + getShell().pack(); + } + + /** + * + * @return + * the wrapped widget + */ + protected MultipleValueSelectionWidget getWidget() { + return this.widget; + } +} |