Bug 463205 - Manhattan routing is extremely inefficient and slows down
editor response
https://bugzilla.redhat.com/show_bug.cgi?id=1181215 -  Arrows are
changed unexpectedly when Node is moved on the canvas
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/BendpointConnectionRouter.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/BendpointConnectionRouter.java
index 48633fe..9e807ed 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/BendpointConnectionRouter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/BendpointConnectionRouter.java
@@ -75,36 +75,39 @@
 	 */
 	@Override
 	protected void initialize(Connection connection) {
-		super.initialize(connection);
-		ffc = (FreeFormConnection)connection;
-
-		movedBendpoint = getMovedBendpoint(ffc);
-		if (movedBendpoint==null)
-			movedBendpoint = getAddedBendpoint(ffc);
-		removedBendpoint = getRemovedBendpoint(ffc);
-
-		findAllShapes();
-		if (movedBendpoint!=null) {
-			for (ContainerShape shape : allShapes) {
-				if (GraphicsUtil.contains(shape, movedBendpoint)) {
-					movedBendpoint = null;
-					break;
+		// check if initialization needed?
+		if (oldPoints==null) {
+			super.initialize(connection);
+			ffc = (FreeFormConnection)connection;
+	
+			movedBendpoint = getMovedBendpoint(ffc);
+			if (movedBendpoint==null)
+				movedBendpoint = getAddedBendpoint(ffc);
+			removedBendpoint = getRemovedBendpoint(ffc);
+	
+			findAllShapes();
+			if (movedBendpoint!=null) {
+				for (ContainerShape shape : allShapes) {
+					if (GraphicsUtil.contains(shape, movedBendpoint)) {
+						movedBendpoint = null;
+						break;
+					}
 				}
 			}
+	
+			/**
+			 * Save the connection's start/end anchors, and their locations as well as
+			 * the bendpoints. This is used to compare against the new ConnectionRoute
+			 */
+			oldPoints = new Point[ffc.getBendpoints().size() + 2];
+			int i = 0;
+			oldPoints[i++] = GraphicsUtil.createPoint(ffc.getStart());
+			for (Point p : ffc.getBendpoints()) {
+				oldPoints[i++] = GraphicsUtil.createPoint(p);
+			}
+			oldPoints[i++] = GraphicsUtil.createPoint(ffc.getEnd());
+			calculateAllowedAnchorSites();
 		}
-
-		/**
-		 * Save the connection's start/end anchors, and their locations as well as
-		 * the bendpoints. This is used to compare against the new ConnectionRoute
-		 */
-		oldPoints = new Point[ffc.getBendpoints().size() + 2];
-		int i = 0;
-		oldPoints[i++] = GraphicsUtil.createPoint(ffc.getStart());
-		for (Point p : ffc.getBendpoints()) {
-			oldPoints[i++] = GraphicsUtil.createPoint(p);
-		}
-		oldPoints[i++] = GraphicsUtil.createPoint(ffc.getEnd());
-		calculateAllowedAnchorSites();
 	}
 	
 	/* (non-Javadoc)
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/ConnectionRoute.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/ConnectionRoute.java
index 4e530ab..1f7cef7 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/ConnectionRoute.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/ConnectionRoute.java
@@ -454,13 +454,13 @@
 		if (i == 0) {
 			i = o1.collisions.size() - o2.collisions.size();
 			if (i == 0) {
-				i = o1.getRank() - o2.getRank();
+				i = o1.crossings.size() - o2.crossings.size();
 				if (i == 0) {
-					i = o1.crossings.size() - o2.crossings.size();
+					i = o1.getLength() - o2.getLength();
 					if (i == 0) {
 						i = o1.getPoints().size() - o2.getPoints().size();
 						if (i == 0) {
-							i = o1.getLength() - o2.getLength();
+							i = o1.getRank() - o2.getRank();
 							if (i == 0) {
 								i = o1.getPoints().size() - o2.getPoints().size();
 							}
@@ -476,14 +476,15 @@
 				// return o1.getLength() - o2.getLength();
 				// }
 			}
-		} else {
-			// pick the shorter route
-			float dl = Math.abs(o1.getLength() - o2.getLength());
-			float sl = (o1.getLength() + o2.getLength()) / 2;
-			dl = dl / sl;
-			if (dl > 0.5)
-				return o1.getLength() - o2.getLength();
 		}
+//		else if (o1.isValid() != o2.isValid()) {
+//			// pick the shorter route
+//			float dl = Math.abs(o1.getLength() - o2.getLength());
+//			float sl = (o1.getLength() + o2.getLength()) / 2;
+//			dl = dl / sl;
+//			if (dl > 0.5)
+//				return o1.getLength() - o2.getLength();
+//		}
 		return i;
 	}
 
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultConnectionRouter.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultConnectionRouter.java
index ee5b51f..90a7b1d 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultConnectionRouter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultConnectionRouter.java
@@ -18,9 +18,10 @@
 import java.util.List;
 
 import org.eclipse.bpmn2.BaseElement;
-import org.eclipse.bpmn2.FlowElementsContainer;
 import org.eclipse.bpmn2.Lane;
 import org.eclipse.bpmn2.di.BPMNShape;
+import org.eclipse.bpmn2.modeler.core.preferences.ShapeStyle;
+import org.eclipse.bpmn2.modeler.core.preferences.ShapeStyle.RoutingStyle;
 import org.eclipse.bpmn2.modeler.core.utils.AnchorType;
 import org.eclipse.bpmn2.modeler.core.utils.AnchorUtil;
 import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil;
@@ -82,6 +83,28 @@
 		super(fp);
 	}
 
+	public static IConnectionRouter getRouter(IFeatureProvider fp, Connection connection) {
+		IConnectionRouter router = null;
+		BaseElement be = BusinessObjectUtil.getFirstBaseElement(connection);
+		if (be!=null) {
+			// get the user preference of routing style for this connection
+			ShapeStyle ss = ShapeStyle.getShapeStyle(be);
+			if (ss!=null) {
+				if (ss.getRoutingStyle() == RoutingStyle.MANHATTAN)
+					router = new ManhattanConnectionRouter(fp);
+				else if (ss.getRoutingStyle() == RoutingStyle.MANUAL) {
+					router = new BendpointConnectionRouter(fp);
+				}
+				else if (ss.getRoutingStyle() == RoutingStyle.AUTOMATIC) {
+					router = new AutomaticConnectionRouter(fp);
+				}
+			}
+		}
+		if (router==null)
+			router = new BendpointConnectionRouter(fp);
+		return router;
+	}
+
 	/* (non-Javadoc)
 	 * @see org.eclipse.bpmn2.modeler.core.features.IConnectionRouter#canRoute(org.eclipse.graphiti.mm.pictograms.Connection)
 	 */
@@ -151,41 +174,88 @@
 	}
 
 	/**
-	 * Find all shapes.
+	 * Find all shapes in the diagram which can cause a collision. 
 	 *
 	 * @return the list
 	 */
 	protected List<ContainerShape> findAllShapes() {
 		if (allShapes!=null)
 			return allShapes;
+		
 		allShapes = new ArrayList<ContainerShape>();
 		Diagram diagram = fp.getDiagramTypeProvider().getDiagram();
+		
+		// first find all ancestors of source and  target, and their siblings
+		List<ContainerShape> ancestors = new ArrayList<ContainerShape>();
+		List<ContainerShape> shapes = new ArrayList<ContainerShape>();
+		
 		TreeIterator<EObject> iter = diagram.eAllContents();
 		while (iter.hasNext()) {
 			EObject o = iter.next();
-			if (o instanceof ContainerShape) {
+			if (o instanceof ContainerShape && !(o instanceof Diagram)) {
 				// this is a potential collision shape
 				ContainerShape shape = (ContainerShape)o;
 				BPMNShape bpmnShape = BusinessObjectUtil.getFirstElementOfType(shape, BPMNShape.class);
-				if (bpmnShape==null)
+				if (bpmnShape==null) {
+					// this shape does not have a visual,
+					// so no collision is possible
 					continue;
-//				if (shape==source || shape==target)
-//					continue;
-				// ignore containers (like Lane, SubProcess, etc.) if the source
-				// or target shapes are children of the container's hierarchy
-				if (shape==source.eContainer() || shape==target.eContainer())
+				}
+				if (FeatureSupport.isGroupShape(shape) || FeatureSupport.isLabelShape(shape) ) {
+					// ignore Groups and Labels
 					continue;
+				}
+
+				boolean ignore = false;
+				EObject ancestor = source.eContainer();
+				while (ancestor!=null) {
+					if (ancestor instanceof ContainerShape && shape==ancestor) {
+						ancestors.add((ContainerShape)ancestor);
+						ignore = true;
+						break;
+					}
+					ancestor = ancestor.eContainer();
+				}
 				
-				// ignore some containers altogether
-				BaseElement be = bpmnShape.getBpmnElement();
-				if (be instanceof Lane)
-					continue;
-				// TODO: other criteria here?
-	
-				allShapes.add(shape);
+				if (!ignore) {
+					ancestor = target.eContainer();
+					while (ancestor!=null) {
+						if (ancestor instanceof ContainerShape && shape==ancestor) {
+							ancestors.add((ContainerShape)ancestor);
+							ignore = true;
+							break;
+						}
+						ancestor = ancestor.eContainer();
+					}
+					
+					if (!ignore && !shapes.contains(shape)) {
+						shapes.add(shape);
+					}
+				}
 			}
 		}
-//		GraphicsUtil.dump("All Shapes", allShapes); //$NON-NLS-1$
+		
+		for (ContainerShape shape : shapes) {
+			// this is a potential collision shape
+			if (!ancestors.contains(shape)) {
+				boolean ignore = false;
+				// only Lanes can be siblings to other Lanes within a container
+				// which may be either another Lane or a Pool.
+				if (BusinessObjectUtil.containsElementOfType(shape, Lane.class)) {
+					EObject ancestor = shape.eContainer();
+					while (!(ancestor instanceof Diagram)) {
+						if (ancestors.contains(ancestor)) {
+							ignore = true;
+							break;
+						}
+						ancestor = ancestor.eContainer();
+					}
+				}
+				if (!ignore) {
+					allShapes.add(shape);
+				}
+			}
+		}
 		return allShapes;
 	}
 
@@ -233,34 +303,9 @@
 		if (allShapes==null)
 			findAllShapes();
 		for (ContainerShape shape : allShapes) {
-			if (!FeatureSupport.isGroupShape(shape) && !FeatureSupport.isLabelShape(shape) ) {
-				EObject bo = BusinessObjectUtil.getBusinessObjectForPictogramElement(shape);
-				if (bo instanceof FlowElementsContainer) {
-					// it's not a collision if the shape is a SubProcess and
-					// both source and target connection points lie inside the SubProcess
-					if (GraphicsUtil.contains(shape, p1) || GraphicsUtil.contains(shape, p2))
-						continue;
-				}
-				
-				if (GraphicsUtil.intersectsLine(shape, p1, p2))
-					collisions.add(shape);
-//				else {
-//					int min = 2;
-//					ILocation loc = this.peService.getLocationRelativeToDiagram(shape);
-//					IDimension size = GraphicsUtil.calculateSize(shape);
-//					if (GraphicsUtil.isVertical(p1, p2)) {
-//						if (Math.abs(p1.getX() - loc.getX()) < min || Math.abs(p1.getX() - (loc.getX() + size.getWidth())) < min)
-//							collisions.add(shape);
-//					}
-//					else if (GraphicsUtil.isHorizontal(p1, p2)) {
-//						if (Math.abs(p1.getY() - loc.getY()) < min || Math.abs(p1.getY() - (loc.getY() + size.getHeight())) < min)
-//							collisions.add(shape);
-//					}
-//				}
-			}
+			if (GraphicsUtil.intersectsLine(shape, p1, p2))
+				collisions.add(shape);
 		}
-//		if (collisions.size()>0)
-//			GraphicsUtil.dump("Collisions with line ["+p1.getX()+", "+p1.getY()+"]"+" ["+p2.getX()+", "+p2.getY()+"]", collisions);
 		return collisions;
 	}
 
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultDeleteBPMNShapeFeature.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultDeleteBPMNShapeFeature.java
index 1788a7e..30c359a 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultDeleteBPMNShapeFeature.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultDeleteBPMNShapeFeature.java
@@ -107,15 +107,15 @@
 
 		// If the deleted PE was a Connection, update all of the remaining
 		// Connections for the source and target shapes
-		connections.clear();
-		for (AnchorContainer shape : shapes) {
-			for (Anchor a : shape.getAnchors()) {
-				connections.addAll(a.getIncomingConnections());
-				connections.addAll(a.getOutgoingConnections());
-			}
-		}
-		for (Connection connection : connections)
-			FeatureSupport.updateConnection(getFeatureProvider(), connection);
+//		connections.clear();
+//		for (AnchorContainer shape : shapes) {
+//			for (Anchor a : shape.getAnchors()) {
+//				connections.addAll(a.getIncomingConnections());
+//				connections.addAll(a.getOutgoingConnections());
+//			}
+//		}
+//		for (Connection connection : connections)
+//			FeatureSupport.updateConnection(getFeatureProvider(), connection);
 	}
 	
 	/* (non-Javadoc)
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultLayoutBPMNConnectionFeature.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultLayoutBPMNConnectionFeature.java
index 5489a4b..bdbefd9 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultLayoutBPMNConnectionFeature.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultLayoutBPMNConnectionFeature.java
@@ -94,31 +94,20 @@
 			Connection connection = (Connection) context.getPictogramElement();
 			if (context.getProperty(GraphitiConstants.INITIAL_UPDATE) == Boolean.TRUE)
 				Graphiti.getPeService().setPropertyValue(connection, GraphitiConstants.INITIAL_UPDATE, Boolean.TRUE.toString());
+
 			diagram = getFeatureProvider().getDiagramTypeProvider().getDiagram();
-			// limit the number of iterations for recalculating other connections
-			int iterations = 0;
-			boolean repeat;
-			do {
-				repeat = false;
-				IConnectionRouter router = getRouter(connection);
-				if (router.canRoute(connection) && router.routingNeeded(connection))
-					hasDoneChanges |= router.route(connection);
-
-				UpdateContext uc = new UpdateContext(connection);
-				getFeatureProvider().updateIfPossible(uc);
-				for (Connection c : diagram.getConnections()) {
-					router = getRouter(c);
-					if (router.canRoute(c) && router.routingNeeded(c)) {
-						router.route(c);
-
-						uc = new UpdateContext(c);
-						getFeatureProvider().updateIfPossible(uc);
-
-						repeat = true;
-					}
-				}
+			IConnectionRouter router = getRouter(connection);
+			if (router.canRoute(connection) && router.routingNeeded(connection)) {
+				hasDoneChanges |= router.route(connection);
+				if (router.routingNeeded(connection))
+					AbstractConnectionRouter.addRoutingInfo(connection, "failed");
+				else
+					AbstractConnectionRouter.removeRoutingInfo(connection);
 			}
-			while (repeat && ++iterations < 3);
+
+			UpdateContext uc = new UpdateContext(connection);
+			getFeatureProvider().updateIfPossible(uc);
+
 			Graphiti.getPeService().removeProperty(connection, GraphitiConstants.INITIAL_UPDATE);
 		}
 		return hasDoneChanges;
@@ -128,25 +117,11 @@
 		if (routers.containsKey(connection))
 			return routers.get(connection);
 		
-		IConnectionRouter router = null;
 		IFeatureProvider fp = getFeatureProvider();
-		BaseElement be = BusinessObjectUtil.getFirstBaseElement(connection);
-		if (be!=null) {
-			// get the user preference of routing style for this connection
-			ShapeStyle ss = ShapeStyle.getShapeStyle(be);
-			if (ss!=null) {
-				if (ss.getRoutingStyle() == RoutingStyle.MANHATTAN)
-					router = new ManhattanConnectionRouter(fp);
-				else if (ss.getRoutingStyle() == RoutingStyle.MANUAL) {
-					router = new BendpointConnectionRouter(fp);
-				}
-				else if (ss.getRoutingStyle() == RoutingStyle.AUTOMATIC) {
-					router = new AutomaticConnectionRouter(fp);
-				}
-			}
-		}
+		IConnectionRouter router = DefaultConnectionRouter.getRouter(fp, connection);
 		if (router==null)
 			router = new BendpointConnectionRouter(fp);
+		
 		routers.put(connection, router);
 		return router;
 	}
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultResizeBPMNShapeFeature.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultResizeBPMNShapeFeature.java
index 7611e4d..05b8fd0 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultResizeBPMNShapeFeature.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultResizeBPMNShapeFeature.java
@@ -91,11 +91,11 @@
 
 		FeatureSupport.updateConnections(getFeatureProvider(), shape);
 		
-		for (Connection connection : getDiagram().getConnections()) {
-			if (GraphicsUtil.intersects(shape, connection)) {
-				FeatureSupport.updateConnection(getFeatureProvider(), connection);
-			}
-		}
+//		for (Connection connection : getDiagram().getConnections()) {
+//			if (GraphicsUtil.intersects(shape, connection)) {
+//				FeatureSupport.updateConnection(getFeatureProvider(), connection);
+//			}
+//		}
 
 		FeatureSupport.updateCategoryValues(getFeatureProvider(), shape);
 		
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/ManhattanConnectionRouter.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/ManhattanConnectionRouter.java
index 1c23813..0b96205 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/ManhattanConnectionRouter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/ManhattanConnectionRouter.java
@@ -14,6 +14,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Hashtable;
 import java.util.List;
 
 import org.eclipse.bpmn2.modeler.core.utils.AnchorSite;
@@ -25,8 +26,10 @@
 import org.eclipse.graphiti.features.IFeatureProvider;
 import org.eclipse.graphiti.mm.algorithms.styles.Point;
 import org.eclipse.graphiti.mm.pictograms.Anchor;
+import org.eclipse.graphiti.mm.pictograms.AnchorContainer;
 import org.eclipse.graphiti.mm.pictograms.Connection;
 import org.eclipse.graphiti.mm.pictograms.ContainerShape;
+import org.eclipse.graphiti.mm.pictograms.FixPointAnchor;
 import org.eclipse.graphiti.mm.pictograms.FreeFormConnection;
 
 /**
@@ -238,6 +241,72 @@
 		return false;
 	}
 	
+	@Override
+	public boolean route(Connection connection) {
+		
+		initialize(connection);
+
+		// if a connection was moved to or from an edge and it changed the number of connections
+		// on an edge, force a re-routing of all the connection on that edge.
+		Hashtable<AnchorSite, List<FixPointAnchor>> sourceAnchorsBefore = AnchorUtil.countAnchors(source); 
+		Hashtable<AnchorSite, List<FixPointAnchor>> targetAnchorsBefore = AnchorUtil.countAnchors(target); 
+
+		boolean changed = false;
+		if (connection instanceof FreeFormConnection) {
+			ConnectionRoute route = calculateRoute();
+			if (route!=null) {
+				changed = isRouteChanged(route);
+				applyRoute(route);
+			}
+			dispose();
+		}
+
+		Hashtable<AnchorSite, List<FixPointAnchor>> sourceAnchorsAfter = AnchorUtil.countAnchors(source); 
+		Hashtable<AnchorSite, List<FixPointAnchor>> targetAnchorsAfter = AnchorUtil.countAnchors(target);
+		
+		boolean repeat = false;
+		int iterations=0;
+		do {
+			repeat = false;
+			for (AnchorSite site : AnchorSite.values()) {
+				List<FixPointAnchor> sb = sourceAnchorsBefore.get(site);
+				List<FixPointAnchor> sa = sourceAnchorsAfter.get(site);
+				if (sa!=null && sb!=null) {
+					if (sa.size()!=sb.size()) {
+						// the number of anchors on this edge of the source shape
+						// has changed: we may need to re-route all of these connections
+						for (Connection c : AnchorUtil.getConnections(source, site)) {
+							IConnectionRouter router = getRouter(fp, c);
+							if (router.canRoute(c) && router.routingNeeded(c)) {
+								router.route(c);
+								repeat = true;
+							}
+						}
+					}
+				}
+	
+				List<FixPointAnchor> tb = targetAnchorsBefore.get(site);
+				List<FixPointAnchor> ta = targetAnchorsAfter.get(site);
+				if (ta!=null && tb!=null) {
+					if (ta.size()!=tb.size()) {
+						// the number of anchors on this edge of the target shape
+						// has changed: we may need to re-route all of these connections
+						for (Connection c : AnchorUtil.getConnections(target, site)) {
+							IConnectionRouter router = getRouter(fp, c);
+							if (router.canRoute(c) && router.routingNeeded(c)) {
+								router.route(c);
+								repeat = true;
+							}
+						}
+					}
+				}
+			}
+		}
+		while (repeat && ++iterations<3);
+		
+		return changed;
+	}
+
 	/* (non-Javadoc)
 	 * @see org.eclipse.bpmn2.modeler.core.features.BendpointConnectionRouter#calculateRoute()
 	 */
@@ -538,7 +607,7 @@
 
 			route = allRoutes.get(0);
 		}
