Browse Source

fixes #1143 the transition label jumping mentioned in

reused sirius label routing (well done @ obeo)
andreas muelder 7 years ago
parent
commit
93aa123bd9

+ 1 - 0
plugins/org.yakindu.base.xtext.utils.gmf/META-INF/MANIFEST.MF

@@ -16,6 +16,7 @@ Export-Package: org.yakindu.base.xtext.utils.gmf.directedit,
  org.yakindu.base.xtext.utils.gmf.experimental,
  org.yakindu.base.xtext.utils.gmf.figures,
  org.yakindu.base.xtext.utils.gmf.resource,
+ org.yakindu.base.xtext.utils.gmf.routing,
  org.yakindu.base.xtext.utils.gmf.viewers
 Bundle-ActivationPolicy: lazy
 

+ 21 - 5
plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/directedit/ExternalXtextLabelEditPart.java

@@ -15,10 +15,13 @@ import static org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants.REQ_D
 
 import org.eclipse.draw2d.IFigure;
 import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.geometry.Rectangle;
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.gef.DragTracker;
 import org.eclipse.gef.Request;
+import org.eclipse.gef.editparts.AbstractConnectionEditPart;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
 import org.eclipse.gef.tools.DirectEditManager;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.tools.DragEditPartsTrackerEx;
@@ -29,6 +32,7 @@ import org.eclipse.gmf.runtime.notation.ShapeStyle;
 import org.eclipse.gmf.runtime.notation.View;
 import org.eclipse.swt.graphics.Color;
 import org.yakindu.base.xtext.utils.gmf.figures.SyntaxColoringLabel;
+import org.yakindu.base.xtext.utils.gmf.routing.EdgeLabelLocator;
 import org.yakindu.base.xtext.utils.jface.viewers.XtextStyledTextCellEditor;
 
 /**
@@ -42,7 +46,9 @@ import org.yakindu.base.xtext.utils.jface.viewers.XtextStyledTextCellEditor;
 public abstract class ExternalXtextLabelEditPart extends LabelEditPart implements IXtextAwareEditPart {
 
 	protected abstract DirectEditManager createDirectEditManager();
+
 	protected abstract void setContext(Resource resource);
+
 	protected abstract void setLabelStyles();
 
 	public ExternalXtextLabelEditPart(final View view) {
@@ -75,9 +81,18 @@ public abstract class ExternalXtextLabelEditPart extends LabelEditPart implement
 		setLabelStyles();
 	}
 
+	@Override
+	public void refreshBounds() {
+		int dx = ((Integer) getStructuralFeatureValue(NotationPackage.eINSTANCE.getLocation_X())).intValue();
+		int dy = ((Integer) getStructuralFeatureValue(NotationPackage.eINSTANCE.getLocation_Y())).intValue();
+		Rectangle bounds = new Rectangle(dx, dy, -1, -1);
+		((AbstractGraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), new EdgeLabelLocator(
+				((AbstractConnectionEditPart) getParent()).getConnectionFigure(), bounds, getKeyPoint()));
+	}
+
 	protected void updateLabelText() {
 		getFigure().setText(getEditText());
-		
+
 	}
 
 	@Override
@@ -122,10 +137,11 @@ public abstract class ExternalXtextLabelEditPart extends LabelEditPart implement
 
 				public void run() {
 					if (isActive()) {
-						
-						if (theRequest.getExtendedData().get(REQ_DIRECTEDIT_EXTENDEDDATA_INITIAL_CHAR) instanceof Character) {
-							final Character initialChar = (Character) theRequest.getExtendedData().get(
-									REQ_DIRECTEDIT_EXTENDEDDATA_INITIAL_CHAR);
+
+						if (theRequest.getExtendedData()
+								.get(REQ_DIRECTEDIT_EXTENDEDDATA_INITIAL_CHAR) instanceof Character) {
+							final Character initialChar = (Character) theRequest.getExtendedData()
+									.get(REQ_DIRECTEDIT_EXTENDEDDATA_INITIAL_CHAR);
 							if (manager instanceof XtextDirectEditManager) {
 								XtextDirectEditManager xtextDirectEditManager = (XtextDirectEditManager) manager;
 								xtextDirectEditManager.show(initialChar);

+ 127 - 0
plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/routing/EdgeLabelLocator.java

@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.yakindu.base.xtext.utils.gmf.routing;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.geometry.Vector;
+import org.eclipse.gef.requests.BendpointRequest;
+import org.eclipse.gef.requests.ReconnectRequest;
+import org.eclipse.gmf.runtime.diagram.ui.figures.LabelLocator;
+
+/**
+ * Specific {@link LabelLocator} for edge labels to reflect the real label
+ * location during the feedback.
+ *
+ * @author <a href="mailto:laurent.fasani@obeo.fr">Laurent Fasani</a>
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public class EdgeLabelLocator extends LabelLocator {
+
+    /** The points list of the edge before to start to move it. */
+    private PointList oldPointList;
+
+    /** The offset of the label before to start to move the edge. */
+    private Vector oldLabelOffset;
+
+    /** Status of the edge routing style */
+    private boolean isEdgeWithObliqueRoutingStyle;
+
+    /**
+     * Constructor for figure who are located and sized.
+     *
+     * @param parent
+     *            the parent figure
+     * @param bounds
+     *            the bounds
+     * @param alignment
+     *            the alignment
+     */
+    public EdgeLabelLocator(IFigure parent, Rectangle bounds, int alignment) {
+        super(parent, bounds, alignment);
+    }
+
+    /**
+     * This method must be called before edge feedback creation (
+     * {@link org.eclipse.sirius.diagram.ui.graphical.edit.policies.TreeLayoutConnectionLineSegEditPolicy#showMoveLineSegFeedback(BendpointRequest)}
+     * or
+     * {@link org.eclipse.sirius.diagram.ui.tools.internal.graphical.edit.policies.SiriusConnectionEndPointEditPolicy#showConnectionMoveFeedback(ReconnectRequest)}
+     * ) for example), to initialize the data needed to compute the label offset
+     * dynamically and draw the label feedback correctly.<BR>
+     * The method {@link #eraseFeedbackData()} must be called when edge feedback
+     * is erase.
+     *
+     * @param oldPointList
+     *            The points list of the edge before to start to move it.
+     * @param oldLabelOffset
+     *            The offset of the label before to start to move the edge.
+     * @param isEdgeWithObliqueRoutingStyle
+     *            The status of the edge routing style
+     */
+    public void setFeedbackData(PointList oldPointList, Vector oldLabelOffset, boolean isEdgeWithObliqueRoutingStyle) {
+        this.oldPointList = oldPointList;
+        this.isEdgeWithObliqueRoutingStyle = isEdgeWithObliqueRoutingStyle;
+        this.oldLabelOffset = oldLabelOffset;
+    }
+
+    /**
+     * This method must be called at the end of the edge feedback (
+     * {@link org.eclipse.gef.editpolicies.ConnectionEndpointEditPolicy.eraseConnectionMoveFeedback(ReconnectRequest)}
+     * or
+     * {@link org.eclipse.gmf.runtime.gef.ui.internal.editpolicies.ConnectionBendpointEditPolicy.eraseConnectionFeedback(BendpointRequest,
+     * boolean)} for example).
+     */
+    public void eraseFeedbackData() {
+        this.oldPointList = null;
+        this.oldLabelOffset = null;
+        this.isEdgeWithObliqueRoutingStyle = false;
+    }
+
+    @Override
+    public void relocate(IFigure target) {
+        Dimension preferredSize = target.getPreferredSize();
+        LabelLocator currentConstraint = (LabelLocator) target.getParent().getLayoutManager().getConstraint(target);
+        Dimension currentExtent = currentConstraint.getSize();
+        Dimension size = new Dimension(currentExtent);
+        if (currentExtent.width == -1) {
+            size.width = preferredSize.width;
+        }
+        if (currentExtent.height == -1) {
+            size.height = preferredSize.height;
+        }
+        target.setSize(size);
+        Point offSet = getOffset();
+        if (oldPointList != null) {
+            // Compute the future offset only if the oldPointList, comes from
+            // edge feedback during a move of an edge. In other case, the offset
+            // to use is the stored one.
+            Vector computedOffSet = computeOffSet(size);
+            offSet = new Point((int) computedOffSet.x, (int) computedOffSet.y);
+        }
+
+        Point centerLocation = EdgeLabelQuery.relativeCenterCoordinateFromOffset(((Connection) parent).getPoints(), getReferencePoint(), offSet);
+        target.setLocation(centerLocation.getTranslated(-1 * size.width / 2, -1 * size.height / 2));
+    }
+
+    /**
+     * Compute offset taking current figure bendpoints as newBendPoints.
+     */
+    private Vector computeOffSet(Dimension size) {
+        EdgeLabelQuery edgeLabelsComputationUtil = new EdgeLabelQuery(oldPointList, getPointList(), isEdgeWithObliqueRoutingStyle, oldLabelOffset.toPoint(), size, getAlignment(),
+               false);
+        Point newMethodPoint = edgeLabelsComputationUtil.calculateGMFLabelOffset();
+        return new Vector(newMethodPoint.x, newMethodPoint.y);
+    }
+}

