Просмотр исходного кода

Merge pull request #1892 from Yakindu/issue-1143-transition-jump

fixes #1143 the transition label jumping mentioned in
Rainer Klute 8 лет назад
Родитель
Сommit
4270cd9767
13 измененных файлов с 1883 добавлено и 207 удалено
  1. 3 1
      plugins/org.yakindu.base.xtext.utils.gmf/META-INF/MANIFEST.MF
  2. 127 35
      plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/commands/AdjustIdentityAnchorCommand.java
  3. 90 0
      plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/commands/SetLabelsOffsetCommand.java
  4. 192 0
      plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/commands/SetLabelsOffsetOperation.java
  5. 21 5
      plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/directedit/ExternalXtextLabelEditPart.java
  6. 127 0
      plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/routing/EdgeLabelLocator.java
  7. 795 0
      plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/routing/EdgeLabelQuery.java
  8. 119 0
      plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/routing/InitialPointsOfRequestDataManager.java
  9. 101 0
      plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/commands/SetConnectionBendpointsAndLabelCommmand.java
  10. 2 2
      plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/editor/figures/StateFigure.java
  11. 95 78
      plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/editparts/RegionCompartmentEditPart.java
  12. 106 86
      plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/editparts/TransitionEditPart.java
  13. 105 0
      plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/policies/InitialPointsConnectionBendpointEditPolicy.java

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

@@ -12,10 +12,12 @@ Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide,
  org.eclipse.xtext.ui.shared
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Export-Package: org.yakindu.base.xtext.utils.gmf.directedit,
+Export-Package: org.yakindu.base.xtext.utils.gmf.commands,
+ 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
 

+ 127 - 35
plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/commands/AdjustIdentityAnchorCommand.java

@@ -16,90 +16,182 @@ import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.PositionConstants;
 import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
 import org.eclipse.draw2d.geometry.PrecisionPoint;
-import org.eclipse.emf.common.util.EList;
+import org.eclipse.draw2d.geometry.Rectangle;
 import org.eclipse.emf.transaction.TransactionalEditingDomain;
 import org.eclipse.gef.EditPart;
+import org.eclipse.gef.handles.HandleBounds;
 import org.eclipse.gef.requests.ChangeBoundsRequest;
 import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.draw2d.ui.figures.BaseSlidableAnchor;
 import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.gmf.runtime.gef.ui.figures.SlidableAnchor;
 import org.eclipse.gmf.runtime.notation.Anchor;
 import org.eclipse.gmf.runtime.notation.Edge;
 import org.eclipse.gmf.runtime.notation.IdentityAnchor;
