Fix for JBPM-3095 - added expand/collapse for subprocesses
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIImport.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIImport.java
index e0fa2aa..8c5f9b7 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIImport.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIImport.java
@@ -47,15 +47,16 @@
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.common.util.TreeIterator;
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.emf.transaction.RecordingCommand;
 import org.eclipse.emf.transaction.TransactionalEditingDomain;
 import org.eclipse.graphiti.datatypes.ILocation;
 import org.eclipse.graphiti.features.IAddFeature;
 import org.eclipse.graphiti.features.IFeatureProvider;
+import org.eclipse.graphiti.features.ILayoutFeature;
 import org.eclipse.graphiti.features.context.impl.AddConnectionContext;
 import org.eclipse.graphiti.features.context.impl.AddContext;
 import org.eclipse.graphiti.features.context.impl.AreaContext;
+import org.eclipse.graphiti.features.context.impl.LayoutContext;
 import org.eclipse.graphiti.mm.algorithms.Rectangle;
 import org.eclipse.graphiti.mm.pictograms.AnchorContainer;
 import org.eclipse.graphiti.mm.pictograms.Connection;
@@ -129,12 +130,26 @@
 
 					relayoutLanes(ownedElement);
 					// FIXME: we don't really want to leave, but we also don't want all diagrams mixed together
-					return;
+					break;
 				}
+				
+				layoutAll();
 			}
 
 		});
 	}
+	
+	private void layoutAll() {
+		for (BaseElement be : elements.keySet()) {
+//			if (be instanceof SubProcess) {
+				PictogramElement pe = elements.get(be);
+				LayoutContext context = new LayoutContext(pe);
+				ILayoutFeature feature = featureProvider.getLayoutFeature(context);
+				if (feature.canLayout(context))
+					feature.layout(context);
+//			}
+		}
+	}
 
 	public void setDiagram(Diagram diagram) {
 		this.diagram = diagram;
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIUtils.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIUtils.java
index bf6b2d8..8f360b8 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIUtils.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIUtils.java
@@ -1,166 +1,165 @@
-/******************************************************************************* 
- * Copyright (c) 2011 Red Hat, Inc. 
- *  All rights reserved. 
- * This program is 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: 
- * Red Hat, Inc. - initial API and implementation 
- *
- * @author Ivar Meikas
- ******************************************************************************/
-package org.eclipse.bpmn2.modeler.core.di;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.eclipse.bpmn2.BaseElement;
-import org.eclipse.bpmn2.di.BPMNDiagram;
-import org.eclipse.bpmn2.di.BPMNEdge;
-import org.eclipse.bpmn2.di.BPMNShape;
-import org.eclipse.bpmn2.di.BpmnDiFactory;
-import org.eclipse.bpmn2.modeler.core.Activator;
-import org.eclipse.bpmn2.modeler.core.ModelHandler;
-import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;
-import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;
-import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
-import org.eclipse.dd.dc.Bounds;
-import org.eclipse.dd.dc.DcFactory;
-import org.eclipse.dd.dc.Point;
-import org.eclipse.dd.di.DiagramElement;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.util.EcoreUtil;
-import org.eclipse.graphiti.datatypes.IDimension;
-import org.eclipse.graphiti.datatypes.ILocation;
-import org.eclipse.graphiti.features.IFeatureProvider;
-import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
-import org.eclipse.graphiti.mm.pictograms.Connection;
-import org.eclipse.graphiti.mm.pictograms.ContainerShape;
-import org.eclipse.graphiti.mm.pictograms.Diagram;
-import org.eclipse.graphiti.mm.pictograms.PictogramElement;
-import org.eclipse.graphiti.mm.pictograms.PictogramLink;
-import org.eclipse.graphiti.mm.pictograms.Shape;
-import org.eclipse.graphiti.mm.pictograms.impl.FreeFormConnectionImpl;
-import org.eclipse.graphiti.services.Graphiti;
-
-public class DIUtils {
-
-	public static void updateDIShape(PictogramElement element) {
-
-		PictogramLink link = element.getLink();
-		if (link == null) {
-			return;
-		}
-
-		BPMNShape bpmnShape = BusinessObjectUtil.getFirstElementOfType(element, BPMNShape.class);
-		if (bpmnShape == null) {
-			return;
-		}
-
-		ILocation loc = Graphiti.getLayoutService().getLocationRelativeToDiagram((Shape) element);
-		Bounds bounds = bpmnShape.getBounds();
-
-		bounds.setX(loc.getX());
-		bounds.setY(loc.getY());
-
-		GraphicsAlgorithm graphicsAlgorithm = element.getGraphicsAlgorithm();
-		IDimension size = Graphiti.getGaService().calculateSize(graphicsAlgorithm);
-		bounds.setHeight(size.getHeight());
-		bounds.setWidth(size.getWidth());
-
-		if (element instanceof ContainerShape) {
-			EList<Shape> children = ((ContainerShape) element).getChildren();
-			for (Shape shape : children) {
-				if (shape instanceof ContainerShape) {
-					updateDIShape(shape);
-				}
-			}
-		}
-	}
-
-	public static void updateDIEdge(Diagram diagram, Connection connection, Class clazz) {
-		try {
-			ModelHandler modelHandler = ModelHandlerLocator.getModelHandler(connection.getLink().getBusinessObjects()
-					.get(0).eResource());
-
-			EObject be = BusinessObjectUtil.getFirstElementOfType(connection, clazz);
-			BPMNEdge edge = (BPMNEdge) modelHandler.findDIElement(diagram, (BaseElement) be);
-			Point point = DcFactory.eINSTANCE.createPoint();
-
-			List<Point> waypoint = edge.getWaypoint();
-			waypoint.clear();
-
-			GraphicsAlgorithm graphicsAlgorithm = connection.getStart().getGraphicsAlgorithm();
-			// FIXME connections must create anchors!!!
-			if (graphicsAlgorithm != null) {
-				point.setX(graphicsAlgorithm.getX());
-				point.setY(graphicsAlgorithm.getY());
-			} else {
-				point.setX(connection.getStart().getParent().getGraphicsAlgorithm().getX());
-				point.setY(connection.getStart().getParent().getGraphicsAlgorithm().getY());
-			}
-			waypoint.add(point);
-
-			if (connection instanceof FreeFormConnectionImpl) {
-				FreeFormConnectionImpl freeForm = (FreeFormConnectionImpl) connection;
-				EList<org.eclipse.graphiti.mm.algorithms.styles.Point> bendpoints = freeForm.getBendpoints();
-				for (org.eclipse.graphiti.mm.algorithms.styles.Point bp : bendpoints) {
-					addBendPoint(freeForm, point);
-				}
-			}
-
-			point = DcFactory.eINSTANCE.createPoint();
-			graphicsAlgorithm = connection.getEnd().getGraphicsAlgorithm();
-			if (graphicsAlgorithm != null) {
-				point.setX(graphicsAlgorithm.getX());
-				point.setY(graphicsAlgorithm.getY());
-			} else {
-				point.setX(connection.getEnd().getParent().getGraphicsAlgorithm().getX());
-				point.setY(connection.getEnd().getParent().getGraphicsAlgorithm().getY());
-			}
-			waypoint.add(point);
-
-		} catch (IOException e) {
-			Activator.logError(e);
-		}
-	}
-
-	static void addBendPoint(FreeFormConnectionImpl freeForm, Point point) {
-		freeForm.getBendpoints().add(Graphiti.getGaService().createPoint((int) point.getX(), (int) point.getY()));
-	}
-
-	public static BPMNShape createDIShape(Shape shape, BaseElement elem, int x, int y, int w, int h,
-			IFeatureProvider fp, Diagram diagram) {
-
-		EList<EObject> businessObjects = Graphiti.getLinkService().getLinkForPictogramElement(diagram)
-				.getBusinessObjects();
-		BPMNShape bpmnShape = null;
-
-		for (EObject eObject : businessObjects) {
-			if (eObject instanceof BPMNDiagram) {
-				BPMNDiagram bpmnDiagram = (BPMNDiagram) eObject;
-
-				bpmnShape = BpmnDiFactory.eINSTANCE.createBPMNShape();
-//				bpmnShape.setId(EcoreUtil.generateUUID());
-				bpmnShape.setBpmnElement(elem);
-				Bounds bounds = DcFactory.eINSTANCE.createBounds();
-				bounds.setX(x);
-				bounds.setY(y);
-				bounds.setWidth(w);
-				bounds.setHeight(h);
-				bpmnShape.setBounds(bounds);
-
-				List<DiagramElement> elements = bpmnDiagram.getPlane().getPlaneElement();
-				elements.add(bpmnShape);
-				ModelUtil.setID(shape);
-
-				fp.link(shape, new Object[] { elem, bpmnShape });
-				break;
-			}
-		}
-
-		return bpmnShape;
-	}
-}
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Ivar Meikas

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.core.di;

+

+import java.io.IOException;

+import java.util.List;

+

+import org.eclipse.bpmn2.BaseElement;

+import org.eclipse.bpmn2.di.BPMNDiagram;

+import org.eclipse.bpmn2.di.BPMNEdge;

+import org.eclipse.bpmn2.di.BPMNShape;

+import org.eclipse.bpmn2.di.BpmnDiFactory;

+import org.eclipse.bpmn2.modeler.core.Activator;

+import org.eclipse.bpmn2.modeler.core.ModelHandler;

+import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;

+import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;

+import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;

+import org.eclipse.dd.dc.Bounds;

+import org.eclipse.dd.dc.DcFactory;

+import org.eclipse.dd.dc.Point;

+import org.eclipse.dd.di.DiagramElement;

+import org.eclipse.emf.common.util.EList;

+import org.eclipse.emf.ecore.EObject;

+import org.eclipse.graphiti.datatypes.IDimension;

+import org.eclipse.graphiti.datatypes.ILocation;

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.pictograms.Connection;

+import org.eclipse.graphiti.mm.pictograms.ContainerShape;

+import org.eclipse.graphiti.mm.pictograms.Diagram;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+import org.eclipse.graphiti.mm.pictograms.PictogramLink;

+import org.eclipse.graphiti.mm.pictograms.Shape;

+import org.eclipse.graphiti.mm.pictograms.impl.FreeFormConnectionImpl;

+import org.eclipse.graphiti.services.Graphiti;

+

+public class DIUtils {

+

+	public static void updateDIShape(PictogramElement element) {

+

+		PictogramLink link = element.getLink();

+		if (link == null) {

+			return;

+		}

+

+		BPMNShape bpmnShape = BusinessObjectUtil.getFirstElementOfType(element, BPMNShape.class);

+		if (bpmnShape == null) {

+			return;

+		}

+

+		ILocation loc = Graphiti.getLayoutService().getLocationRelativeToDiagram((Shape) element);

+		Bounds bounds = bpmnShape.getBounds();

+

+		bounds.setX(loc.getX());

+		bounds.setY(loc.getY());

+

+		GraphicsAlgorithm graphicsAlgorithm = element.getGraphicsAlgorithm();

+		IDimension size = Graphiti.getGaService().calculateSize(graphicsAlgorithm);

+		bounds.setHeight(size.getHeight());

+		bounds.setWidth(size.getWidth());

+

+		if (element instanceof ContainerShape) {

+			EList<Shape> children = ((ContainerShape) element).getChildren();

+			for (Shape shape : children) {

+				if (shape instanceof ContainerShape) {

+					updateDIShape(shape);

+				}

+			}

+		}

+	}

+

+	public static void updateDIEdge(Diagram diagram, Connection connection, Class clazz) {

+		try {

+			ModelHandler modelHandler = ModelHandlerLocator.getModelHandler(connection.getLink().getBusinessObjects()

+					.get(0).eResource());

+

+			EObject be = BusinessObjectUtil.getFirstElementOfType(connection, clazz);

+			BPMNEdge edge = (BPMNEdge) modelHandler.findDIElement(diagram, (BaseElement) be);

+			Point point = DcFactory.eINSTANCE.createPoint();

+

+			List<Point> waypoint = edge.getWaypoint();

+			waypoint.clear();

+

+			GraphicsAlgorithm graphicsAlgorithm = connection.getStart().getGraphicsAlgorithm();

+			// FIXME connections must create anchors!!!

+			if (graphicsAlgorithm != null) {

+				point.setX(graphicsAlgorithm.getX());

+				point.setY(graphicsAlgorithm.getY());

+			} else {

+				point.setX(connection.getStart().getParent().getGraphicsAlgorithm().getX());

+				point.setY(connection.getStart().getParent().getGraphicsAlgorithm().getY());

+			}

+			waypoint.add(point);

+

+			if (connection instanceof FreeFormConnectionImpl) {

+				FreeFormConnectionImpl freeForm = (FreeFormConnectionImpl) connection;

+				EList<org.eclipse.graphiti.mm.algorithms.styles.Point> bendpoints = freeForm.getBendpoints();

+				for (org.eclipse.graphiti.mm.algorithms.styles.Point bp : bendpoints) {

+					addBendPoint(freeForm, point);

+				}

+			}

+

+			point = DcFactory.eINSTANCE.createPoint();

+			graphicsAlgorithm = connection.getEnd().getGraphicsAlgorithm();

+			if (graphicsAlgorithm != null) {

+				point.setX(graphicsAlgorithm.getX());

+				point.setY(graphicsAlgorithm.getY());

+			} else {

+				point.setX(connection.getEnd().getParent().getGraphicsAlgorithm().getX());

+				point.setY(connection.getEnd().getParent().getGraphicsAlgorithm().getY());

+			}

+			waypoint.add(point);

+

+		} catch (IOException e) {

+			Activator.logError(e);

+		}

+	}

+

+	static void addBendPoint(FreeFormConnectionImpl freeForm, Point point) {

+		freeForm.getBendpoints().add(Graphiti.getGaService().createPoint((int) point.getX(), (int) point.getY()));

+	}

+

+	public static BPMNShape createDIShape(Shape shape, BaseElement elem, int x, int y, int w, int h,

+			IFeatureProvider fp, Diagram diagram) {

+

+		EList<EObject> businessObjects = Graphiti.getLinkService().getLinkForPictogramElement(diagram)

+				.getBusinessObjects();

+		BPMNShape bpmnShape = null;

+

+		for (EObject eObject : businessObjects) {

+			if (eObject instanceof BPMNDiagram) {

+				BPMNDiagram bpmnDiagram = (BPMNDiagram) eObject;

+

+				bpmnShape = BpmnDiFactory.eINSTANCE.createBPMNShape();

+//				bpmnShape.setId(EcoreUtil.generateUUID());

+				bpmnShape.setBpmnElement(elem);

+				Bounds bounds = DcFactory.eINSTANCE.createBounds();

+				bounds.setX(x);

+				bounds.setY(y);

+				bounds.setWidth(w);

+				bounds.setHeight(h);

+				bpmnShape.setBounds(bounds);

+

+				List<DiagramElement> elements = bpmnDiagram.getPlane().getPlaneElement();

+				elements.add(bpmnShape);

+				ModelUtil.setID(shape);

+

+				fp.link(shape, new Object[] { elem, bpmnShape });

+				break;

+			}

+		}

+

+		return bpmnShape;

+	}

+}

diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/AbstractBpmnAddFeature.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/AbstractBpmnAddFeature.java
index dcb894f..531f686 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/AbstractBpmnAddFeature.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/AbstractBpmnAddFeature.java
@@ -1,158 +1,157 @@
-/******************************************************************************* 
- * Copyright (c) 2011 Red Hat, Inc. 
- *  All rights reserved. 
- * This program is 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: 
- * Red Hat, Inc. - initial API and implementation 
- *
- * @author Ivar Meikas
- ******************************************************************************/
-package org.eclipse.bpmn2.modeler.core.features;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.eclipse.bpmn2.Activity;
-import org.eclipse.bpmn2.Association;
-import org.eclipse.bpmn2.BaseElement;
-import org.eclipse.bpmn2.MessageFlow;
-import org.eclipse.bpmn2.SequenceFlow;
-import org.eclipse.bpmn2.di.BPMNDiagram;
-import org.eclipse.bpmn2.di.BPMNEdge;
-import org.eclipse.bpmn2.di.BPMNShape;
-import org.eclipse.bpmn2.di.BpmnDiFactory;
-import org.eclipse.bpmn2.modeler.core.Activator;
-import org.eclipse.bpmn2.modeler.core.ModelHandler;
-import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;
-import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
-import org.eclipse.dd.dc.Bounds;
-import org.eclipse.dd.dc.DcFactory;
-import org.eclipse.dd.dc.Point;
-import org.eclipse.dd.di.DiagramElement;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.util.EcoreUtil;
-import org.eclipse.graphiti.datatypes.ILocation;
-import org.eclipse.graphiti.features.IFeatureProvider;
-import org.eclipse.graphiti.features.impl.AbstractAddShapeFeature;
-import org.eclipse.graphiti.mm.pictograms.Connection;
-import org.eclipse.graphiti.mm.pictograms.Shape;
-import org.eclipse.graphiti.services.Graphiti;
-
-public abstract class AbstractBpmnAddFeature extends AbstractAddShapeFeature {
-
-	public AbstractBpmnAddFeature(IFeatureProvider fp) {
-		super(fp);
-	}
-
-	protected void createDIShape(Shape gShape, BaseElement elem) {
-		try {
-			BPMNShape shape = (BPMNShape) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(
-					getDiagram(), elem);
-			createDIShape(gShape, elem, shape);
-		} catch (IOException e) {
-			Activator.logError(e);
-		}
-	}
-
-	protected void createDIShape(Shape gShape, BaseElement elem, BPMNShape shape) {
-		ILocation loc = Graphiti.getLayoutService().getLocationRelativeToDiagram(gShape);
-		if (shape == null) {
-			EList<EObject> businessObjects = Graphiti.getLinkService().getLinkForPictogramElement(getDiagram())
-					.getBusinessObjects();
-			for (EObject eObject : businessObjects) {
-				if (eObject instanceof BPMNDiagram) {
-					BPMNDiagram bpmnDiagram = (BPMNDiagram) eObject;
-
-					shape = BpmnDiFactory.eINSTANCE.createBPMNShape();
-//					shape.setId(EcoreUtil.generateUUID());
-					shape.setBpmnElement(elem);
-					Bounds bounds = DcFactory.eINSTANCE.createBounds();
-					if (elem instanceof Activity) {
-						bounds.setHeight(gShape.getGraphicsAlgorithm().getHeight());
-					} else {
-						bounds.setHeight(gShape.getGraphicsAlgorithm().getHeight());
-					}
-					bounds.setWidth(gShape.getGraphicsAlgorithm().getWidth());
-					bounds.setX(loc.getX());
-					bounds.setY(loc.getY());
-					shape.setBounds(bounds);
-
-					addShape(shape, bpmnDiagram);
-					ModelUtil.setID(shape);
-				}
-			}
-		}
-		link(gShape, new Object[] { elem, shape });
-	}
-
-	private void addShape(DiagramElement elem, BPMNDiagram bpmnDiagram) {
-		List<DiagramElement> elements = bpmnDiagram.getPlane().getPlaneElement();
-		elements.add(elem);
-	}
-
-	protected void createDIEdge(Connection connection, BaseElement conElement) {
-		try {
-			BPMNEdge edge = (BPMNEdge) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(
-					getDiagram(), conElement);
-			createDIEdge(connection, conElement, edge);
-		} catch (IOException e) {
-			Activator.logError(e);
-		}
-
-	}
-
-	protected void createDIEdge(Connection connection, BaseElement conElement, BPMNEdge edge) throws IOException {
-		ModelHandler modelHandler = ModelHandlerLocator.getModelHandler(getDiagram().eResource());
-		if (edge == null) {
-			EList<EObject> businessObjects = Graphiti.getLinkService().getLinkForPictogramElement(getDiagram())
-					.getBusinessObjects();
-			for (EObject eObject : businessObjects) {
-				if (eObject instanceof BPMNDiagram) {
-					BPMNDiagram bpmnDiagram = (BPMNDiagram) eObject;
-
-					edge = BpmnDiFactory.eINSTANCE.createBPMNEdge();
-//					edge.setId(EcoreUtil.generateUUID());
-					edge.setBpmnElement(conElement);
-
-					if (conElement instanceof Association) {
-						edge.setSourceElement(modelHandler.findDIElement(getDiagram(),
-								((Association) conElement).getSourceRef()));
-						edge.setTargetElement(modelHandler.findDIElement(getDiagram(),
-								((Association) conElement).getTargetRef()));
-					} else if (conElement instanceof MessageFlow) {
-						edge.setSourceElement(modelHandler.findDIElement(getDiagram(),
-								(BaseElement) ((MessageFlow) conElement).getSourceRef()));
-						edge.setTargetElement(modelHandler.findDIElement(getDiagram(),
-								(BaseElement) ((MessageFlow) conElement).getTargetRef()));
-					} else if (conElement instanceof SequenceFlow) {
-						edge.setSourceElement(modelHandler.findDIElement(getDiagram(),
-								((SequenceFlow) conElement).getSourceRef()));
-						edge.setTargetElement(modelHandler.findDIElement(getDiagram(),
-								((SequenceFlow) conElement).getTargetRef()));
-					}
-
-					ILocation sourceLoc = Graphiti.getPeService().getLocationRelativeToDiagram(connection.getStart());
-					ILocation targetLoc = Graphiti.getPeService().getLocationRelativeToDiagram(connection.getEnd());
-
-					Point point = DcFactory.eINSTANCE.createPoint();
-					point.setX(sourceLoc.getX());
-					point.setY(sourceLoc.getY());
-					edge.getWaypoint().add(point);
-
-					point = DcFactory.eINSTANCE.createPoint();
-					point.setX(targetLoc.getX());
-					point.setY(targetLoc.getY());
-					edge.getWaypoint().add(point);
-
-					addShape(edge, bpmnDiagram);
-					ModelUtil.setID(edge);
-				}
-			}
-		}
-		link(connection, new Object[] { conElement, edge });
-	}
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Ivar Meikas

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.core.features;

+

+import java.io.IOException;

+import java.util.List;

+

+import org.eclipse.bpmn2.Activity;

+import org.eclipse.bpmn2.Association;

+import org.eclipse.bpmn2.BaseElement;

+import org.eclipse.bpmn2.MessageFlow;

+import org.eclipse.bpmn2.SequenceFlow;

+import org.eclipse.bpmn2.di.BPMNDiagram;

+import org.eclipse.bpmn2.di.BPMNEdge;

+import org.eclipse.bpmn2.di.BPMNShape;

+import org.eclipse.bpmn2.di.BpmnDiFactory;

+import org.eclipse.bpmn2.modeler.core.Activator;

+import org.eclipse.bpmn2.modeler.core.ModelHandler;

+import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;

+import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;

+import org.eclipse.dd.dc.Bounds;

+import org.eclipse.dd.dc.DcFactory;

+import org.eclipse.dd.dc.Point;

+import org.eclipse.dd.di.DiagramElement;

+import org.eclipse.emf.common.util.EList;

+import org.eclipse.emf.ecore.EObject;

+import org.eclipse.graphiti.datatypes.ILocation;

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.impl.AbstractAddShapeFeature;

+import org.eclipse.graphiti.mm.pictograms.Connection;

+import org.eclipse.graphiti.mm.pictograms.Shape;

+import org.eclipse.graphiti.services.Graphiti;

+

+public abstract class AbstractBpmnAddFeature extends AbstractAddShapeFeature {

+

+	public AbstractBpmnAddFeature(IFeatureProvider fp) {

+		super(fp);

+	}

+

+	protected void createDIShape(Shape gShape, BaseElement elem) {

+		try {

+			BPMNShape shape = (BPMNShape) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(

+					getDiagram(), elem);

+			createDIShape(gShape, elem, shape);

+		} catch (IOException e) {

+			Activator.logError(e);

+		}

+	}

+

+	protected void createDIShape(Shape gShape, BaseElement elem, BPMNShape shape) {

+		ILocation loc = Graphiti.getLayoutService().getLocationRelativeToDiagram(gShape);

+		if (shape == null) {

+			EList<EObject> businessObjects = Graphiti.getLinkService().getLinkForPictogramElement(getDiagram())

+					.getBusinessObjects();

+			for (EObject eObject : businessObjects) {

+				if (eObject instanceof BPMNDiagram) {

+					BPMNDiagram bpmnDiagram = (BPMNDiagram) eObject;

+

+					shape = BpmnDiFactory.eINSTANCE.createBPMNShape();

+//					shape.setId(EcoreUtil.generateUUID());

+					shape.setBpmnElement(elem);

+					Bounds bounds = DcFactory.eINSTANCE.createBounds();

+					if (elem instanceof Activity) {

+						bounds.setHeight(gShape.getGraphicsAlgorithm().getHeight());

+					} else {

+						bounds.setHeight(gShape.getGraphicsAlgorithm().getHeight());

+					}

+					bounds.setWidth(gShape.getGraphicsAlgorithm().getWidth());

+					bounds.setX(loc.getX());

+					bounds.setY(loc.getY());

+					shape.setBounds(bounds);

+

+					addShape(shape, bpmnDiagram);

+					ModelUtil.setID(shape);

+				}

+			}

+		}

+		link(gShape, new Object[] { elem, shape });

+	}

+

+	private void addShape(DiagramElement elem, BPMNDiagram bpmnDiagram) {

+		List<DiagramElement> elements = bpmnDiagram.getPlane().getPlaneElement();

+		elements.add(elem);

+	}

+

+	protected void createDIEdge(Connection connection, BaseElement conElement) {

+		try {

+			BPMNEdge edge = (BPMNEdge) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(

+					getDiagram(), conElement);

+			createDIEdge(connection, conElement, edge);

+		} catch (IOException e) {

+			Activator.logError(e);

+		}

+

+	}

+

+	protected void createDIEdge(Connection connection, BaseElement conElement, BPMNEdge edge) throws IOException {

+		ModelHandler modelHandler = ModelHandlerLocator.getModelHandler(getDiagram().eResource());

+		if (edge == null) {

+			EList<EObject> businessObjects = Graphiti.getLinkService().getLinkForPictogramElement(getDiagram())

+					.getBusinessObjects();

+			for (EObject eObject : businessObjects) {

+				if (eObject instanceof BPMNDiagram) {

+					BPMNDiagram bpmnDiagram = (BPMNDiagram) eObject;

+

+					edge = BpmnDiFactory.eINSTANCE.createBPMNEdge();

+//					edge.setId(EcoreUtil.generateUUID());

+					edge.setBpmnElement(conElement);

+

+					if (conElement instanceof Association) {

+						edge.setSourceElement(modelHandler.findDIElement(getDiagram(),

+								((Association) conElement).getSourceRef()));

+						edge.setTargetElement(modelHandler.findDIElement(getDiagram(),

+								((Association) conElement).getTargetRef()));

+					} else if (conElement instanceof MessageFlow) {

+						edge.setSourceElement(modelHandler.findDIElement(getDiagram(),

+								(BaseElement) ((MessageFlow) conElement).getSourceRef()));

+						edge.setTargetElement(modelHandler.findDIElement(getDiagram(),

+								(BaseElement) ((MessageFlow) conElement).getTargetRef()));

+					} else if (conElement instanceof SequenceFlow) {

+						edge.setSourceElement(modelHandler.findDIElement(getDiagram(),

+								((SequenceFlow) conElement).getSourceRef()));

+						edge.setTargetElement(modelHandler.findDIElement(getDiagram(),

+								((SequenceFlow) conElement).getTargetRef()));

+					}

+

+					ILocation sourceLoc = Graphiti.getPeService().getLocationRelativeToDiagram(connection.getStart());

+					ILocation targetLoc = Graphiti.getPeService().getLocationRelativeToDiagram(connection.getEnd());

+

+					Point point = DcFactory.eINSTANCE.createPoint();

+					point.setX(sourceLoc.getX());

+					point.setY(sourceLoc.getY());

+					edge.getWaypoint().add(point);

+

+					point = DcFactory.eINSTANCE.createPoint();

+					point.setX(targetLoc.getX());

+					point.setY(targetLoc.getY());

+					edge.getWaypoint().add(point);

+

+					addShape(edge, bpmnDiagram);

+					ModelUtil.setID(edge);

+				}

+			}

+		}

+		link(connection, new Object[] { conElement, edge });

+	}

 }
\ No newline at end of file
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/AbstractAddActivityFeature.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/AbstractAddActivityFeature.java
index eea322e..90b0598 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/AbstractAddActivityFeature.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/AbstractAddActivityFeature.java
@@ -35,6 +35,8 @@
 
 public abstract class AbstractAddActivityFeature extends AbstractBpmnAddFeature {
 
+	public static final String ACTIVITY_DECORATOR = "activity-decorator";
+
 	public AbstractAddActivityFeature(IFeatureProvider fp) {
 		super(fp);
 	}
@@ -44,7 +46,9 @@
 		boolean intoDiagram = context.getTargetContainer().equals(getDiagram());
 		boolean intoLane = FeatureSupport.isTargetLane(context) && FeatureSupport.isTargetLaneOnTop(context);
 		boolean intoParticipant = FeatureSupport.isTargetParticipant(context);
-		return intoDiagram || intoLane || intoParticipant;
+		boolean intoSubProcess = FeatureSupport.isTargetSubProcess(context);
+				
+		return intoDiagram || intoLane || intoParticipant || intoSubProcess;
 	}
 
 	@Override
@@ -86,6 +90,11 @@
 		Graphiti.getPeService().setPropertyValue(containerShape, IS_COMPENSATE_PROPERTY, Boolean.toString(false));
 		Graphiti.getPeService().setPropertyValue(containerShape, IS_LOOP_OR_MULTI_INSTANCE,
 		        LoopCharacteristicType.NULL.getName());
+		// set a property on the decorators so we can distinguish them from the real children (i.e. tasks, etc.)
+		for (PictogramElement pe : containerShape.getChildren()) {
+			Graphiti.getPeService().setPropertyValue(pe, ACTIVITY_DECORATOR, "true");
+		}
+		
 		updatePictogramElement(containerShape);
 		layoutPictogramElement(containerShape);
 
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/ActivityLayoutFeature.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/ActivityLayoutFeature.java
index fdc8409..77be33a 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/ActivityLayoutFeature.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/ActivityLayoutFeature.java
@@ -16,9 +16,12 @@
 
 import org.eclipse.bpmn2.Activity;
 import org.eclipse.bpmn2.BaseElement;
+import org.eclipse.bpmn2.SubProcess;
+import org.eclipse.bpmn2.di.BPMNShape;
 import org.eclipse.bpmn2.modeler.core.di.DIUtils;
 import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;
 import org.eclipse.bpmn2.modeler.core.features.event.AbstractBoundaryEventOperation;
+import org.eclipse.bpmn2.modeler.core.utils.AnchorUtil;
 import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport;
 import org.eclipse.bpmn2.modeler.core.utils.GraphicsUtil;
 import org.eclipse.graphiti.features.IFeatureProvider;
@@ -27,6 +30,8 @@
 import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
 import org.eclipse.graphiti.mm.algorithms.RoundedRectangle;
 import org.eclipse.graphiti.mm.pictograms.ContainerShape;
+import org.eclipse.graphiti.mm.pictograms.Diagram;
+import org.eclipse.graphiti.mm.pictograms.PictogramElement;
 import org.eclipse.graphiti.mm.pictograms.Shape;
 import org.eclipse.graphiti.services.Graphiti;
 import org.eclipse.graphiti.services.IGaService;
@@ -85,8 +90,50 @@
 		}.doWork(activity, getDiagram());
 
 		DIUtils.updateDIShape(containerShape);
+		layoutConnections(containerShape);
+		
+		if (containerShape.eContainer() instanceof ContainerShape) {
+			PictogramElement pe = (PictogramElement) containerShape.eContainer();
+			if (BusinessObjectUtil.containsElementOfType(pe, SubProcess.class)) {
+				layoutPictogramElement(pe);
+			}
+		}
 		return true;
 	}
