[111892] gmf_head crevells 070518 First milestone of group/ungroup support (painting issues when grouping shapes with border items)
diff --git a/org.eclipse.gmf.examples.runtime.diagram.geoshapes/plugin.xml b/org.eclipse.gmf.examples.runtime.diagram.geoshapes/plugin.xml
index d761182..d07a4c9 100644
--- a/org.eclipse.gmf.examples.runtime.diagram.geoshapes/plugin.xml
+++ b/org.eclipse.gmf.examples.runtime.diagram.geoshapes/plugin.xml
@@ -117,9 +117,35 @@
             <partAction menubarPath="/file/print" id="printPreviewAction">
             </partAction>
          </partContribution>
-       </contributionItemProvider>
+       </contributionItemProvider>      
    </extension>
-  
+      
+   <extension id="GeoshapesExampleGroupContributionItemProvider" name="GeoshapesExampleGroupContributionItemProvider" point="org.eclipse.gmf.runtime.common.ui.services.action.contributionItemProviders">
+      <contributionItemProvider class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContributionItemProvider">
+         <Priority name="Low">
+         </Priority>
+         <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
+            <popupStructuredContributionCriteria
+                  objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.IPrimaryEditPart"
+                  objectCount="2+">
+               <method
+                     name="getDiagramEditDomain().getEditorPart().getEditorSite().getId()"
+                     value="GeoshapeEditor"/>     
+            </popupStructuredContributionCriteria>     
+            <popupAction path="/formatMenu/miscellaneousGroup" id="groupAction">
+            </popupAction>
+         </popupContribution>
+         <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
+            <popupStructuredContributionCriteria objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart">
+            	<method
+                     name="getDiagramEditDomain().getEditorPart().getEditorSite().getId()"
+                     value="GeoshapeEditor"/>     
+            </popupStructuredContributionCriteria>                    
+            <popupAction path="/formatMenu/miscellaneousGroup" id="ungroupAction">
+            </popupAction>   
+         </popupContribution>                                 
+      </contributionItemProvider>
+   </extension>  
   
   <extension point="org.eclipse.emf.ecore.extension_parser">
       <parser type="geo" class="org.eclipse.gmf.runtime.emf.core.resources.GMFResourceFactory">
diff --git a/org.eclipse.gmf.examples.runtime.diagram.logic/plugin.xml b/org.eclipse.gmf.examples.runtime.diagram.logic/plugin.xml
index fb4de01..d949a6b 100644
--- a/org.eclipse.gmf.examples.runtime.diagram.logic/plugin.xml
+++ b/org.eclipse.gmf.examples.runtime.diagram.logic/plugin.xml
@@ -242,6 +242,33 @@
        </contributionItemProvider>
    </extension>
    
+   <extension id="LogicExampleGroupContributionItemProvider" name="LogicExampleGroupContributionItemProvider" point="org.eclipse.gmf.runtime.common.ui.services.action.contributionItemProviders">
+      <contributionItemProvider class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContributionItemProvider">
+         <Priority name="Low">
+         </Priority>
+         <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
+            <popupStructuredContributionCriteria
+                  objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.IPrimaryEditPart"
+                  objectCount="2+">
+               <method
+                     name="getDiagramEditDomain().getEditorPart().getEditorSite().getId()"
+                     value="LogicEditor"/>     
+            </popupStructuredContributionCriteria>     
+            <popupAction path="/formatMenu/miscellaneousGroup" id="groupAction">
+            </popupAction>
+         </popupContribution>
+         <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
+            <popupStructuredContributionCriteria objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart">
+            	<method
+                     name="getDiagramEditDomain().getEditorPart().getEditorSite().getId()"
+                     value="LogicEditor"/>     
+            </popupStructuredContributionCriteria>                    
+            <popupAction path="/formatMenu/miscellaneousGroup" id="ungroupAction">
+            </popupAction>   
+         </popupContribution>                                 
+      </contributionItemProvider>
+   </extension>  
+   
    <extension id="LogicModelingAssistantProvider" name="%logic.provider.modelingassistant" point="org.eclipse.gmf.runtime.emf.ui.modelingAssistantProviders">
       <modelingAssistantProvider class="org.eclipse.gmf.examples.runtime.diagram.logic.internal.providers.LogicModelingAssistantProvider">
          <Priority name="Low"/>
