diff options
Diffstat (limited to 'plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator')
4 files changed, 292 insertions, 129 deletions
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/CenterLocator.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/CenterLocator.java index b76858aad8f..780a84c2404 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/CenterLocator.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/CenterLocator.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010 CEA + * Copyright (c) 2010, 2018 CEA, Christian W. Damus, and others * * * All rights reserved. This program and the accompanying materials @@ -11,6 +11,7 @@ * * Contributors: * Atos Origin - Initial API and implementation + * Christian W. Damus - bug 536486 * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.sequence.locator; @@ -18,6 +19,7 @@ package org.eclipse.papyrus.uml.diagram.sequence.locator; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.gmf.runtime.diagram.ui.figures.BorderedNodeFigure; import org.eclipse.gmf.runtime.diagram.ui.internal.figures.BorderItemContainerFigure; import org.eclipse.gmf.runtime.gef.ui.figures.DefaultSizeNodeFigure; import org.eclipse.papyrus.uml.diagram.common.locator.AdvancedBorderItemLocator; @@ -64,6 +66,10 @@ public class CenterLocator extends AdvancedBorderItemLocator { BorderItemContainerFigure borderItemContainerFigure = getBorderItemContainerFigure(); if (borderItemContainerFigure != null) { for (Object child : borderItemContainerFigure.getChildren()) { + if (child instanceof BorderedNodeFigure) { + // Unwrap it (the destruction occurrence, itself, can have border items) + child = ((BorderedNodeFigure) child).getMainFigure(); + } if (child instanceof DefaultSizeNodeFigure) { for (Object figure : ((DefaultSizeNodeFigure) child).getChildren()) { if (figure instanceof DestructionEventFigure) { @@ -106,7 +112,8 @@ public class CenterLocator extends AdvancedBorderItemLocator { public Rectangle getValidLocation(Rectangle proposedLocation, IFigure borderItem) { // The valid position for destruction event is always the bottom if (getDestructionEventFigure() != null) { - if (borderItem.equals(getDestructionEventFigure().getParent())) { + // The destruction event supports border items, itself, so there are two levels of parent + if (borderItem.equals(getDestructionEventFigure().getParent().getParent())) { Rectangle realLocation = new Rectangle(proposedLocation); Point point = new Point(getParentBorder().getCenter().x - realLocation.getSize().width / 2, getParentBorder().y + getParentBorder().height - realLocation.height / 2); realLocation.setLocation(point); diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/DurationConstraintLocator.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/DurationConstraintLocator.java deleted file mode 100644 index 2ae0b926ab2..00000000000 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/DurationConstraintLocator.java +++ /dev/null @@ -1,127 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2017 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 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Celine Janssens (celine.janssens@all4tec.net) - Initial API and implementation - * - *****************************************************************************/ - -package org.eclipse.papyrus.uml.diagram.sequence.locator; - -import org.eclipse.draw2d.IFigure; -import org.eclipse.draw2d.geometry.Dimension; -import org.eclipse.draw2d.geometry.Rectangle; -import org.eclipse.papyrus.uml.diagram.common.locator.AdvancedBorderItemLocator; -import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.LifelineEditPart; - -/** - * @author Celine JANSSENS - * This class is used for Duration Constraint (@see {@link LifelineEditPart}) in order to locate it just next to the middle of it's parent (the Lifeline) on the X axe. - * The Y Axe is free except if the top is upper than its Parent. - */ -public class DurationConstraintLocator extends AdvancedBorderItemLocator { - - /** - * Constructor. - * - * @param borderItem - * @param parentFigure - * @param constraint - */ - public DurationConstraintLocator(IFigure borderItem, IFigure parentFigure, Rectangle constraint) { - super(borderItem, parentFigure, constraint); - - } - - /** - * Constructor. - * - */ - public DurationConstraintLocator(IFigure parentFigure) { - super(parentFigure); - } - - - /** - * Constructor. - * - */ - public DurationConstraintLocator(IFigure parentFigure, int position) { - super(parentFigure, position); - } - - /** - * @see org.eclipse.papyrus.uml.diagram.common.locator.AdvancedBorderItemLocator#relocate(org.eclipse.draw2d.IFigure) - * - * @param borderItem - */ - @Override - public void relocate(IFigure borderItem) { - Dimension size = getSize(borderItem); - // The returned constraint is relative to the parent - Rectangle rectSuggested = getConstraint(); - rectSuggested.setSize(size); - // transform it to absolute - Rectangle suggestedRectIndiagram = rectSuggested.getCopy(); - suggestedRectIndiagram.x = suggestedRectIndiagram.x + getParentFigure().getBounds().x; - suggestedRectIndiagram.y = suggestedRectIndiagram.y + getParentFigure().getBounds().y; - // get the valid Location in Absolute coordinates - suggestedRectIndiagram = getValidLocation(suggestedRectIndiagram, borderItem); - - // transform it back in relative coordinate to its parent. - borderItem.setBounds(suggestedRectIndiagram.getCopy()); - suggestedRectIndiagram.x = suggestedRectIndiagram.x - getParentFigure().getBounds().x; - suggestedRectIndiagram.y = suggestedRectIndiagram.y - getParentFigure().getBounds().y; - - // Set the new Constraint in Relative. - setConstraint(suggestedRectIndiagram); - - } - - /** - * - * The Valid location for a Duration Constraint is just next to the center of its parent (the lifeline). - * - * @see org.eclipse.papyrus.uml.diagram.common.locator.AdvancedBorderItemLocator#getValidLocation(org.eclipse.draw2d.geometry.Rectangle, org.eclipse.draw2d.IFigure) - * - * @param proposedLocation - * @param borderItem - * @return - */ - @Override - public Rectangle getValidLocation(Rectangle proposedLocation, IFigure borderItem) { - // the offset required to take the Lifeline Header height into account - int headerYOffset = 20; - - int parentMiddleX = getParentFigure().getBounds().x + (getParentFigure().getBounds().width / 2); - - // Place the DurationConstraint Just next to the lifeline (right or left depends on the proposedLocation ) - if (proposedLocation.x < parentMiddleX) { - proposedLocation.setX(parentMiddleX - proposedLocation.width()); - } else { - proposedLocation.setX(parentMiddleX); - - } - - // If the proposed Location is upper than the Parent Figure (The lifeline) , then set the location as close as possible from the top of the parent. - if (proposedLocation.y < getParentFigure().getBounds().y + headerYOffset) { - proposedLocation.setY(getParentFigure().getBounds().y + headerYOffset); - } - - // If the DurationConstraint is out of the Lifeline bottom then relocate it into the Lifeline - if (proposedLocation.y + proposedLocation.height > getParentFigure().getBounds().bottom()) { - proposedLocation.setY(getParentFigure().getBounds().bottom() - proposedLocation.height); - } - - - return super.getValidLocation(proposedLocation, borderItem); - } - -} diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/IntersectionPointSelectionLocator.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/IntersectionPointSelectionLocator.java new file mode 100644 index 00000000000..ac593325fbf --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/IntersectionPointSelectionLocator.java @@ -0,0 +1,54 @@ +/***************************************************************************** + * Copyright (c) 2018 CEA LIST, EclipseSource and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * EclipseSource - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.sequence.locator; + +import org.eclipse.draw2d.Connection; +import org.eclipse.draw2d.ConnectionLocator; +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.draw2d.geometry.PointList; +import org.eclipse.draw2d.geometry.Rectangle; + +/** ConnectionLocator that provides the location of the intersection point of two PointLists. */ +public class IntersectionPointSelectionLocator extends ConnectionLocator { + + private PointList pointList1; + private PointList pointList2; + + /** + * Constructor. + * + * @param connection + */ + public IntersectionPointSelectionLocator(Connection connection, PointList pointList1, PointList pointList2) { + super(connection); + this.pointList1 = pointList1; + this.pointList2 = pointList2; + } + + @Override + protected Point getLocation(PointList points) { + if (pointList1 == null || pointList2 == null) { + return super.getLocation(points); + } + + Rectangle intersect = pointList1.getBounds().intersect(pointList2.getBounds()); + if (!intersect.isEmpty()) { + return intersect.getLocation(); + } + // fallback to default (middle point) + return super.getLocation(points); + } +}
\ No newline at end of file diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/TimeElementLocator.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/TimeElementLocator.java new file mode 100644 index 00000000000..574071f4696 --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/locator/TimeElementLocator.java @@ -0,0 +1,229 @@ +/***************************************************************************** + * Copyright (c) 2018 CEA LIST, 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: + * CEA LIST - Initial API and implementation + * Christian W. Damus - bug 536486 + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.sequence.locator; + +import java.util.Optional; +import java.util.function.ToIntFunction; +import java.util.stream.Stream; + +import org.eclipse.draw2d.IFigure; +import org.eclipse.draw2d.PositionConstants; +import org.eclipse.draw2d.geometry.Dimension; +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gef.EditPart; +import org.eclipse.gmf.runtime.diagram.ui.figures.IBorderItemLocator; +import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure; +import org.eclipse.papyrus.uml.diagram.sequence.figures.DestructionEventNodePlate; +import org.eclipse.papyrus.uml.diagram.sequence.figures.LifelineFigure; +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.TimeConstraint; +import org.eclipse.uml2.uml.TimeObservation; + +/** + * Specific locator for {@link TimeObservation} or {@link TimeConstraint} on exec spec. + */ +public class TimeElementLocator implements IBorderItemLocator { + + private final IBorderItemLocator centeringDelegate; + + private IFigure parentFigure; + private Rectangle constraint; + private ToIntFunction<? super Rectangle> sideFunction; + + /** + * Initializes me with my parent figure and a function that computes the side on + * which to place the time element based on a proposed locating rectangle. + * + * @param parentFigure + * the parent figure + * @param sideFunction + * the proposed rectangle to side function. Valid outputs of the + * side function are the NSEW and {@link PositionConstants#CENTER CENTER} + * values of the {@link PositionConstants} + */ + public TimeElementLocator(IFigure parentFigure, ToIntFunction<? super Rectangle> sideFunction) { + super(); + + this.setParentFigure(parentFigure); + this.sideFunction = sideFunction; + + this.centeringDelegate = new CenterLocator(parentFigure, PositionConstants.NONE); + } + + @Override + public void setConstraint(Rectangle constraint) { + this.constraint = constraint; + } + + private Rectangle getConstraint() { + return constraint; + } + + @Override + public Rectangle getValidLocation(Rectangle proposedLocation, IFigure borderItem) { + Rectangle realLocation = new Rectangle(proposedLocation); + Point newTopLeft = locateOnBorder(realLocation, borderItem); + realLocation.setLocation(newTopLeft); + return realLocation; + } + + @Override + public int getCurrentSideOfParent() { + if (getConstraint().y() >= 10) { + return PositionConstants.SOUTH; + } + return PositionConstants.NORTH; + } + + @Override + public void relocate(IFigure borderItem) { + Dimension size = getSize(borderItem); + Rectangle rectSuggested = new Rectangle( + getPreferredLocation(borderItem), size); + + // Point ptNewLocation = locateOnBorder(rectSuggested, borderItem); + borderItem.setBounds(rectSuggested); + } + + protected Point locateOnBorder(Rectangle rectSuggested, IFigure borderItem) { + Point relativeItem = rectSuggested.getTopLeft(); + Rectangle parentBounds = getParentFigure().getBounds(); + Rectangle itemBounds = borderItem.getBounds(); + + // On which side? + int side = sideFunction.applyAsInt(rectSuggested); + switch (side) { + case PositionConstants.WEST: // Applied on the lifeline head + relativeItem.setLocation(-(itemBounds.width() / 2), + getLifelineHead().height() / 2); + break; + case PositionConstants.EAST: // Applied on the lifeline head + relativeItem.setLocation(parentBounds.width() - (itemBounds.width() / 2), + getLifelineHead().height() / 2); + break; + case PositionConstants.NORTH: // Applied on an execution specification + relativeItem.setLocation((parentBounds.width() - rectSuggested.width()) / 2, 0); + break; + case PositionConstants.SOUTH: // Applied on an execution specification + relativeItem.setLocation((parentBounds.width() - rectSuggested.width()) / 2, + parentBounds.height()); + break; + case PositionConstants.CENTER: // Applied on a destruction occurrence and lifeline + if (isOnDestructionOccurrence()) { + // Center vertically, also + relativeItem.setLocation((parentBounds.width() - itemBounds.width()) / 2, + parentBounds.height() / 2); + } else { + return centeringDelegate.getValidLocation(rectSuggested, borderItem) + .getLocation(); + } + break; + default: + throw new IllegalArgumentException("unsupported side: " + side); + } + + Point result = getAbsoluteToBorder(relativeItem); + return result; + } + + protected boolean isOnDestructionOccurrence() { + return getParentFigure() instanceof DestructionEventNodePlate; + } + + protected Rectangle getLifelineHead() { + // The first (and only) child of the lifeline node plate is the lifeline figure + LifelineFigure lifeline = (LifelineFigure) getParentFigure().getChildren().get(0); + return lifeline.getHeaderFigure().getBounds(); + } + + protected IFigure getParentFigure() { + return parentFigure; + } + + protected void setParentFigure(IFigure parentFigure) { + this.parentFigure = parentFigure; + } + + /** + * Gets the size of the border item figure. + * + * @param borderItem + * the figure on border + * @return the size of the border item figure. + */ + protected final Dimension getSize(IFigure borderItem) { + Dimension size = getConstraint().getSize(); + if (size.isEmpty()) { + size = borderItem.getPreferredSize(); + } + return size; + } + + protected Point getPreferredLocation(IFigure borderItem) { + Point constraintLocation = locateOnBorder(getConstraint(), borderItem); + return constraintLocation; + } + + + /** + * Convert the relative coords in the model to ones that are Relative to the + * container (absolute in respect to the main figure) + * + * @param ptRelativeOffset + * @return point + */ + protected Point getAbsoluteToBorder(Point ptRelativeOffset) { + Point parentOrigin = getParentBorder().getTopLeft(); + return parentOrigin.translate(ptRelativeOffset); + } + + /** + * Utility to calculate the parent bounds with consideration for the handle + * bounds inset. + * + * @return <code>Rectangle</code> that is the bounds of the parent. + */ + protected Rectangle getParentBorder() { + Rectangle bounds = getParentFigure().getBounds().getCopy(); + if (getParentFigure() instanceof NodeFigure) { + bounds = ((NodeFigure) getParentFigure()).getHandleBounds() + .getCopy(); + } + return bounds; + } + + public static <T extends NamedElement> Optional<T> getTimedElement(EditPart timeElementEP, Class<T> type) { + return Optional.ofNullable(timeElementEP.getAdapter(EObject.class)) + .filter(NamedElement.class::isInstance).map(NamedElement.class::cast) + .flatMap(named -> getTimedElement(named, type)); + } + + public static <T extends NamedElement> Optional<T> getTimedElement(NamedElement timeElement, Class<T> type) { + Stream<T> timed = Stream.empty(); + + if (timeElement instanceof TimeConstraint) { + TimeConstraint constraint = (TimeConstraint) timeElement; + timed = constraint.getConstrainedElements().stream().filter(type::isInstance).map(type::cast); + } else if (timeElement instanceof TimeObservation) { + TimeObservation observation = (TimeObservation) timeElement; + timed = Stream.of(observation.getEvent()).filter(type::isInstance).map(type::cast); + } + + return timed.findFirst(); + } + +} |