+	
+	public static Diagram getDiagram(ContainerShape container) {
+		while ( !(container instanceof Diagram) ) {
+			container = container.getContainer();
+		}
+		return (Diagram)container;
+	}
+	
+	public void layoutConnections(Shape shape) {
+		Diagram diagram = getDiagram();
+		if (diagram!=null) {
+			if (shape.getLink()!=null) {
+				for (Object object : shape.getLink().getBusinessObjects()) {
+					if (object instanceof BPMNShape) {
+						BPMNShape s = (BPMNShape) object;
+						AnchorUtil.reConnect(s, diagram);
+					}
+				}
+			}
+			
+			if (shape instanceof ContainerShape) {
+				for (PictogramElement pe : FeatureSupport.getContainerChildren((ContainerShape)shape)) {
+					if (pe.getLink()!=null) {
+						for (Object object : pe.getLink().getBusinessObjects()) {
+							if (object instanceof BPMNShape) {
+								BPMNShape s = (BPMNShape) object;
+								AnchorUtil.reConnect(s, diagram);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
 
 	protected int getMarkerContainerOffset() {
 		return 0;
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/ActivityMoveFeature.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/ActivityMoveFeature.java
index 954794a..ef04b97 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/ActivityMoveFeature.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/activity/ActivityMoveFeature.java
@@ -1,59 +1,130 @@
-/******************************************************************************* 
- * Copyright (c) 2011 Red Hat, Inc. 
- *  All rights reserved. 
- * This program is 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: 
- * Red Hat, Inc. - initial API and implementation 
- *
- * @author Ivar Meikas
- ******************************************************************************/
-package org.eclipse.bpmn2.modeler.core.features.activity;
-
-import org.eclipse.bpmn2.Activity;
-import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;
-import org.eclipse.bpmn2.modeler.core.features.MoveFlowNodeFeature;
-import org.eclipse.bpmn2.modeler.core.features.event.AbstractBoundaryEventOperation;
-import org.eclipse.graphiti.features.IFeatureProvider;
-import org.eclipse.graphiti.features.IMoveShapeFeature;
-import org.eclipse.graphiti.features.context.IMoveShapeContext;
-import org.eclipse.graphiti.features.context.impl.MoveShapeContext;
-import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
-import org.eclipse.graphiti.mm.pictograms.ContainerShape;
-
-public class ActivityMoveFeature extends MoveFlowNodeFeature {
-
-	public static final String ACTIVITY_MOVE_PROPERTY = "activity.move";
-
-	public ActivityMoveFeature(IFeatureProvider fp) {
-		super(fp);
-	}
-
-	@Override
-	protected void postMoveShape(final IMoveShapeContext context) {
-		super.postMoveShape(context);
-		Activity activity = BusinessObjectUtil.getFirstElementOfType(context.getPictogramElement(), Activity.class);
-		new AbstractBoundaryEventOperation() {
-			@Override
-			protected void doWorkInternal(ContainerShape container) {
-				GraphicsAlgorithm ga = container.getGraphicsAlgorithm();
-
-				MoveShapeContext newContext = new MoveShapeContext(container);
-				newContext.setDeltaX(context.getDeltaX());
-				newContext.setDeltaY(context.getDeltaY());
-				newContext.setSourceContainer(context.getSourceContainer());
-				newContext.setTargetContainer(context.getTargetContainer());
-				newContext.setTargetConnection(context.getTargetConnection());
-				newContext.setLocation(ga.getX(), ga.getY());
-				newContext.putProperty(ACTIVITY_MOVE_PROPERTY, true);
-
-				IMoveShapeFeature moveFeature = getFeatureProvider().getMoveShapeFeature(newContext);
-				if (moveFeature.canMoveShape(newContext)) {
-					moveFeature.moveShape(newContext);
-				}
-			}
-		}.doWork(activity, getDiagram());
-	}
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Ivar Meikas

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.core.features.activity;

+

+import org.eclipse.bpmn2.Activity;

+import org.eclipse.bpmn2.SubProcess;

+import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;

+import org.eclipse.bpmn2.modeler.core.features.MoveFlowNodeFeature;

+import org.eclipse.bpmn2.modeler.core.features.event.AbstractBoundaryEventOperation;

+import org.eclipse.graphiti.datatypes.ILocation;

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.IMoveShapeFeature;

+import org.eclipse.graphiti.features.context.IMoveShapeContext;

+import org.eclipse.graphiti.features.context.impl.MoveShapeContext;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.pictograms.ContainerShape;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+import org.eclipse.graphiti.services.Graphiti;

+import org.eclipse.graphiti.services.IPeLayoutService;

+

+public class ActivityMoveFeature extends MoveFlowNodeFeature {

+

+	public static final String ACTIVITY_MOVE_PROPERTY = "activity.move";

+

+	public ActivityMoveFeature(IFeatureProvider fp) {

+		super(fp);

+	}

+

+	@Override

+	protected void preMoveShape(IMoveShapeContext context) {

+		MoveShapeContext msc = (MoveShapeContext)context;

+		ContainerShape oldContainer = context.getSourceContainer();

+		ContainerShape newContainer = context.getTargetContainer();

+		IPeLayoutService peLayoutService = Graphiti.getPeLayoutService();

+//		Shape shape = context.getShape();

+//		ILocation loc = peService.getLocationRelativeToDiagram(shape);

+		ILocation oldLoc = peLayoutService.getLocationRelativeToDiagram(oldContainer);

+		ILocation newLoc = peLayoutService.getLocationRelativeToDiagram(newContainer);

+//		System.out.println(

+//				(oldContainer==newContainer ? "inside:\n" : "outside:\n")+

+//				"oldContainer:\n" +

+//				"  x="+oldLoc.getX()+"\n"+

+//					"  y="+oldLoc.getY()+"\n"+

+//				"newContainer:\n" +

+//				"  x="+newLoc.getX()+"\n"+

+//					"  y="+newLoc.getY()+"\n"+

+//				"shape:\n" +

+//				"  rel x="+shape.getGraphicsAlgorithm().getX()+"\n"+

+//					"  rel y="+shape.getGraphicsAlgorithm().getY()+"\n"+

+//				"  abs x="+loc.getX()+"\n"+

+//					"  abs y="+loc.getY()+"\n"+

+//				"context:\n" +

+//				"  x="+msc.getX()+"\n"+

+//					"  y="+msc.getY()+"\n"+

+//				"  deltaX="+msc.getDeltaX()+"\n"+

+//					"  deltaY="+msc.getDeltaY()+"\n"+

+//				"\n"

+//		);

+		

+		if (oldContainer!=newContainer) {

+			int x = newLoc.getX() + msc.getX() - oldLoc.getX();

+			int y = newLoc.getY() + msc.getY() - oldLoc.getY();

+			int deltaX = newLoc.getX() + msc.getDeltaX() - oldLoc.getX();

+			int deltaY = newLoc.getY() + msc.getDeltaY() - oldLoc.getY();

+			

+//			System.out.println(

+//					"new context:\n"+

+//					"  x="+( newLoc.getX() + msc.getX() - oldLoc.getX() )+"\n"+

+//								"  y="+msc.getY()+"\n"+

+//					"  deltaX="+( newLoc.getX() + msc.getDeltaX() - oldLoc.getX() )+"\n"+

+//								"  deltaY="+msc.getDeltaY()+"\n"+

+//					"\n"

+//			);

+			

+			msc.setX(x);

+			msc.setY(y);

+			msc.setDeltaX(deltaX);

+			msc.setDeltaY(deltaY);

+			msc.setTargetContainer(oldContainer);

+		}

+

+		super.preMoveShape(context);

+	}

+

+	@Override

+	protected void postMoveShape(final IMoveShapeContext context) {

+		super.postMoveShape(context);

+		PictogramElement containerShape = context.getPictogramElement();

+		Activity activity = BusinessObjectUtil.getFirstElementOfType(containerShape, Activity.class);

+		new AbstractBoundaryEventOperation() {

+			@Override

+			protected void doWorkInternal(ContainerShape container) {

+				GraphicsAlgorithm ga = container.getGraphicsAlgorithm();

+

+				MoveShapeContext newContext = new MoveShapeContext(container);

+				newContext.setDeltaX(context.getDeltaX());

+				newContext.setDeltaY(context.getDeltaY());

+				newContext.setSourceContainer(context.getSourceContainer());

+				newContext.setTargetContainer(context.getTargetContainer());

+				newContext.setTargetConnection(context.getTargetConnection());

+				newContext.setLocation(ga.getX(), ga.getY());

+				newContext.putProperty(ACTIVITY_MOVE_PROPERTY, true);

+

+				IMoveShapeFeature moveFeature = getFeatureProvider().getMoveShapeFeature(newContext);

+				if (moveFeature.canMoveShape(newContext)) {

+					moveFeature.moveShape(newContext);

+				}

+				

+				Graphiti.getPeService().sendToFront(context.getShape());

+			}

+		}.doWork(activity, getDiagram());

+		

+		if (containerShape.eContainer() instanceof ContainerShape) {

+			PictogramElement pe = (PictogramElement) containerShape.eContainer();

+			if (BusinessObjectUtil.containsElementOfType(pe, SubProcess.class)) {

+				layoutPictogramElement(pe);

+			}

+		}

+	}

 }
\ No newline at end of file
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/AnchorUtil.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/AnchorUtil.java
index 45e0c55..7daf0b2 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/AnchorUtil.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/AnchorUtil.java
@@ -1,429 +1,440 @@
-/******************************************************************************* 
- * Copyright (c) 2011 Red Hat, Inc. 
- *  All rights reserved. 
- * This program is 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: 
- * Red Hat, Inc. - initial API and implementation 
- *
- * @author Ivar Meikas
- ******************************************************************************/
-package org.eclipse.bpmn2.modeler.core.utils;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.bpmn2.di.BPMNEdge;
-import org.eclipse.bpmn2.di.BPMNShape;
-import org.eclipse.bpmn2.modeler.core.Activator;
-import org.eclipse.bpmn2.modeler.core.ModelHandler;
-import org.eclipse.dd.di.DiagramElement;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.graphiti.datatypes.IDimension;
-import org.eclipse.graphiti.datatypes.ILocation;
-import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
-import org.eclipse.graphiti.mm.algorithms.styles.Point;
-import org.eclipse.graphiti.mm.pictograms.Anchor;
-import org.eclipse.graphiti.mm.pictograms.Connection;
-import org.eclipse.graphiti.mm.pictograms.ContainerShape;
-import org.eclipse.graphiti.mm.pictograms.Diagram;
-import org.eclipse.graphiti.mm.pictograms.FixPointAnchor;
-import org.eclipse.graphiti.mm.pictograms.Shape;
-import org.eclipse.graphiti.mm.pictograms.impl.FreeFormConnectionImpl;
-import org.eclipse.graphiti.services.Graphiti;
-import org.eclipse.graphiti.services.IGaService;
-import org.eclipse.graphiti.services.IPeService;
-
-public class AnchorUtil {
-
-	public static final String BOUNDARY_FIXPOINT_ANCHOR = "boundary.fixpoint.anchor";
-
-	private static final IPeService peService = Graphiti.getPeService();
-	private static final IGaService gaService = Graphiti.getGaService();
-
-	public enum AnchorLocation {
-		TOP("anchor.top"), BOTTOM("anchor.bottom"), LEFT("anchor.left"), RIGHT("anchor.right");
-
-		private final String key;
-
-		private AnchorLocation(String key) {
-			this.key = key;
-		}
-
-		public String getKey() {
-			return key;
-		}
-
-		public static AnchorLocation getLocation(String key) {
-			for (AnchorLocation l : values()) {
-				if (l.getKey().equals(key)) {
-					return l;
-				}
-			}
-			return null;
-		}
-	}
-
-	public static class AnchorTuple {
-		public FixPointAnchor sourceAnchor;
-		public FixPointAnchor targetAnchor;
-	}
-
-	public static class BoundaryAnchor {
-		public FixPointAnchor anchor;
-		public AnchorLocation locationType;
-		public ILocation location;
-	}
-
-	public static FixPointAnchor createAnchor(Shape s, AnchorLocation loc, int x, int y) {
-		IGaService gaService = Graphiti.getGaService();
-		IPeService peService = Graphiti.getPeService();
-
-		FixPointAnchor anchor = peService.createFixPointAnchor(s);
-		peService.setPropertyValue(anchor, BOUNDARY_FIXPOINT_ANCHOR, loc.getKey());
-		anchor.setLocation(gaService.createPoint(x, y));
-		gaService.createInvisibleRectangle(anchor);
-
-		return anchor;
-	}
-
-	public static Map<AnchorLocation, BoundaryAnchor> getBoundaryAnchors(Shape s) {
-		Map<AnchorLocation, BoundaryAnchor> map = new HashMap<AnchorLocation, AnchorUtil.BoundaryAnchor>(4);
-		Iterator<Anchor> iterator = s.getAnchors().iterator();
-		while (iterator.hasNext()) {
-			Anchor anchor = iterator.next();
-			String property = Graphiti.getPeService().getPropertyValue(anchor, BOUNDARY_FIXPOINT_ANCHOR);
-			if (property != null && anchor instanceof FixPointAnchor) {
-				BoundaryAnchor a = new BoundaryAnchor();
-				a.anchor = (FixPointAnchor) anchor;
-				a.locationType = AnchorLocation.getLocation(property);
-				a.location = peService.getLocationRelativeToDiagram(anchor);
-				map.put(a.locationType, a);
-			}
-		}
-		return map;
-	}
-
-	public static Point getCenterPoint(Shape s) {
-		GraphicsAlgorithm ga = s.getGraphicsAlgorithm();
-		ILocation loc = peService.getLocationRelativeToDiagram(s);
-		return gaService.createPoint(loc.getX() + (ga.getWidth() / 2), loc.getY() + (ga.getHeight() / 2));
-	}
-
-	@SuppressWarnings("restriction")
-	public static Tuple<FixPointAnchor, FixPointAnchor> getSourceAndTargetBoundaryAnchors(Shape source, Shape target,
-			Connection connection) {
-		Map<AnchorLocation, BoundaryAnchor> sourceBoundaryAnchors = getBoundaryAnchors(source);
-		Map<AnchorLocation, BoundaryAnchor> targetBoundaryAnchors = getBoundaryAnchors(target);
-
-		if (connection instanceof FreeFormConnectionImpl) {
-			EList<Point> bendpoints = ((FreeFormConnectionImpl) connection).getBendpoints();
-			if (bendpoints.size() > 0) {
-				FixPointAnchor sourceAnchor = getCorrectAnchor(sourceBoundaryAnchors, bendpoints.get(0));
-				FixPointAnchor targetAnchor = getCorrectAnchor(targetBoundaryAnchors,
-						bendpoints.get(bendpoints.size() - 1));
-				return new Tuple<FixPointAnchor, FixPointAnchor>(sourceAnchor, targetAnchor);
-			}
-		}
-
-		BoundaryAnchor sourceTop = sourceBoundaryAnchors.get(AnchorLocation.TOP);
-		BoundaryAnchor sourceBottom = sourceBoundaryAnchors.get(AnchorLocation.BOTTOM);
-		BoundaryAnchor sourceLeft = sourceBoundaryAnchors.get(AnchorLocation.LEFT);
-		BoundaryAnchor sourceRight = sourceBoundaryAnchors.get(AnchorLocation.RIGHT);
-		BoundaryAnchor targetBottom = targetBoundaryAnchors.get(AnchorLocation.BOTTOM);
-		BoundaryAnchor targetTop = targetBoundaryAnchors.get(AnchorLocation.TOP);
-		BoundaryAnchor targetRight = targetBoundaryAnchors.get(AnchorLocation.RIGHT);
-		BoundaryAnchor targetLeft = targetBoundaryAnchors.get(AnchorLocation.LEFT);
-
-		boolean sLower = sourceTop.location.getY() > targetBottom.location.getY();
-		boolean sHigher = sourceBottom.location.getY() < targetTop.location.getY();
-		boolean sRight = sourceLeft.location.getX() > targetRight.location.getX();
-		boolean sLeft = sourceRight.location.getX() < targetLeft.location.getX();
-
-		if (sLower) {
-			if (!sLeft && !sRight) {
-				return new Tuple<FixPointAnchor, FixPointAnchor>(sourceTop.anchor, targetBottom.anchor);
-			} else if (sLeft) {
-				FixPointAnchor fromTopAnchor = getCorrectAnchor(targetBoundaryAnchors,
-						peService.getLocationRelativeToDiagram(sourceTop.anchor));
-				FixPointAnchor fromRightAnchor = getCorrectAnchor(targetBoundaryAnchors,
-						peService.getLocationRelativeToDiagram(sourceRight.anchor));
-
-				double topLength = getLength(peService.getLocationRelativeToDiagram(fromTopAnchor),
-						peService.getLocationRelativeToDiagram(sourceTop.anchor));
-				double rightLength = getLength(peService.getLocationRelativeToDiagram(fromRightAnchor),
-						peService.getLocationRelativeToDiagram(sourceRight.anchor));
-
-				if (topLength < rightLength) {
-					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceTop.anchor, fromTopAnchor);
-				} else {
-					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceRight.anchor, fromRightAnchor);
-				}
-			} else {
-				FixPointAnchor fromTopAnchor = getCorrectAnchor(targetBoundaryAnchors,
-						peService.getLocationRelativeToDiagram(sourceTop.anchor));
-				FixPointAnchor fromLeftAnchor = getCorrectAnchor(targetBoundaryAnchors,
-						peService.getLocationRelativeToDiagram(sourceLeft.anchor));
-
-				double topLength = getLength(peService.getLocationRelativeToDiagram(fromTopAnchor),
-						peService.getLocationRelativeToDiagram(sourceTop.anchor));
-				double leftLength = getLength(peService.getLocationRelativeToDiagram(fromLeftAnchor),
-						peService.getLocationRelativeToDiagram(sourceLeft.anchor));
-				if (topLength < leftLength) {
-					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceTop.anchor, fromTopAnchor);
-				} else {
-					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceLeft.anchor, fromLeftAnchor);
-				}
-			}
-
-		}
-
-		if (sHigher) {
-			if (!sLeft && !sRight) {
-				return new Tuple<FixPointAnchor, FixPointAnchor>(sourceBottom.anchor, targetTop.anchor);
-			} else if (sLeft) {
-				FixPointAnchor fromBottomAnchor = getCorrectAnchor(targetBoundaryAnchors,
-						peService.getLocationRelativeToDiagram(sourceBottom.anchor));
-				FixPointAnchor fromRightAnchor = getCorrectAnchor(targetBoundaryAnchors,
-						peService.getLocationRelativeToDiagram(sourceRight.anchor));
-
-				double bottomLength = getLength(peService.getLocationRelativeToDiagram(fromBottomAnchor),
-						peService.getLocationRelativeToDiagram(sourceBottom.anchor));
-				double rightLength = getLength(peService.getLocationRelativeToDiagram(fromRightAnchor),
-						peService.getLocationRelativeToDiagram(sourceRight.anchor));
-
-				if (bottomLength < rightLength) {
-					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceBottom.anchor, fromBottomAnchor);
-				} else {
-					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceRight.anchor, fromRightAnchor);
-				}
-			} else {
-				FixPointAnchor fromBottomAnchor = getCorrectAnchor(targetBoundaryAnchors,
-						peService.getLocationRelativeToDiagram(sourceBottom.anchor));
-				FixPointAnchor fromLeftAnchor = getCorrectAnchor(targetBoundaryAnchors,
-						peService.getLocationRelativeToDiagram(sourceLeft.anchor));
-
-				double bottomLength = getLength(peService.getLocationRelativeToDiagram(fromBottomAnchor),
-						peService.getLocationRelativeToDiagram(sourceBottom.anchor));
-				double leftLength = getLength(peService.getLocationRelativeToDiagram(fromLeftAnchor),
-						peService.getLocationRelativeToDiagram(sourceLeft.anchor));
-				if (bottomLength < leftLength) {
-					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceBottom.anchor, fromBottomAnchor);
-				} else {
-					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceLeft.anchor, fromLeftAnchor);
-				}
-			}
-		}
-
-		// if source left is further than target right then use source left and target right
-		if (sRight) {
-			return new Tuple<FixPointAnchor, FixPointAnchor>(sourceLeft.anchor, targetRight.anchor);
-		}
-
-		// if source right is smaller than target left then use source right and target left
-		if (sLeft) {
-			return new Tuple<FixPointAnchor, FixPointAnchor>(sourceRight.anchor, targetLeft.anchor);
-		}
-
-		return new Tuple<FixPointAnchor, FixPointAnchor>(sourceTop.anchor, targetTop.anchor);
-	}
-
-	private static FixPointAnchor getCorrectAnchor(Map<AnchorLocation, BoundaryAnchor> targetBoundaryAnchors,
-			ILocation loc) {
-		return getCorrectAnchor(targetBoundaryAnchors, gaService.createPoint(loc.getX(), loc.getY()));
-	}
-
-	private static double getLength(ILocation start, ILocation end) {
-		return Math.sqrt(Math.pow(start.getX() - end.getX(), 2) + Math.pow(start.getY() - end.getY(), 2));
-	}
-
-	private static FixPointAnchor getCorrectAnchor(Map<AnchorLocation, BoundaryAnchor> boundaryAnchors, Point point) {
-
-		BoundaryAnchor bottom = boundaryAnchors.get(AnchorLocation.BOTTOM);
-		BoundaryAnchor top = boundaryAnchors.get(AnchorLocation.TOP);
-		BoundaryAnchor right = boundaryAnchors.get(AnchorLocation.RIGHT);
-		BoundaryAnchor left = boundaryAnchors.get(AnchorLocation.LEFT);
-
-		boolean pointLower = point.getY() > bottom.location.getY();
-		boolean pointHigher = point.getY() < top.location.getY();
-		boolean pointRight = point.getX() > right.location.getX();
-		boolean pointLeft = point.getX() < left.location.getX();
-
-		// Find the best connector.
-		if (pointLower) {
-			if (!pointLeft && !pointRight) {
-				// bendpoint is straight below the shape
-				return bottom.anchor;
-			} else if (pointLeft) {
-
-				int deltaX = left.location.getX() - point.getX();
-				int deltaY = point.getY() - bottom.location.getY();
-				if (deltaX > deltaY) {
-					return left.anchor;
-				} else {
-					return bottom.anchor;
-				}
-			} else {
-				int deltaX = point.getX() - right.location.getX();
-				int deltaY = point.getY() - bottom.location.getY();
-				if (deltaX > deltaY) {
-					return right.anchor;
-				} else {
-					return bottom.anchor;
-				}
-			}
-		}
-
-		if (pointHigher) {
-			if (!pointLeft && !pointRight) {
-				// bendpoint is straight above the shape
-				return top.anchor;
-			} else if (pointLeft) {
-				int deltaX = left.location.getX() - point.getX();
-				int deltaY = top.location.getY() - point.getY();
-				if (deltaX > deltaY) {
-					return left.anchor;
-				} else {
-					return top.anchor;
-				}
-			} else {
-				int deltaX = point.getX() - right.location.getX();
-				int deltaY = top.location.getY() - point.getY();
-				if (deltaX > deltaY) {
-					return right.anchor;
-				} else {
-					return top.anchor;
-				}
-			}
-
-		}
-
-		// if we reach here, then the point is neither above or below the shape and we only need to determine if we need
-		// to connect to the left or right part of the shape
-		if (pointRight) {
-			return right.anchor;
-		}
-
-		if (pointLeft) {
-			return left.anchor;
-		}
-
-		return top.anchor;
-	}
-
-	public static void reConnect(BPMNShape shape, Diagram diagram) {
-		try {
-			ModelHandler handler = ModelHandler.getInstance(diagram);
-			for (BPMNEdge bpmnEdge : handler.getAll(BPMNEdge.class)) {
-				DiagramElement sourceElement = bpmnEdge.getSourceElement();
-				DiagramElement targetElement = bpmnEdge.getTargetElement();
-				if (sourceElement != null && targetElement != null) {
-					boolean sourceMatches = sourceElement.getId().equals(shape.getId());
-					boolean targetMatches = targetElement.getId().equals(shape.getId());
-					if (sourceMatches || targetMatches) {
-						updateEdge(bpmnEdge, diagram);
-					}
-				}
-			}
-		} catch (Exception e) {
-			Activator.logError(e);
-		}
-	}
-
-	private static void updateEdge(BPMNEdge edge, Diagram diagram) {
-		ContainerShape source = (ContainerShape) Graphiti.getLinkService()
-				.getPictogramElements(diagram, edge.getSourceElement()).get(0);
-		ContainerShape target = (ContainerShape) Graphiti.getLinkService()
-				.getPictogramElements(diagram, edge.getTargetElement()).get(0);
-		Connection connection = (Connection) Graphiti.getLinkService().getPictogramElements(diagram, edge).get(0);
-		Tuple<FixPointAnchor, FixPointAnchor> anchors = getSourceAndTargetBoundaryAnchors(source, target, connection);
-
-		ILocation loc = peService.getLocationRelativeToDiagram(anchors.getFirst());
-		org.eclipse.dd.dc.Point p = edge.getWaypoint().get(0);
-		p.setX(loc.getX());
-		p.setY(loc.getY());
-
-		loc = peService.getLocationRelativeToDiagram(anchors.getSecond());
-		p = edge.getWaypoint().get(edge.getWaypoint().size() - 1);
-		p.setX(loc.getX());
-		p.setY(loc.getY());
-
-		relocateConnection(source.getAnchors(), anchors, target);
-		deleteEmptyAdHocAnchors(source);
-		deleteEmptyAdHocAnchors(target);
-	}
-
-	private static void relocateConnection(EList<Anchor> anchors, Tuple<FixPointAnchor, FixPointAnchor> newAnchors,
-			ContainerShape target) {
-
-		List<Connection> connectionsToBeUpdated = new ArrayList<Connection>();
-
-		for (Anchor anchor : anchors) {
-			if (!(anchor instanceof FixPointAnchor)) {
-				continue;
-			}
-
-			for (Connection connection : anchor.getOutgoingConnections()) {
-				if (connection.getEnd().eContainer().equals(target)) {
-					connectionsToBeUpdated.add(connection);
-				}
-			}
-		}
-
-		for (Connection c : connectionsToBeUpdated) {
-			c.setStart(newAnchors.getFirst());
-			c.setEnd(newAnchors.getSecond());
-		}
-	}
-
-	private static void deleteEmptyAdHocAnchors(Shape s) {
-		List<Integer> indexes = new ArrayList<Integer>();
-
-		for (int i = s.getAnchors().size()-1; i>=0; --i) {
-			Anchor a = s.getAnchors().get(i);
-			if (!(a instanceof FixPointAnchor)) {
-				continue;
-			}
-
-			if (peService.getProperty(a, BOUNDARY_FIXPOINT_ANCHOR) == null && a.getIncomingConnections().isEmpty()
-					&& a.getOutgoingConnections().isEmpty()) {
-				indexes.add(i);
-			}
-		}
-
-		for (int i : indexes) {
-			peService.deletePictogramElement(s.getAnchors().get(i));
-		}
-	}
-
-	public static void addFixedPointAnchors(Shape shape, GraphicsAlgorithm ga) {
-		IDimension size = gaService.calculateSize(ga);
-		int w = size.getWidth();
-		int h = size.getHeight();
-		AnchorUtil.createAnchor(shape, AnchorLocation.TOP, w / 2, 0);
-		AnchorUtil.createAnchor(shape, AnchorLocation.RIGHT, w, h / 2);
-		AnchorUtil.createAnchor(shape, AnchorLocation.BOTTOM, w / 2, h);
-		AnchorUtil.createAnchor(shape, AnchorLocation.LEFT, 0, h / 2);
-	}
-
-	public static void relocateFixPointAnchors(Shape shape, int w, int h) {
-		Map<AnchorLocation, BoundaryAnchor> anchors = AnchorUtil.getBoundaryAnchors(shape);
-
-		FixPointAnchor anchor = anchors.get(AnchorLocation.TOP).anchor;
-		anchor.setLocation(gaService.createPoint(w / 2, 0));
-
-		anchor = anchors.get(AnchorLocation.RIGHT).anchor;
-		anchor.setLocation(gaService.createPoint(w, h / 2));
-
-		anchor = anchors.get(AnchorLocation.BOTTOM).anchor;
-		anchor.setLocation(gaService.createPoint(w / 2, h));
-
-		anchor = anchors.get(AnchorLocation.LEFT).anchor;
-		anchor.setLocation(gaService.createPoint(0, h / 2));
-	}
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Ivar Meikas

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.core.utils;

+

+import java.util.ArrayList;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Map;

+

+import org.eclipse.bpmn2.di.BPMNEdge;

+import org.eclipse.bpmn2.di.BPMNShape;

+import org.eclipse.bpmn2.modeler.core.Activator;

+import org.eclipse.bpmn2.modeler.core.ModelHandler;

+import org.eclipse.dd.di.DiagramElement;

+import org.eclipse.emf.common.util.EList;

+import org.eclipse.graphiti.datatypes.IDimension;

+import org.eclipse.graphiti.datatypes.ILocation;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.algorithms.styles.Point;

+import org.eclipse.graphiti.mm.pictograms.Anchor;

+import org.eclipse.graphiti.mm.pictograms.Connection;

+import org.eclipse.graphiti.mm.pictograms.ContainerShape;

+import org.eclipse.graphiti.mm.pictograms.Diagram;

+import org.eclipse.graphiti.mm.pictograms.FixPointAnchor;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+import org.eclipse.graphiti.mm.pictograms.Shape;

+import org.eclipse.graphiti.mm.pictograms.impl.FreeFormConnectionImpl;

+import org.eclipse.graphiti.services.Graphiti;

+import org.eclipse.graphiti.services.IGaService;

+import org.eclipse.graphiti.services.IPeService;

+

+public class AnchorUtil {

+

+	public static final String BOUNDARY_FIXPOINT_ANCHOR = "boundary.fixpoint.anchor";

+

+	private static final IPeService peService = Graphiti.getPeService();

+	private static final IGaService gaService = Graphiti.getGaService();

+

+	public enum AnchorLocation {

+		TOP("anchor.top"), BOTTOM("anchor.bottom"), LEFT("anchor.left"), RIGHT("anchor.right");

+

+		private final String key;

+

+		private AnchorLocation(String key) {

+			this.key = key;

+		}

+

+		public String getKey() {

+			return key;

+		}

+

+		public static AnchorLocation getLocation(String key) {

+			for (AnchorLocation l : values()) {

+				if (l.getKey().equals(key)) {

+					return l;

+				}

+			}

+			return null;

+		}

+	}

+

+	public static class AnchorTuple {

+		public FixPointAnchor sourceAnchor;

+		public FixPointAnchor targetAnchor;

+	}

+

+	public static class BoundaryAnchor {

+		public FixPointAnchor anchor;

+		public AnchorLocation locationType;

+		public ILocation location;

+	}

+

+	public static FixPointAnchor createAnchor(Shape s, AnchorLocation loc, int x, int y) {

+		IGaService gaService = Graphiti.getGaService();

+		IPeService peService = Graphiti.getPeService();

+

+		FixPointAnchor anchor = peService.createFixPointAnchor(s);

+		peService.setPropertyValue(anchor, BOUNDARY_FIXPOINT_ANCHOR, loc.getKey());

+		anchor.setLocation(gaService.createPoint(x, y));

+		gaService.createInvisibleRectangle(anchor);

+

+		return anchor;

+	}

+

+	public static Map<AnchorLocation, BoundaryAnchor> getBoundaryAnchors(Shape s) {

+		Map<AnchorLocation, BoundaryAnchor> map = new HashMap<AnchorLocation, AnchorUtil.BoundaryAnchor>(4);

+		Iterator<Anchor> iterator = s.getAnchors().iterator();

+		while (iterator.hasNext()) {

+			Anchor anchor = iterator.next();

+			String property = Graphiti.getPeService().getPropertyValue(anchor, BOUNDARY_FIXPOINT_ANCHOR);

+			if (property != null && anchor instanceof FixPointAnchor) {

+				BoundaryAnchor a = new BoundaryAnchor();

+				a.anchor = (FixPointAnchor) anchor;

+				a.locationType = AnchorLocation.getLocation(property);

+				a.location = peService.getLocationRelativeToDiagram(anchor);

+				map.put(a.locationType, a);

+			}

+		}

+		return map;

+	}

+

+	public static Point getCenterPoint(Shape s) {

+		GraphicsAlgorithm ga = s.getGraphicsAlgorithm();

+		ILocation loc = peService.getLocationRelativeToDiagram(s);

+		return gaService.createPoint(loc.getX() + (ga.getWidth() / 2), loc.getY() + (ga.getHeight() / 2));

+	}

+

+	@SuppressWarnings("restriction")

+	public static Tuple<FixPointAnchor, FixPointAnchor> getSourceAndTargetBoundaryAnchors(Shape source, Shape target,

+			Connection connection) {

+		Map<AnchorLocation, BoundaryAnchor> sourceBoundaryAnchors = getBoundaryAnchors(source);

+		Map<AnchorLocation, BoundaryAnchor> targetBoundaryAnchors = getBoundaryAnchors(target);

+

+		if (connection instanceof FreeFormConnectionImpl) {

+			EList<Point> bendpoints = ((FreeFormConnectionImpl) connection).getBendpoints();

+			if (bendpoints.size() > 0) {

+				FixPointAnchor sourceAnchor = getCorrectAnchor(sourceBoundaryAnchors, bendpoints.get(0));

+				FixPointAnchor targetAnchor = getCorrectAnchor(targetBoundaryAnchors,

+						bendpoints.get(bendpoints.size() - 1));

+				return new Tuple<FixPointAnchor, FixPointAnchor>(sourceAnchor, targetAnchor);

+			}

+		}

+

+		BoundaryAnchor sourceTop = sourceBoundaryAnchors.get(AnchorLocation.TOP);

+		BoundaryAnchor sourceBottom = sourceBoundaryAnchors.get(AnchorLocation.BOTTOM);

+		BoundaryAnchor sourceLeft = sourceBoundaryAnchors.get(AnchorLocation.LEFT);

+		BoundaryAnchor sourceRight = sourceBoundaryAnchors.get(AnchorLocation.RIGHT);

+		BoundaryAnchor targetBottom = targetBoundaryAnchors.get(AnchorLocation.BOTTOM);

+		BoundaryAnchor targetTop = targetBoundaryAnchors.get(AnchorLocation.TOP);

+		BoundaryAnchor targetRight = targetBoundaryAnchors.get(AnchorLocation.RIGHT);

+		BoundaryAnchor targetLeft = targetBoundaryAnchors.get(AnchorLocation.LEFT);

+

+		boolean sLower = sourceTop.location.getY() > targetBottom.location.getY();

+		boolean sHigher = sourceBottom.location.getY() < targetTop.location.getY();

+		boolean sRight = sourceLeft.location.getX() > targetRight.location.getX();

+		boolean sLeft = sourceRight.location.getX() < targetLeft.location.getX();

+

+		if (sLower) {

+			if (!sLeft && !sRight) {

+				return new Tuple<FixPointAnchor, FixPointAnchor>(sourceTop.anchor, targetBottom.anchor);

+			} else if (sLeft) {

+				FixPointAnchor fromTopAnchor = getCorrectAnchor(targetBoundaryAnchors,

+						peService.getLocationRelativeToDiagram(sourceTop.anchor));

+				FixPointAnchor fromRightAnchor = getCorrectAnchor(targetBoundaryAnchors,

+						peService.getLocationRelativeToDiagram(sourceRight.anchor));

+

+				double topLength = getLength(peService.getLocationRelativeToDiagram(fromTopAnchor),

+						peService.getLocationRelativeToDiagram(sourceTop.anchor));

+				double rightLength = getLength(peService.getLocationRelativeToDiagram(fromRightAnchor),

+						peService.getLocationRelativeToDiagram(sourceRight.anchor));

+

+				if (topLength < rightLength) {

+					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceTop.anchor, fromTopAnchor);

+				} else {

+					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceRight.anchor, fromRightAnchor);

+				}

+			} else {

+				FixPointAnchor fromTopAnchor = getCorrectAnchor(targetBoundaryAnchors,

+						peService.getLocationRelativeToDiagram(sourceTop.anchor));

+				FixPointAnchor fromLeftAnchor = getCorrectAnchor(targetBoundaryAnchors,

+						peService.getLocationRelativeToDiagram(sourceLeft.anchor));

+

+				double topLength = getLength(peService.getLocationRelativeToDiagram(fromTopAnchor),

+						peService.getLocationRelativeToDiagram(sourceTop.anchor));

+				double leftLength = getLength(peService.getLocationRelativeToDiagram(fromLeftAnchor),

+						peService.getLocationRelativeToDiagram(sourceLeft.anchor));

+				if (topLength < leftLength) {

+					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceTop.anchor, fromTopAnchor);

+				} else {

+					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceLeft.anchor, fromLeftAnchor);

+				}

+			}

+

+		}

