Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #411 Execution nesting changes #423

Merged
merged 4 commits into from
Nov 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.eclipse.papyrus.uml.interaction.model.MExecution;
import org.eclipse.papyrus.uml.interaction.model.MInteraction;
import org.eclipse.papyrus.uml.interaction.model.MObject;
import org.eclipse.papyrus.uml.interaction.model.spi.ViewTypes;
import org.eclipse.papyrus.uml.interaction.model.util.Optionals;
import org.eclipse.papyrus.uml.interaction.model.util.SequenceDiagramSwitch;
import org.eclipse.uml2.uml.Element;
Expand Down Expand Up @@ -74,8 +75,12 @@ public Command caseExecutionSpecification(IElementType type) {
}
}

return execution.insertNestedExecutionAfter(before.orElse(execution), offset,
size != null ? size.height : 40, eClass);
return execution
.insertNestedExecutionAfter(before.orElse(execution), offset,
size != null ? size.height
: getLayoutConstraints()
.getMinimumHeight(ViewTypes.EXECUTION_SPECIFICATION),
eClass);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*****************************************************************************
* Copyright (c) 2018 Christian W. Damus and others.
*
* 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:
* Christian W. Damus - Initial API and implementation
*****************************************************************************/

package org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.edit.policies;

import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.as;

import java.util.Optional;

import org.eclipse.papyrus.uml.interaction.model.MExecution;
import org.eclipse.papyrus.uml.interaction.model.MLifeline;
import org.eclipse.uml2.uml.ExecutionSpecification;