diff --git a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/commands/GroupCommand.java b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/commands/GroupCommand.java
new file mode 100644
index 0000000..84a16bf
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/commands/GroupCommand.java
@@ -0,0 +1,170 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+package org.eclipse.gmf.runtime.diagram.core.commands;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.diagram.core.internal.l10n.DiagramCoreMessages;
+import org.eclipse.gmf.runtime.diagram.core.util.ViewType;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.gmf.runtime.notation.Bounds;
+import org.eclipse.gmf.runtime.notation.LayoutConstraint;
+import org.eclipse.gmf.runtime.notation.Location;
+import org.eclipse.gmf.runtime.notation.Node;
+import org.eclipse.gmf.runtime.notation.NotationFactory;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * This command groups node views (i.e. shapes) together. It creates a new group
+ * view and reparents the nodes passed in to be children of the group. The
+ * nodes' locations are also changed to be relative to the location of the
+ * group.
+ * 
+ * @author crevells, mmostafa
+ */
+public class GroupCommand
+    extends AbstractTransactionalCommand {
+
+    private List nodes;
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param editingDomain
+     *            the editing domain
+     * @param nodes
+     *            A list of nodes (i.e. shape views) that are to be grouped. The
+     *            nodes must all have the same parent.
+     */
+    public GroupCommand(TransactionalEditingDomain editingDomain, List nodes) {
+        this(editingDomain, nodes, null);
+    }
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param editingDomain
+     *            the editing domain
+     * @param nodes
+     *            A list of nodes (i.e. shape views) that are to be grouped. The
+     *            nodes must all have the same parent.
+     * @param options
+     *            for the transaction in which this command executes, or
+     *            <code>null</code> for the default options
+     */
+    public GroupCommand(TransactionalEditingDomain editingDomain, List nodes,
+            Map options) {
+        super(editingDomain, DiagramCoreMessages.GroupCommand_Label, options,
+            getWorkspaceFiles(nodes));
+        this.nodes = nodes;
+    }
+
+    /**
+     * Creates the new group, reparents the nodes, and sets the locations of the
+     * group and nodes as appropriate.\
+     */
+    protected CommandResult doExecuteWithResult(
+            IProgressMonitor progressMonitor, IAdaptable info)
+        throws ExecutionException {
+
+        Node group = NotationFactory.eINSTANCE.createNode();
+        group.setType(ViewType.GROUP);
+        group.setElement(null);
+
+        View parentView = (View) ((View) getNodes().get(0)).eContainer();
+
+        for (Iterator iter = getNodes().iterator(); iter.hasNext();) {
+            Object view = iter.next();
+            if (view instanceof Node) {
+                ((View) ((Node) view).eContainer()).removeChild((View) view);
+            }
+        }
+
+        parentView.getPersistedChildren().add(group);
+
+        int x = 0;
+        int y = 0;
+
+        boolean first = true;
+        for (Iterator iter = getNodes().iterator(); iter.hasNext();) {
+            Object view = iter.next();
+            if (view instanceof Node) {
+                LayoutConstraint layoutConstraint = ((Node) view)
+                    .getLayoutConstraint();
+                if (layoutConstraint instanceof Location) {
+                    Location location = (Location) layoutConstraint;
+                    if (first) {
+                        x = location.getX();
+                        y = location.getY();
+                        first = false;
+                    } else {
+                        if (x > location.getX())
+                            x = location.getX();
+                        if (y > location.getY())
+                            y = location.getY();
+                    }
+                }
+                group.insertChild((View) view);
+            }
+        }
+
+        Bounds groupBounds = NotationFactory.eINSTANCE.createBounds();
+        groupBounds.setX(x);
+        groupBounds.setY(y);
+        groupBounds.setWidth(-1);
+        groupBounds.setHeight(-1);
+        group.setLayoutConstraint(groupBounds);
+
+        translateChildrenLocations(x, y);
+        return CommandResult.newOKCommandResult(group);
+    }
+
+    /**
+     * Translate the location of the children to be relative to the group's
+     * location.
+     * 
+     * @param x
+     * @param y
+     */
+    protected void translateChildrenLocations(int x, int y) {
+        if (x == 0 && y == 0)
+            return;
+        for (Iterator iter = getNodes().iterator(); iter.hasNext();) {
+            Object view = iter.next();
+            if (view instanceof Node) {
+                LayoutConstraint layoutConstraint = ((Node) view)
+                    .getLayoutConstraint();
+                if (layoutConstraint instanceof Location) {
+                    Location location = (Location) layoutConstraint;
+                    location.setX(location.getX() - x);
+                    location.setY(location.getY() - y);
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the list of nodes to be grouped.
+     * 
+     * @return the list of nodes to be grouped
+     */
+    protected List getNodes() {
+        return nodes;
+    }
+
+}
diff --git a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/commands/UngroupCommand.java b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/commands/UngroupCommand.java
new file mode 100644
index 0000000..8d94bd1
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/commands/UngroupCommand.java
@@ -0,0 +1,122 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+package org.eclipse.gmf.runtime.diagram.core.commands;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.diagram.core.internal.l10n.DiagramCoreMessages;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.gmf.runtime.emf.type.core.commands.DestroyElementCommand;
+import org.eclipse.gmf.runtime.notation.LayoutConstraint;
+import org.eclipse.gmf.runtime.notation.Location;
+import org.eclipse.gmf.runtime.notation.Node;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * This command ungroups a group view. It reparents the children of the group so
+ * that their parent is the group's parent and it deletes the group view. The
+ * children's locations are also changed to be relative to the location of their
+ * new parent.
+ * 
+ * @author crevells
+ */
+public class UngroupCommand
+    extends AbstractTransactionalCommand {
+
+    private Node group;
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param editingDomain
+     *            the editing domain
+     * @param groupView
+     *            the group view to ungroup
+     */
+    public UngroupCommand(TransactionalEditingDomain editingDomain,
+            Node groupView) {
+        this(editingDomain, groupView, null);
+    }
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param editingDomain
+     *            the editing domain
+     * @param groupView
+     *            the group view to ungroup
+     * @param options
+     *            for the transaction in which this command executes, or
+     *            <code>null</code> for the default options
+     */
+    public UngroupCommand(TransactionalEditingDomain editingDomain,
+            Node group, Map options) {
+        super(editingDomain, DiagramCoreMessages.UngroupCommand_Label, options,
+            getWorkspaceFiles(group));
+        this.group = group;
+    }
+
+    protected CommandResult doExecuteWithResult(
+            IProgressMonitor progressMonitor, IAdaptable info)
+        throws ExecutionException {
+
+        translateChildrenLocations();
+
+        View parentView = (View) getGroup().eContainer();
+        if (parentView != null) {
+            parentView.getPersistedChildren().addAll(
+                getGroup().getPersistedChildren());
+        }
+        
+        DestroyElementCommand.destroy(getGroup());
+
+        return CommandResult.newOKCommandResult();
+    }
+
+    /**
+     * Translate the location of the children to no longer be relative to the
+     * group's location.
+     */
+    protected void translateChildrenLocations() {
+        Location groupLocation = (Location) getGroup().getLayoutConstraint();
+
+        for (Iterator iter = getGroup().getChildren().iterator(); iter
+            .hasNext();) {
+            Object child = iter.next();
+            if (child instanceof Node) {
+                LayoutConstraint layoutConstraint = ((Node) child)
+                    .getLayoutConstraint();
+                if (layoutConstraint instanceof Location) {
+                    Location location = (Location) layoutConstraint;
+                    location.setX(location.getX() + groupLocation.getX());
+                    location.setY(location.getY() + groupLocation.getY());
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Returns the group to be ungrouped.
+     * 
+     * @return the group to be ungrouped.
+     */
+    protected Node getGroup() {
+        return group;
+    }
+
+}
diff --git a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/edithelpers/NotationViewDependentsAdvice.java b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/edithelpers/NotationViewDependentsAdvice.java
index ead45a0..ebf2836 100644
--- a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/edithelpers/NotationViewDependentsAdvice.java
+++ b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/edithelpers/NotationViewDependentsAdvice.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2006 IBM Corporation and others.
+ * Copyright (c) 2006, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,6 +24,9 @@
 import org.eclipse.emf.transaction.util.TransactionUtil;
 import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
 import org.eclipse.gmf.runtime.common.core.command.ICommand;
+import org.eclipse.gmf.runtime.diagram.core.commands.UngroupCommand;
+import org.eclipse.gmf.runtime.diagram.core.internal.commands.AdjustGroupLocationCommand;
+import org.eclipse.gmf.runtime.diagram.core.util.ViewType;
 import org.eclipse.gmf.runtime.emf.core.util.CrossReferenceAdapter;
 import org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice;
 import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyDependentsRequest;
@@ -37,105 +40,128 @@
  * Edit helper advice for the {@link DestroyDependentsRequest} that destroys
  * notations views under the following circumstances:
  * <ul>
- *   <li>element being destroyed is the view's semantic referent</li>
- *   <li>element being destroyed is a Node or Edge to which an Edge is connected</li>
+ * <li>element being destroyed is the view's semantic referent</li>
+ * <li>element being destroyed is a Node or Edge to which an Edge is connected</li>
  * </ul>
- *
+ * 
  * @author Christian W. Damus (cdamus)
  */
 public class NotationViewDependentsAdvice extends AbstractEditHelperAdvice {
 
-	public ICommand getBeforeEditCommand(IEditCommandRequest request) {
-		if (request instanceof DestroyDependentsRequest) {
-			return getBeforeDestroyDependentsCommand((DestroyDependentsRequest) request);
-		}
-		return null;
-	}
-	
-	public ICommand getAfterEditCommand(IEditCommandRequest request) {		
-		return null;
-	}
-	
-	protected ICommand getBeforeDestroyDependentsCommand(
-			DestroyDependentsRequest request) {
-		
-		EObject destructee = request.getElementToDestroy();
+    public ICommand getBeforeEditCommand(IEditCommandRequest request) {
+        if (request instanceof DestroyDependentsRequest) {
+            return getBeforeDestroyDependentsCommand((DestroyDependentsRequest) request);
+        }
+        return null;
+    }
+
+    public ICommand getAfterEditCommand(IEditCommandRequest request) {
+        return null;
+    }
+
+    protected ICommand getBeforeDestroyDependentsCommand(
+            DestroyDependentsRequest request) {
+
+        EObject destructee = request.getElementToDestroy();
 		CrossReferenceAdapter crossReferenceAdapter = getCrossReferenceAdapter(request, destructee);
-		ICommand result = getDestroyDependentsCommand(destructee, request,
-				NotationPackage.Literals.VIEW__ELEMENT, crossReferenceAdapter);
-		// handle the node entries for views
-		if (destructee instanceof View) {
+        ICommand result = getDestroyDependentsCommand(destructee, request,
+            NotationPackage.Literals.VIEW__ELEMENT, crossReferenceAdapter);
+        // handle the node entries for views
+        if (destructee instanceof View) {
 			result = CompositeCommand.compose(result, getDestroyDependentsCommand(destructee, request,
 				NotationPackage.Literals.NODE_ENTRY__KEY, crossReferenceAdapter));
 
-			//  handle the edges connected to nodes or other edges        
-			if (destructee instanceof Node || destructee instanceof Edge) {
-				View view = (View) destructee;
+            // handle the edges connected to nodes or other edges
+            if (destructee instanceof Node || destructee instanceof Edge) {
+                View view = (View) destructee;
 
-				if (view.eIsSet(NotationPackage.Literals.VIEW__SOURCE_EDGES)) {
-					result = CompositeCommand.compose(result, request
-						.getDestroyDependentsCommand(view.getSourceEdges()));
-				}
-				if (view.eIsSet(NotationPackage.Literals.VIEW__TARGET_EDGES)) {
-					result = CompositeCommand.compose(result, request
-						.getDestroyDependentsCommand(view.getTargetEdges()));
-				}
-			}			
-		}
-		return result;
-	}
-	
-	private CrossReferenceAdapter getCrossReferenceAdapter(
-			DestroyDependentsRequest request, EObject destructee) {
-		
-		CrossReferenceAdapter crossReferenceAdapter = null;
-		Map cacheMaps = (Map) request.getParameter("Cache_Maps");//$NON-NLS-1$ RequestCacheEntries.Cache_Maps
-		if (cacheMaps != null) {
-			crossReferenceAdapter = (CrossReferenceAdapter) cacheMaps
-					.get("CrossRefAdapter");//$NON-NLS-1$ RequestCacheEntries.CrossRefAdapter
-		}
+                if (view.eIsSet(NotationPackage.Literals.VIEW__SOURCE_EDGES)) {
+                    result = CompositeCommand.compose(result, request
+                        .getDestroyDependentsCommand(view.getSourceEdges()));
+                }
+                if (view.eIsSet(NotationPackage.Literals.VIEW__TARGET_EDGES)) {
+                    result = CompositeCommand.compose(result, request
+                        .getDestroyDependentsCommand(view.getTargetEdges()));
+                }
+            }
+        }
 
-		if (crossReferenceAdapter == null) {
-			crossReferenceAdapter = CrossReferenceAdapter
-					.getExistingCrossReferenceAdapter(destructee);
-			if (crossReferenceAdapter == null) {
-				TransactionalEditingDomain domain = TransactionUtil
-						.getEditingDomain(destructee);
-				if (domain != null) {
-					crossReferenceAdapter = CrossReferenceAdapter
-							.getCrossReferenceAdapter(domain.getResourceSet());
-				}
-			}
-		}
-		return crossReferenceAdapter;
-	}
-	
-	
-	private ICommand getDestroyDependentsCommand(EObject destructee,
+        // handle deletion of groups
+        if (destructee instanceof Node) {
+            EObject parent = ((Node) destructee).eContainer();
+            if (parent instanceof Node
+                && ViewType.GROUP.equals(((Node) parent).getType())) {
+                if (((Node) parent).getChildren().size() == 2) {
+                    // There will only be one child of the group left after this
+                    // child is destroyed, so remove the group as well.
+                    result = CompositeCommand.compose(result,
+                        new UngroupCommand(request.getEditingDomain(),
+                            (Node) parent));
+                } else {
+                    // The remaining group's location may require changing after
+                    // the deletion.
+                    result = CompositeCommand.compose(result,
+                        new AdjustGroupLocationCommand(request
+                            .getEditingDomain(), (Node) parent));
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private CrossReferenceAdapter getCrossReferenceAdapter(
+            DestroyDependentsRequest request, EObject destructee) {
+
+        CrossReferenceAdapter crossReferenceAdapter = null;
+        Map cacheMaps = (Map) request.getParameter("Cache_Maps");//$NON-NLS-1$ RequestCacheEntries.Cache_Maps
+        if (cacheMaps != null) {
+            crossReferenceAdapter = (CrossReferenceAdapter) cacheMaps
+                .get("CrossRefAdapter");//$NON-NLS-1$ RequestCacheEntries.CrossRefAdapter
+        }
+
+        if (crossReferenceAdapter == null) {
+            crossReferenceAdapter = CrossReferenceAdapter
+                .getExistingCrossReferenceAdapter(destructee);
+            if (crossReferenceAdapter == null) {
+                TransactionalEditingDomain domain = TransactionUtil
+                    .getEditingDomain(destructee);
+                if (domain != null) {
+                    crossReferenceAdapter = CrossReferenceAdapter
+                        .getCrossReferenceAdapter(domain.getResourceSet());
+                }
+            }
+        }
+        return crossReferenceAdapter;
+    }
+
+    private ICommand getDestroyDependentsCommand(EObject destructee,
 			DestroyDependentsRequest request, EReference eRef, CrossReferenceAdapter crossReferenceAdapter) {
-		
-		if (crossReferenceAdapter != null) {
-			Collection revRefs = crossReferenceAdapter
-				.getNonNavigableInverseReferences(destructee);
-			if (revRefs.isEmpty() == false) {
-				Set set = null;
-				Iterator it = revRefs.iterator();
-				while (it.hasNext()) {
-					Setting setting = (Setting) it.next();
-					if (setting.getEStructuralFeature() == eRef) {
-						if (set == null) {
-							set = new HashSet();
-						}
-						set.add(setting.getEObject());
-					}
-				}
 
-				if (set != null) {
-					return request.getDestroyDependentsCommand(set);
-				}
-			}
-		}
+        if (crossReferenceAdapter != null) {
+            Collection revRefs = crossReferenceAdapter
+                .getNonNavigableInverseReferences(destructee);
+            if (revRefs.isEmpty() == false) {
+                Set set = null;
+                Iterator it = revRefs.iterator();
+                while (it.hasNext()) {
+                    Setting setting = (Setting) it.next();
+                    if (setting.getEStructuralFeature() == eRef) {
+                        if (set == null) {
+                            set = new HashSet();
+                        }
+                        set.add(setting.getEObject());
+                    }
+                }
 
-		return null;
-	}
+                if (set != null) {
+                    return request.getDestroyDependentsCommand(set);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    
 }
diff --git a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/commands/AdjustGroupLocationCommand.java b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/commands/AdjustGroupLocationCommand.java
new file mode 100644
index 0000000..1d09b9f
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/commands/AdjustGroupLocationCommand.java
@@ -0,0 +1,133 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.diagram.core.internal.commands;
+
+import java.util.Iterator;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.diagram.core.internal.l10n.DiagramCoreMessages;
+import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.gmf.runtime.notation.LayoutConstraint;
+import org.eclipse.gmf.runtime.notation.Location;
+import org.eclipse.gmf.runtime.notation.Node;
+import org.eclipse.gmf.runtime.notation.NotationPackage;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * This command will relocate the group so that the group's location reflects
+ * the location of the top-most and left-most shape. The locations of all the
+ * children will also be updated so that they are relative to the new location
+ * of the group. It can be used after a shape in the group has been moved,
+ * resized, or deleted.
+ * 
+ * @author crevells
+ */
+public class AdjustGroupLocationCommand
+    extends AbstractTransactionalCommand {
+
+    private View groupView;
+
+    /**
+     * Creates a new instance.
+     */
+    public AdjustGroupLocationCommand(TransactionalEditingDomain domain,
+            View groupView) {
+        super(domain, DiagramCoreMessages.AdjustLocation_Label,
+            getWorkspaceFiles(groupView));
+        this.groupView = groupView;
+    }
+
+    protected CommandResult doExecuteWithResult(IProgressMonitor monitor,
+            IAdaptable info)
+        throws ExecutionException {
+
+        int minChildX = Integer.MAX_VALUE;
+        int minChildY = Integer.MAX_VALUE;
+
+        for (Iterator iterator = groupView.getChildren().iterator(); iterator
+            .hasNext();) {
+            View childView = (View) iterator.next();
+
+            if (childView instanceof Node) {
+                LayoutConstraint layoutConstraint = ((Node) childView)
+                    .getLayoutConstraint();
+                if (layoutConstraint instanceof Location) {
+                    Location childLocation = (Location) layoutConstraint;
+
+                    if (childLocation.getX() < minChildX) {
+                        minChildX = childLocation.getX();
+                    }
+                    if (childLocation.getY() < minChildY) {
+                        minChildY = childLocation.getY();
+                    }
+                }
+            }
+        }
+
+        if (minChildX != 0) {
+
+            // The group's x location must change and consequently all the
+            // children x locations as they are relative to the group's
+            // location.
+
+            Integer x = (Integer) ViewUtil.getStructuralFeatureValue(groupView,
+                NotationPackage.eINSTANCE.getLocation_X());
+            ViewUtil.setStructuralFeatureValue(groupView,
+                NotationPackage.eINSTANCE.getLocation_X(), new Integer(x
+                    .intValue()
+                    + minChildX));
+
+            for (Iterator iterator = groupView.getChildren().iterator(); iterator
+                .hasNext();) {
+                View childView = (View) iterator.next();
+                x = (Integer) ViewUtil.getStructuralFeatureValue(childView,
+                    NotationPackage.eINSTANCE.getLocation_X());
+                ViewUtil.setStructuralFeatureValue(childView,
+                    NotationPackage.eINSTANCE.getLocation_X(), new Integer(x
+                        .intValue()
+                        - minChildX));
+            }
+        }
+
+        if (minChildY != 0) {
+
+            // The group's y location must change and consequently all the
+            // children y locations as they are relative to the group's
+            // location.
+
+            Integer y = (Integer) ViewUtil.getStructuralFeatureValue(groupView,
+                NotationPackage.eINSTANCE.getLocation_Y());
+            ViewUtil.setStructuralFeatureValue(groupView,
+                NotationPackage.eINSTANCE.getLocation_Y(), new Integer(y
+                    .intValue()
+                    + minChildY));
+
+            for (Iterator iterator = groupView.getChildren().iterator(); iterator
+                .hasNext();) {
+                View childView = (View) iterator.next();
+                y = (Integer) ViewUtil.getStructuralFeatureValue(childView,
+                    NotationPackage.eINSTANCE.getLocation_Y());
+                ViewUtil.setStructuralFeatureValue(childView,
+                    NotationPackage.eINSTANCE.getLocation_Y(), new Integer(y
+                        .intValue()
+                        - minChildY));
+            }
+        }
+        return CommandResult.newOKCommandResult();
+    }
+
+}
diff --git a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/l10n/DiagramCoreMessages.java b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/l10n/DiagramCoreMessages.java
index da80559..feaff66 100644
--- a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/l10n/DiagramCoreMessages.java
+++ b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/l10n/DiagramCoreMessages.java
@@ -37,6 +37,7 @@
     
     public static String GroupCommand_Label;
     public static String UngroupCommand_Label;
+    public static String AdjustLocation_Label;
 
 	static {
 		NLS.initializeMessages(BUNDLE_NAME, DiagramCoreMessages.class);
diff --git a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/l10n/DiagramCoreMessages.properties b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/l10n/DiagramCoreMessages.properties
index 53c9e24..1c936d2 100644
--- a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/l10n/DiagramCoreMessages.properties
+++ b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/internal/l10n/DiagramCoreMessages.properties
@@ -24,8 +24,9 @@
 SendBackwardCommand_Label=Send Backward
 SendToBackCommand_Label=Send To Back
 
-GroupCommand_Label = Group Shapes
-UngroupCommand_Label = Ungroup Shapes
+GroupCommand_Label = Group
+UngroupCommand_Label = Ungroup
+AdjustLocation_Label = Adjust Location
 
 # ===============================================================================
 # Diagram Internal - Translation Instruction : do not translate this section
diff --git a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/util/ViewType.java b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/util/ViewType.java
index d9fc012..a0f42ba 100644
--- a/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/util/ViewType.java
+++ b/org.eclipse.gmf.runtime.diagram.core/src/org/eclipse/gmf/runtime/diagram/core/util/ViewType.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -39,5 +39,10 @@
 	 * the diagram link semantic hint
 	 */
 	public static String DIAGRAM_LINK = "DiagramLink"; //$NON-NLS-1$
-	
+
+    /**
+     * the group semantic hint
+     */
+    public static String GROUP = "Group"; //$NON-NLS-1$
+
 }
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/icons/dlcl16/group.gif b/org.eclipse.gmf.runtime.diagram.ui.actions/icons/dlcl16/group.gif
new file mode 100644
index 0000000..8f6a925
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/icons/dlcl16/group.gif
Binary files differ
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/icons/dlcl16/ungroup.gif b/org.eclipse.gmf.runtime.diagram.ui.actions/icons/dlcl16/ungroup.gif
new file mode 100644
index 0000000..7373b3a
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/icons/dlcl16/ungroup.gif
Binary files differ
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/icons/elcl16/group.gif b/org.eclipse.gmf.runtime.diagram.ui.actions/icons/elcl16/group.gif
new file mode 100644
index 0000000..43547d5
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/icons/elcl16/group.gif
Binary files differ
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/icons/elcl16/ungroup.gif b/org.eclipse.gmf.runtime.diagram.ui.actions/icons/elcl16/ungroup.gif
new file mode 100644
index 0000000..7d184af
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/icons/elcl16/ungroup.gif
Binary files differ
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/ArrangeAction.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/ArrangeAction.java
index b3d5d0d..1c7faac 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/ArrangeAction.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/ArrangeAction.java
@@ -34,6 +34,7 @@
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsPluginImages;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.editparts.IEditableEditPart;
@@ -50,310 +51,322 @@
  */
 public class ArrangeAction extends DiagramAction {
 
-	private boolean selectionOnly;
+    private boolean selectionOnly;
 
-	/**
-	 * @param workbenchPage
-	 */
-	protected ArrangeAction(
-		IWorkbenchPage workbenchPage,
-		boolean selectionOnly) {
-		super(workbenchPage);
-		this.selectionOnly = selectionOnly;
-	}
+    /**
+     * @param workbenchPage
+     */
+    protected ArrangeAction(
+        IWorkbenchPage workbenchPage,
+        boolean selectionOnly) {
+        super(workbenchPage);
+        this.selectionOnly = selectionOnly;
+    }
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction#createTargetRequest()
-	 */
-	protected Request createTargetRequest() {
-		return new ArrangeRequest(getId());
-	}
+    /* (non-Javadoc)
+     * @see org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction#createTargetRequest()
+     */
+    protected Request createTargetRequest() {
+        return new ArrangeRequest(getId());
+    }
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction#updateTargetRequest()
-	 */
-	protected void updateTargetRequest() {
-		ArrangeRequest request = (ArrangeRequest) getTargetRequest();
-		request.setPartsToArrange(getOperationSet());
-	}
+    /* (non-Javadoc)
+     * @see org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction#updateTargetRequest()
+     */
+    protected void updateTargetRequest() {
+        ArrangeRequest request = (ArrangeRequest) getTargetRequest();
+        request.setPartsToArrange(getOperationSet());
+    }
 
-	private boolean isArrangeAll() {
-		return !selectionOnly;
-	}
+    private boolean isArrangeAll() {
+        return !selectionOnly;
+    }
 
-	protected Command getCommand() {
-		CompoundCommand arrangeCC = new CompoundCommand(getLabel());
-		if (isArrangeAll()) {
-			List elements = getOperationSet();
-			for (Iterator iter = elements.iterator(); iter.hasNext();) {
-				EditPart element = (EditPart) iter.next();
-				Command cmd = element.getCommand(getTargetRequest());
-				if (cmd != null)
-					arrangeCC.add(cmd);
-			}
-		} else if (getOperationSet().size() >= 2) {
-			EditPart parent = getSelectionParent(getOperationSet());
-			if (parent != null) {
-				Command cmd = parent.getCommand(getTargetRequest());
-				if (cmd != null)
-					arrangeCC.add(cmd);
-			}
-		}
-		return arrangeCC;
-	}
+    protected Command getCommand() {
+        CompoundCommand arrangeCC = new CompoundCommand(getLabel());
+        if (isArrangeAll()) {
+            List elements = getOperationSet();
+            for (Iterator iter = elements.iterator(); iter.hasNext();) {
+                EditPart element = (EditPart) iter.next();
+                Command cmd = element.getCommand(getTargetRequest());
+                if (cmd != null)
+                    arrangeCC.add(cmd);
+            }
+        } else if (getOperationSet().size() >= 2) {
+            EditPart parent = getSelectionParent(getOperationSet());
+            if (parent != null) {
+                Command cmd = parent.getCommand(getTargetRequest());
+                if (cmd != null)
+                    arrangeCC.add(cmd);
+            }
+        }
+        return arrangeCC;
+    }
 
-	/**
-	 * Action is enabled if arrange all. If arrange selection, action is enabled
-	 * if the operation set's parent has XYLayout and there is atleast 2
-	 * siblings to arrange
-	 * 
-	 * @see org.eclipse.gef.ui.actions.EditorPartAction#calculateEnabled()
-	 */
-	protected boolean calculateEnabled() {
-		
-		List operationSet = getOperationSet();
-		
-		//arrange all, always enable
-		if( isArrangeAll() && !operationSet.isEmpty()){
-			return true;
-		}
+    /**
+     * Action is enabled if arrange all. If arrange selection, action is enabled
+     * if the operation set's parent has XYLayout and there is atleast 2
+     * siblings to arrange
+     * 
+     * @see org.eclipse.gef.ui.actions.EditorPartAction#calculateEnabled()
+     */
+    protected boolean calculateEnabled() {
+        
+        List operationSet = getOperationSet();
+        
+        //arrange all, always enable
+        if( isArrangeAll() && !operationSet.isEmpty()){
+            return true;
+        }
 
-		EditPart parentEP = getSelectionParent(operationSet);
-		
-		// bugzilla 156733: disable this action if the parent or selected edit parts are not editable
-		if ((parentEP instanceof IEditableEditPart)
-				&& !((IEditableEditPart) parentEP)
-						.isEditModeEnabled()) {
-			return false;
-		}
-		
-		for (Iterator i = operationSet.iterator(); i.hasNext();) {
-			Object next = i.next();
-			if ((next instanceof IEditableEditPart)
-					&& !((IEditableEditPart) next)
-							.isEditModeEnabled()) {
-				return false;
-			}
-		}
-		
-		//arrange selection
-		if (operationSet.size() >= 2) {
-			if (parentEP instanceof GraphicalEditPart) {
-				GraphicalEditPart parent = (GraphicalEditPart)parentEP;
-				if ((parent != null) &&(parent.getContentPane().getLayoutManager() instanceof XYLayout))
-					return true;
-			}
-		}
-		return false;
-	}
+        EditPart parentEP = getSelectionParent(operationSet);
+        
+        // bugzilla 156733: disable this action if the parent or selected edit parts are not editable
+        if ((parentEP instanceof IEditableEditPart)
+                && !((IEditableEditPart) parentEP)
+                        .isEditModeEnabled()) {
+            return false;
+        }
+        
+        for (Iterator i = operationSet.iterator(); i.hasNext();) {
+            Object next = i.next();
+            if ((next instanceof IEditableEditPart)
+                    && !((IEditableEditPart) next)
+                            .isEditModeEnabled()) {
+                return false;
+            }
+        }
+        
+        //arrange selection
+        if (operationSet.size() >= 2) {
+            if (parentEP instanceof GraphicalEditPart) {
+                GraphicalEditPart parent = (GraphicalEditPart)parentEP;
+                if ((parent != null) &&(parent.getContentPane().getLayoutManager() instanceof XYLayout))
+                    return true;
+            }
+        } else if (operationSet.size() == 1
+            && operationSet.get(0) instanceof GroupEditPart) {
+            return true;
+        }
+        return false;
+    }
 
-	/* 
-	 * The operation set is the shapes, connections or both on the diagrm edit part
-	 * (non-Javadoc)
-	 * @see org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction#createOperationSet()
-	 */
-	protected List createOperationSet() {
-		List selection = getSelectedObjects();
-		
-		if( isArrangeAll() ) {
-			if( !selection.isEmpty()){
-				return getElementsToArrange(selection);
-			}
-			if( getDiagramEditPart() != null )				
-				return createOperationSet(getDiagramEditPart().getChildren());
+    /* 
+     * The operation set is the shapes, connections or both on the diagrm edit part
+     * (non-Javadoc)
+     * @see org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction#createOperationSet()
+     */
+    protected List createOperationSet() {
+        List selection = getSelectedObjects();
+        
+        if( isArrangeAll() ) {
+            if( !selection.isEmpty()){
+                return getElementsToArrange(selection);
+            }
+            if( getDiagramEditPart() != null )              
+                return createOperationSet(getDiagramEditPart().getChildren());
 
-			return Collections.EMPTY_LIST;
-		}
+            return Collections.EMPTY_LIST;
+        }
 
-		if (selection.isEmpty() ||
-				!(selection.get(0) instanceof IGraphicalEditPart))
-			return Collections.EMPTY_LIST;
+        if (selection.isEmpty() ||
+                !(selection.get(0) instanceof IGraphicalEditPart))
+            return Collections.EMPTY_LIST;
 
-		selection = ToolUtilities.getSelectionWithoutDependants(selection);
-		return createOperationSet(selection);
-	}
+        selection = ToolUtilities.getSelectionWithoutDependants(selection);
+        return createOperationSet(selection);
+    }
 
-	/**
-	 * getSelectionParent
-	 * Utility to return the logical parent of the selection list
-	 * 
-	 * @param editparts List to parse for a common parent.
-	 * @return EditPart that is the parent or null if a common parent doesn't exist.
-	 */
-	private EditPart getSelectionParent(List editparts) {
-		ListIterator li = editparts.listIterator();
-		while (li.hasNext()) {
-			Object obj = li.next();
-			if (!(obj instanceof ConnectionEditPart) && obj instanceof EditPart) {
-				return ((EditPart)obj).getParent();
-			}
-		}
-		
-		return null;
-	}
-	
-	private List createOperationSet(List editparts) {
-		if (editparts == null || editparts.isEmpty())
-			return Collections.EMPTY_LIST;
-		EditPart parent = getSelectionParent(editparts);
-		if (parent == null)
-			return Collections.EMPTY_LIST;
-		
-		for (int i = 1; i < editparts.size(); i++) {
-			EditPart part = (EditPart) editparts.get(i);
-			if (part instanceof ConnectionEditPart){
-				continue;
-			}
-			if (part.getParent() != parent)
-				return Collections.EMPTY_LIST;
-		}
-		return editparts;
-	}
+    /**
+     * getSelectionParent
+     * Utility to return the logical parent of the selection list
+     * 
+     * @param editparts List to parse for a common parent.
+     * @return EditPart that is the parent or null if a common parent doesn't exist.
+     */
+    private EditPart getSelectionParent(List editparts) {
+        ListIterator li = editparts.listIterator();
+        while (li.hasNext()) {
+            Object obj = li.next();
+            if (!(obj instanceof ConnectionEditPart) && obj instanceof EditPart) {
+                return ((EditPart)obj).getParent();
+            }
+        }
+        
+        return null;
+    }
+    
+    private List createOperationSet(List editparts) {
+        if (editparts == null || editparts.isEmpty())
+            return Collections.EMPTY_LIST;
+        
+        EditPart parent;
+        if (editparts.size() == 1 && editparts.get(0) instanceof GroupEditPart) {
+             GroupEditPart groupEP = (GroupEditPart) editparts.get(0);
+            parent = groupEP;
+            editparts = groupEP.getChildren();
+        } else {
+            parent = getSelectionParent(editparts);
+        }
+        
+        if (parent == null)
+            return Collections.EMPTY_LIST;
+        
+        for (int i = 1; i < editparts.size(); i++) {
+            EditPart part = (EditPart) editparts.get(i);
+            if (part instanceof ConnectionEditPart){
+                continue;
+            }
+            if (part.getParent() != parent)
+                return Collections.EMPTY_LIST;
+        }
+        return editparts;
+    }
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.gmf.runtime.common.ui.action.AbstractActionHandler#isSelectionListener()
-	 */
-	protected boolean isSelectionListener() {
-		return true;
-	}
+    /* (non-Javadoc)
+     * @see org.eclipse.gmf.runtime.common.ui.action.AbstractActionHandler#isSelectionListener()
+     */
+    protected boolean isSelectionListener() {
+        return true;
+    }
 
-	/**
-	 * Creates the Arrange All action
-	 * @param workbenchPage
-	 */
-	public static ArrangeAction createArrangeAllAction(IWorkbenchPage workbenchPage) {
-		ArrangeAction action = new ArrangeAction(workbenchPage,false);
-		action.setId(ActionIds.ACTION_ARRANGE_ALL);
-		action.setText(DiagramUIActionsMessages.ArrangeAction_ArrangeAll_ActionLabelText);
-		action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_ArrangeAll_ActionToolTipText);
-		
-		action
-			.setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
-		action
-			.setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL_DISABLED);
-		action
-			.setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
-		return action;
-	}
-	
-	/**
-	 * Creates the Arrange All action for the toolbar menu
-	 * @param workbenchPage
-	 */
-	public static ArrangeAction createToolbarArrangeAllAction(IWorkbenchPage workbenchPage) {
-		ArrangeAction action = new ArrangeAction(workbenchPage, false);
-		action.setId(ActionIds.ACTION_TOOLBAR_ARRANGE_ALL);
-		action.setText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeAll_ActionLabelText);
-		action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeAll_ActionToolTipText);
-		
-		action
-			.setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
-		action
-			.setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL_DISABLED);
-		action
-			.setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
-		return action;
-	}
+    /**
+     * Creates the Arrange All action
+     * @param workbenchPage
+     */
+    public static ArrangeAction createArrangeAllAction(IWorkbenchPage workbenchPage) {
+        ArrangeAction action = new ArrangeAction(workbenchPage,false);
+        action.setId(ActionIds.ACTION_ARRANGE_ALL);
+        action.setText(DiagramUIActionsMessages.ArrangeAction_ArrangeAll_ActionLabelText);
+        action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_ArrangeAll_ActionToolTipText);
+        
+        action
+            .setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
+        action
+            .setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL_DISABLED);
+        action
+            .setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
+        return action;
+    }
+    
+    /**
+     * Creates the Arrange All action for the toolbar menu
+     * @param workbenchPage
+     */
+    public static ArrangeAction createToolbarArrangeAllAction(IWorkbenchPage workbenchPage) {
+        ArrangeAction action = new ArrangeAction(workbenchPage, false);
+        action.setId(ActionIds.ACTION_TOOLBAR_ARRANGE_ALL);
+        action.setText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeAll_ActionLabelText);
+        action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeAll_ActionToolTipText);
+        
+        action
+            .setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
+        action
+            .setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL_DISABLED);
+        action
+            .setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
+        return action;
+    }
 
-	/**
-	 * Creates the Arrange Selection Only action
-	 * @param workbenchPage
-	 */
-	public static ArrangeAction createArrangeSelectionAction(IWorkbenchPage workbenchPage) {
-		ArrangeAction action = new ArrangeAction(workbenchPage, true);
-		action.setId(ActionIds.ACTION_ARRANGE_SELECTION);
-		action.setText(DiagramUIActionsMessages.ArrangeAction_ArrangeSelection_ActionLabelText);
-		action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_ArrangeSelection_ActionToolTipText);
-		
-		action
-			.setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
-		action
-			.setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED_DISABLED);
-		action
-			.setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
-		return action;
-	}
-	
-	/**
-	 * Creates the Arrange Selection Only action for the toolbar menu
-	 * @param workbenchPage
-	 */
-	public static ArrangeAction createToolbarArrangeSelectionAction(IWorkbenchPage workbenchPage) {
-		ArrangeAction action = new ArrangeAction(workbenchPage, true);
-		action.setId(ActionIds.ACTION_TOOLBAR_ARRANGE_SELECTION);
-		action.setText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeSelection_ActionLabelText);
-		action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeSelection_ActionToolTipText);
-		
-		action
-			.setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
-		action
-			.setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED_DISABLED);
-		action
-			.setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
-		return action;
-	}
-	
-	protected void doRun(IProgressMonitor progressMonitor) {
-		IPreferenceStore preferenceStore = (IPreferenceStore) getDiagramEditPart().getDiagramPreferencesHint().getPreferenceStore();
-		boolean animatedLayout = preferenceStore.getBoolean(
-			IPreferenceConstants.PREF_ENABLE_ANIMATED_LAYOUT);
-		
-		if (animatedLayout)
-			Animation.markBegin();
-			
-		super.doRun(progressMonitor);
-		
-		if (animatedLayout) {
-			int durationInc = 800;
-			int factor = 10;
-			int size = 0;
-			
-			List operationSet = getOperationSet();
-			if (isArrangeAll()){
-				for (Iterator iter = operationSet.iterator(); iter.hasNext();) {
-					IGraphicalEditPart element = (IGraphicalEditPart) iter.next();
-					size += element.getFigure().getChildren().size();
-				}
-			}
-			else if (operationSet != null && !operationSet.isEmpty()) {
-				IGraphicalEditPart container = (IGraphicalEditPart)getSelectionParent(operationSet);
-				size += container.getFigure().getChildren().size();
-			}
-			
-			int totalDuration = Math.min(durationInc * factor / 2, Math.max(durationInc, (size / 
-					factor) * durationInc));
-			
-			Animation.run(totalDuration);
-		}
-	}
-	
-	/**
-	 * @param selection
-	 * @return
-	 */
-	private List getElementsToArrange(List selection) {
-		Set parentsSet = new HashSet();
-		for (Iterator iter = selection.iterator(); iter.hasNext();) {
-			Object element = iter.next();
-			if (element instanceof ShapeCompartmentEditPart || element instanceof DiagramEditPart){
-				parentsSet.add(element);
-			} else if (element instanceof EditPart){
-				EditPart gEditPart = 
-					(EditPart)element;
-				EditPart parentEditPart = gEditPart.getParent();
-				if (parentEditPart instanceof ShapeCompartmentEditPart ||
-					parentEditPart instanceof DiagramEditPart){
-					if (!parentsSet.contains(parentEditPart))
-						parentsSet.add(parentEditPart);
-				}
-			}
-		}
-		if (parentsSet.isEmpty())
-			return Collections.EMPTY_LIST;
-		List elements = new ArrayList();
-		elements.addAll(parentsSet);			
-		return elements;
-	}
+    /**
+     * Creates the Arrange Selection Only action
+     * @param workbenchPage
+     */
+    public static ArrangeAction createArrangeSelectionAction(IWorkbenchPage workbenchPage) {
+        ArrangeAction action = new ArrangeAction(workbenchPage, true);
+        action.setId(ActionIds.ACTION_ARRANGE_SELECTION);
+        action.setText(DiagramUIActionsMessages.ArrangeAction_ArrangeSelection_ActionLabelText);
+        action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_ArrangeSelection_ActionToolTipText);
+        
+        action
+            .setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
+        action
+            .setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED_DISABLED);
+        action
+            .setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
+        return action;
+    }
+    
+    /**
+     * Creates the Arrange Selection Only action for the toolbar menu
+     * @param workbenchPage
+     */
+    public static ArrangeAction createToolbarArrangeSelectionAction(IWorkbenchPage workbenchPage) {
+        ArrangeAction action = new ArrangeAction(workbenchPage, true);
+        action.setId(ActionIds.ACTION_TOOLBAR_ARRANGE_SELECTION);
+        action.setText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeSelection_ActionLabelText);
+        action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeSelection_ActionToolTipText);
+        
+        action
+            .setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
+        action
+            .setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED_DISABLED);
+        action
+            .setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
+        return action;
+    }
+    
+    protected void doRun(IProgressMonitor progressMonitor) {
+        IPreferenceStore preferenceStore = (IPreferenceStore) getDiagramEditPart().getDiagramPreferencesHint().getPreferenceStore();
+        boolean animatedLayout = preferenceStore.getBoolean(
+            IPreferenceConstants.PREF_ENABLE_ANIMATED_LAYOUT);
+        
+        if (animatedLayout)
+            Animation.markBegin();
+            
+        super.doRun(progressMonitor);
+        
+        if (animatedLayout) {
+            int durationInc = 800;
+            int factor = 10;
+            int size = 0;
+            
+            List operationSet = getOperationSet();
+            if (isArrangeAll()){
+                for (Iterator iter = operationSet.iterator(); iter.hasNext();) {
+                    IGraphicalEditPart element = (IGraphicalEditPart) iter.next();
+                    size += element.getFigure().getChildren().size();
+                }
+            }
+            else if (operationSet != null && !operationSet.isEmpty()) {
+                IGraphicalEditPart container = (IGraphicalEditPart)getSelectionParent(operationSet);
+                size += container.getFigure().getChildren().size();
+            }
+            
+            int totalDuration = Math.min(durationInc * factor / 2, Math.max(durationInc, (size / 
+                    factor) * durationInc));
+            
+            Animation.run(totalDuration);
+        }
+    }
+    
+    /**
+     * @param selection
+     * @return
+     */
+    private List getElementsToArrange(List selection) {
+        Set parentsSet = new HashSet();
+        for (Iterator iter = selection.iterator(); iter.hasNext();) {
+            Object element = iter.next();
+            if (element instanceof ShapeCompartmentEditPart || element instanceof DiagramEditPart){
+                parentsSet.add(element);
+            } else if (element instanceof EditPart){
+                EditPart gEditPart = 
+                    (EditPart)element;
+                EditPart parentEditPart = gEditPart.getParent();
+                if (parentEditPart instanceof ShapeCompartmentEditPart ||
+                    parentEditPart instanceof DiagramEditPart){
+                    if (!parentsSet.contains(parentEditPart))
+                        parentsSet.add(parentEditPart);
+                }
+            }
+        }
+        if (parentsSet.isEmpty())
+            return Collections.EMPTY_LIST;
+        List elements = new ArrayList();
+        elements.addAll(parentsSet);            
+        return elements;
+    }
 
 }
 
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/ColorPropertyContributionItem.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/ColorPropertyContributionItem.java
index 91a74fe..e263a37 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/ColorPropertyContributionItem.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/ColorPropertyContributionItem.java
@@ -22,6 +22,7 @@
 import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsPluginImages;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.properties.Properties;
 import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities;
