blob: 7ad63c0fde9a9ffcc15fef24ede108aecdc8c0f2 [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
*******************************************************************************/
package org.eclipse.modisco.facet.widgets.celleditors.internal.ui;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
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.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
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.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
/** A dialog to edit a multiplicity-many {@link EAttribute} */
public class NaryAttributeEditingDialog<T extends Object> extends AbstractNaryEditingDialog<T> {
private static final int NUM_COLUMNS = 2;
private TableViewer featureValuesTableViewer;
private final Object newValuePlaceholder = new Object();
private Button addButton;
private Button removeButton;
private Button upButton;
private Button downButton;
private final ColumnLabelProvider labelProvider = new ColumnLabelProvider() {
private final LabelProvider delegateLabelProvider = new CustomizableLabelProvider();
@Override
public Image getImage(final Object element) {
return this.delegateLabelProvider.getImage(element);
}
@Override
public String getText(final Object element) {
if (element == NaryAttributeEditingDialog.this.newValuePlaceholder) {
return Messages.NaryAttributeEditingDialog_enterNewValuePlaceholder;
}
return this.delegateLabelProvider.getText(element);
}
@Override
public Color getForeground(final Object element) {
if (element == NaryAttributeEditingDialog.this.newValuePlaceholder) {
return Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY);
}
return null;
}
};
/**
* @param parent
* the parent {@link Shell}
* @param values
* the current values
* @param editHandler
* the edit handler to perform the commit.
* @param feature
* the feature to edit
* @param eObject
* the eObject being currently edited. Should not be modified in this dialog.
*/
public NaryAttributeEditingDialog(final Shell shell, final List<T> values,
final IModelCellEditHandler editHandler, final EObject eObject, final EStructuralFeature feature) {
super(shell, values, editHandler, eObject, feature);
}
@Override
protected void configureShell(final Shell shell) {
super.configureShell(shell);
shell.setText(NLS.bind(Messages.NaryReferenceEditingDialog_shellTitle,
getFeature().getName(), geteObject().eClass().getName()));
// prevent Escape or Enter from closing the dialog
// when a cell editor is active
shell.addListener(SWT.Traverse, new Listener() {
public void handleEvent(final Event e) {
if ((e.detail == SWT.TRAVERSE_ESCAPE || e.detail == SWT.TRAVERSE_RETURN)
&& NaryAttributeEditingDialog.this.featureValuesTableViewer
.isCellEditorActive()) {
e.doit = false;
NaryAttributeEditingDialog.this.featureValuesTableViewer.cancelEditing();
}
}
});
}
@Override
protected Control createDialogArea(final Composite parent) {
final Composite contents = (Composite) super.createDialogArea(parent);
final GridLayout contentsGridLayout = (GridLayout) contents.getLayout();
contentsGridLayout.numColumns = NaryAttributeEditingDialog.NUM_COLUMNS;
final GridData contentsGridData = (GridData) contents.getLayoutData();
contentsGridData.horizontalAlignment = SWT.FILL;
contentsGridData.verticalAlignment = SWT.FILL;
createValuesPane(contents);
createButtonsPane(contents);
this.featureValuesTableViewer.addOpenListener(new IOpenListener() {
public void open(final OpenEvent event) {
editSelectedElement();
}
});
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.removeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
removeButtonClicked();
}
});
return contents;
}
@SuppressWarnings("unchecked") // type erasure on generic
private void addButtonClicked() {
getValues().add(0, (T) NaryAttributeEditingDialog.this.newValuePlaceholder);
refresh();
this.featureValuesTableViewer.editElement(this.newValuePlaceholder, 0);
}
@SuppressWarnings("unchecked") // type erasure on generic
private void removeButtonClicked() {
final IStructuredSelection selection = (IStructuredSelection) this.featureValuesTableViewer
.getSelection();
for (final Iterator<T> it = selection.iterator(); it.hasNext();) {
final Object element = it.next();
if (getValues().contains(element)) {
getValues().remove(element);
}
}
refresh();
}
private void spacer(final Composite parent) {
@SuppressWarnings("unused")
Label label = new Label(parent, SWT.NONE);
}
private void createButtonsPane(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);
this.addButton = new Button(buttonsComposite, SWT.PUSH);
this.addButton.setText(Messages.NaryAttributeEditingDialog_add);
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.NaryAttributeEditingDialog_delete);
final GridData removeButtonGridData = new GridData();
removeButtonGridData.verticalAlignment = SWT.FILL;
removeButtonGridData.horizontalAlignment = SWT.FILL;
this.removeButton.setLayoutData(removeButtonGridData);
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 createValuesPane(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 Table table = new Table(featureComposite, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
final GridData tableGridData = new GridData();
tableGridData.widthHint = AbstractNaryEditingDialog.AVAILABLE_VALUES_TREE_WIDTH;
tableGridData.heightHint = AbstractNaryEditingDialog.AVAILABLE_VALUES_TREE_HEIGHT;
tableGridData.verticalAlignment = SWT.FILL;
tableGridData.horizontalAlignment = SWT.FILL;
tableGridData.grabExcessHorizontalSpace = true;
tableGridData.grabExcessVerticalSpace = true;
table.setLayoutData(tableGridData);
final TableColumn tableColumn = new TableColumn(table, SWT.CENTER);
// full-width column
table.addControlListener(new ControlListener() {
public void controlResized(final ControlEvent e) {
tableColumn.setWidth(table.getClientArea().width);
}
public void controlMoved(final ControlEvent e) {
//
}
});
this.featureValuesTableViewer = new TableViewer(table);
this.featureValuesTableViewer.setContentProvider(new AssignedValuesContentProvider());
// this.fFeatureValuesTableViewer.setLabelProvider(this.labelProvider);
this.featureValuesTableViewer
.setInput(getValues());
final TableViewerColumn tableViewerColumn = new TableViewerColumn(
this.featureValuesTableViewer, tableColumn);
tableViewerColumn.setLabelProvider(this.labelProvider);
tableViewerColumn.setEditingSupport(new ModelCellsEditingSupport<T>(
this.featureValuesTableViewer, getFeature(), geteObject(),
this.newValuePlaceholder, getValues()));
// keyboard accessibility
table.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent e) {
if (e.keyCode == SWT.F2) {
editSelectedElement();
}
if (e.keyCode == SWT.DEL) {
if (NaryAttributeEditingDialog.this.removeButton.isEnabled()) {
NaryAttributeEditingDialog.this.removeButton.notifyListeners(
SWT.Selection, null);
}
}
if (e.keyCode == SWT.ARROW_UP
&& ((e.stateMask & SWT.COMMAND) != 0 || (e.stateMask & SWT.CONTROL) != 0)) {
if (NaryAttributeEditingDialog.this.upButton.isEnabled()) {
NaryAttributeEditingDialog.this.upButton.notifyListeners(SWT.Selection,
null);
}
}
if (e.keyCode == SWT.ARROW_DOWN
&& ((e.stateMask & SWT.COMMAND) != 0 || (e.stateMask & SWT.CONTROL) != 0)) {
if (NaryAttributeEditingDialog.this.downButton.isEnabled()) {
NaryAttributeEditingDialog.this.downButton.notifyListeners(SWT.Selection,
null);
}
}
}
});
}
private void editSelectedElement() {
ISelection selection = NaryAttributeEditingDialog.this.featureValuesTableViewer
.getSelection();
if (selection instanceof IStructuredSelection) {
IStructuredSelection structuredSelection = (IStructuredSelection) selection;
if (structuredSelection.getFirstElement() != null) {
NaryAttributeEditingDialog.this.featureValuesTableViewer.editElement(
structuredSelection.getFirstElement(), 0);
}
}
}
@Override
public void refresh() {
this.featureValuesTableViewer.refresh();
}
@Override
protected boolean isResizable() {
return true;
}
@Override
protected void createButtonsForButtonBar(final Composite parent) {
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
}
@Override
public ISelection getSelection() {
return this.featureValuesTableViewer.getSelection();
}
}