+ 795 - 0
plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/routing/EdgeLabelQuery.java

@@ -0,0 +1,795 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.yakindu.base.xtext.utils.gmf.routing;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.eclipse.draw2d.ConnectionLocator;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.draw2d.geometry.Straight;
+import org.eclipse.draw2d.geometry.Transform;
+import org.eclipse.draw2d.geometry.Vector;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.internal.util.LabelViewConstants;
+import org.eclipse.gmf.runtime.draw2d.ui.geometry.LineSeg;
+import org.eclipse.gmf.runtime.draw2d.ui.geometry.PointListUtilities;
+import org.eclipse.gmf.runtime.notation.Bounds;
+
+/**
+ * Utility class used to compute the position of a label according to its edge
+ * move (old points and new points list).
+ *
+ * @author <a href="mailto:laurent.fasani@obeo.fr">Laurent Fasani</a>
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+@SuppressWarnings("restriction")
+public class EdgeLabelQuery {
+
+	private final static double DISTANCE_TOLERANCE = 0.001;
+
+	/** Status for {@link #getSameLineStatus(Vector, LineSeg)} method. */
+	private static final int NOT_ON_SAME_LINE = 0;
+
+	/** Status for {@link #getSameLineStatus(Vector, LineSeg)} method. */
+	private static final int ON_SAME_LINE_SAME_DIRECTION = 1;
+
+	/** Status for {@link #getSameLineStatus(Vector, LineSeg)} method. */
+	private static final int ON_SAME_LINE_OPPOSITE_DIRECTION = 2;
+
+	/** BendPoint list before the edge modification. */
+	private PointList oldBendPointList;
+
+	/** BendPoint list corresponding to the edge modification. */
+	private PointList newBendPointList;
+
+	/** The routing status of edge on which the label is. */
+	private boolean isEdgeWithObliqueRoutingStyle;
+
+	/** The old offset of the label */
+	private Point oldLabelOffset;
+
+	/**
+	 * The keyPoint of the label (
+	 * {@link org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart#getKeyPoint()}
+	 * ).
+	 */
+	private Integer keyPoint;
+
+	private List<LineSeg> oldEdgeSegments;
+
+	private List<LineSeg> newEdgeSegments;
+
+	/**
+	 * True if the parent's label is a bracketEdge (specific locator for center
+	 * label and possibility to rotate the middle segment), false otherwise.
+	 */
+	private boolean isOnBracketEdge;
+
+	/** The size of the label. */
+	private Dimension labelSize;
+
+	/**
+	 * Return the default snap back position according to the keyPoint of the label.
+	 *
+	 * @param keyPoint
+	 *            The keyPoint of the label (
+	 *            {@link org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart#getKeyPoint()}
+	 *            ).
+	 * @return the default snap back position according to the keyPoint.
+	 */
+	public static Point getSnapBackPosition(Integer keyPoint) {
+		return new Point();
+	}
+
+	/**
+	 * Calculates the label offset from the reference point given the label center
+	 * and a points list.<BR>
+	 * {@link org.eclipse.gmf.runtime.diagram.ui.internal.figures.LabelHelper#offsetFromRelativeCoordinate(org.eclipse.draw2d.IFigure, org.eclipse.draw2d.geometry.Rectangle, Point)}
+	 *
+	 * @param labelCenter
+	 *            the label center for the <code>IFigure</code> to calculate the
+	 *            offset for
+	 * @param points
+	 *            the <code>PointList</code> of the edge that contains the label.
+	 *            The label offset is relative to this <code>PointList</code>.
+	 * @param ref
+	 *            the <code>Point</code> that is the reference point that the offset
+	 *            is based on.
+	 * @return a <code>Point</code> which represents a value offset from the
+	 *         <code>ref</code> point oriented based on the nearest line segment.
+	 */
+	public static Point offsetFromRelativeCoordinate(Point labelCenter, PointList points, Point ref) {
+		Vector fromAnchorToLabelCenterPointVector = new Vector(labelCenter.x - ref.x, labelCenter.y - ref.y);
+		@SuppressWarnings("rawtypes")
+		List lineSegments = PointListUtilities.getLineSegments(points);
+		LineSeg segmentContainingLabelAnchor = PointListUtilities.getNearestSegment(lineSegments, ref.x, ref.y);
+		Vector rotatedVector = getRotatedVector(fromAnchorToLabelCenterPointVector, segmentContainingLabelAnchor,
+				false);
+
+		return new PrecisionPoint(rotatedVector.x, rotatedVector.y);
+	}
+
+	/**
+	 * Calculates the relative coordinate that is equivalent to the offset from the
+	 * reference point, that can be used to set the label center location. <BR>
+	 *
+	 * This is another implementation of
+	 * {@link org.eclipse.gmf.runtime.diagram.ui.internal.figures.LabelHelper#relativeCoordinateFromOffset(org.eclipse.draw2d.IFigure, Point, Point)}
+	 * . See bugzilla 476305 for more detail.
+	 *
+	 * @param points
+	 *            the <code>PointList</code> of the edge that contains the label.
+	 *            The label offset is relative to this <code>PointList</code>.
+	 * @param ref
+	 *            a <code>Point</code> located on the parent which the offset value
+	 *            is relative to.
+	 * @param offset
+	 *            a <code>Point</code> which represents a value offset from the
+	 *            <code>ref</code> point oriented based on the nearest line segment.
+	 * @return a <code>Point</code> that is the relative coordinate of the label
+	 *         that can be used to set it's center location.
+	 */
+	public static Point relativeCenterCoordinateFromOffset(PointList points, Point ref, Point offset) {
+		Vector fromAnchorToLabelCenterPointVector = new Vector(offset.x, offset.y);
+		@SuppressWarnings("rawtypes")
+		List lineSegments = PointListUtilities.getLineSegments(points);
+		LineSeg segmentContainingLabelAnchor = PointListUtilities.getNearestSegment(lineSegments, ref.x, ref.y);
+		Vector rotatedVector = getRotatedVector(fromAnchorToLabelCenterPointVector, segmentContainingLabelAnchor, true);
+
+		return new PrecisionPoint(ref.x + rotatedVector.x, ref.y + rotatedVector.y);
+	}
+
+	/**
+	 * Default constructor.
+	 *
+	 * @param oldBendPointList
+	 *            Bendpoint list before the edge modification
+	 * @param newBendPointList
+	 *            Bendpoint list after the edge modification
+	 * @param isEdgeWithObliqueRoutingStyle
+	 *            status of the edge from which to get the previous position of the
+	 *            bendpoints and from which to get the three labels
+	 * @param oldLabelOffset
+	 *            The old offset.
+	 * @param labelSize
+	 *            The size of the label
+	 * @param keyPoint
+	 *            The keyPoint of the label (
+	 *            {@link org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart#getKeyPoint()}
+	 *            )
+	 * @param isOnBracketEdge
+	 *            True if the parent's label is a bracketEdge (specific locator for
+	 *            center label and possibility to rotate the middle segment), false
+	 *            otherwise.
+	 */
+	// @SuppressWarnings("unchecked")
+	@SuppressWarnings("unchecked")
+	public EdgeLabelQuery(PointList oldBendPointList, PointList newBendPointList, boolean isEdgeWithObliqueRoutingStyle,
+			Point oldLabelOffset, Dimension labelSize, Integer keyPoint, boolean isOnBracketEdge) {
+		this.isEdgeWithObliqueRoutingStyle = isEdgeWithObliqueRoutingStyle;
+
+		this.oldBendPointList = oldBendPointList;
+		this.newBendPointList = newBendPointList;
+		this.oldLabelOffset = oldLabelOffset;
+		this.labelSize = labelSize;
+		this.keyPoint = keyPoint;
+		this.isOnBracketEdge = isOnBracketEdge;
+
+		// compute lineSegments from bendPoints
+		oldEdgeSegments = PointListUtilities.getLineSegments(oldBendPointList);
+		newEdgeSegments = PointListUtilities.getLineSegments(newBendPointList);
+	}
+
+	/**
+	 * Calculate the new GMF label offset: the label offset defines the position of
+	 * the label compared to labelAnchor point. <br>
+	 * The new Label offset is computed taking into account:<br>
+	 * <ul>
+	 * <li>the label anchor point move (start, center or end)</li>
+	 * <li>the orientation of the segment owning the label anchor. Indeed, the label
+	 * offset is displayed by draw2D relatively to the direction of the edge segment
+	 * including the anchor of the label</li>
+	 * <li>the expected move of the label according to the functional
+	 * specification</li>
+	 * </ul>
+	 * .
+	 *
+	 * @return the new offset of the label
+	 */
+	public Point calculateGMFLabelOffset() {
+		if (areBendpointsIdentical() && areSegmentsValid()) {
+			return oldLabelOffset;
+		} else {
+			int anchorPointRatio = getLocation(keyPoint);
+			Point oldAnchorPoint = getAnchorPoint(oldBendPointList, anchorPointRatio);
+			Point oldLabelCenter = relativeCenterCoordinateFromOffset(oldBendPointList, oldAnchorPoint, oldLabelOffset);
+
+			Point newAnchorPoint = getAnchorPoint(newBendPointList, anchorPointRatio);
+
+			Point newLabelCenter = calculateNewCenterLocation(oldLabelCenter,
+					getStandardLabelCenterLocation(newBendPointList, keyPoint));
+			return offsetFromRelativeCoordinate(newLabelCenter, newBendPointList, newAnchorPoint);
+		}
+	}
+
+	private Point getAnchorPoint(PointList pointList, int anchorPointRatio) {
+		return PointListUtilities.calculatePointRelativeToLine(pointList, 0, anchorPointRatio, true);
+	}
+
+	/**
+	 * Check if all segments of new and old points are valid (no segment with same
+	 * origin and terminus).
+	 *
+	 * @return true if segments are valid, false otherwise.
+	 */
+	private boolean areSegmentsValid() {
+		boolean areSegmentsValid = true;
+		for (LineSeg lineSeg : newEdgeSegments) {
+			if (lineSeg.getOrigin().equals(lineSeg.getTerminus())) {
+				areSegmentsValid = false;
+				break;
+			}
+		}
+
+		if (areSegmentsValid) {
+			for (LineSeg lineSeg : oldEdgeSegments) {
+				if (lineSeg.getOrigin().equals(lineSeg.getTerminus())) {
+					areSegmentsValid = false;
+					break;
+				}
+			}
+		}
+		return areSegmentsValid;
+	}
+
+	/**
+	 * Check if the old points and the new one are the same.
+	 *
+	 * @return true if the old points are the same as the new, false otherwise.
+	 */
+	private boolean areBendpointsIdentical() {
+		boolean areBendpointsIdentical = true;
+		if (newBendPointList.size() == oldBendPointList.size()) {
+			for (int i = 0; i < newBendPointList.size(); i++) {
+				Point newPoint = newBendPointList.getPoint(i);
+				Point oldPoint = oldBendPointList.getPoint(i);
+				if (!newPoint.equals(oldPoint)) {
+					areBendpointsIdentical = false;
+					break;
+				}
+			}
+		} else {
+			areBendpointsIdentical = false;
+		}
+
+		return areBendpointsIdentical;
+	}
+
+	/**
+	 * Calculate the new center location of the label according to functional
+	 * specification.
+	 *
+	 * @param oldCenterLabel
+	 *            The old center location of the label.
+	 * @param newDefaultLocation
+	 *            The standard center location according to the label keyPoint (
+	 *            {@link org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart#getKeyPoint()}
+	 *            and the default snap back position (
+	 *            {@link LabelEditPart#getSnapBackPosition(String)}.
+	 * @return
+	 */
+	private Point calculateNewCenterLocation(Point oldCenterLabel, Point newDefaultLocation) {
+		Vector fromOldToNewCenterVector = null;
+
+		// Step 1 : Calculate old reference point (the nearest point on the edge
+		// from the center of the label).
+		LineSeg oldNearestSeg = PointListUtilities.getNearestSegment(oldEdgeSegments, oldCenterLabel.x,
+				oldCenterLabel.y);
+		Point oldNearestPoint = oldNearestSeg.perpIntersect(oldCenterLabel.x, oldCenterLabel.y);
+
+		// Step 2 : Is there a new segment and an old segment on the same line?
+		// Case of segment increased or decreased (and eventually inverted)
+		Optional<Vector> fromOldToNewRefPoint = getVectorFromOldToNewForSegmentsOnSameLine(oldNearestSeg,
+				oldNearestPoint, oldCenterLabel);
+		if (fromOldToNewRefPoint.isPresent()) {
+			// In this case the vector for the reference point is the same than
+			// for the label center.
+			fromOldToNewCenterVector = fromOldToNewRefPoint.get();
+		} else { // No identical segment line has been found
+			// RECTILINEAR and TREE routing
+			if (!isEdgeWithObliqueRoutingStyle) {
+				// Get projection of oldNearestPoint on newSegments along
+				// oldRefVector
+				LineSeg oldRefVectorIntoSegment = null;
+				if (oldCenterLabel.equals(oldNearestPoint)) {
+					// Get a segment perpendicular to oldRefSegment going
+					// through oldNearestPoint
+					oldRefVectorIntoSegment = new LineSeg(oldNearestPoint,
+							new PrecisionPoint(
+									oldNearestPoint.x + (oldNearestSeg.getOrigin().y - oldNearestSeg.getTerminus().y),
+									oldNearestPoint.y - (oldNearestSeg.getOrigin().x - oldNearestSeg.getTerminus().x)));
+				} else {
+					oldRefVectorIntoSegment = new LineSeg(oldCenterLabel, oldNearestPoint);
+				}
+
+				// Is there a new segment at the same index as old segment and
+				// with same axis? Case of rectilinear segment move.
+				fromOldToNewCenterVector = getVectorForSegmentMoveCase(oldNearestSeg, oldNearestPoint, oldCenterLabel);
+				if (fromOldToNewCenterVector == null && isOnBracketEdge) {
+					// Is there a new segment at the same index as old segment
+					// and with opposite axis? Case of change orientation of the
+					// bracket edge
+					fromOldToNewCenterVector = getVectorForBracketEdgeOrientationChangeCase(oldNearestSeg,
+							oldNearestPoint, oldCenterLabel);
+				}
+				if (fromOldToNewCenterVector == null) {
+					for (LineSeg lineSeg : newEdgeSegments) {
+						PointList linesIntersections = oldRefVectorIntoSegment.getLinesIntersections(lineSeg);
+						// intersection should be, at more, one point
+						if (linesIntersections.size() == 1 && lineSeg.distanceToPoint(linesIntersections.getPoint(0).x,
+								linesIntersections.getPoint(0).y) <= Math.sqrt(2)) {
+							Vector tempLabelMove = new Vector(linesIntersections.getPoint(0).x - oldNearestPoint.x,
+									linesIntersections.getPoint(0).y - oldNearestPoint.y);
+							if (fromOldToNewCenterVector == null
+									|| tempLabelMove.getLength() < fromOldToNewCenterVector.getLength()) {
+								fromOldToNewCenterVector = tempLabelMove;
+							}
+						}
+					}
+					// Compare the minimalLabelMove with the default location.
+					// If the default location is nearer reset the labelMove.
+					Vector fromOldNearestPointToStandardLocation = new Vector(newDefaultLocation.x - oldNearestPoint.x,
+							newDefaultLocation.y - oldNearestPoint.y);
+					if (fromOldToNewCenterVector == null || fromOldNearestPointToStandardLocation
+							.getLength() < fromOldToNewCenterVector.getLength()) {
+						fromOldToNewCenterVector = null;
+					}
+				}
+			} else if (newEdgeSegments.size() == oldEdgeSegments.size()) {
+				// The newNearestSegment as the same index in
+				// newEdgeSegments than oldNearestSegment in oldEdgeSegments
+				LineSeg newRefSeg = newEdgeSegments.get(oldEdgeSegments.indexOf(oldNearestSeg));
+				// Keep ratio on segment for newRefPoint
+				double oldRatio = oldNearestSeg.projection(oldCenterLabel.x, oldCenterLabel.y);
+				Point newRefPoint = new PrecisionPoint(
+						newRefSeg.getOrigin().x + oldRatio * (newRefSeg.getTerminus().x - newRefSeg.getOrigin().x),
+						newRefSeg.getOrigin().y + oldRatio * (newRefSeg.getTerminus().y - newRefSeg.getOrigin().y));
+				fromOldToNewCenterVector = new Vector(newRefPoint.x - oldNearestPoint.x,
+						newRefPoint.y - oldNearestPoint.y);
+
+			}
+		}
+		if (fromOldToNewCenterVector == null) {
+			return newDefaultLocation;
+		} else {
+			return oldCenterLabel.getTranslated(fromOldToNewCenterVector.x, fromOldToNewCenterVector.y);
+		}
+	}
+
+	/**
+	 * Check if we are in case of a rectilinear segment move: there is a new segment
+	 * at the same index as old nearest segment and with the same axis. Return the
+	 * corresponding vector from old to new center in this case, null otherwise.
+	 *
+	 * @param oldNearestSeg
+	 *            The segment that is the nearest from the center of the label in
+	 *            the old points list.
+	 * @return the corresponding vector from old to new center in case of
+	 *         rectilinear segment move, null otherwise.
+	 */
+	private Vector getVectorForSegmentMoveCase(LineSeg oldNearestSeg, Point oldNearestPoint, Point oldCenterLabel) {
+		Vector fromOldToNewCenterVector = null;
+		if (newEdgeSegments.size() == oldEdgeSegments.size()) {
+			int index = oldEdgeSegments.indexOf(oldNearestSeg);
+			LineSeg newNearestSegment = newEdgeSegments.get(index);
+			if (oldNearestSeg.isHorizontal() == newNearestSegment.isHorizontal()) {
+				Vector oldVector = new Vector(oldNearestSeg.getTerminus().x - oldNearestSeg.getOrigin().x,
+						oldNearestSeg.getTerminus().y - oldNearestSeg.getOrigin().y);
+				Vector newVector = new Vector(newNearestSegment.getTerminus().x - newNearestSegment.getOrigin().x,
+						newNearestSegment.getTerminus().y - newNearestSegment.getOrigin().y);
+				fromOldToNewCenterVector = applyOldRatioOnNewSegment(oldNearestSeg, oldNearestPoint, oldCenterLabel,
+						newNearestSegment, oldVector.getAngle(newVector) == 180, false);
+			}
+		}
+		return fromOldToNewCenterVector;
+	}
+
+	/**
+	 * Check if we are in case of a orientation segment change: there is a new
+	 * segment at the same index as old nearest segment and with apposite axis.
+	 * Return the corresponding vector from old to new center in this case, null
+	 * otherwise.
+	 *
+	 * @param oldNearestSeg
+	 *            The segment that is the nearest from the center of the label in
+	 *            the old points list.
+	 * @return the corresponding vector from old to new center in case of
+	 *         orientation segment change, null otherwise.
+	 */
+	private Vector getVectorForBracketEdgeOrientationChangeCase(LineSeg oldNearestSeg, Point oldNearestPoint,
+			Point oldCenterLabel) {
+		Vector fromOldToNewCenterVector = null;
+		if (newEdgeSegments.size() == oldEdgeSegments.size()) {
+			int index = oldEdgeSegments.indexOf(oldNearestSeg);
+			LineSeg newNearestSegment = newEdgeSegments.get(index);
+			if (oldNearestSeg.isHorizontal() != newNearestSegment.isHorizontal()) {
+				Vector oldVector = new Vector(oldNearestSeg.getTerminus().x - oldNearestSeg.getOrigin().x,
+						oldNearestSeg.getTerminus().y - oldNearestSeg.getOrigin().y);
+				Vector newVector = new Vector(newNearestSegment.getTerminus().x - newNearestSegment.getOrigin().x,
+						newNearestSegment.getTerminus().y - newNearestSegment.getOrigin().y);
+				double angleInDegree = Math.toDegrees(angleBetween2Lines(oldVector, newVector));
+				fromOldToNewCenterVector = applyOldRatioOnNewOrthogonalSegment(oldNearestSeg, oldNearestPoint,
+						oldCenterLabel, newNearestSegment, angleInDegree == 90 || angleInDegree == -270);
+			}
+		}
+		return fromOldToNewCenterVector;
+	}
+
+	private Optional<Vector> getVectorFromOldToNewForSegmentsOnSameLine(LineSeg oldRefSeg, Point oldRefPoint,
+			Point oldCenterLabel) {
+		Optional<Vector> result = Optional.empty();
+		LineSeg newSegmentOnSameLineWithSameDirection = null;
+		LineSeg newSegmentOnSameLineWithOppositeDirection = null;
+		// Firstly, for points lists with same nb of segments, search if the
+		// vector, at
+		// the same index, is on the same line
+		int sameLineStatus = NOT_ON_SAME_LINE;
+		if (newEdgeSegments.size() == oldEdgeSegments.size()) {
+			LineSeg newSegAtSameIndex = newEdgeSegments.get(oldEdgeSegments.indexOf(oldRefSeg));
+			sameLineStatus = getSameLineStatus(oldRefSeg, newSegAtSameIndex);
+			if (ON_SAME_LINE_SAME_DIRECTION == sameLineStatus) {
+				newSegmentOnSameLineWithSameDirection = newSegAtSameIndex;
+			} else if (ON_SAME_LINE_OPPOSITE_DIRECTION == sameLineStatus) {
+				newSegmentOnSameLineWithOppositeDirection = newSegAtSameIndex;
+			}
+		}
+		if (NOT_ON_SAME_LINE == sameLineStatus) {
+			// If this is not the case search on all new segments.
+			for (LineSeg newSeg : newEdgeSegments) {
+				sameLineStatus = getSameLineStatus(oldRefSeg, newSeg);
+				if (ON_SAME_LINE_SAME_DIRECTION == sameLineStatus) {
+					newSegmentOnSameLineWithSameDirection = newSeg;
+					break;
+				} else if (ON_SAME_LINE_OPPOSITE_DIRECTION == sameLineStatus) {
+					newSegmentOnSameLineWithOppositeDirection = newSeg;
+					// Continue to search a potential segment in the same
+					// direction.
+				}
+			}
+		}
+
+		LineSeg newRefSeg = newSegmentOnSameLineWithSameDirection;
+		if (newRefSeg == null) {
+			newRefSeg = newSegmentOnSameLineWithOppositeDirection;
+		}
+
+		if (newRefSeg != null) {
+			result = Optional.of(applyOldRatioOnNewSegment(oldRefSeg, oldRefPoint, oldCenterLabel, newRefSeg,
+					newSegmentOnSameLineWithOppositeDirection != null, true));
+		}
+		return result;
+	}
+
+	/**
+	 * Check if the <code>segment</code> is on the same line as the
+	 * <code>referenceSegment</code> and if it is in the same direction or not.
+	 *
+	 * @param referenceSegment
+	 *            The reference segment.
+	 * @param segment
+	 *            The segment to test
+	 * @return one of these statuses {@link #NOT_ON_SAME_LINE},
+	 *         {@link #ON_SAME_LINE_SAME_DIRECTION} or
+	 *         {@link #ON_SAME_LINE_OPPOSITE_DIRECTION}.
+	 */
+	private int getSameLineStatus(LineSeg referenceSegment, LineSeg segment) {
+		int result = NOT_ON_SAME_LINE;
+		if (segment.length() != 0) {
+			Vector referenceVector = new Vector(referenceSegment.getTerminus().x - referenceSegment.getOrigin().x,
+					referenceSegment.getTerminus().y - referenceSegment.getOrigin().y);
+			Vector vector = new Vector(segment.getTerminus().x - segment.getOrigin().x,
+					segment.getTerminus().y - segment.getOrigin().y);
+			double angle = referenceVector.getAngle(vector);
+			if (angle == 0 || angle == 180) {
+				Straight straight = new Straight(new PrecisionPoint(segment.getOrigin()),
+						new PrecisionPoint(segment.getTerminus()));
+				double distToInfiniteLine = straight
+						.getDistance(new Vector(referenceSegment.getOrigin().x, referenceSegment.getOrigin().y));
+				if (distToInfiniteLine < DISTANCE_TOLERANCE) {
+					if (angle == 180) {
+						result = ON_SAME_LINE_OPPOSITE_DIRECTION;
+					} else {
+						result = ON_SAME_LINE_SAME_DIRECTION;
+					}
+				}
+			}
+		}
+		return result;
+	}
+
+	private Vector applyOldRatioOnNewSegment(LineSeg oldRefSeg, Point oldRefPoint, Point oldCenterLabel,
+			LineSeg newRefSeg, boolean oppositeDirection, boolean sameLine) {
+		Vector result;
+		double newRatio = newRefSeg.projection(oldCenterLabel.x, oldCenterLabel.y);
+		if (sameLine && newRatio >= 0 && newRatio <= 1) {
+			// If the orthogonal projection is inside segment (between 0 and
+			// 1), the reference point does not move.
+			result = new Vector(0, 0);
+		} else {
+			Point newRefPoint;
+			double oldRatio = oldRefSeg.projection(oldCenterLabel.x, oldCenterLabel.y);
+			if (!oppositeDirection) {
+				newRefPoint = new PrecisionPoint(
+						newRefSeg.getOrigin().x + oldRatio * (newRefSeg.getTerminus().x - newRefSeg.getOrigin().x),
+						newRefSeg.getOrigin().y + oldRatio * (newRefSeg.getTerminus().y - newRefSeg.getOrigin().y));
+			} else {
+				newRefPoint = new PrecisionPoint(
+						newRefSeg.getOrigin().x - oldRatio * (newRefSeg.getOrigin().x - newRefSeg.getTerminus().x),
+						newRefSeg.getOrigin().y - oldRatio * (newRefSeg.getOrigin().y - newRefSeg.getTerminus().y));
+			}
+			if (!sameLine && newRatio >= 0 && newRatio <= 1) {
+				// If the orthogonal projection is inside segment (between 0 and
+				// 1), we keep the oldRefPoint one axis
+				if (newRefSeg.isHorizontal()) {
+					newRefPoint.setX(oldRefPoint.x);
+				} else {
+					newRefPoint.setY(oldRefPoint.y);
+				}
+			}
+			Vector vectorFromOldToNewRefPoint = new Vector(newRefPoint.x - oldRefPoint.x,
+					newRefPoint.y - oldRefPoint.y);
+			if (oldRatio >= 0 && oldRatio <= 1) {
+				// Keep ratio on segment for newRefPoint (if it was
+				// previously inside segment)
+				result = vectorFromOldToNewRefPoint;
+			} else {
+				// If the label is previously outside of the segment, we
+				// keep the shortest point (new or old one).
+				Point potentialNewCenter = oldCenterLabel.getTranslated(vectorFromOldToNewRefPoint.x,
+						vectorFromOldToNewRefPoint.y);
+				if ((newRatio > 1 && newRatio < newRefSeg.projection(potentialNewCenter.x, potentialNewCenter.y))
+						|| (newRatio < 0
+								&& newRatio > newRefSeg.projection(potentialNewCenter.x, potentialNewCenter.y))) {
+					result = new Vector(0, 0);
+				} else {
+					result = vectorFromOldToNewRefPoint;
+				}
+			}
+		}
+		return result;
+	}
+
+	private Vector applyOldRatioOnNewOrthogonalSegment(LineSeg oldRefSeg, Point oldRefPoint, Point oldCenterLabel,
+			LineSeg newRefSeg, boolean is90Angle) {
+		double oldRatio = oldRefSeg.projection(oldCenterLabel.x, oldCenterLabel.y);
+		Transform rotateTransform = new Transform();
+		// Get the new reference point and the rotation to apply
+		Point newRefPoint;
+		if (is90Angle) {
+			// As GMF coordinates system is reversed (y positive orientation is
+			// from top to bottom), we reverse the rotation to apply
+			rotateTransform.setRotation(Math.toRadians(-90));
+			if (0 <= oldRatio && oldRatio <= 1) {
+				// Apply same ratio on the new segment to compute the new
+				// reference point
+				newRefPoint = new PrecisionPoint(
+						newRefSeg.getOrigin().x - oldRatio * (newRefSeg.getOrigin().x - newRefSeg.getTerminus().x),
+						newRefSeg.getOrigin().y - oldRatio * (newRefSeg.getOrigin().y - newRefSeg.getTerminus().y));
+			} else if (oldRatio > 1) {
+				// Just apply the vector from old terminus to old reference
+				// point to the new terminus
+				Vector vectorFromOldTerminusToOldRefPoint = new Vector(oldRefPoint.x - oldRefSeg.getTerminus().x,
+						oldRefPoint.y - oldRefSeg.getTerminus().y);
+				Point vectorFromNewTerminusToNewRefPoint = rotateTransform
+						.getTransformed(vectorFromOldTerminusToOldRefPoint.toPoint());
+				newRefPoint = newRefSeg.getTerminus().getTranslated(vectorFromNewTerminusToNewRefPoint);
+			} else {
+				Vector vectorFromOldOriginToOldRefPoint = new Vector(oldRefPoint.x - oldRefSeg.getOrigin().x,
+						oldRefPoint.y - oldRefSeg.getOrigin().y);
+				Point vectorFromNewOriginToNewRefPoint = rotateTransform
+						.getTransformed(vectorFromOldOriginToOldRefPoint.toPoint());
+				newRefPoint = newRefSeg.getOrigin().getTranslated(vectorFromNewOriginToNewRefPoint);
+			}
+		} else {
+			// As GMF coordinates system is reversed (y positive orientation is
+			// from top to bottom), we reverse the rotation to apply
+			rotateTransform.setRotation(Math.toRadians(90));
+			if (0 <= oldRatio && oldRatio <= 1) {
+				// Apply same ratio on the new segment to compute the new
+				// reference point (but inverse the origin and the terminus)
+				newRefPoint = new PrecisionPoint(
+						newRefSeg.getOrigin().x + oldRatio * (newRefSeg.getTerminus().x - newRefSeg.getOrigin().x),
+						newRefSeg.getOrigin().y + oldRatio * (newRefSeg.getTerminus().y - newRefSeg.getOrigin().y));
+			} else if (oldRatio > 1) {
+				// Just apply the vector from old terminus to old reference
+				// point to the new terminus
+				Vector vectorFromOldTerminusToOldRefPoint = new Vector(oldRefPoint.x - oldRefSeg.getTerminus().x,
+						oldRefPoint.y - oldRefSeg.getTerminus().y);
+				Point vectorFromNewTerminusToNewRefPoint = rotateTransform
+						.getTransformed(vectorFromOldTerminusToOldRefPoint.toPoint());
+				newRefPoint = newRefSeg.getTerminus().getTranslated(vectorFromNewTerminusToNewRefPoint);
+			} else {
+				Vector vectorFromOldOriginToOldRefPoint = new Vector(oldRefPoint.x - oldRefSeg.getOrigin().x,
+						oldRefPoint.y - oldRefSeg.getOrigin().y);
+				Point vectorFromNewOriginToNewRefPoint = rotateTransform
+						.getTransformed(vectorFromOldOriginToOldRefPoint.toPoint());
+				newRefPoint = newRefSeg.getOrigin().getTranslated(vectorFromNewOriginToNewRefPoint);
+			}
+		}
+		Vector vectorFromOldRefPointToOldCenterLabel = new Vector(oldCenterLabel.x - oldRefPoint.x,
+				oldCenterLabel.y - oldRefPoint.y);
+		Point fromNewRefPointToNewCenterLabel = rotateTransform
+				.getTransformed(vectorFromOldRefPointToOldCenterLabel.toPoint());
+		// Adjust the vector to apply according to orientation change (width
+		// becomes height and conversely)
+		if (newRefSeg.isHorizontal()) {
+			if (0 <= oldRatio && oldRatio <= 1) {
+				int invertedWidthHeight = labelSize.width - labelSize.height;
+				if (newRefSeg.getOrigin().x > newRefSeg.getTerminus().x) {
+					invertedWidthHeight = -invertedWidthHeight;
+				}
+				fromNewRefPointToNewCenterLabel.translate(0, invertedWidthHeight / 2);
+			} else if (oldRatio > 1) {
+				int invertedWidthHeight = labelSize.width - labelSize.height;
+				if (newRefSeg.getOrigin().x > newRefSeg.getTerminus().x) {
+					invertedWidthHeight = -invertedWidthHeight;
+				}
+				fromNewRefPointToNewCenterLabel.translate(invertedWidthHeight / 2, 0);
+			} else {
+				fromNewRefPointToNewCenterLabel.translate(0, 0);
+				int invertedWidthHeight = labelSize.width - labelSize.height;
+				if (newRefSeg.getOrigin().x < newRefSeg.getTerminus().x) {
+					invertedWidthHeight = -invertedWidthHeight;
+				}
+				fromNewRefPointToNewCenterLabel.translate(invertedWidthHeight / 2, 0);
+			}
+		} else {
+			if (0 <= oldRatio && oldRatio <= 1) {
+				int invertedWidthHeight = labelSize.width - labelSize.height;
+				if (newRefSeg.getOrigin().y > newRefSeg.getTerminus().y) {
+					invertedWidthHeight = -invertedWidthHeight;
+				}
+				fromNewRefPointToNewCenterLabel.translate(invertedWidthHeight / 2, 0);
+			} else if (oldRatio > 1) {
+				int invertedWidthHeight = labelSize.height - labelSize.width;
+				if (newRefSeg.getOrigin().y > newRefSeg.getTerminus().y) {
+					invertedWidthHeight = -invertedWidthHeight;
+				}
+				fromNewRefPointToNewCenterLabel.translate(0, invertedWidthHeight / 2);
+			} else {
+				int invertedWidthHeight = labelSize.height - labelSize.width;
+				if (newRefSeg.getOrigin().y < newRefSeg.getTerminus().y) {
+					invertedWidthHeight = -invertedWidthHeight;
+				}
+				fromNewRefPointToNewCenterLabel.translate(0, invertedWidthHeight / 2);
+			}
+		}
+		// Apply the rotated vector on new reference point to have the new
+		// center
+		Point newCenterLabel = newRefPoint.getTranslated(fromNewRefPointToNewCenterLabel);
+		// Compute the vector from old center to new center
+		return new Vector(newCenterLabel.x - oldCenterLabel.x, newCenterLabel.y - oldCenterLabel.y);
+	}
+
+	/**
+	 * Get the rotated vector according to the segment orientation.
+	 *
+	 * @param vector
+	 *            vector to be rotated
+	 * @param segment
+	 *            reference segment
+	 * @param inverseRotation
+	 *            if true, inverse rotation
+	 * @return the rotated Vector
+	 */
+	private static Vector getRotatedVector(Vector vector, LineSeg segment, boolean inverseRotation) {
+		Vector result = new Vector(vector.x, vector.y);
+		if (vector.x != 0 || vector.y != 0) {
+			double angle = angleBetween2Lines(new LineSeg(new Point(0, 0), new Point(1, 0)), segment)
+					* (inverseRotation ? -1 : 1);
+			Transform rotateTransform = new Transform();
+			rotateTransform.setRotation(angle);
+			Point rotatedPoint = rotateTransform.getTransformed(vector.toPoint());
+
+			result.x = rotatedPoint.x;
+			result.y = rotatedPoint.y;
+		}
+		return result;
+	}
+
+	/**
+	 * Get the signed angle between two segments.
+	 *
+	 * @param line1
+	 * @param line2
+	 * @return the signed angle in radian.
+	 */
+	private static double angleBetween2Lines(LineSeg line1, LineSeg line2) {
+		if (line1 == null || line2 == null) {
+			return 0;
+		}
+		double angle1 = Math.atan2(line1.getOrigin().y - line1.getTerminus().y,
+				line1.getOrigin().x - line1.getTerminus().x);
+		double angle2 = Math.atan2(line2.getOrigin().y - line2.getTerminus().y,
+				line2.getOrigin().x - line2.getTerminus().x);
+		return angle1 - angle2;
+	}
+
+	/**
+	 * Get the signed angle between two vectors.
+	 *
+	 * @param vector1
+	 *            The first vector
+	 * @param vector2
+	 *            The second vector
+	 * @return the signed angle in radian.
+	 */
+	private static double angleBetween2Lines(Vector vector1, Vector vector2) {
+		if (vector1 == null || vector2 == null) {
+			return 0;
+		}
+		double angle1 = Math.atan2(vector1.y, vector1.x);
+		double angle2 = Math.atan2(vector2.y, vector2.x);
+		return angle1 - angle2;
+	}
+
+	/**
+	 * Get the standard center location according to the label keyPoint (
+	 * {@link org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart#getKeyPoint()}
+	 * ) and the default snap back position (
+	 * {@link LabelEditPart#getSnapBackPosition(String)}
+	 *
+	 * @param pointsList
+	 *            The points of the edge of the label.
+	 * @param keyPoint
+	 *            The keyPoint of the label (
+	 *            {@link org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart#getKeyPoint()}
+	 *            ).
+	 * @return The center of the label {@link Bounds} if this label is located by
+	 *         default.
+	 */
+	private Point getStandardLabelCenterLocation(PointList pointsList, Integer keyPoint) {
+		int percentage = getLocation(keyPoint);
+		Point newAnchorPoint = getAnchorPoint(pointsList, percentage);
+		Point snapBackPosition = getSnapBackPosition(keyPoint);
+		Point standardLabelCenter = newAnchorPoint.getTranslated(snapBackPosition);
+		return standardLabelCenter;
+	}
+
+	/**
+	 * Get the location among {@link LabelViewConstants} constants where to relocate
+	 * the label figure.
+	 *
+	 * @return the location among {@link LabelViewConstants} constants
+	 */
+	private static int getLocation(Integer keyPoint) {
+		int location = LabelViewConstants.MIDDLE_LOCATION;
+		switch (keyPoint) {
+		case ConnectionLocator.SOURCE:
+			location = LabelViewConstants.TARGET_LOCATION;
+			break;
+		case ConnectionLocator.TARGET:
+			location = LabelViewConstants.SOURCE_LOCATION;
+			break;
+		case ConnectionLocator.MIDDLE:
+			location = LabelViewConstants.MIDDLE_LOCATION;
+			break;
+		default:
+			location = LabelViewConstants.MIDDLE_LOCATION;
+			break;
+		}
+		return location;
+	}
+}