@@ -658,5 +659,18 @@
 			disabledBasicImageData);
 	}
 
+  
+    protected List getTargetEditParts(EditPart editpart) {
+        if (editpart instanceof GroupEditPart) {
+            List list = new ArrayList();
+            for (Iterator iter = ((GroupEditPart) editpart)
+                .getFlattenedChildren().iterator(); iter.hasNext();) {
+                list.addAll(getTargetEditParts((EditPart) iter.next()));
+            }
+            return list;
+        } else {
+            return super.getTargetEditParts(editpart);
+        }
+    }
 
 }
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/DeleteFromDiagramAction.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/DeleteFromDiagramAction.java
index fc5d69f..1b40ecb 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/DeleteFromDiagramAction.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/DeleteFromDiagramAction.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -27,6 +27,7 @@
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editpolicies.CanonicalEditPolicy;
 import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
@@ -227,6 +228,9 @@
 	 */
 	private boolean isCanonical(IGraphicalEditPart gep) {
 		EditPart parent = gep.getParent();
+        while (parent instanceof GroupEditPart) {
+            parent = parent.getParent();
+        }
 		if (parent instanceof IGraphicalEditPart) {
 			CanonicalEditPolicy cep = (CanonicalEditPolicy)parent.getEditPolicy(EditPolicyRoles.CANONICAL_ROLE);
 			if ( cep != null ) {
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/DuplicateActionDelegate.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/DuplicateActionDelegate.java
index 5f2036e..ef8ee3b 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/DuplicateActionDelegate.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/DuplicateActionDelegate.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -32,6 +32,7 @@
 import org.eclipse.gmf.runtime.common.core.util.Trace;
 import org.eclipse.gmf.runtime.common.ui.action.AbstractActionDelegate;
 import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer;
 import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
@@ -170,6 +171,12 @@
 		List eps = new ArrayList();
 		for (Iterator i = selection.iterator(); i.hasNext();) {
 			Object selectedItem = i.next();
+            
+            // Disable duplicate on groups for now.  See bugzilla 182972.
+            if (selectedItem instanceof GroupEditPart) {
+                return null;
+            }
+            
 			if (selectedItem instanceof IGraphicalEditPart) {
 				eps.add(selectedItem);
 			}
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontDialogAction.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontDialogAction.java
index 278dc41..f528117 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontDialogAction.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontDialogAction.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,11 +11,17 @@
 
 package org.eclipse.gmf.runtime.diagram.ui.actions.internal;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.gef.EditPart;
 import org.eclipse.gef.commands.CompoundCommand;
 import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsPluginImages;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.actions.PropertyChangeAction;
 import org.eclipse.gmf.runtime.diagram.ui.internal.properties.Properties;
 import org.eclipse.gmf.runtime.diagram.ui.requests.ChangePropertyValueRequest;
@@ -89,4 +95,17 @@
 		}
 	}
 
+    protected List getTargetEditParts(EditPart editpart) {
+        if (editpart instanceof GroupEditPart) {
+            List targetedEPs = new ArrayList();
+            for (Iterator iter = ((GroupEditPart) editpart)
+                .getFlattenedChildren().iterator(); iter.hasNext();) {
+                EditPart childEP = (EditPart) iter.next();
+                targetedEPs.addAll(getTargetEditParts(childEP));
+            }
+            return targetedEPs;
+        } else {
+            return super.getTargetEditParts(editpart);
+        }
+    }
 }
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontNameContributionItem.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontNameContributionItem.java
index 1842a47..f2f849d 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontNameContributionItem.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontNameContributionItem.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,8 +11,14 @@
 
 package org.eclipse.gmf.runtime.diagram.ui.actions.internal;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.gef.EditPart;
 import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.properties.Properties;
 import org.eclipse.gmf.runtime.diagram.ui.internal.util.FontHelper;
 import org.eclipse.gmf.runtime.diagram.ui.internal.util.IUIConstants;
@@ -107,4 +113,17 @@
 	protected boolean isOperationHistoryListener() {
 		return true;
 	}
+    
+    protected List getTargetEditParts(EditPart editpart) {
+        if (editpart instanceof GroupEditPart) {
+            List list = new ArrayList();
+            for (Iterator iter = ((GroupEditPart) editpart)
+                .getFlattenedChildren().iterator(); iter.hasNext();) {
+                list.addAll(getTargetEditParts((EditPart) iter.next()));
+            }
+            return list;
+        } else {
+            return super.getTargetEditParts(editpart);
+        }
+    }
 }
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontSizeContributionItem.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontSizeContributionItem.java
index dae3737..dfd8e68 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontSizeContributionItem.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontSizeContributionItem.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,8 +11,14 @@
 
 package org.eclipse.gmf.runtime.diagram.ui.actions.internal;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.gef.EditPart;
 import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.properties.Properties;
 import org.eclipse.gmf.runtime.diagram.ui.internal.util.FontHelper;
 import org.eclipse.gmf.runtime.diagram.ui.internal.util.IUIConstants;
@@ -105,5 +111,17 @@
     protected boolean isOperationHistoryListener() {
         return true;
     }
-
+    
+    protected List getTargetEditParts(EditPart editpart) {
+        if (editpart instanceof GroupEditPart) {
+            List list = new ArrayList();
+            for (Iterator iter = ((GroupEditPart) editpart)
+                .getFlattenedChildren().iterator(); iter.hasNext();) {
+                list.addAll(getTargetEditParts((EditPart) iter.next()));
+            }
+            return list;
+        } else {
+            return super.getTargetEditParts(editpart);
+        }
+    }
 }
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontStyleAction.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontStyleAction.java
index c432b4c..decc412 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontStyleAction.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/FontStyleAction.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2004 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,10 +11,16 @@
 
 package org.eclipse.gmf.runtime.diagram.ui.actions.internal;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.gef.EditPart;
 import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
 import org.eclipse.gmf.runtime.diagram.ui.actions.BooleanPropertyAction;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsPluginImages;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.l10n.DiagramUIPluginImages;
 import org.eclipse.gmf.runtime.diagram.ui.internal.properties.Properties;
 import org.eclipse.ui.IWorkbenchPage;
@@ -76,5 +82,18 @@
 		action.setDisabledImageDescriptor(DiagramUIPluginImages.DESC_ITALIC_DISABLED);
 		return action;
 	}
-
+    
+    protected List getTargetEditParts(EditPart editpart) {
+        if (editpart instanceof GroupEditPart) {
+            List targetedEPs = new ArrayList();
+            for (Iterator iter = ((GroupEditPart) editpart)
+                .getFlattenedChildren().iterator(); iter.hasNext();) {
+                EditPart childEP = (EditPart) iter.next();
+                targetedEPs.addAll(getTargetEditParts(childEP));
+            }
+            return targetedEPs;
+        } else {
+            return super.getTargetEditParts(editpart);
+        }
+    }
 }
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/GroupAction.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/GroupAction.java
new file mode 100644
index 0000000..4bc090d
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/GroupAction.java
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.diagram.ui.actions.internal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.commands.UnexecutableCommand;
+import org.eclipse.gef.requests.GroupRequest;
+import org.eclipse.gef.tools.ToolUtilities;
+import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
+import org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction;
+import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
+import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsPluginImages;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.ui.IWorkbenchPage;
+
+/**
+ * An action to group shapes together.
+ * 
+ * @author mmostafa, crevells
+ */
+public class GroupAction
+    extends DiagramAction {
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param workbenchPage
+     */
+    public GroupAction(IWorkbenchPage workbenchPage) {
+        super(workbenchPage);
+        setId(ActionIds.ACTION_GROUP);
+        setText(DiagramUIActionsMessages.GroupAction_Group_ActionLabelText);
+        setToolTipText(DiagramUIActionsMessages.GroupAction_Group_ActionToolTipText);
+        setImageDescriptor(DiagramUIActionsPluginImages.DESC_GROUP);
+        setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_GROUP_DISABLED);
+        setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_GROUP);
+    }
+
+    protected Request createTargetRequest() {
+        return new GroupRequest(getId());
+    }
+
+    protected void updateTargetRequest() {
+        GroupRequest request = (GroupRequest) getTargetRequest();
+        request.setEditParts(getOperationSet());
+    }
+
+    protected Command getCommand() {
+        if (getOperationSet().size() > 1) {
+            EditPart parent = ((EditPart) getOperationSet().get(0)).getParent();
+            return parent.getCommand(getTargetRequest());
+        }
+        return UnexecutableCommand.INSTANCE;
+    }
+
+    protected List createOperationSet() {
+        List selection = getSelectedObjects();
+        if (selection.size() <= 1
+            || !(selection.get(0) instanceof IGraphicalEditPart))
+            return Collections.EMPTY_LIST;
+
+        return ToolUtilities.getSelectionWithoutDependants(selection);
+    }
+
+    protected boolean isSelectionListener() {
+        return true;
+    }
+
+    protected void doRun(IProgressMonitor progressMonitor) {
+
+        super.doRun(progressMonitor);
+
+        Object model = ((EditPart) ((GroupRequest) getTargetRequest())
+            .getEditParts().get(0)).getModel();
+        if (model instanceof View) {
+            Object groupView = ((View) model).eContainer();
+            Object groupEP = getDiagramGraphicalViewer().getEditPartRegistry()
+                .get(groupView);
+            if (groupEP != null) {
+                getDiagramGraphicalViewer().setSelection(
+                    new StructuredSelection(groupEP));
+            }
+        }
+    }
+
+}
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/SelectAllAction.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/SelectAllAction.java
index aff669f..c48ec67 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/SelectAllAction.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/SelectAllAction.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -28,6 +28,7 @@
 import org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsPluginImages;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderItemEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
@@ -134,7 +135,12 @@
 			else {
 				if (editpart.isSelectable())
 					retval.add(editpart);
-				getSelectableChildrenNodes(editpart, retval);
+
+                // Do not dig into groups -- just select the group, but not the
+                // shapes inside.
+                if (!(editpart instanceof GroupEditPart)) {
+                    getSelectableChildrenNodes(editpart, retval);
+                }
 			}
 		}
 	}
@@ -179,7 +185,11 @@
 		Set connnectableEditParts = new HashSet(editparts);
 		ListIterator li = editparts.listIterator();
 		while (li.hasNext()) {
-			getBorderItemEditParts((EditPart)li.next(), connnectableEditParts);
+            EditPart ep = (EditPart)li.next();
+			getBorderItemEditParts(ep, connnectableEditParts);
+            if (ep instanceof GroupEditPart) {
+                connnectableEditParts.addAll(((GroupEditPart)ep).getFlattenedChildren());
+            }
 		}
 		
 		if (diagramEditPart != null) {
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/UngroupAction.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/UngroupAction.java
new file mode 100644
index 0000000..8c9bd38
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/UngroupAction.java
@@ -0,0 +1,52 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.diagram.ui.actions.internal;
+
+import org.eclipse.gef.Request;
+import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
+import org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction;
+import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
+import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsPluginImages;
+import org.eclipse.ui.IWorkbenchPage;
+
+/**
+ * An action to ungroup a group of shapes.
+ * 
+ * @author crevells
+ */
+public class UngroupAction
+    extends DiagramAction {
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param workbenchPage
+     */
+    public UngroupAction(IWorkbenchPage workbenchPage) {
+        super(workbenchPage);
+        setId(ActionIds.ACTION_UNGROUP);
+        setText(DiagramUIActionsMessages.GroupAction_Ungroup_ActionLabelText);
+        setToolTipText(DiagramUIActionsMessages.GroupAction_Ungroup_ActionToolTipText);
+        setImageDescriptor(DiagramUIActionsPluginImages.DESC_UNGROUP);
+        setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_UNGROUP_DISABLED);
+        setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_UNGROUP);
+    }
+
+    protected Request createTargetRequest() {
+        return new Request(getId());
+    }
+
+    protected boolean isSelectionListener() {
+        return true;
+    }
+
+}
diff --git a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/l10n/DiagramUIActionsPluginImages.java b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/l10n/DiagramUIActionsPluginImages.java
index 193f681..d1d22f1 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/l10n/DiagramUIActionsPluginImages.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.actions/src/org/eclipse/gmf/runtime/diagram/ui/actions/internal/l10n/DiagramUIActionsPluginImages.java
@@ -173,6 +173,11 @@
 	public static final ImageDescriptor DESC_COPY_APPEARANCE_DISABLED = create(PREFIX_DISABLED
 		+ "copy_appearance_properties.gif"); //$NON-NLS-1$	
 
+    public static final ImageDescriptor DESC_GROUP = create(PREFIX_ENABLED + "group.gif"); //$NON-NLS-1$
+    public static final ImageDescriptor DESC_GROUP_DISABLED = create(PREFIX_DISABLED + "group.gif"); //$NON-NLS-1$
+    public static final ImageDescriptor DESC_UNGROUP = create(PREFIX_ENABLED + "ungroup.gif"); //$NON-NLS-1$
+    public static final ImageDescriptor DESC_UNGROUP_DISABLED = create(PREFIX_DISABLED + "ungroup.gif"); //$NON-NLS-1$
+
 	/**
 	 * Creates the image descriptor from the filename given.
 	 * 
diff --git a/org.eclipse.gmf.runtime.diagram.ui.properties/src/org/eclipse/gmf/runtime/diagram/ui/properties/sections/AbstractModelerPropertySection.java b/org.eclipse.gmf.runtime.diagram.ui.properties/src/org/eclipse/gmf/runtime/diagram/ui/properties/sections/AbstractModelerPropertySection.java
index 3b8a8f9..93531f7 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.properties/src/org/eclipse/gmf/runtime/diagram/ui/properties/sections/AbstractModelerPropertySection.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.properties/src/org/eclipse/gmf/runtime/diagram/ui/properties/sections/AbstractModelerPropertySection.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -38,6 +38,7 @@
 import org.eclipse.gmf.runtime.common.core.util.Log;
 import org.eclipse.gmf.runtime.common.core.util.Trace;
 import org.eclipse.gmf.runtime.common.ui.services.properties.PropertiesServiceAdapterFactory;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
 import org.eclipse.gmf.runtime.diagram.ui.properties.internal.DiagramPropertiesDebugOptions;
 import org.eclipse.gmf.runtime.diagram.ui.properties.internal.DiagramPropertiesPlugin;
@@ -119,10 +120,22 @@
 			.hasNext();) {
 			Object next = it.next();
 			
-			// unwrap down to EObject and add to the eObjects list
-			if (addToEObjectList(next)) {
-				input.add(next);
-			}
+            if (digIntoGroups() && next instanceof GroupEditPart) {
+                for (Iterator iter = ((GroupEditPart) next)
+                    .getFlattenedChildren().iterator(); iter.hasNext();) {
+                    Object childEP = iter.next();
+                    // unwrap down to EObject and add to the eObjects list
+                    if (addToEObjectList(childEP)) {
+                        input.add(childEP);
+                    }
+                    continue;
+                }
+            }
+            // unwrap down to EObject and add to the eObjects list
+            if (addToEObjectList(next)) {
+                input.add(next);
+            }
+            
 		}
 
 
@@ -635,5 +648,15 @@
 		return DiagramPropertiesPlugin.getDefault()
 			.getUpdateRequestCollapser();
 	}
+    
+    /**
+     * Override to return true to have this property section work on the shapes
+     * in a <code>GroupEditPart</code> as if the shapes were multi-selected.
+     * 
+     * @return true if this property section is to dig into the shapes of groups
+     */
+    protected boolean digIntoGroups() {
+        return false;
+    }
 	
 }
\ No newline at end of file
diff --git a/org.eclipse.gmf.runtime.diagram.ui.properties/src/org/eclipse/gmf/runtime/diagram/ui/properties/sections/appearance/ColorsAndFontsPropertySection.java b/org.eclipse.gmf.runtime.diagram.ui.properties/src/org/eclipse/gmf/runtime/diagram/ui/properties/sections/appearance/ColorsAndFontsPropertySection.java
index 301631f..19f68f8 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.properties/src/org/eclipse/gmf/runtime/diagram/ui/properties/sections/appearance/ColorsAndFontsPropertySection.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.properties/src/org/eclipse/gmf/runtime/diagram/ui/properties/sections/appearance/ColorsAndFontsPropertySection.java
@@ -721,4 +721,8 @@
         }
         super.dispose();
     }
