/***************************************************************************** * 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.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); getParent().addDisposeListener(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 */ 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} */ public void widgetDisposed(org.eclipse.swt.events.DisposeEvent e) { dispose(); modelProperty.removeChangeListener(this); } /** * {@inheritDoc} Handles the event when the edit button is pressed */ public void widgetSelected(SelectionEvent e) { 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 */ 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); } }