+ 118 - 0
plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/routing/InitialPointsOfRequestDataManager.java

@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.yakindu.base.xtext.utils.gmf.routing;
+
+import java.util.List;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Vector;
+import org.eclipse.gef.ConnectionEditPart;
+import org.eclipse.gef.requests.LocationRequest;
+import org.eclipse.gmf.runtime.draw2d.ui.figures.WrappingLabel;
+import org.yakindu.base.xtext.utils.gmf.directedit.ExternalXtextLabelEditPart;
+
+/**
+ * This manager is used to store the initial points of an edge before the
+ * feedback is used. These initial points are stored in the request.<BR>
+ * The method
+ * {@link #storeInitialPointsInRequest(LocationRequest, ConnectionEditPart, Connection)}
+ * must be called in the corresponding policy before drawing the feedback.<BR>
+ * And the method {@link #eraseInitialPoints(Connection)} must be called at the
+ * end of the feedback drawing (eraseConnection*Feedback methods of Policy
+ * classes).
+ *
+ *
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public class InitialPointsOfRequestDataManager {
+    /**
+     * The key used to store the initial points of the edge (before the feedback
+     * drawing).
+     */
+    private static final String INITIAL_POINTS_KEY = "InitialPointsManagerForEdgePolicy.initialPointsKey"; //$NON-NLS-1$
+
+    /** The list of points before feedback drawing. */
+    private PointList initialPoints;
+
+    /**
+     * Store the initial points of the edge in the request (before feedback
+     * drawing). This data can be used later for computing the location of the
+     * labels of this edge in the command construction.<BR>
+     * This method also set the feedback data of the {@link EdgeLabelLocator} of
+     * the labels of the current connection to correctly draw the label feedback
+     * during the label move.
+     *
+     * @param request
+     *            the request in which to store the original points of the edge.
+     * @param connectionEditPart
+     *            the editPart of the edge
+     */
+    @SuppressWarnings("unchecked")
+	public void storeInitialPointsInRequest(LocationRequest request, ConnectionEditPart connectionEditPart) {
+        if (initialPoints == null) {
+            initialPoints = new PointList();
+            Connection connection = (Connection) connectionEditPart.getFigure();
+            for (int i = 0; i < connection.getPoints().size(); i++) {
+                initialPoints.addPoint(connection.getPoints().getPoint(i).getCopy());
+            }
+
+            request.getExtendedData().put(INITIAL_POINTS_KEY, initialPoints);
+            List<?> children = connectionEditPart.getChildren();
+            for (Object child : children) {
+                if (child instanceof ExternalXtextLabelEditPart) {
+                    IFigure figure = ((ExternalXtextLabelEditPart) child).getFigure();
+                        Object currentConstraint = connection.getLayoutManager().getConstraint(figure);
+                        if (currentConstraint instanceof EdgeLabelLocator) {
+                            EdgeLabelLocator edgeLabelLocator = (EdgeLabelLocator) currentConstraint;
+                            edgeLabelLocator.setFeedbackData(initialPoints, new Vector(edgeLabelLocator.getOffset().x, edgeLabelLocator.getOffset().y), true);
+//                                    new ConnectionEditPartQuery(connectionEditPart).isEdgeWithObliqueRoutingStyle()); //TODO
+                        }
+                    }
+                }
+            }
+    }
+
+
+    /**
+     * Reset the initial points stored in this manager and also erase the
+     * feedback data from all the {@link EdgeLabelLocator} of the labels of the
+     * current connection.
+     *
+     * @param connection
+     *            The connection from which to erase feedback data
+     */
+    public void eraseInitialPoints(Connection connection) {
+        initialPoints = null;
+        for (Object object : connection.getChildren()) {
+            if (object instanceof WrappingLabel) {
+                Object currentConstraint = connection.getLayoutManager().getConstraint((WrappingLabel) object);
+                if (currentConstraint instanceof EdgeLabelLocator) {
+                    ((EdgeLabelLocator) currentConstraint).eraseFeedbackData();
+                }
+            }
+        }
+    }
+
+    /**
+     * Get the initial points list of the edge stored in the
+     * <code>request</code>.
+     *
+     * @param request
+     *            The request to query
+     * @return the original points list or null if no original points are stored
+     *         in this request.
+     */
+    public static PointList getOriginalPoints(LocationRequest request) {
+        return (PointList) request.getExtendedData().get(INITIAL_POINTS_KEY);
+    }
+}