+    
+    protected boolean digIntoGroups() {
+        return true;
+    }
 }
diff --git a/org.eclipse.gmf.runtime.diagram.ui.providers/plugin.xml b/org.eclipse.gmf.runtime.diagram.ui.providers/plugin.xml
index 35fd018..ea9719d 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.providers/plugin.xml
+++ b/org.eclipse.gmf.runtime.diagram.ui.providers/plugin.xml
@@ -214,7 +214,7 @@
             <partAction menubarPath="/diagramMenu/arrangeMenu/arrangeGroup" id="arrangeSelectionAction">
             </partAction>  
             <partAction toolbarPath="/arrangeMenu/arrangeGroup" id="toolbarArrangeSelectionAction">
-            </partAction>                
+            </partAction>                                
             <partMenu menubarPath="/diagramMenu/formatGroup" toolbarPath="/toolbarViewGroup" id="alignMenu">
             </partMenu><partMenuGroup menubarPath="/diagramMenu/alignMenu/" toolbarPath="/alignMenu/" id="alignHorizontalGroup">
             </partMenuGroup>
@@ -243,8 +243,7 @@
             <partAction menubarPath="/diagramMenu/zorderMenu/zorderGroup" id="bringForwardAction">
             </partAction>
             <partAction menubarPath="/diagramMenu/zorderMenu/zorderGroup" id="sendBackwardAction">
-            </partAction>     
-            
+            </partAction>    
             <partMenu menubarPath="/diagramMenu/viewGroup" id="viewMenu">
             </partMenu> 
             <partMenuGroup menubarPath="/diagramMenu/viewMenu/" id="gridGroup">
@@ -416,18 +415,23 @@
              <popupCustom path="/formatMenu/fontFillLineGroup" id="fillColorContributionItem">
             </popupCustom>
             <popupCustom path="/formatMenu/fontFillLineGroup" id="lineColorContributionItem">
-            </popupCustom>           
-            <popupAction path="/addGroup" id="addNoteLinkAction">
-            </popupAction>                         
+            </popupCustom>                               
             <popupMenu path="/formatMenu/miscellaneousGroup" id="arrangeMenu">
             </popupMenu>    
             <popupMenuGroup path="/formatMenu/arrangeMenu/" id="arrangeGroup">
             </popupMenuGroup>             
             <popupAction path="/formatMenu/arrangeMenu/arrangeGroup" id="arrangeAllAction">
             </popupAction>   
-             <popupAction path="/formatMenu/arrangeMenu/arrangeGroup" id="arrangeSelectionAction">
-            </popupAction>              
+            <popupAction path="/formatMenu/arrangeMenu/arrangeGroup" id="arrangeSelectionAction">
+            </popupAction>    
          </popupContribution>
+         <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
+            <popupStructuredContributionCriteria objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.INotableEditPart">
+            </popupStructuredContributionCriteria>           
+            <popupAction path="/addGroup" id="addNoteLinkAction">   
+            </popupAction>    
+         </popupContribution>  
+         
          
 <!-- format and filter menu actions -->         
          <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
@@ -462,7 +466,7 @@
             <popupAction path="/formatMenu/zorderMenu/zorderGroup" id="bringForwardAction">
             </popupAction>
             <popupAction path="/formatMenu/zorderMenu/zorderGroup" id="sendBackwardAction">
-            </popupAction>                        			
+            </popupAction>
             <popupAction path="/formatMenu/sizeGroup" id="autoSizeAction">
             </popupAction>  
             
@@ -477,7 +481,23 @@
             <popupAction path="/filtersMenu/compartmentMenu/allCompartmentsGroup" id="noCompartmentsAction">
             </popupAction>     
          </popupContribution>       
-         
+           
+<!-- REMOVE ME BEFORE COMMITTING -->
+         <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
+            <popupStructuredContributionCriteria
+                  objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.IPrimaryEditPart"
+                  objectCount="2+">
+            </popupStructuredContributionCriteria>     
+            <popupAction path="/formatMenu/miscellaneousGroup" id="groupAction">
+            </popupAction>
+         </popupContribution>
+         <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
+            <popupStructuredContributionCriteria objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart">
+            </popupStructuredContributionCriteria>                    
+            <popupAction path="/formatMenu/miscellaneousGroup" id="ungroupAction">
+            </popupAction>   
+         </popupContribution>   
+                   
          <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
             <popupStructuredContributionCriteria objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart">
             </popupStructuredContributionCriteria>
@@ -595,7 +615,7 @@
             </popupStructuredContributionCriteria> 
             <popupAction path="/editGroup" id="deleteFromDiagramAction">
             </popupAction>            
-          </popupContribution>                   
+          </popupContribution>       
           <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
             <popupStructuredContributionCriteria objectClass="org.eclipse.gmf.runtime.diagram.ui.internal.editparts.IContainedEditPart">
                <method name="getNotationView().getElement()" notValue="null">                  
@@ -604,6 +624,7 @@
             <popupAction path="/editGroup" id="deleteFromModelAction">
             </popupAction>            
           </popupContribution>
+          
            <popupContribution class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
            <popupStructuredContributionCriteria objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.NoteEditPart" objectCount="1">
             </popupStructuredContributionCriteria> 
@@ -611,7 +632,7 @@
             </popupStructuredContributionCriteria> 
             <popupAction path="/navigateMenu/openGroup" id="OpenAction">
             </popupAction>
-         </popupContribution>   
+         </popupContribution>    
 		   <popupContribution
                  class="org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider">
               <popupStructuredContributionCriteria
@@ -702,7 +723,7 @@
          <Priority name="Lowest">
          </Priority>
          <object class="org.eclipse.gmf.runtime.notation.View" id="ShapesByType">
-            <method name="getType()" value="Note, Text, NoteAttachment, DiagramName, Description">
+            <method name="getType()" value="Note, Text, NoteAttachment, DiagramName, Description, Group">
             </method>
          </object>
          <context views="ShapesByType">
diff --git a/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/DiagramContributionItemProvider.java b/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/DiagramContributionItemProvider.java
index 44b789d..db2ccf1 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/DiagramContributionItemProvider.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/DiagramContributionItemProvider.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -43,6 +43,7 @@
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.FontNameContributionItem;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.FontSizeContributionItem;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.FontStyleAction;
+import org.eclipse.gmf.runtime.diagram.ui.actions.internal.GroupAction;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.HideConnectionLabelsAction;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.MakeSameSizeMenuManager;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.OpenWithMenuManager;
@@ -61,6 +62,7 @@
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.SnapBackAction;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.SnapToGridAction;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.SortFilterAction;
+import org.eclipse.gmf.runtime.diagram.ui.actions.internal.UngroupAction;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.ViewGridAction;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.ViewMenuManager;
 import org.eclipse.gmf.runtime.diagram.ui.actions.internal.ViewPageBreaksAction;
@@ -350,6 +352,12 @@
             return new SelectConnectionEndAction(workbenchPage,true);
         if (actionId.equals(ActionIds.SELECT_CONNECTION_TARGET))
             return new SelectConnectionEndAction(workbenchPage,false);
+        
+        if (actionId.equals(ActionIds.ACTION_GROUP))
+            return new GroupAction(workbenchPage);
+        if (actionId.equals(ActionIds.ACTION_UNGROUP))
+            return new UngroupAction(workbenchPage);
+
 
 		return super.createAction(actionId, partDescriptor);
 	}
diff --git a/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DefaultProvider.java b/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DefaultProvider.java
index 714bde8..1a883bc 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DefaultProvider.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DefaultProvider.java
@@ -22,12 +22,14 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.draw2d.geometry.Dimension;
 import org.eclipse.draw2d.geometry.Insets;
 import org.eclipse.draw2d.geometry.Point;
 import org.eclipse.draw2d.geometry.PointList;
 import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.graph.CompoundDirectedGraph;
 import org.eclipse.draw2d.graph.DirectedGraph;
 import org.eclipse.draw2d.graph.DirectedGraphLayout;
 import org.eclipse.draw2d.graph.Edge;
@@ -44,6 +46,7 @@
 import org.eclipse.gef.requests.ChangeBoundsRequest;
 import org.eclipse.gmf.runtime.common.core.service.IOperation;
 import org.eclipse.gmf.runtime.common.core.util.Trace;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderItemEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderedShapeEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
@@ -59,7 +62,6 @@
 import org.eclipse.gmf.runtime.draw2d.ui.mapmode.IMapMode;
 import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
 import org.eclipse.gmf.runtime.notation.View;
