Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas FAUVERGUE2018-09-18 07:53:00 -0400
committerPatrick Tessier2018-09-24 04:49:22 -0400
commit25c4a7bf6631eb1bd658d92ee035610811e326d9 (patch)
treeecb4f137525968cf37c228772622a00359b06ed1
parent4a72be5d308762ef1e329cbee86b0dc7956fae61 (diff)
downloadorg.eclipse.papyrus-25c4a7bf6631eb1bd658d92ee035610811e326d9.tar.gz
org.eclipse.papyrus-25c4a7bf6631eb1bd658d92ee035610811e326d9.tar.xz
org.eclipse.papyrus-25c4a7bf6631eb1bd658d92ee035610811e326d9.zip
Bug 538466: [Sequence] Lifelines should be resizable
Allow the resize of the lifeline but remove the possibility of resize over its existing elements. Change-Id: Ifa4498df7ebfd9ff595443667044ec2a7a9a33a8 Signed-off-by: Nicolas FAUVERGUE <nicolas.fauvergue@cea.fr>
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/policies/LifelineSelectionEditPolicy.java144
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/LifeLineXYLayoutEditPolicy.java82
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/SequenceUtil.java3
3 files changed, 189 insertions, 40 deletions
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/policies/LifelineSelectionEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/policies/LifelineSelectionEditPolicy.java
index cc0ab5b702e..485ebc839ee 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/policies/LifelineSelectionEditPolicy.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/policies/LifelineSelectionEditPolicy.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2010, 2017 CEA List, ALL4TEC and others
+ * Copyright (c) 2010, 2017-2018 CEA List, ALL4TEC 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,10 +11,12 @@
* Contributors:
* CEA List - Initial API and implementation
* Mickaël ADAM (ALL4TEC) mickael.adam@all4tec.net - Bug 522228
+ * Nicolas FAUVERGUE (CEA LIST) nicolas.fauvergue@cea.fr - Bug 538466
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.edit.policies;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.Cursors;
@@ -28,29 +30,167 @@ import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Handle;
import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.commands.Command;
import org.eclipse.gef.handles.MoveHandle;
import org.eclipse.gef.handles.MoveHandleLocator;
import org.eclipse.gef.handles.RelativeHandleLocator;
import org.eclipse.gef.handles.ResizeHandle;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.tools.ResizeTracker;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IPrimaryEditPart;
+import org.eclipse.gmf.runtime.draw2d.ui.figures.PolylineConnectionEx;
import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.papyrus.infra.gmfdiag.common.SemanticFromGMFElement;
import org.eclipse.papyrus.infra.gmfdiag.common.editpolicies.PapyrusResizableShapeEditPolicy;
+import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.AbstractExecutionSpecificationEditPart;
+import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.AbstractMessageEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.CombinedFragmentEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.LifelineEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.figures.LifelineFigure;
+import org.eclipse.papyrus.uml.diagram.sequence.util.LifelineEditPartUtil;
+import org.eclipse.papyrus.uml.diagram.sequence.util.LifelineMessageDeleteHelper;
+import org.eclipse.papyrus.uml.diagram.sequence.util.SequenceUtil;
import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.uml2.uml.ExecutionOccurrenceSpecification;
+import org.eclipse.uml2.uml.ExecutionSpecification;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.Lifeline;
+import org.eclipse.uml2.uml.Message;
+import org.eclipse.uml2.uml.MessageOccurrenceSpecification;
+import org.eclipse.uml2.uml.OccurrenceSpecification;
public class LifelineSelectionEditPolicy extends PapyrusResizableShapeEditPolicy {
public LifelineSelectionEditPolicy() {
- setResizeDirections(PositionConstants.WEST | PositionConstants.EAST);
+ setResizeDirections(PositionConstants.WEST | PositionConstants.EAST | PositionConstants.SOUTH);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.papyrus.infra.gmfdiag.common.editpolicies.PapyrusResizableShapeEditPolicy#getResizeCommand(org.eclipse.gef.requests.ChangeBoundsRequest)
+ */
+ @Override
+ protected Command getResizeCommand(final ChangeBoundsRequest request) {
+ LifelineEditPart llEditPart = (LifelineEditPart) getHost();
+ if (!LifelineMessageDeleteHelper.hasIncomingMessageDelete(llEditPart)) {
+
+ final Dimension sizeDelta = request.getSizeDelta();
+ final int moveHeight = sizeDelta.height();
+
+ if (moveHeight != 0) {
+
+ final Rectangle absoluteBounds = SequenceUtil.getAbsoluteBounds(llEditPart);
+ final Point pointFromWhichOneSearch = new Point(absoluteBounds.x + (absoluteBounds.width / 2), absoluteBounds.y + absoluteBounds.height);
+
+ // Get the last Y position of elements on life line
+ final int maxY = getLastPointOfLifeLineChildren(llEditPart, pointFromWhichOneSearch);
+
+ // Compare the last Y position with the current move to determinate if the resize can be done
+ if (maxY > (absoluteBounds.y + absoluteBounds.height() + moveHeight)) {
+ return null;
+ }
+ }
+
+ return super.getResizeCommand(request);
+ }
+ return null;
+ }
+
+ /**
+ * This allows to calculate the last Y position of elements on life line.
+ *
+ * @param lifelineEditPart
+ * The life line edit part.
+ * @param pointFromWhichOneSearch
+ * The last point of the life line.
+ * @return the last Y position of the last event on the life line.
+ */
+ protected int getLastPointOfLifeLineChildren(final LifelineEditPart lifelineEditPart, final Point pointFromWhichOneSearch) {
+ int maxY = 0;
+
+ final List<OccurrenceSpecification> previousEvents = LifelineEditPartUtil.getPreviousEventsFromPosition(pointFromWhichOneSearch, lifelineEditPart);
+
+ if (previousEvents != null && !previousEvents.isEmpty()) {
+ final OccurrenceSpecification lastPreviousEvent = previousEvents.get(previousEvents.size() - 1);
+ if (lastPreviousEvent instanceof ExecutionOccurrenceSpecification) {
+ final ExecutionSpecification execSpec = ((ExecutionOccurrenceSpecification) lastPreviousEvent).getExecution();
+ final IGraphicalEditPart editPart = getEditPartFromSemantic(execSpec);
+ if (editPart instanceof AbstractExecutionSpecificationEditPart) {
+ final EObject element = ((View) ((AbstractExecutionSpecificationEditPart) editPart).getAdapter(View.class)).getElement();
+
+ if (element instanceof ExecutionSpecification && null != ((ExecutionSpecification) element).getStart() && ((ExecutionSpecification) element).getStart().equals(lastPreviousEvent)) {
+ final Rectangle absoluteBounds = SequenceUtil.getAbsoluteBounds(editPart);
+
+ if (maxY < (absoluteBounds.y + absoluteBounds.height())) {
+ maxY = absoluteBounds.y + absoluteBounds.height();
+ }
+ }
+ }
+
+ } else if (lastPreviousEvent instanceof MessageOccurrenceSpecification) {
+ final Message message = ((MessageOccurrenceSpecification) lastPreviousEvent).getMessage();
+ final IGraphicalEditPart editPart = getEditPartFromSemantic(message);
+ if (editPart instanceof ConnectionEditPart) {
+ final EObject element = ((View) ((AbstractMessageEditPart) editPart).getAdapter(View.class)).getElement();
+ if (element instanceof Message && null != ((Message) element).getSendEvent() && ((Message) element).getSendEvent().equals(lastPreviousEvent)
+ || element instanceof Message && null != ((Message) element).getReceiveEvent() && ((Message) element).getReceiveEvent().equals(lastPreviousEvent)) {
+
+ PolylineConnectionEx polyline = (PolylineConnectionEx) ((ConnectionEditPart) editPart).getFigure();
+ Point anchorPositionOnScreen;
+ if (((Message) element).getSendEvent().equals(lastPreviousEvent)) {
+ anchorPositionOnScreen = polyline.getSourceAnchor().getReferencePoint();
+ } else {
+ anchorPositionOnScreen = polyline.getTargetAnchor().getReferencePoint();
+ }
+
+ if (maxY < anchorPositionOnScreen.y) {
+ maxY = anchorPositionOnScreen.y;
+ }
+ }
+ }
+ }
+ }
+
+ return maxY;
+ }
+
+ /**
+ * This method return the controller attached to the semantic element.
+ * The complexity of this algorithm is N (N the number of controller in the opened sequence diagram).
+ *
+ * @param semanticElement
+ * This must be different from null.
+ * @return The reference to the controller or null.
+ */
+ protected IGraphicalEditPart getEditPartFromSemantic(final Object semanticElement) {
+ IGraphicalEditPart researchedEditPart = null;
+ final SemanticFromGMFElement semanticFromGMFElement = new SemanticFromGMFElement();
+ final EditPartViewer editPartViewer = getHost().getViewer();
+ if (editPartViewer != null) {
+ // look for all edit part if the semantic is contained in the list
+ final Iterator<?> iter = editPartViewer.getEditPartRegistry().values().iterator();
+
+ while (iter.hasNext() && researchedEditPart == null) {
+ final Object currentEditPart = iter.next();
+ // look only amidst IPrimary editpart to avoid compartment and labels of links
+ if (currentEditPart instanceof IPrimaryEditPart) {
+ final Object currentElement = semanticFromGMFElement.getSemanticElement(currentEditPart);
+ if (semanticElement.equals(currentElement)) {
+ researchedEditPart = ((IGraphicalEditPart) currentEditPart);
+ }
+ }
+ }
+ }
+ return researchedEditPart;
}
@Override
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/LifeLineXYLayoutEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/LifeLineXYLayoutEditPolicy.java
index 72aa760245b..ef89d74c9ec 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/LifeLineXYLayoutEditPolicy.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/LifeLineXYLayoutEditPolicy.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2016 CEA LIST and others.
+ * Copyright (c) 2016, 2018 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 +11,7 @@
* Contributors:
* CEA LIST - Initial API and implementation
* Mickaël ADAM (ALL4TEC) mickael.adam@all4tec.net - Bug 526079
+ * Nicolas FAUVERGUE (CEA LIST) nicolas.fauvergue@cea.fr - Bug 538466
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.referencialgrilling;
@@ -62,7 +63,7 @@ import org.eclipse.papyrus.uml.diagram.sequence.edit.policies.SequenceReferenceE
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.ExecutionSpecificationUtil;
-import org.eclipse.papyrus.uml.diagram.sequence.util.LifelineEditPartUtil;
+import org.eclipse.papyrus.uml.diagram.sequence.util.LifelineMessageDeleteHelper;
import org.eclipse.papyrus.uml.diagram.sequence.util.LogOptions;
import org.eclipse.papyrus.uml.diagram.sequence.util.SequenceUtil;
import org.eclipse.papyrus.uml.service.types.element.UMLDIElementTypes;
@@ -282,15 +283,15 @@ public class LifeLineXYLayoutEditPolicy extends XYLayoutWithConstrainedResizedEd
newBounds.setLocation(new Point((parentBound.width / 2) - (AbstractExecutionSpecificationEditPart.DEFAUT_WIDTH / 2), newBounds.getLocation().y));
// Manage a collection of edit parts to skip during the calculation of new bounds (because the strong references are moved with the execution specification and the weak references can be moved with the execution specification)
- final Collection<EditPart> editPartsToSkipForCalculation = new HashSet<EditPart>();
- if(((EditPart) child).getEditPolicy(SequenceReferenceEditPolicy.SEQUENCE_REFERENCE) != null) {
+ final Collection<EditPart> editPartsToSkipForCalculation = new HashSet<>();
+ if (child.getEditPolicy(SequenceReferenceEditPolicy.SEQUENCE_REFERENCE) != null) {
final AbstractExecutionSpecificationEditPart execSpecEditPart = (AbstractExecutionSpecificationEditPart) child;
final SequenceReferenceEditPolicy references = (SequenceReferenceEditPolicy) execSpecEditPart.getEditPolicy(SequenceReferenceEditPolicy.SEQUENCE_REFERENCE);
editPartsToSkipForCalculation.addAll(references.getStrongReferences().keySet());
-
+
boolean mustMoveBelowAtMovingDown = UMLDiagramEditorPlugin.getInstance().getPreferenceStore().getBoolean(CustomDiagramGeneralPreferencePage.PREF_MOVE_BELOW_ELEMENTS_AT_MESSAGE_DOWN);
-
- if(mustMoveBelowAtMovingDown) {
+
+ if (mustMoveBelowAtMovingDown) {
editPartsToSkipForCalculation.addAll(references.getWeakReferences().keySet());
}
}
@@ -301,7 +302,7 @@ public class LifeLineXYLayoutEditPolicy extends XYLayoutWithConstrainedResizedEd
Rectangle boundsToRectangle = null;
CompoundCommand compoundCommand = null;
-
+
// Loop until found command for the execution specifications bounds (because by moving other execution specification, the first one can be moved another time).
do {
// Calculate the moved execution specification bounds
@@ -383,36 +384,43 @@ public class LifeLineXYLayoutEditPolicy extends XYLayoutWithConstrainedResizedEd
public Command getCommand(Request request) {
CompoundCommand cmd = new CompoundCommand();
- Command superCmd = super.getCommand(request);
- if (null != superCmd && superCmd.canExecute()) {
- cmd.add(superCmd);
- }
- // When resizing Lifeline, move the ES accordingly (only on the x direction)
- if (REQ_RESIZE.equals(request.getType()) && request instanceof ChangeBoundsRequest) {
- ChangeBoundsRequest boundsReq = (ChangeBoundsRequest) request;
- Dimension sizeDelta = boundsReq.getSizeDelta();
-
- List children = getHost().getChildren();
- Iterator iter = children.iterator();
- while (iter.hasNext()) {
- EditPart child = (EditPart) iter.next();
- Command moveChildrenCmd = null;
- if (child instanceof AbstractExecutionSpecificationEditPart) {
- AbstractExecutionSpecificationEditPart ES = (AbstractExecutionSpecificationEditPart) child;
- // Building the new Request for the ES
- ChangeBoundsRequest moveESRequest = new ChangeBoundsRequest(REQ_RESIZE);
- moveESRequest.setEditParts(ES);
- moveESRequest.setResizeDirection(boundsReq.getResizeDirection());
- moveESRequest.setMoveDelta(new Point(sizeDelta.width() / 2, 0));
- // Get the according command
- moveChildrenCmd = ES.getCommand(moveESRequest);
+ LifelineEditPart llEditPart = (LifelineEditPart) getHost();
+ if (!LifelineMessageDeleteHelper.hasIncomingMessageDelete(llEditPart)) {
- }
+ Command superCmd = super.getCommand(request);
+ if (null != superCmd && superCmd.canExecute()) {
+ cmd.add(superCmd);
+ }
- // for all the ES, add the get command
- if (null != moveChildrenCmd && moveChildrenCmd.canExecute()) {
- cmd.add(moveChildrenCmd);
+ // When resizing Lifeline, move the ES accordingly (only on the x direction)
+ if (REQ_RESIZE.equals(request.getType()) && request instanceof ChangeBoundsRequest) {
+ ChangeBoundsRequest boundsReq = (ChangeBoundsRequest) request;
+ Dimension sizeDelta = boundsReq.getSizeDelta();
+
+ if (sizeDelta.width > 0) {
+ List children = getHost().getChildren();
+ Iterator iter = children.iterator();
+ while (iter.hasNext()) {
+ EditPart child = (EditPart) iter.next();
+ Command moveChildrenCmd = null;
+ if (child instanceof AbstractExecutionSpecificationEditPart) {
+ AbstractExecutionSpecificationEditPart ES = (AbstractExecutionSpecificationEditPart) child;
+ // Building the new Request for the ES
+ ChangeBoundsRequest moveESRequest = new ChangeBoundsRequest(REQ_RESIZE);
+ moveESRequest.setEditParts(ES);
+ moveESRequest.setResizeDirection(boundsReq.getResizeDirection());
+ moveESRequest.setMoveDelta(new Point(sizeDelta.width() / 2, 0));
+ // Get the according command
+ moveChildrenCmd = ES.getCommand(moveESRequest);
+
+ }
+
+ // for all the ES, add the get command
+ if (null != moveChildrenCmd && moveChildrenCmd.canExecute()) {
+ cmd.add(moveChildrenCmd);
+ }
+ }
}
}
}
@@ -436,8 +444,8 @@ public class LifeLineXYLayoutEditPolicy extends XYLayoutWithConstrainedResizedEd
protected Command createAddCommand(ChangeBoundsRequest request, EditPart child, Object constraint) {
if (child instanceof LifelineEditPart || child instanceof CombinedFragmentEditPart || child instanceof InteractionUseEditPart) {
return UnexecutableCommand.INSTANCE;
- // The reparent of execution specification in another life line is not allowed
- } else if(child instanceof AbstractExecutionSpecificationEditPart && getHost() instanceof CLifeLineEditPart) {
+ // The reparent of execution specification in another life line is not allowed
+ } else if (child instanceof AbstractExecutionSpecificationEditPart && getHost() instanceof CLifeLineEditPart) {
final LifelineEditPart parentLifeLine = SequenceUtil.getParentLifelinePart(child);
if (null != parentLifeLine && !parentLifeLine.equals(getHost())) {
return UnexecutableCommand.INSTANCE;
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/SequenceUtil.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/SequenceUtil.java
index 39bbea92c33..30b1e48a67c 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/SequenceUtil.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/SequenceUtil.java
@@ -78,6 +78,7 @@ import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil;
import org.eclipse.papyrus.uml.diagram.common.helper.DurationConstraintHelper;
import org.eclipse.papyrus.uml.diagram.common.helper.InteractionFragmentHelper;
+import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.AbstractExecutionSpecificationEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.AbstractMessageEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.BehaviorExecutionSpecificationEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.CCombinedCompartmentEditPart;
@@ -697,7 +698,7 @@ public class SequenceUtil {
List<?> children = lifelineEditPart.getChildren();
for (Object child : children) {
// children executions
- if (child instanceof CCombinedCompartmentEditPart || child instanceof BehaviorExecutionSpecificationEditPart) {
+ if (child instanceof CCombinedCompartmentEditPart || child instanceof AbstractExecutionSpecificationEditPart) {
EObject element = ((GraphicalEditPart) child).resolveSemanticElement();
if (element instanceof ExecutionSpecification) {
// find start and finish events of the execution

Back to the top