+

+		if (sHigher) {

+			if (!sLeft && !sRight) {

+				return new Tuple<FixPointAnchor, FixPointAnchor>(sourceBottom.anchor, targetTop.anchor);

+			} else if (sLeft) {

+				FixPointAnchor fromBottomAnchor = getCorrectAnchor(targetBoundaryAnchors,

+						peService.getLocationRelativeToDiagram(sourceBottom.anchor));

+				FixPointAnchor fromRightAnchor = getCorrectAnchor(targetBoundaryAnchors,

+						peService.getLocationRelativeToDiagram(sourceRight.anchor));

+

+				double bottomLength = getLength(peService.getLocationRelativeToDiagram(fromBottomAnchor),

+						peService.getLocationRelativeToDiagram(sourceBottom.anchor));

+				double rightLength = getLength(peService.getLocationRelativeToDiagram(fromRightAnchor),

+						peService.getLocationRelativeToDiagram(sourceRight.anchor));

+

+				if (bottomLength < rightLength) {

+					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceBottom.anchor, fromBottomAnchor);

+				} else {

+					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceRight.anchor, fromRightAnchor);

+				}

+			} else {

+				FixPointAnchor fromBottomAnchor = getCorrectAnchor(targetBoundaryAnchors,

+						peService.getLocationRelativeToDiagram(sourceBottom.anchor));

+				FixPointAnchor fromLeftAnchor = getCorrectAnchor(targetBoundaryAnchors,

+						peService.getLocationRelativeToDiagram(sourceLeft.anchor));

+

+				double bottomLength = getLength(peService.getLocationRelativeToDiagram(fromBottomAnchor),

+						peService.getLocationRelativeToDiagram(sourceBottom.anchor));

+				double leftLength = getLength(peService.getLocationRelativeToDiagram(fromLeftAnchor),

+						peService.getLocationRelativeToDiagram(sourceLeft.anchor));

+				if (bottomLength < leftLength) {

+					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceBottom.anchor, fromBottomAnchor);

+				} else {

+					return new Tuple<FixPointAnchor, FixPointAnchor>(sourceLeft.anchor, fromLeftAnchor);

+				}

