diff options
author | Nicolas FAUVERGUE | 2019-05-23 07:35:06 +0000 |
---|---|---|
committer | Patrick Tessier | 2019-05-23 09:59:57 +0000 |
commit | 889f4d8cafc5b2a0225e9fa38be07157daca1e7e (patch) | |
tree | 67852b8e975bcef01c4dbbebf782744262dbb02a /plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse | |
parent | 4b2cf01b47527be213eedd1f024aba6557873001 (diff) | |
download | org.eclipse.papyrus-889f4d8cafc5b2a0225e9fa38be07157daca1e7e.tar.gz org.eclipse.papyrus-889f4d8cafc5b2a0225e9fa38be07157daca1e7e.tar.xz org.eclipse.papyrus-889f4d8cafc5b2a0225e9fa38be07157daca1e7e.zip |
Bug 542802: [SequenceDiagram] Undo after message creation removes other
elements from the model
- Manage the undo manually because an action was done silently after the
command execution that's re-order the items in interaction or
interaction operand, so the undo delete the wrong elements.
Change-Id: I3507d7ffe744ce19876aa6132312cb181dae3c5b
Signed-off-by: Nicolas FAUVERGUE <nicolas.fauvergue@cea.fr>
Diffstat (limited to 'plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse')
2 files changed, 140 insertions, 24 deletions
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/command/CreateExecutionSpecificationWithMessage.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/command/CreateExecutionSpecificationWithMessage.java index cff9fe915d7..8b14d785590 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/command/CreateExecutionSpecificationWithMessage.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/command/CreateExecutionSpecificationWithMessage.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2017 CEA LIST and others. + * Copyright (c) 2017, 2019 CEA LIST and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,6 +10,7 @@ * * Contributors: * CEA LIST - Initial API and implementation + * Nicolas FAUVERGUE (CEA LIST) nicolas.fauvergue@cea.fr - Bug 542802 * *****************************************************************************/ @@ -24,9 +25,12 @@ import java.util.stream.StreamSupport; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPart; @@ -44,7 +48,9 @@ import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequestFactory; import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; +import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.type.core.IHintedType; +import org.eclipse.gmf.runtime.emf.type.core.commands.DestroyElementCommand; import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.papyrus.commands.DestroyElementPapyrusCommand; @@ -56,17 +62,19 @@ import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.LifelineEditPart; import org.eclipse.papyrus.uml.diagram.sequence.messages.Messages; import org.eclipse.papyrus.uml.diagram.sequence.part.UMLDiagramEditorPlugin; import org.eclipse.papyrus.uml.diagram.sequence.preferences.CustomDiagramGeneralPreferencePage; +import org.eclipse.papyrus.uml.diagram.sequence.util.SequenceDeleteHelper; import org.eclipse.papyrus.uml.service.types.element.UMLDIElementTypes; +import org.eclipse.uml2.uml.DestructionOccurrenceSpecification; import org.eclipse.uml2.uml.ExecutionSpecification; +import org.eclipse.uml2.uml.Interaction; +import org.eclipse.uml2.uml.InteractionOperand; import org.eclipse.uml2.uml.Message; import org.eclipse.uml2.uml.MessageEnd; import org.eclipse.uml2.uml.OccurrenceSpecification; import org.eclipse.uml2.uml.UMLPackage; /** - * this class is used to automatically create execution specifications at target - * from the request in charge of creating a message between lifelines - * according to the preferences for this message sort + * This class is used to automatically create execution specifications at target from the request in charge of creating a message between lifelines according to the preferences for this message sort. */ public class CreateExecutionSpecificationWithMessage extends AbstractTransactionalCommand { @@ -78,6 +86,16 @@ public class CreateExecutionSpecificationWithMessage extends AbstractTransaction protected boolean createReply; /** + * This allows to stove the created execution specification needed for the undo. + */ + private ExecutionSpecification createdExecutionSpecification; + + /** + * This allows to store the created message reply needed for the undo. + */ + private Message createdMessageReply; + + /** * @param domain * @param request * the request that is in charge of creating the message @@ -93,15 +111,12 @@ public class CreateExecutionSpecificationWithMessage extends AbstractTransaction } /** - * @see org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand#doExecuteWithResult(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable) + * {@inheritDoc} * - * @param monitor - * @param info - * @return - * @throws ExecutionException + * @see org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand#doExecuteWithResult(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable) */ @Override - protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { + protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException { // 1. look for the message triggering the creation of the execution specification Message message = getMessage(); if (message == null) { @@ -118,6 +133,93 @@ public class CreateExecutionSpecificationWithMessage extends AbstractTransaction return CommandResult.newOKCommandResult(); } + /** + * {@inheritDoc} + * + * @see org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand#doUndo(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable) + */ + @Override + protected IStatus doUndo(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException { + + // Remove the reply message + if (null != createdMessageReply) { + // First delete the send and receive events + final MessageEnd sendEvent = createdMessageReply.getSendEvent(); + final MessageEnd receiveEvent = createdMessageReply.getReceiveEvent(); + + final CompoundCommand compoundCommand = new CompoundCommand(); + SequenceDeleteHelper.destroyMessageEvent(compoundCommand, sendEvent, getEditingDomain()); + if (false == receiveEvent instanceof DestructionOccurrenceSpecification) { + SequenceDeleteHelper.destroyMessageEvent(compoundCommand, receiveEvent, getEditingDomain()); + } + if (!compoundCommand.isEmpty() && compoundCommand.canExecute()) { + compoundCommand.execute(); + } + + // Destroy the graphical representation first + final CompositeTransactionalCommand compositeCommand = new CompositeTransactionalCommand(getEditingDomain(), "Remove message view"); //$NON-NLS-1$ + SequenceDeleteHelper.deleteView(compositeCommand, createdMessageReply, getEditingDomain()); + compositeCommand.execute(monitor, info); + + // Remove the reply message + final EObject container = createdMessageReply.eContainer(); + if (container instanceof Interaction) { + ((Interaction) container).getMessages().remove(createdMessageReply); + } + } + // Remove the execution specification + if (null != createdExecutionSpecification) { + // First delete its start and finish + final OccurrenceSpecification start = createdExecutionSpecification.getStart(); + final OccurrenceSpecification finish = createdExecutionSpecification.getFinish(); + final CompoundCommand compoundCommand = new CompoundCommand(); + + if (null != start) { + DestroyElementRequest delStart = new DestroyElementRequest(getEditingDomain(), start, false); + compoundCommand.add(new ICommandProxy(new DestroyElementCommand(delStart))); + } + if (null != finish) { + DestroyElementRequest delEnd = new DestroyElementRequest(getEditingDomain(), finish, false); + compoundCommand.add(new ICommandProxy(new DestroyElementCommand(delEnd))); + } + if (!compoundCommand.isEmpty() && compoundCommand.canExecute()) { + compoundCommand.execute(); + } + + // Destroy the graphical representation first + final CompositeTransactionalCommand compositeCommand = new CompositeTransactionalCommand(getEditingDomain(), "Remove execution specification view"); //$NON-NLS-1$ + SequenceDeleteHelper.deleteView(compositeCommand, createdExecutionSpecification, getEditingDomain()); + compositeCommand.execute(monitor, info); + // Remove the execution specification + final EObject container = createdExecutionSpecification.eContainer(); + if (container instanceof Interaction) { + ((Interaction) container).getFragments().remove(createdExecutionSpecification); + } else if (container instanceof InteractionOperand) { + ((InteractionOperand) container).getFragments().remove(createdExecutionSpecification); + } + } + + // Clear the stored values because the redo will fill this fields if needed + createdExecutionSpecification = null; + createdMessageReply = null; + + setResult(new CommandResult(Status.OK_STATUS)); + return Status.OK_STATUS; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand#doRedo(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable) + */ + @Override + protected IStatus doRedo(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException { + // Only re-execute the initial process + final CommandResult result = doExecuteWithResult(monitor, info); + + setResult(result); + return result.getStatus(); + } /** @@ -131,16 +233,17 @@ public class CreateExecutionSpecificationWithMessage extends AbstractTransaction requestcreation.setLocation(point); Command command = lifelineEditPart.getCommand(requestcreation); command.execute(); + // Save the created execution specification for the possible undo + createdExecutionSpecification = getCreatedElement(command, ExecutionSpecification.class); // case where a reply message must also be created if (createReply) { // Gets the created execution specification - ExecutionSpecification executionSpecification = getCreatedElement(command, ExecutionSpecification.class); - if (null != executionSpecification) { + if (null != createdExecutionSpecification) { Point replysourcepoint = point.getCopy(); replysourcepoint.setY(replysourcepoint.y + CustomActionExecutionSpecificationEditPart.DEFAULT_HEIGHT); // source of the reply message is the end of the execution specification - createReplyMessage(lifelineEditPart, executionSpecification, replysourcepoint); + createReplyMessage(lifelineEditPart, createdExecutionSpecification, replysourcepoint); } } } @@ -178,9 +281,10 @@ public class CreateExecutionSpecificationWithMessage extends AbstractTransaction replycommand.execute(); // replace execution Specification finish event by the message reply send event. - Message messageReply = getCreatedElement(replycommand, Message.class); - if (null != messageReply) { - MessageEnd sendEvent = messageReply.getSendEvent(); + // Save the created execution specification for the possible undo + createdMessageReply = getCreatedElement(replycommand, Message.class); + if (null != createdMessageReply) { + MessageEnd sendEvent = createdMessageReply.getSendEvent(); OccurrenceSpecification finish = executionSpecification.getFinish(); SetCommand setSendEventCommand = new SetCommand(getEditingDomain(), executionSpecification, UMLPackage.eINSTANCE.getExecutionSpecification_Finish(), sendEvent); setSendEventCommand.execute(); @@ -188,7 +292,8 @@ public class CreateExecutionSpecificationWithMessage extends AbstractTransaction // delete the old finish os. DestroyElementPapyrusCommand destroyElementPapyrusCommand = new DestroyElementPapyrusCommand(new DestroyElementRequest(finish, false)); if (destroyElementPapyrusCommand != null && destroyElementPapyrusCommand.canExecute()) { - getEditingDomain().getCommandStack().execute(new GMFtoEMFCommandWrapper(destroyElementPapyrusCommand)); + new GMFtoEMFCommandWrapper(destroyElementPapyrusCommand).execute(); + // getEditingDomain().getCommandStack().execute(new GMFtoEMFCommandWrapper(destroyElementPapyrusCommand)); } } } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/SequenceDeleteHelper.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/SequenceDeleteHelper.java index 541196959fe..9274494882b 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/SequenceDeleteHelper.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/SequenceDeleteHelper.java @@ -1,6 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010 CEA - * + * Copyright (c) 2010, 2019 CEA LIST and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,6 +10,7 @@ * * Contributors: * Atos Origin - Initial API and implementation + * Nicolas FAUVERGUE (CEA LIST) nicolas.fauvergue@cea.fr - Bug 542802 * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.sequence.util; @@ -125,7 +125,7 @@ public class SequenceDeleteHelper { if (lifelineChild instanceof IBorderItemEditPart) { final IBorderItemEditPart timePart = (IBorderItemEditPart) lifelineChild; OccurrenceSpecification start = execution.getStart(); - OccurrenceSpecification finish = execution.getStart(); + OccurrenceSpecification finish = execution.getFinish(); int positionForStart = SequenceUtil.positionWhereEventIsLinkedToPart(start, timePart); int positionForFinish = SequenceUtil.positionWhereEventIsLinkedToPart(finish, timePart); if (positionForStart != PositionConstants.NONE || positionForFinish != PositionConstants.NONE) { @@ -234,13 +234,24 @@ public class SequenceDeleteHelper { } } - static void destroyMessageEvent(CompoundCommand deleteElementsCommand, MessageEnd event, TransactionalEditingDomain transactionalEditingDomain) { + /** + * This allows to destroy a message event. + * + * @param deleteElementsCommand + * The compound command to fill. + * @param event + * The event to delete. + * @param transactionalEditingDomain + * The editing domain. + * @since 5.2 + */ + public static void destroyMessageEvent(final CompoundCommand deleteElementsCommand, final MessageEnd event, final TransactionalEditingDomain transactionalEditingDomain) { if (event != null) { - DestroyElementRequest myReq = new DestroyElementRequest(transactionalEditingDomain, event, false); + final DestroyElementRequest myReq = new DestroyElementRequest(transactionalEditingDomain, event, false); // Sometimes, the message end is also the end of a execution. - RestoreExecutionEndAdvice provider = new RestoreExecutionEndAdvice(); + final RestoreExecutionEndAdvice provider = new RestoreExecutionEndAdvice(); if (provider != null) { - ICommand editCommand = provider.getAfterEditCommand(myReq); + final ICommand editCommand = provider.getAfterEditCommand(myReq); if (editCommand != null && editCommand.canExecute()) { deleteElementsCommand.add(new ICommandProxy(editCommand)); } |