+ 100 - 0
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/commands/SetConnectionBendpointsAndLabelCommmand.java

@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.yakindu.sct.ui.editor.commands;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.internal.commands.SetConnectionBendpointsCommand;
+
+/**
+ * This class allows to update edge label Node position when updating
+ * bendpoints.
+ *
+ * @author <a href="mailto:laurent.fasani@obeo.fr">Laurent Fasani</a>
+ *
+ */
+@SuppressWarnings("restriction")
+public class SetConnectionBendpointsAndLabelCommmand extends SetConnectionBendpointsCommand {
+
+    /** Operation to delegate the job concerning the labels. */
+    private SetLabelsOffsetOperation setLabelsOperation;
+
+    /**
+     * Default constructor.
+     *
+     * @param editingDomain
+     *            the editing domain through which model changes are made
+     */
+    public SetConnectionBendpointsAndLabelCommmand(TransactionalEditingDomain editingDomain) {
+        super(editingDomain);
+        setLabelsOperation = new SetLabelsOffsetOperation();
+    }
+
+    @Override
+    protected IStatus doExecute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
+        setLabelsOperation.updateGMFLabelsOffset();
+        return super.doExecute(monitor, info);
+    }
+
+    /**
+     * Set labels to update according to a connectionEditPart (all labels of
+     * this connection will be update). <BR>
+     * This method must be called after having called the
+     * {@link #setNewPointList(PointList, org.eclipse.draw2d.ConnectionAnchor, org.eclipse.draw2d.ConnectionAnchor)}
+     * of {@link #setNewPointList(PointList, Point, Point)} method.
+     *
+     * @param connectionEditPart
+     *            The connection from which to get the potential three labels to
+     *            update
+     */
+    public void setLabelsToUpdate(ConnectionEditPart connectionEditPart) {
+        setLabelsOperation.setLabelsToUpdate(connectionEditPart);
+
+    }
+
+    /**
+     * Set labels to update according to a connectionEditPart (all labels of
+     * this connection will be update). This method must be used if the edge
+     * figure is updated (through feedback) during the move. Indeed, in this
+     * case, we can not use the figure to retrieve the old points.<BR>
+     * This method must be called after having called the
+     * {@link #setNewPointList(PointList, org.eclipse.draw2d.ConnectionAnchor, org.eclipse.draw2d.ConnectionAnchor)}
+     * of {@link #setNewPointList(PointList, Point, Point)} method.
+     *
+     * @param connectionEditPart
+     *            The connection from which to get the potential three labels to
+     *            update
+     * @param originalPoints
+     *            The points of the edge before the move.
+     */
+    public void setLabelsToUpdate(ConnectionEditPart connectionEditPart, PointList originalPoints) {
+        setLabelsOperation.setLabelsToUpdate(connectionEditPart, originalPoints);
+    }
+
+    @Override
+    public void setNewPointList(PointList newPointList, Point sourceRefPoint, Point targetRefPoint) {
+        super.setNewPointList(newPointList, sourceRefPoint, targetRefPoint);
+        setLabelsOperation.setNewPointList(newPointList);
+    }
+
+    @Override
+    public void setNewPointList(PointList newPointList, ConnectionAnchor sourceAnchor, ConnectionAnchor targetAnchor) {
+        super.setNewPointList(newPointList, sourceAnchor, targetAnchor);
+        setLabelsOperation.setNewPointList(newPointList);
+    }
+}