+			}

+		}

+

+		// if source left is further than target right then use source left and target right

+		if (sRight) {

+			return new Tuple<FixPointAnchor, FixPointAnchor>(sourceLeft.anchor, targetRight.anchor);

+		}

+

+		// if source right is smaller than target left then use source right and target left

+		if (sLeft) {

+			return new Tuple<FixPointAnchor, FixPointAnchor>(sourceRight.anchor, targetLeft.anchor);

+		}

+

+		return new Tuple<FixPointAnchor, FixPointAnchor>(sourceTop.anchor, targetTop.anchor);

+	}

+

+	private static FixPointAnchor getCorrectAnchor(Map<AnchorLocation, BoundaryAnchor> targetBoundaryAnchors,

+			ILocation loc) {

+		return getCorrectAnchor(targetBoundaryAnchors, gaService.createPoint(loc.getX(), loc.getY()));

+	}

+

+	private static double getLength(ILocation start, ILocation end) {

+		return Math.sqrt(Math.pow(start.getX() - end.getX(), 2) + Math.pow(start.getY() - end.getY(), 2));

+	}

+

+	private static FixPointAnchor getCorrectAnchor(Map<AnchorLocation, BoundaryAnchor> boundaryAnchors, Point point) {

+

+		BoundaryAnchor bottom = boundaryAnchors.get(AnchorLocation.BOTTOM);

+		BoundaryAnchor top = boundaryAnchors.get(AnchorLocation.TOP);

+		BoundaryAnchor right = boundaryAnchors.get(AnchorLocation.RIGHT);

+		BoundaryAnchor left = boundaryAnchors.get(AnchorLocation.LEFT);

+

+		boolean pointLower = point.getY() > bottom.location.getY();

+		boolean pointHigher = point.getY() < top.location.getY();

+		boolean pointRight = point.getX() > right.location.getX();

+		boolean pointLeft = point.getX() < left.location.getX();

+

+		// Find the best connector.

+		if (pointLower) {

+			if (!pointLeft && !pointRight) {

+				// bendpoint is straight below the shape

+				return bottom.anchor;

+			} else if (pointLeft) {

+

+				int deltaX = left.location.getX() - point.getX();

+				int deltaY = point.getY() - bottom.location.getY();

+				if (deltaX > deltaY) {

+					return left.anchor;

+				} else {

+					return bottom.anchor;

+				}

+			} else {

+				int deltaX = point.getX() - right.location.getX();

+				int deltaY = point.getY() - bottom.location.getY();

+				if (deltaX > deltaY) {

+					return right.anchor;

+				} else {

+					return bottom.anchor;

+				}

+			}

+		}

+

+		if (pointHigher) {

+			if (!pointLeft && !pointRight) {

+				// bendpoint is straight above the shape

+				return top.anchor;

+			} else if (pointLeft) {

+				int deltaX = left.location.getX() - point.getX();

+				int deltaY = top.location.getY() - point.getY();

+				if (deltaX > deltaY) {

+					return left.anchor;

+				} else {

+					return top.anchor;

+				}

+			} else {

+				int deltaX = point.getX() - right.location.getX();

+				int deltaY = top.location.getY() - point.getY();

+				if (deltaX > deltaY) {

+					return right.anchor;

+				} else {

+					return top.anchor;

+				}

+			}

+

+		}

+

+		// if we reach here, then the point is neither above or below the shape and we only need to determine if we need

+		// to connect to the left or right part of the shape

+		if (pointRight) {

+			return right.anchor;

+		}

+

+		if (pointLeft) {

+			return left.anchor;

+		}

+

+		return top.anchor;

+	}

+

+	public static void reConnect(BPMNShape shape, Diagram diagram) {

+		try {

+			ModelHandler handler = ModelHandler.getInstance(diagram);

+			for (BPMNEdge bpmnEdge : handler.getAll(BPMNEdge.class)) {

+				DiagramElement sourceElement = bpmnEdge.getSourceElement();

+				DiagramElement targetElement = bpmnEdge.getTargetElement();

+				if (sourceElement != null && targetElement != null) {

+					boolean sourceMatches = sourceElement.getId().equals(shape.getId());

+					boolean targetMatches = targetElement.getId().equals(shape.getId());

+					if (sourceMatches || targetMatches) {

+						updateEdge(bpmnEdge, diagram);

+					}

+				}

+			}

+		} catch (Exception e) {

+			Activator.logError(e);

+		}

+	}

+

+	private static void updateEdge(BPMNEdge edge, Diagram diagram) {

+		List<PictogramElement> elements;

+		elements =  Graphiti.getLinkService().getPictogramElements(diagram, edge.getSourceElement());

+		if (elements.size()==0)

+			return;

+		ContainerShape source = (ContainerShape) elements.get(0);

+		

+		elements =  Graphiti.getLinkService().getPictogramElements(diagram, edge.getTargetElement());

+		if (elements.size()==0)

+			return;

+		ContainerShape target = (ContainerShape) elements.get(0);

+		

+		elements = Graphiti.getLinkService().getPictogramElements(diagram, edge);

+		if (elements.size()==0)

+			return;

+		Connection connection = (Connection) elements.get(0);

+		Tuple<FixPointAnchor, FixPointAnchor> anchors = getSourceAndTargetBoundaryAnchors(source, target, connection);

+

+		ILocation loc = peService.getLocationRelativeToDiagram(anchors.getFirst());

+		org.eclipse.dd.dc.Point p = edge.getWaypoint().get(0);

+		p.setX(loc.getX());

+		p.setY(loc.getY());

+

+		loc = peService.getLocationRelativeToDiagram(anchors.getSecond());

+		p = edge.getWaypoint().get(edge.getWaypoint().size() - 1);

+		p.setX(loc.getX());

+		p.setY(loc.getY());

+

+		relocateConnection(source.getAnchors(), anchors, target);

+		deleteEmptyAdHocAnchors(source);

+		deleteEmptyAdHocAnchors(target);

+	}

+

+	private static void relocateConnection(EList<Anchor> anchors, Tuple<FixPointAnchor, FixPointAnchor> newAnchors,

+			ContainerShape target) {

+

+		List<Connection> connectionsToBeUpdated = new ArrayList<Connection>();

+

+		for (Anchor anchor : anchors) {

+			if (!(anchor instanceof FixPointAnchor)) {

+				continue;

+			}

+

+			for (Connection connection : anchor.getOutgoingConnections()) {

+				if (connection.getEnd().eContainer().equals(target)) {

+					connectionsToBeUpdated.add(connection);

+				}

+			}

+		}

+

+		for (Connection c : connectionsToBeUpdated) {

+			c.setStart(newAnchors.getFirst());

+			c.setEnd(newAnchors.getSecond());

+		}

+	}

+

+	private static void deleteEmptyAdHocAnchors(Shape s) {

+		List<Integer> indexes = new ArrayList<Integer>();

+

+		for (int i = s.getAnchors().size()-1; i>=0; --i) {

+			Anchor a = s.getAnchors().get(i);

+			if (!(a instanceof FixPointAnchor)) {

+				continue;

+			}

+

+			if (peService.getProperty(a, BOUNDARY_FIXPOINT_ANCHOR) == null && a.getIncomingConnections().isEmpty()

+					&& a.getOutgoingConnections().isEmpty()) {

+				indexes.add(i);

+			}

+		}

+

+		for (int i : indexes) {

+			peService.deletePictogramElement(s.getAnchors().get(i));

+		}

+	}

+

+	public static void addFixedPointAnchors(Shape shape, GraphicsAlgorithm ga) {

+		IDimension size = gaService.calculateSize(ga);

+		int w = size.getWidth();

+		int h = size.getHeight();

+		AnchorUtil.createAnchor(shape, AnchorLocation.TOP, w / 2, 0);

+		AnchorUtil.createAnchor(shape, AnchorLocation.RIGHT, w, h / 2);

+		AnchorUtil.createAnchor(shape, AnchorLocation.BOTTOM, w / 2, h);

+		AnchorUtil.createAnchor(shape, AnchorLocation.LEFT, 0, h / 2);

+	}

+

+	public static void relocateFixPointAnchors(Shape shape, int w, int h) {

+		Map<AnchorLocation, BoundaryAnchor> anchors = AnchorUtil.getBoundaryAnchors(shape);

+

+		FixPointAnchor anchor = anchors.get(AnchorLocation.TOP).anchor;

+		anchor.setLocation(gaService.createPoint(w / 2, 0));

+

+		anchor = anchors.get(AnchorLocation.RIGHT).anchor;

+		anchor.setLocation(gaService.createPoint(w, h / 2));

+

+		anchor = anchors.get(AnchorLocation.BOTTOM).anchor;

+		anchor.setLocation(gaService.createPoint(w / 2, h));

+

+		anchor = anchors.get(AnchorLocation.LEFT).anchor;

+		anchor.setLocation(gaService.createPoint(0, h / 2));

+	}

 }
\ No newline at end of file
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FeatureSupport.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FeatureSupport.java
index 2116999..33816c7 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FeatureSupport.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FeatureSupport.java
@@ -12,6 +12,8 @@
  ******************************************************************************/
 package org.eclipse.bpmn2.modeler.core.utils;
 
+import static org.eclipse.bpmn2.modeler.core.features.activity.AbstractAddActivityFeature.ACTIVITY_DECORATOR;
+
 import java.awt.Dimension;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -38,6 +40,9 @@
 import org.eclipse.graphiti.mm.algorithms.Polyline;
 import org.eclipse.graphiti.mm.algorithms.Text;
 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.Diagram;
 import org.eclipse.graphiti.mm.pictograms.PictogramElement;
@@ -77,6 +82,41 @@
 		return lane.getChildLaneSet() == null || lane.getChildLaneSet().getLanes().isEmpty();
 	}
 
