Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into planger/issues/42
Browse files Browse the repository at this point in the history
Conflicts:
	plugins/org.eclipse.papyrus.uml.interaction.model/src/org/eclipse/papyrus/uml/interaction/internal/model/commands/SetCoveredCommand.java
  • Loading branch information
planger committed Nov 14, 2018
2 parents 4d9bb77 + 688f8a7 commit b38db93
Show file tree
Hide file tree
Showing 20 changed files with 1,423 additions and 342 deletions.
Expand Up @@ -17,7 +17,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.13.0,4.0.0)",
org.eclipse.papyrus.uml.service.types;bundle-version="[3.1.0,4.0.0)",
org.eclipse.papyrus.infra.gmfdiag.preferences;bundle-version="[3.0.0,4.0.0)",
org.eclipse.papyrus.uml.diagram.css;bundle-version="[2.0.0,3.0.0)",
org.eclipse.e4.ui.css.core;bundle-version="[0.12.101,1.0.0)"
org.eclipse.e4.ui.css.core;bundle-version="[0.12.101,1.0.0)",
org.eclipse.papyrus.infra.gmfdiag.dnd;bundle-version="[1.3.0,2.0.0)"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Bundle-Localization: plugin
Expand Down
Expand Up @@ -22,8 +22,10 @@
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gmf.runtime.diagram.ui.editparts.BorderedBorderItemEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderItemEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
Expand All @@ -37,6 +39,7 @@
import org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.edit.policies.ExecutionSpecificationGraphicalNodeEditPolicy;
import org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.edit.policies.InteractionSemanticEditPolicy;
import org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.locators.ExecutionSpecificationBorderItemLocator;
import org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.tools.SequenceDragTracker;
import org.eclipse.papyrus.uml.interaction.model.MInteraction;
import org.eclipse.papyrus.uml.interaction.model.MLifeline;

Expand Down Expand Up @@ -144,4 +147,16 @@ private void refreshEditPartOfShape(Shape shape) {
}
}

// The superclass does not delegate to edit-policies to get the drag tracker
@Override
public DragTracker getDragTracker(Request request) {
// We support dragging and dropping onto another lifeline
return new SequenceDragTracker(this) {

@Override
protected boolean isMove() {
return super.isMove();
}
};
}
}
Expand Up @@ -15,26 +15,47 @@
import static org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.edit.policies.PrivateRequestUtils.isAllowSemanticReordering;
import static org.eclipse.papyrus.uml.interaction.internal.model.commands.DependencyContext.defer;
import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.as;
import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.filter;
import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.flatMapToInt;
import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.flatMapToObj;
import static org.eclipse.papyrus.uml.interaction.model.util.Optionals.mapToInt;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Supplier;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.tools.ResizeTracker;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderItemEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.figures.IBorderItemLocator;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.edit.parts.LifelineBodyEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.locators.OnLineBorderItemLocator;
import org.eclipse.papyrus.uml.diagram.sequence.runtime.internal.tools.SequenceResizeTracker;
import org.eclipse.papyrus.uml.interaction.model.CreationCommand;
import org.eclipse.papyrus.uml.interaction.model.MElement;
import org.eclipse.papyrus.uml.interaction.model.MExecution;
import org.eclipse.papyrus.uml.interaction.model.MInteraction;
import org.eclipse.papyrus.uml.interaction.model.MLifeline;
import org.eclipse.papyrus.uml.interaction.model.MMessageEnd;
import org.eclipse.papyrus.uml.interaction.model.MOccurrence;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ExecutionOccurrenceSpecification;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.OccurrenceSpecification;

