| /*******************************************************************************
|
| * 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();
|
| }
|
| }
|