+	public static List<PictogramElement> getContainerChildren(ContainerShape container) {
+		List<PictogramElement> list = new ArrayList<PictogramElement>();
+		for (PictogramElement pe : container.getChildren()) {
+			String value = Graphiti.getPeService().getPropertyValue(pe, ACTIVITY_DECORATOR);
+			if (value!=null && "true".equals(value))
+				continue;
+			list.add(pe);
+		}
+		return list;
+	}
+
+	public static List<PictogramElement> getContainerDecorators(ContainerShape container) {
+		List<PictogramElement> list = new ArrayList<PictogramElement>();
+		for (PictogramElement pe : container.getChildren()) {
+			String value = Graphiti.getPeService().getPropertyValue(pe, ACTIVITY_DECORATOR);
+			if (value!=null && "true".equals(value))
+				list.add(pe);
+		}
+		return list;
+	}
+	
+	public static void setContainerChildrenVisible(ContainerShape container, boolean visible) {
+		for (PictogramElement pe : getContainerChildren(container)) {
+			pe.setVisible(visible);
+			if (pe instanceof AnchorContainer) {
+				AnchorContainer ac = (AnchorContainer)pe;
+				for (Anchor a : ac.getAnchors()) {
+					for (Connection c : a.getOutgoingConnections()) {
+						c.setVisible(visible);
+					}
+				}
+			}
+		}
+	}
+	
 	/**
 	 * Use ModelHandler.getInstance(diagram) instead
 	 * 
diff --git a/org.eclipse.bpmn2.modeler.ui/icons/16/collapse.png b/org.eclipse.bpmn2.modeler.ui/icons/16/collapse.png
new file mode 100644
index 0000000..a54ded9
--- /dev/null
+++ b/org.eclipse.bpmn2.modeler.ui/icons/16/collapse.png
Binary files differ
diff --git a/org.eclipse.bpmn2.modeler.ui/icons/16/expand.png b/org.eclipse.bpmn2.modeler.ui/icons/16/expand.png
new file mode 100644
index 0000000..0258923
--- /dev/null
+++ b/org.eclipse.bpmn2.modeler.ui/icons/16/expand.png
Binary files differ
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/ImageProvider.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/ImageProvider.java
index 10dff3d..c739d5a 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/ImageProvider.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/ImageProvider.java
@@ -142,6 +142,9 @@
 	public static final String IMG_20_MULTIPLE = PREFIX + "multipleeventdefinition" + dot20; // FIXME
 
 	public static final String IMG_16_ACTION = "default_action";
+	
+	public static final String IMG_16_EXPAND = PREFIX + "expand" + dot16;
+	public static final String IMG_16_COLLAPSE = PREFIX + "collapse" + dot16;
 
 	@Override
 	protected void addAvailableImages() {
@@ -197,5 +200,7 @@
 		addImageFilePath(IMG_20_MULTIPLE, ICONS_20 + "Multiple.png");
 
 		addImageFilePath(IMG_16_ACTION, ICONS_16 + "action.gif");
+		addImageFilePath(IMG_16_EXPAND, ICONS_16 + "expand.png");
+		addImageFilePath(IMG_16_COLLAPSE, ICONS_16 + "collapse.png");
 	}
 }
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/diagram/BPMNFeatureProvider.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/diagram/BPMNFeatureProvider.java
index 9a0512d..0aef007 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/diagram/BPMNFeatureProvider.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/diagram/BPMNFeatureProvider.java
@@ -15,6 +15,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.bpmn2.SubProcess;
+import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;
 import org.eclipse.bpmn2.modeler.core.features.ConnectionFeatureContainer;
 import org.eclipse.bpmn2.modeler.core.features.DefaultBpmnDeleteFeature;
 import org.eclipse.bpmn2.modeler.core.features.FeatureContainer;
@@ -24,6 +26,8 @@
 import org.eclipse.bpmn2.modeler.core.features.bendpoint.RemoveBendpointFeature;
 import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.AdHocSubProcessFeatureContainer;
 import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.CallActivityFeatureContainer;
+import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.SubProcessCollapseFeature;
+import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.SubProcessExpandFeature;
 import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.SubProcessFeatureContainer;
 import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.TransactionFeatureContainer;
 import org.eclipse.bpmn2.modeler.ui.features.activity.task.BusinessRuleTaskFeatureContainer;
@@ -92,6 +96,7 @@
 import org.eclipse.graphiti.features.IUpdateFeature;
 import org.eclipse.graphiti.features.context.IAddBendpointContext;
 import org.eclipse.graphiti.features.context.IAddContext;
+import org.eclipse.graphiti.features.context.ICustomContext;
 import org.eclipse.graphiti.features.context.IDeleteContext;
 import org.eclipse.graphiti.features.context.IDirectEditingContext;
 import org.eclipse.graphiti.features.context.ILayoutContext;
@@ -101,8 +106,8 @@
 import org.eclipse.graphiti.features.context.IRemoveBendpointContext;
 import org.eclipse.graphiti.features.context.IResizeShapeContext;
 import org.eclipse.graphiti.features.context.IUpdateContext;
+import org.eclipse.graphiti.features.custom.ICustomFeature;
 import org.eclipse.graphiti.mm.pictograms.PictogramElement;
-import org.eclipse.graphiti.services.Graphiti;
 import org.eclipse.graphiti.ui.features.DefaultFeatureProvider;
 
 /**
@@ -422,4 +427,17 @@
 		return new DefaultBpmnDeleteFeature(this);
 	}
 
+	@Override
+	public ICustomFeature[] getCustomFeatures(ICustomContext context) {
+		PictogramElement[] elements = context.getPictogramElements();
+		for (PictogramElement pe : elements) {
+			if (BusinessObjectUtil.containsElementOfType(pe, SubProcess.class)) {
+				return new ICustomFeature[] {
+						new SubProcessExpandFeature(this),
+						new SubProcessCollapseFeature(this)
+				};
+			}
+		}
+		return new ICustomFeature[] {};
+	}
 }
\ No newline at end of file
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/diagram/BpmnToolBehaviourFeature.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/diagram/BpmnToolBehaviourFeature.java
index b0ccbde..48bc9cf 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/diagram/BpmnToolBehaviourFeature.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/diagram/BpmnToolBehaviourFeature.java
@@ -1,330 +1,331 @@
-/******************************************************************************* 
- * Copyright (c) 2011 Red Hat, Inc. 
- *  All rights reserved. 
- * This program is 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: 
- * Red Hat, Inc. - initial API and implementation 
- *
- * @author Innar Made
- ******************************************************************************/
-package org.eclipse.bpmn2.modeler.ui.diagram;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.eclipse.bpmn2.modeler.core.Activator;
-import org.eclipse.bpmn2.modeler.core.features.activity.ActivitySelectionBehavior;
-import org.eclipse.bpmn2.modeler.core.features.event.EventSelectionBehavior;
-import org.eclipse.bpmn2.modeler.core.preferences.ToolEnablementPreferences;
-import org.eclipse.bpmn2.modeler.core.runtime.CustomTaskDescriptor;
-import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime;
-import org.eclipse.bpmn2.modeler.ui.FeatureMap;
-import org.eclipse.bpmn2.modeler.ui.ImageProvider;
-import org.eclipse.bpmn2.modeler.ui.editor.BPMN2Editor;
-import org.eclipse.bpmn2.modeler.ui.features.activity.task.CustomTaskFeatureContainer;
-import org.eclipse.bpmn2.modeler.ui.features.choreography.ChoreographySelectionBehavior;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.graphiti.dt.IDiagramTypeProvider;
-import org.eclipse.graphiti.features.FeatureCheckerAdapter;
-import org.eclipse.graphiti.features.ICreateConnectionFeature;
-import org.eclipse.graphiti.features.ICreateFeature;
-import org.eclipse.graphiti.features.IFeature;
-import org.eclipse.graphiti.features.IFeatureChecker;
-import org.eclipse.graphiti.features.IFeatureCheckerHolder;
-import org.eclipse.graphiti.features.IFeatureProvider;
-import org.eclipse.graphiti.features.context.IContext;
-import org.eclipse.graphiti.features.context.IPictogramElementContext;
-import org.eclipse.graphiti.features.context.impl.CreateConnectionContext;
-import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
-import org.eclipse.graphiti.mm.pictograms.Anchor;
-import org.eclipse.graphiti.mm.pictograms.AnchorContainer;
-import org.eclipse.graphiti.mm.pictograms.PictogramElement;
-import org.eclipse.graphiti.palette.IPaletteCompartmentEntry;
-import org.eclipse.graphiti.palette.impl.ConnectionCreationToolEntry;
-import org.eclipse.graphiti.palette.impl.ObjectCreationToolEntry;
-import org.eclipse.graphiti.palette.impl.PaletteCompartmentEntry;
-import org.eclipse.graphiti.services.Graphiti;
-import org.eclipse.graphiti.tb.ContextButtonEntry;
-import org.eclipse.graphiti.tb.DefaultToolBehaviorProvider;
-import org.eclipse.graphiti.tb.IContextButtonPadData;
-
-public class BpmnToolBehaviourFeature extends DefaultToolBehaviorProvider implements IFeatureCheckerHolder {
-
-	public BpmnToolBehaviourFeature(IDiagramTypeProvider diagramTypeProvider) {
-		super(diagramTypeProvider);
-	}
-
-	@Override
-	public IPaletteCompartmentEntry[] getPalette() {
-
-		EList<Resource> resources = getDiagramTypeProvider().getDiagram().eResource().getResourceSet().getResources();
-		IProject project = null;
-		for (Resource resource : resources) {
-			if (resource.getURI().segmentCount() > 1) {
-				String projectName = resource.getURI().segment(1);
-				project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
-				if (project != null) {
-					break;
-				}
-			}
-		}
-
-		ToolEnablementPreferences pref = ToolEnablementPreferences.getPreferences(project);
-
-		List<IPaletteCompartmentEntry> ret = new ArrayList<IPaletteCompartmentEntry>();
-
-		// add compartments from super class
-
-		IFeatureProvider featureProvider = getFeatureProvider();
-
-		createConnectors(pref, ret, featureProvider);
-
-		createEventsCompartments(pref, ret, featureProvider);
-		createTasksCompartments(pref, ret, featureProvider);
-		createGatewaysCompartments(pref, ret, featureProvider);
-		createEventDefinitionsCompartments(pref, ret, featureProvider);
-		createDataCompartments(pref, ret, featureProvider);
-		createOtherCompartments(pref, ret, featureProvider);
-
-		createCustomTasks(ret, featureProvider);
-
-		return ret.toArray(new IPaletteCompartmentEntry[ret.size()]);
-	}
-
-	private void createEventsCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,
-			IFeatureProvider featureProvider) {
-		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Events", null);
-		ret.add(compartmentEntry);
-
-		createEntries(pref, FeatureMap.EVENTS, compartmentEntry, featureProvider);
-	}
-
-	private void createOtherCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,
-			IFeatureProvider featureProvider) {
-		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Other", null);
-		compartmentEntry.setInitiallyOpen(false);
-		ret.add(compartmentEntry);
-
-		createEntries(pref, FeatureMap.OTHER, compartmentEntry, featureProvider);
-
-	}
-
-	private void createDataCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,
-			IFeatureProvider featureProvider) {
-		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Data Items", null);
-		compartmentEntry.setInitiallyOpen(false);
-		ret.add(compartmentEntry);
-
-		createEntries(pref, FeatureMap.DATA, compartmentEntry, featureProvider);
-
-	}
-
-	private void createEventDefinitionsCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,
-			IFeatureProvider featureProvider) {
-		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Event Definitions", null);
-		compartmentEntry.setInitiallyOpen(false);
-		ret.add(compartmentEntry);
-
-		createEntries(pref, FeatureMap.EVENT_DEFINITIONS, compartmentEntry, featureProvider);
-
-	}
-
-	private void createGatewaysCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,
-			IFeatureProvider featureProvider) {
-		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Gateways", null);
-		ret.add(compartmentEntry);
-
-		createEntries(pref, FeatureMap.GATEWAYS, compartmentEntry, featureProvider);
-
-	}
-
-	private void createTasksCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,
-			IFeatureProvider featureProvider) {
-		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Tasks", null);
-		ret.add(compartmentEntry);
-
-		createEntries(pref, FeatureMap.TASKS, compartmentEntry, featureProvider);
-
-	}
-
-	private void createConnectors(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,
-			IFeatureProvider featureProvider) {
-		PaletteCompartmentEntry compartmentEntry;
-		compartmentEntry = new PaletteCompartmentEntry("Connectors", null);
-		ret.add(compartmentEntry);
-		// add all create-connection-features to the new stack-entry
-		ICreateConnectionFeature[] createConnectionFeatures = featureProvider.getCreateConnectionFeatures();
-		for (ICreateConnectionFeature cf : createConnectionFeatures) {
-			if (pref.isEnabled(FeatureMap.getElement(cf))) {
-				ConnectionCreationToolEntry connectionCreationToolEntry = new ConnectionCreationToolEntry(
-						cf.getCreateName(), cf.getCreateDescription(), cf.getCreateImageId(),
-						cf.getCreateLargeImageId());
-				connectionCreationToolEntry.addCreateConnectionFeature(cf);
-				compartmentEntry.addToolEntry(connectionCreationToolEntry);
-			}
-		}
-	}
-
-	private void createEntries(ToolEnablementPreferences pref, List<Class<? extends IFeature>> neededEntries,
-			PaletteCompartmentEntry compartmentEntry, IFeatureProvider featureProvider) {
-		List<ICreateFeature> tools = Arrays.asList(featureProvider.getCreateFeatures());
-
-		for (ICreateFeature cf : tools) {
-			EClass feature = FeatureMap.getElement(cf);
-			if (pref.isEnabled(feature) && neededEntries.contains(cf.getClass())) {
-				ObjectCreationToolEntry objectCreationToolEntry = new ObjectCreationToolEntry(cf.getCreateName(),
-						cf.getCreateDescription(), cf.getCreateImageId(), cf.getCreateLargeImageId(), cf);
-				compartmentEntry.addToolEntry(objectCreationToolEntry);
-			}
-		}
-	}
-
-	private void createCustomTasks(List<IPaletteCompartmentEntry> ret, IFeatureProvider featureProvider) {
-		PaletteCompartmentEntry compartmentEntry = null;
-		BPMN2Editor editor = (BPMN2Editor) getDiagramTypeProvider().getDiagramEditor();
-		TargetRuntime rt = editor.getTargetRuntime();
-		
-		try {
-			for (CustomTaskDescriptor tc : rt.getCustomTasks()) {
-				
-				CustomTaskFeatureContainer container = (CustomTaskFeatureContainer)tc.getCreateFeature();
-
-				container.setId(featureProvider, tc.getId());
-				ICreateFeature cf = container.getCreateFeature(featureProvider);
-				ObjectCreationToolEntry objectCreationToolEntry = new ObjectCreationToolEntry(tc.getName(),
-						cf.getCreateDescription(), cf.getCreateImageId(), cf.getCreateLargeImageId(), cf);
-				
-				if (compartmentEntry==null) {
-					compartmentEntry = new PaletteCompartmentEntry("Custom Task", null);
-					compartmentEntry.setInitiallyOpen(false);
-					ret.add(compartmentEntry);
-				}
-				
-				compartmentEntry.addToolEntry(objectCreationToolEntry);
-
-			}
-		} catch (Exception ex) {
-			Activator.logError(ex);
-		}
-	}
-
-	@Override
-	public IFeatureChecker getFeatureChecker() {
-		return new FeatureCheckerAdapter(false) {
-			@Override
-			public boolean allowAdd(IContext context) {
-				return super.allowAdd(context);
-			}
-
-			@Override
-			public boolean allowCreate() {
-				return super.allowCreate();
-			}
-		};
-	}
-
-	@Override
-	public GraphicsAlgorithm[] getClickArea(PictogramElement pe) {
-		if (ActivitySelectionBehavior.canApplyTo(pe)) {
-			return ActivitySelectionBehavior.getClickArea(pe);
-		} else if (EventSelectionBehavior.canApplyTo(pe)) {
-			return EventSelectionBehavior.getClickArea(pe);
-		} else if (ChoreographySelectionBehavior.canApplyTo(pe)) {
-			return ChoreographySelectionBehavior.getClickArea(pe);
-		}
-		return super.getClickArea(pe);
-	}
-
-	@Override
-	public GraphicsAlgorithm getSelectionBorder(PictogramElement pe) {
-		if (ActivitySelectionBehavior.canApplyTo(pe)) {
-			return ActivitySelectionBehavior.getSelectionBorder(pe);
-		} else if (EventSelectionBehavior.canApplyTo(pe)) {
-			return EventSelectionBehavior.getSelectionBorder(pe);
-		} else if (ChoreographySelectionBehavior.canApplyTo(pe)) {
-			return ChoreographySelectionBehavior.getSelectionBorder(pe);
-		}
-		return super.getSelectionBorder(pe);
-	}
-
-	@Override
-	public IContextButtonPadData getContextButtonPad(IPictogramElementContext context) {
-		IContextButtonPadData data = super.getContextButtonPad(context);
-		PictogramElement pe = context.getPictogramElement();
-
-		// 1. set the generic context buttons
-		// note, that we do not add 'remove' (just as an example)
-		setGenericContextButtons(data, pe, CONTEXT_BUTTON_DELETE | CONTEXT_BUTTON_UPDATE);
-
-		// 2. set the expand & collapse buttons
-		// TODO: implement this as a resizable container shape within the current editor instead of as a drilldown feature
-//		CustomContext cc = new CustomContext(new PictogramElement[] { pe });
-//		ICustomFeature[] cf = getFeatureProvider().getCustomFeatures(cc);
-//		for (int i = 0; i < cf.length; i++) {
-//			ICustomFeature iCustomFeature = cf[i];
-//			ContextButtonEntry button = new ContextButtonEntry(iCustomFeature, cc);
-//			button.setText(iCustomFeature.getName()); //$NON-NLS-1$
-//			button.setIconId(iCustomFeature.getImageId());
-//			button.setDescription(iCustomFeature.getDescription());
-//			
-//			data.getDomainSpecificContextButtons().add(button);
-//		}
-
-		// 3. add one domain specific context-button, which offers all
-		// available connection-features as drag&drop features...
-
-		// 3.a. create new CreateConnectionContext
-		CreateConnectionContext ccc = new CreateConnectionContext();
-		ccc.setSourcePictogramElement(pe);
-		Anchor anchor = null;
-		if (pe instanceof Anchor) {
-			anchor = (Anchor) pe;
-		} else if (pe instanceof AnchorContainer) {
-			// assume, that our shapes always have chopbox anchors
-			anchor = Graphiti.getPeService().getChopboxAnchor((AnchorContainer) pe);
-		}
-		ccc.setSourceAnchor(anchor);
-
-		// 3.b. create context button and add "Create Connections" feature
-		ICreateConnectionFeature[] features = getFeatureProvider().getCreateConnectionFeatures();
-		ContextButtonEntry button = new ContextButtonEntry(null, context);
-		button.setText("Create Connection"); //$NON-NLS-1$
-		String description = null;
-		ArrayList<String> names = new ArrayList<String>();
-		button.setIconId(ImageProvider.IMG_16_SEQUENCE_FLOW);
-		for (ICreateConnectionFeature feature : features) {
-			if (feature.isAvailable(ccc) && feature.canStartConnection(ccc)) {
-				button.addDragAndDropFeature(feature);
-				names.add(feature.getCreateName());
-			}
-		}
-		
-		// 3.c. build a reasonable description for the context button action 
-		for (int i=0; i<names.size(); ++i) {
-			if (description==null)
-				description = "Click and drag to create a\n";
-			description += names.get(i);
-			if (i+2 == names.size())
-				description += " or ";
-			else if (i+1 < names.size())
-				description += ", ";
-		}
-		button.setDescription(description);
-
-		// 3.d. add context button, but only if it contains at least one feature
-		if (button.getDragAndDropFeatures().size() > 0) {
-			data.getDomainSpecificContextButtons().add(button);
-		}
-
-		return data;
-	}
-
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Innar Made

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.ui.diagram;

+

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.List;

+

+import org.eclipse.bpmn2.modeler.core.Activator;

+import org.eclipse.bpmn2.modeler.core.features.activity.ActivitySelectionBehavior;

+import org.eclipse.bpmn2.modeler.core.features.event.EventSelectionBehavior;

+import org.eclipse.bpmn2.modeler.core.preferences.ToolEnablementPreferences;

+import org.eclipse.bpmn2.modeler.core.runtime.CustomTaskDescriptor;

+import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime;

+import org.eclipse.bpmn2.modeler.ui.FeatureMap;

+import org.eclipse.bpmn2.modeler.ui.ImageProvider;

+import org.eclipse.bpmn2.modeler.ui.editor.BPMN2Editor;

+import org.eclipse.bpmn2.modeler.ui.features.activity.task.CustomTaskFeatureContainer;

+import org.eclipse.bpmn2.modeler.ui.features.choreography.ChoreographySelectionBehavior;

+import org.eclipse.core.resources.IProject;

+import org.eclipse.core.resources.ResourcesPlugin;

+import org.eclipse.emf.common.util.EList;

+import org.eclipse.emf.ecore.EClass;

+import org.eclipse.emf.ecore.resource.Resource;

+import org.eclipse.graphiti.dt.IDiagramTypeProvider;

+import org.eclipse.graphiti.features.FeatureCheckerAdapter;

+import org.eclipse.graphiti.features.ICreateConnectionFeature;

+import org.eclipse.graphiti.features.ICreateFeature;

+import org.eclipse.graphiti.features.IFeature;

+import org.eclipse.graphiti.features.IFeatureChecker;

+import org.eclipse.graphiti.features.IFeatureCheckerHolder;

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.context.IContext;

+import org.eclipse.graphiti.features.context.IPictogramElementContext;

+import org.eclipse.graphiti.features.context.impl.CreateConnectionContext;

+import org.eclipse.graphiti.features.context.impl.CustomContext;

+import org.eclipse.graphiti.features.custom.ICustomFeature;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.pictograms.Anchor;

+import org.eclipse.graphiti.mm.pictograms.AnchorContainer;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+import org.eclipse.graphiti.palette.IPaletteCompartmentEntry;

+import org.eclipse.graphiti.palette.impl.ConnectionCreationToolEntry;

+import org.eclipse.graphiti.palette.impl.ObjectCreationToolEntry;

+import org.eclipse.graphiti.palette.impl.PaletteCompartmentEntry;

+import org.eclipse.graphiti.services.Graphiti;

+import org.eclipse.graphiti.tb.ContextButtonEntry;

+import org.eclipse.graphiti.tb.DefaultToolBehaviorProvider;

+import org.eclipse.graphiti.tb.IContextButtonPadData;

+

+public class BpmnToolBehaviourFeature extends DefaultToolBehaviorProvider implements IFeatureCheckerHolder {

+

+	public BpmnToolBehaviourFeature(IDiagramTypeProvider diagramTypeProvider) {

+		super(diagramTypeProvider);

+	}

+

+	@Override

+	public IPaletteCompartmentEntry[] getPalette() {

+

+		EList<Resource> resources = getDiagramTypeProvider().getDiagram().eResource().getResourceSet().getResources();

+		IProject project = null;

+		for (Resource resource : resources) {

+			if (resource.getURI().segmentCount() > 1) {

+				String projectName = resource.getURI().segment(1);

+				project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);

+				if (project != null) {

+					break;

+				}

+			}

+		}

+

+		ToolEnablementPreferences pref = ToolEnablementPreferences.getPreferences(project);

+

+		List<IPaletteCompartmentEntry> ret = new ArrayList<IPaletteCompartmentEntry>();

+

+		// add compartments from super class

+

+		IFeatureProvider featureProvider = getFeatureProvider();

+

+		createConnectors(pref, ret, featureProvider);

+

+		createEventsCompartments(pref, ret, featureProvider);

+		createTasksCompartments(pref, ret, featureProvider);

+		createGatewaysCompartments(pref, ret, featureProvider);

+		createEventDefinitionsCompartments(pref, ret, featureProvider);

+		createDataCompartments(pref, ret, featureProvider);

+		createOtherCompartments(pref, ret, featureProvider);

+

+		createCustomTasks(ret, featureProvider);

+

+		return ret.toArray(new IPaletteCompartmentEntry[ret.size()]);

+	}

+

+	private void createEventsCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,

+			IFeatureProvider featureProvider) {

+		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Events", null);

+		ret.add(compartmentEntry);

+

+		createEntries(pref, FeatureMap.EVENTS, compartmentEntry, featureProvider);

+	}

+

+	private void createOtherCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,

+			IFeatureProvider featureProvider) {

+		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Other", null);

+		compartmentEntry.setInitiallyOpen(false);

+		ret.add(compartmentEntry);

+

+		createEntries(pref, FeatureMap.OTHER, compartmentEntry, featureProvider);

+

+	}

+

+	private void createDataCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,

+			IFeatureProvider featureProvider) {

+		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Data Items", null);

+		compartmentEntry.setInitiallyOpen(false);

+		ret.add(compartmentEntry);

+

+		createEntries(pref, FeatureMap.DATA, compartmentEntry, featureProvider);

+

+	}

+

+	private void createEventDefinitionsCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,

+			IFeatureProvider featureProvider) {

+		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Event Definitions", null);

+		compartmentEntry.setInitiallyOpen(false);

+		ret.add(compartmentEntry);

+

+		createEntries(pref, FeatureMap.EVENT_DEFINITIONS, compartmentEntry, featureProvider);

+

+	}

+

+	private void createGatewaysCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,

+			IFeatureProvider featureProvider) {

+		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Gateways", null);

+		ret.add(compartmentEntry);

+

+		createEntries(pref, FeatureMap.GATEWAYS, compartmentEntry, featureProvider);

+

+	}

+

+	private void createTasksCompartments(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,

+			IFeatureProvider featureProvider) {

+		PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Tasks", null);

+		ret.add(compartmentEntry);

+

+		createEntries(pref, FeatureMap.TASKS, compartmentEntry, featureProvider);

+

+	}

+