-import org.eclipse.jface.util.Assert;
 
 /**
  * Provider that creates a command for the DirectedGraph layout in GEF.
@@ -199,26 +201,26 @@
 
                 Point position = shapeEP.getLocation();
 
-                // determine topleft most point, layout of items will be placed
-                // starting at topleft point
-                if (minX == -1) {
-                    minX = position.x;
-                    minY = position.y;
-                } else {
-                    minX = Math.min(minX, position.x);
-                    minY = Math.min(minY, position.y);
-                }
+        // determine topleft most point, layout of items will be placed
+        // starting at topleft point
+        if (minX == -1) {
+            minX = position.x;
+            minY = position.y;
+        } else {
+            minX = Math.min(minX, position.x);
+            minY = Math.min(minY, position.y);
+        }
 
                 Node n = new Node(shapeEP);
-                n.setPadding(new Insets(NODE_PADDING));
+        n.setPadding(new Insets(NODE_PADDING));
                 Dimension size = shapeEP.getSize();
 
-                setNodeMetrics(n, new Rectangle(position.x, position.y,
-                    size.width, size.height));
+        setNodeMetrics(n, new Rectangle(position.x, position.y,
+            size.width, size.height));
 
                 editPartToNodeDict.put(shapeEP, n);
                 nodes.add(n);
-            }
+    }
         }
 
         return nodes;
@@ -340,13 +342,8 @@
                         to = to.getParent();
                     else if (shouldHandleListItems && to instanceof ListItemEditPart)
                         to = getFirstAnscestorinNodesMap(to, editPartToNodeDict);
-                    Node fromNode = (Node) editPartToNodeDict.get(from);
-                    Node toNode = (Node) editPartToNodeDict.get(to);
 
-                    if (fromNode != null && toNode != null
-                        && !fromNode.equals(toNode)) {
-                        addEdge(edges, poly, toNode, fromNode);
-                    }
+                        addEdge(edges, poly, to, from, editPartToNodeDict);
                 }else{
                     notTopDownEdges.add(poly);
                 }
@@ -367,13 +364,7 @@
                 to = to.getParent();
             else if (shouldHandleListItems && to instanceof ListItemEditPart)
                 to = getFirstAnscestorinNodesMap(to, editPartToNodeDict);
-            Node fromNode = (Node) editPartToNodeDict.get(from);
-            Node toNode = (Node) editPartToNodeDict.get(to);
-            
-            if (fromNode != null && toNode != null
-                && !fromNode.equals(toNode)) {
-                addEdge(edges, poly, fromNode, toNode);
-            }
+            addEdge(edges, poly, from, to, editPartToNodeDict);
         }
         return edges;
     }
@@ -385,11 +376,39 @@
      * @param toNode
      */
     private void addEdge(EdgeList edges, ConnectionEditPart connectionEP,
-            Node fromNode, Node toNode) {
-        Edge edge = new Edge(connectionEP, fromNode, toNode);
-        initializeEdge(connectionEP, edge);
-        
-        edges.add(edge);
+            EditPart fromEP, EditPart toEP, Map editPartToNodeDict) {
+
+        Node fromNode = (Node) editPartToNodeDict.get(fromEP);
+        Node toNode = (Node) editPartToNodeDict.get(toEP);
+
+        if (fromNode != null && toNode != null && !fromNode.equals(toNode)) {
+
+            Edge edge = new Edge(connectionEP, fromNode, toNode);
+            initializeEdge(connectionEP, edge);
+            edges.add(edge);
+
+            // create edges to/from groups
+            boolean foundGroup = false;
+            if (fromEP.getParent() instanceof GroupEditPart) {
+                fromEP = fromEP.getParent();
+                foundGroup = true;
+            }
+            if (toEP.getParent() instanceof GroupEditPart) {
+                toEP = toEP.getParent();
+                foundGroup = true;
+            }
+            if (foundGroup) {
+                fromNode = (Node) editPartToNodeDict.get(fromEP);
+                toNode = (Node) editPartToNodeDict.get(toEP);
+
+                if (fromNode != null && toNode != null
+                    && !fromNode.equals(toNode)) {
+
+                    edges.add(new Edge("ImpliedGroupConnection", fromNode, //$NON-NLS-1$
+                        toNode));
+                }
+            }
+        }
     }
 
     /**
@@ -740,11 +759,12 @@
             Node source = null, target = null;
             
             collectPoints(points, edge);
-            cep = (ConnectionEditPart)edge.data;
-            source = edge.source;
-            target = edge.target;
             
-            if (cep != null) {
+            if (edge.data instanceof ConnectionEditPart) {
+                cep = (ConnectionEditPart) edge.data;
+                source = edge.source;
+                target = edge.target;
+
                 PointListUtilities.normalizeSegments(points, MapModeUtil.getMapMode(cep.getFigure()).DPtoLP(3));
                     
                 // Reset the points list
@@ -852,8 +872,8 @@
     /**
      * Creates the graph that will be used by the layouy provider
      * Clients can override this method create different kind of graphs
-     * This method is called by {@link DefaultProvider#layoutEditParts(GraphicalEditPart, IAdaptable) } 
-     * and {@link DefaultProvider#layoutEditParts(List, IAdaptable)}  
+     * This method is called by {@link CopyOfDefaultProvider#layoutEditParts(GraphicalEditPart, IAdaptable) } 
+     * and {@link CopyOfDefaultProvider#layoutEditParts(List, IAdaptable)}  
      * @return the Graph that will be used by the layout algorithm
      */
     protected DirectedGraph createGraph(){
@@ -862,8 +882,8 @@
     
     /**
      * Creates the graph layout algorithm that will be used to layout the diagram
-     * This method is called by {@link DefaultProvider#layoutEditParts(GraphicalEditPart, IAdaptable) } 
-     * and {@link DefaultProvider#layoutEditParts(List, IAdaptable)}  
+     * This method is called by {@link CopyOfDefaultProvider#layoutEditParts(GraphicalEditPart, IAdaptable) } 
+     * and {@link CopyOfDefaultProvider#layoutEditParts(List, IAdaptable)}  
      * @return the graph layout 
      */
     protected DirectedGraphLayout createGraphLayout() {
diff --git a/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DiagramEditPartProvider.java b/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DiagramEditPartProvider.java
index f49d078..29f1af7 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DiagramEditPartProvider.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DiagramEditPartProvider.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -19,6 +19,7 @@
 import org.eclipse.gmf.runtime.common.ui.services.parser.CommonParserHint;
 import org.eclipse.gmf.runtime.diagram.core.util.ViewType;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.NoteEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.editparts.DescriptionCompartmentEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.editparts.DiagramNameCompartmentEditPart;
@@ -46,6 +47,7 @@
 	{
 		shapeMap.put(ViewType.NOTE, NoteEditPart.class);
 		shapeMap.put(ViewType.TEXT, TextEditPart.class);
+        shapeMap.put(ViewType.GROUP, GroupEditPart.class);
 	}
 	/** list of supportted text editparts. */
 	private Map textCompartmentMap = new HashMap();
@@ -75,7 +77,7 @@
 	protected Class getNodeEditPartClass(View view){
 		String type = view.getType();
 		Class clazz = null;
-		if(type!=null && type.length()>0){
+        if(type!=null && type.length()>0){
 			clazz = (Class)textCompartmentMap.get(type);
 			if(clazz==null)
 				clazz = (Class)shapeMap.get(type);
@@ -84,6 +86,7 @@
 				clazz = NoteEditPart.class;
 			}
 		}
+            
 	    return clazz;
 	}
 	
diff --git a/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DiagramIconProvider.java b/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DiagramIconProvider.java
index 4163e41..1684d67 100644
--- a/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DiagramIconProvider.java
+++ b/org.eclipse.gmf.runtime.diagram.ui.providers/src/org/eclipse/gmf/runtime/diagram/ui/providers/internal/DiagramIconProvider.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -19,6 +19,8 @@
 import org.eclipse.gmf.runtime.common.core.service.IOperation;
 import org.eclipse.gmf.runtime.common.ui.services.icon.IIconOperation;
 import org.eclipse.gmf.runtime.common.ui.services.icon.IIconProvider;
+import org.eclipse.gmf.runtime.diagram.core.util.ViewType;
+import org.eclipse.gmf.runtime.diagram.ui.internal.l10n.DiagramUIPluginImages;
 import org.eclipse.gmf.runtime.diagram.ui.internal.util.DiagramNotationType;
 import org.eclipse.gmf.runtime.diagram.ui.l10n.SharedImages;
 import org.eclipse.gmf.runtime.emf.type.core.IElementType;
@@ -53,11 +55,12 @@
         if (view != null) {
             if (DiagramViewProvider.isTextView(view)) {
                 return SharedImages.get(SharedImages.IMG_TEXT);
-            }
-
-            else if (DiagramViewProvider.isNoteView(view)) {
+            } else if (DiagramViewProvider.isNoteView(view)) {
 
                 return SharedImages.get(SharedImages.IMG_NOTE);
+            } else if (ViewType.GROUP.equals(view.getType())) {
+                 return DiagramUIPluginImages
+                    .get(DiagramUIPluginImages.IMG_GROUP);
             }
         } else if (hint.getAdapter(IElementType.class) != null) {
             String fileName = (String) typeIconMap.get(hint);
@@ -80,11 +83,12 @@
 		}
 				
         View view = (View) adapter.getAdapter(View.class);
-        if (view != null && 
-		   (DiagramViewProvider.isNoteView(view)
-		   	|| DiagramViewProvider.isTextView(view))) {
-			return true;
-		}
+        if (view != null
+            && (DiagramViewProvider.isNoteView(view)
+                || DiagramViewProvider.isTextView(view) || ViewType.GROUP
+                .equals(view.getType()))) {
+            return true;
+        }
 		
 		if (oper.getHint().getAdapter(IElementType.class) != null) {
 			String fileName = (String) typeIconMap.get(oper.getHint());
diff --git a/org.eclipse.gmf.runtime.diagram.ui/icons/group.gif b/org.eclipse.gmf.runtime.diagram.ui/icons/group.gif
new file mode 100644
index 0000000..56b2a59
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui/icons/group.gif
Binary files differ
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/actions/ActionIds.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/actions/ActionIds.java
index 8dd0667..728e84b 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/actions/ActionIds.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/actions/ActionIds.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2005, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -79,7 +79,7 @@
 	public final String ACTION_TOOLBAR_ARRANGE_SELECTION = "toolbarArrangeSelectionAction"; //$NON-NLS-1$
     public final String SELECT_CONNECTION_SOURCE = "selectConnectionSource"; //$NON-NLS-1$
     public final String SELECT_CONNECTION_TARGET = "selectConnectionTarget"; //$NON-NLS-1$
-    public final String ACTION_SELECT_ALL_SHAPES = "selectAllShapesAction"; //$NON-NLS-1$
+	public final String ACTION_SELECT_ALL_SHAPES = "selectAllShapesAction"; //$NON-NLS-1$
 	public final String ACTION_SELECT_ALL_CONNECTIONS = "selectAllConnectorsAction"; //$NON-NLS-1$
 	public final String ACTION_TOOLBAR_SELECT_ALL = "toolbarSelectAllAction"; //$NON-NLS-1$
 	public final String ACTION_TOOLBAR_SELECT_ALL_SHAPES = "toolbarSelectAllShapesAction"; //$NON-NLS-1$
@@ -102,6 +102,8 @@
 	public final String ACTION_SHOW_CONNECTION_LABELS = "showConnectorLabels"; //$NON-NLS-1$
 	public final String ACTION_HIDE_CONNECTION_LABELS = "hideConnectorLabels"; //$NON-NLS-1$	
 	public final String ACTION_SHOW_COMPARTMENT_TITLE = "showCompartmentTitle"; //$NON-NLS-1$	
+    public final String ACTION_GROUP = "groupAction"; //$NON-NLS-1$
+    public final String ACTION_UNGROUP = "ungroupAction"; //$NON-NLS-1$
 	
 	/* The menu ID for the diagram editor popup menu */
 	public final String DIAGRAM_EDITOR_CONTEXT_MENU = "org.eclipse.gmf.runtime.diagram.ui.DiagramEditorContextMenu"; //$NON-NLS-1$
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/GroupEditPart.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/GroupEditPart.java
new file mode 100644
index 0000000..8e68f81
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/GroupEditPart.java
@@ -0,0 +1,160 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.diagram.ui.editparts;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.XYLayout;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.editpolicies.SnapFeedbackPolicy;
+import org.eclipse.gef.requests.SelectionRequest;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ContainerEditPolicy;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DecorationEditPolicy;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.GroupComponentEditPolicy;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.GroupXYLayoutEditPolicy;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.NonResizableEditPolicyEx;
+import org.eclipse.gmf.runtime.diagram.ui.tools.DragEditPartsTrackerEx;
+import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * The editpart for a group. A group is a special type of container around
+ * shapes.
+ * 
+ * @author crevells, mmostafa
+ */
+public class GroupEditPart
+    extends ShapeEditPart {
+    
+    class GroupFigure extends NodeFigure {
+        public boolean containsPoint(int x, int y) {
+            Point absolutePoint = new Point(x, y);
+            translateToAbsolute(absolutePoint);
+            for (Iterator iterator = getChildren().iterator(); iterator
+                .hasNext();) {
+                IFigure child = (IFigure) iterator.next();
+                Point pt = absolutePoint.getCopy();
+                child.translateToRelative(pt);
+                if (child.containsPoint(pt)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        protected boolean useLocalCoordinates() {
+            return true;
+        }
+    }
+
+    /**
+     * constructor
+     * 
+     * @param view
+     *            the view controlled by this edit part
+     */
+    public GroupEditPart(View view) {
+        super(view);
+    }
+
+    protected IFigure createFigure() {
+        IFigure f = new GroupFigure();
+        f.setLayoutManager(new XYLayout());
+        f.setOpaque(false);
+        return f;
+    }
+
+    public DragTracker getDragTracker(Request request) {
+
+        // we only want to select the group if the user clicked the area
+        // over one of the shapes in the group
+        if (request instanceof SelectionRequest) {
+
+            for (Iterator iterator = getChildren().iterator(); iterator
+                .hasNext();) {
+                IGraphicalEditPart childEP = (IGraphicalEditPart) iterator
+                    .next();
+                Point location = ((SelectionRequest) request).getLocation()
+                    .getCopy();
+
+                childEP.getFigure().translateToRelative(location);
+
+                if (childEP.getFigure().containsPoint(location)) {
+                    return super.getDragTracker(request);
+                }
+            }
+
+            // in this case the user has not clicked over one of the shapes,
+            // so disable selection; however, we must still support dragging
+            // to move the group if it is already selected.
+            return new DragEditPartsTrackerEx(this) {
+
+                protected boolean handleButtonDown(int button) {
+                    int selectedState = getSelected();
+                    if (selectedState == SELECTED
+                        || selectedState == SELECTED_PRIMARY) {
+                        return super.handleButtonDown(button);
+                    }
+
+                    // do nothing if the group isn't selected
+                    return true;
+                }
+
+            };
+        }
+
+        return super.getDragTracker(request);
+    }
+
+    protected void createDefaultEditPolicies() {
+        installEditPolicy(EditPolicyRoles.DECORATION_ROLE,
+            new DecorationEditPolicy());
+        installEditPolicy(EditPolicy.LAYOUT_ROLE, new GroupXYLayoutEditPolicy());
+        installEditPolicy(EditPolicy.COMPONENT_ROLE,
+            new GroupComponentEditPolicy());
+        installEditPolicy(EditPolicy.CONTAINER_ROLE, new ContainerEditPolicy());
+        installEditPolicy(EditPolicyRoles.SNAP_FEEDBACK_ROLE,
+            new SnapFeedbackPolicy());
+    }
+
+    public EditPolicy getPrimaryDragEditPolicy() {
+        return new NonResizableEditPolicyEx();
+    }
+
+    /**
+     * Gets all the shape children of this group, digging into any nested groups
+     * found.
+     * 
+     * @return all the shape children including shapes in nested groups
+     */
+    public List getFlattenedChildren() {
+        List flatChildren = new ArrayList(getChildren().size());
+        for (Iterator iter = getChildren().iterator(); iter.hasNext();) {
+            Object childEP = iter.next();
+            if (childEP instanceof GroupEditPart) {
+                flatChildren.addAll(((GroupEditPart) childEP)
+                    .getFlattenedChildren());
+            } else {
+                flatChildren.add(childEP);
+            }
+        }
+        return flatChildren;
+    }
+
+}
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/ShapeEditPart.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/ShapeEditPart.java
index 3f82a79..eec8378 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/ShapeEditPart.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/ShapeEditPart.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,13 +11,19 @@
 
 package org.eclipse.gmf.runtime.diagram.ui.editparts;
 
+import java.util.Iterator;
+
 import org.eclipse.draw2d.geometry.Dimension;
 import org.eclipse.draw2d.geometry.Point;
 import org.eclipse.draw2d.geometry.Rectangle;
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gef.EditPart;
 import org.eclipse.gef.EditPolicy;
 import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.requests.SelectionRequest;
 import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ComponentEditPolicy;
 import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ContainerEditPolicy;
 import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
@@ -28,12 +34,9 @@
 import org.eclipse.gmf.runtime.notation.NotationPackage;
 import org.eclipse.gmf.runtime.notation.View;
 
-/*
- * @canBeSeenBy %partners
- */
 /**
  * the base controler for shapes
- * @author mmostafa
+ * @author mmostafa, crevells
  *
  */
 public abstract class ShapeEditPart extends TopGraphicEditPart implements IPrimaryEditPart {
@@ -144,4 +147,54 @@
 	public EditPolicy getPrimaryDragEditPolicy() {
 		return new ResizableShapeEditPolicy();
 	}
+
+    public EditPart getTargetEditPart(Request request) {
+
+        if (RequestConstants.REQ_SELECTION == request.getType()
+            && getParent() instanceof GroupEditPart) {
+            
+            // If the shape is already selected then do not give up selection to
+            // the group.
+            if (getSelected() != SELECTED_NONE) {
+                return super.getTargetEditPart(request);
+            }
+
+            GroupEditPart groupEP = (GroupEditPart) getParent();
+
+            // Normally when a shape is not selected, the right-mouse button
+            // will cause the shape to be selected and the context menu to show.
+            // If the shape is in a group, we do not want this behavior as we
+            // want the context menu of the group to show.
+            if (getSelected() == SELECTED_NONE
+                && (request instanceof SelectionRequest)
+                && ((SelectionRequest) request).getLastButtonPressed() == 3) {
+                return groupEP.getTargetEditPart(request);
+            }
+          
+            // If the group is currently selected, then this is the second click
+            // then the shape should be selected.
+            if (groupEP.getSelected() != SELECTED_NONE) {
+                return super.getTargetEditPart(request);
+            }
+
+            // If any of the group's children are currently selected then the
+            // selection of another child of the group will result in the child
+            // being selected and not the group.
+            for (Iterator iter = groupEP.getChildren().iterator(); iter
+                .hasNext();) {
+                EditPart childEP = (EditPart) iter.next();
+                if (childEP.getSelected() != SELECTED_NONE) {
+                    return super.getTargetEditPart(request);
+                }
+
+            }
+
+            // otherwise we want the group to get selected
+            return groupEP.getTargetEditPart(request);
+        }
+
+        return super.getTargetEditPart(request);
+    }
+
+     
 }
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/TreeContainerEditPart.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/TreeContainerEditPart.java
index aacf9d9..3d575b8 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/TreeContainerEditPart.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editparts/TreeContainerEditPart.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,11 +11,12 @@
 
 package org.eclipse.gmf.runtime.diagram.ui.editparts;
 
+import java.util.Collections;
 import java.util.List;
 
 import org.eclipse.emf.common.notify.Notification;
-import org.eclipse.gmf.runtime.notation.Diagram;
 import org.eclipse.gmf.runtime.notation.NotationPackage;
+import org.eclipse.gmf.runtime.notation.View;
 
 /**
  * Implementation for the regular tree edit part
@@ -40,9 +41,9 @@
 	 * @return  List of children.
 	 */
 	protected List getModelChildren() {
-		if (getModel() instanceof Diagram)
-			return ((Diagram) getModel()).getChildren();
-		return null;
+		if (getModel() instanceof View)
+			return ((View) getModel()).getChildren();
+		return Collections.EMPTY_LIST;
 	}
 
 	/**
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CanonicalConnectionEditPolicy.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CanonicalConnectionEditPolicy.java
index 57c1c62..3818b1a 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CanonicalConnectionEditPolicy.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CanonicalConnectionEditPolicy.java
@@ -35,6 +35,7 @@
 import org.eclipse.gmf.runtime.diagram.ui.commands.DeferredLayoutCommand;
 import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
 import org.eclipse.gmf.runtime.diagram.ui.commands.SetViewMutabilityCommand;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.INodeEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.figures.ICanonicalShapeCompartmentLayout;
@@ -125,9 +126,18 @@
 			View tgt = (View) tep.getAdapter(View.class);
 			if (src != null && tgt != null) {
 
-				return sep.getParent().getEditPolicy(
+                EditPart sourceParent = sep.getParent();
+                while (sourceParent instanceof GroupEditPart) {
+                    sourceParent = sourceParent.getParent();
+                }
+                EditPart targetParent = sep.getParent();
+                while (targetParent instanceof GroupEditPart) {
+                    targetParent = targetParent.getParent();
+                }
+				
+                return sourceParent.getEditPolicy(
 					EditPolicyRoles.CANONICAL_ROLE) != null
-					&& tep.getParent().getEditPolicy(
+					&& targetParent.getEditPolicy(
 						EditPolicyRoles.CANONICAL_ROLE) != null;
 			}
 		}
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CanonicalEditPolicy.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CanonicalEditPolicy.java
index 8b110b8..cda7dae 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CanonicalEditPolicy.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CanonicalEditPolicy.java
@@ -54,6 +54,7 @@
 import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
 import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener;
 import org.eclipse.gmf.runtime.diagram.core.listener.NotificationUtil;
+import org.eclipse.gmf.runtime.diagram.core.util.ViewType;
 import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
 import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
 import org.eclipse.gmf.runtime.diagram.ui.commands.CreateCommand;
@@ -942,17 +943,40 @@
 
 			
 	/**
-	 * Return the host's model children.
-	 * @return list of <code>View</Code>s
-	 */
-	protected List getViewChildren() {
-		return new ArrayList(((View)host().getModel()).getChildren());
-		
-	}
+     * Return the host's model children.
+     * 
+     * @return list of <code>View</Code>s
+     */
+    protected List getViewChildren() {
+        return getViewChildren((View) host().getModel());
+    }
+
+    /**
+     * Return the host's model children. This is a recursive method that handles
+     * groups.
+     * 
+     * @param view
+     *            the view to find the children for
+     * @return list of children views with groups removed.
+     */
+    private List getViewChildren(View view) {
+        ArrayList list = new ArrayList();
+        for (Iterator iter = view.getChildren().iterator(); iter.hasNext();) {
+
+            Object child = iter.next();
+            if (child instanceof Node
+                && ViewType.GROUP.equals(((Node) child).getType())) {
+                list.addAll(getViewChildren((View) child));
+            } else {
+                list.add(child);
+            }
+        }
+        return list;
+    }
 
 	/**
-	 * Resynchronize the canonical container.
-	 */
+     * Resynchronize the canonical container.
+     */
 	public final void refresh() {
 		try {
 			if ( isEnabled() ) {
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ComponentEditPolicy.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ComponentEditPolicy.java
index 9e37a5b..e81b5a0 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ComponentEditPolicy.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ComponentEditPolicy.java
@@ -27,6 +27,7 @@
 import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
 import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IInsertableEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.SemanticListCompartmentEditPart;
@@ -100,8 +101,16 @@
                 (SemanticListCompartmentEditPart)parent;
             return semListCompartment.isCanonicalOn();
             
+        } else {
+
+            // If the parent is a group, then we want to get the first parent
+            // that isn't a group and test for a canonical editpolicy there.
+            while (parent instanceof GroupEditPart) {
+                parent = parent.getParent();
+            }
         }
         
+        
         if (parent instanceof IGraphicalEditPart) {
 			CanonicalEditPolicy cep = (CanonicalEditPolicy)parent.getEditPolicy(EditPolicyRoles.CANONICAL_ROLE);
 			if ( cep != null ) {
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ContainerEditPolicy.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ContainerEditPolicy.java
index 9eddb7e..c2f8b4c 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ContainerEditPolicy.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ContainerEditPolicy.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Set;
@@ -36,6 +37,7 @@
 import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
 import org.eclipse.gmf.runtime.common.core.util.ObjectAdapter;
 import org.eclipse.gmf.runtime.common.ui.util.ICustomData;
+import org.eclipse.gmf.runtime.diagram.core.commands.GroupCommand;
 import org.eclipse.gmf.runtime.diagram.core.internal.commands.BringForwardCommand;
 import org.eclipse.gmf.runtime.diagram.core.internal.commands.BringToFrontCommand;
 import org.eclipse.gmf.runtime.diagram.core.internal.commands.SendBackwardCommand;
@@ -45,12 +47,14 @@
 import org.eclipse.gmf.runtime.diagram.ui.commands.DeferredLayoutCommand;
 import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderItemEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.ListItemEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.commands.DuplicateViewsCommand;
 import org.eclipse.gmf.runtime.diagram.ui.internal.commands.PasteCommand;
 import org.eclipse.gmf.runtime.diagram.ui.internal.commands.RefreshEditPartCommand;
+import org.eclipse.gmf.runtime.diagram.ui.internal.editparts.IEditableEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.editparts.ISurfaceEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.requests.PasteViewRequest;
 import org.eclipse.gmf.runtime.diagram.ui.internal.services.layout.IInternalLayoutRunnable;
@@ -420,8 +424,11 @@
 	 * @see org.eclipse.gef.EditPolicy#getCommand(Request)
 	 */
 	public Command getCommand(Request request) {
-		
-		if (request instanceof ArrangeRequest) {
+        if (ActionIds.ACTION_GROUP.equals(request.getType())
+            && request instanceof GroupRequest) {
+            return getGroupCommand((GroupRequest) request);
+        } 
+        else if (request instanceof ArrangeRequest) {
 			return getArrangeCommand((ArrangeRequest)request);
 		}
 
@@ -471,7 +478,55 @@
 		return super.getCommand(request);
 	}
 
-	/**
+    /**
+     * Returns a command to group the editparts in the request.
+     * 
+     * @param request
+     *            the request containing the editparts to be grouped.
+     * @return the command to perform the grouping
+     */
+    protected Command getGroupCommand(GroupRequest request) {
+        List shapeViews = new LinkedList();
+        IGraphicalEditPart parentEP = null;
+        for (Iterator iter = request.getEditParts().iterator(); iter.hasNext();) {
+            Object editpart = iter.next();
+
+            if (editpart instanceof ShapeEditPart) {
+
+                if (!((IEditableEditPart) editpart).isEditModeEnabled()) {
+                    return null;
+                }
+                
+                if (editpart instanceof IBorderItemEditPart) {
+                    return null;
+                }
+
+                if (parentEP != null) {
+                    if (parentEP != ((ShapeEditPart) editpart).getParent()) {
+                        // can only group shapes with the same parent
+                        return null;
+                    }
+                } else {
+                    parentEP = (IGraphicalEditPart) ((ShapeEditPart) editpart)
+                        .getParent();
+                }
+
+                if (((ShapeEditPart) editpart).getModel() instanceof Node) {
+                    shapeViews.add(((ShapeEditPart) editpart).getModel());
+                }
+            }
+        }
+
+        if (parentEP == null || !parentEP.isEditModeEnabled()) {
+            return null;
+        }
+
+        GroupCommand cmd = new GroupCommand(((IGraphicalEditPart) getHost())
+            .getEditingDomain(), shapeViews);
+        return new ICommandProxy(cmd);
+    }
+
+    /**
 	 * @see org.eclipse.gef.EditPolicy#getTargetEditPart(org.eclipse.gef.Request)
 	 */
 	public EditPart getTargetEditPart(Request request) {
@@ -486,6 +541,7 @@
 			ActionIds.ACTION_ARRANGE_ALL.equals(request.getType())
 				|| ActionIds.ACTION_TOOLBAR_ARRANGE_ALL.equals(request.getType())
 				|| ActionIds.ACTION_ARRANGE_SELECTION.equals(request.getType())
+                || ActionIds.ACTION_GROUP.equals(request.getType())
 				|| ActionIds.ACTION_TOOLBAR_ARRANGE_SELECTION.equals(request.getType())
 				|| RequestConstants.REQ_ARRANGE_RADIAL.equals(request.getType())
 				|| RequestConstants.REQ_ARRANGE_DEFERRED.equals(request.getType())
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CreationEditPolicy.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CreationEditPolicy.java
index 51496fd..489842f 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CreationEditPolicy.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/CreationEditPolicy.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -20,6 +20,7 @@
 
 import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
@@ -46,6 +47,7 @@
 import org.eclipse.gmf.runtime.diagram.ui.commands.CreateOrSelectElementCommand;
 import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
 import org.eclipse.gmf.runtime.diagram.ui.commands.SemanticCreateCommand;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
@@ -61,7 +63,6 @@
 import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest;
 import org.eclipse.gmf.runtime.emf.type.core.requests.MoveRequest;
 import org.eclipse.gmf.runtime.notation.View;
-import org.eclipse.jface.util.Assert;
 import org.eclipse.swt.widgets.Display;
 
 /**
@@ -151,6 +152,9 @@
 			if ( ep instanceof LabelEditPart ) {
 				continue;
 			}
+            if (ep instanceof GroupEditPart) {
+                cc.compose(getReparentGroupCommand((GroupEditPart) ep));
+            }
 			
 			View view = (View)ep.getAdapter(View.class);
 			if ( view == null ) {
@@ -167,13 +171,57 @@
 		}
 		return cc.isEmpty() ? null : new ICommandProxy(cc.reduce());
 	}
-	
-	/** 
-	 * Return the command to reparent the supplied editpart's semantic and notation
-	 * elements.
-	 * @param gep the editpart being reparented
-	 * @return A CompositeCommand2 that will reparent both the semantic and notation elements.
-	 */
+    
+    /**
+     * Return the command to reparent the supplied group editpart's semantic and
+     * notation elements.
+     * 
+     * @param gep
+     *            the groupEP editpart being reparented
+     * @return A composite command that will reparent both the semantic and
+     *         notation elements of the group.
+     */
+    protected ICommand getReparentGroupCommand(GroupEditPart groupEP) {
+        CompositeCommand cc = new CompositeCommand(
+            DiagramUIMessages.AddCommand_Label);
+        View container = (View) getHost().getModel();
+        EObject context = ViewUtil.resolveSemanticElement(container);
+
+        // semantic
+        TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost())
+            .getEditingDomain();
+        for (Iterator iter = groupEP.getFlattenedChildren().iterator(); iter
+            .hasNext();) {
+            IGraphicalEditPart childEP = (IGraphicalEditPart) iter.next();
+            EObject element = ViewUtil.resolveSemanticElement((View) childEP
+                .getModel());
+            if (element != null) {
+                Command moveSemanticCmd = getHost().getCommand(
+                    new EditCommandRequestWrapper(new MoveRequest(
+                        editingDomain, context, element)));
+
+                if (moveSemanticCmd == null) {
+                    return org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand.INSTANCE;
+                }
+
+                cc.compose(new CommandProxy(moveSemanticCmd));
+            }
+        }
+
+        // notation
+        cc.compose(getReparentViewCommand(groupEP));
+        return cc;
+    }
+
+    /**
+     * Return the command to reparent the supplied editpart's semantic and
+     * notation elements.
+     * 
+     * @param gep
+     *            the editpart being reparented
+     * @return A CompositeCommand2 that will reparent both the semantic and
+     *         notation elements.
+     */
 	protected ICommand getReparentCommand( IGraphicalEditPart gep ) {
         CompositeCommand cc = new CompositeCommand(DiagramUIMessages.AddCommand_Label); 
 		View container = (View)getHost().getModel();
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/DiagramDragDropEditPolicy.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/DiagramDragDropEditPolicy.java
index 4228aee..a6d726c 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/DiagramDragDropEditPolicy.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/DiagramDragDropEditPolicy.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,6 +22,7 @@
 import org.eclipse.gef.commands.CompoundCommand;
 import org.eclipse.gef.requests.ChangeBoundsRequest;
 
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.ListCompartmentEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.requests.ArrangeRequest;
@@ -141,7 +142,11 @@
 				if (cmd != null) {
 					return cmd;
 				} 
-			}
+			} else if (parentEP instanceof GroupEditPart) {
+                // Dragging shapes outside the group will cause the group to
+                // grow and thus should not reparent.
+                return null;
+            }
 		}
 		return super.getDropCommand(request);
 	}
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/GroupComponentEditPolicy.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/GroupComponentEditPolicy.java
new file mode 100644
index 0000000..e98e8c0
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/GroupComponentEditPolicy.java
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.diagram.ui.editpolicies;
+
+import java.util.Iterator;
+
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.commands.CompoundCommand;
+import org.eclipse.gef.requests.GroupRequest;
+import org.eclipse.gmf.runtime.diagram.core.commands.UngroupCommand;
+import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
+import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper;
+import org.eclipse.gmf.runtime.diagram.ui.requests.GroupRequestViaKeyboard;
+import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
+import org.eclipse.gmf.runtime.notation.Node;
+
+/**
+ * A <code>ComponentEditPolicy</code> for a <code>GroupEditPart</code>.
+ * 
+ * @author crevells
+ */
+public class GroupComponentEditPolicy
+    extends ComponentEditPolicy {
+
+
+    public boolean understandsRequest(Request request) {
+        if (ActionIds.ACTION_UNGROUP.equals(request.getType())) {
+            return true;
+        }
+        return super.understandsRequest(request);
+    }
+    
+    public Command getCommand(Request request) {
+        if (ActionIds.ACTION_UNGROUP.equals(request.getType())) {
+            return getUngroupCommand(request);
+        }
+        return super.getCommand(request);
+    }
+
+    public EditPart getTargetEditPart(Request request) {
+        return understandsRequest(request) ? getHost()
+            : null;
+    }
+    
+    /**
+     * Returns a command to ungroup and then delete the group in the request.
+     * 
+     * @param request
+     *            the request containing the group to be ungrouped
+     * @return the command to perform the ungrouping
+     */
+    protected Command getUngroupCommand(Request request) {
+        UngroupCommand cmd = new UngroupCommand(((GroupEditPart) getHost())
+            .getEditingDomain(), (Node) getHost().getModel());
+        return new ICommandProxy(cmd);
+    }
+    
+    protected Command createDeleteSemanticCommand(GroupRequest deleteRequest) {
+        TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost())
+            .getEditingDomain();
+
+        boolean shouldShowPrompt = (deleteRequest instanceof GroupRequestViaKeyboard) ? ((GroupRequestViaKeyboard) deleteRequest)
+            .isShowInformationDialog()
+            : false;
+
+        EditCommandRequestWrapper editCommandRequest = new EditCommandRequestWrapper(
+            new DestroyElementRequest(editingDomain, shouldShowPrompt),
+            deleteRequest.getExtendedData());
+
+        CompoundCommand cc = new CompoundCommand();
+        for (Iterator iter = ((GroupEditPart) getHost()).getFlattenedChildren()
+            .iterator(); iter.hasNext();) {
+            IGraphicalEditPart childEP = (IGraphicalEditPart) iter.next();
+            Command semanticCmd = childEP.getCommand(editCommandRequest);
+            if (semanticCmd != null && semanticCmd.canExecute()) {
+                cc.add(semanticCmd);
+            }
+        }
+
+        if (!cc.isEmpty()) {
+            cc.add(createDeleteViewCommand(deleteRequest));
+            return cc;
+        }
+
+        return createDeleteViewCommand(deleteRequest);
+    }
+
+}
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/GroupXYLayoutEditPolicy.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/GroupXYLayoutEditPolicy.java
new file mode 100644
index 0000000..da273e4
--- /dev/null
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/GroupXYLayoutEditPolicy.java
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.runtime.diagram.ui.editpolicies;
+
+import java.util.Iterator;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.commands.CompoundCommand;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gmf.runtime.diagram.core.internal.commands.AdjustGroupLocationCommand;
+import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * A <code>XYLayoutEditPolicy</code> for a <code>GroupEditPart</code>.
+ * 
+ * @author crevells
+ */
+public class GroupXYLayoutEditPolicy
+    extends XYLayoutEditPolicy {
+
+    public boolean understandsRequest(Request req) {
+        if (RequestConstants.REQ_AUTOSIZE.equals(req.getType())) {
+            return true;
+        }
+        return super.understandsRequest(req);
+    }
+
+    public Command getCommand(Request request) {
+        if (RequestConstants.REQ_AUTOSIZE.equals(request.getType()))
+            return getCommandFromChildren(request);
+        return super.getCommand(request);
+    }
+
+    /**
+     * Overridden so that if a child shape is moved or resized such that the
+     * group's location (i.e. top left corner) changes, the group's location as
+     * well as all the children's relative locations are updated.
+     */
+    protected Command getResizeChildrenCommand(ChangeBoundsRequest request) {
+        CompoundCommand resize = new CompoundCommand();
+        resize.add(super.getResizeChildrenCommand(request));
+        resize.add(new ICommandProxy(new AdjustGroupLocationCommand(
+            ((IGraphicalEditPart) getHost()).getEditingDomain(),
+            (View) getHost().getModel())));
+        return resize;
+    }
+
+    public EditPart getTargetEditPart(Request request) {
+        if (REQ_CREATE.equals(request.getType())) {
+            return null;
+        } else if (RequestConstants.REQ_AUTOSIZE.equals(request.getType())) {
+            return getHost();
+        }
+        return super.getTargetEditPart(request);
+    }
+
+    /**
+     * Gets a command from each child in the group.
+     * 
+     * @param request
+     * @return the compound command
+     */
+    private Command getCommandFromChildren(Request request) {
+        CompoundCommand cc = new CompoundCommand();
+        for (Iterator iter = getHost().getChildren().iterator(); iter.hasNext();) {
+            EditPart childEP = (EditPart) iter.next();
+            cc.add(childEP.getCommand(request));
+        }
+        cc.unwrap();
+        return cc;
+    }
+
+}
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ShapeCompartmentDropEditPolicy.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ShapeCompartmentDropEditPolicy.java
index 874df7d..e0bdad1 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ShapeCompartmentDropEditPolicy.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/editpolicies/ShapeCompartmentDropEditPolicy.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -26,6 +26,7 @@
 import org.eclipse.gef.commands.CompoundCommand;
 import org.eclipse.gef.requests.ChangeBoundsRequest;
 
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.requests.ArrangeRequest;
 import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest;
@@ -59,7 +60,11 @@
 					IGraphicalEditPart gep = (IGraphicalEditPart)getHost();
 					if (gep.getTopGraphicEditPart().equals(requestEP)) {
 						return null;
-					}
+					} else if (requestEP.getParent() instanceof GroupEditPart) {
+                        // Dragging shapes outside the group will cause the
+                        // group to grow and thus should not reparent.
+                        return null;
+                    }
 				}
 			}
 		}
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/internal/commands/ToggleCanonicalModeCommand.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/internal/commands/ToggleCanonicalModeCommand.java
index b3cb6c2..8a3a58a 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/internal/commands/ToggleCanonicalModeCommand.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/internal/commands/ToggleCanonicalModeCommand.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -28,6 +28,7 @@
 import org.eclipse.emf.workspace.AbstractEMFOperation;
 import org.eclipse.gef.EditPart;
 import org.eclipse.gef.commands.Command;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editpolicies.CanonicalEditPolicy;
 import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
 import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
@@ -139,9 +140,18 @@
 	 * @param editPart edit part to use
 	 * @return the canoncial edit policy if there is any
 	 */
-	protected static CanonicalEditPolicy getCanonicalEditPolicy( EditPart editPart ) {
-		return (CanonicalEditPolicy)editPart.getEditPolicy(EditPolicyRoles.CANONICAL_ROLE);
-	}
+	protected static CanonicalEditPolicy getCanonicalEditPolicy(
+            EditPart editPart) {
+
+        // If the editpart is a group, then we want to get the first parent
+        // that isn't a group and get the canonical editpolicy there.
+        while (editPart instanceof GroupEditPart) {
+            editPart = editPart.getParent();
+        }
+
+        return (CanonicalEditPolicy) editPart
+            .getEditPolicy(EditPolicyRoles.CANONICAL_ROLE);
+    }
 	
 	/** Removes the canonical editpolict from the target editpart. */ 
 	public void execute() {
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/internal/l10n/DiagramUIPluginImages.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/internal/l10n/DiagramUIPluginImages.java
index 4c3759a..bf9aec6 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/internal/l10n/DiagramUIPluginImages.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/internal/l10n/DiagramUIPluginImages.java
@@ -63,6 +63,8 @@
 	public static final String IMG_POPUPBAR = PREFIX_ROOT + "popupbar.gif"; //$NON-NLS-1$
 	public static final String IMG_POPUPBAR_PLUS = PREFIX_ROOT + "popupbar_plus.gif"; //$NON-NLS-1$
 
+    public static final String IMG_GROUP = PREFIX_ROOT + "group.gif"; //$NON-NLS-1$
+
 	// Image descriptors.
 
 	public static final ImageDescriptor DESC_HANDLE_COLLAPSE = createAndCache(IMG_HANDLE_COLLAPSE);
@@ -187,7 +189,9 @@
 	public static final ImageDescriptor DESC_DOWN_PATH = create(PREFIX_ROOT + "CollectionDown.gif"); //$NON-NLS-1$
 	public static final ImageDescriptor DESC_SORT_ARROW_UP = create(PREFIX_ROOT + "sm_arrow_up.gif"); //$NON-NLS-1$
 	public static final ImageDescriptor DESC_SORT_ARROW_DN = create(PREFIX_ROOT + "sm_arrow_dn.gif"); //$NON-NLS-1$
-	
+    
+    public static final ImageDescriptor DESC_GROUP = createAndCache(IMG_GROUP); 
+
 	/**
 	 * Creates the image descriptor from the filename given.
 	 * 
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/parts/DiagramEditor.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/parts/DiagramEditor.java
index 7e41fca..ed2e6a8 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/parts/DiagramEditor.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/parts/DiagramEditor.java
@@ -27,6 +27,7 @@
 import org.eclipse.core.commands.operations.ObjectUndoContext;
 import org.eclipse.core.commands.operations.OperationHistoryEvent;
 import org.eclipse.core.commands.operations.OperationHistoryFactory;
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IStatus;
@@ -76,11 +77,13 @@
 import org.eclipse.gmf.runtime.common.ui.util.IPartSelector;
 import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
 import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
+import org.eclipse.gmf.runtime.diagram.core.util.ViewType;
 import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
 import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IDiagramPreferenceSupport;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.TreeContainerEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.TreeDiagramEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.TreeEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIDebugOptions;
@@ -113,7 +116,6 @@
 import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.preference.PreferenceStore;
-import org.eclipse.jface.util.Assert;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.swt.SWT;
@@ -131,7 +133,6 @@
 import org.eclipse.ui.IWorkbenchPartSite;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.actions.ActionFactory;
-import org.eclipse.ui.contexts.IContextActivation;
 import org.eclipse.ui.contexts.IContextService;
 import org.eclipse.ui.part.IPageSite;
 import org.eclipse.ui.part.IShowInSource;
@@ -151,7 +152,7 @@
     implements IDiagramWorkbenchPart, ITabbedPropertySheetPageContributor,
     IShowInSource {
 	
-	public static String DIAGRAM_CONTEXT_ID = "org.eclipse.gmf.runtime.diagram.ui.diagramContext";
+	public static String DIAGRAM_CONTEXT_ID = "org.eclipse.gmf.runtime.diagram.ui.diagramContext"; //$NON-NLS-1$
 
     /**
      * teh ID of the outline
@@ -1517,12 +1518,15 @@
 		return new EditPartFactory() {
 
 			public EditPart createEditPart(EditPart context, Object model) {
-				if (model instanceof Diagram) {
-					return new TreeDiagramEditPart(model);
-				} else {
-					return new TreeEditPart(model);
-				}
-			}
+                if (model instanceof Diagram) {
+                    return new TreeDiagramEditPart(model);
+                } else if (model instanceof View
+                    && ViewType.GROUP.equals(((View) model).getType())) {
+                    return new TreeContainerEditPart(model);
+                } else {
+                    return new TreeEditPart(model);
+                }
+            }
 		};
 	}
 
diff --git a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/tools/DragEditPartsTrackerEx.java b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/tools/DragEditPartsTrackerEx.java
index c9243a6..11a63c6 100644
--- a/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/tools/DragEditPartsTrackerEx.java
+++ b/org.eclipse.gmf.runtime.diagram.ui/src/org/eclipse/gmf/runtime/diagram/ui/tools/DragEditPartsTrackerEx.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * Copyright (c) 2002, 2006 IBM Corporation and others.
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -26,6 +26,7 @@
 import org.eclipse.gef.requests.ChangeBoundsRequest;
 import org.eclipse.gef.tools.DragEditPartsTracker;
 import org.eclipse.gef.tools.ToolUtilities;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.requests.DuplicateRequest;
 import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
@@ -197,6 +198,43 @@
         }
         return super.calculateCursor();
     }
-
     
+    protected boolean handleButtonDown(int button) {
+
+        // If the group is selected, and the user clicks on a shape, defer the
+        // selection of the shape until the mouse button is released instead of
+        // selecting on mouse down because if the user does a drag they will
+        // move the entire group and not the shape.
+        if (button == 1
+            && getSourceEditPart().getParent() instanceof GroupEditPart
+            && getSourceEditPart().getParent().getSelected() != EditPart.SELECTED_NONE) {
+
+            stateTransition(STATE_INITIAL, STATE_DRAG);
+            return true;
+        }
+
+        return super.handleButtonDown(button);
+    }
+    
+    protected boolean handleDoubleClick(int button) {
+        // If the user double-clicks a shape in a group and the shape is not
+        // selected, select the shape.
+        if (getSourceEditPart().getParent() instanceof GroupEditPart
+            && getSourceEditPart().getSelected() == EditPart.SELECTED_NONE) {
+            performSelection();
+            return true;
+        } else {
+            return super.handleDoubleClick(button);
+        }
+    }
+
+    protected void performSelection() {
+        super.performSelection();
+
+        // If the new selection is a child of a group, we want to deselect the group.
+        if (getSourceEditPart().getParent() instanceof GroupEditPart
+            && getSourceEditPart().getParent().getSelected() != EditPart.SELECTED_NONE) {
+            getCurrentViewer().deselect(getSourceEditPart().getParent());
+        }
+    }
 }
diff --git a/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/AllTests.java b/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/AllTests.java
index d009c7c..d1b9b5c 100644
--- a/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/AllTests.java
+++ b/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/AllTests.java
@@ -25,6 +25,8 @@
 import org.eclipse.gmf.tests.runtime.diagram.ui.logic.DiagramAssistantTests;
 import org.eclipse.gmf.tests.runtime.diagram.ui.logic.DiagramEventBrokerTests;
 import org.eclipse.gmf.tests.runtime.diagram.ui.logic.DiagramGraphicalViewerTests;
+import org.eclipse.gmf.tests.runtime.diagram.ui.logic.GroupTests;
+import org.eclipse.gmf.tests.runtime.diagram.ui.logic.GroupsInCompartmentTests;
 import org.eclipse.gmf.tests.runtime.diagram.ui.logic.LogicCanonicalTests;
 import org.eclipse.gmf.tests.runtime.diagram.ui.logic.LogicCreationTests;
 import org.eclipse.gmf.tests.runtime.diagram.ui.logic.LogicDiagramTests;
@@ -78,7 +80,9 @@
         suite.addTest(DiagramEditingDomainTestCase.suite());
         suite.addTest(CommandUtilitiesTest.suite());
         suite.addTest(DiagramEventBrokerServiceTests.suite());        
-		
+        suite.addTest(GroupTests.suite());
+        suite.addTest(GroupsInCompartmentTests.suite());
+        
 		return suite;
 	}
 
diff --git a/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/logic/GroupTests.java b/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/logic/GroupTests.java
new file mode 100644
index 0000000..24abf24
--- /dev/null
+++ b/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/logic/GroupTests.java
@@ -0,0 +1,1119 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.tests.runtime.diagram.ui.logic;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.Tool;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.palette.ToolEntry;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gef.requests.GroupRequest;
+import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.eclipse.gmf.examples.runtime.diagram.logic.internal.LogicDiagramPlugin;
+import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
+import org.eclipse.gmf.runtime.diagram.ui.actions.internal.GroupAction;
+import org.eclipse.gmf.runtime.diagram.ui.actions.internal.SelectAllAction;
+import org.eclipse.gmf.runtime.diagram.ui.actions.internal.UngroupAction;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.geoshapes.internal.providers.GeoshapeType;
+import org.eclipse.gmf.runtime.diagram.ui.internal.util.DiagramNotationType;
+import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
+import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
+import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.gmf.tests.runtime.diagram.ui.AbstractTestBase;
+import org.eclipse.gmf.tests.runtime.diagram.ui.util.ITestActionCallback;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IWorkbenchPage;
+
+/**
+ * Tests for group and ungroup functionality.
+ * 
+ * @author crevells
+ */
+public class GroupTests
+    extends AbstractTestBase {
+
+    public static Test suite() {
+        TestSuite s = new TestSuite(GroupTests.class);
+        return s;
+    }
+
+    public GroupTests() {
+        super("Group Tests");//$NON-NLS-1$
+    }
+
+    public class GroupTestFixture
+        extends LogicTestFixture {
+
+        protected void createShapesAndConnectors()
+            throws Exception {
+            // do nothing, each test will create the shapes it wants
+        }
+
+        public void openDiagram()
+            throws Exception {
+            super.openDiagram();
+
+            // Expand the diagram since these tests simulate mouse clicks
+            // and it is necessary that the diagram be completely visible in
+            // the viewport.
+            IEditorReference[] editors = getWorkbenchPage().findEditors(
+                ((DiagramEditor) getDiagramWorkbenchPart()).getEditorInput(),
+                LogicDiagramPlugin.EDITOR_ID, IWorkbenchPage.MATCH_ID);
+            getWorkbenchPage().setPartState(editors[0],
+                IWorkbenchPage.STATE_MAXIMIZED);
+        }
+    }
+
+    protected void setTestFixture() {
+        testFixture = new GroupTestFixture();
+    }
+
+    protected LogicTestFixture getFixture() {
+        return (LogicTestFixture) testFixture;
+    }
+
+    protected View note1View;
+
+    protected View note2View;
+
+    protected View geoshape1View;
+
+    protected View geoshape2View;
+
+    /**
+     * Adds two notes and two geoshapes and some connections between them. Look
+     * at the details of the method to see what gets created.
+     */
+    protected void setupShapes() {
+        ShapeEditPart note1EP = getFixture().createShapeUsingTool(
+            DiagramNotationType.NOTE, new Point(10, 10), getContainerEP(),
+            new Dimension(50, 50));
+
+        ShapeEditPart note2EP = getFixture().createShapeUsingTool(
+            DiagramNotationType.NOTE, new Point(100, 10), getContainerEP(),
+            new Dimension(50, 50));
+
+        ShapeEditPart geoshape1EP = getFixture().createShapeUsingTool(
+            GeoshapeType.CYLINDER, new Point(10, 100), getContainerEP(),
+            new Dimension(50, 50));
+
+        ShapeEditPart geoshape2EP = getFixture().createShapeUsingTool(
+            GeoshapeType.DIAMOND, new Point(100, 100), getContainerEP(),
+            new Dimension(50, 50));
+
+        flushEventQueue();
+
+        // Cache the views so we can find the editparts again later.
+        note1View = (View) note1EP.getModel();
+        note2View = (View) note2EP.getModel();
+        geoshape1View = (View) geoshape1EP.getModel();
+        geoshape2View = (View) geoshape2EP.getModel();
+
+        // Create some connections just to make things more complicated.
+        getFixture().createConnectorUsingTool(note1EP, geoshape1EP,
+            GeoshapeType.LINE);
+        getFixture().createConnectorUsingTool(note2EP, geoshape1EP,
+            DiagramNotationType.NOTE_ATTACHMENT);
+        getFixture().createConnectorUsingTool(note2EP, geoshape2EP,
+            DiagramNotationType.NOTE_ATTACHMENT);
+        getFixture().createConnectorUsingTool(geoshape1EP, geoshape2EP,
+            GeoshapeType.LINE);
+
+        flushEventQueue();
+    }
+
+    protected IGraphicalEditPart getContainerEP() {
+        return getDiagramEditPart();
+    }
+
+    protected ShapeEditPart getNote1EP() {
+        return (ShapeEditPart) findEditPart(note1View);
+    }
+
+    protected ShapeEditPart getNote2EP() {
+        return (ShapeEditPart) findEditPart(note2View);
+    }
+
+    protected ShapeEditPart getGeoshape1EP() {
+        return (ShapeEditPart) findEditPart(geoshape1View);
+    }
+
+    protected ShapeEditPart getGeoshape2EP() {
+        return (ShapeEditPart) findEditPart(geoshape2View);
+    }
+
+    protected void setupShapesAndGroups() {
+        setupShapes();
+
+        List shapes = new LinkedList();
+        shapes.add(getNote1EP());
+        shapes.add(getGeoshape1EP());
+
+        GroupEditPart groupEP = groupShapes(shapes);
+
+        shapes.clear();
+        shapes.add(groupEP);
+        shapes.add(getNote2EP());
+
+        groupShapes(shapes);
+
+        assertEquals(2, getContainerEP().getChildren().size());
+        assertEquals(2, getOuterGroupEP().getChildren().size());
+        assertEquals(2, getInnerGroupEP().getChildren().size());
+    }
+
+    protected GroupEditPart getInnerGroupEP() {
+        return (GroupEditPart) getNote1EP().getParent();
+    }
+
+    protected GroupEditPart getOuterGroupEP() {
+        return (GroupEditPart) getNote2EP().getParent();
+    }
+
+    protected GroupEditPart groupShapes(List editparts) {
+        View childView = (View) ((IGraphicalEditPart) editparts.get(0))
+            .getModel();
+
+        GroupRequest request = new GroupRequest(ActionIds.ACTION_GROUP);
+        request.setEditParts(editparts);
+        Command cmd = ((IGraphicalEditPart) editparts.get(0)).getParent()
+            .getCommand(request);
+        assertTrue(cmd.canExecute());
+        getCommandStack().execute(cmd);
+        flushEventQueue();
+
+        EditPart groupEP = findEditPart(childView).getParent();
+        assertTrue(groupEP instanceof GroupEditPart);
+        return (GroupEditPart) groupEP;
+    }
+
+    protected Tool getSelectionToolFromPalette() {
+        PaletteViewer paletteViewer = getDiagramEditPart().getViewer()
+            .getEditDomain().getPaletteViewer();
+        ToolEntry selectionTool = paletteViewer.getPaletteRoot()
+            .getDefaultEntry();
+        paletteViewer.setActiveTool(selectionTool);
+        Tool tool = selectionTool.createTool();
+        tool.setEditDomain((EditDomain) getDiagramWorkbenchPart()
+            .getDiagramEditDomain());
+        return tool;
+    }
+
+    /**
+     * @return
+     */
+    protected IGraphicalEditPart findEditPart(View view) {
+        return (IGraphicalEditPart) getDiagramEditPart().getViewer()
+            .getEditPartRegistry().get(view);
+    }
+
+    protected MouseEvent createMouseEvent(int x, int y) {
+        Event e = new Event();
+
+        e.widget = getDiagramEditPart().getViewer().getControl();
+        ;
+        e.display = e.widget.getDisplay();
+        e.button = 1; // left button
+        e.x = x;
+        e.y = y;
+
+        return new MouseEvent(e);
+    }
+
+    protected MouseEvent createRightMouseEvent(int x, int y) {
+        Event e = new Event();
+
+        e.widget = getDiagramEditPart().getViewer().getControl();
+        ;
+        e.display = e.widget.getDisplay();
+        e.button = 3; // right button
+        e.x = x;
+        e.y = y;
+
+        return new MouseEvent(e);
+    }
+
+    protected Rectangle getAbsoluteBounds(IGraphicalEditPart editpart) {
+        Rectangle bounds = editpart.getFigure().getBounds().getCopy();
+        editpart.getFigure().translateToAbsolute(bounds);
+        return bounds;
+    }
+
+    public void testGroupCommandAndUndoRedo()
+        throws Exception {
+
+        setupShapes();
+
+        // Group note1 and geoshape1 and test undo/redo of the action.
+        List shapes = new LinkedList();
+        shapes.add(getNote1EP());
+        shapes.add(getGeoshape1EP());
+
+        GroupEditPart group1EP = groupShapes(shapes);
+
+        assertEquals(3, getContainerEP().getChildren().size());
+        assertEquals(group1EP, getGeoshape1EP().getParent());
+        assertEquals(group1EP.getParent(), getContainerEP());
+        assertEquals(2, group1EP.getChildren().size());
+        assertEquals(getAbsoluteBounds(group1EP), getAbsoluteBounds(
+            getNote1EP()).union(getAbsoluteBounds(getGeoshape1EP())));
+
+        assertTrue(getCommandStack().canUndo());
+        getCommandStack().undo();
+
+        assertEquals(getContainerEP(), getNote1EP().getParent());
+        assertEquals(getGeoshape1EP().getParent(), getContainerEP());
+        assertEquals(4, getContainerEP().getChildren().size());
+
+        assertTrue(getCommandStack().canRedo());
+        getCommandStack().redo();
+
+        group1EP = (GroupEditPart) getNote1EP().getParent();
+        assertEquals(group1EP, getGeoshape1EP().getParent());
+        assertEquals(group1EP.getParent(), getContainerEP());
+        assertEquals(2, group1EP.getChildren().size());
+        assertEquals(3, getContainerEP().getChildren().size());
+        assertEquals(getAbsoluteBounds(group1EP), getAbsoluteBounds(
+            getNote1EP()).union(getAbsoluteBounds(getGeoshape1EP())));
+
+        // Group group1 and note2 and test undo/redo of the action.
+
+        shapes.clear();
+        shapes.add(group1EP);
+        shapes.add(getNote2EP());
+
+        GroupEditPart group2EP = groupShapes(shapes);
+
+        group1EP = (GroupEditPart) getNote1EP().getParent();
+
+        assertEquals(group1EP, getGeoshape1EP().getParent());
+        assertEquals(group2EP, group1EP.getParent());
+        assertEquals(group2EP, getNote2EP().getParent());
+        assertEquals(getContainerEP(), group2EP.getParent());
+        assertEquals(2, group1EP.getChildren().size());
+        assertEquals(2, group2EP.getChildren().size());
+        assertEquals(2, getContainerEP().getChildren().size());
+        assertEquals(getAbsoluteBounds(group2EP), getAbsoluteBounds(
+            getNote2EP()).union(getAbsoluteBounds(group1EP)));
+
+        assertTrue(getCommandStack().canUndo());
+        getCommandStack().undo();
+
+        group1EP = (GroupEditPart) getNote1EP().getParent();
+        assertEquals(getContainerEP(), group1EP.getParent());
+        assertEquals(getContainerEP(), getNote2EP().getParent());
+        assertEquals(3, getContainerEP().getChildren().size());
+
+        assertTrue(getCommandStack().canRedo());
+        getCommandStack().redo();
+
+        group1EP = (GroupEditPart) getNote1EP().getParent();
+        group2EP = (GroupEditPart) getNote2EP().getParent();
+        assertEquals(group2EP, group1EP.getParent());
+        assertEquals(getContainerEP(), group2EP.getParent());
+        assertEquals(2, group1EP.getChildren().size());
+        assertEquals(2, group2EP.getChildren().size());
+        assertEquals(2, getContainerEP().getChildren().size());
+        assertEquals(getAbsoluteBounds(group2EP), getAbsoluteBounds(
+            getNote2EP()).union(getAbsoluteBounds(group1EP)));
+    }
+
+    public void testUngroupCommandAndUndoRedo()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        // Ungroup the top-level group.
+        Request request = new Request(ActionIds.ACTION_UNGROUP);
+        Command cmd = getOuterGroupEP().getCommand(request);
+        assertTrue(cmd.canExecute());
+        getCommandStack().execute(cmd);
+        // flushEventQueue();
+
+        assertEquals(3, getContainerEP().getChildren().size());
+        assertEquals(getContainerEP(), getInnerGroupEP().getParent());
+        assertEquals(getContainerEP(), getNote2EP().getParent());
+
+        // Undo the ungroup of the top-level group.
+        assertTrue(getCommandStack().canUndo());
+        getCommandStack().undo();
+
+        assertEquals(2, getContainerEP().getChildren().size());
+        assertEquals(getOuterGroupEP(), getInnerGroupEP().getParent());
+        assertEquals(2, getOuterGroupEP().getChildren().size());
+
+        // Redo the ungroup of the top-level group.
+        assertTrue(getCommandStack().canRedo());
+        getCommandStack().redo();
+        // flushEventQueue();
+
+        assertEquals(3, getContainerEP().getChildren().size());
+        assertEquals(getContainerEP(), getInnerGroupEP().getParent());
+        assertEquals(getContainerEP(), getNote2EP().getParent());
+    }
+
+    public void testGroupIsSelectedAfterGroupAction()
+        throws Exception {
+
+        setupShapes();
+
+        List shapes = new LinkedList();
+        shapes.add(getNote1EP());
+        shapes.add(getGeoshape1EP());
+
+        GroupAction action = new GroupAction(getWorkbenchPage());
+        getWorkbenchPage().activate(getDiagramWorkbenchPart());
+        action.init();
+
+        EditPartViewer viewer = getDiagramWorkbenchPart()
+            .getDiagramGraphicalViewer();
+        viewer.deselectAll();
+        viewer.setSelection(new StructuredSelection(shapes));
+
+        action.refresh();
+        assertTrue(action.isEnabled());
+        action.run();
+        action.dispose();
+
+        flushEventQueue();
+
+        assertEquals(1, ((StructuredSelection) viewer.getSelection()).size());
+        assertTrue(((StructuredSelection) viewer.getSelection())
+            .getFirstElement() instanceof GroupEditPart);
+    }
+
+    public void testGroupActionEnablement()
+        throws Exception {
+        setupShapes();
+
+        GroupAction action = new GroupAction(getWorkbenchPage());
+        getWorkbenchPage().activate(getDiagramWorkbenchPart());
+        action.init();
+
+        EditPartViewer viewer = getDiagramWorkbenchPart()
+            .getDiagramGraphicalViewer();
+        viewer.deselectAll();
+
+        // should be enabled when connections are included in the selection
+        viewer.setSelection(new StructuredSelection(getDiagramEditPart()
+            .getPrimaryEditParts()));
+        action.refresh();
+        assertTrue(action.isEnabled());
+
+        // should be disabled when only one shape is selected
+        viewer.setSelection(new StructuredSelection(getNote1EP()));
+        action.refresh();
+        assertFalse(action.isEnabled());
+
+        // should be enabled when connections are included in the selection
+        viewer.setSelection(new StructuredSelection(getDiagramEditPart()
+            .getPrimaryEditParts()));
+        action.refresh();
+        assertTrue(action.isEnabled());
+
+        // should be disabled when only connections are selected
+        viewer.setSelection(new StructuredSelection(getDiagramEditPart()
+            .getConnections()));
+        action.refresh();
+        assertFalse(action.isEnabled());
+
+        // should be enabled on groups
+        List shapes = new LinkedList();
+        shapes.add(getNote1EP());
+        shapes.add(getGeoshape1EP());
+        GroupEditPart groupEP = groupShapes(shapes);
+        shapes.clear();
+        shapes.add(groupEP);
+        shapes.add(getNote2EP());
+        viewer.setSelection(new StructuredSelection(shapes));
+        action.refresh();
+        assertTrue(action.isEnabled());
+
+        // should be disabled on uneditable diagrams
+        getContainerEP().disableEditMode();
+        action.refresh();
+        assertFalse(action.isEnabled());
+    }
+
+    public void testUngroupActionEnablement()
+        throws Exception {
+        setupShapes();
+
+        List shapes = new LinkedList();
+        shapes.add(getNote1EP());
+        shapes.add(getGeoshape1EP());
+        GroupEditPart group1EP = groupShapes(shapes);
+
+        shapes.clear();
+        shapes.add(getNote2EP());
+        shapes.add(getGeoshape2EP());
+        GroupEditPart group2EP = groupShapes(shapes);
+
+        UngroupAction action = new UngroupAction(getWorkbenchPage());
+        getWorkbenchPage().activate(getDiagramWorkbenchPart());
+        action.init();
+
+        EditPartViewer viewer = getDiagramWorkbenchPart()
+            .getDiagramGraphicalViewer();
+        viewer.deselectAll();
+
+        // should be enabled when one group is selected
+        viewer.setSelection(new StructuredSelection(getInnerGroupEP()));
+        action.refresh();
+        assertTrue(action.isEnabled());
+
+        // should be enabled when multiple groups are selected
+        List groups = new LinkedList();
+        groups.add(group1EP);
+        groups.add(group2EP);
+        viewer.setSelection(new StructuredSelection(groups));
+        action.refresh();
+        assertTrue(action.isEnabled());
+    }
+
+    public void testSelectGroupWithClickAndDrag()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        EditPartViewer viewer = getDiagramEditPart().getViewer();
+        PaletteViewer paletteViewer = viewer.getEditDomain().getPaletteViewer();
+
+        ToolEntry selectionTool = paletteViewer.getPaletteRoot()
+            .getDefaultEntry();
+        paletteViewer.setActiveTool(selectionTool);
+        Tool tool = selectionTool.createTool();
+        tool.setEditDomain((EditDomain) getDiagramWorkbenchPart()
+            .getDiagramEditDomain());
+
+        // draw rubber band around all the shapes
+        viewer.getSelectionManager().deselectAll();
+        tool.activate();
+        tool.mouseDown(createMouseEvent(0, 0), viewer);
+        tool.mouseDrag(createMouseEvent(200, 200), viewer);
+        tool.mouseUp(createMouseEvent(200, 200), viewer);
+        tool.deactivate();
+
+        // size should be 6: 1 group, 1 shape, 4 connections
+        assertEquals(6, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getOuterGroupEP()));
+    }
+
+    public void testSelectGroupWithRightClick()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        Tool tool = getSelectionToolFromPalette();
+
+        // click on a shape in the outer group and the outer group should be
+        // selected
+        EditPartViewer viewer = getDiagramEditPart().getViewer();
+        viewer.getSelectionManager().deselectAll();
+        tool.activate();
+        Point point = getAbsoluteBounds(getNote2EP()).getCenter();
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getOuterGroupEP()));
+
+        // right-click on the same shape a second time and the group should
+        // still be
+        // selected
+        tool.mouseDown(createRightMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createRightMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getOuterGroupEP()));
+    }
+
+    public void testSelectShapesAndGroupsWithClick()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        Tool tool = getSelectionToolFromPalette();
+
+        // click on a shape in the outer group and the outer group should be
+        // selected
+        EditPartViewer viewer = getDiagramEditPart().getViewer();
+        viewer.getSelectionManager().deselectAll();
+        tool.activate();
+        Point point = getAbsoluteBounds(getNote2EP()).getCenter();
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getOuterGroupEP()));
+
+        // click on the same shape a second time and the shape should be
+        // selected
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getNote2EP()));
+
+        // right-click on the same shape and it should remain selected
+        tool.mouseDown(createRightMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createRightMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getNote2EP()));
+
+        // click on a shape not in the group and that shape itself should be
+        // selected
+        viewer.getSelectionManager().deselectAll();
+        point = getAbsoluteBounds(getGeoshape2EP()).getCenter();
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getGeoshape2EP()));
+
+        // click on an area of blank space in a group and nothing should be
+        // selected
+        viewer.getSelectionManager().deselectAll();
+        tool.mouseDown(createMouseEvent(30, 75), viewer);
+        tool.mouseUp(createMouseEvent(30, 75), viewer);
+
+        assertEquals(0, viewer.getSelectedEditParts().size());
+
+        // click on a shape in the inner group and the outer group should be
+        // selected
+        viewer.getSelectionManager().deselectAll();
+        point = getAbsoluteBounds(getNote1EP()).getCenter();
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getOuterGroupEP()));
+
+        // click on the same shape a second time and the inner group should be
+        // selected
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getInnerGroupEP()));
+
+        // click on the same shape a third time and the shape itself should be
+        // selected
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertTrue(viewer.getSelectedEditParts().contains(getNote1EP()));
+
+        tool.deactivate();
+    }
+
+    /**
+     * This ensure that when a group is created you can select a connection that
+     * exists between shapes in the group. The issue was that the connection
+     * editpart was not active.
+     * 
+     * This fails because of GEF Bugzilla 174085.
+     * 
+     * @throws Exception
+     */
+    public void testSelectConnectionInGroupWithClick()
+        throws Exception {
+
+        setupShapes();
+
+        List shapes = new LinkedList();
+        shapes.add(getNote1EP());
+        shapes.add(getGeoshape1EP());
+        GroupEditPart groupEP = groupShapes(shapes);
+
+        ConnectionEditPart connectionEP = (ConnectionEditPart) getNote1EP()
+            .getSourceConnections().get(0);
+
+        Tool tool = getSelectionToolFromPalette();
+        EditPartViewer viewer = getDiagramEditPart().getViewer();
+        viewer.getSelectionManager().deselectAll();
+        tool.activate();
+
+        Point point = getAbsoluteBounds(connectionEP).getCenter();
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        assertEquals(1, viewer.getSelectedEditParts().size());
+        assertEquals(connectionEP, viewer.getSelectedEditParts().get(0));
+        assertTrue(connectionEP.isActive());
+        assertTrue(connectionEP.getSource().isActive());
+        assertEquals(groupEP, connectionEP.getSource().getParent());
+        assertTrue(connectionEP.getTarget().isActive());
+        assertEquals(groupEP, connectionEP.getTarget().getParent());
+
+        tool.deactivate();
+    }
+
+    public void testMoveGroup()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        Tool tool = getSelectionToolFromPalette();
+
+        System.out.println(getInnerGroupEP().getFigure().getBounds());
+        System.out.println(getAbsoluteBounds(getInnerGroupEP()));
+        Rectangle origGroupBounds = getAbsoluteBounds(getInnerGroupEP());
+        Rectangle origNote1Bounds = getAbsoluteBounds(getNote1EP());
+        Rectangle origGeoshape1Bounds = getAbsoluteBounds(getGeoshape1EP());
+
+        Point offset = new Point(25, 25);
+
+        // Click and drag the group in one gesture.
+        EditPartViewer viewer = getDiagramEditPart().getViewer();
+        viewer.getSelectionManager().deselectAll();
+        tool.activate();
+        Point point = origNote1Bounds.getCenter();
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        point.translate(offset);
+        tool.mouseDrag(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+        tool.deactivate();
+        flushEventQueue();
+        Thread.sleep(5000);
+
+        // Cannot test the exact bounds because I can't figure out what the
+        // exact bounds should be (maybe there are rounding issues?) so the
+        // tests here will have to do.
+        Dimension resultingOffset = origGroupBounds.getLocation()
+            .getDifference(getAbsoluteBounds(getInnerGroupEP()).getLocation());
+        assertTrue(resultingOffset.height != 0 && resultingOffset.width != 0);
+        assertEquals(resultingOffset, origNote1Bounds.getLocation()
+            .getDifference(getAbsoluteBounds(getNote1EP()).getLocation()));
+        assertEquals(resultingOffset, origGeoshape1Bounds.getLocation()
+            .getDifference(getAbsoluteBounds(getGeoshape1EP()).getLocation()));
+
+        // Now select the group first and then click over a shape and drag. This
+        // should move the group.
+        origGroupBounds = getAbsoluteBounds(getInnerGroupEP());
+        origNote1Bounds = getAbsoluteBounds(getNote1EP());
+        origGeoshape1Bounds = getAbsoluteBounds(getGeoshape1EP());
+        point = origNote1Bounds.getCenter();
+        offset = new Point(-25, -25);
+
+        viewer.getSelectionManager().deselectAll();
+        viewer.select(getInnerGroupEP());
+        tool.activate();
+
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        point.translate(offset);
+        tool.mouseDrag(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+        tool.deactivate();
+
+        flushEventQueue();
+
+        // Cannot test the exact bounds because I can't figure out what the
+        // exact bounds should be (maybe there are rounding issues?) so the
+        // tests here will have to do.
+        resultingOffset = origGroupBounds.getLocation().getDifference(
+            getAbsoluteBounds(getInnerGroupEP()).getLocation());
+        assertTrue(resultingOffset.height != 0 && resultingOffset.width != 0);
+
+        resultingOffset = origNote1Bounds.getLocation().getDifference(
+            getAbsoluteBounds(getNote1EP()).getLocation());
+        assertTrue(resultingOffset.height != 0 && resultingOffset.width != 0);
+
+        resultingOffset = origGeoshape1Bounds.getLocation().getDifference(
+            getAbsoluteBounds(getGeoshape1EP()).getLocation());
+        assertTrue(resultingOffset.height != 0 && resultingOffset.width != 0);
+
+        // Confirm sizes are still the same.
+        assertEquals(origGroupBounds.getSize(), getAbsoluteBounds(
+            getInnerGroupEP()).getSize());
+        assertEquals(origNote1Bounds.getSize(), getAbsoluteBounds(getNote1EP())
+            .getSize());
+        assertEquals(origGeoshape1Bounds.getSize(), getAbsoluteBounds(
+            getGeoshape1EP()).getSize());
+    }
+
+    public void testMoveShapeInGroup()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        Tool tool = getSelectionToolFromPalette();
+
+        Rectangle origGroupBounds = getAbsoluteBounds(getInnerGroupEP());
+        Rectangle origNote1Bounds = getAbsoluteBounds(getNote1EP());
+        Rectangle origGeoshape1Bounds = getAbsoluteBounds(getGeoshape1EP());
+
+        Point offset = new Point(25, 25);
+
+        // Move geoshape1. Click three times -- first select the outer group,
+        // then select the inner group, then select geoshape1.
+        EditPartViewer viewer = getDiagramEditPart().getViewer();
+        viewer.getSelectionManager().deselectAll();
+        tool.activate();
+        Point point = origGeoshape1Bounds.getCenter();
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+
+        // Now click and drag geoshape1 to move it.
+        tool.mouseDown(createMouseEvent(point.x, point.y), viewer);
+        point.translate(offset);
+        tool.mouseDrag(createMouseEvent(point.x, point.y), viewer);
+        tool.mouseUp(createMouseEvent(point.x, point.y), viewer);
+        tool.deactivate();
+        flushEventQueue();
+
+        // Confirm geoshape1 was not removed from the group.
+        assertEquals(2, getInnerGroupEP().getChildren().size());
+
+        // geoshape1 should have moved.
+        Dimension resultingOffset = origGeoshape1Bounds.getLocation()
+            .getDifference(getAbsoluteBounds(getGeoshape1EP()).getLocation());
+        assertTrue(resultingOffset.height != 0 && resultingOffset.width != 0);
+        assertEquals(origGeoshape1Bounds.getSize(), getAbsoluteBounds(
+            getGeoshape1EP()).getSize());
+
+        // note1 should remain the same.
+        assertEquals(origNote1Bounds, getAbsoluteBounds(getNote1EP()));
+
+        // The group location should not have changed but the size should have
+        // grown.
+        assertEquals(origGroupBounds.getLocation(), getAbsoluteBounds(
+            getInnerGroupEP()).getLocation());
+        assertNotSame(origGroupBounds.getSize(), getAbsoluteBounds(
+            getInnerGroupEP()).getSize());
+
+    }
+
+    public void testUngroupShapesMaintainsShapeLocations()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        // Ungroup the inner group.
+
+        // First cache the bounds in absolute coordinates of one of the figures.
+        Rectangle origGeoshape1Bounds = getAbsoluteBounds(getGeoshape1EP());
+
+        // Perform the ungroup.
+        Request request = new Request(ActionIds.ACTION_UNGROUP);
+        Command cmd = getInnerGroupEP().getCommand(request);
+        assertTrue(cmd.canExecute());
+        getCommandStack().execute(cmd);
+        flushEventQueue();
+
+        // Test that the bounds in absolute have not changed.
+        assertEquals(origGeoshape1Bounds, getAbsoluteBounds(getGeoshape1EP()));
+
+        // Ungroup the outer group.
+
+        // First cache the bounds in absolute coordinates of one of the figures.
+        Rectangle origNote2Bounds = getAbsoluteBounds(getNote2EP());
+
+        // Perform the ungroup.
+        request = new Request(ActionIds.ACTION_UNGROUP);
+        cmd = getInnerGroupEP().getCommand(request);
+        assertTrue(cmd.canExecute());
+        getCommandStack().execute(cmd);
+        flushEventQueue();
+
+        // Test that the bounds in absolute have not changed.
+        assertEquals(origNote2Bounds, getAbsoluteBounds(getNote2EP()));
+    }
+
+    public void testDeleteShapeInGroup()
+        throws Exception {
+
+        setupShapes();
+
+        List shapes = new LinkedList();
+        shapes.add(getNote1EP());
+        shapes.add(getGeoshape1EP());
+        shapes.add(getGeoshape2EP());
+
+        GroupEditPart groupEP = groupShapes(shapes);
+
+        shapes.clear();
+        shapes.add(groupEP);
+        shapes.add(getNote2EP());
+
+        groupShapes(shapes);
+
+        // Inner group has 3 shapes, outer group has inner group and 1 shape.
+        assertEquals(1, getContainerEP().getChildren().size());
+        assertEquals(2, getOuterGroupEP().getChildren().size());
+        assertEquals(3, getInnerGroupEP().getChildren().size());
+
+        Request request = new GroupRequest(RequestConstants.REQ_DELETE);
+
+        // Delete one shape from the inner group.
+        getCommandStack().execute(getGeoshape1EP().getCommand(request));
+
+        // Inner group should now have 2 shapes.
+        assertEquals(2, getInnerGroupEP().getChildren().size());
+
+        // Delete another shape from the inner group.
+        getCommandStack().execute(getNote1EP().getCommand(request));
+
+        // Inner group should not exist anymore.
+        assertEquals(getOuterGroupEP(), getGeoshape2EP().getParent());
+        assertEquals(2, getOuterGroupEP().getChildren().size());
+
+        // Now try undo.
+        getCommandStack().undo();
+        getCommandStack().undo();
+
+        // Inner group has 3 shapes, outer group has inner group and 1 shape.
+        assertEquals(1, getContainerEP().getChildren().size());
+        assertEquals(2, getOuterGroupEP().getChildren().size());
+        assertEquals(3, getInnerGroupEP().getChildren().size());
+
+    }
+
+    public void testCannotResizeGroup()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        ChangeBoundsRequest request = new ChangeBoundsRequest(
+            RequestConstants.REQ_RESIZE);
+        request.setResizeDirection(PositionConstants.SOUTH);
+        request.setEditParts(getOuterGroupEP());
+        request.setSizeDelta(new Dimension(0, 100));
+
+        Command cmd = getOuterGroupEP().getCommand(request);
+        assertTrue(cmd == null || !cmd.canExecute());
+    }
+
+    public void testResizeShapeInGroup()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        Rectangle origNote1Bounds = getAbsoluteBounds(getNote1EP());
+        Rectangle origGeoshape1Bounds = getAbsoluteBounds(getGeoshape1EP());
+
+        // Increase note1's size by 10 on each side.
+        ChangeBoundsRequest request = new ChangeBoundsRequest(
+            RequestConstants.REQ_RESIZE);
+        request.setResizeDirection(PositionConstants.NORTH_EAST);
+        request.setEditParts(getNote1EP());
+        request.setSizeDelta(new Dimension(10, 10));
+
+        getNote1EP().getCommand(request).execute();
+
+        assertNotSame(origNote1Bounds, getAbsoluteBounds(getNote1EP()));
+        assertEquals(origGeoshape1Bounds, getAbsoluteBounds(getGeoshape1EP()));
+        assertEquals(getAbsoluteBounds(getNote1EP()).union(
+            getAbsoluteBounds(getGeoshape1EP())),
+            getAbsoluteBounds(getInnerGroupEP()));
+
+        request.setResizeDirection(PositionConstants.SOUTH_WEST);
+        getNote1EP().getCommand(request).execute();
+
+        assertEquals(origGeoshape1Bounds, getAbsoluteBounds(getGeoshape1EP()));
+        assertEquals(getAbsoluteBounds(getNote1EP()).union(
+            getAbsoluteBounds(getGeoshape1EP())),
+            getAbsoluteBounds(getInnerGroupEP()));
+
+        // Increase geoshape1's size by 10 on each side.
+        origNote1Bounds = getAbsoluteBounds(getNote1EP());
+        origGeoshape1Bounds = getAbsoluteBounds(getGeoshape1EP());
+
+        request.setResizeDirection(PositionConstants.SOUTH_EAST);
+        request.setEditParts(getGeoshape1EP());
+
+        getGeoshape1EP().getCommand(request).execute();
+
+        assertNotSame(origGeoshape1Bounds, getAbsoluteBounds(getGeoshape1EP()));
+        assertEquals(origNote1Bounds, getAbsoluteBounds(getNote1EP()));
+        assertEquals(getAbsoluteBounds(getNote1EP()).union(
+            getAbsoluteBounds(getGeoshape1EP())),
+            getAbsoluteBounds(getInnerGroupEP()));
+
+        request.setResizeDirection(PositionConstants.NORTH_WEST);
+        getGeoshape1EP().getCommand(request).execute();
+
+        assertEquals(origNote1Bounds, getAbsoluteBounds(getNote1EP()));
+        assertEquals(getAbsoluteBounds(getNote1EP()).union(
+            getAbsoluteBounds(getGeoshape1EP())),
+            getAbsoluteBounds(getInnerGroupEP()));
+
+        // Decrease note1's size by 10 on each side.
+        origNote1Bounds = getAbsoluteBounds(getNote1EP());
+        origGeoshape1Bounds = getAbsoluteBounds(getGeoshape1EP());
+
+        request.setResizeDirection(PositionConstants.NORTH_EAST);
+        request.setEditParts(getNote1EP());
+        request.setSizeDelta(new Dimension(-10, -10));
+
+        getNote1EP().getCommand(request).execute();
+
+        assertNotSame(origNote1Bounds, getAbsoluteBounds(getNote1EP()));
+        assertEquals(origGeoshape1Bounds, getAbsoluteBounds(getGeoshape1EP()));
+        assertEquals(getAbsoluteBounds(getNote1EP()).union(
+            getAbsoluteBounds(getGeoshape1EP())),
+            getAbsoluteBounds(getInnerGroupEP()));
+
+        request.setResizeDirection(PositionConstants.SOUTH_WEST);
+        getNote1EP().getCommand(request).execute();
+
+        assertEquals(origGeoshape1Bounds, getAbsoluteBounds(getGeoshape1EP()));
+        assertEquals(getAbsoluteBounds(getNote1EP()).union(
+            getAbsoluteBounds(getGeoshape1EP())),
+            getAbsoluteBounds(getInnerGroupEP()));
+
+        // Decrease geoshape1's size by 10 on each side.
+        origNote1Bounds = getAbsoluteBounds(getNote1EP());
+        origGeoshape1Bounds = getAbsoluteBounds(getNote1EP());
+
+        request.setResizeDirection(PositionConstants.SOUTH_EAST);
+        request.setEditParts(getGeoshape1EP());
+
+        getGeoshape1EP().getCommand(request).execute();
+
+        assertNotSame(origGeoshape1Bounds, getGeoshape1EP().getFigure()
+            .getBounds());
+        assertEquals(origNote1Bounds, getAbsoluteBounds(getNote1EP()));
+        assertEquals(getAbsoluteBounds(getNote1EP()).union(
+            getAbsoluteBounds(getGeoshape1EP())),
+            getAbsoluteBounds(getInnerGroupEP()));
+
+        request.setResizeDirection(PositionConstants.NORTH_WEST);
+        getGeoshape1EP().getCommand(request).execute();
+
+        assertEquals(origNote1Bounds, getAbsoluteBounds(getNote1EP()));
+        assertEquals(getAbsoluteBounds(getNote1EP()).union(
+            getAbsoluteBounds(getGeoshape1EP())),
+            getAbsoluteBounds(getInnerGroupEP()));
+    }
+
+    public void testDeleteGroup()
+        throws Exception {
+
+        setupShapesAndGroups();
+
+        Request request = new GroupRequest(RequestConstants.REQ_DELETE);
+        getCommandStack().execute(getOuterGroupEP().getCommand(request));
+
+        assertEquals(1, getContainerEP().getChildren().size());
+
+        getCommandStack().undo();
+
+        assertEquals(2, getContainerEP().getChildren().size());
+        assertEquals(2, getOuterGroupEP().getChildren().size());
+        assertEquals(2, getInnerGroupEP().getChildren().size());
+
+    }
+
+    public void testSelectActions()
+        throws Exception {
+        setupShapesAndGroups();
+
+        // test select all
+        getContainerEP().getViewer().setSelection(
+            new StructuredSelection(getContainerEP()));
+
+        SelectAllAction selectAction = SelectAllAction
+            .createSelectAllAction(getWorkbenchPage());
+
+        testAction(selectAction, new ITestActionCallback() {
+
+            public void onRunExecution() {
+
+                List selectedParts = getContainerEP().getViewer()
+                    .getSelectedEditParts();
+
+                // 2 shapes and 4 connectors
+                assertEquals(6, selectedParts.size());
+                assertTrue(selectedParts.contains(getOuterGroupEP()));
+                assertTrue(selectedParts.contains(getNote2EP()
+                    .getSourceConnections().get(0)));
+                assertFalse(selectedParts.contains(getNote1EP()));
+
+            }
+        });
+
+        // test select all shapes
+        getContainerEP().getViewer().deselectAll();
+        getContainerEP().getViewer().setSelection(
+            new StructuredSelection(getContainerEP()));
+
+        selectAction = SelectAllAction
+            .createSelectAllShapesAction(getWorkbenchPage());
+
+        testAction(selectAction, new ITestActionCallback() {
+
+            public void onRunExecution() {
+
+                List selectedParts = getContainerEP().getViewer()
+                    .getSelectedEditParts();
+
+                // 2 shapes
+                assertEquals(2, selectedParts.size());
+                assertTrue(selectedParts.contains(getOuterGroupEP()));
+                assertTrue(selectedParts.contains(getGeoshape2EP()));
+
+            }
+        });
+
+        // test select all connections
+        getContainerEP().getViewer().deselectAll();
+        getContainerEP().getViewer().setSelection(
+            new StructuredSelection(getContainerEP()));
+
+        selectAction = SelectAllAction
+            .createSelectAllConnectionsAction(getWorkbenchPage());
+
+        testAction(selectAction, new ITestActionCallback() {
+
+            public void onRunExecution() {
+
+                List selectedParts = getContainerEP().getViewer()
+                    .getSelectedEditParts();
+
+                // 4 connectors
+                assertEquals(4, selectedParts.size());
+                assertTrue(selectedParts.contains(getNote2EP()
+                    .getSourceConnections().get(0)));
+            }
+        });
+    }
+
+}
diff --git a/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/logic/GroupsInCompartmentTests.java b/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/logic/GroupsInCompartmentTests.java
new file mode 100644
index 0000000..45cfbcc
--- /dev/null
+++ b/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/logic/GroupsInCompartmentTests.java
@@ -0,0 +1,163 @@
+/******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation 
+ ****************************************************************************/
+
+package org.eclipse.gmf.tests.runtime.diagram.ui.logic;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.requests.GroupRequest;
+import org.eclipse.gmf.examples.runtime.diagram.logic.internal.editparts.CircuitEditPart;
+import org.eclipse.gmf.examples.runtime.diagram.logic.internal.providers.LogicConstants;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.geoshapes.internal.providers.GeoshapeType;
+import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
+import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry;
+import org.eclipse.gmf.runtime.emf.type.core.IElementType;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * Repeat all the same tests in <code>GroupTests</code> but within a
+ * compartment.
+ * 
+ * @author crevells
+ */
+public class GroupsInCompartmentTests
+    extends GroupTests {
+
+    public static Test suite() {
+        TestSuite s = new TestSuite(GroupsInCompartmentTests.class);
+        return s;
+    }
+
+    private static IElementType CIRCUIT_TYPE = ElementTypeRegistry
+        .getInstance().getType("logic.circuit"); //$NON-NLS-1$
+
+    private IGraphicalEditPart logicCompartmentEP;
+
+    protected IGraphicalEditPart getContainerEP() {
+        return logicCompartmentEP;
+    }
+
+    protected void setTestFixture() {
+        testFixture = new GroupTestFixture() {
+
+            protected void createShapesAndConnectors()
+                throws Exception {
+
+                // create the circuit that is the container
+                IElementType typeCircuit = ElementTypeRegistry.getInstance()
+                    .getType("logic.circuit"); //$NON-NLS-1$
+                CircuitEditPart circuitEP = (CircuitEditPart) getFixture()
+                    .createShapeUsingTool(typeCircuit, new Point(5, 5),
+                        new Dimension(300, 300));
+                logicCompartmentEP = circuitEP
+                    .getChildBySemanticHint(LogicConstants.LOGIC_SHAPE_COMPARTMENT);
+            }
+        };
+    }
+
+    /**
+     * Create LEDs instead of Notes to test for canonical issues.
+     */
+    protected void setupShapes() {
+
+        ShapeEditPart note1EP = getFixture().createShapeUsingTool(CIRCUIT_TYPE,
+            new Point(10, 10), getContainerEP(), new Dimension(50, 50));
+
+        ShapeEditPart note2EP = getFixture().createShapeUsingTool(CIRCUIT_TYPE,
+            new Point(100, 10), getContainerEP(), new Dimension(50, 50));
+
+        ShapeEditPart geoshape1EP = getFixture().createShapeUsingTool(
+            GeoshapeType.CYLINDER, new Point(10, 100), getContainerEP(),
+            new Dimension(50, 50));
+
+        ShapeEditPart geoshape2EP = getFixture().createShapeUsingTool(
+            GeoshapeType.DIAMOND, new Point(100, 100), getContainerEP(),
+            new Dimension(50, 50));
+
+        flushEventQueue();
+
+        // Cache the views so we can find the editparts again later.
+        note1View = (View) note1EP.getModel();
+        note2View = (View) note2EP.getModel();
+        geoshape1View = (View) geoshape1EP.getModel();
+        geoshape2View = (View) geoshape2EP.getModel();
+
+        // Create some connections just to make things more complicated.
+        getFixture().createConnectorUsingTool(note1EP, geoshape1EP,
+            GeoshapeType.LINE);
+        getFixture().createConnectorUsingTool(note2EP, geoshape1EP,
+            GeoshapeType.LINE);
+        getFixture().createConnectorUsingTool(note2EP, geoshape2EP,
+            GeoshapeType.LINE);
+        getFixture().createConnectorUsingTool(geoshape1EP, geoshape2EP,
+            GeoshapeType.LINE);
+
+        flushEventQueue();
+    }
+
+    public void testRefreshCanonicalDoesNotCreateDoubles()
+        throws Exception {
+        setupShapesAndGroups();
+
+        assertEquals(2, getContainerEP().getChildren().size());
+
+        // trigger a canonical refresh
+        getFixture().createShapeUsingTool(CIRCUIT_TYPE, new Point(10, 10),
+            getContainerEP(), new Dimension(50, 50));
+        flushEventQueue();
+
+        assertEquals(3, getContainerEP().getChildren().size());
+    }
+
+    public void testDeleteShapeInGroupDoesNotReappear()
+        throws Exception {
+
+        setupShapes();
+
+        List shapes = new LinkedList();
+        shapes.add(getNote1EP());
+        shapes.add(getGeoshape1EP());
+        shapes.add(getGeoshape2EP());
+
+        GroupEditPart groupEP = groupShapes(shapes);
+
+        assertEquals(2, getContainerEP().getChildren().size());
+        assertEquals(3, groupEP.getChildren().size());
+
+        Request request = new GroupRequest(RequestConstants.REQ_DELETE);
+
+        // Delete one shape from the inner group.
+        getCommandStack().execute(getNote1EP().getCommand(request));
+
+        assertEquals(2, getContainerEP().getChildren().size());
+        assertEquals(2, groupEP.getChildren().size());
+
+        // trigger a canonical refresh
+        getFixture().createShapeUsingTool(CIRCUIT_TYPE, new Point(10, 10),
+            getContainerEP(), new Dimension(50, 50));
+        flushEventQueue();
+
+        assertEquals(3, getContainerEP().getChildren().size());
+        assertEquals(2, groupEP.getChildren().size());
+
+    }
+
+}
diff --git a/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/util/AbstractPresentationTestFixture.java b/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/util/AbstractPresentationTestFixture.java
index b6cf997..bf2cc44 100644
--- a/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/util/AbstractPresentationTestFixture.java
+++ b/org.eclipse.gmf.tests.runtime.diagram.ui/src/org/eclipse/gmf/tests/runtime/diagram/ui/util/AbstractPresentationTestFixture.java
@@ -24,6 +24,7 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.draw2d.geometry.Dimension;
 import org.eclipse.draw2d.geometry.Point;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.resource.Resource;
