[570518] Ignore the labels in Bendpoint computation

When moving the source or the target Editpart of an edge, the labels are
ignored when recomputing the bendpoints of this edge.

Bug: 570518
Change-Id: I910e285070d17eda4e5d448e65d0ce03f06482e5
Signed-off-by: Glenn Plouhinec <glenn.plouhinec@obeo.fr>
Signed-off-by: Laurent Fasani <laurent.fasani@obeo.fr>
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/edit/api/part/AbstractDiagramEdgeEditPart.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/edit/api/part/AbstractDiagramEdgeEditPart.java
index c6bf696..61fb561 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/edit/api/part/AbstractDiagramEdgeEditPart.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/edit/api/part/AbstractDiagramEdgeEditPart.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2020 THALES GLOBAL SERVICES and others.
+ * Copyright (c) 2008, 2021 THALES GLOBAL SERVICES and others.
  * 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
@@ -77,6 +77,7 @@
 import org.eclipse.sirius.diagram.ui.tools.internal.ruler.SiriusSnapToHelperUtil;
 import org.eclipse.sirius.ext.gmf.runtime.draw2d.ui.figures.SiriusPolylineConnectionEx;
 import org.eclipse.sirius.ext.gmf.runtime.editparts.GraphicalHelper;
+import org.eclipse.sirius.ext.gmf.runtime.gef.ui.figures.IFigureWithoutLabels;
 import org.eclipse.sirius.ext.gmf.runtime.gef.ui.figures.SiriusWrapLabel;
 import org.eclipse.sirius.viewpoint.description.tool.AbstractToolDescription;
 import org.eclipse.sirius.viewpoint.description.tool.PaneBasedSelectionWizardDescription;
@@ -499,7 +500,7 @@
     /**
      * The figure.
      */