/**
Expand All @@ -61,7 +82,7 @@ protected MExecution getExecution() {
}

@Override
protected Command getSetBoundsCommand(ChangeBoundsRequest request, Node execShape, Rectangle newBounds) {
protected Command getResizeCommand(ChangeBoundsRequest request, Node execShape, Rectangle newBounds) {
org.eclipse.emf.common.command.Command result = null;

MExecution execution = getExecution();
Expand Down Expand Up @@ -143,4 +164,165 @@ protected Supplier<? extends org.eclipse.emf.common.command.Command> move(MExecu
protected ResizeTracker getResizeTracker(int direction) {
return new SequenceResizeTracker((GraphicalEditPart)getHost(), direction);
}

@Override
protected Command getMoveCommand(ChangeBoundsRequest request, Node execShape, Rectangle newBounds) {
org.eclipse.emf.common.command.Command result = null;

MExecution execution = getExecution();

// Check for semantic re-ordering
if (!isAllowSemanticReordering(request)
&& impliesFragmentReordering(execution, execShape, newBounds)) {
return UnexecutableCommand.INSTANCE;
}

OptionalInt top = execution.getTop();
OptionalInt bottom = execution.getBottom();

int absTop = getLayoutHelper().toAbsoluteY(execShape, newBounds.y());
int absBottom = getLayoutHelper().toAbsoluteY(execShape, newBounds.bottom());

if (top.isPresent() && (top.getAsInt() != absTop) && bottom.isPresent()
&& (bottom.getAsInt() != absBottom)) {

result = getMoveExecutionCommand(request, execution, absTop, absBottom);
}

return wrap(result);
}

protected boolean impliesFragmentReordering(MExecution execution, Node execShape, Rectangle newBounds) {
MInteraction interaction = execution.getInteraction();
List<InteractionFragment> fragments = interaction.getElement().getFragments();

// Get the element above that is being moved and could be re-ordered
Optional<? extends MElement<? extends Element>> normalizedStart = execution.getStart();
Optional<MMessageEnd> startEnd = as(normalizedStart, MMessageEnd.class);
if (startEnd.filter(MMessageEnd::isReceive).isPresent()) {
// Take the send end
normalizedStart = startEnd.flatMap(MMessageEnd::getOtherEnd);
}
OptionalInt startIndex = filter(
mapToInt(normalizedStart, start -> fragments.indexOf(start.getElement())), i -> i > 0);
Optional<? extends MElement<? extends Element>> above = flatMapToObj(startIndex,
i -> interaction.getElement(fragments.get(i - 1)));

// Get the element below that is being moved and could be re-ordered
Optional<? extends MElement<? extends Element>> normalizedFinish = execution.getFinish();
Optional<MMessageEnd> finishEnd = as(normalizedFinish, MMessageEnd.class);
if (finishEnd.filter(MMessageEnd::isSend).isPresent()) {
// Take the receive end
normalizedFinish = finishEnd.flatMap(MMessageEnd::getOtherEnd);
}
OptionalInt finishIndex = filter(
mapToInt(normalizedFinish, finish -> fragments.indexOf(finish.getElement())),
i -> i < (fragments.size() - 1));
Optional<? extends MElement<? extends Element>> below = flatMapToObj(finishIndex,
i -> interaction.getElement(fragments.get(i + 1)));

int absNewTop = getLayoutHelper().toAbsoluteY(execShape, newBounds.y());
int absNewBottom = getLayoutHelper().toAbsoluteY(execShape, newBounds.bottom());
return filter(flatMapToInt(above, MElement::getBottom), b -> b >= absNewTop).isPresent()
|| filter(flatMapToInt(below, MElement::getTop), t -> t <= absNewBottom).isPresent();
}

protected org.eclipse.emf.common.command.Command getMoveExecutionCommand(ChangeBoundsRequest request,
MExecution execution, int top, int bottom) {

org.eclipse.emf.common.command.Command result = null;

// TODO: Handle changing lifeline
MLifeline newOwner = execution.getOwner();

if (isAllowSemanticReordering(request)) {
// TODO: handle semantic reordering
}

result = chain(result, execution.setOwner(newOwner, OptionalInt.of(top), OptionalInt.of(bottom)));

return result;
}

@Override
protected void showChangeBoundsFeedback(ChangeBoundsRequest request) {
Point moveDelta = request.getMoveDelta();
Dimension sizeDelta = request.getSizeDelta();

if ((sizeDelta != null) && ((sizeDelta.width != 0) || (sizeDelta.height != 0))) {
// If there's a resize involved, then don't support dropping on another lifeline
showChangeBoundsFeedback(request.getMoveDelta(), sizeDelta);
return;
}

LifelineBodyEditPart thisLifeline = null;
for (EditPart parent = getHost().getParent(); (thisLifeline == null)
&& (parent != null); parent = parent.getParent()) {
if (parent instanceof LifelineBodyEditPart) {
thisLifeline = (LifelineBodyEditPart)parent;
}
}
if (thisLifeline == null) {
showChangeBoundsFeedback(moveDelta, sizeDelta);
return;
}

Point pointer = request.getLocation();
EditPart dropLifeline = ((GraphicalViewer)getHost().getViewer()).findObjectAtExcluding(pointer,
Collections.singleton(thisLifeline.getFigure()), LifelineBodyEditPart.class::isInstance);
if (!(dropLifeline instanceof LifelineBodyEditPart)) {
// Not dropping on some other lifeline
showChangeBoundsFeedback(moveDelta, sizeDelta);
return;
}

// Create a border-item locator for the lifeline we're dropping on
IFigure dropLifelineFigure = ((LifelineBodyEditPart)dropLifeline).getFigure();
IBorderItemLocator borderItemLocator = new OnLineBorderItemLocator(dropLifelineFigure);

// Constrain the lifeline drop to the original Y location
moveDelta = moveDelta.getCopy();
moveDelta.setY(0);

showChangeBoundsFeedback(moveDelta, null, dropLifelineFigure, borderItemLocator);
}

protected void showChangeBoundsFeedback(Point moveDelta, Dimension sizeDelta) {
IBorderItemEditPart borderItemEP = (IBorderItemEditPart)getHost();
IBorderItemLocator borderItemLocator = borderItemEP.getBorderItemLocator();

if (borderItemLocator != null) {
showChangeBoundsFeedback(moveDelta, sizeDelta,
((GraphicalEditPart)getHost().getParent()).getFigure(), borderItemLocator);
}
}

protected void showChangeBoundsFeedback(Point moveDelta, Dimension sizeDelta, IFigure onLifeline,
IBorderItemLocator locator) {

if (locator != null) {
IBorderItemEditPart borderItemEP = (IBorderItemEditPart)getHost();
IFigure feedback = getDragSourceFeedbackFigure();
PrecisionRectangle rect = new PrecisionRectangle(getInitialFeedbackBounds().getCopy());
getHostFigure().getParent().translateToAbsolute(rect);

rect.translate(moveDelta);
if (sizeDelta != null) {
rect.resize(sizeDelta);
}

// And bring it into the lifeline's coördinate space
Rectangle lifelineBounds = onLifeline.getBounds().getCopy();
onLifeline.getParent().translateToAbsolute(lifelineBounds);
rect.translate(lifelineBounds.getLocation().getNegated());

IFigure borderItemfigure = borderItemEP.getFigure();
Rectangle realLocation = locator.getValidLocation(rect.getCopy(), borderItemfigure);
onLifeline.translateToAbsolute(realLocation);

feedback.translateToRelative(realLocation);
feedback.setBounds(realLocation);
}
}

}
@@ -0,0 +1,81 @@
/*****************************************************************************
* 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 java.util.OptionalInt;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
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;
import org.eclipse.papyrus.uml.interaction.model.MLifeline;
import org.eclipse.papyrus.uml.interaction.model.util.Optionals;
import org.eclipse.uml2.uml.ExecutionSpecification;
import org.eclipse.uml2.uml.Lifeline;

/**
* Edit policy for dropping elements onto the lifeline body.
*/
public class LifelineBodyDropEditPolicy extends DragDropEditPolicy implements ISequenceEditPolicy {

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

@Override
protected Command getDropElementCommand(EObject element, DropObjectsRequest request) {
Command result = null;

if (element instanceof ExecutionSpecification) {
Optional<MExecution> exec = Optionals
.as(getInteraction().getElement((ExecutionSpecification)element), MExecution.class);
return exec.map(e -> getDropExecutionCommand(e, request)).orElse(null);
}

return result;
}

/**
* Obtain a command that drops an {@code execution} specification onto the host lifeline.
*
* @param execution
* an execution specification to drop
* @param request
* the drop request
* @return the command, or {@code null} if none
*/
protected Command getDropExecutionCommand(MExecution execution, DropObjectsRequest request) {
Optional<MLifeline> lifeline = getHostLifeline();

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);
}

protected Optional<MLifeline> getHostLifeline() {
Optional<Lifeline> lifeline = as(Optional.ofNullable(getHostObject()), Lifeline.class);
return lifeline.flatMap(getInteraction()::getLifeline);
}
}

0 comments on commit b38db93

Please sign in to comment.