@@ -398,60 +399,78 @@
 		}
 	}
 	
-	/**
-	 * Creates a new shape using the request created by the
-	 * <code>CreationTool</code>.
-	 * 
-	 * @param elementType
-	 *            the type of the shape/element to be created
-	 * @param location
-	 *            the location for the new shape
-	 * @return the new shape's editpart
-	 */
-	public ShapeEditPart createShapeUsingTool(IElementType elementType,
-			Point location, IGraphicalEditPart containerEP) {
+       /**
+     * Creates a new shape using the request created by the
+     * <code>CreationTool</code>.
+     * 
+     * @param elementType
+     *            the type of the shape/element to be created
+     * @param location
+     *            the location for the new shape
+     * @return the new shape's editpart
+     */
+    public ShapeEditPart createShapeUsingTool(IElementType elementType,
+            Point location, IGraphicalEditPart containerEP) {
+        return createShapeUsingTool(elementType, location, containerEP, null);
+    }
+    
+    /**
+     * Creates a new shape using the request created by the
+     * <code>CreationTool</code>.
+     * 
+     * @param elementType
+     *            the type of the shape/element to be created
+     * @param location
+     *            the location for the new shape
+     * @param size
+     *            the initial size of the new shape
+     * @return the new shape's editpart
+     */
+    public ShapeEditPart createShapeUsingTool(IElementType elementType,
+            Point location, IGraphicalEditPart containerEP, Dimension size) {
 
-		CreateRequest request = getCreationRequest(elementType);
-		request.setLocation(location);
-		Command cmd = containerEP.getCommand(request);
+        CreateRequest request = getCreationRequest(elementType);
+        request.setLocation(location);
+        request.setSize(size);
+        Command cmd = containerEP.getCommand(request);
 
-		int previousNumChildren = containerEP.getChildren().size();
+        int previousNumChildren = containerEP.getChildren().size();
 
-		getCommandStack().execute(cmd);
-		assertEquals(previousNumChildren + 1, containerEP.getChildren().size());
+        getCommandStack().execute(cmd);
+        assertEquals(previousNumChildren + 1, containerEP.getChildren().size());
 
-		Object newView = ((IAdaptable) ((List) request.getNewObject()).get(0)).getAdapter(View.class);
-		assertNotNull(newView);
-		assertTrue(!ViewUtil.isTransient((View)newView));
-		
-		EObject element = ((View)newView).getElement();
-		
-		getCommandStack().undo();
-		assertEquals(previousNumChildren, containerEP.getChildren().size());
+        Object newView = ((IAdaptable) ((List) request.getNewObject()).get(0)).getAdapter(View.class);
+        assertNotNull(newView);
+        assertTrue(!ViewUtil.isTransient((View)newView));
+        
+        EObject element = ((View)newView).getElement();
+        
+        getCommandStack().undo();
+        assertEquals(previousNumChildren, containerEP.getChildren().size());
 
-		getCommandStack().redo();
-		assertEquals(previousNumChildren + 1, containerEP.getChildren().size());
+        getCommandStack().redo();
+        assertEquals(previousNumChildren + 1, containerEP.getChildren().size());
 
-		IGraphicalEditPart newShape = null;
-		if (element != null) {
-			List children = containerEP.getChildren();
-			ListIterator li = children.listIterator();
-			while (li.hasNext()) {
-				IGraphicalEditPart gep = (IGraphicalEditPart)li.next();
-				if (gep.getNotationView().getElement().equals(element)) {
-					newShape = gep;
-				}
-			}
-		}
-		else {
-			newShape = (ShapeEditPart) getDiagramEditPart()
-			.getViewer().getEditPartRegistry().get(newView);
-			assertNotNull(newShape);
-		}
-		
-		assertTrue(newShape != null && newShape instanceof ShapeEditPart);
-		return (ShapeEditPart)newShape;
-	}
+        IGraphicalEditPart newShape = null;
+        if (element != null) {
+            List children = containerEP.getChildren();
+            ListIterator li = children.listIterator();
+            while (li.hasNext()) {
+                IGraphicalEditPart gep = (IGraphicalEditPart)li.next();
+                if (gep.getNotationView() != null && element.equals(gep.getNotationView().getElement())) {
+                    newShape = gep;
+                }
+            }
+        }
+        else {
+            newShape = (ShapeEditPart) getDiagramEditPart()
+            .getViewer().getEditPartRegistry().get(newView);
+            assertNotNull(newShape);
+        }
+        
+        assertTrue(newShape != null && newShape instanceof ShapeEditPart);
+        return (ShapeEditPart)newShape;
+    }
 
 	/**
 	 * Given an <code>IElementType</code>, gets the creation request that can be used to 
@@ -483,22 +502,43 @@
 		return request;
 	}
 
-	/**
-	 * Creates a new shape using the request created by the
-	 * <code>CreationTool</code>.
-	 * 
-	 * @param elementType
-	 *            the type of the shape/element to be created
-	 * @param location
-	 *            the location for the new shape
-	 * @return the new shape's editpart
-	 */
-	public ShapeEditPart createShapeUsingTool(IElementType elementType,
-			Point location) {
+    /**
+     * Creates a new shape using the request created by the
+     * <code>CreationTool</code>.
+     * 
+     * @param elementType
+     *            the type of the shape/element to be created
+     * @param location
+     *            the location for the new shape
+     * @return the new shape's editpart
+     */
+    public ShapeEditPart createShapeUsingTool(IElementType elementType,
+            Point location) {
 
-		return createShapeUsingTool(elementType, location, getDiagramEditPart());
+        return createShapeUsingTool(elementType, location, getDiagramEditPart());
 
-	}
+    }
+
+    /**
+     * Creates a new shape using the request created by the
+     * <code>CreationTool</code>.
+     * 
+     * @param elementType
+     *            the type of the shape/element to be created
+     * @param location
+     *            the location for the new shape
+     * @param size
+     *            the initial size of the new shape
+     * @return the new shape's editpart
+     */
+    public ShapeEditPart createShapeUsingTool(IElementType elementType,
+            Point location, Dimension size) {
+
+        ShapeEditPart shapeEP = createShapeUsingTool(elementType, location, getDiagramEditPart(), size);
+        
+        return shapeEP;
+
+    }
 	
 	/**
 	 * Creates a new connector using the request created by the