+ 192 - 0
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/commands/SetLabelsOffsetOperation.java

@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.yakindu.sct.ui.editor.commands;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart;
+import org.eclipse.gmf.runtime.notation.Bounds;
+import org.eclipse.gmf.runtime.notation.ConnectorStyle;
+import org.eclipse.gmf.runtime.notation.Edge;
+import org.eclipse.gmf.runtime.notation.LayoutConstraint;
+import org.eclipse.gmf.runtime.notation.Location;
+import org.eclipse.gmf.runtime.notation.Node;
+import org.eclipse.gmf.runtime.notation.NotationPackage;
+import org.eclipse.gmf.runtime.notation.Routing;
+import org.yakindu.base.xtext.utils.gmf.routing.EdgeLabelQuery;
+
+/**
+ * Operation concerning the label offset. Used to delegate from the
+ * {@link SetLabelsOffsetCommmand} and from the
+ * {@link SetConnectionBendpointsAndLabelCommmand}.
+ *
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public class SetLabelsOffsetOperation {
+	/**
+	 * The labels with their offset computed during the call to
+	 * {@link #setLabelsToUpdate(ConnectionEditPart)}. This list is then used during
+	 * the execution of the operations to update the label location.
+	 */
+	private Map<Node, Point> labelsWithNewOffset;
+
+	/** The old points list, used in case of feedback that impacts the edge. */
+	private PointList oldBendPointsList;
+
+	/** The new points list. */
+	private PointList newPointList;
+
+	/**
+	 * Method to set the newPointList.
+	 *
+	 * @param newPointList
+	 *            The new points list
+	 */
+	public void setNewPointList(PointList newPointList) {
+		this.newPointList = new PointList(newPointList.size());
+		for (int i = 0; i < newPointList.size(); i++) {
+			this.newPointList.addPoint(newPointList.getPoint(i));
+		}
+	}
+
+	/**
+	 * Set labels to update according to a connectionEditPart (all labels of this
+	 * connection will be update). This method must be used if the edge figure is
+	 * updated (through feedback) during the move. Indeed, in this case, we can not
+	 * use the figure to retrieve the old points.<BR>
+	 * This method must be called after having called the
+	 * {@link #setNewPointList(PointList)} method.
+	 *
+	 * @param connectionEditPart
+	 *            The connection from which to get the potential three labels to
+	 *            update
+	 * @param originalPoints
+	 *            The points of the edge before the move.
+	 */
+	public void setLabelsToUpdate(ConnectionEditPart connectionEditPart, PointList originalPoints) {
+		oldBendPointsList = originalPoints;
+		setLabelsToUpdate(connectionEditPart);
+	}
+
+	/**
+	 * Set labels to update according to a connectionEditPart (all labels of this
+	 * connection will be update). <BR>
+	 * This method must be called after having called the
+	 * {@link #setNewPointList(PointList)} method.
+	 *
+	 * @param connectionEditPart
+	 *            The connection from which to get the potential three labels to
+	 *            update
+	 */
+	public void setLabelsToUpdate(ConnectionEditPart connectionEditPart) {
+		List<LabelEditPart> labelEditPartsToUpdate = new ArrayList<>();
+		List<?> children = connectionEditPart.getChildren();
+		for (Object child : children) {
+			if (child instanceof LabelEditPart) {
+				Object view = ((LabelEditPart) child).getModel();
+				if (view instanceof Node) {
+					labelEditPartsToUpdate.add((LabelEditPart) child);
+				}
+			}
+		}
+
+		computeGMFLabelsOffset(labelEditPartsToUpdate, connectionEditPart);
+	}
+
+	/**
+	 * Update {@link Bounds} of the labels {@link Node}.
+	 *
+	 * @param labelEditPartsToUpdate
+	 *            List of labels to update
+	 * @param connectionEditPart
+	 *            The connection having these labels
+	 */
+	private void computeGMFLabelsOffset(List<LabelEditPart> labelEditPartsToUpdate,
+			ConnectionEditPart connectionEditPart) {
+		labelsWithNewOffset = new HashMap<>();
+		// For each label, compute the new offset
+		for (LabelEditPart labelEditPartToUpdate : labelEditPartsToUpdate) {
+			computeGMFLabelOffset(labelEditPartToUpdate, connectionEditPart);
+		}
+
+	}
+
+	/**
+	 * Update {@link Bounds} of a label {@link Node}.
+	 *
+	 * @param labelEdgeEditPart
+	 *            the editPart of the edge label to be updated
+	 * @param connectionEditPart
+	 *            The connection having these labels
+	 */
+	private void computeGMFLabelOffset(LabelEditPart labelEditPartToUpdate, ConnectionEditPart connectionEditPart) {
+		Point newLabelOffset = null;
+		Node labelNodeToUpdate = (Node) labelEditPartToUpdate.getModel();
+		if (connectionEditPart.getModel() instanceof Edge) {
+			PointList oldBendpoints = oldBendPointsList;
+			if (oldBendpoints == null) {
+				oldBendpoints = connectionEditPart.getConnectionFigure().getPoints();
+			}
+			boolean isEdgeWithObliqueRoutingStyle = isEdgeWithObliqueRoutingStyle(connectionEditPart);
+			LayoutConstraint layoutConstraint = labelNodeToUpdate.getLayoutConstraint();
+			if (layoutConstraint instanceof Location) {
+				Location point = (Location) layoutConstraint;
+				newLabelOffset = new EdgeLabelQuery(oldBendpoints, newPointList, isEdgeWithObliqueRoutingStyle,
+						new Point(point.getX(), point.getY()), labelEditPartToUpdate.getFigure().getSize(),
+						labelEditPartToUpdate.getKeyPoint(), false).calculateGMFLabelOffset();
+			}
+		}
+
+		if (newLabelOffset != null) {
+			labelsWithNewOffset.put(labelNodeToUpdate, newLabelOffset);
+		}
+	}
+
+	protected boolean isEdgeWithObliqueRoutingStyle(ConnectionEditPart part) {
+		Edge edge = (Edge) part.getModel();
+		ConnectorStyle style = (ConnectorStyle) edge.getStyle(NotationPackage.Literals.CONNECTOR_STYLE);
+		if (style != null) {
+			return Routing.MANUAL_LITERAL == style.getRouting();
+		}
+		return false;
+	}
+
+	/**
+	 * Update the offset ({@link Bounds}) of the labels {@link Node}. This method
+	 * must be called after setting the newPointList and the labelToUpdate. If the
+	 * methods {@link #setLabelsToUpdate(ConnectionEditPart)} or
+	 * {@link #setLabelsToUpdate(ConnectionEditPart, PointList)} are not called,
+	 * this method has no effect.
+	 */
+	public void updateGMFLabelsOffset() {
+		if (labelsWithNewOffset != null) {
+			// Update Bounds of the three labels Node (Center, Begin and End)
+			Set<Entry<Node, Point>> entries = labelsWithNewOffset.entrySet();
+			for (Entry<Node, Point> entry : entries) {
+				LayoutConstraint layoutConstraint = entry.getKey().getLayoutConstraint();
+				if (layoutConstraint instanceof Location) {
+					Location bounds = (Location) layoutConstraint;
+					bounds.setX(entry.getValue().x);
+					bounds.setY(entry.getValue().y);
+				}
+			}
+		}
+	}
+}

