[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