From 2510711e6871542910d2ea1f56e1778560b8107e Mon Sep 17 00:00:00 2001 From: vlorenzo Date: Wed, 16 Oct 2013 13:19:20 +0200 Subject: 419575: [Table 2] Set value by Drag&Drop from the model explorer is not supported https://bugs.eclipse.org/bugs/show_bug.cgi?id=419575 --- .../manager/cell/EMFFeatureValueCellManager.java | 83 ++++++++++- .../nattable/listener/NatTableDropListener.java | 153 +++++++++++++++++++-- .../nattable/manager/cell/CellManagerFactory.java | 22 +++ 3 files changed, 242 insertions(+), 16 deletions(-) (limited to 'extraplugins') diff --git a/extraplugins/table/org.eclipse.papyrus.infra.emf.nattable/src/org/eclipse/papyrus/infra/emf/nattable/manager/cell/EMFFeatureValueCellManager.java b/extraplugins/table/org.eclipse.papyrus.infra.emf.nattable/src/org/eclipse/papyrus/infra/emf/nattable/manager/cell/EMFFeatureValueCellManager.java index 825c7343238..297e2a3a5cf 100644 --- a/extraplugins/table/org.eclipse.papyrus.infra.emf.nattable/src/org/eclipse/papyrus/infra/emf/nattable/manager/cell/EMFFeatureValueCellManager.java +++ b/extraplugins/table/org.eclipse.papyrus.infra.emf.nattable/src/org/eclipse/papyrus/infra/emf/nattable/manager/cell/EMFFeatureValueCellManager.java @@ -14,21 +14,35 @@ package org.eclipse.papyrus.infra.emf.nattable.manager.cell; import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.Map; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.command.UnexecutableCommand; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.gmf.runtime.emf.type.core.requests.AbstractEditCommandRequest; import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.papyrus.commands.wrappers.EMFtoGMFCommandWrapper; import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper; import org.eclipse.papyrus.infra.emf.utils.EMFStringValueConverter; import org.eclipse.papyrus.infra.nattable.manager.cell.AbstractCellManager; +import org.eclipse.papyrus.infra.nattable.manager.cell.CellManagerFactory; +import org.eclipse.papyrus.infra.nattable.manager.cell.ICellManager; import org.eclipse.papyrus.infra.nattable.manager.table.INattableModelManager; import org.eclipse.papyrus.infra.nattable.paste.IValueSetter; import org.eclipse.papyrus.infra.nattable.paste.ReferenceValueSetter; @@ -39,6 +53,7 @@ import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils; import org.eclipse.papyrus.infra.services.edit.service.IElementEditService; import org.eclipse.papyrus.infra.tools.converter.AbstractStringValueConverter; import org.eclipse.papyrus.infra.tools.converter.ConvertedValueContainer; +import org.eclipse.swt.widgets.Display; /** * Cell Manager which allows to get the value of an {@link EStructuralFeature} for an {@link EObject} @@ -170,7 +185,73 @@ public class EMFFeatureValueCellManager extends AbstractCellManager { protected Command getSetValueCommand(final TransactionalEditingDomain domain, final EObject elementToEdit, final EStructuralFeature featureToEdit, final Object newValue) { final AbstractEditCommandRequest request = new SetRequest(domain, elementToEdit, featureToEdit, newValue); final IElementEditService provider = ElementEditServiceUtils.getCommandProvider(elementToEdit); - return new GMFtoEMFCommandWrapper(provider.getEditCommand(request)); + final ICommand cmd = provider.getEditCommand(request); + ICommand returnedCommand = cmd; + if(cmd.canExecute() && featureToEdit instanceof EReference) { + boolean shouldOpenDialog = false; + final EReference editedReference = (EReference)featureToEdit; + + //we are editing a containment feature + if(editedReference.isContainment()) { + if(newValue instanceof Collection) { + if(!editedReference.isMany()) { + return UnexecutableCommand.INSTANCE; + } else { + final Collection currentValues = new ArrayList((Collection)elementToEdit.eGet(editedReference)); + final Collection addedValues = new ArrayList((Collection)newValue); + addedValues.removeAll((Collection)currentValues); + //we need to test the added values + final Iterator iter = ((Collection)addedValues).iterator(); + while(iter.hasNext() && !shouldOpenDialog) { + final Object current = iter.next(); + if(current instanceof EObject) { + if(elementToEdit == current) { + //an element can be owned by itself + return UnexecutableCommand.INSTANCE; + } else { + shouldOpenDialog = ((EObject)current).eContainer() != elementToEdit; + } + } + } + } + } else if(elementToEdit == newValue) { + //an element can be owned by itself + return UnexecutableCommand.INSTANCE; + } else if(newValue instanceof EObject) { + shouldOpenDialog = ((EObject)newValue).eContainer() != elementToEdit; + } + + if(shouldOpenDialog) { + returnedCommand = getOpenConfirmChangeContainmentDialogCommand(domain, returnedCommand, editedReference.isMany()); + } + + } + } + return new GMFtoEMFCommandWrapper(returnedCommand); + } + + + protected final ICommand getOpenConfirmChangeContainmentDialogCommand(final TransactionalEditingDomain domain, final ICommand defaultCommand, final boolean isMany){ + final String messageDialog; + if(isMany) { + messageDialog = "Your are setting a value in a containment feature. This action will change the owner of the dropped element(s).\nContinue?"; + } else { + messageDialog = "Your are setting a value in a containment feature. The previous value will be erased and the owner of the dropped element(s) will be changed.\nContinue?"; + } + final ICommand cmd = new AbstractTransactionalCommand(domain, "Set Value Command Dialog", null) { + + @Override + protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException { + final boolean result = MessageDialog.openConfirm(Display.getDefault().getActiveShell(), "Set Containment Value", messageDialog); + if(result) { + defaultCommand.execute(monitor, info); + return CommandResult.newOKCommandResult(); + } else { + return CommandResult.newCancelledCommandResult(); + } + } + }; + return cmd; } /** diff --git a/extraplugins/table/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/listener/NatTableDropListener.java b/extraplugins/table/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/listener/NatTableDropListener.java index a38465ccbb8..ee8754c0734 100644 --- a/extraplugins/table/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/listener/NatTableDropListener.java +++ b/extraplugins/table/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/listener/NatTableDropListener.java @@ -13,13 +13,22 @@ *****************************************************************************/ package org.eclipse.papyrus.infra.nattable.listener; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.command.UnexecutableCommand; import org.eclipse.emf.edit.ui.dnd.LocalTransfer; +import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.core.services.ServicesRegistry; +import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForEObject; +import org.eclipse.papyrus.infra.nattable.Activator; +import org.eclipse.papyrus.infra.nattable.manager.cell.CellManagerFactory; import org.eclipse.papyrus.infra.nattable.manager.table.INattableModelManager; import org.eclipse.papyrus.infra.nattable.utils.LocationValue; import org.eclipse.swt.dnd.DND; @@ -27,30 +36,69 @@ import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.DropTargetListener; import org.eclipse.swt.graphics.Point; - +/** + * + * This listener allow to manage the drop inside the table + * + */ public class NatTableDropListener implements DropTargetListener { - + /** + * the table manager + */ private final INattableModelManager manager; + /** + * the location value to use to drop the elements + */ private LocationValue dropKindValue; + /** + * + * Constructor. + * + * @param manager + * the table manager + */ public NatTableDropListener(final INattableModelManager manager) { this.manager = manager; } + /** + * + * @see org.eclipse.swt.dnd.DropTargetListener#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) + * + * @param event + */ public void dragEnter(final DropTargetEvent event) { - + //nothing to do } - +/** + * + * @see org.eclipse.swt.dnd.DropTargetListener#dragLeave(org.eclipse.swt.dnd.DropTargetEvent) + * + * @param event + */ public void dragLeave(final DropTargetEvent event) { - + //nothing to do } + /** + * + * @see org.eclipse.swt.dnd.DropTargetListener#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent) + * + * @param event + */ public void dragOperationChanged(final DropTargetEvent event) { - + //nothing to do } + /** + * + * @see org.eclipse.swt.dnd.DropTargetListener#dragOver(org.eclipse.swt.dnd.DropTargetEvent) + * + * @param event + */ public void dragOver(final DropTargetEvent event) { this.dropKindValue = null; final LocalTransfer localTransfer = LocalTransfer.getInstance(); @@ -59,33 +107,42 @@ public class NatTableDropListener implements DropTargetListener { if(data instanceof IStructuredSelection) { structuredSelection = (IStructuredSelection)data; } - final Collection objectsToAdd = Collections.checkedCollection(structuredSelection.toList(), Object.class); + final List droppedElements = new ArrayList((Collection)structuredSelection.toList()); this.dropKindValue = this.manager.getLocationInTheTable(new Point(event.x, event.y)); int drop = DND.DROP_NONE; switch(this.dropKindValue.getKind()) { case AFTER_COLUMN_HEADER: - if(this.manager.canDropColumnsElement(objectsToAdd)) { + if(this.manager.canDropColumnsElement(droppedElements)) { drop = DND.DROP_DEFAULT; } break; case AFTER_ROW_HEADER: - if(this.manager.canDropRowElement(objectsToAdd)) { + if(this.manager.canDropRowElement(droppedElements)) { drop = DND.DROP_DEFAULT; } break; case COLUMN_HEADER: - if(this.manager.canInsertColumns(objectsToAdd, this.dropKindValue.getColumnIndex())) { + if(this.manager.canInsertColumns(droppedElements, this.dropKindValue.getColumnIndex())) { drop = DND.DROP_DEFAULT; } break; case ROW_HEADER: - if(this.manager.canInsertRow(objectsToAdd, this.dropKindValue.getRowIndex())) { + if(this.manager.canInsertRow(droppedElements, this.dropKindValue.getRowIndex())) { drop = DND.DROP_DEFAULT; } break; case CELL: - //TODO - drop = DND.DROP_NONE; + int rowIndex = this.dropKindValue.getRowIndex(); + int columnIndex = this.dropKindValue.getColumnIndex(); + final Object rowElement = this.manager.getRowElement(rowIndex); + final Object columnElement = this.manager.getColumnElement(columnIndex); + if(CellManagerFactory.INSTANCE.isCellEditable(columnElement, rowElement)) { + final TransactionalEditingDomain domain = getEditingDomain(); + final Command cmd = getDropSetValueCommand(domain, droppedElements); + if(cmd.canExecute()) { + drop = DND.DROP_DEFAULT; + } + } break; case UNKNOWN: drop = DND.DROP_NONE; @@ -97,13 +154,51 @@ public class NatTableDropListener implements DropTargetListener { event.detail = drop; } + /** + * + * @param droppedElements + * the dropped elements + * @return + * the command to set the value in the selected cell + */ + private Command getDropSetValueCommand(final TransactionalEditingDomain domain, final List droppedElements) { + int rowIndex = this.dropKindValue.getRowIndex(); + int columnIndex = this.dropKindValue.getColumnIndex(); + final Object rowElement = this.manager.getRowElement(rowIndex); + final Object columnElement = this.manager.getColumnElement(columnIndex); + if(CellManagerFactory.INSTANCE.isCellEditable(columnElement, rowElement)) { + Object newValue = null; + final Object currentValue = CellManagerFactory.INSTANCE.getCrossValue(columnElement, rowElement, this.manager); + if(currentValue instanceof Collection) { + //the dropped elements will be added to the current Value in case of multivalued cell + final Collection tmpNewValue = new ArrayList(); + tmpNewValue.addAll((Collection)currentValue); + tmpNewValue.addAll(droppedElements); + newValue = tmpNewValue; + } else if(droppedElements.size() == 1) { + newValue = droppedElements.get(0); + } else { + newValue = droppedElements; + } + final Command cmd = CellManagerFactory.INSTANCE.getSetCellValueCommand(domain, columnElement, rowElement, newValue, manager); + return cmd; + } + return UnexecutableCommand.INSTANCE; + } + + /** + * + * @see org.eclipse.swt.dnd.DropTargetListener#drop(org.eclipse.swt.dnd.DropTargetEvent) + * + * @param event + */ public void drop(final DropTargetEvent event) { //we drop the elements into the table LocalTransfer localTransfer = LocalTransfer.getInstance(); Object data = localTransfer.nativeToJava(event.currentDataType); if(data instanceof StructuredSelection) { final IStructuredSelection selection = (IStructuredSelection)data; - final List droppedElements = selection.toList(); + final List< Object> droppedElements = new ArrayList((Collection)selection.toList()); if(this.dropKindValue != null) { switch(this.dropKindValue.getKind()) { case AFTER_COLUMN_HEADER: @@ -119,7 +214,11 @@ public class NatTableDropListener implements DropTargetListener { this.manager.insertRows(droppedElements, this.dropKindValue.getRowIndex()); break; case CELL: - //TODO + final TransactionalEditingDomain domain = getEditingDomain(); + final Command cmd = getDropSetValueCommand(domain, droppedElements); + if(cmd.canExecute()) { + domain.getCommandStack().execute(cmd); + } break; case UNKNOWN: break; @@ -133,7 +232,31 @@ public class NatTableDropListener implements DropTargetListener { public void dropAccept(final DropTargetEvent event) { + //nothing to do + } + /** + * + * @return + * the Transactional Editing Domain to use to edit the model + */ + private TransactionalEditingDomain getEditingDomain() { + TransactionalEditingDomain domain = null; + ServicesRegistry registry = null; + try { + registry = ServiceUtilsForEObject.getInstance().getServiceRegistry(this.manager.getTable().getContext()); + } catch (ServiceException e) { + Activator.log.error(e); + } + + if(registry != null) { + try { + domain = registry.getService(TransactionalEditingDomain.class); + } catch (ServiceException e) { + Activator.log.error(e); + } + } + return domain; } } diff --git a/extraplugins/table/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/manager/cell/CellManagerFactory.java b/extraplugins/table/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/manager/cell/CellManagerFactory.java index fee12d8dd48..ab19f51bdb1 100644 --- a/extraplugins/table/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/manager/cell/CellManagerFactory.java +++ b/extraplugins/table/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/manager/cell/CellManagerFactory.java @@ -255,4 +255,26 @@ public final class CellManagerFactory { } + /** + * + * @param domain + * the editing domain + * @param columnElement + * the column element + * @param rowElement + * the row element + * @param newValue + * the new value + * @param tableManager + * the table manager + * @return + * the command to use to do the set value + */ + public Command getSetCellValueCommand(final TransactionalEditingDomain domain, final Object columnElement, final Object rowElement, final Object newValue, final INattableModelManager tableManager) { + final ICellManager cellManager = getCellManager(columnElement, rowElement); + if(cellManager != null) { + return cellManager.getSetValueCommand(domain, columnElement, rowElement, newValue, tableManager); + } + return UnexecutableCommand.INSTANCE; + } } -- cgit v1.2.3