+	private void createConnectors(ToolEnablementPreferences pref, List<IPaletteCompartmentEntry> ret,

+			IFeatureProvider featureProvider) {

+		PaletteCompartmentEntry compartmentEntry;

+		compartmentEntry = new PaletteCompartmentEntry("Connectors", null);

+		ret.add(compartmentEntry);

+		// add all create-connection-features to the new stack-entry

+		ICreateConnectionFeature[] createConnectionFeatures = featureProvider.getCreateConnectionFeatures();

+		for (ICreateConnectionFeature cf : createConnectionFeatures) {

+			if (pref.isEnabled(FeatureMap.getElement(cf))) {

+				ConnectionCreationToolEntry connectionCreationToolEntry = new ConnectionCreationToolEntry(

+						cf.getCreateName(), cf.getCreateDescription(), cf.getCreateImageId(),

+						cf.getCreateLargeImageId());

+				connectionCreationToolEntry.addCreateConnectionFeature(cf);

+				compartmentEntry.addToolEntry(connectionCreationToolEntry);

+			}

+		}

+	}

+

+	private void createEntries(ToolEnablementPreferences pref, List<Class<? extends IFeature>> neededEntries,

+			PaletteCompartmentEntry compartmentEntry, IFeatureProvider featureProvider) {

+		List<ICreateFeature> tools = Arrays.asList(featureProvider.getCreateFeatures());

+

+		for (ICreateFeature cf : tools) {

+			EClass feature = FeatureMap.getElement(cf);

+			if (pref.isEnabled(feature) && neededEntries.contains(cf.getClass())) {

+				ObjectCreationToolEntry objectCreationToolEntry = new ObjectCreationToolEntry(cf.getCreateName(),

+						cf.getCreateDescription(), cf.getCreateImageId(), cf.getCreateLargeImageId(), cf);

+				compartmentEntry.addToolEntry(objectCreationToolEntry);

+			}

+		}

+	}

+

+	private void createCustomTasks(List<IPaletteCompartmentEntry> ret, IFeatureProvider featureProvider) {

+		PaletteCompartmentEntry compartmentEntry = null;

+		BPMN2Editor editor = (BPMN2Editor) getDiagramTypeProvider().getDiagramEditor();

+		TargetRuntime rt = editor.getTargetRuntime();

+		

+		try {

+			for (CustomTaskDescriptor tc : rt.getCustomTasks()) {

+				

+				CustomTaskFeatureContainer container = (CustomTaskFeatureContainer)tc.getCreateFeature();

+

+				container.setId(featureProvider, tc.getId());

+				ICreateFeature cf = container.getCreateFeature(featureProvider);

+				ObjectCreationToolEntry objectCreationToolEntry = new ObjectCreationToolEntry(tc.getName(),

+						cf.getCreateDescription(), cf.getCreateImageId(), cf.getCreateLargeImageId(), cf);

+				

+				if (compartmentEntry==null) {

+					compartmentEntry = new PaletteCompartmentEntry("Custom Task", null);

+					compartmentEntry.setInitiallyOpen(false);

+					ret.add(compartmentEntry);

+				}

+				

+				compartmentEntry.addToolEntry(objectCreationToolEntry);

+

+			}

+		} catch (Exception ex) {

+			Activator.logError(ex);

+		}

+	}

+

+	@Override

+	public IFeatureChecker getFeatureChecker() {

+		return new FeatureCheckerAdapter(false) {

+			@Override

+			public boolean allowAdd(IContext context) {

+				return super.allowAdd(context);

+			}

+

+			@Override

+			public boolean allowCreate() {

+				return super.allowCreate();

+			}

+		};

+	}

+

+	@Override

+	public GraphicsAlgorithm[] getClickArea(PictogramElement pe) {

+		if (ActivitySelectionBehavior.canApplyTo(pe)) {

+			return ActivitySelectionBehavior.getClickArea(pe);

+		} else if (EventSelectionBehavior.canApplyTo(pe)) {

+			return EventSelectionBehavior.getClickArea(pe);

+		} else if (ChoreographySelectionBehavior.canApplyTo(pe)) {

+			return ChoreographySelectionBehavior.getClickArea(pe);

+		}

+		return super.getClickArea(pe);

+	}

+

+	@Override

+	public GraphicsAlgorithm getSelectionBorder(PictogramElement pe) {

+		if (ActivitySelectionBehavior.canApplyTo(pe)) {

+			return ActivitySelectionBehavior.getSelectionBorder(pe);

+		} else if (EventSelectionBehavior.canApplyTo(pe)) {

+			return EventSelectionBehavior.getSelectionBorder(pe);

+		} else if (ChoreographySelectionBehavior.canApplyTo(pe)) {

+			return ChoreographySelectionBehavior.getSelectionBorder(pe);

+		}

+		return super.getSelectionBorder(pe);

+	}

+

+	@Override

+	public IContextButtonPadData getContextButtonPad(IPictogramElementContext context) {

+		IContextButtonPadData data = super.getContextButtonPad(context);

+		PictogramElement pe = context.getPictogramElement();

+

+		// 1. set the generic context buttons

+		// note, that we do not add 'remove' (just as an example)

+		setGenericContextButtons(data, pe, CONTEXT_BUTTON_DELETE | CONTEXT_BUTTON_UPDATE);

+

+		// 2. set the expand & collapse buttons

+		CustomContext cc = new CustomContext(new PictogramElement[] { pe });

+		ICustomFeature[] cf = getFeatureProvider().getCustomFeatures(cc);

+		for (int i = 0; i < cf.length; i++) {

+			ICustomFeature iCustomFeature = cf[i];

+			ContextButtonEntry button = new ContextButtonEntry(iCustomFeature, cc);

+			button.setText(iCustomFeature.getName()); //$NON-NLS-1$

+			button.setIconId(iCustomFeature.getImageId());

+			button.setDescription(iCustomFeature.getDescription());

+			

+			data.getDomainSpecificContextButtons().add(button);

+		}

+

+		// 3. add one domain specific context-button, which offers all

+		// available connection-features as drag&drop features...

+

+		// 3.a. create new CreateConnectionContext

+		CreateConnectionContext ccc = new CreateConnectionContext();

+		ccc.setSourcePictogramElement(pe);

+		Anchor anchor = null;

+		if (pe instanceof Anchor) {

+			anchor = (Anchor) pe;

+		} else if (pe instanceof AnchorContainer) {

+			// assume, that our shapes always have chopbox anchors

+			anchor = Graphiti.getPeService().getChopboxAnchor((AnchorContainer) pe);

+		}

+		ccc.setSourceAnchor(anchor);

+

+		// 3.b. create context button and add "Create Connections" feature

+		ICreateConnectionFeature[] features = getFeatureProvider().getCreateConnectionFeatures();

+		ContextButtonEntry button = new ContextButtonEntry(null, context);

+		button.setText("Create Connection"); //$NON-NLS-1$

+		String description = null;

+		ArrayList<String> names = new ArrayList<String>();

+		button.setIconId(ImageProvider.IMG_16_SEQUENCE_FLOW);

+		for (ICreateConnectionFeature feature : features) {

+			if (feature.isAvailable(ccc) && feature.canStartConnection(ccc)) {

+				button.addDragAndDropFeature(feature);

+				names.add(feature.getCreateName());

+			}

+		}

+		

+		// 3.c. build a reasonable description for the context button action 

+		for (int i=0; i<names.size(); ++i) {

+			if (description==null)

+				description = "Click and drag to create a\n";

+			description += names.get(i);

+			if (i+2 == names.size())

+				description += " or ";

+			else if (i+1 < names.size())

+				description += ", ";

+		}

+		button.setDescription(description);

+

+		// 3.d. add context button, but only if it contains at least one feature

+		if (button.getDragAndDropFeatures().size() > 0) {

+			data.getDomainSpecificContextButtons().add(button);

+		}

+

+		return data;

+	}

+

 }
\ No newline at end of file
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2Editor.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2Editor.java
index e433406..8203f7c 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2Editor.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2Editor.java
@@ -1,326 +1,333 @@
-/******************************************************************************* 
- * Copyright (c) 2011 Red Hat, Inc. 
- *  All rights reserved. 
- * This program is 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: 
- * Red Hat, Inc. - initial API and implementation 
- *
- * @author Innar Made
- ******************************************************************************/
-package org.eclipse.bpmn2.modeler.ui.editor;
-
-import java.io.IOException;
-
-import org.eclipse.bpmn2.modeler.core.ModelHandler;
-import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;
-import org.eclipse.bpmn2.modeler.core.ProxyURIConverterImplExtension;
-import org.eclipse.bpmn2.modeler.core.di.DIImport;
-import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerResourceImpl;
-import org.eclipse.bpmn2.modeler.core.preferences.Bpmn2Preferences;
-import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime;
-import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
-import org.eclipse.bpmn2.modeler.ui.Activator;
-import org.eclipse.bpmn2.modeler.ui.BPMN2ContentDescriber;
-import org.eclipse.bpmn2.modeler.ui.preferences.Bpmn2PropertyPage;
-import org.eclipse.bpmn2.modeler.ui.util.ErrorUtils;
-import org.eclipse.bpmn2.modeler.ui.wizards.BPMN2DiagramCreator;
-import org.eclipse.bpmn2.util.Bpmn2ResourceImpl;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.emf.common.command.BasicCommandStack;
-import org.eclipse.emf.common.util.BasicDiagnostic;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-import org.eclipse.emf.transaction.ExceptionHandler;
-import org.eclipse.emf.transaction.RecordingCommand;
-import org.eclipse.emf.transaction.TransactionalCommandStack;
-import org.eclipse.emf.transaction.TransactionalEditingDomain;
-import org.eclipse.emf.transaction.TransactionalEditingDomain.Lifecycle;
-import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;
-import org.eclipse.graphiti.tb.IToolBehaviorProvider;
-import org.eclipse.graphiti.ui.editor.DiagramEditor;
-import org.eclipse.graphiti.ui.editor.DiagramEditorInput;
-import org.eclipse.jface.action.IStatusLineManager;
-import org.eclipse.ui.IActionBars;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IEditorReference;
-import org.eclipse.ui.IEditorSite;
-import org.eclipse.ui.IFileEditorInput;
-import org.eclipse.ui.IViewSite;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchListener;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.IWorkbenchPartSite;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.application.WorkbenchAdvisor;
-
-/**
- * 
- */
-@SuppressWarnings("restriction")
-public class BPMN2Editor extends DiagramEditor {
-
-	public static final String EDITOR_ID = "org.eclipse.bpmn2.modeler.ui.bpmn2editor";
-	public static final String CONTRIBUTOR_ID = "org.eclipse.bpmn2.modeler.ui.PropertyContributor";
-
-	private ModelHandler modelHandler;
-	private URI modelUri;
-	private URI diagramUri;
-
-	private IFile modelFile;
-	private IFile diagramFile;
-	
-	private IWorkbenchListener workbenchListener;
-	private boolean workbenchShutdown = false;
-	
-	private BPMN2EditingDomainListener editingDomainListener;
-	
-	private Bpmn2Preferences preferences;
-	private TargetRuntime targetRuntime;
-
-	@Override
-	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
-		
-		try {
-			if (input instanceof IFileEditorInput) {
-				modelFile = ((IFileEditorInput) input).getFile();
-				loadPreferences(modelFile.getProject());
-
-				input = createNewDiagramEditorInput();
-
-			} else if (input instanceof DiagramEditorInput) {
-				getModelPathFromInput((DiagramEditorInput) input);
-				loadPreferences(modelFile.getProject());
-
-				// This was incorrectly constructed input, we ditch the old one and make a new and clean one instead
-				input = createNewDiagramEditorInput();
-			}
-		} catch (CoreException e) {
-			Activator.showErrorWithLogging(e);
-		}
-		
-		// add a listener so we get notified if the workbench is shutting down.
-		// in this case we don't want to delete the temp file!
-		addWorkbenchListener();
-		
-		super.init(site, input);
-	}
-
-	public Bpmn2Preferences getPreferences() {
-		if (preferences==null) {
-			assert(modelFile!=null);
-			IProject project = modelFile.getProject();
-			loadPreferences(project);
-		}
-		return preferences;
-	}
-	
-	private void loadPreferences(IProject project) {
-		preferences = new Bpmn2Preferences(project);
-		preferences.load();
-	}
-
-	/**
-	 * ID for tabbed property sheets.
-	 * 
-	 * @return the contributor id
-	 */
-	@Override
-	public String getContributorId() {
-		return CONTRIBUTOR_ID;
-	}
-
-	public TargetRuntime getTargetRuntime() {
-		if (targetRuntime==null)
-			targetRuntime = getPreferences().getRuntime(modelFile);
-		return targetRuntime;
-	}
-	
-	private void getModelPathFromInput(DiagramEditorInput input) {
-		URI uri = input.getDiagram().eResource().getURI();
-		String uriString = uri.trimFragment().toPlatformString(true);
-		modelFile = BPMN2DiagramCreator.getModelFile(new Path(uriString));
-	}
-
-	/**
-	 * Beware, creates a new input and changes this editor!
-	 */
-	private IEditorInput createNewDiagramEditorInput() throws CoreException {
-		IPath fullPath = modelFile.getFullPath();
-		modelUri = URI.createPlatformResourceURI(fullPath.toString(), true);
-
-		IFolder folder = BPMN2DiagramCreator.getTempFolder(fullPath);
-		diagramFile = BPMN2DiagramCreator.getTempFile(fullPath,folder);
-
-		// Create new temporary diagram file
-		BPMN2DiagramCreator creator = new BPMN2DiagramCreator();
-		creator.setDiagramFile(diagramFile);
-
-		IEditorInput input = creator.createDiagram(false);
-		diagramUri = creator.getUri();
-
-		return input;
-	}
-
-	@Override
-	public void doSave(IProgressMonitor monitor) {
-		modelHandler.save();
-		((BasicCommandStack) getEditingDomain().getCommandStack()).saveIsDone();
-	}
-
-	@Override
-	protected void setInput(IEditorInput input) {
-		super.setInput(input);
-		
-		// Hook a transaction exception handler so we can get diagnostics about EMF validation errors.
-		getEditingDomainListener();
-		
-		BasicCommandStack basicCommandStack = (BasicCommandStack) getEditingDomain().getCommandStack();
-
-		if (input instanceof DiagramEditorInput) {
-			ResourceSet resourceSet = getEditingDomain().getResourceSet();
-			getTargetRuntime().setResourceSet(resourceSet);
-			
-			Bpmn2ResourceImpl bpmnResource = (Bpmn2ResourceImpl) resourceSet.createResource(modelUri,
-					Bpmn2ModelerResourceImpl.BPMN2_CONTENT_TYPE_ID);
-
-			resourceSet.setURIConverter(new ProxyURIConverterImplExtension());
-
-			modelHandler = ModelHandlerLocator.createModelHandler(modelUri, bpmnResource);
-			ModelHandlerLocator.put(diagramUri, modelHandler);
-
-			try {
-				if (modelFile.exists()) {
-					bpmnResource.load(null);
-				} else {
-					doSave(null);
-				}
-			} catch (IOException e) {
-				Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
-				ErrorUtils.showErrorWithLogging(status);
-			}
-			basicCommandStack.execute(new RecordingCommand(getEditingDomain()) {
-
-				@Override
-				protected void doExecute() {
-					importDiagram();
-				}
-			});
-		}
-		basicCommandStack.saveIsDone();
-	}
-	
-	private void importDiagram() {
-		DIImport di = new DIImport();
-		di.setDiagram(getDiagramTypeProvider().getDiagram());
-		di.setDomain(getEditingDomain());
-		di.setModelHandler(modelHandler);
-		di.setFeatureProvider(getDiagramTypeProvider().getFeatureProvider());
-		di.generateFromDI();
-	}
-
-	private void addWorkbenchListener() {
-		if (workbenchListener==null) {
-			workbenchListener = new IWorkbenchListener() {
-				@Override
-				public boolean preShutdown(IWorkbench workbench, boolean forced) {
-					workbenchShutdown = true;
-					return true;
-				}
-
-				@Override
-				public void postShutdown(IWorkbench workbench) {
-				}
-
-			};
-			PlatformUI.getWorkbench().addWorkbenchListener(workbenchListener);
-		}
-	}
-	
-	private void removeWorkbenchListener()
-	{
-		if (workbenchListener!=null) {
-			PlatformUI.getWorkbench().removeWorkbenchListener(workbenchListener);
-			workbenchListener = null;
-		}
-	}
-	
-	public BPMN2EditingDomainListener getEditingDomainListener() {
-		if (editingDomainListener==null) {
-			TransactionalEditingDomainImpl editingDomain = (TransactionalEditingDomainImpl)getEditingDomain();
-			if (editingDomain==null) {
-				return null;
-			}
-			editingDomainListener = new BPMN2EditingDomainListener(this);
-
-			Lifecycle domainLifeCycle = (Lifecycle) editingDomain.getAdapter(Lifecycle.class);
-			domainLifeCycle.addTransactionalEditingDomainListener(editingDomainListener);
-		}
-		return editingDomainListener;
-	}
-	
-	public BasicDiagnostic getDiagnostics() {
-		return getEditingDomainListener().getDiagnostics();
-	}
-	
-	public void showErrorMessage(String msg) {
-		IWorkbench wb = PlatformUI.getWorkbench();
-		IWorkbenchWindow win = wb.getActiveWorkbenchWindow();
-		IWorkbenchPage page = win.getActivePage();
-		IWorkbenchPart part = page.getActivePart();
-		IWorkbenchPartSite site = part.getSite();
-		IViewSite vSite = ( IViewSite ) site;
-		IActionBars actionBars =  vSite.getActionBars();
-
-		if( actionBars == null )
-			return;
-
-		IStatusLineManager statusLineManager = actionBars.getStatusLineManager();
-		if( statusLineManager == null )
-			return;
-		
-		statusLineManager.setErrorMessage(msg);
-		statusLineManager.markDirty();
-		statusLineManager.update(true);
-	}
-	
-	@Override
-	public void dispose() {
-		// clear ID mapping tables if no more instances of editor are active
-		int instances = 0;
-		IWorkbenchPage[] pages = getEditorSite().getWorkbenchWindow().getPages();
-		for (IWorkbenchPage p : pages) {
-			IEditorReference[] refs = p.getEditorReferences();
-			instances += refs.length;
-		}
-		ModelUtil.clearIDs(modelHandler.getResource(), instances==0);
-		super.dispose();
-		ModelHandlerLocator.releaseModel(modelUri);
-		// get rid of temp files and folders, but only if the workbench is being shut down.
-		// when the workbench is restarted, we need to have those temp files around!
-		if (!workbenchShutdown)
-			BPMN2DiagramCreator.dispose(diagramFile);
-		removeWorkbenchListener();
-		getPreferences().dispose();
-	}
-
-	public IFile getModelFile() {
-		return modelFile;
-	}
-}
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Innar Made

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.ui.editor;

+

+import java.io.IOException;

+import java.util.ArrayList;

+

+import org.eclipse.bpmn2.modeler.core.ModelHandler;

+import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;

+import org.eclipse.bpmn2.modeler.core.ProxyURIConverterImplExtension;

+import org.eclipse.bpmn2.modeler.core.di.DIImport;

+import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerResourceImpl;

+import org.eclipse.bpmn2.modeler.core.preferences.Bpmn2Preferences;

+import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime;

+import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;

+import org.eclipse.bpmn2.modeler.ui.Activator;

+import org.eclipse.bpmn2.modeler.ui.util.ErrorUtils;

+import org.eclipse.bpmn2.modeler.ui.wizards.BPMN2DiagramCreator;

+import org.eclipse.bpmn2.util.Bpmn2ResourceImpl;

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.resources.IFolder;

+import org.eclipse.core.resources.IProject;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.core.runtime.Path;

+import org.eclipse.core.runtime.Status;

+import org.eclipse.emf.common.command.BasicCommandStack;

+import org.eclipse.emf.common.util.BasicDiagnostic;

+import org.eclipse.emf.common.util.URI;

+import org.eclipse.emf.ecore.resource.ResourceSet;

+import org.eclipse.emf.transaction.RecordingCommand;

+import org.eclipse.emf.transaction.TransactionalEditingDomain.Lifecycle;

+import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+import org.eclipse.graphiti.ui.editor.DiagramEditor;

+import org.eclipse.graphiti.ui.editor.DiagramEditorInput;

+import org.eclipse.jface.action.IStatusLineManager;

+import org.eclipse.ui.IActionBars;

+import org.eclipse.ui.IEditorInput;

+import org.eclipse.ui.IEditorReference;

+import org.eclipse.ui.IEditorSite;

+import org.eclipse.ui.IFileEditorInput;

+import org.eclipse.ui.IViewSite;

+import org.eclipse.ui.IWorkbench;

+import org.eclipse.ui.IWorkbenchListener;

+import org.eclipse.ui.IWorkbenchPage;

+import org.eclipse.ui.IWorkbenchPart;

+import org.eclipse.ui.IWorkbenchPartSite;

+import org.eclipse.ui.IWorkbenchWindow;

+import org.eclipse.ui.PartInitException;

+import org.eclipse.ui.PlatformUI;

+

+/**

+ * 

+ */

+@SuppressWarnings("restriction")

