blob: 3a39803e2e677a99cb336c2cd14da3c7814ceef5 [file] [log] [blame]
/**
*
* Copyright (c) 2002-2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.edit.ui.celleditor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.viewers.AbstractTreeViewer;
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.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
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.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl;
import org.eclipse.emf.common.ui.celleditor.ExtendedComboBoxCellEditor;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor.ValueHandler;
import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.ItemProvider;
import org.eclipse.emf.edit.ui.EMFEditUIPlugin;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
public class FeatureEditorDialog extends Dialog
{
protected ILabelProvider labelProvider;
protected IContentProvider contentProvider;
protected Object object;
protected EClassifier eClassifier;
protected String displayName;
protected ItemProvider values;
protected List<?> choiceOfValues;
protected EList<?> result;
protected boolean multiLine;
protected boolean unique;
/**
* @since 2.14
*/
protected ValueHandler valueHandler;
/**
* @since 2.14
*/
public FeatureEditorDialog
(Shell parent,
ILabelProvider labelProvider,
Object object,
EClassifier eClassifier,
List<?> currentValues,
String displayName,
List<?> choiceOfValues,
boolean multiLine,
boolean sortChoices,
boolean unique,
IItemPropertyDescriptor.ValueHandler valueHandler)
{
super(parent);
this.valueHandler = valueHandler;
setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX);
this.labelProvider = labelProvider;
this.object = object;
this.eClassifier = eClassifier;
this.displayName = displayName;
this.choiceOfValues = choiceOfValues;
this.multiLine = multiLine;
this.unique = unique;
AdapterFactory adapterFactory = new ComposedAdapterFactory(Collections.<AdapterFactory>emptyList());
values = new ItemProvider(adapterFactory, currentValues);
contentProvider = new AdapterFactoryContentProvider(adapterFactory);
if (sortChoices && choiceOfValues != null)
{
this.choiceOfValues = new ArrayList<Object>(choiceOfValues);
ExtendedComboBoxCellEditor.createItems(this.choiceOfValues, labelProvider, true);
}
}
/**
* @since 2.6
*/
public FeatureEditorDialog
(Shell parent,
ILabelProvider labelProvider,
Object object,
EClassifier eClassifier,
List<?> currentValues,
String displayName,
List<?> choiceOfValues,
boolean multiLine,
boolean sortChoices,
boolean unique)
{
this(parent, labelProvider, object, eClassifier, currentValues, displayName, choiceOfValues, multiLine, sortChoices, unique, null);
}
/**
* @deprecated Use {@link #FeatureEditorDialog(Shell, ILabelProvider, Object, EClassifier, List, String, List, boolean, boolean, boolean)},
* which provides proper behaviour for unique and non-unique features. This form retains the old behaviour, where
* specifying a list of choices enforces uniqueness.
*/
@Deprecated
public FeatureEditorDialog
(Shell parent,
ILabelProvider labelProvider,
Object object,
EClassifier eClassifier,
List<?> currentValues,
String displayName,
List<?> choiceOfValues,
boolean multiLine,
boolean sortChoices)
{
this(parent, labelProvider, object, eClassifier, currentValues, displayName, choiceOfValues, multiLine, sortChoices, choiceOfValues != null);
}
/**
* @deprecated Use {@link #FeatureEditorDialog(Shell, ILabelProvider, Object, EClassifier, List, String, List, boolean, boolean, boolean)},
* which provides proper behaviour for unique and non-unique features. This form retains the old behaviour, where
* specifying a list of choices enforces uniqueness.
*/
@Deprecated
public FeatureEditorDialog
(Shell parent,
ILabelProvider labelProvider,
Object object,
EClassifier eClassifier,
List<?> currentValues,
String displayName,
List<?> choiceOfValues)
{
this(parent, labelProvider, object, eClassifier, currentValues, displayName, choiceOfValues, false, false, choiceOfValues != null);
}
public FeatureEditorDialog
(Shell parent,
ILabelProvider labelProvider,
EObject eObject,
EStructuralFeature eStructuralFeature,
String displayName,
List<?> choiceOfValues)
{
this(parent,
labelProvider,
eObject,
eStructuralFeature.getEType(),
(List<?>)eObject.eGet(eStructuralFeature),
displayName,
choiceOfValues,
false,
false,
eStructuralFeature.isUnique() || eStructuralFeature instanceof EReference);
}
@Override
protected void configureShell(Shell shell)
{
super.configureShell(shell);
shell.setText
(EMFEditUIPlugin.INSTANCE.getString
("_UI_FeatureEditorDialog_title", new Object [] { displayName, labelProvider.getText(object) }));
shell.setImage(labelProvider.getImage(object));
}
@Override
protected Control createDialogArea(Composite parent)
{
Composite contents = (Composite)super.createDialogArea(parent);
GridLayout contentsGridLayout = (GridLayout)contents.getLayout();
contentsGridLayout.numColumns = 3;
GridData contentsGridData = (GridData)contents.getLayoutData();
contentsGridData.horizontalAlignment = SWT.FILL;
contentsGridData.verticalAlignment = SWT.FILL;
Text patternText = null;
if (choiceOfValues != null)
{
Group filterGroupComposite = new Group(contents, SWT.NONE);
filterGroupComposite.setText(EMFEditUIPlugin.INSTANCE.getString("_UI_Choices_pattern_group"));
filterGroupComposite.setLayout(new GridLayout(2, false));
filterGroupComposite.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 3, 1));
Label label = new Label(filterGroupComposite, SWT.NONE);
label.setText(EMFEditUIPlugin.INSTANCE.getString("_UI_Choices_pattern_label"));
patternText = new Text(filterGroupComposite, SWT.BORDER);
patternText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
}
Composite choiceComposite = new Composite(contents, SWT.NONE);
{
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.horizontalAlignment = SWT.END;
choiceComposite.setLayoutData(data);
GridLayout layout = new GridLayout();
data.horizontalAlignment = SWT.FILL;
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.numColumns = 1;
choiceComposite.setLayout(layout);
}
Label choiceLabel = new Label(choiceComposite, SWT.NONE);
choiceLabel.setText
(EMFEditUIPlugin.INSTANCE.getString
(choiceOfValues == null ?
"_UI_Value_label" :
valueHandler == null ?
"_UI_Choices_label" :
"_UI_ValueAndChoices_label"));
GridData choiceLabelGridData = new GridData();
choiceLabelGridData.verticalAlignment = SWT.FILL;
choiceLabelGridData.horizontalAlignment = SWT.FILL;
choiceLabel.setLayoutData(choiceLabelGridData);
// We use multi even for a single line because we want to respond to the enter key.
//
int style = multiLine ?
SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER :
SWT.MULTI | SWT.BORDER;
final Text choiceText = choiceOfValues == null || valueHandler != null ? new Text(choiceComposite, style) : null;
if (choiceText != null)
{
GridData choiceTextGridData = new GridData();
choiceTextGridData.widthHint = Display.getCurrent().getBounds().width / 5;
choiceTextGridData.verticalAlignment = SWT.BEGINNING;
choiceTextGridData.horizontalAlignment = SWT.FILL;
choiceTextGridData.grabExcessHorizontalSpace = true;
if (multiLine)
{
choiceTextGridData.verticalAlignment = SWT.FILL;
choiceTextGridData.grabExcessVerticalSpace = true;
}
choiceText.setLayoutData(choiceTextGridData);
if (valueHandler == null)
{
valueHandler = new ItemPropertyDescriptor.DataTypeValueHandler((EDataType)eClassifier);
}
}
final Table choiceTable = choiceOfValues == null ? null : new Table(choiceComposite, SWT.MULTI | SWT.BORDER);
if (choiceTable != null)
{
GridData choiceTableGridData = new GridData();
choiceTableGridData.widthHint = Display.getCurrent().getBounds().width / 5;
choiceTableGridData.heightHint = Display.getCurrent().getBounds().height / 3;
choiceTableGridData.verticalAlignment = SWT.FILL;
choiceTableGridData.horizontalAlignment = SWT.FILL;
choiceTableGridData.grabExcessHorizontalSpace= true;
choiceTableGridData.grabExcessVerticalSpace= true;
choiceTable.setLayoutData(choiceTableGridData);
}
final TableViewer choiceTableViewer = choiceOfValues == null ? null : new TableViewer(choiceTable);
if (choiceTableViewer != null)
{
choiceTableViewer.setContentProvider(new AdapterFactoryContentProvider(new AdapterFactoryImpl()));
choiceTableViewer.setLabelProvider(labelProvider);
final PatternFilter filter =
new PatternFilter()
{
@Override
protected boolean isParentMatch(Viewer viewer, Object element)
{
return viewer instanceof AbstractTreeViewer && super.isParentMatch(viewer, element);
}
};
choiceTableViewer.addFilter(filter);
if (patternText != null)
{
patternText.addModifyListener
(new ModifyListener()
{
public void modifyText(ModifyEvent e)
{
filter.setPattern(((Text)e.widget).getText());
choiceTableViewer.refresh();
}
});
}
if (unique)
{
choiceTableViewer.addFilter
(new ViewerFilter()
{
@Override
public boolean select(Viewer viewer, Object parentElement, Object element)
{
return !values.getChildren().contains(element);
}
});
}
choiceTableViewer.setInput(new ItemProvider(choiceOfValues));
}
Composite controlButtons = new Composite(contents, SWT.NONE);
GridData controlButtonsGridData = new GridData();
controlButtonsGridData.verticalAlignment = SWT.FILL;
controlButtonsGridData.horizontalAlignment = SWT.FILL;
controlButtons.setLayoutData(controlButtonsGridData);
GridLayout controlsButtonGridLayout = new GridLayout();
controlButtons.setLayout(controlsButtonGridLayout);
new Label(controlButtons, SWT.NONE);
final Button addButton = new Button(controlButtons, SWT.PUSH);
addButton.setText(EMFEditUIPlugin.INSTANCE.getString("_UI_Add_label"));
GridData addButtonGridData = new GridData();
addButtonGridData.verticalAlignment = SWT.FILL;
addButtonGridData.horizontalAlignment = SWT.FILL;
addButton.setLayoutData(addButtonGridData);
addButton.setEnabled(valueHandler != null && valueHandler.isValid("") == null);
final Button removeButton = new Button(controlButtons, SWT.PUSH);
removeButton.setText(EMFEditUIPlugin.INSTANCE.getString("_UI_Remove_label"));
GridData removeButtonGridData = new GridData();
removeButtonGridData.verticalAlignment = SWT.FILL;
removeButtonGridData.horizontalAlignment = SWT.FILL;
removeButton.setLayoutData(removeButtonGridData);
removeButton.setEnabled(false);
Label spaceLabel = new Label(controlButtons, SWT.NONE);
GridData spaceLabelGridData = new GridData();
spaceLabelGridData.verticalSpan = 2;
spaceLabel.setLayoutData(spaceLabelGridData);
final Button upButton = new Button(controlButtons, SWT.PUSH);
upButton.setText(EMFEditUIPlugin.INSTANCE.getString("_UI_Up_label"));
GridData upButtonGridData = new GridData();
upButtonGridData.verticalAlignment = SWT.FILL;
upButtonGridData.horizontalAlignment = SWT.FILL;
upButton.setLayoutData(upButtonGridData);
upButton.setEnabled(false);
final Button downButton = new Button(controlButtons, SWT.PUSH);
downButton.setText(EMFEditUIPlugin.INSTANCE.getString("_UI_Down_label"));
GridData downButtonGridData = new GridData();
downButtonGridData.verticalAlignment = SWT.FILL;
downButtonGridData.horizontalAlignment = SWT.FILL;
downButton.setLayoutData(downButtonGridData);
downButton.setEnabled(false);
Composite featureComposite = new Composite(contents, SWT.NONE);
{
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.horizontalAlignment = SWT.END;
featureComposite.setLayoutData(data);
GridLayout layout = new GridLayout();
data.horizontalAlignment = SWT.FILL;
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.numColumns = 1;
featureComposite.setLayout(layout);
}
Label featureLabel = new Label(featureComposite, SWT.NONE);
featureLabel.setText(EMFEditUIPlugin.INSTANCE.getString("_UI_Feature_label"));
GridData featureLabelGridData = new GridData();
featureLabelGridData.horizontalSpan = 2;
featureLabelGridData.horizontalAlignment = SWT.FILL;
featureLabelGridData.verticalAlignment = SWT.FILL;
featureLabel.setLayoutData(featureLabelGridData);
final Table featureTable = new Table(featureComposite, SWT.MULTI | SWT.BORDER);
GridData featureTableGridData = new GridData();
featureTableGridData.widthHint = Display.getCurrent().getBounds().width / 5;
featureTableGridData.heightHint = Display.getCurrent().getBounds().height / 3;
featureTableGridData.verticalAlignment = SWT.FILL;
featureTableGridData.horizontalAlignment = SWT.FILL;
featureTableGridData.grabExcessHorizontalSpace= true;
featureTableGridData.grabExcessVerticalSpace= true;
featureTable.setLayoutData(featureTableGridData);
// We carefully manage the selection because for non-unique features,
// because the value selected by a selection-preserving refresh will be the first of the duplicates.
//
final TableViewer featureTableViewer = new TableViewer(featureTable)
{
@Override
public void refresh(Object element, boolean updateLabels)
{
internalRefresh(element, updateLabels);
}
@Override
public void refresh(Object element)
{
internalRefresh(element);
}
};
featureTableViewer.setContentProvider(contentProvider);
featureTableViewer.setLabelProvider(labelProvider);
featureTableViewer.setInput(values);
featureTableViewer.addSelectionChangedListener(new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent event)
{
// Remove is enabled only if something is selected.
//
removeButton.setEnabled(!event.getSelection().isEmpty());
int[] selectionIndices = getSelectionIndices(featureTable);
// Up is enabled only if something will actually be moved up.
//
boolean upEnabled = false;
if (selectionIndices.length > 0)
{
int upIndex = Math.max(selectionIndices[0] - 1, 0);
for (int i = 0; i < selectionIndices.length; ++i)
{
if (upIndex++ != selectionIndices[i])
{
upEnabled = true;
}
}
}
upButton.setEnabled(upEnabled);
// Down is enabled only if something will actually be moved up.
//
boolean downEnabled = false;
if (selectionIndices.length > 0)
{
int downIndex = Math.min(selectionIndices[selectionIndices.length - 1] + 1, featureTable.getItemCount() - 1);
for (int i = selectionIndices.length - 1; i >= 0; --i)
{
if (downIndex-- != selectionIndices[i])
{
downEnabled = true;
}
}
}
downButton.setEnabled(downEnabled);
}
});
// Manage the active control used by the Add button.
//
class ActiveControl
{
private Control control = choiceText == null ? choiceTable : choiceText;
public Control get()
{
return control;
}
public void set(Control control)
{
this.control = control;
if (control == choiceText)
{
choiceText.notifyListeners(SWT.Modify, null);
}
else
{
choiceTable.notifyListeners(SWT.Selection, null);
setErrorMessage(null);
}
}
}
final ActiveControl activeControl = new ActiveControl();
final EList<Object> children = values.getChildren();
if (!children.isEmpty())
{
featureTableViewer.setSelection(new StructuredSelection(children.get(0)));
}
if (choiceTableViewer != null)
{
choiceTableViewer.addSelectionChangedListener(new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent event)
{
if (activeControl.get() == choiceTable)
{
addButton.setEnabled(!event.getSelection().isEmpty());
}
}
});
choiceTableViewer.addDoubleClickListener(new IDoubleClickListener()
{
public void doubleClick(DoubleClickEvent event)
{
if (addButton.isEnabled())
{
addButton.notifyListeners(SWT.Selection, null);
}
}
});
choiceTable.addFocusListener(new FocusAdapter()
{
@Override
public void focusGained(FocusEvent e)
{
activeControl.set(choiceTable);
}
});
}
featureTableViewer.addDoubleClickListener(new IDoubleClickListener()
{
public void doubleClick(DoubleClickEvent event)
{
if (removeButton.isEnabled())
{
removeButton.notifyListeners(SWT.Selection, null);
}
}
});
if (choiceText != null)
{
choiceText.addKeyListener(
new KeyAdapter()
{
@Override
public void keyPressed(KeyEvent event)
{
if (!multiLine && (event.character == '\r' || event.character == '\n'))
{
event.doit = false;
if (addButton.isEnabled())
{
addButton.notifyListeners(SWT.Selection, null);
}
}
}
});
choiceText.addModifyListener(
new ModifyListener()
{
public void modifyText(ModifyEvent e)
{
if (activeControl.get() == choiceText)
{
String text = choiceText.getText();
String errorMessage = valueHandler.isValid(text);
if (errorMessage == null && unique && children.contains(valueHandler.toValue(text)))
{
errorMessage = EMFEditUIPlugin.INSTANCE.getString("_UI_DuplicateValue_message");
}
if (choiceText.isFocusControl() || !"".equals(text))
{
setErrorMessage(errorMessage);
}
addButton.setEnabled(errorMessage == null);
}
}
});
choiceText.addFocusListener(new FocusAdapter()
{
@Override
public void focusGained(FocusEvent e)
{
activeControl.set(choiceText);
}
});
}
upButton.addSelectionListener(
new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent event)
{
// We use indices to properly handle non-unique values.
//
int[] selectionIndices = getSelectionIndices(featureTable);
int index = Math.max(selectionIndices[0] - 1, 0);
int start = index;
for (int i = 0; i < selectionIndices.length; ++i)
{
children.move(index++, selectionIndices[i]);
}
// We manage the selection to select exactly the appropriate indices.
//
featureTableViewer.refresh();
featureTable.setSelection(start, start + selectionIndices.length - 1);
featureTable.notifyListeners(SWT.Selection, null);
}
});
downButton.addSelectionListener(
new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent event)
{
// We use indices to properly handle non-unique values.
//
int[] selectionIndices = getSelectionIndices(featureTable);
int index = Math.min(selectionIndices[selectionIndices.length - 1] + 1, children.size() - 1);
for (int i = selectionIndices.length - 1; i >= 0; --i)
{
children.move(index--, selectionIndices[i]);
}
// We manage the selection to select exactly the appropriate indices.
//
featureTableViewer.refresh();
featureTable.setSelection(index + 1, index + selectionIndices.length);
featureTable.notifyListeners(SWT.Selection, null);
}
});
addButton.addSelectionListener(
new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent event)
{
// If there is a choice table and there is no choice text or the choice table is the active control...
//
if (choiceTableViewer != null && (choiceText == null || activeControl.get() == choiceTable))
{
// Remember the selection of the choices table.
//
int[] selectionIndices = getSelectionIndices(choiceTable);
// Process the selected values...
//
IStructuredSelection selection = (IStructuredSelection)choiceTableViewer.getSelection();
int addCount = 0;
for (Object value : selection.toArray())
{
// If duplicates are allowed or the value isn't already present...
//
if (!unique || !children.contains(value))
{
// Add the value and remember how many we added.
children.add(value);
++addCount;
// If there is a choice text, and its value is equal to the text value we added, clear that value.
//
if (choiceText != null && choiceText.getText().equals(valueHandler.toString(value)))
{
choiceText.setText("");
}
}
}
// Select exactly the expected indices.
//
featureTableViewer.refresh();
featureTable.setSelection(children.size() - addCount, children.size() - 1);
featureTable.notifyListeners(SWT.Selection, null);
// Refresh the choice table based on the filters and if the table isn't empty and there is no selection.
//
choiceTableViewer.refresh();
if (choiceTable.getItemCount() > 0 && getSelectionIndices(choiceTable).length == 0)
{
// Select the index before the previously selected index.
//
choiceTable.setSelection(selectionIndices.length == 0 || selectionIndices[0] == 0 ? 0 : selectionIndices[0] - 1);
choiceTableViewer.setSelection(choiceTableViewer.getSelection());
}
}
else if (choiceText != null)
{
// Convert the value, add it, and clear the value from the choice text.
//
Object value = valueHandler.toValue(choiceText.getText());
children.add(value);
choiceText.setText("");
// Select the new value at the end of the table.
//
featureTableViewer.refresh();
featureTable.setSelection(featureTable.getItemCount() - 1);
featureTable.notifyListeners(SWT.Selection, null);
// If there is a choice table...
//
if (choiceTableViewer != null)
{
// Refresh it and if there is no longer a selection and the table isn't empty...
//
choiceTableViewer.refresh();
if (choiceTableViewer.getSelection().isEmpty() && choiceTable.getItemCount() > 0)
{
// Select the first item in the table.
//
choiceTable.setSelection(0);
choiceTable.notifyListeners(SWT.Selection, null);
}
}
}
}
});
removeButton.addSelectionListener(
new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent event)
{
// Remember the selection in the feature table...
//
IStructuredSelection selection = (IStructuredSelection)featureTableViewer.getSelection();
// Process the selection to remove the appropriate values.
// And remember the value we might put into the choice text.
//
int[] selectionIndices = getSelectionIndices(featureTable);
Object firstValue = children.get(selectionIndices[0]);
for (int i = selectionIndices.length -1; i >= 0; --i)
{
children.remove(selectionIndices[i]);
}
// Refresh the feature table and select the index before the previous selection.
//
featureTableViewer.refresh();
if (!children.isEmpty())
{
featureTable.setSelection(selectionIndices[0] == 0 ? 0 : selectionIndices[0] - 1);
}
featureTable.notifyListeners(SWT.Selection, null);
// If there is a choice table...
//
if (choiceTableViewer != null)
{
// Refresh it and select the values we just removed.
//
choiceTableViewer.refresh();
choiceTableViewer.setSelection(selection);
// Check which values are actually selected, them from the list of things we tried to select...
//
IStructuredSelection choiceSelection = (IStructuredSelection)choiceTableViewer.getSelection();
@SuppressWarnings("unchecked")
List<?> values = new ArrayList<Object>(selection.toList());
values.removeAll(choiceSelection.toList());
// If there is a value that was removed but isn't selected in the choice table...
//
if (!values.isEmpty())
{
// Use the first such value as the value to set into the choice text.
//
firstValue = values.get(0);
}
}
// If there is a choice text, and we have a value...
//
if (choiceText != null && firstValue != null)
{
// Convert the value to text, and set it into the choice.
//
String value = valueHandler.toString(firstValue);
choiceText.setText(value);
// If the choice table is the active control and it doesn't have a selection...
//
if (activeControl.get() == choiceTable && choiceTableViewer.getSelection().isEmpty())
{
// Make the choice text the active control.
// This ensures that when you do a remove, that the Add button is enabled and you can add the value back.
//
activeControl.set(choiceText);
}
}
}
});
// If there is a choice text, clear the error message to ensure that the dialog does not come up initially in an error state.
// The add button will be disabled if there is an error message.
//
if (choiceText != null)
{
choiceText.getDisplay().asyncExec(new Runnable()
{
public void run()
{
if (!choiceText.isDisposed())
{
if (choiceTable != null && choiceTable.getItemCount() == 0)
{
choiceText.setFocus();
}
setErrorMessage(null);
}
}
});
}
return contents;
}
@Override
protected Control createButtonBar(Composite parent)
{
// Specialize the button area so that we can provide a label control that displays error messages.
//
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
composite.setLayout(layout);
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);
composite.setLayoutData(data);
composite.setFont(parent.getFont());
Label label = new Label(composite, SWT.NONE);
label.setForeground(JFaceColors.getErrorText(label.getDisplay()));
GridData labelData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER | GridData.GRAB_HORIZONTAL);
labelData.horizontalIndent = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
label.setLayoutData(labelData);
Control buttonBar = super.createButtonBar(composite);
GridData buttonBarData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_CENTER);
buttonBar.setLayoutData(buttonBarData);
return buttonBar;
}
/**
* @since 2.14
*/
protected void setErrorMessage(String message)
{
Label label = (Label)getButtonBar().getParent().getChildren()[0];
label.setText(message == null ? "" : message);
label.setToolTipText(message == null ? "" : message);
}
@Override
protected void okPressed()
{
result = new BasicEList<Object>(values.getChildren());
super.okPressed();
}
@Override
public boolean close()
{
contentProvider.dispose();
return super.close();
}
public EList<?> getResult()
{
return result;
}
private static int[] getSelectionIndices(Table table)
{
int[] selectionIndices = table.getSelectionIndices();
Arrays.sort(selectionIndices);
return selectionIndices;
}
}