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