+public class BPMN2Editor extends DiagramEditor {

+

+	public static final String EDITOR_ID = "org.eclipse.bpmn2.modeler.ui.bpmn2editor";

+	public static final String CONTRIBUTOR_ID = "org.eclipse.bpmn2.modeler.ui.PropertyContributor";

+

+	private ModelHandler modelHandler;

+	private URI modelUri;

+	private URI diagramUri;

+

+	private IFile modelFile;

+	private IFile diagramFile;

+	

+	private IWorkbenchListener workbenchListener;

+	private boolean workbenchShutdown = false;

+	

+	private BPMN2EditingDomainListener editingDomainListener;

+	

+	private Bpmn2Preferences preferences;

+	private TargetRuntime targetRuntime;

+

+	@Override

+	public void init(IEditorSite site, IEditorInput input) throws PartInitException {

+		

+		try {

+			if (input instanceof IFileEditorInput) {

+				modelFile = ((IFileEditorInput) input).getFile();

+				loadPreferences(modelFile.getProject());

+

+				input = createNewDiagramEditorInput();

+

+			} else if (input instanceof DiagramEditorInput) {

+				getModelPathFromInput((DiagramEditorInput) input);

+				loadPreferences(modelFile.getProject());

+

+				// This was incorrectly constructed input, we ditch the old one and make a new and clean one instead

+				input = createNewDiagramEditorInput();

+			}

+		} catch (CoreException e) {

+			Activator.showErrorWithLogging(e);

+		}

+		

+		// add a listener so we get notified if the workbench is shutting down.

+		// in this case we don't want to delete the temp file!

+		addWorkbenchListener();

+		

+		super.init(site, input);

+	}

+

+	public Bpmn2Preferences getPreferences() {

+		if (preferences==null) {

+			assert(modelFile!=null);

+			IProject project = modelFile.getProject();

+			loadPreferences(project);

+		}

+		return preferences;

+	}

+	

+	private void loadPreferences(IProject project) {

+		preferences = new Bpmn2Preferences(project);

+		preferences.load();

+	}

+

+	/**

+	 * ID for tabbed property sheets.

+	 * 

+	 * @return the contributor id

+	 */

+	@Override

+	public String getContributorId() {

+		return CONTRIBUTOR_ID;

+	}

+

+	public TargetRuntime getTargetRuntime() {

+		if (targetRuntime==null)

+			targetRuntime = getPreferences().getRuntime(modelFile);

+		return targetRuntime;

+	}

+	

+	private void getModelPathFromInput(DiagramEditorInput input) {

+		URI uri = input.getDiagram().eResource().getURI();

+		String uriString = uri.trimFragment().toPlatformString(true);

+		modelFile = BPMN2DiagramCreator.getModelFile(new Path(uriString));

+	}

+

+	/**

+	 * Beware, creates a new input and changes this editor!

+	 */

+	private IEditorInput createNewDiagramEditorInput() throws CoreException {

+		IPath fullPath = modelFile.getFullPath();

+		modelUri = URI.createPlatformResourceURI(fullPath.toString(), true);

+

+		IFolder folder = BPMN2DiagramCreator.getTempFolder(fullPath);

+		diagramFile = BPMN2DiagramCreator.getTempFile(fullPath,folder);

+

+		// Create new temporary diagram file

+		BPMN2DiagramCreator creator = new BPMN2DiagramCreator();

+		creator.setDiagramFile(diagramFile);

+

+		IEditorInput input = creator.createDiagram(false);

+		diagramUri = creator.getUri();

+

+		return input;

+	}

+

+	@Override

+	public void doSave(IProgressMonitor monitor) {

+		modelHandler.save();

+		((BasicCommandStack) getEditingDomain().getCommandStack()).saveIsDone();

+	}

+

+	@Override

+	protected void setInput(IEditorInput input) {

+		super.setInput(input);

+		

+		// Hook a transaction exception handler so we can get diagnostics about EMF validation errors.

+		getEditingDomainListener();

+		

+		BasicCommandStack basicCommandStack = (BasicCommandStack) getEditingDomain().getCommandStack();

+

+		if (input instanceof DiagramEditorInput) {

+			ResourceSet resourceSet = getEditingDomain().getResourceSet();

+			getTargetRuntime().setResourceSet(resourceSet);

+			

+			Bpmn2ResourceImpl bpmnResource = (Bpmn2ResourceImpl) resourceSet.createResource(modelUri,

+					Bpmn2ModelerResourceImpl.BPMN2_CONTENT_TYPE_ID);

+

+			resourceSet.setURIConverter(new ProxyURIConverterImplExtension());

+

+			modelHandler = ModelHandlerLocator.createModelHandler(modelUri, bpmnResource);

+			ModelHandlerLocator.put(diagramUri, modelHandler);

+

+			try {

+				if (modelFile.exists()) {

+					bpmnResource.load(null);

+				} else {

+					doSave(null);

+				}

+			} catch (IOException e) {

+				Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);

+				ErrorUtils.showErrorWithLogging(status);

+			}

+			basicCommandStack.execute(new RecordingCommand(getEditingDomain()) {

+

+				@Override

+				protected void doExecute() {

+					importDiagram();

+				}

+			});

+		}

+		basicCommandStack.saveIsDone();

+	}

+	

+	private void importDiagram() {

+		// make sure this guy is active, otherwise it's not selectable

+		getDiagramTypeProvider().getDiagram().setActive(true);

+		

+		DIImport di = new DIImport();

+		di.setDiagram(getDiagramTypeProvider().getDiagram());

+		di.setDomain(getEditingDomain());

+		di.setModelHandler(modelHandler);

+		di.setFeatureProvider(getDiagramTypeProvider().getFeatureProvider());

+		di.generateFromDI();

+	}

+

+	@Override

+	protected PictogramElement[] getPictogramElementsForSelection() {

+		// filter out invisible elements when setting selection

+		ArrayList<PictogramElement> visibleList = new ArrayList<PictogramElement>();

+		PictogramElement[] pictogramElements = getSelectedPictogramElements();

+		for (PictogramElement pe : pictogramElements) {

+			if (pe.isVisible())

+				visibleList.add(pe);

+		}

+		return visibleList.toArray(new PictogramElement[visibleList.size()]);

+	}

+	

+	private void addWorkbenchListener() {

+		if (workbenchListener==null) {

+			workbenchListener = new IWorkbenchListener() {

+				@Override

+				public boolean preShutdown(IWorkbench workbench, boolean forced) {

+					workbenchShutdown = true;

+					return true;

+				}

+

+				@Override

+				public void postShutdown(IWorkbench workbench) {

+				}

+

+			};

+			PlatformUI.getWorkbench().addWorkbenchListener(workbenchListener);

+		}

+	}

+	

+	private void removeWorkbenchListener()

+	{

+		if (workbenchListener!=null) {

+			PlatformUI.getWorkbench().removeWorkbenchListener(workbenchListener);

+			workbenchListener = null;

+		}

+	}

+	

+	public BPMN2EditingDomainListener getEditingDomainListener() {

+		if (editingDomainListener==null) {

+			TransactionalEditingDomainImpl editingDomain = (TransactionalEditingDomainImpl)getEditingDomain();

+			if (editingDomain==null) {

+				return null;

+			}

+			editingDomainListener = new BPMN2EditingDomainListener(this);

+

+			Lifecycle domainLifeCycle = (Lifecycle) editingDomain.getAdapter(Lifecycle.class);

+			domainLifeCycle.addTransactionalEditingDomainListener(editingDomainListener);

+		}

+		return editingDomainListener;

+	}

+	

+	public BasicDiagnostic getDiagnostics() {

+		return getEditingDomainListener().getDiagnostics();

+	}

+	

+	public void showErrorMessage(String msg) {

+		IWorkbench wb = PlatformUI.getWorkbench();

+		IWorkbenchWindow win = wb.getActiveWorkbenchWindow();

+		IWorkbenchPage page = win.getActivePage();

+		IWorkbenchPart part = page.getActivePart();

+		IWorkbenchPartSite site = part.getSite();

+		IViewSite vSite = ( IViewSite ) site;

+		IActionBars actionBars =  vSite.getActionBars();

+

+		if( actionBars == null )

+			return;

+

+		IStatusLineManager statusLineManager = actionBars.getStatusLineManager();

+		if( statusLineManager == null )

+			return;

+		

+		statusLineManager.setErrorMessage(msg);

+		statusLineManager.markDirty();

+		statusLineManager.update(true);

+	}

+	

+	@Override

+	public void dispose() {

+		// clear ID mapping tables if no more instances of editor are active

+		int instances = 0;

+		IWorkbenchPage[] pages = getEditorSite().getWorkbenchWindow().getPages();

+		for (IWorkbenchPage p : pages) {

+			IEditorReference[] refs = p.getEditorReferences();

+			instances += refs.length;

+		}

+		ModelUtil.clearIDs(modelHandler.getResource(), instances==0);

+		super.dispose();

+		ModelHandlerLocator.releaseModel(modelUri);

+		// get rid of temp files and folders, but only if the workbench is being shut down.

+		// when the workbench is restarted, we need to have those temp files around!

+		if (!workbenchShutdown)

+			BPMN2DiagramCreator.dispose(diagramFile);

+		removeWorkbenchListener();

+		getPreferences().dispose();

+	}

+

+	public IFile getModelFile() {

+		return modelFile;

+	}

+}

diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/AbstractSubProcessFeatureContainer.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/AbstractSubProcessFeatureContainer.java
index 0851e0d..cca5596 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/AbstractSubProcessFeatureContainer.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/AbstractSubProcessFeatureContainer.java
@@ -1,49 +1,55 @@
-/******************************************************************************* 
- * Copyright (c) 2011 Red Hat, Inc. 
- *  All rights reserved. 
- * This program is 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: 
- * Red Hat, Inc. - initial API and implementation 
- *
- * @author Innar Made
- ******************************************************************************/
-package org.eclipse.bpmn2.modeler.ui.features.activity.subprocess;
-
-import org.eclipse.bpmn2.BaseElement;
-import org.eclipse.bpmn2.modeler.core.features.AbstractBaseElementUpdateFeature;
-import org.eclipse.bpmn2.modeler.core.features.MultiUpdateFeature;
-import org.eclipse.bpmn2.modeler.ui.features.activity.AbstractActivityFeatureContainer;
-import org.eclipse.graphiti.features.IDirectEditingFeature;
-import org.eclipse.graphiti.features.IFeatureProvider;
-import org.eclipse.graphiti.features.ILayoutFeature;
-import org.eclipse.graphiti.features.context.IUpdateContext;
-
-public abstract class AbstractSubProcessFeatureContainer extends AbstractActivityFeatureContainer {
-
-	@Override
-	public IDirectEditingFeature getDirectEditingFeature(IFeatureProvider fp) {
-		return null;
-	}
-
-	@Override
-	public ILayoutFeature getLayoutFeature(IFeatureProvider fp) {
-		return new SubProcessLayoutFeature(fp);
-	}
-
-	@Override
-	public MultiUpdateFeature getUpdateFeature(IFeatureProvider fp) {
-		MultiUpdateFeature multiUpdate = super.getUpdateFeature(fp);
-		AbstractBaseElementUpdateFeature nameUpdateFeature = new AbstractBaseElementUpdateFeature(fp) {
-			@Override
-			public boolean canUpdate(IUpdateContext context) {
-				Object bo = getBusinessObjectForPictogramElement(context.getPictogramElement());
-				return bo != null && bo instanceof BaseElement && canApplyTo((BaseElement) bo);
-			}
-		};
-		multiUpdate.addUpdateFeature(nameUpdateFeature);
-		return multiUpdate;
-	}
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Innar Made

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.ui.features.activity.subprocess;

+

+import org.eclipse.bpmn2.BaseElement;

+import org.eclipse.bpmn2.modeler.core.features.AbstractBaseElementUpdateFeature;

+import org.eclipse.bpmn2.modeler.core.features.MultiUpdateFeature;

+import org.eclipse.bpmn2.modeler.ui.features.activity.AbstractActivityFeatureContainer;

+import org.eclipse.graphiti.features.IDirectEditingFeature;

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.ILayoutFeature;

+import org.eclipse.graphiti.features.IResizeShapeFeature;

+import org.eclipse.graphiti.features.context.IUpdateContext;

+

+public abstract class AbstractSubProcessFeatureContainer extends AbstractActivityFeatureContainer {

+

+	@Override

+	public IDirectEditingFeature getDirectEditingFeature(IFeatureProvider fp) {

+		return null;

+	}

+

+	@Override

+	public ILayoutFeature getLayoutFeature(IFeatureProvider fp) {

+		return new SubProcessLayoutFeature(fp);

+	}

+

+	@Override

+	public MultiUpdateFeature getUpdateFeature(IFeatureProvider fp) {

+		MultiUpdateFeature multiUpdate = super.getUpdateFeature(fp);

+		AbstractBaseElementUpdateFeature nameUpdateFeature = new AbstractBaseElementUpdateFeature(fp) {

+			@Override

+			public boolean canUpdate(IUpdateContext context) {

+				Object bo = getBusinessObjectForPictogramElement(context.getPictogramElement());

+				return bo != null && bo instanceof BaseElement && canApplyTo((BaseElement) bo);

+			}

+		};

+		multiUpdate.addUpdateFeature(nameUpdateFeature);

+		return multiUpdate;

+	}

+

+	@Override

+	public IResizeShapeFeature getResizeFeature(IFeatureProvider fp) {

+		return new SubProcessResizeFeature(fp);

+	}

 }
\ No newline at end of file
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessCollapseFeature.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessCollapseFeature.java
new file mode 100644
index 0000000..aef1fc4
--- /dev/null
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessCollapseFeature.java
@@ -0,0 +1,120 @@
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Bob Brodt

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.ui.features.activity.subprocess;

+

+import org.eclipse.bpmn2.SubProcess;

+import org.eclipse.bpmn2.di.BPMNShape;

+import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;

+import org.eclipse.bpmn2.modeler.core.utils.GraphicsUtil;

+import org.eclipse.bpmn2.modeler.ui.ImageProvider;

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.IResizeShapeFeature;

+import org.eclipse.graphiti.features.context.IContext;

+import org.eclipse.graphiti.features.context.ICustomContext;

+import org.eclipse.graphiti.features.context.impl.ResizeShapeContext;

+import org.eclipse.graphiti.features.custom.AbstractCustomFeature;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.pictograms.ContainerShape;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+

+public class SubProcessCollapseFeature extends AbstractCustomFeature {

+

+	public SubProcessCollapseFeature(IFeatureProvider fp) {

+		super(fp);

+		// TODO Auto-generated constructor stub

+	}

+

+	@Override

+	public String getName() {

+		return "Collapse"; //$NON-NLS-1$

+	}

+

+	@Override

+	public String getDescription() {

+

+		return "Collapse the Sub-Process and hide contents"; //$NON-NLS-1$

+	}

+

+	@Override

+	public String getImageId() {

+		return ImageProvider.IMG_16_COLLAPSE;

+	}

+

+	@Override

+	public boolean isAvailable(IContext context) {

+		return true;

+	}

+

+	@Override

+	public boolean canExecute(ICustomContext context) {

+		boolean ret = false;

+		PictogramElement[] pes = context.getPictogramElements();

+		if (pes != null && pes.length == 1) {

+			Object bo = getBusinessObjectForPictogramElement(pes[0]);

+			if (bo instanceof SubProcess) {

+				try {

+					BPMNShape bpmnShape = (BPMNShape) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(

+							getDiagram(), (SubProcess)bo);

+					if (bpmnShape.isIsExpanded())

+						ret = true;

+				} catch (Exception e) {

+					e.printStackTrace();

+				}

+			}

+		}

+		return ret;

+	}

+

+	@Override

+	public void execute(ICustomContext context) {

+		PictogramElement[] pes = context.getPictogramElements();

+		if (pes != null && pes.length == 1) {

+			PictogramElement pe0 = pes[0];

+			Object bo = getBusinessObjectForPictogramElement(pe0);

+			if (pe0 instanceof ContainerShape && bo instanceof SubProcess) {

+				ContainerShape containerShape = (ContainerShape)pe0;

+				SubProcess subProcess = (SubProcess)bo;

+				try {

+					BPMNShape bpmnShape = (BPMNShape) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(

+							getDiagram(), subProcess);

+					if (bpmnShape.isIsExpanded()) {

+						

+						// SubProcess is collapsed - resize to standard task size

+						// NOTE: children tasks will be set not-visible in SubProcessLayoutFeature

+						

+						bpmnShape.setIsExpanded(false);

+

+						GraphicsAlgorithm ga = containerShape.getGraphicsAlgorithm();

+						ResizeShapeContext resizeContext = new ResizeShapeContext(containerShape);

+						IResizeShapeFeature resizeFeature = getFeatureProvider().getResizeShapeFeature(resizeContext);

+						int oldWidth = ga.getWidth();

+						int oldHeight = ga.getHeight();

+						int newWidth = GraphicsUtil.TASK_DEFAULT_WIDTH;

+						int newHeight = GraphicsUtil.TASK_DEFAULT_HEIGHT;

+						resizeContext.setX(ga.getX() + oldWidth/2 - newWidth/2);

+						resizeContext.setY(ga.getY() + oldHeight/2 - newHeight/2);

+						resizeContext.setWidth(newWidth);

+						resizeContext.setHeight(newHeight);

+						resizeFeature.resizeShape(resizeContext);

+						

+						getDiagramEditor().selectPictogramElements(new PictogramElement[] {});

+					}

+					

+				} catch (Exception e) {

+					// TODO Auto-generated catch block

+					e.printStackTrace();

+				}

+			}

+		}

+	}

+}

diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessDrilldownFeature.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessDrilldownFeature.java
deleted file mode 100644
index 952c499..0000000
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessDrilldownFeature.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/******************************************************************************* 
- * Copyright (c) 2011 Red Hat, Inc. 
- *  All rights reserved. 
- * This program is 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: 
- * Red Hat, Inc. - initial API and implementation 
- *
- * @author Innar Made
- ******************************************************************************/
-package org.eclipse.bpmn2.modeler.ui.features.activity.subprocess;
-
-import java.util.Collection;
-
-import org.eclipse.bpmn2.SubProcess;
-import org.eclipse.graphiti.features.IFeatureProvider;
-import org.eclipse.graphiti.features.context.ICustomContext;
-import org.eclipse.graphiti.mm.pictograms.Diagram;
-import org.eclipse.graphiti.mm.pictograms.PictogramElement;
-import org.eclipse.graphiti.ui.features.AbstractDrillDownFeature;
-
-// NOT USED YET
-public class SubProcessDrilldownFeature extends AbstractDrillDownFeature {
-
-	public SubProcessDrilldownFeature(IFeatureProvider fp) {
-	    super(fp);
-    }
-	
-	@Override
-	public String getName() {
-	    return "Open sub-process";
-	}
-	
-	@Override
-	public String getDescription() {
-	    return "Shows sub-process contents";
-	}
-	
-	@Override
-	public boolean canExecute(ICustomContext context) {
-		PictogramElement[] elements = context.getPictogramElements();
-		if(elements != null && elements.length == 1) {
-			Object o = getBusinessObjectForPictogramElement(elements[0]);
-			if( o instanceof SubProcess ) {
-				return super.canExecute(context);
-			}
-		}
-	    return false;
-	}
-	
-	@Override
-    protected Collection<Diagram> getDiagrams() {
-	    return null;
-    }
-}
\ No newline at end of file
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessExpandFeature.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessExpandFeature.java
new file mode 100644
index 0000000..f6285f4
--- /dev/null
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessExpandFeature.java
@@ -0,0 +1,118 @@
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Bob Brodt

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.ui.features.activity.subprocess;

+

+import org.eclipse.bpmn2.SubProcess;

+import org.eclipse.bpmn2.di.BPMNShape;

+import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;

+import org.eclipse.bpmn2.modeler.ui.ImageProvider;

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.IResizeShapeFeature;

+import org.eclipse.graphiti.features.context.IContext;

+import org.eclipse.graphiti.features.context.ICustomContext;

+import org.eclipse.graphiti.features.context.impl.ResizeShapeContext;

+import org.eclipse.graphiti.features.custom.AbstractCustomFeature;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.pictograms.ContainerShape;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+

+// NOT USED YET

+public class SubProcessExpandFeature extends AbstractCustomFeature {

+

+	public SubProcessExpandFeature(IFeatureProvider fp) {

+	    super(fp);

+    }

+	

+	@Override

+	public String getName() {

+	    return "Expand";

+	}

+	

+	@Override

+	public String getDescription() {

+	    return "Expand the Sub-Process and show contents";

+	}

+

+	@Override

+	public String getImageId() {

+		return ImageProvider.IMG_16_EXPAND;

+	}

+

+	@Override

+	public boolean isAvailable(IContext context) {

+		return true;

+	}

+

+	@Override

+	public boolean canExecute(ICustomContext context) {

+		boolean ret = false;

+		PictogramElement[] pes = context.getPictogramElements();

+		if (pes != null && pes.length == 1) {

+			Object bo = getBusinessObjectForPictogramElement(pes[0]);

+			if (bo instanceof SubProcess) {

+				try {

+					BPMNShape bpmnShape = (BPMNShape) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(

+							getDiagram(), (SubProcess)bo);

+					if (!bpmnShape.isIsExpanded())

+						ret = true;

+				} catch (Exception e) {

+					// TODO Auto-generated catch block

+					e.printStackTrace();

+				}

+			}

+		}

+		return ret;

+	}

+

+	@Override

+	public void execute(ICustomContext context) {

+		PictogramElement[] pes = context.getPictogramElements();

+		if (pes != null && pes.length == 1) {

+			PictogramElement pe0 = pes[0];

+			Object bo = getBusinessObjectForPictogramElement(pe0);

+			if (pe0 instanceof ContainerShape && bo instanceof SubProcess) {

+				ContainerShape containerShape = (ContainerShape)pe0;

+				SubProcess subProcess = (SubProcess)bo;

+				try {

+					BPMNShape bpmnShape = (BPMNShape) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(

+							getDiagram(), subProcess);

+					if (!bpmnShape.isIsExpanded()) {

+						

+						// SubProcess is collapsed - resize to minimum size such that all children are visible

+						// NOTE: children tasks will be set visible in SubProcessLayoutFeature

+

+						bpmnShape.setIsExpanded(true);

+						

+						GraphicsAlgorithm ga = containerShape.getGraphicsAlgorithm();

+						ResizeShapeContext resizeContext = new ResizeShapeContext(containerShape);

+						IResizeShapeFeature resizeFeature = getFeatureProvider().getResizeShapeFeature(resizeContext);

+						int oldWidth = ga.getWidth();

+						int oldHeight = ga.getHeight();

+						SubProcessResizeFeature.SizeCalculator newSize = new SubProcessResizeFeature.SizeCalculator(containerShape);

+						int newWidth = newSize.getWidth();

+						int newHeight = newSize.getHeight();

+						resizeContext.setX(ga.getX() + oldWidth/2 - newWidth/2);

+						resizeContext.setY(ga.getY() + oldHeight/2 - newHeight/2);

+						resizeContext.setWidth(newWidth);

+						resizeContext.setHeight(newHeight);

+						resizeFeature.resizeShape(resizeContext);

+					}

+					

+				} catch (Exception e) {

+					// TODO Auto-generated catch block

+					e.printStackTrace();

+				}

+			}

+		}

+	}

+}
\ No newline at end of file
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessFeatureContainer.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessFeatureContainer.java
index a235aa1..15e1142 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessFeatureContainer.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessFeatureContainer.java
@@ -1,71 +1,87 @@
-/******************************************************************************* 
- * Copyright (c) 2011 Red Hat, Inc. 
- *  All rights reserved. 
- * This program is 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: 
- * Red Hat, Inc. - initial API and implementation 
- *
- * @author Innar Made
- ******************************************************************************/
-package org.eclipse.bpmn2.modeler.ui.features.activity.subprocess;
-
-import org.eclipse.bpmn2.SubProcess;
-import org.eclipse.bpmn2.modeler.core.ModelHandler;
-import org.eclipse.bpmn2.modeler.core.features.MultiUpdateFeature;
-import org.eclipse.bpmn2.modeler.core.features.activity.subprocess.AbstractCreateSubProcess;
-import org.eclipse.bpmn2.modeler.ui.ImageProvider;
-import org.eclipse.graphiti.features.IAddFeature;
-import org.eclipse.graphiti.features.ICreateFeature;
-import org.eclipse.graphiti.features.IFeatureProvider;
-import org.eclipse.graphiti.features.context.ICreateContext;
-
-public class SubProcessFeatureContainer extends AbstractSubProcessFeatureContainer {
-
-	public static final String TRIGGERED_BY_EVENT = "triggered-by-event-key";
-
-	@Override
-	public boolean canApplyTo(Object o) {
-		return super.canApplyTo(o) && o instanceof SubProcess;
-	}
-
-	@Override
-	public ICreateFeature getCreateFeature(IFeatureProvider fp) {
-		return new CreateSubProcessFeature(fp);
-	}
-
-	@Override
-	public IAddFeature getAddFeature(IFeatureProvider fp) {
-		return new AddExpandedSubProcessFeature(fp);
-	}
-
-	@Override
-	public MultiUpdateFeature getUpdateFeature(IFeatureProvider fp) {
-		MultiUpdateFeature multiUpdate = super.getUpdateFeature(fp);
-		UpdateSubProcessFeature updateSubProcessFeature = new UpdateSubProcessFeature(fp);
-		multiUpdate.addUpdateFeature(updateSubProcessFeature);
-		return multiUpdate;
-	}
-
-	public static class CreateSubProcessFeature extends AbstractCreateSubProcess {
-
-		public CreateSubProcessFeature(IFeatureProvider fp) {
-			super(fp, "Expanded Sub-Process", "Inner activity");
-		}
-
-		@Override
-		protected SubProcess createFlowElement(ICreateContext context) {
-			SubProcess subProcess = ModelHandler.FACTORY.createSubProcess();
-			subProcess.setName("SubProcess");
-			subProcess.setTriggeredByEvent(false);
-			return subProcess;
-		}
-
-		@Override
-		protected String getStencilImageId() {
-			return ImageProvider.IMG_16_SUB_PROCESS;
-		}
-	}
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Innar Made

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.ui.features.activity.subprocess;

+

+import org.eclipse.bpmn2.SubProcess;

+import org.eclipse.bpmn2.di.BPMNShape;

+import org.eclipse.bpmn2.modeler.core.ModelHandler;

+import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;

+import org.eclipse.bpmn2.modeler.core.features.MultiUpdateFeature;

+import org.eclipse.bpmn2.modeler.core.features.activity.subprocess.AbstractCreateSubProcess;

+import org.eclipse.bpmn2.modeler.ui.ImageProvider;

+import org.eclipse.graphiti.features.IAddFeature;

+import org.eclipse.graphiti.features.ICreateFeature;

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.context.ICreateContext;

+

+public class SubProcessFeatureContainer extends AbstractSubProcessFeatureContainer {

+

+	public static final String TRIGGERED_BY_EVENT = "triggered-by-event-key";

+

+	@Override

+	public boolean canApplyTo(Object o) {

+		return super.canApplyTo(o) && o instanceof SubProcess;

+	}

+

+	@Override

+	public ICreateFeature getCreateFeature(IFeatureProvider fp) {

+		return new CreateSubProcessFeature(fp);

+	}

+

+	@Override

+	public IAddFeature getAddFeature(IFeatureProvider fp) {

+		return new AddExpandedSubProcessFeature(fp);

+	}

+

+	@Override

+	public MultiUpdateFeature getUpdateFeature(IFeatureProvider fp) {

+		MultiUpdateFeature multiUpdate = super.getUpdateFeature(fp);

+		UpdateSubProcessFeature updateSubProcessFeature = new UpdateSubProcessFeature(fp);

+		multiUpdate.addUpdateFeature(updateSubProcessFeature);

+		return multiUpdate;

+	}

+

+	public static class CreateSubProcessFeature extends AbstractCreateSubProcess {

+

+		public CreateSubProcessFeature(IFeatureProvider fp) {

+			super(fp, "Expanded Sub-Process", "Inner activity");

+		}

+

+		@Override

+		public Object[] create(ICreateContext context) {

+			Object[] elems = super.create(context);

+			try {

+				BPMNShape shape = (BPMNShape) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(

+						getDiagram(), (SubProcess)elems[0]);

+				shape.setIsExpanded(true);

+			} catch (Exception e) {

+				// TODO Auto-generated catch block

+				e.printStackTrace();

+			}

+			return elems;

+		}

+		

+		@Override

+		protected SubProcess createFlowElement(ICreateContext context) {

+			SubProcess subProcess = ModelHandler.FACTORY.createSubProcess();

+			subProcess.setName("SubProcess");

+			subProcess.setTriggeredByEvent(false);

+			return subProcess;

+		}

+

+		@Override

+		protected String getStencilImageId() {

+			return ImageProvider.IMG_16_SUB_PROCESS;

+		}

+	}

 }
\ No newline at end of file
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessLayoutFeature.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessLayoutFeature.java
index f0ab21c..ce80836 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessLayoutFeature.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessLayoutFeature.java
@@ -13,9 +13,16 @@
 package org.eclipse.bpmn2.modeler.ui.features.activity.subprocess;
 
 import org.eclipse.bpmn2.Activity;
+import org.eclipse.bpmn2.SubProcess;
+import org.eclipse.bpmn2.di.BPMNShape;
+import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;
+import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;
 import org.eclipse.bpmn2.modeler.core.features.activity.ActivityLayoutFeature;
+import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport;
 import org.eclipse.graphiti.features.IFeatureProvider;
+import org.eclipse.graphiti.features.IResizeShapeFeature;
 import org.eclipse.graphiti.features.context.ILayoutContext;
+import org.eclipse.graphiti.features.context.impl.ResizeShapeContext;
 import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
 import org.eclipse.graphiti.mm.algorithms.Text;
 import org.eclipse.graphiti.mm.pictograms.ContainerShape;
@@ -25,9 +32,6 @@
 
 public class SubProcessLayoutFeature extends ActivityLayoutFeature {
 
-	private final static int MARGIN = 2;
-	private final static int NUMBER_OF_PARENT_ELEMENTS = 3;
-	
 	public SubProcessLayoutFeature(IFeatureProvider fp) {
 		super(fp);
 	}
@@ -44,86 +48,59 @@
 	@Override
 	public boolean layout(ILayoutContext context) {
 		ContainerShape containerShape = (ContainerShape) context.getPictogramElement();
-		GraphicsAlgorithm parentGa = containerShape.getGraphicsAlgorithm();
-		int newWidth = parentGa.getWidth();
-		int newHeight = parentGa.getHeight();
-
-		int minX = Integer.MAX_VALUE;
-		int minY = Integer.MAX_VALUE;
-		int minWidth = 0;
-		int minHeight = 0;
-		int size = containerShape.getChildren().size();
-		for (int i=NUMBER_OF_PARENT_ELEMENTS; i<size; ++i) {
-			PictogramElement pe = containerShape.getChildren().get(i);
-			GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();
-			if (ga!=null) {
-				int x = ga.getX();
-				int y = ga.getY();
-				if (x < minX)
-					minX = x;
-				if (y < minY)
-					minY = y;
-			}
-		}
-		for (int i=NUMBER_OF_PARENT_ELEMENTS; i<size; ++i) {
-			PictogramElement pe = containerShape.getChildren().get(i);
-			GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();
-			if (ga!=null) {
-				int w = ga.getX() - minX + ga.getWidth();
-				int h = ga.getY() - minY + ga.getHeight();
-				if (w > minWidth)
-					minWidth = w;
-				if (h > minHeight)
-					minHeight = h;
-			}
-		}
-		
-		if (minX < MARGIN)
-			minX = MARGIN;
-		if (minY < MARGIN)
-			minY = MARGIN;
-		minWidth += 2 * MARGIN;
-		minHeight += 2 * MARGIN;
-		
-		if (newWidth < minWidth) {
-			parentGa.setWidth(minWidth);
-		}
-		if (newWidth < minX + minWidth) {
-			int shift = minX + minWidth - newWidth;
-			if (shift>minX-MARGIN) {
-				shift = minX-MARGIN;
-			}
-			if (shift>0) {
-				for (int i=NUMBER_OF_PARENT_ELEMENTS; i<size; ++i) {
-					PictogramElement pe = containerShape.getChildren().get(i);
+		SubProcess subProcess = BusinessObjectUtil.getFirstElementOfType(containerShape, SubProcess.class);
+		try {
+			BPMNShape shape = (BPMNShape) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(
+					getDiagram(), subProcess);
+			
+			if (shape.isIsExpanded()) {
+				
+				// SubProcess is expanded
+				
+				boolean needResize = false;
+				GraphicsAlgorithm parentGa = containerShape.getGraphicsAlgorithm();
+				
+				for (PictogramElement pe : FeatureSupport.getContainerChildren(containerShape)) {
 					GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();
 					if (ga!=null) {
-						int x = ga.getX() - shift;
-						ga.setX(x);
+						if (ga.getX() < 0 || ga.getY() < 0) {
+							needResize = true;
+							break;
+						}
+						if (ga.getX() + ga.getWidth() > parentGa.getWidth()) {
+							needResize = true;
+							break;
+						}
+						if (ga.getY() + ga.getHeight() > parentGa.getHeight()) {
+							needResize = true;
+							break;
+						}
 					}
 				}
-			}
-		}
-		if (newHeight < minHeight) {
-			parentGa.setHeight(minHeight);
-		}
-		if (newHeight < minY + minHeight) {
-			int shift = minY + minHeight - newHeight;
-			if (shift>minY-MARGIN) {
-				shift = minY-MARGIN;
-			}
-			if (shift>0) {
-				for (int i=NUMBER_OF_PARENT_ELEMENTS; i<size; ++i) {
-					PictogramElement pe = containerShape.getChildren().get(i);
-					GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();
-					if (ga!=null) {
-						int y = ga.getY() - shift;
-						ga.setY(y);
-					}
+				if (needResize) {
+					ResizeShapeContext resizeContext = new ResizeShapeContext(containerShape);
+					resizeContext.setX(parentGa.getX());
+					resizeContext.setY(parentGa.getY());
+					resizeContext.setWidth(parentGa.getWidth());
+					resizeContext.setHeight(parentGa.getHeight());
+					IResizeShapeFeature resizeFeature = getFeatureProvider().getResizeShapeFeature(resizeContext);
+					resizeFeature.resizeShape(resizeContext);
 				}
+				
+				FeatureSupport.setContainerChildrenVisible(containerShape, true);
 			}
+			else {
+				
+				// SubProcess is collapsed
+				
+				FeatureSupport.setContainerChildrenVisible(containerShape, false);
+			}
+			
+		} catch (Exception e) {
+			// It's OK, I've played a programmer before...
+			// e.printStackTrace();
 		}
-
+		
 		return super.layout(context);
 	}
 }
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessResizeFeature.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessResizeFeature.java
new file mode 100644
index 0000000..6bce020
--- /dev/null
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/features/activity/subprocess/SubProcessResizeFeature.java
@@ -0,0 +1,231 @@
+/******************************************************************************* 

+ * Copyright (c) 2011 Red Hat, Inc. 

+ *  All rights reserved. 

+ * This program is 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: 

+ * Red Hat, Inc. - initial API and implementation 

+ *

+ * @author Bob Brodt

+ ******************************************************************************/

+package org.eclipse.bpmn2.modeler.ui.features.activity.subprocess;

+

+import org.eclipse.bpmn2.SubProcess;

+import org.eclipse.bpmn2.di.BPMNShape;

+import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator;

+import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;

+import org.eclipse.bpmn2.modeler.core.features.DefaultBPMNResizeFeature;

+import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport;

+import org.eclipse.bpmn2.modeler.core.utils.GraphicsUtil;

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.context.IResizeShapeContext;

+import org.eclipse.graphiti.features.context.impl.ResizeShapeContext;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.pictograms.ContainerShape;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+import org.eclipse.graphiti.services.Graphiti;

+

+public class SubProcessResizeFeature extends DefaultBPMNResizeFeature {

+	public final static int MARGIN = 20;

+	

+	public SubProcessResizeFeature(IFeatureProvider fp) {

+		super(fp);

+	}

+	

+	@Override

+	public void resizeShape(IResizeShapeContext context) {

+

+		ResizeShapeContext resizeShapeContext = (ResizeShapeContext)context;

+

+		ContainerShape containerShape = (ContainerShape) context.getPictogramElement();

+		SubProcess subProcess = BusinessObjectUtil.getFirstElementOfType(containerShape, SubProcess.class);

+		try {

+			BPMNShape shape = (BPMNShape) ModelHandlerLocator.getModelHandler(getDiagram().eResource()).findDIElement(

+					getDiagram(), subProcess);

+			

+			if (shape.isIsExpanded()) {

+

+				// SubProcess is expanded

+				

+				GraphicsAlgorithm parentGa = containerShape.getGraphicsAlgorithm();

+				int newWidth = resizeShapeContext.getWidth();

+				int newHeight = resizeShapeContext.getHeight();

+				SizeCalculator sizeCalc = new SizeCalculator(containerShape);

+				int shiftX = sizeCalc.shiftX;

+				int shiftY = sizeCalc.shiftY;

+				int minWidth = sizeCalc.minWidth;

+				int minHeight = sizeCalc.minHeight;

+				

+				if (shiftX < 0) {

+					for (PictogramElement pe : FeatureSupport.getContainerChildren(containerShape)) {

+						GraphicsAlgorithm childGa = pe.getGraphicsAlgorithm();

+						if (childGa!=null) {

+							int x = childGa.getX() - shiftX + MARGIN;

+							childGa.setX(x);

+						}

+					}

+					resizeShapeContext.setX(resizeShapeContext.getX() + shiftX - MARGIN);

+					shiftX = MARGIN;

+				}

+				

+				if (shiftY < 0) {

+					for (PictogramElement pe : FeatureSupport.getContainerChildren(containerShape)) {

+						GraphicsAlgorithm childGa = pe.getGraphicsAlgorithm();

+						if (childGa!=null) {

+							int y = childGa.getY() - shiftY + MARGIN;

+							childGa.setY(y);

+						}

+					}

+					resizeShapeContext.setY(resizeShapeContext.getY() + shiftY - MARGIN);

+					shiftX = MARGIN;

+				}

+

+				if (shiftX < MARGIN)

+					shiftX = MARGIN;

+				if (shiftY < MARGIN)

+					shiftY = MARGIN;

+				minWidth += 2 * MARGIN;

+				minHeight += 2 * MARGIN;

+

+				if (newWidth < minWidth) {

+					parentGa.setWidth(minWidth);

+				}

+				if (newWidth < shiftX + minWidth) {

+					int shift = shiftX + minWidth - newWidth;

+					if (shift>shiftX-MARGIN) {

+						shift = shiftX-MARGIN;

+					}

+					if (shift>0) {

+						for (PictogramElement pe : FeatureSupport.getContainerChildren(containerShape)) {

+							GraphicsAlgorithm childGa = pe.getGraphicsAlgorithm();

+							if (childGa!=null) {

+								int x = childGa.getX() - shift;

+								childGa.setX(x);

+							}

+						}

+					}

+				}

+				if (newHeight < minHeight) {

+					parentGa.setHeight(minHeight);

+				}

+				if (newHeight < shiftY + minHeight) {

+					int shift = shiftY + minHeight - newHeight;

+					if (shift>shiftY-MARGIN) {

+						shift = shiftY-MARGIN;

+					}

+					if (shift>0) {

+						for (PictogramElement pe : FeatureSupport.getContainerChildren(containerShape)) {

+							GraphicsAlgorithm childGa = pe.getGraphicsAlgorithm();

+							if (childGa!=null) {

+								int y = childGa.getY() - shift;

+								childGa.setY(y);

+							}

+						}

+					}

+				}

+				

+				if (resizeShapeContext.getWidth() < minWidth)

+					resizeShapeContext.setWidth(minWidth);

+				if (resizeShapeContext.getHeight() < minHeight)

+					resizeShapeContext.setHeight(minHeight);

+			}

+			else {

+				

+				// SubProcess is collapsed

+				

+				for (PictogramElement pe : FeatureSupport.getContainerDecorators(containerShape)) {

+					GraphicsAlgorithm childGa = pe.getGraphicsAlgorithm();

+					if (childGa!=null) {

+						childGa.setWidth(GraphicsUtil.TASK_DEFAULT_WIDTH);

+						childGa.setHeight(GraphicsUtil.TASK_DEFAULT_HEIGHT);

+					}

+				}

+				

+				resizeShapeContext.setWidth(GraphicsUtil.TASK_DEFAULT_WIDTH);

+				resizeShapeContext.setHeight(GraphicsUtil.TASK_DEFAULT_HEIGHT);

+			}

+			

+		} catch (Exception e) {

+			// TODO Auto-generated catch block

+			e.printStackTrace();

+		}

+		Graphiti.getPeService().sendToFront(containerShape);

+		

+		super.resizeShape(context);

+	}

+	

+	public static class SizeCalculator {

+		

+		int shiftX;

+		int shiftY;

+		int minWidth;

+		int minHeight;

+		ContainerShape containerShape;

+		

+		public SizeCalculator(ContainerShape containerShape) {

+			setShape(containerShape);

+		}

+		

+		public void setShape(ContainerShape containerShape) {

+			this.containerShape = containerShape;

+			calculate();

+		}

+		

+		private void calculate() {

+			int minX = Integer.MAX_VALUE;

+			int minY = Integer.MAX_VALUE;

+			minWidth = 0;

+			minHeight = 0;

+

+			int size = containerShape.getChildren().size();

+			for (PictogramElement pe : FeatureSupport.getContainerChildren(containerShape)) {

+				GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();

+				if (ga!=null) {

+					int x = ga.getX();

+					int y = ga.getY();

+					if (x < minX)

+						minX = x;

+					if (y < minY)

+						minY = y;

+				}

+			}

+			

+			shiftX = minX;

+			shiftY = minY;

+			

+			for (PictogramElement pe : FeatureSupport.getContainerChildren(containerShape)) {

+				GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();

+				if (ga!=null) {

+					int w = ga.getX() - minX + ga.getWidth();

+					int h = ga.getY() - minY + ga.getHeight();

+					if (w > minWidth)

+						minWidth = w;

+					if (h > minHeight)

+						minHeight = h;

+				}

+			}

+			if (minWidth<=0)

+				minWidth = GraphicsUtil.SUB_PROCEESS_DEFAULT_WIDTH;

+			if (minHeight<=0)

+				minHeight = GraphicsUtil.SUB_PROCESS_DEFAULT_HEIGHT;

+		}

+

+		public int getShiftX() {

+			return shiftX;

+		}

+

+		public int getShiftY() {

+			return shiftY;

+		}

+		

+		public int getWidth() {

+			return minWidth;

+		}

+		

+		public int getHeight() {

+			return minHeight;

+		}

+	}

+}