blob: 5ff2970cd2a03db58708b4c42bf999e66ddf024e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2019 CEA LIST.
*
* 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:
* Nicolas Bros (Mia-Software) - initial API and implementation
* Nicolas Guyomar (Mia-Software) - Bug 339554 - org.eclipse.modisco.facet.widgets.celleditors API cleaning
* Nicolas Guyomar (Mia-Software) - Bug 342451 - To be able to edit derived facet attributes and derived facet references in a table
* Gregoire Dupe (Mia-Software) - Bug 369987 - [Restructuring][Table] Switch to the new customization and facet framework
*******************************************************************************/
package org.eclipse.modisco.facet.widgets.celleditors.internal.ui;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.modisco.facet.efacet.metamodel.v0_2_0.efacet.FacetReference;
import org.eclipse.modisco.facet.util.emf.ui.internal.dialogs.CreateInstanceDialog;
import org.eclipse.modisco.facet.widgets.celleditors.IModelCellEditHandler;
import org.eclipse.modisco.facet.widgets.celleditors.internal.Messages;
import org.eclipse.modisco.facet.widgets.internal.CustomizableLabelProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.dialogs.PatternFilter;
/** A dialog to edit a multiplicity-many {@link EReference} */
public class NaryReferenceEditingDialog<T extends EObject> extends AbstractNaryEditingDialog<T> {
private Button addButton;
private Button removeButton;
private Button addAllButton;
private Button removeAllButton;
private Button upButton;
private Button downButton;
private static final int NUM_COLUMNS = 4;
// this is a *tree* viewer because PatternFilter only supports Trees
private TreeViewer availableValuesTreeViewer;
private ListViewer featureValuesListViewer;
private Button createInstanceButton;
private AssignableValuesContentProvider assignableValuesContentProvider;
private final List<T> availableValues;
/**
*
* @param parent
* the parent {@link Shell}
* @param values
* the list of current values.
* @param feature
* the feature to edit
* @param eObject
* the eObject being currently edited. Should not be modified in this dialog.
* @param editHandler
* The editHandler which has to be called when the edition is completed
*/
public NaryReferenceEditingDialog(final Shell shell, final List<T> values,
final List<T> availableValues, final IModelCellEditHandler editHandler,
final EObject eObject, final EStructuralFeature feature) {
super(shell, values, editHandler, eObject, feature);
this.availableValues = new ArrayList<T>(availableValues);
}
@Override
protected void configureShell(final Shell shell) {
super.configureShell(shell);
shell.setText(NLS.bind(Messages.NaryReferenceEditingDialog_shellTitle,
getFeature().getName(), geteObject().eClass().getName()));
}
@Override
protected Control createDialogArea(final Composite parent) {
final Composite contents = (Composite) super.createDialogArea(parent);
final GridLayout contentsGridLayout = (GridLayout) contents.getLayout();
contentsGridLayout.numColumns = NaryReferenceEditingDialog.NUM_COLUMNS;
final GridData contentsGridData = (GridData) contents.getLayoutData();
contentsGridData.horizontalAlignment = SWT.FILL;
contentsGridData.verticalAlignment = SWT.FILL;
createLeftPane(contents);
createMiddleButtonsPane(contents);
createRightPane(contents);
createRightButtonsPane(contents);
this.availableValuesTreeViewer.addOpenListener(new IOpenListener() {
public void open(final OpenEvent event) {
if (NaryReferenceEditingDialog.this.addButton.isEnabled()) {
NaryReferenceEditingDialog.this.addButton.notifyListeners(SWT.Selection, null);
}
}
});
this.featureValuesListViewer.addOpenListener(new IOpenListener() {
public void open(final OpenEvent event) {
if (NaryReferenceEditingDialog.this.removeButton.isEnabled()) {
NaryReferenceEditingDialog.this.removeButton.notifyListeners(SWT.Selection,
null);
}
}
});
this.upButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
upButtonClicked();
}
});
this.downButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
downButtonClicked();
}
});
this.addButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
addButtonClicked();
}
});
this.addAllButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
addAllButtonClicked();
}
});
this.removeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
removeButtonClicked();
}
});
this.removeAllButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
removeAllButtonClicked();
}
});
if (this.createInstanceButton != null) {
this.createInstanceButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
createInstanceButtonClicked();
}
});
}
return contents;
}
private void addButtonClicked() {
final IStructuredSelection selection = (IStructuredSelection) this.availableValuesTreeViewer
.getSelection();
if (selection.isEmpty() || !confirmMove()) {
return;
}
Iterator<T> it = getTCastedStructuredSelectionIterator(selection);
while (it.hasNext()) {
T element = it.next();
if (!(getValues() != null && getValues().contains(element))) {
getValues().add(element);
this.availableValues.remove(element);
}
}
refresh();
this.featureValuesListViewer.setSelection(selection);
}
@SuppressWarnings({ "unchecked", "static-method" })
//unchecked: the selection in not type parameterized, then we cannot get a cleaned cast iterator
//static-method: this method cannot be static to be able to use the T type.
private Iterator<T> getTCastedStructuredSelectionIterator(final IStructuredSelection selection) {
return selection.iterator();
}
private void addAllButtonClicked() {
if (this.availableValues.isEmpty() || !confirmMove()) {
return;
}
getValues().addAll(this.availableValues);
this.availableValues.removeAll(getValues());
refresh();
}
private void removeButtonClicked() {
final IStructuredSelection selection = (IStructuredSelection) this.featureValuesListViewer
.getSelection();
if (selection.isEmpty() || !confirmRemove()) {
return;
}
Iterator<T> it = this.getTCastedStructuredSelectionIterator(selection);
while (it.hasNext()) {
T element = it.next();
if (getValues().contains(element)) {
this.availableValues.add(element);
getValues().remove(element);
}
}
refresh();
}
private void removeAllButtonClicked() {
if (getValues().isEmpty() || !confirmRemove()) {
return;
}
this.availableValues.addAll(getValues());
getValues().removeAll(getValues());
refresh();
}
private boolean confirmRemove() {
if (getFeature() instanceof EReference) {
EReference eReference = (EReference) getFeature();
if (eReference.isContainment()) {
return MessageDialog.openConfirm(getShell(),
Messages.NaryReferenceEditingDialog_deleteElements,
Messages.NaryReferenceEditingDialog_deleteElementsLong);
}
}
return true;
}
private boolean confirmMove() {
if (getFeature() instanceof EReference || getFeature() instanceof FacetReference) {
EReference reference = (EReference) getFeature();
if (reference.isContainment()) {
String fullMessage = Messages.NaryReferenceEditingDialog_moveWarning;
return MessageDialog.openConfirm(getShell(),
Messages.NaryReferenceEditingDialog_moveElement, fullMessage);
}
}
return true;
}
@SuppressWarnings("unchecked") // type erasure on generic
private void createInstanceButtonClicked() {
EClassifier eType = getFeature().getEType();
if (eType instanceof EClass) {
EClass eClass = (EClass) eType;
EObject newInstance = CreateInstanceDialog.open(getShell(), eClass,
new CustomizableLabelProvider());
if (newInstance != null) {
getValues().add((T) newInstance);
refresh();
}
}
}
private void createLeftPane(final Composite contents) {
final Composite choiceComposite = new Composite(contents, SWT.NONE);
final GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.horizontalAlignment = SWT.END;
choiceComposite.setLayoutData(data);
final GridLayout layout = new GridLayout();
data.horizontalAlignment = SWT.FILL;
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.numColumns = 1;
choiceComposite.setLayout(layout);
final Label choiceLabel = new Label(choiceComposite, SWT.NONE);
choiceLabel.setText(Messages.NaryReferenceEditingDialog_availableValues);
final GridData choiceLabelGridData = new GridData();
choiceLabelGridData.verticalAlignment = SWT.FILL;
choiceLabelGridData.horizontalAlignment = SWT.FILL;
choiceLabel.setLayoutData(choiceLabelGridData);
final Text patternText = createFilterText(choiceComposite);
final Tree availableValuesTree = new Tree(choiceComposite, SWT.MULTI | SWT.BORDER);
final GridData availableValuesGridData = new GridData();
availableValuesGridData.widthHint = AbstractNaryEditingDialog.AVAILABLE_VALUES_TREE_WIDTH;
availableValuesGridData.heightHint = AbstractNaryEditingDialog.AVAILABLE_VALUES_TREE_HEIGHT;
availableValuesGridData.horizontalAlignment = SWT.FILL;
availableValuesGridData.verticalAlignment = SWT.FILL;
availableValuesGridData.grabExcessHorizontalSpace = true;
availableValuesGridData.grabExcessVerticalSpace = true;
availableValuesTree.setLayoutData(availableValuesGridData);
this.availableValuesTreeViewer = new TreeViewer(availableValuesTree);
this.assignableValuesContentProvider = new AssignableValuesContentProvider();
this.availableValuesTreeViewer.setContentProvider(this.assignableValuesContentProvider);
this.availableValuesTreeViewer.setLabelProvider(new CustomizableLabelProvider());
final PatternFilter filter = new PatternFilter();
this.availableValuesTreeViewer.addFilter(filter);
this.availableValuesTreeViewer.setInput(this.availableValues);
patternText.addModifyListener(new ModifyListener() {
public void modifyText(final ModifyEvent e) {
filter.setPattern(patternText.getText());
NaryReferenceEditingDialog.this.availableValuesTreeViewer.refresh();
}
});
}
private void createMiddleButtonsPane(final Composite contents) {
final Composite buttonsComposite = new Composite(contents, SWT.NONE);
final GridData buttonsCompositeGridData = new GridData();
buttonsCompositeGridData.verticalAlignment = SWT.CENTER;
buttonsCompositeGridData.horizontalAlignment = SWT.FILL;
buttonsComposite.setLayoutData(buttonsCompositeGridData);
buttonsComposite.setLayout(new GridLayout());
// new Label(buttonsComposite, SWT.NONE);
this.addButton = new Button(buttonsComposite, SWT.PUSH);
this.addButton.setText(Messages.NaryReferenceEditingDialog_add);
this.addButton.setToolTipText(Messages.NaryReferenceEditingDialog_addTooltip);
final GridData addButtonGridData = new GridData();
addButtonGridData.verticalAlignment = SWT.FILL;
addButtonGridData.horizontalAlignment = SWT.FILL;
this.addButton.setLayoutData(addButtonGridData);
this.removeButton = new Button(buttonsComposite, SWT.PUSH);
this.removeButton.setText(Messages.NaryReferenceEditingDialog_remove);
this.removeButton.setToolTipText(Messages.NaryReferenceEditingDialog_removeTooltip);
final GridData removeButtonGridData = new GridData();
removeButtonGridData.verticalAlignment = SWT.FILL;
removeButtonGridData.horizontalAlignment = SWT.FILL;
this.removeButton.setLayoutData(removeButtonGridData);
spacer(buttonsComposite);
this.addAllButton = new Button(buttonsComposite, SWT.PUSH);
this.addAllButton.setText(Messages.NaryReferenceEditingDialog_addAll);
this.addAllButton.setToolTipText(Messages.NaryReferenceEditingDialog_addAllTooltip);
this.removeAllButton = new Button(buttonsComposite, SWT.PUSH);
this.removeAllButton.setText(Messages.NaryReferenceEditingDialog_removeAll);
this.removeAllButton.setToolTipText(Messages.NaryReferenceEditingDialog_removeAllTooltip);
}
private void spacer(final Composite parent) {
@SuppressWarnings("unused")
Label label = new Label(parent, SWT.NONE);
}
private void createRightButtonsPane(final Composite contents) {
final Composite buttonsComposite = new Composite(contents, SWT.NONE);
final GridData buttonsCompositeGridData = new GridData();
buttonsCompositeGridData.verticalAlignment = SWT.FILL;
buttonsCompositeGridData.horizontalAlignment = SWT.FILL;
buttonsComposite.setLayoutData(buttonsCompositeGridData);
buttonsComposite.setLayout(new GridLayout());
// spacer
spacer(buttonsComposite);
if (getFeature() instanceof EReference) {
EReference eReference = (EReference) getFeature();
if (eReference.isContainment()) {
this.createInstanceButton = new Button(buttonsComposite, SWT.PUSH);
this.createInstanceButton.setText(Messages.NaryReferenceEditingDialog_newInstance);
final GridData createButtonGridData = new GridData();
createButtonGridData.verticalAlignment = SWT.FILL;
createButtonGridData.horizontalAlignment = SWT.FILL;
this.createInstanceButton.setLayoutData(createButtonGridData);
spacer(buttonsComposite);
}
}
this.upButton = new Button(buttonsComposite, SWT.PUSH);
this.upButton.setText(Messages.NaryReferenceEditingDialog_up);
final GridData upButtonGridData = new GridData();
upButtonGridData.verticalAlignment = SWT.FILL;
upButtonGridData.horizontalAlignment = SWT.FILL;
this.upButton.setLayoutData(upButtonGridData);
this.downButton = new Button(buttonsComposite, SWT.PUSH);
this.downButton.setText(Messages.NaryReferenceEditingDialog_down);
final GridData downButtonGridData = new GridData();
downButtonGridData.verticalAlignment = SWT.FILL;
downButtonGridData.horizontalAlignment = SWT.FILL;
this.downButton.setLayoutData(downButtonGridData);
}
private void createRightPane(final Composite contents) {
final Composite featureComposite = new Composite(contents, SWT.NONE);
final GridData featureCompositeData = new GridData(SWT.FILL, SWT.FILL, true, true);
featureCompositeData.horizontalAlignment = SWT.END;
featureComposite.setLayoutData(featureCompositeData);
final GridLayout featureCompositeLayout = new GridLayout();
featureCompositeData.horizontalAlignment = SWT.FILL;
featureCompositeLayout.marginHeight = 0;
featureCompositeLayout.marginWidth = 0;
featureCompositeLayout.numColumns = 1;
featureComposite.setLayout(featureCompositeLayout);
final Label featureLabel = new Label(featureComposite, SWT.NONE);
featureLabel.setText(Messages.NaryReferenceEditingDialog_values);
final GridData valuesLabelGridData = new GridData();
valuesLabelGridData.horizontalSpan = 2;
valuesLabelGridData.horizontalAlignment = SWT.FILL;
valuesLabelGridData.verticalAlignment = SWT.FILL;
featureLabel.setLayoutData(valuesLabelGridData);
final org.eclipse.swt.widgets.List availableValuesList = new org.eclipse.swt.widgets.List(
featureComposite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
final GridData availableValuesGridData = new GridData();
availableValuesGridData.widthHint = AbstractNaryEditingDialog.AVAILABLE_VALUES_TREE_WIDTH;
availableValuesGridData.heightHint = AbstractNaryEditingDialog.AVAILABLE_VALUES_TREE_HEIGHT;
availableValuesGridData.verticalAlignment = SWT.FILL;
availableValuesGridData.horizontalAlignment = SWT.FILL;
availableValuesGridData.grabExcessHorizontalSpace = true;
availableValuesGridData.grabExcessVerticalSpace = true;
availableValuesList.setLayoutData(availableValuesGridData);
this.featureValuesListViewer = new ListViewer(availableValuesList);
this.featureValuesListViewer.setContentProvider(new AssignedValuesContentProvider());
this.featureValuesListViewer.setLabelProvider(new CustomizableLabelProvider());
this.featureValuesListViewer
.setInput(getValues());
}
private Text createFilterText(final Composite contents) {
Text patternText = new Text(contents, SWT.BORDER | SWT.SEARCH);
patternText.setMessage(Messages.NaryReferenceEditingDialog_typeFilterText);
patternText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
return patternText;
}
@Override
public void refresh() {
this.availableValuesTreeViewer.refresh();
this.featureValuesListViewer.refresh();
}
@Override
protected boolean isResizable() {
return true;
}
@Override
protected void createButtonsForButtonBar(final Composite parent) {
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
}
@Override
public ISelection getSelection() {
return this.featureValuesListViewer.getSelection();
}
}