/******************************************************************************* * Copyright (c) 2010, 2011 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: * Nicolas Bros (Mia-Software) - initial API and implementation * Nicolas Guyomar (Mia-Software) - Bug 339554 - org.eclipse.papyrus.emf.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.papyrus.emf.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.papyrus.emf.facet.widgets.celleditors.IModelCellEditHandler; import org.eclipse.papyrus.emf.facet.widgets.celleditors.internal.Messages; import org.eclipse.papyrus.emf.facet.widgets.internal.CustomizableLabelProvider; 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.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 extends AbstractNaryEditingDialog { 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 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 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( 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(); } }