+import org.eclipse.gmf.runtime.notation.NotationFactory;
 import org.eclipse.gmf.runtime.notation.View;
 
 /**
- * EXPERIMENTAL !!
  * 
  * Recalculates the {@link IdentityAnchor}s to recalculate connection anchors
  * when a node is resized
  * 
- * @author andreas muelder - Initial contribution and API
+ * Parts are copied from Sirius ShiftEdgeIdentityAnchorOperation
  * 
  */
 public class AdjustIdentityAnchorCommand extends AbstractTransactionalCommand {
 
+	final private static char TERMINAL_START_CHAR = '(';
+	final private static char TERMINAL_DELIMITER_CHAR = ',';
+	final private static char TERMINAL_END_CHAR = ')';
+
+	private final static PrecisionPoint DEFAULT_POINT = new PrecisionPoint(0.5d, 0.5d);
+
 	private ChangeBoundsRequest request;
-	private List<IGraphicalEditPart> editParts;
 
-	@SuppressWarnings("unchecked")
+	private Dimension futureSize;
+
+	private PrecisionPoint delta;
+
 	public AdjustIdentityAnchorCommand(TransactionalEditingDomain domain, ChangeBoundsRequest request) {
 		super(domain, "Adjusting anchors", null);
 		this.request = request;
-		editParts = request.getEditParts();
 
 	}
 
 	@Override
 	protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
-		for (EditPart editPart : editParts) {
+		@SuppressWarnings("unchecked")
+		List<IGraphicalEditPart> editParts = request.getEditParts();
+		for (IGraphicalEditPart editPart : editParts) {
 			adjustAnchors(editPart);
 		}
 		return CommandResult.newOKCommandResult();
 	}
 
 	@SuppressWarnings("unchecked")
-	private void adjustAnchors(EditPart editPart) {
+	protected void adjustAnchors(IGraphicalEditPart editPart) {
 		if (editPart instanceof IGraphicalEditPart) {
 			View view = ((IGraphicalEditPart) editPart).getNotationView();
-			EList<Edge> targetEdges = view.getTargetEdges();
+			List<Edge> targetEdges = view.getTargetEdges();
 			for (Edge edge : targetEdges) {
-				Anchor targetAnchor = edge.getTargetAnchor();
-				if (targetAnchor instanceof IdentityAnchor) {
-					PrecisionPoint anchorPoint = BaseSlidableAnchor.parseTerminalString(((IdentityAnchor) targetAnchor)
-							.getId());
-					IFigure figure = ((IGraphicalEditPart) editPart).getFigure();
-					Dimension sizeBefore = figure.getBounds().getSize();
-					float widthFactor = (float) (sizeBefore.width() + request.getSizeDelta().width())
-							/ (float) sizeBefore.width();
-					float heightFactor = (float) (sizeBefore.height() + request.getSizeDelta().height())
-							/ (float) sizeBefore.height();
-					PrecisionPoint newPoint = new PrecisionPoint(anchorPoint.preciseX() / widthFactor,
-							anchorPoint.preciseY() / heightFactor);
-					((IdentityAnchor) targetAnchor).setId(composeTerminalString(newPoint));
-				}
+				handleEdge(edge, editPart, false);
+			}
+			List<Edge> sourceEdges = view.getSourceEdges();
+			for (Edge edge : sourceEdges) {
+				handleEdge(edge, editPart, true);
 			}
 		}
+	}
 
+	private void handleEdge(Edge edge, EditPart editPart, boolean sourceAnchor) {
+		Anchor anchorToModify;
+		if (sourceAnchor) {
+			anchorToModify = edge.getSourceAnchor();
+		} else {
+			anchorToModify = edge.getTargetAnchor();
+		}
+		String terminalString = composeTerminalString(DEFAULT_POINT);
+		if (anchorToModify instanceof IdentityAnchor) {
+			terminalString = ((IdentityAnchor) anchorToModify).getId();
+		}
+		PrecisionPoint anchorPoint = BaseSlidableAnchor.parseTerminalString(terminalString);
+		PrecisionPoint newPoint = computeNewAnchor(anchorPoint, editPart);
+		String newTerminalString = new SlidableAnchor(null, newPoint).getTerminal();
+		if (anchorToModify instanceof IdentityAnchor) {
+			((IdentityAnchor) anchorToModify).setId(newTerminalString);
+		} else if (anchorToModify == null) {
+			// Create a new one
+			IdentityAnchor newAnchor = NotationFactory.eINSTANCE.createIdentityAnchor();
+			newAnchor.setId(newTerminalString);
+			if (sourceAnchor) {
+				edge.setSourceAnchor(newAnchor);
+			} else {
+				edge.setTargetAnchor(newAnchor);
+			}
+		}
 	}
 
-	// Copied from BaseSlideableAnchor
-	final private static char TERMINAL_START_CHAR = '(';
-	final private static char TERMINAL_DELIMITER_CHAR = ',';
-	final private static char TERMINAL_END_CHAR = ')';
+	protected double getScale(EditPart part) {
+		double scale = 1.0;
+		if (part.getRoot() instanceof DiagramRootEditPart) {
+			DiagramRootEditPart rootEditPart = (DiagramRootEditPart) part.getRoot();
+			scale = rootEditPart.getZoomManager().getZoom();
+		}
+		return scale;
+	}
+
+	private PrecisionPoint computeNewAnchor(PrecisionPoint currentAnchorPoint, EditPart editPart) {
+
+		double scale = getScale(editPart);
+		IFigure figure = ((IGraphicalEditPart) editPart).getFigure();
+		Rectangle bounds = figure.getBounds();
+		if (figure instanceof HandleBounds) {
+			bounds = ((HandleBounds) figure).getHandleBounds();
+		}
+
+		Point currentRelativePoint = getAnchorRelativePoint(currentAnchorPoint, bounds);
+
+		if (futureSize != null && delta != null) {
+			// In case of border node, the real location is computed earlier
+			// (according to BorderItemLocator). The corresponding futureSize
+			// and delta are used instead of the request data.
+			return new PrecisionPoint(((double) (currentRelativePoint.x - delta.x)) / futureSize.width,
+					((double) (currentRelativePoint.y - delta.y)) / futureSize.height);
+		} else {
+
+			double logicalWidthDelta = request.getSizeDelta().width / scale;
+			double logicalHeightDelta = request.getSizeDelta().height / scale;
+
+			int direction = request.getResizeDirection();
+
+			double newRelativeX = computeNewXRelativeLocation(direction, currentRelativePoint, logicalWidthDelta);
+			double newRelativeY = computeNewYRelativeLocation(direction, currentRelativePoint, logicalHeightDelta);
+
+			return new PrecisionPoint(newRelativeX / (bounds.width() + logicalWidthDelta),
+					newRelativeY / (bounds.height() + logicalHeightDelta));
+		}
+	}
+
+	protected Point getAnchorRelativePoint(PrecisionPoint currentAnchorPoint, Rectangle bounds) {
+		return new PrecisionPoint(bounds.width() * currentAnchorPoint.preciseX(),
+				bounds.height() * currentAnchorPoint.preciseY());
+	}
+
+	private double computeNewXRelativeLocation(int direction, Point currentRelativePoint, double logicalWidthDelta) {
+
+		if (direction == PositionConstants.NORTH_WEST || direction == PositionConstants.WEST
+				|| direction == PositionConstants.SOUTH_WEST) {
+			return currentRelativePoint.preciseX() + logicalWidthDelta;
+		} else {
+
+			return currentRelativePoint.preciseX();
+		}
+	}
+
+	protected double computeNewYRelativeLocation(int direction, Point currentRelativePoint, double logicalHeightDelta) {
+
+		if (direction == PositionConstants.NORTH_WEST || direction == PositionConstants.NORTH
+				|| direction == PositionConstants.NORTH_EAST) {
+			return currentRelativePoint.preciseY() + logicalHeightDelta;
+		} else {
+			return currentRelativePoint.preciseY();
+		}
+	}
 
 	protected String composeTerminalString(PrecisionPoint p) {
 		StringBuffer s = new StringBuffer(24);
-		s.append(TERMINAL_START_CHAR); // 1 char
-		s.append(p.preciseX()); // 10 chars
-		s.append(TERMINAL_DELIMITER_CHAR); // 1 char
-		s.append(p.preciseY()); // 10 chars
-		s.append(TERMINAL_END_CHAR); // 1 char
-		return s.toString(); // 24 chars max (+1 for safety, i.e. for string
-								// termination)
+		s.append(TERMINAL_START_CHAR);
+		s.append(p.preciseX());
+		s.append(TERMINAL_DELIMITER_CHAR);
+		s.append(p.preciseY());
+		s.append(TERMINAL_END_CHAR);
+		return s.toString();
 	}
-
 }

+ 90 - 0
plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/commands/SetLabelsOffsetCommand.java

@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.commands;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+
+/**
+ * This class allows to update edge label Node position.
+ *
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public class SetLabelsOffsetCommand extends AbstractTransactionalCommand {
+
+	/** 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 SetLabelsOffsetCommand(TransactionalEditingDomain editingDomain) {
+		super(editingDomain, "Set Label offset", null);
+		setLabelsOperation = new SetLabelsOffsetOperation();
+	}
+
+	/**
+	 * Method to set the newPointList.
+	 *
+	 * @param newPointList
+	 *            The new points list
+	 */
+	public void setNewPointList(PointList newPointList) {
+		setLabelsOperation.setNewPointList(newPointList);
+	}
+
+	@Override
+	protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
+		setLabelsOperation.updateGMFLabelsOffset();
+		return CommandResult.newOKCommandResult();
+	}
+
+	/**
+	 * 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) {
+		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)} 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);
+	}
+}

+ 192 - 0
plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/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.base.xtext.utils.gmf.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);
+		}
+	}
+
+	public static boolean isEdgeWithObliqueRoutingStyle(org.eclipse.gef.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);
+				}
+			}
+		}
+	}
+}

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

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

@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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.commands.SetLabelsOffsetOperation;
+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),
+								SetLabelsOffsetOperation.isEdgeWithObliqueRoutingStyle(connectionEditPart));
+
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * 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);
+	}
+}

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

@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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;
+import org.yakindu.base.xtext.utils.gmf.commands.SetLabelsOffsetOperation;
+
+/**
+ * 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);
+    }
+}

+ 2 - 2
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/editor/figures/StateFigure.java

@@ -47,8 +47,8 @@ public class StateFigure extends RoundedRectangle {
 		GridLayout layout = new GridLayout(1, false);
 		layout.verticalSpacing = 0;
 		layout.horizontalSpacing = 0;
-		layout.marginHeight = 3;
-		layout.marginWidth = 3;
+		layout.marginHeight = 5;
+		layout.marginWidth = 5;
 		this.setLayoutManager(layout);
 		this.setCornerDimensions(new Dimension(mapMode.DPtoLP(15), mapMode
 				.DPtoLP(15)));

+ 95 - 78
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/editparts/RegionCompartmentEditPart.java

@@ -1,78 +1,95 @@
-/**
- * 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.IFigure;
-import org.eclipse.draw2d.LayoutAnimator;
-import org.eclipse.gef.EditPolicy;
-import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
-import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart;
-import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DragDropEditPolicy;
-import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
-import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ResizableEditPolicyEx;
-import org.eclipse.gmf.runtime.diagram.ui.editpolicies.XYLayoutEditPolicy;
-import org.eclipse.gmf.runtime.diagram.ui.figures.ResizableCompartmentFigure;
-import org.eclipse.gmf.runtime.diagram.ui.figures.ShapeCompartmentFigure;
-import org.eclipse.gmf.runtime.notation.View;
-import org.yakindu.sct.ui.editor.DiagramActivator;
-import org.yakindu.sct.ui.editor.policies.CompartmentCreationEditPolicy;
-import org.yakindu.sct.ui.editor.policies.RegionCompartmentCanonicalEditPolicy;
-
-/**
- * @author muelder
- * @author muehlbrandt
- */
-public class RegionCompartmentEditPart extends ShapeCompartmentEditPart {
-
-	public RegionCompartmentEditPart(View view) {
-		super(view);
-	}
-
-	@Override
-	protected void createDefaultEditPolicies() {
-		super.createDefaultEditPolicies();
-		installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CompartmentCreationEditPolicy());
-		installEditPolicy(EditPolicyRoles.CANONICAL_ROLE, new RegionCompartmentCanonicalEditPolicy());
-		installEditPolicy(EditPolicyRoles.DRAG_DROP_ROLE, new DragDropEditPolicy());
-		installEditPolicy(EditPolicy.LAYOUT_ROLE, new XYLayoutEditPolicy());
-		// Removes the collapse expand handler
-		installEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE, new ResizableEditPolicyEx());
-		installEditPolicy(EditPolicyRoles.SNAP_FEEDBACK_ROLE, new SimpleSnapFeedbackPolicy());
-	}
-
-	@Override
-	public PreferencesHint getDiagramPreferencesHint() {
-		return DiagramActivator.DIAGRAM_PREFERENCES_HINT;
-	}
-
-	@Override
-	protected IFigure createFigure() {
-		ShapeCompartmentFigure figure = new ShapeCompartmentFigure(getCompartmentName(), getMapMode());
-		figure.getContentPane().setLayoutManager(getLayoutManager());
-		figure.getContentPane().addLayoutListener(LayoutAnimator.getDefault());
-		figure.setBorder(null);
-		figure.setFitContents(true);
-		figure.setToolTip((String) null);
-		return figure;
-	}
-
-	@Override
-	public boolean isSelectable() {
-		return false;
-	}
-
-	@Override
-	protected void refreshVisuals() {
-		super.refreshVisuals();
-		((ResizableCompartmentFigure) getFigure()).getScrollPane().setScrollBarVisibility(
-				org.eclipse.draw2d.ScrollPane.NEVER);
-	}
-}
+/**
+ * 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.IFigure;
+import org.eclipse.draw2d.LayoutAnimator;
+import org.eclipse.emf.transaction.util.TransactionUtil;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.commands.CompoundCommand;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
+import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DragDropEditPolicy;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ResizableEditPolicyEx;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.XYLayoutEditPolicy;
+import org.eclipse.gmf.runtime.diagram.ui.figures.ResizableCompartmentFigure;
+import org.eclipse.gmf.runtime.diagram.ui.figures.ShapeCompartmentFigure;
+import org.eclipse.gmf.runtime.notation.View;
+import org.yakindu.base.xtext.utils.gmf.commands.AdjustIdentityAnchorCommand;
+import org.yakindu.sct.ui.editor.DiagramActivator;
+import org.yakindu.sct.ui.editor.policies.CompartmentCreationEditPolicy;
+import org.yakindu.sct.ui.editor.policies.RegionCompartmentCanonicalEditPolicy;
+
+/**
+ * @author muelder
+ * @author muehlbrandt
+ */
+public class RegionCompartmentEditPart extends ShapeCompartmentEditPart {
+
+	public RegionCompartmentEditPart(View view) {
+		super(view);
+	}
+
+	@Override
+	protected void createDefaultEditPolicies() {
+		super.createDefaultEditPolicies();
+		installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CompartmentCreationEditPolicy());
+		installEditPolicy(EditPolicyRoles.CANONICAL_ROLE, new RegionCompartmentCanonicalEditPolicy());
+		installEditPolicy(EditPolicyRoles.DRAG_DROP_ROLE, new DragDropEditPolicy());
+		installEditPolicy(EditPolicy.LAYOUT_ROLE, new XYLayoutEditPolicy() {
+			@Override
+			protected Command getResizeChildrenCommand(ChangeBoundsRequest request) {
+				//Remove dithering connection anchors 
+				CompoundCommand result = new CompoundCommand();
+				result.add(super.getResizeChildrenCommand(request));
+				AdjustIdentityAnchorCommand command = new AdjustIdentityAnchorCommand(
+						TransactionUtil.getEditingDomain(resolveSemanticElement()), request);
+				result.add(new ICommandProxy(command));
+				return result;
+			}
+		});
+		// Removes the collapse expand handler
+		installEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE, new ResizableEditPolicyEx());
+		installEditPolicy(EditPolicyRoles.SNAP_FEEDBACK_ROLE, new SimpleSnapFeedbackPolicy());
+	}
+
+	@Override
+	public PreferencesHint getDiagramPreferencesHint() {
+		return DiagramActivator.DIAGRAM_PREFERENCES_HINT;
+	}
+
+	@Override
+	protected IFigure createFigure() {
+		ShapeCompartmentFigure figure = new ShapeCompartmentFigure(getCompartmentName(), getMapMode());
+		figure.getContentPane().setLayoutManager(getLayoutManager());
+		figure.getContentPane().addLayoutListener(LayoutAnimator.getDefault());
+		figure.setBorder(null);
+		figure.setFitContents(true);
+		figure.setToolTip((String) null);
+		return figure;
+	}
+
+	@Override
+	public boolean isSelectable() {
+		return false;
+	}
+
+	@Override
+	protected void refreshVisuals() {
+		super.refreshVisuals();
+		((ResizableCompartmentFigure) getFigure()).getScrollPane()
+				.setScrollBarVisibility(org.eclipse.draw2d.ScrollPane.NEVER);
+	}
+}

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

@@ -1,86 +1,106 @@
-/**
- * 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 (EditPolicy.CONNECTION_BENDPOINTS_ROLE.equals(key)) {
+			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());
+			}
+		} else {
+			super.installEditPolicy(key, editPolicy);
+		}
+	}
+
+	@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);
+	}
+
+}