/**
* Edit policy for dropping elements onto an execution specification.
*/
public class ExecutionSpecificationDropEditPolicy extends LifelineBodyDropEditPolicy {

/**
* Initializes me.
*/
public ExecutionSpecificationDropEditPolicy() {
super();
}

@Override
protected Optional<MLifeline> getHostLifeline() {
Optional<ExecutionSpecification> execution = as(Optional.ofNullable(getHostObject()),
ExecutionSpecification.class);
return as(execution.flatMap(getInteraction()::getElement), MExecution.class)
.map(MExecution::getOwner);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@

package org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.edit.policies;

import static org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.edit.policies.PrivateRequestUtils.getChangeBoundsRequest;
import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.as;
import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.flatMap;
import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.map;
import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.mapToInt;

import java.util.Optional;
import java.util.OptionalInt;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DragDropEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest;
import org.eclipse.papyrus.uml.interaction.model.MExecution;
Expand Down Expand Up @@ -65,13 +71,19 @@ protected Command getDropElementCommand(EObject element, DropObjectsRequest requ
protected Command getDropExecutionCommand(MExecution execution, DropObjectsRequest request) {
Optional<MLifeline> lifeline = getHostLifeline();

// FIXME: Must allow non-reordering changes
if (!PrivateRequestUtils.isAllowSemanticReordering(request)) {
// Block the operation if the semantic override modifier is not applied
return UnexecutableCommand.INSTANCE;
}

return lifeline.map(ll -> wrap(execution.setOwner(ll, OptionalInt.empty(), OptionalInt.empty())))
.orElse(null);
Optional<Point> changeBounds = Optional.ofNullable(getChangeBoundsRequest(request))
.map(ChangeBoundsRequest::getMoveDelta);
OptionalInt deltaY = mapToInt(changeBounds, Point::y);
OptionalInt top = flatMap(execution.getTop(), t -> map(deltaY, y -> t + y));
OptionalInt bottom = flatMap(execution.getBottom(), b -> map(deltaY, y -> b + y));

return lifeline.map(ll -> wrap(execution.setOwner(ll, top, bottom))).orElse(null);
}

protected Optional<MLifeline> getHostLifeline() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public NoPapyrusEditPolicyProvider() {
withDrop(LifelineCreationEditPolicy::new, LifelineBodyDropEditPolicy::new));
substitute(InteractionCompartmentEditPart.class, EditPolicyRoles.CREATION_ROLE,
InteractionCreationEditPolicy::new);
substitute(ExecutionSpecificationEditPart.class, EditPolicyRoles.CREATION_ROLE,
ExecutionSpecificationCreationEditPolicy::new);
substitute(ExecutionSpecificationEditPart.class, EditPolicyRoles.CREATION_ROLE, withDrop(
ExecutionSpecificationCreationEditPolicy::new, ExecutionSpecificationDropEditPolicy::new));

// Diagram assistant edit policies
substitute(LifelineBodyEditPart.class, EditPolicyRoles.POPUPBAR_ROLE,
Expand Down Expand Up @@ -164,11 +164,13 @@ public void setHost(EditPart host) {
super.setHost(host);
}

@SuppressWarnings("unchecked")
@Override
protected DropObjectsRequest castToDropObjectsRequest(ChangeBoundsRequest request) {
DropObjectsRequest result = super.castToDropObjectsRequest(request);

PrivateRequestUtils.forwardParameters(request, result);
PrivateRequestUtils.setChangeBoundsRequest(result, request);

return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.Request;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest;

/**
* Utilities for working with private {@link Request}s and/or private details of {@code Request}s.
Expand All @@ -32,10 +34,12 @@ public final class PrivateRequestUtils {

private static final String ALLOW_SEMANTIC_REORDERING_PARAMETER = "__allow_semantic_reordering__"; //$NON-NLS-1$

private static final String CHANGE_BOUNDS_REQUEST_PARAMETER = "__change_bounds_request__"; //$NON-NLS-1$

private static final String[] PARAMETERS = { //
FORCE_PARAMETER, //
ORIGINAL_MOUSE_PARAMETER, ORIGINAL_SOURCE_PARAMETER, ORIGINAL_TARGET_PARAMETER, //
ALLOW_SEMANTIC_REORDERING_PARAMETER, //
ALLOW_SEMANTIC_REORDERING_PARAMETER, CHANGE_BOUNDS_REQUEST_PARAMETER, //
};

/**
Expand Down Expand Up @@ -198,4 +202,27 @@ public static void forwardParameters(Request fromRequest, Request toRequest) {
.filter(p -> !hasParameter(toRequest, p))
.forEach(p -> setParameter(toRequest, p, getParameter(fromRequest, p, Object.class, null)));
}

/**
* Records the change-bounds request that triggers a {@code drop}.
*
* @param drop
* a drop request
* @param changeBounds
* the change-bounds request that triggered it
*/
public static void setChangeBoundsRequest(DropObjectsRequest drop, ChangeBoundsRequest changeBounds) {
setParameter(drop, CHANGE_BOUNDS_REQUEST_PARAMETER, changeBounds);
}

/**
* Queries the change-bounds request that triggers a {@code drop}.
*
* @param drop
* a drop request
* @return the change-bounds request that triggered it
*/
public static ChangeBoundsRequest getChangeBoundsRequest(DropObjectsRequest drop) {
return getParameter(drop, CHANGE_BOUNDS_REQUEST_PARAMETER, ChangeBoundsRequest.class, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ private class MoveDownVisitor extends CommandBuildingVisitor<Vertex> {

private final int delta;

private Set<Shape> movingLifelineBodies = new HashSet<>();
private Set<Shape> movingShapes = new HashSet<>();

MoveDownVisitor(int delta) {
super();
Expand All @@ -134,10 +134,13 @@ protected void process(Vertex vertex) {
if (view instanceof Shape) {
// Move the shape down
Shape shape = (Shape)view;
if (!isShapeOnMovingLifeline(shape)) {
if (!isShapeOnMovingShape(shape)) {
int top = layoutHelper().getTop(shape);
chain(layoutHelper().setTop(shape, top + delta));
}

// Whether we moved it, or it's moving indirectly, it's moving
movingShapes.add(shape);
} else if (view instanceof Connector && element instanceof Message) {
// Move connector anchors down
Connector connector = (Connector)view;
Expand All @@ -163,12 +166,12 @@ protected void process(Vertex vertex) {
.map(Vertex.class::cast);
// Record that we're moving this
lifeline.map(Vertex::getDiagramView).map(diagramHelper()::getLifelineBodyShape)
.ifPresent(movingLifelineBodies::add);
.ifPresent(movingShapes::add);
Optional<Shape> shape = lifeline.map(Vertex::getDiagramView).map(Shape.class::cast);
shape.ifPresent(s -> chain(
layoutHelper().setTop(shape.get(), layoutHelper().getTop(s) + delta)));
} else if (targetVtx.hasTag(Tag.LIFELINE_DESTRUCTION)
&& !isShapeOnMovingLifeline(targetOn)) {
&& !isShapeOnMovingShape(targetOn)) {
// Move Destruction Shape if it's not moved implicitly by the lifeline it's on
Optional<Shape> shape = Optional.ofNullable(targetVtx.getDiagramView())
.filter(Shape.class::isInstance).map(Shape.class::cast);
Expand Down Expand Up @@ -229,12 +232,20 @@ private boolean isMessageEndNudgeCommand(Element element) {
*/
private boolean skipMove(Shape shape) {
return !ViewTypes.LIFELINE_BODY.equals(shape.getType()) //
|| movingLifelineBodies.contains(shape) //
|| isShapeOnMovingLifeline(shape);
|| movingShapes.contains(shape) //
|| isShapeOnMovingShape(shape);
}

private boolean isShapeOnMovingLifeline(Shape shape) {
return movingLifelineBodies.contains(shape.eContainer());
/**
* Is a shape on (a child of) a shape that is already being nudged, and so doesn't need to be nudged,
* itself?
*
* @param shape
* a shape to be nudged (perhaps)
* @return whether it is indirectly being nudged by being a child of a shape being nudged
*/
private boolean isShapeOnMovingShape(Shape shape) {
return movingShapes.contains(shape.eContainer());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,56 +12,44 @@

package org.eclipse.papyrus.uml.interaction.internal.model.commands;

import java.util.List;
import java.util.Optional;

import org.eclipse.papyrus.uml.interaction.model.MElement;
import org.eclipse.papyrus.uml.interaction.model.MExecution;
import org.eclipse.uml2.uml.Element;

/**
* A {@linkplain DependencyContext context} variable that records ownership change in progress.
*
* @see DependencyContext
*/
public final class PendingChildData {
private final MElement<? extends Element> owner;

private final MElement<? extends Element> child;
public final class PendingChildData extends PendingContainmentChangeData<MElement<? extends Element>, MElement<? extends Element>> {

private PendingChildData(MElement<? extends Element> owner, MElement<? extends Element> child) {
super();

this.owner = owner;
this.child = child;
super(owner, child);
}

/**
* Queries the owner of the pending {@linkplain #getPendingChild() owned element}.
* Query the element that is in process of having the given element set as its new {@code owner}.
*
* @return the owner element
* @param owner
* an element that may or may not be getting a new owned child
* @return the pending child element
*/
public MElement<? extends Element> getOwner() {
return owner;
public static Optional<MElement<? extends Element>> getPendingChild(MElement<? extends Element> owner) {
return PendingContainmentChangeData.getPendingChild(PendingChildData.class, owner);
}

/**
* Queries the element that is being assigned a {@linkplain #getOwner() new owner}.
*
* @return the owned element
*/
public MElement<? extends Element> getPendingChild() {
return child;
}

/**
* Query the element that is in process of having the given element set as its new {@code owner}.
* Query the elements that are in process of having the given element set as their new {@code owner}.
*
* @param owner
* an element that may or may not be getting a new owned child
* @return the pending child element
* @return the owned elements
*/
public static Optional<MElement<? extends Element>> getPendingChild(MElement<? extends Element> owner) {
return DependencyContext.get().get(owner, PendingChildData.class)
.map(PendingChildData::getPendingChild);
public static List<MElement<? extends Element>> getPendingChildren(MElement<? extends Element> owner) {
return PendingContainmentChangeData.getPendingChildren(PendingChildData.class, owner);
}

/**
Expand All @@ -72,8 +60,7 @@ public static Optional<MElement<? extends Element>> getPendingChild(MElement<? e
* @return the pending owner element
*/
public static Optional<MElement<? extends Element>> getPendingOwner(MElement<? extends Element> child) {
return DependencyContext.get().get(child, PendingOwnerData.class)
.map(PendingOwnerData::getPendingOwner);
return PendingContainmentChangeData.getPendingParent(PendingChildData.class, child);
}

/**
Expand All @@ -86,28 +73,14 @@ public static Optional<MElement<? extends Element>> getPendingOwner(MElement<? e
*/
static void setPendingChild(MElement<? extends Element> owner, MElement<? extends Element> pendingChild) {
if (owner.getElement() != pendingChild.getOwner().getElement()) {
DependencyContext ctx = DependencyContext.get();
PendingChildData childData = new PendingChildData(owner, pendingChild);
ctx.put(owner, childData);
ctx.put(pendingChild, new PendingOwnerData(childData));
}
}

//
// Nested types
//

private static final class PendingOwnerData {
private final PendingChildData childData;

PendingOwnerData(PendingChildData childData) {
super();

this.childData = childData;
}

MElement<? extends Element> getPendingOwner() {
return childData.getOwner();
PendingContainmentChangeData.setPendingChild(PendingChildData.class, owner, pendingChild,
PendingChildData::new);

if (pendingChild instanceof MExecution) {
// Its nested executions also get the new owner lifeline
((MExecution)pendingChild).getNestedExecutions()
.forEach(nested -> setPendingChild(owner, nested));
}
}
}

Expand Down
Loading