diff options
author | Asma Smaoui | 2018-03-09 13:46:57 +0000 |
---|---|---|
committer | Ansgar Radermacher | 2018-03-09 14:51:48 +0000 |
commit | c24fe36ff2ed08b048885e68a698dfa5a8f94878 (patch) | |
tree | 479f9d514dd5905faf52ed2fc462d34063b02ee1 /plugins | |
parent | 0dac77dfab1dd890604fd0d47a26eed191c79d1f (diff) | |
download | org.eclipse.papyrus-c24fe36ff2ed08b048885e68a698dfa5a8f94878.tar.gz org.eclipse.papyrus-c24fe36ff2ed08b048885e68a698dfa5a8f94878.tar.xz org.eclipse.papyrus-c24fe36ff2ed08b048885e68a698dfa5a8f94878.zip |
Bug 527181 - [Composite structure diagram] Initial port location on a
part is top-left corner
- Add possibility to override the initial port poisition in
ShowHidecontentsAction
- Create a custom port position for the composite-structure diagram that
locates
the diagram for the defining type (if any) and copies port positions
from there. Based
on similar code in PapyrusRT
- Add a new edit policy "CompositeSideAffixedNodesCreation".
Change-Id: If3c62f78ea1f2373a610f78260d317174ca4ca12
Signed-off-by: Asma Smaoui <asma.smaoui@cea.fr>
Diffstat (limited to 'plugins')
12 files changed, 628 insertions, 23 deletions
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/PapyrusDiagramEditPart.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/PapyrusDiagramEditPart.java index cdd6a6aa30f..9810d54c940 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/PapyrusDiagramEditPart.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/editpart/PapyrusDiagramEditPart.java @@ -86,7 +86,7 @@ public class PapyrusDiagramEditPart extends DiagramEditPart { IMultiDiagramEditor multiDiagramEditor = ServiceUtilsForEditPart.getInstance().getService(IMultiDiagramEditor.class, this); activeEditor = multiDiagramEditor.getActiveEditor(); } catch (ServiceException e) { - //Ignore: the IMultiDiagramEditor may not be present in headless mode + Activator.log.error(e); } ((IRefreshHandlerPart) SVGPostProcessor.instance).refresh(activeEditor); } diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/preferences/PreferencesConstantsHelper.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/preferences/PreferencesConstantsHelper.java index 9c4dff238b2..65390b83014 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/preferences/PreferencesConstantsHelper.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/preferences/PreferencesConstantsHelper.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2013, 2018 CEA LIST. + * Copyright (c) 2013 CEA LIST. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -10,7 +10,6 @@ * * CEA LIST - Initial API and implementation * Fanch Bonnabesse (ALL4TEC) fanch.bonnabesse@alltec.net - Bug 419357 - * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Bug 531055 * *****************************************************************************/ package org.eclipse.papyrus.infra.gmfdiag.common.preferences; @@ -24,7 +23,7 @@ import org.eclipse.gmf.runtime.diagram.ui.internal.properties.WorkspaceViewerPro * A class that defines the available preference type available through Papyrus. * </p> * <p> - * It defines the following type (and more): + * It defines the following type: * </p> * <ul> * <li>COLOR_FILL</li> @@ -461,10 +460,7 @@ public class PreferencesConstantsHelper { break; case EXTERNAL_REFERENCE_STRATEGY: sb.append(EXTERNAL_REFERENCE_STRATEGY_CONSTANT); - break; - case DRAW_CONNECTION_POINT: - sb.append(DRAW_CONNECTION_POINT_CONSTANT); - break; + break; default: break; } diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/utils/DiagramEditPartsUtil.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/utils/DiagramEditPartsUtil.java index 0fe3a81a4c0..7d459582a9b 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/utils/DiagramEditPartsUtil.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/utils/DiagramEditPartsUtil.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2012, 2016 CEA LIST, Christian W. Damus, and others. + * Copyright (c) 2012, 2016, 2017 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 @@ -10,6 +10,7 @@ * CEA LIST - Initial API and implementation * Christian W. Damus - bugs 433206, 473148, 485220 * Vincent Lorenzo - bug 492522 + * Ansgar Radermacher - bug 527181 *****************************************************************************/ package org.eclipse.papyrus.infra.gmfdiag.common.utils; @@ -1057,4 +1058,32 @@ public class DiagramEditPartsUtil { } return null; } + + /** + * Gets the diagram on the given {@code context} matching a particular + * {@code filter} condition. + * + * @param context + * a diagram context (its {@link View#getElement() element}) + * @param filter + * the diagram selection criterion, or {@code null} to get any diagram + * + * @return the matching diagram, or {@code null} if none + * @since 3.100 + */ + public static Diagram getDiagram(EObject context, java.util.function.Predicate<? super Diagram> filter) { + if (filter == null) { + filter = __ -> true; + } + + return EMFHelper.getUsages(context).stream() + .filter(s -> s.getEObject() instanceof Diagram) + .filter(s -> s.getEStructuralFeature() == NotationPackage.Literals.VIEW__ELEMENT) + .map(s -> s.getEObject()) + // Not in an undone command's change description + .filter(o -> o.eResource() != null) + .map(Diagram.class::cast) + .filter(filter) + .findAny().orElse(null); + } } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/actions/ShowHideContentsAction.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/actions/ShowHideContentsAction.java index a1a3f2b6153..d4109183550 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/actions/ShowHideContentsAction.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/actions/ShowHideContentsAction.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010 CEA LIST. + * Copyright (c) 2010, 2017 CEA LIST. * * * All rights reserved. This program and the accompanying materials @@ -9,7 +9,9 @@ * * Contributors: * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation - * Benoit maggi (CEA LIST) benoit.maggi@cea.fr -#501701 Showing nested port on Port + * Benoit maggi (CEA LIST) benoit.maggi@cea.fr -#501701 Showing nested port on Port + * Ansgar Radermacher (CEA LIST) ansgar.radermacher@cea.fr - bug 527181, ports on part layout + * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.actions; @@ -176,18 +178,27 @@ public class ShowHideContentsAction extends AbstractShowHideAction implements IA if (!(rep instanceof OptionalEditPartRepresentation)) { continue; } - EditPart ep = ((OptionalEditPartRepresentation) rep).getParentRepresentation().getParentRepresentation().getRepresentedEditPart(); - View compartmentView = ((OptionalEditPartRepresentation) rep).getParentRepresentation().getRepresentedEditPart().getNotationView(); + OptionalEditPartRepresentation optRep = (OptionalEditPartRepresentation) rep; + EditPart ep = optRep.getParentRepresentation().getParentRepresentation().getRepresentedEditPart(); + View compartmentView = optRep.getParentRepresentation().getRepresentedEditPart().getNotationView(); if (compartmentView != null) { - req = new ShowHideElementsRequest(compartmentView, ((OptionalEditPartRepresentation) rep).getSemanticElement()); + req = new ShowHideElementsRequest(compartmentView, optRep.getSemanticElement()); if (isXYLayout(compartmentView, ep)) { propertyLocation.x += INCREMENT; propertyLocation.y += INCREMENT; req.setLocation(new Point(propertyLocation)); - } else if (isAffixedChildNode(ep, ((OptionalEditPartRepresentation) rep).getSemanticElement())) { + } else if (isAffixedChildNode(ep, optRep.getSemanticElement())) { + portLocation.y += INCREMENT; - req.setLocation(new Point(portLocation)); + Point initialPosition = getInitialPortLocation(ep, optRep.getSemanticElement()); + if (initialPosition != null) { + // use initial-position instead of increment-based one + req.setLocation(initialPosition); + } + else { + req.setLocation(new Point(portLocation)); + } } Command cmd = ep.getCommand(req); if (cmd != null && cmd.canExecute()) { @@ -199,6 +210,17 @@ public class ShowHideContentsAction extends AbstractShowHideAction implements IA } /** + * Return the initial position of a port on a part. Should be override by subclasses (e.g. composite diagram) + * + * @param partEditPart edit part of the part within a composite (for which we want to display a port) + * @param port the semantic UML2 port which we want to display + * @return the initial location of the port or null (if none could be determined) + */ + public Point getInitialPortLocation(EditPart partEditPart, EObject port) { + return null; + } + + /** * Test if the child is represented by an affixed child node * TODO This method will not work if we have an UML element E1 which inherits from * another element E2 and if E2 is represented by an affixed child node and diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/helper/RelativePortLocation.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/helper/RelativePortLocation.java new file mode 100644 index 00000000000..5b12424bd2b --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/helper/RelativePortLocation.java @@ -0,0 +1,288 @@ +/***************************************************************************** + * Copyright (c) 2016, 2017 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 + * Ansgar Radermacher - Moved class from PapyrusRT to base Papyrus + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.common.helper; + +import static java.lang.Math.abs; +import static java.lang.Math.max; +import static java.lang.Math.min; +import static org.eclipse.draw2d.PositionConstants.EAST; +import static org.eclipse.draw2d.PositionConstants.NORTH; +import static org.eclipse.draw2d.PositionConstants.SOUTH; +import static org.eclipse.draw2d.PositionConstants.WEST; + +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.gmf.runtime.notation.Bounds; + +/** + * A representation of the relative location of a port on the border of a shape. + * @since 3.1 + */ +public final class RelativePortLocation { + + private final int side; + private final int relativePosition; + + /** + * Initializes me. + * + * @param side + * the side of the parent shape on which the port is located. + * One of {@link PositionConstants#NORTH}, {@link PositionConstants#WEST}, + * {@link PositionConstants#SOUTH}, {@link PositionConstants#EAST} + * + * @param relativePosition + * the percentage across or down, as appropriate to the + * {@code side}, at which the centre-point of the port is located. + * Between 0 and 100, inclusive + */ + private RelativePortLocation(int side, int relativePosition) { + super(); + + this.side = side; + this.relativePosition = relativePosition; + } + + /** + * Computes the relative position of a port on a shape. + * + * @param portBounds + * the port bounds + * @param onShape + * the bounds of the shape that it's on + * + * @return the relative position + */ + public static RelativePortLocation of(Rectangle portBounds, Rectangle onShape) { + Point portCenter = portBounds.getCenter(); + + int side = getSide(portCenter, onShape); + double relativePosition; + + switch (side) { + case WEST: + case EAST: + relativePosition = min(max(0.0, portCenter.preciseY()), onShape.preciseHeight()) * 100 + / onShape.preciseHeight(); + break; + case NORTH: + case SOUTH: + relativePosition = min(max(0, portCenter.preciseX()), onShape.preciseWidth()) * 100 + / onShape.preciseWidth(); + break; + default: + throw new IllegalStateException("Could not compute side of relative port location"); //$NON-NLS-1$ + } + + return new RelativePortLocation(side, (int) Math.round(relativePosition)); + } + + /** + * Computes the relative position of a port on a shape. + * + * @param portBounds + * the port bounds + * @param onShape + * the bounds of the shape that it's on + * + * @return the relative position + */ + public static RelativePortLocation of(Bounds portBounds, Bounds onShape) { + return of(new Rectangle(portBounds.getX(), portBounds.getY(), portBounds.getWidth(), portBounds.getHeight()), + new Rectangle(onShape.getX(), onShape.getY(), onShape.getWidth(), onShape.getHeight())); + } + + /** + * Computes the side of a rectangle on which a point lies. + * + * @param portCenter + * a point to locate on a rectangle + * @param onShape + * the rectangle on which to locate it + * + * @return the side of the rectangle (north, south, west, east) on + * which the point lies + */ + static int getSide(Point portCenter, Rectangle onShape) { + int result; + + // Where is the centre of the port? + int closenessToLeft = abs(portCenter.x()); + int closenessToTop = abs(portCenter.y()); + int closenessToRight = abs(onShape.width() - portCenter.x()); + int closenessToBottom = abs(onShape.height() - portCenter.y()); + + if (closenessToLeft < closenessToRight) { + // It's left-ish, but maybe top or bottom + if (closenessToBottom < closenessToTop) { + if (closenessToBottom < closenessToLeft) { + result = SOUTH; + } else { + result = WEST; + } + } else { + if (closenessToTop < closenessToLeft) { + result = NORTH; + } else { + result = WEST; + } + } + } else { + // It's right-ish, but maybe top or bottom + if (closenessToBottom < closenessToTop) { + if (closenessToBottom < closenessToRight) { + result = SOUTH; + } else { + result = EAST; + } + } else { + if (closenessToTop < closenessToRight) { + result = NORTH; + } else { + result = EAST; + } + } + } + + return result; + } + + /** + * Queries the side of the parent shape on which the port is located. + * + * @return one of {@link PositionConstants#NORTH}, {@link PositionConstants#WEST}, + * {@link PositionConstants#SOUTH}, {@link PositionConstants#EAST} + */ + public final int side() { + return side; + } + + /** + * Queries the percentage across or down, as appropriate to the + * {@linkplain #side() side}, at which the centre-point of the + * port is located. + * + * @return between 0 and 100, inclusive + */ + public final int relativePosition() { + return relativePosition; + } + + /** + * Obtains the point on a shape's {@code bounds} that is the absolute + * location that I indicate. + * + * @param bounds + * a shape's bounds + * @param portSize + * the size of the port to locate (I represent the relative position + * of its centre-point) + * + * @return the point on the {@code bounds} that I represent, in absolute terms of + * the port's origin corner + */ + public Point applyTo(Rectangle bounds, Dimension portSize) { + Point result = new Point(-portSize.width() / 2, -portSize.height() / 2); + + switch (side()) { + case WEST: + result.translate( + 0, + // Relative position up and down the left side + bounds.height() * relativePosition() / 100); + break; + case NORTH: + result.translate( + // Relative position along the top side + bounds.width() * relativePosition() / 100, + 0); + break; + case EAST: + result.translate( + bounds.width(), + // Relative position up and down the right side + bounds.height() * relativePosition() / 100); + break; + case SOUTH: + result.translate( + // Relative position along the bottom side + bounds.width() * relativePosition() / 100, + bounds.height()); + break; + default: + throw new IllegalStateException("invalid side: " + side()); + } + + return result; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + relativePosition; + result = prime * result + side; + return result; + } + + /** + * Relative port locations are equal if they are on the same side + * at the same relative position. + * + * @param obj + * another object + * @return whether they are equivalent relative port locations + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RelativePortLocation other = (RelativePortLocation) obj; + if (relativePosition != other.relativePosition) + return false; + if (side != other.side) + return false; + return true; + } + + @Override + public String toString() { + String sideString; + switch (side) { + case NORTH: + sideString = "NORTH"; //$NON-NLS-1$ + break; + case WEST: + sideString = "WEST"; //$NON-NLS-1$ + break; + case SOUTH: + sideString = "SOUTH"; //$NON-NLS-1$ + break; + case EAST: + sideString = "EAST"; //$NON-NLS-1$ + break; + default: + sideString = "<invalid>"; //$NON-NLS-1$ + } + + return String.format("Port@(%s, %d%%)", sideString, relativePosition); + } +} diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/META-INF/MANIFEST.MF b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/META-INF/MANIFEST.MF index 6d4c80c0cc8..71f1f5932fc 100755 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/META-INF/MANIFEST.MF +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/META-INF/MANIFEST.MF @@ -81,3 +81,4 @@ Bundle-Version: 3.1.0.qualifier Bundle-Activator: org.eclipse.papyrus.uml.diagram.composite.part.UMLDiagramEditorPlugin Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.papyrus.uml.diagram.composite; singleton:=true +Import-Package: com.google.common.base;version="21.0.0" diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/actions/ShowHideRelatedContentsAction.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/actions/ShowHideRelatedContentsAction.java index b39122ed8f3..6acac305bba 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/actions/ShowHideRelatedContentsAction.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/actions/ShowHideRelatedContentsAction.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2009-2011 CEA LIST. + * Copyright (c) 2009-2011, 2017 CEA LIST. * * * All rights reserved. This program and the accompanying materials @@ -9,15 +9,20 @@ * * Contributors: * Yann Tanguy (CEA LIST) yann.tanguy@cea.fr - Initial API and implementation + * Ansgar Radermacher (CEA LIST) ansgar.radermacher@cea.fr - bug 527181, ports on part layout * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.composite.custom.actions; +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gef.EditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.uml.diagram.common.actions.ShowHideContentsAction; import org.eclipse.papyrus.uml.diagram.common.editpolicies.ShowHideRelatedContentsEditPolicy; import org.eclipse.papyrus.uml.diagram.composite.custom.messages.Messages; +import org.eclipse.papyrus.uml.diagram.composite.custom.utils.CompositeStructureDiagramUtils; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Property; @@ -48,4 +53,16 @@ public class ShowHideRelatedContentsAction extends ShowHideContentsAction { } } } + + /** + * Return the initial position of a port on a part. + * + * @param partEditPart edit part of the part within a composite (for which we want to display a port) + * @param port the semantic UML2 port which we want to display + * @return the initial location of the port or null (if none could be determined) + */ + @Override + public Point getInitialPortLocation(EditPart partEditPart, EObject port) { + return CompositeStructureDiagramUtils.getInitialPortLocation(partEditPart, port, null); + } } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/edit/policies/CompositeSideAffixedNodesCreationEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/edit/policies/CompositeSideAffixedNodesCreationEditPolicy.java new file mode 100644 index 00000000000..4e02f9c39e7 --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/edit/policies/CompositeSideAffixedNodesCreationEditPolicy.java @@ -0,0 +1,73 @@ +/***************************************************************************** + * Copyright (c) 2017 CEA LIST + * + * 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: + * Ansgar Radermacher (CEA) ansgar.radermacher@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.composite.custom.edit.policies; + +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.draw2d.FigureListener; +import org.eclipse.draw2d.IFigure; +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand; +import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; +import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest; +import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor; +import org.eclipse.papyrus.commands.Activator; +import org.eclipse.papyrus.infra.gmfdiag.common.editpart.NodeEditPart; +import org.eclipse.papyrus.uml.diagram.common.editpolicies.SideAffixedNodesCreationEditPolicy; +import org.eclipse.papyrus.uml.diagram.composite.custom.utils.CompositeStructureDiagramUtils; +import org.eclipse.uml2.uml.Port; + +/** + * This EditPolicy takes care of the correct placement of ports, see bug 527181 + */ +public class CompositeSideAffixedNodesCreationEditPolicy extends SideAffixedNodesCreationEditPolicy { + + /** + * Extends the inherited method with handling of ports. + */ + @Override + protected ICommand getSetBoundsCommand(CreateViewRequest request, ViewDescriptor descriptor) { + + EObject portEObj = descriptor.getElementAdapter().getAdapter(EObject.class); + if (portEObj instanceof Port) { + final NodeEditPart partEditPart = (NodeEditPart) getHost(); + if (partEditPart.getFigure().getBounds().width != 0) { + Point initialLocation = CompositeStructureDiagramUtils.getInitialPortLocation(getHost(), (Port) portEObj, descriptor); + if (initialLocation != null) { + return new SetBoundsCommand(partEditPart.getEditingDomain(), + DiagramUIMessages.SetLocationCommand_Label_Resize, descriptor, initialLocation); + } + } + else { + // host figure does not have proper bounds yet, make deferred calculation + partEditPart.getFigure().addFigureListener(new FigureListener() { + + @Override + public void figureMoved(IFigure source) { + Point initialLocation = CompositeStructureDiagramUtils.getInitialPortLocation(getHost(), (Port) portEObj, descriptor); + SetBoundsCommand cmd = new SetBoundsCommand(partEditPart.getEditingDomain(), + DiagramUIMessages.SetLocationCommand_Label_Resize, descriptor, initialLocation); + try { + cmd.execute(null, descriptor); + } catch (ExecutionException e) { + Activator.log.error(e); + } + source.removeFigureListener(this); + } + }); + } + } + return super.getSetBoundsCommand(request, descriptor); + } +} diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/utils/CompositeStructureDiagramUtils.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/utils/CompositeStructureDiagramUtils.java new file mode 100644 index 00000000000..33fcfb85781 --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/custom-src/org/eclipse/papyrus/uml/diagram/composite/custom/utils/CompositeStructureDiagramUtils.java @@ -0,0 +1,179 @@ +/***************************************************************************** + * Copyright (c) 2014, 2017 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 - bugs 493869, 513067 + * Ansgar Radermacher - move & adapt from PapyrusRT to base Papyrus, bug 527181 + * Asma Smaoui - bug 527181 + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.diagram.composite.custom.utils; + +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +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.core.util.ViewUtil; +import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor; +import org.eclipse.gmf.runtime.notation.Bounds; +import org.eclipse.gmf.runtime.notation.Diagram; +import org.eclipse.gmf.runtime.notation.Node; +import org.eclipse.gmf.runtime.notation.View; +import org.eclipse.papyrus.infra.core.resource.ModelSet; +import org.eclipse.papyrus.infra.core.services.ServicesRegistry; +import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForEObject; +import org.eclipse.papyrus.infra.gmfdiag.common.editpart.NodeEditPart; +import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel; +import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil; +import org.eclipse.papyrus.infra.tools.util.TypeUtils; +import org.eclipse.papyrus.uml.diagram.common.Activator; +import org.eclipse.papyrus.uml.diagram.common.helper.RelativePortLocation; +import org.eclipse.papyrus.uml.diagram.composite.edit.parts.ClassCompositeEditPart; +import org.eclipse.papyrus.uml.diagram.composite.edit.parts.CompositeStructureDiagramEditPart; +import org.eclipse.uml2.uml.Class; +import org.eclipse.uml2.uml.Property; +import org.eclipse.uml2.uml.Type; + +/** + * Utility method for composite structure diagrams + * + * @since 3.1 + */ +public class CompositeStructureDiagramUtils { + + /** + * Returns <code>true</code> if the diagram is a composite structure diagram (and has a class as base element) + * + * @param diagram + * the diagram to check + * @return <code>true</code> if the diagram is a composite capsule structure diagram + */ + public static boolean isCompositeStructureDiagram(Diagram diagram) { + if (diagram == null) { + return false; + } + if (CompositeStructureDiagramEditPart.MODEL_ID.equals(diagram.getType())) { + EObject businessElement = diagram.getElement(); + if (businessElement instanceof org.eclipse.uml2.uml.Class) { + return true; + } + } + return false; + } + + /** + * Obtains the Composite Structure Diagram for a class + * + * @param component + * b * @return its Composite Structure Diagram, or {@code null} if none is currently known (perhaps + * because it is in a resource that is not yet loaded) + */ + public static Diagram getCompositeStructureDiagram(Class component) { + return DiagramEditPartsUtil.getDiagram(component, CompositeStructureDiagramUtils::isCompositeStructureDiagram); + } + + /** + * Obtains the first view of the Type (here the Class) in any diagrams + * + * @param typingClass: the type of the Part + * + */ + public static View getPartTypeFirstView(Class typingClass) { + View view = null; + try { + ServicesRegistry servicesRegistry = ServiceUtilsForEObject.getInstance().getServiceRegistry(typingClass); + ModelSet modelSet = servicesRegistry.getService(ModelSet.class); + NotationModel notation = (NotationModel) modelSet.getModel(NotationModel.MODEL_ID); + List<Diagram> diagrams = notation.getResource().getContents().stream() + .map(Diagram.class::cast) + .collect(Collectors.toList()); + + for (Diagram d : diagrams) { + for (Iterator children = d.getChildren().iterator(); children.hasNext();) { + View child = (View) children.next(); + if (ViewUtil.resolveSemanticElement(child).equals(typingClass)) { + return child; + } + } + } + } catch (Exception e) { + Activator.log.error(e); + } + return view; + } + + /** + * @param partEditPart + * the edit part of an element + * @return the type (if it is a UML Class) for a given partEditPart + */ + public static Class getPartType(EditPart partEditPart) { + Object modelObj = partEditPart.getModel(); + if (modelObj instanceof View) { + View model = (View) modelObj; + EObject elementEObj = model.getElement(); + if (elementEObj instanceof Property) { + Type type = ((Property) elementEObj).getType(); + if (type instanceof Class) { + return (Class) type; + } + } + } + return null; + } + + /** + * Return the initial position of a port on a part. + * + * @param partEditPart + * edit part of the part within a composite (for which we want to display a port) + * @param port + * the semantic UML2 port which we want to display + * @return the initial location of the port or null (if none could be determined) + */ + public static Point getInitialPortLocation(EditPart partEditPart, EObject port, ViewDescriptor descriptor) { + Class typingClass = getPartType(partEditPart); + View typingClassView = null; + Diagram d = null; + if (typingClass != null) { + d = CompositeStructureDiagramUtils.getCompositeStructureDiagram(typingClass); + // look for another diagram if no owning composite diagram + if (d != null) { + typingClassView = ViewUtil.getChildBySemanticHint(d, ClassCompositeEditPart.VISUAL_ID); + } else { + typingClassView = getPartTypeFirstView(typingClass); + } + View portOnTypingClass = null; + for (Object child : typingClassView.getChildren()) { + if (child instanceof View && ((View) child).getElement() == port) { + portOnTypingClass = (View) child; + break; + } + } + if (portOnTypingClass != null) { + Bounds typingClassBounds = TypeUtils.as(((Node) typingClassView).getLayoutConstraint(), Bounds.class); + Bounds portOnTypingClassBounds = TypeUtils.as(((Node) portOnTypingClass).getLayoutConstraint(), Bounds.class); + int portWidth = portOnTypingClassBounds.getWidth(); + int portHeight = portOnTypingClassBounds.getHeight(); + Rectangle r = new Rectangle(portOnTypingClassBounds.getX(), portOnTypingClassBounds.getY(), portWidth, portHeight); + // use 0, 0 as starting point, since the port coordinates are relative to the part. + RelativePortLocation relative = RelativePortLocation.of(r, new Rectangle(0, 0, typingClassBounds.getWidth(), typingClassBounds.getHeight())); + final Rectangle partBounds = ((NodeEditPart) partEditPart).getFigure().getBounds(); + + return relative.applyTo(partBounds, new Dimension(portWidth, portHeight)); + } + + } + return null; + } +} diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/model/compositediagram.gmfgen b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/model/compositediagram.gmfgen index 40a225f31d9..5da54c43952 100755 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/model/compositediagram.gmfgen +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/model/compositediagram.gmfgen @@ -440,7 +440,7 @@ <behaviour xsi:type="gmfgen:CustomBehaviour" key="org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles.CREATION_ROLE" - editPolicyQualifiedClassName="org.eclipse.papyrus.uml.diagram.common.editpolicies.SideAffixedNodesCreationEditPolicy"/> + editPolicyQualifiedClassName="org.eclipse.papyrus.uml.diagram.composite.custom.edit.policies.CompositeSideAffixedNodesCreationEditPolicy"/> <modelFacet modelElementSelector="/0/@expressionProviders/@providers.0/@expressions.2"> <metaClass @@ -10551,7 +10551,7 @@ iD="org.eclipse.papyrus.uml.diagram.composite" name="Papyrus Composite Structure Diagram " provider="Eclipse Modeling Project" - version="3.0.0.qualifier"> + version="3.1.0.qualifier"> <requiredPlugins>org.eclipse.draw2d</requiredPlugins> <requiredPlugins>org.eclipse.gmf.runtime.draw2d.ui</requiredPlugins> </plugin> diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/src-gen/org/eclipse/papyrus/uml/diagram/composite/edit/parts/PropertyPartEditPartCN.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/src-gen/org/eclipse/papyrus/uml/diagram/composite/edit/parts/PropertyPartEditPartCN.java index e0e142e6541..e75f2b399d1 100755 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/src-gen/org/eclipse/papyrus/uml/diagram/composite/edit/parts/PropertyPartEditPartCN.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/src-gen/org/eclipse/papyrus/uml/diagram/composite/edit/parts/PropertyPartEditPartCN.java @@ -55,9 +55,9 @@ import org.eclipse.papyrus.uml.diagram.common.editpolicies.MaskManagedNodeEditPo import org.eclipse.papyrus.uml.diagram.common.editpolicies.QualifiedNameDisplayEditPolicy; import org.eclipse.papyrus.uml.diagram.common.editpolicies.ShowHideCompartmentEditPolicy; import org.eclipse.papyrus.uml.diagram.common.editpolicies.ShowHideRelatedContentsEditPolicy; -import org.eclipse.papyrus.uml.diagram.common.editpolicies.SideAffixedNodesCreationEditPolicy; import org.eclipse.papyrus.uml.diagram.common.locator.PortPositionLocator; import org.eclipse.papyrus.uml.diagram.common.locator.RoundedRectangleLabelPositionLocator; +import org.eclipse.papyrus.uml.diagram.composite.custom.edit.policies.CompositeSideAffixedNodesCreationEditPolicy; import org.eclipse.papyrus.uml.diagram.composite.custom.edit.policies.CustomDiagramDragDropEditPolicy; import org.eclipse.papyrus.uml.diagram.composite.custom.edit.policies.PropertyLayoutEditPolicy; import org.eclipse.papyrus.uml.diagram.composite.custom.figures.PropertyPartFigure; @@ -114,7 +114,7 @@ public class PropertyPartEditPartCN extends RoundedCompartmentEditPart { installEditPolicy(ShowHideRelatedContentsEditPolicy.SHOW_HIDE_RELATED_CONTENTS_POLICY, new ShowHideRelatedContentsEditPolicy()); installEditPolicy(IMaskManagedLabelEditPolicy.MASK_MANAGED_LABEL_EDIT_POLICY, new MaskManagedNodeEditPolicy()); installEditPolicy(EditPolicy.LAYOUT_ROLE, new GetChildLayoutEditPolicy()); - installEditPolicy(EditPolicyRoles.CREATION_ROLE, new SideAffixedNodesCreationEditPolicy()); + installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CompositeSideAffixedNodesCreationEditPolicy()); // XXX need an SCR to runtime to have another abstract superclass that would let children add reasonable editpolicies // removeEditPolicy(org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles.CONNECTION_HANDLES_ROLE); } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/src-gen/org/eclipse/papyrus/uml/diagram/composite/edit/parts/StateMachineCompositeEditPart.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/src-gen/org/eclipse/papyrus/uml/diagram/composite/edit/parts/StateMachineCompositeEditPart.java index f12fd539dc9..fbf2ee06e3c 100755 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/src-gen/org/eclipse/papyrus/uml/diagram/composite/edit/parts/StateMachineCompositeEditPart.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.composite/src-gen/org/eclipse/papyrus/uml/diagram/composite/edit/parts/StateMachineCompositeEditPart.java @@ -53,10 +53,10 @@ import org.eclipse.papyrus.uml.diagram.common.editpolicies.BorderItemResizableEd import org.eclipse.papyrus.uml.diagram.common.editpolicies.QualifiedNameDisplayEditPolicy; import org.eclipse.papyrus.uml.diagram.common.editpolicies.ShowHideClassifierContentsEditPolicy; import org.eclipse.papyrus.uml.diagram.common.editpolicies.ShowHideCompartmentEditPolicy; -import org.eclipse.papyrus.uml.diagram.common.editpolicies.SideAffixedNodesCreationEditPolicy; import org.eclipse.papyrus.uml.diagram.common.locator.PortPositionLocator; import org.eclipse.papyrus.uml.diagram.common.locator.RoundedRectangleLabelPositionLocator; import org.eclipse.papyrus.uml.diagram.composite.custom.edit.policies.BehaviorLayoutEditPolicy; +import org.eclipse.papyrus.uml.diagram.composite.custom.edit.policies.CompositeSideAffixedNodesCreationEditPolicy; import org.eclipse.papyrus.uml.diagram.composite.custom.edit.policies.CustomDiagramDragDropEditPolicy; import org.eclipse.papyrus.uml.diagram.composite.custom.figures.StateMachineCompositeFigure; import org.eclipse.papyrus.uml.diagram.composite.part.UMLVisualIDRegistry; @@ -110,7 +110,7 @@ public class StateMachineCompositeEditPart extends RoundedCompartmentEditPart { installEditPolicy(ShowHideCompartmentEditPolicy.SHOW_HIDE_COMPARTMENT_POLICY, new ShowHideCompartmentEditPolicy()); installEditPolicy(AffixedNodeAlignmentEditPolicy.AFFIXED_CHILD_ALIGNMENT_ROLE, new AffixedNodeAlignmentEditPolicy()); installEditPolicy(EditPolicy.LAYOUT_ROLE, new GetChildLayoutEditPolicy()); - installEditPolicy(EditPolicyRoles.CREATION_ROLE, new SideAffixedNodesCreationEditPolicy()); + installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CompositeSideAffixedNodesCreationEditPolicy()); // XXX need an SCR to runtime to have another abstract superclass that would let children add reasonable editpolicies // removeEditPolicy(org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles.CONNECTION_HANDLES_ROLE); } |