-		
+
 		return route;
 	}
 	
@@ -1006,6 +1075,8 @@
 					route.setRank(4);
 			}
 			if (size>2) {
+				// TODO: instead of ranking these poorly,
+				// move the bendpoints instead if possible.
 				if (GraphicsUtil.getLength(p1, p2) < margin) {
 					p1 = route.get(1);
 					p2 = route.get(2);
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/containers/AbstractResizeContainerFeature.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/containers/AbstractResizeContainerFeature.java
index 1332701..7783542 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/containers/AbstractResizeContainerFeature.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/containers/AbstractResizeContainerFeature.java
@@ -24,6 +24,7 @@
 import org.eclipse.graphiti.features.context.IResizeShapeContext;
 import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
 import org.eclipse.graphiti.mm.algorithms.styles.Point;
+import org.eclipse.graphiti.mm.pictograms.AnchorContainer;
 import org.eclipse.graphiti.mm.pictograms.ContainerShape;
 import org.eclipse.graphiti.mm.pictograms.FreeFormConnection;
 import org.eclipse.graphiti.mm.pictograms.PictogramElement;
@@ -81,7 +82,6 @@
 		// leaves them in the same location relative to the diagram.
 		// This allows the user to create (or remove) space between
 		// the Lane's edge and the contained activities.
-		Point offset = null;
 		Point pos = containerPos.pop();
 		if (context.getDirection()==IResizeShapeContext.DIRECTION_NORTH ||
 				context.getDirection()==IResizeShapeContext.DIRECTION_WEST ||
@@ -91,7 +91,7 @@
 			int deltaX = pos.getX() - context.getX();
 			int deltaY = pos.getY() - context.getY();
 			// we'll need to use this as the offset for MOVABLE Labels
-			offset = Graphiti.getCreateService().createPoint(deltaX, deltaY);
+			Point offset = Graphiti.getCreateService().createPoint(deltaX, deltaY);
 			
 			for (PictogramElement pe : descendants) {
 				if (containerShape.getChildren().contains(pe)) {
@@ -102,13 +102,6 @@
 			}
 		}
 		
-		for (PictogramElement pe : descendants) {
-			if (pe instanceof FreeFormConnection) {
-				FreeFormConnection c = (FreeFormConnection) pe;
-				FeatureSupport.updateConnection(getFeatureProvider(), c, true);
-			}
-		}
-		
 		DIUtils.updateDIShape(containerShape);
 		if (rootContainer!=containerShape) {
 			DIUtils.updateDIShape(rootContainer);
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/containers/LayoutContainerFeature.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/containers/LayoutContainerFeature.java
index 6977fff..388bb97 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/containers/LayoutContainerFeature.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/containers/LayoutContainerFeature.java
@@ -31,8 +31,10 @@
 import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
 import org.eclipse.graphiti.mm.algorithms.Polyline;
 import org.eclipse.graphiti.mm.algorithms.styles.Point;
+import org.eclipse.graphiti.mm.pictograms.AnchorContainer;
 import org.eclipse.graphiti.mm.pictograms.Connection;
 import org.eclipse.graphiti.mm.pictograms.ContainerShape;
+import org.eclipse.graphiti.mm.pictograms.FreeFormConnection;
 import org.eclipse.graphiti.mm.pictograms.PictogramElement;
 import org.eclipse.graphiti.mm.pictograms.Shape;
 import org.eclipse.graphiti.services.Graphiti;
@@ -85,8 +87,13 @@
 		DIUtils.updateDIShape(rootContainer);
 		
 		for (PictogramElement pe : FeatureSupport.getPoolAndLaneDescendants(rootContainer)) {
-			if (pe instanceof Connection) {
-				FeatureSupport.updateConnection(getFeatureProvider(), (Connection)pe, true);
+			if (pe instanceof FreeFormConnection) {
+				FreeFormConnection c = (FreeFormConnection) pe;
+				// only reroute connections between shapes in different containers
+				AnchorContainer start = c.getStart().getParent();
+				AnchorContainer end = c.getEnd().getParent();
+				if (start.eContainer()!=end.eContainer())
+					FeatureSupport.updateConnection(getFeatureProvider(), (Connection)pe, true);
 			}
 		}
 
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/AnchorUtil.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/AnchorUtil.java
index b3f8f3b..f7eadc2 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/AnchorUtil.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/AnchorUtil.java
@@ -13,12 +13,12 @@
 package org.eclipse.bpmn2.modeler.core.utils;
 
 import java.util.ArrayList;
+import java.util.Hashtable;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.TreeMap;
 
 import org.eclipse.bpmn2.BaseElement;
-import org.eclipse.bpmn2.Participant;
 import org.eclipse.bpmn2.modeler.core.features.GraphitiConstants;
 import org.eclipse.bpmn2.modeler.core.utils.GraphicsUtil.LineSegment;
 import org.eclipse.emf.common.notify.Notification;
@@ -341,6 +341,58 @@
 		AnchorContainer ac = anchor.getParent();
 		return ac;
 	}
+	
+	public static Hashtable<AnchorSite, List<FixPointAnchor>> countAnchors(AnchorContainer ac) {
+		Hashtable<AnchorSite, List<FixPointAnchor>> result = new Hashtable<AnchorSite, List<FixPointAnchor>>(); 
+		List<FixPointAnchor> topAnchors = null;
+		List<FixPointAnchor> bottomAnchors = null;
+		List<FixPointAnchor> leftAnchors = null;
+		List<FixPointAnchor> rightAnchors = null;
+		for (Anchor a : ac.getAnchors()) {
+			AnchorType at = AnchorType.getType(a);
+			if (at == AnchorType.ACTIVITY || at == AnchorType.MESSAGELINK) {
+				// Count all of the Activity Anchors 
+				FixPointAnchor anchor = (FixPointAnchor) a;
+				AnchorSite site = AnchorSite.getSite(anchor);
+				switch (site) {
+				case BOTTOM:
+					if (bottomAnchors==null) {
+						bottomAnchors = new ArrayList<FixPointAnchor>();
+						result.put(site, bottomAnchors);
+					}
+					bottomAnchors.add(anchor);
+					break;
+				case CENTER:
+					break;
+				case LEFT:
+					if (leftAnchors==null) {
+						leftAnchors = new ArrayList<FixPointAnchor>();
+						result.put(site, leftAnchors);
+					}
+					leftAnchors.add(anchor);
+					break;
+				case RIGHT:
+					if (rightAnchors==null) {
+						rightAnchors = new ArrayList<FixPointAnchor>();
+						result.put(site, rightAnchors);
+					}
+					rightAnchors.add(anchor);
+					break;
+				case TOP:
+					if (topAnchors==null) {
+						topAnchors = new ArrayList<FixPointAnchor>();
+						result.put(site, topAnchors);
+					}
+					topAnchors.add(anchor);
+					break;
+				default:
+					break;
+				
+				}
+			}
+		}
+		return result;
+	}
 
 	/////////////////////////////////////////////////////////////////////
 	// Private API
@@ -426,64 +478,25 @@
 		if (ac==null || isConnectionAnchorContainer(ac))
 			return;
 
-		// These are the number of Activity Anchors along each
-		// edge of the Activity. These anchors are distributed
-		// evenly along an edge of the shape
-		int topCount = 0;
-		int bottomCount = 0;
-		int leftCount = 0;
-		int rightCount = 0;
 		// Calculated offsets for each Activity Anchor
 		int topOffset = 0;
 		int bottomOffset = 0;
 		int leftOffset = 0;
 		int rightOffset = 0;
 		// Connections attached to each anchor
-		List<FixPointAnchor> topAnchors = null;
-		List<FixPointAnchor> bottomAnchors = null;
-		List<FixPointAnchor> leftAnchors = null;
-		List<FixPointAnchor> rightAnchors = null;
-		
-		for (Anchor a : ac.getAnchors()) {
-			AnchorType at = AnchorType.getType(a);
-			if (at == AnchorType.ACTIVITY || at == AnchorType.MESSAGELINK) {
-				// Count all of the Activity Anchors 
-				FixPointAnchor anchor = (FixPointAnchor) a;
-				AnchorSite site = AnchorSite.getSite(anchor);
-				switch (site) {
-				case BOTTOM:
-					++bottomCount;
-					if (bottomAnchors==null)
-						bottomAnchors = new ArrayList<FixPointAnchor>();
-					bottomAnchors.add(anchor);
-					break;
-				case CENTER:
-					break;
-				case LEFT:
-					++leftCount;
-					if (leftAnchors==null)
-						leftAnchors = new ArrayList<FixPointAnchor>();
-					leftAnchors.add(anchor);
-					break;
-				case RIGHT:
-					++rightCount;
-					if (rightAnchors==null)
-						rightAnchors = new ArrayList<FixPointAnchor>();
-					rightAnchors.add(anchor);
-					break;
-				case TOP:
-					++topCount;
-					if (topAnchors==null)
-						topAnchors = new ArrayList<FixPointAnchor>();
-					topAnchors.add(anchor);
-					break;
-				default:
-					break;
-				
-				}
-			}
-		}
-		
+		Hashtable<AnchorSite, List<FixPointAnchor>> anchors = countAnchors(ac);
+		List<FixPointAnchor> topAnchors = anchors.get(AnchorSite.TOP);
+		List<FixPointAnchor> bottomAnchors = anchors.get(AnchorSite.BOTTOM);
+		List<FixPointAnchor> leftAnchors = anchors.get(AnchorSite.LEFT);
+		List<FixPointAnchor> rightAnchors = anchors.get(AnchorSite.RIGHT);
+		// These are the number of Activity Anchors along each
+		// edge of the Activity. These anchors are distributed
+		// evenly along an edge of the shape
+		int topCount = topAnchors==null ? 0 : topAnchors.size();
+		int bottomCount = bottomAnchors==null ? 0 : bottomAnchors.size();
+		int leftCount = leftAnchors==null ? 0 : leftAnchors.size();
+		int rightCount = rightAnchors==null ? 0 : rightAnchors.size();
+
 		for (Anchor a : ac.getAnchors()) {
 			AnchorType at = AnchorType.getType(a);
 			if (at == AnchorType.ACTIVITY) {
@@ -505,7 +518,7 @@
 				case LEFT:
 					index = calculateIndex(anchor, leftAnchors);
 					if (index>=0)
-						leftOffset = (index+1) * w/(leftCount+1);
+						leftOffset = (index+1) * h/(leftCount+1);
 					else
 						leftOffset += h/(leftCount+1);
 					anchor.setLocation(gaService.createPoint(0, leftOffset));
@@ -513,7 +526,7 @@
 				case RIGHT:
 					index = calculateIndex(anchor, rightAnchors);
 					if (index>=0)
-						rightOffset = (index+1) * w/(rightCount+1);
+						rightOffset = (index+1) * h/(rightCount+1);
 					else
 						rightOffset += h/(rightCount+1);
 					anchor.setLocation(gaService.createPoint(w, rightOffset));
@@ -604,10 +617,9 @@
 	private static int calculateIndex(FixPointAnchor anchor, List<FixPointAnchor> all) {
 		// TODO: fix this: should probably look at the location of the closest bendboint,
 		// not the opposite anchor.
-		if (true) return -1;
+//		if (true) return -1;
 		TreeMap<Integer, FixPointAnchor> offsets = new TreeMap<Integer, FixPointAnchor>();
 		AnchorSite site = AnchorSite.getSite(anchor);
-		Connection c;
 		for (FixPointAnchor a : all) {
 			FixPointAnchor a2 = getOpposite(a);
 			if (a2!=null) {
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FeatureSupport.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FeatureSupport.java
index 92f000a..46088fd 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FeatureSupport.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FeatureSupport.java
@@ -810,12 +810,12 @@
 
 	public static void updateConnections(IFeatureProvider fp, AnchorContainer ac) {
 		List<Connection> alreadyUpdated = new ArrayList<Connection>();
-		if (ac instanceof ContainerShape) {
-			for (Shape child : ((ContainerShape)ac).getChildren()) {
-				if (child instanceof ContainerShape)
-					updateConnections(fp, child, alreadyUpdated);
-			}
-		}
+//		if (ac instanceof ContainerShape) {
+//			for (Shape child : ((ContainerShape)ac).getChildren()) {
+//				if (child instanceof ContainerShape)
+//					updateConnections(fp, child, alreadyUpdated);
+//			}
+//		}
 		updateConnections(fp, ac, alreadyUpdated);
 //		AnchorUtil.relocateAnchors((Shape)ac);
 	}