+ 102 - 86
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/editparts/TransitionEditPart.java

@@ -1,86 +1,102 @@
-/**
- * Copyright (c) 2010 committers of YAKINDU 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:
- * 	committers of YAKINDU - initial API and implementation
- * 
- */
-package org.yakindu.sct.ui.editor.editparts;
-
-import org.eclipse.draw2d.Connection;
-import org.eclipse.emf.common.notify.Notification;
-import org.eclipse.gef.DragTracker;
-import org.eclipse.gef.EditPart;
-import org.eclipse.gef.Request;
-import org.eclipse.gef.requests.DirectEditRequest;
-import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionNodeEditPart;
-import org.eclipse.gmf.runtime.gef.ui.internal.tools.SelectConnectionEditPartTracker;
-import org.eclipse.gmf.runtime.notation.NotationPackage;
-import org.eclipse.gmf.runtime.notation.View;
-import org.yakindu.sct.ui.editor.editor.figures.TransitionFigure;
-
-/**
- * 
- * @author andreas muelder - Initial contribution and API
- * 
- */
-@SuppressWarnings("restriction")
-public class TransitionEditPart extends ConnectionNodeEditPart {
-
-	public TransitionEditPart(View view) {
-		super(view);
-	}
-
-	@Override
-	protected Connection createConnectionFigure() {
-		return new TransitionFigure(getMapMode());
-	}
-
-	private TransitionFigure getPrimaryShape() {
-		return (TransitionFigure) getFigure();
-	}
-
-	@Override
-	protected void addChildVisual(EditPart childEditPart, int index) {
-		if (childEditPart instanceof TransitionExpressionEditPart) {
-			getPrimaryShape().add(
-					((TransitionExpressionEditPart) childEditPart).getFigure());
-		} else
-			super.addChildVisual(childEditPart, index);
-	}
-
-	@Override
-	protected void removeChildVisual(EditPart childEditPart) {
-		if (childEditPart instanceof TransitionExpressionEditPart) {
-			getPrimaryShape().remove(
-					((TransitionExpressionEditPart) childEditPart).getFigure());
-		}
-	}
-
-	@Override
-	protected void handleNotificationEvent(Notification notification) {
-		if (NotationPackage.eINSTANCE.getFontStyle().getEAllAttributes()
-				.contains(notification.getFeature())) {
-			refreshFont();
-		} else {
-			super.handleNotificationEvent(notification);
-		}
-	}
-
-	@Override
-	public DragTracker getDragTracker(Request req) {
-		return new SelectConnectionEditPartTracker(this) {
-			@Override
-			protected boolean handleDoubleClick(int button) {
-				DirectEditRequest req = new DirectEditRequest();
-				req.setLocation(getCurrentInput().getMouseLocation());
-				TransitionEditPart.this.performDirectEditRequest(req);
-				return true;
-			}
-		};
-	}
-
-}
+/**
+ * Copyright (c) 2010 committers of YAKINDU 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.sct.ui.editor.editparts;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.requests.DirectEditRequest;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionNodeEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.internal.editpolicies.TreeConnectionBendpointEditPolicy;
+import org.eclipse.gmf.runtime.draw2d.ui.internal.routers.ForestRouter;
+import org.eclipse.gmf.runtime.draw2d.ui.internal.routers.OrthogonalRouter;
+import org.eclipse.gmf.runtime.gef.ui.internal.editpolicies.LineMode;
+import org.eclipse.gmf.runtime.gef.ui.internal.tools.SelectConnectionEditPartTracker;
+import org.eclipse.gmf.runtime.notation.NotationPackage;
+import org.eclipse.gmf.runtime.notation.View;
+import org.yakindu.sct.ui.editor.editor.figures.TransitionFigure;
+import org.yakindu.sct.ui.editor.policies.InitialPointsConnectionBendpointEditPolicy;
+
+/**
+ * 
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+@SuppressWarnings("restriction")
+public class TransitionEditPart extends ConnectionNodeEditPart {
+
+	public TransitionEditPart(View view) {
+		super(view);
+	}
+
+	@Override
+	protected Connection createConnectionFigure() {
+		return new TransitionFigure(getMapMode());
+	}
+
+	private TransitionFigure getPrimaryShape() {
+		return (TransitionFigure) getFigure();
+	}
+
+	@Override
+	public void installEditPolicy(Object key, EditPolicy editPolicy) {
+		if (getConnectionFigure().getConnectionRouter() instanceof ForestRouter) {
+			super.installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE, new TreeConnectionBendpointEditPolicy());
+		} else if (getConnectionFigure().getConnectionRouter() instanceof OrthogonalRouter) {
+			super.installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE,
+					new InitialPointsConnectionBendpointEditPolicy(LineMode.ORTHOGONAL_FREE));
+		} else {
+			super.installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE,
+					new InitialPointsConnectionBendpointEditPolicy());
+		}
+	}
+
+	@Override
+	protected void addChildVisual(EditPart childEditPart, int index) {
+		if (childEditPart instanceof TransitionExpressionEditPart) {
+			getPrimaryShape().add(((TransitionExpressionEditPart) childEditPart).getFigure());
+		} else
+			super.addChildVisual(childEditPart, index);
+	}
+
+	@Override
+	protected void removeChildVisual(EditPart childEditPart) {
+		if (childEditPart instanceof TransitionExpressionEditPart) {
+			getPrimaryShape().remove(((TransitionExpressionEditPart) childEditPart).getFigure());
+		}
+	}
+
+	@Override
+	protected void handleNotificationEvent(Notification notification) {
+		if (NotationPackage.eINSTANCE.getFontStyle().getEAllAttributes().contains(notification.getFeature())) {
+			refreshFont();
+		} else {
+			super.handleNotificationEvent(notification);
+		}
+	}
+
+	@Override
+	public DragTracker getDragTracker(Request req) {
+		return new SelectConnectionEditPartTracker(this) {
+			@Override
+			protected boolean handleDoubleClick(int button) {
+				DirectEditRequest req = new DirectEditRequest();
+				req.setLocation(getCurrentInput().getMouseLocation());
+				TransitionEditPart.this.performDirectEditRequest(req);
+				return true;
+			}
+		};
+	}
+
+}

+ 105 - 0
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/policies/InitialPointsConnectionBendpointEditPolicy.java

@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.yakindu.sct.ui.editor.policies;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gef.ConnectionEditPart;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.requests.BendpointRequest;
+import org.eclipse.gmf.runtime.common.core.command.ICommand;
+import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ConnectionBendpointEditPolicy;
+import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
+import org.eclipse.gmf.runtime.gef.ui.internal.editpolicies.LineMode;
+import org.eclipse.gmf.runtime.notation.Edge;
+import org.yakindu.base.xtext.utils.gmf.routing.InitialPointsOfRequestDataManager;
+import org.yakindu.sct.ui.editor.commands.SetConnectionBendpointsAndLabelCommmand;
+
+/**
+ * Mostly copied from
+ * org.eclipse.sirius.diagram.ui.internal.edit.policies.SiriusConnectionBendpointEditPolicy
+ *
+ */
+@SuppressWarnings("restriction")
+public class InitialPointsConnectionBendpointEditPolicy extends ConnectionBendpointEditPolicy {
+
+	private InitialPointsOfRequestDataManager initialPointsManager = new InitialPointsOfRequestDataManager();
+	
+	public InitialPointsConnectionBendpointEditPolicy(LineMode lineSegMode) {
+		super(lineSegMode);
+	}
+
+	public InitialPointsConnectionBendpointEditPolicy() {
+		super(LineMode.OBLIQUE);
+	}
+
+	@Override
+	protected Command getBendpointsChangedCommand(BendpointRequest request) {
+		PointList originalPoints = InitialPointsOfRequestDataManager.getOriginalPoints(request);
+		Command result = super.getBendpointsChangedCommand(request);
+		if (result instanceof ICommandProxy) {
+			ICommand iCommand = ((ICommandProxy) result).getICommand();
+			if (iCommand instanceof SetConnectionBendpointsAndLabelCommmand) {
+				((SetConnectionBendpointsAndLabelCommmand) iCommand).setLabelsToUpdate(
+						(org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart) getHost(), originalPoints);
+			}
+		}
+		return result;
+	}
+
+	@Override
+	protected Command getBendpointsChangedCommand(Connection connection, Edge edge) {
+		Point ptRef1 = connection.getSourceAnchor().getReferencePoint();
+		getConnection().translateToRelative(ptRef1);
+
+		Point ptRef2 = connection.getTargetAnchor().getReferencePoint();
+		getConnection().translateToRelative(ptRef2);
+
+		TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()).getEditingDomain();
+
+		SetConnectionBendpointsAndLabelCommmand sbbCommand = new SetConnectionBendpointsAndLabelCommmand(editingDomain);
+		sbbCommand.setEdgeAdapter(new EObjectAdapter(edge));
+		sbbCommand.setNewPointList(connection.getPoints(), ptRef1, ptRef2);
+
+		return new ICommandProxy(sbbCommand);
+	}
+
+	@Override
+	protected void showMoveBendpointFeedback(BendpointRequest request) {
+		initialPointsManager.storeInitialPointsInRequest(request, (ConnectionEditPart) getHost());
+		super.showMoveBendpointFeedback(request);
+	}
+
+	@Override
+	protected void showCreateBendpointFeedback(BendpointRequest request) {
+		initialPointsManager.storeInitialPointsInRequest(request, (ConnectionEditPart) getHost());
+		super.showCreateBendpointFeedback(request);
+	}
+
+	@Override
+	protected void eraseConnectionFeedback(BendpointRequest request, boolean removeFeedbackFigure) {
+		super.eraseConnectionFeedback(request, removeFeedbackFigure);
+		if (removeFeedbackFigure) {
+			initialPointsManager.eraseInitialPoints(getConnection());
+		}
+	}
+
+	@Override
+	protected void showMoveLineSegFeedback(BendpointRequest request) {
+		initialPointsManager.storeInitialPointsInRequest(request, (ConnectionEditPart) getHost());
+		super.showMoveLineSegFeedback(request);
+	}
+
+}