-    public class ViewEdgeFigure extends SiriusPolylineConnectionEx implements ITreeConnection {
+    public class ViewEdgeFigure extends SiriusPolylineConnectionEx implements ITreeConnection, IFigureWithoutLabels {
         /**
          * Label figure that allows to set the model {@link View}. These labels are created before label edit parts are
          * created so we need to be able to attached the right view after.
@@ -841,6 +842,11 @@
         public IGraphicalEditPart getEditPart() {
             return AbstractDiagramEdgeEditPart.this;
         }
+
+        @Override
+        public Rectangle getBoundsWithoutLabels() {
+            return getPoints().getBounds();
+        }
     }
 
     private static boolean invalidPath(final AbstractDiagramEdgeEditPart editPart, final DEdge edge) {
@@ -1043,7 +1049,6 @@
         return routingStyle;
     }
 
-
     /**
      * Set the routing style for which a listener is added in the DiagramEventBroker during the activation of this edit
      * part.<BR>
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SetConnectionBendpointsAccordingToExtremityMoveCommmand.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SetConnectionBendpointsAccordingToExtremityMoveCommmand.java
index 792b4df..5142ab0 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SetConnectionBendpointsAccordingToExtremityMoveCommmand.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SetConnectionBendpointsAccordingToExtremityMoveCommmand.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014-2020 THALES GLOBAL SERVICES and others.
+ * Copyright (c) 2014, 2021 THALES GLOBAL SERVICES and others.
  * 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
@@ -115,8 +115,8 @@
             }
         }
         // Get the bounds of the source and target nodes.
-        PrecisionRectangle sourceBounds = new PrecisionRectangle(GraphicalHelper.getAbsoluteBoundsIn100Percent((IGraphicalEditPart) connectionEditPart.getSource()));
-        PrecisionRectangle targetBounds = new PrecisionRectangle(GraphicalHelper.getAbsoluteBoundsIn100Percent((IGraphicalEditPart) connectionEditPart.getTarget()));
+        PrecisionRectangle sourceBounds = new PrecisionRectangle(GraphicalHelper.getAbsoluteBoundsWithoutLabelsIn100Percent((IGraphicalEditPart) connectionEditPart.getSource()));
+        PrecisionRectangle targetBounds = new PrecisionRectangle(GraphicalHelper.getAbsoluteBoundsWithoutLabelsIn100Percent((IGraphicalEditPart) connectionEditPart.getTarget()));
         boolean isEdgeWithRectilinearRoutingStyle = connectionEditPartQuery.isEdgeWithRectilinearRoutingStyle();
         if (sourceMove) {
             moveFirstSegmentAndRefPointAccordingToSourceMove(moveDelta, isEdgeWithRectilinearRoutingStyle, sourceBounds, targetBounds, sourceRefPoint, targetRefPoint, connectionPointList);
diff --git a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
index de4eb22..8b479f8 100644
--- a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
+++ b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
@@ -199,6 +199,10 @@
 				<code>org.eclipse.sirius.ui.business.api.dialect.DialectUIManager.isRefreshActivatedOnRepresentationOpening()</code> has been removed. Use 
 				<code>org.eclipse.sirius.business.api.session.SiriusPreferences.isRefreshAtRepresentationOpening()</code> instead.
 			</li>
+			<li><span class="label label-success">Added</span> The API 
+				<code>org.eclipse.sirius.ext.gmf.runtime.gef.ui.figures.IFigureWithoutLabels</code> has been created so that a Figure, that implements this API, can provide its bounds without considering its labels. The method 
+				<code>org.eclipse.sirius.ext.gmf.runtime.editparts.GraphicalHelper.getAbsoluteBoundsWithoutLabelsIn100Percent(GraphicalEditPart)</code> has been added to get the rectangle bounds without taking labels into account. This is used, in particular, to compute the bendpoints of an edge when the source or the target of the edge is an edge.
+			</li>
 		</ul>
 		<h2 id="sirius6.4.1">Changes in Sirius 6.4.1</h2>
 		<p>This is service release to fix two issues which were not detected in time for 6.4.0. The issues only impact a new API which was introduced in 6.4.0 (Bug 563117 - 
diff --git a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
index 902e6f7..ab90dfb 100644
--- a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
+++ b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
@@ -19,6 +19,7 @@
 * <span class="label label-danger">Removed</span> @org.eclipse.sirius.tools.api.ui.RefreshHelper.isAutoRefresh()@ has been removed. Clients should call @Session.getPreferences.isAutoRefresh()@ or @new DRepresentationQuery(DRpresentation).isAutoRefresh()@ instead.
 * <span class="label label-danger">Removed</span> @org.eclipse.sirius.diagram.ui.tools.api.properties.PropertiesService@, @org.eclipse.sirius.tools.api.ui.property.IPropertiesProvider@ and @org.eclipse.sirius.diagram.ui.tools.internal.properties.SiriusDiagramEditorPropertiesProvider@ have been removed. Clients should call @Session.getPreferences.isAutoRefresh()@ or @new DRepresentationQuery(DRpresentation).isAutoRefresh()@ instead.
 * <span class="label label-danger">Removed</span> @org.eclipse.sirius.ui.business.api.dialect.DialectUIManager.isRefreshActivatedOnRepresentationOpening()@ has been removed. Use @org.eclipse.sirius.business.api.session.SiriusPreferences.isRefreshAtRepresentationOpening()@ instead.
+* <span class="label label-success">Added</span> The API @org.eclipse.sirius.ext.gmf.runtime.gef.ui.figures.IFigureWithoutLabels@ has been created so that a Figure, that implements this API, can provide its bounds without considering its labels. The method @org.eclipse.sirius.ext.gmf.runtime.editparts.GraphicalHelper.getAbsoluteBoundsWithoutLabelsIn100Percent(GraphicalEditPart)@ has been added to get the rectangle bounds without taking labels into account. This is used, in particular, to compute the bendpoints of an edge when the source or the target of the edge is an edge.
 
 h2(#sirius6.4.1). Changes in Sirius 6.4.1
 
diff --git a/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/editparts/GraphicalHelper.java b/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/editparts/GraphicalHelper.java
index 6431fb4..8541fa5 100644
--- a/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/editparts/GraphicalHelper.java
+++ b/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/editparts/GraphicalHelper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2019 THALES GLOBAL SERVICES and others.
+ * Copyright (c) 2011, 2021 THALES GLOBAL SERVICES and others.
  * 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
@@ -39,10 +39,10 @@
 import org.eclipse.gmf.runtime.notation.Anchor;
 import org.eclipse.gmf.runtime.notation.IdentityAnchor;
 import org.eclipse.sirius.ext.draw2d.figure.FigureUtilities;
+import org.eclipse.sirius.ext.gmf.runtime.gef.ui.figures.IFigureWithoutLabels;
 
 /**
- * Utility class to collect helper methods which deal with GraphicalOrdering but
- * which are not part of its API.
+ * Utility class to collect helper methods which deal with GraphicalOrdering but which are not part of its API.
  * 
  * @author nlepine
  */
@@ -73,19 +73,15 @@
      * Applied zoom on relative point.<BR>
      * For example:
      * <UL>
-     * <LI>For a zoom of 200%, the result of this method for the point (100,
-     * 100) is (200, 200)</LI>
-     * <LI>For a zoom of 50%, the result of this method for the point (100, 100)
-     * is (50, 50)</LI>
+     * <LI>For a zoom of 200%, the result of this method for the point (100, 100) is (200, 200)</LI>
+     * <LI>For a zoom of 50%, the result of this method for the point (100, 100) is (50, 50)</LI>
      * </UL>
      * 
      * @param part
      *            the current part
      * @param relativePoint
      *            relative point
-     * @deprecated Use
-     *             {@link #applyInverseZoomOnPoint(IGraphicalEditPart, Point)}
-     *             instead
+     * @deprecated Use {@link #applyInverseZoomOnPoint(IGraphicalEditPart, Point)} instead
      */
     @Deprecated
     public static void appliedZoomOnRelativePoint(IGraphicalEditPart part, Point relativePoint) {
@@ -101,10 +97,8 @@
      * Applies zoom on a point and returns this point for convenience.<BR>
      * For example:
      * <UL>
-     * <LI>For a zoom of 200%, the result of this method for the point (100,
-     * 100) is (200, 200)</LI>
-     * <LI>For a zoom of 50%, the result of this method for the point (100, 100)
-     * is (50, 50)</LI>
+     * <LI>For a zoom of 200%, the result of this method for the point (100, 100) is (200, 200)</LI>
+     * <LI>For a zoom of 50%, the result of this method for the point (100, 100) is (50, 50)</LI>
      * </UL>
      * 
      * @param part
@@ -124,14 +118,11 @@
     }
 
     /**
-     * Applies inverse zoom on a point and returns this point for convenience.
-     * <BR>
+     * Applies inverse zoom on a point and returns this point for convenience. <BR>
      * For example:
      * <UL>
-     * <LI>For a zoom of 200%, the result of this method for the point (100,
-     * 100) is (50, 50)</LI>
-     * <LI>For a zoom of 50%, the result of this method for the point (100, 100)
-     * is (200, 200)</LI>
+     * <LI>For a zoom of 200%, the result of this method for the point (100, 100) is (50, 50)</LI>
+     * <LI>For a zoom of 50%, the result of this method for the point (100, 100) is (200, 200)</LI>
      * </UL>
      * 
      * @param part
@@ -168,9 +159,8 @@
     }
 
     /**
-     * Returns the difference between the logical origin (0, 0) and the top-left
-     * point actually visible. This corresponds to how much the scrollbars
-     * "shift" the diagram.
+     * Returns the difference between the logical origin (0, 0) and the top-left point actually visible. This
+     * corresponds to how much the scrollbars "shift" the diagram.
      * 
      * @param part
      *            an edit part on the view
@@ -322,9 +312,8 @@
     }
 
     /**
-     * Converts a dimension from logical coordinates to screen coordinates.
-     * Dimensions have no defined position, so only the current zoom level is
-     * take into account, not the scroll state.
+     * Converts a dimension from logical coordinates to screen coordinates. Dimensions have no defined position, so only
+     * the current zoom level is take into account, not the scroll state.
      * 
      * @param dim
      *            the dimension to convert.
@@ -336,9 +325,8 @@
     }
 
     /**
-     * Return the Point (absolute draw2d coordinates) corresponding to this
-     * Anchor. If anchor is not an IdentityAnchor, the center of
-     * <code>parent</code> is returned.
+     * Return the Point (absolute draw2d coordinates) corresponding to this Anchor. If anchor is not an IdentityAnchor,
+     * the center of <code>parent</code> is returned.
      * 
      * @param parent
      *            The parent node
@@ -386,9 +374,8 @@
     }
 
     /**
-     * Get intersection between a line between lineOrigin and lineTerminus, and
-     * the rectangle bounds of the part. If there are several intersections, the
-     * shortest is returned.
+     * Get intersection between a line between lineOrigin and lineTerminus, and the rectangle bounds of the part. If
+     * there are several intersections, the shortest is returned.
      * 
      * @param lineOrigin
      *            Origin of the line
@@ -397,8 +384,7 @@
      * @param part
      *            Part to detect intersection.
      * @param minimalDistancefromLineOrigin
-     *            true if the shortest distance is between the line origin and
-     *            the part, false otherwise.
+     *            true if the shortest distance is between the line origin and the part, false otherwise.
      * @return Intersection between a line and a rectangle.
      */
     public static Optional<Point> getIntersection(Point lineOrigin, Point lineTerminus, IGraphicalEditPart part, boolean minimalDistancefromLineOrigin) {
@@ -406,9 +392,8 @@
     }
 
     /**
-     * Get intersection between a line between lineOrigin and lineTerminus, and
-     * the rectangle bounds of the part. If there are several intersections, the
-     * shortest is returned.
+     * Get intersection between a line between lineOrigin and lineTerminus, and the rectangle bounds of the part. If
+     * there are several intersections, the shortest is returned.
      * 
      * @param lineOrigin
      *            Origin of the line
@@ -417,11 +402,9 @@
      * @param part
      *            Part to detect intersection.
      * @param minimalDistancefromLineOrigin
-     *            true if the shortest distance is between the line origin and
-     *            the part, false otherwise.
+     *            true if the shortest distance is between the line origin and the part, false otherwise.
      * @param useNearestPoint
-     *            If true, if there is no intersection, the nearest point on the
-     *            rectangle is returned.
+     *            If true, if there is no intersection, the nearest point on the rectangle is returned.
      * @return Intersection between a line and a rectangle.
      */
     public static Optional<Point> getIntersection(Point lineOrigin, Point lineTerminus, IGraphicalEditPart part, boolean minimalDistancefromLineOrigin, boolean useNearestPoint) {
@@ -431,9 +414,8 @@
     }
 
     /**
-     * Get intersection between a line between lineOrigin and lineTerminus, and
-     * a rectangle. If there are several intersections, the shortest is
-     * returned.
+     * Get intersection between a line between lineOrigin and lineTerminus, and a rectangle. If there are several
+     * intersections, the shortest is returned.
      * 
      * @param lineOrigin
      *            Origin of the line
@@ -442,8 +424,7 @@
      * @param rectangle
      *            rectangle to detect intersection.
      * @param minimalDistancefromLineOrigin
-     *            true if the shortest distance is between the line origin and
-     *            the part, false otherwise.
+     *            true if the shortest distance is between the line origin and the part, false otherwise.
      * @return Intersection between a line and a rectangle.
      */
     public static Optional<Point> getIntersection(Point lineOrigin, Point lineTerminus, Rectangle rectangle, boolean minimalDistancefromLineOrigin) {
@@ -451,9 +432,8 @@
     }
 
     /**
-     * Get intersection between a line between lineOrigin and lineTerminus, and
-     * a rectangle. If there are several intersections, the shortest is
-     * returned.
+     * Get intersection between a line between lineOrigin and lineTerminus, and a rectangle. If there are several
+     * intersections, the shortest is returned.
      * 
      * @param lineOrigin
      *            Origin of the line
@@ -462,11 +442,9 @@
      * @param rectangle
      *            rectangle to detect intersection.
      * @param minimalDistancefromLineOrigin
-     *            true if the shortest distance is between the line origin and
-     *            the part, false otherwise.
+     *            true if the shortest distance is between the line origin and the part, false otherwise.
      * @param useNearestPoint
-     *            If true, if there is no intersection, the nearest point on the
-     *            rectangle is returned.
+     *            If true, if there is no intersection, the nearest point on the rectangle is returned.
      * @return Intersection between a line and a rectangle.
      */
     public static Optional<Point> getIntersection(Point lineOrigin, Point lineTerminus, Rectangle rectangle, boolean minimalDistancefromLineOrigin, boolean useNearestPoint) {
@@ -551,8 +529,8 @@
     }
 
     /**
-     * Get the intersection point list between the segment formed by the start
-     * and end points and the given figure bounds.
+     * Get the intersection point list between the segment formed by the start and end points and the given figure
+     * bounds.
      * 
      * @param start
      *            start point
@@ -578,8 +556,8 @@
 
     /**
      * Get the absolute bounds of this <code>part</code>.<BR>
-     * Detail: If the zoom is set to 200%, the location and the size are
-     * multiplied by two with respect to the real location and size.
+     * Detail: If the zoom is set to 200%, the location and the size are multiplied by two with respect to the real
+     * location and size.
      * 
      * @param part
      *            The part to consider.
@@ -597,8 +575,8 @@
     }
 
     /**
-     * Get the absolute bounds of this <code>part</code>. In case of zoom or/and
-     * a scrollbar, the bounds are converted from screen to logical.<BR>
+     * Get the absolute bounds of this <code>part</code>. In case of zoom or/and a scrollbar, the bounds are converted
+     * from screen to logical.<BR>
      * 
      * @param part
      *            The part to consider.
@@ -632,13 +610,31 @@
     }
 
     /**
-     * Return true if the snapToGrid is enabled for the diagram containing this
-     * edit part, false otherwise.
+     * Get the absolute bounds of this <code>part</code> by excluding labels from the bounds.<br/>
+     * In case of zoom or/and scrollbars, the bounds are converted from screen to logical.<BR>
+     * 
+     * @param part
+     *            The part to consider.
+     * @return The absolute bounds.
+     */
+    public static Rectangle getAbsoluteBoundsWithoutLabelsIn100Percent(GraphicalEditPart part) {
+        PrecisionRectangle bounds;
+        if (part.getFigure() instanceof IFigureWithoutLabels) {
+            bounds = new PrecisionRectangle(((IFigureWithoutLabels) part.getFigure()).getBoundsWithoutLabels());
+            part.getFigure().translateToAbsolute(bounds);
+            screen2logical(bounds, part, false);
+        } else {
+            bounds = new PrecisionRectangle(getAbsoluteBoundsIn100Percent(part));
+        }
+        return bounds;
+    }
+
+    /**
+     * Return true if the snapToGrid is enabled for the diagram containing this edit part, false otherwise.
      * 
      * @param editPart
      *            The edit part to use.
-     * @return true if the snapToGrid is enabled for the diagram containing this
-     *         edit part, false otherwise.
+     * @return true if the snapToGrid is enabled for the diagram containing this edit part, false otherwise.
      */
     public static boolean isSnapToGridEnabled(EditPart editPart) {
         return (Boolean) editPart.getViewer().getProperty(SnapToGrid.PROPERTY_GRID_ENABLED);
diff --git a/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/gef/ui/figures/IFigureWithoutLabels.java b/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/gef/ui/figures/IFigureWithoutLabels.java
new file mode 100644
index 0000000..290c9e8
--- /dev/null
+++ b/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/gef/ui/figures/IFigureWithoutLabels.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2021 THALES GLOBAL SERVICES and others.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.ext.gmf.runtime.gef.ui.figures;
+
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * Represents the shape of a {@link Figure} but without the labels that are outside the main shape of the figure.<br/>
+ * Example: labels of an Edge.
+ * 
+ * @author lfasani
+ *
+ */
+public interface IFigureWithoutLabels {
+
+    /**
+     * Get the bounding box ignoring the labels that are outside the main shape of the figure.
+     * 
+     * @return the bounds
+     */
+    Rectangle getBoundsWithoutLabels();
+}