Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Redor2015-03-25 17:36:04 +0000
committerLaurent Redor2015-07-06 06:50:34 +0000
commit6c1e6980a73095c67de71c78e246582e6510095a (patch)
tree70b9f285de1c072b9b581bdb63005b74cfdb23c2
parenta37057c793aaa16273ca830340c7d5c655dfc399 (diff)
downloadorg.eclipse.sirius-6c1e6980a73095c67de71c78e246582e6510095a.tar.gz
org.eclipse.sirius-6c1e6980a73095c67de71c78e246582e6510095a.tar.xz
org.eclipse.sirius-6c1e6980a73095c67de71c78e246582e6510095a.zip
[463485] Add a snap to all shapes mode
* Several edit parts have been updated to use SiriusSnapToHelperUtil instead of SnapToHelperUtil to choose SiriusSnapToGeometry instead of SnapToGeometryEx * SiriusSnapToGeometry extends SnapToGeometryEx to allow to snap to all visible shapes and not only brothers ones. It uses the snapToAll mode from extended data of request (set by the below trackers). * Update tracker NoCopyDragEditPartsTrackerEx to activate the mode snapToAllShapes when shortcut is pressed. * Update tracker SiriusResizeTracker to activate the mode snapToAllShapes when shortcut is pressed. A specific request is used for this tracker as we can not use the extended meta-data, as for NoCopyDragEditPartsTrackerEx. Indeed, the meta-data is cleaned before calling SiriusSnapToGeometry. * Add automatic tests with zoom, scroll in diagram, scroll in container with all kind of nodes (container, node, border nodes). * GraphicalHelper.getAbsoluteBoundsIn100Percent has been improved because of a lack of precision detected during tests. All similar methods, ie using translateToAbsolute(), have been also improved. Bug: 463485 Change-Id: Icaabf7d7d763c9cf2a283e3cab76f1ec0aa0956e Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/edit/api/part/AbstractBorderedDiagramElementEditPart.java23
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SiriusResizeTracker.java55
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SnapChangeBoundsRequest.java62
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/AbstractDNodeContainerCompartmentEditPart.java10
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/DDiagramEditPart.java13
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ruler/SiriusSnapToGeometry.java138
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ruler/SiriusSnapToHelperUtil.java95
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ui/NoCopyDragEditPartsTrackerEx.java82
-rw-r--r--plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/util/EditPartQuery.java102
-rw-r--r--plugins/org.eclipse.sirius.doc/.settings/org.eclipse.core.resources.prefs2
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/Release_Notes.html28
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile10
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.html53
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.textile39
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/properties_view_rulers_and_grid_tab.pngbin0 -> 33205 bytes
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_all_shapes.png (renamed from plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/images/snapToAllShapes.png)bin12781 -> 12781 bytes
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_all_shapes_2.png (renamed from plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/images/snapToAllShapes_2.png)bin13135 -> 13135 bytes
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_shape.pngbin0 -> 8938 bytes
-rw-r--r--plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/463485.html (renamed from plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/463485.html)0
-rw-r--r--plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/463485.textile (renamed from plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/463485.textile)0
-rw-r--r--plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/images/snapToAllShapes.pngbin0 -> 12781 bytes
-rw-r--r--plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/images/snapToAllShapes_2.pngbin0 -> 13135 bytes
-rw-r--r--plugins/org.eclipse.sirius.ext.emf.ui/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.sirius.ext.gef/META-INF/MANIFEST.MF5
-rw-r--r--plugins/org.eclipse.sirius.ext.gef/src/org/eclipse/sirius/ext/gef/query/EditPartQuery.java95
-rw-r--r--plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/editparts/GraphicalHelper.java26
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot.support/src/org/eclipse/sirius/tests/swtbot/support/api/condition/TopCondition.java77
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/My.ecore18
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/representations.aird443
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/snapToAll.odesign74
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/SnapAllShapesTest.java295
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java1
33 files changed, 1718 insertions, 36 deletions
diff --git a/plugins/org.eclipse.sirius.diagram.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.diagram.ui/META-INF/MANIFEST.MF
index a0c2c249f6..3904b6ea79 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.sirius.diagram.ui/META-INF/MANIFEST.MF
@@ -179,6 +179,7 @@ Export-Package: org.eclipse.sirius.diagram.description.concern.provider;version=
org.eclipse.sirius.diagram.ui.tools.internal.providers.decorators;x-internal:=true;version="2.0.4",
org.eclipse.sirius.diagram.ui.tools.internal.resource;x-internal:=true;version="2.0.4",
org.eclipse.sirius.diagram.ui.tools.internal.routers;x-internal:=true;version="2.0.4",
+ org.eclipse.sirius.diagram.ui.tools.internal.ruler;x-internal:=true;version="3.1.0",
org.eclipse.sirius.diagram.ui.tools.internal.testers;x-internal:=true;version="2.1.0",
org.eclipse.sirius.diagram.ui.tools.internal.ui;x-internal:=true;version="2.0.4",
org.eclipse.sirius.diagram.ui.tools.internal.util;x-internal:=true;version="3.0.0",
@@ -191,7 +192,8 @@ Bundle-ActivationPolicy: lazy
Import-Package: org.eclipse.sirius.ext.base;version="2.0.0",
org.eclipse.sirius.ext.draw2d.figure;version="2.0.0",
org.eclipse.sirius.ext.emf;version="2.0.0",
- org.eclipse.sirius.ext.emf.ui.properties,
+ org.eclipse.sirius.ext.emf.ui.properties;version="3.0.0",
org.eclipse.sirius.ext.gef.editpolicies;version="2.0.0",
+ org.eclipse.sirius.ext.gef.query;version="3.1.0",
org.eclipse.sirius.ext.gmf.runtime.editparts;version="2.0.0",
org.eclipse.sirius.ext.swt;version="2.0.0"
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/edit/api/part/AbstractBorderedDiagramElementEditPart.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/edit/api/part/AbstractBorderedDiagramElementEditPart.java
index 00de07ec0c..bb8b31c9c6 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/edit/api/part/AbstractBorderedDiagramElementEditPart.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/edit/api/part/AbstractBorderedDiagramElementEditPart.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 THALES GLOBAL SERVICES.
+ * Copyright (c) 2013, 2015 THALES GLOBAL SERVICES.
* 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
@@ -14,6 +14,7 @@ import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gef.SnapToHelper;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener;
import org.eclipse.gmf.runtime.diagram.ui.editparts.AbstractBorderedShapeEditPart;
@@ -24,6 +25,7 @@ import org.eclipse.sirius.diagram.ui.edit.internal.part.AbstractDiagramNodeEditP
import org.eclipse.sirius.diagram.ui.edit.internal.part.DiagramElementEditPartOperation;
import org.eclipse.sirius.diagram.ui.edit.internal.part.EditStatusUpdater;
import org.eclipse.sirius.diagram.ui.tools.api.permission.EditPartAuthorityListener;
+import org.eclipse.sirius.diagram.ui.tools.internal.ruler.SiriusSnapToHelperUtil;
import org.eclipse.sirius.ecore.extender.business.api.permission.IPermissionAuthority;
import org.eclipse.sirius.ecore.extender.business.api.permission.PermissionAuthorityRegistry;
import org.eclipse.swt.graphics.Image;
@@ -83,6 +85,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
*
* @see org.eclipse.sirius.diagram.edit.api.part.IDiagramElementEditPart#getEAdapterDiagramElement()
*/
+ @Override
public NotificationListener getEAdapterDiagramElement() {
if (this.adapterDiagramElement == null) {
this.adapterDiagramElement = DiagramElementEditPartOperation.createEApdaterDiagramElement(this);
@@ -93,6 +96,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
/**
* {@inheritDoc}
*/
+ @Override
public NotificationListener getEditModeListener() {
return this.editModeListener;
}
@@ -102,6 +106,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
*
* @see org.eclipse.sirius.diagram.edit.api.part.IDiagramElementEditPart#getEditPartAuthorityListener()
*/
+ @Override
public EditPartAuthorityListener getEditPartAuthorityListener() {
return this.authListener;
}
@@ -111,6 +116,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
*
* @see org.eclipse.sirius.diagram.edit.api.part.IDiagramElementEditPart#resolveAllSemanticElements()
*/
+ @Override
public List<EObject> resolveAllSemanticElements() {
return DiagramElementEditPartOperation.resolveAllSemanticElements(this);
}
@@ -120,6 +126,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
*
* @see org.eclipse.sirius.diagram.edit.api.part.IDiagramElementEditPart#resolveDiagramElement()
*/
+ @Override
public DDiagramElement resolveDiagramElement() {
return DiagramElementEditPartOperation.resolveDiagramElement(this);
}
@@ -129,6 +136,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
*
* @see org.eclipse.sirius.diagram.edit.api.part.IDiagramElementEditPart#resolveTargetSemanticElement()
*/
+ @Override
public EObject resolveTargetSemanticElement() {
return DiagramElementEditPartOperation.resolveTargetSemanticElement(this);
}
@@ -138,6 +146,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
*
* @see org.eclipse.sirius.diagram.edit.api.part.IDiagramElementEditPart#getStyleEditPart()
*/
+ @Override
public IStyleEditPart getStyleEditPart() {
return DiagramElementEditPartOperation.getStyleEditPart(this);
}
@@ -215,6 +224,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
* @see org.eclipse.sirius.diagram.edit.api.part.IAbstractDiagramNodeEditPart#createBorderItemLocator(IFigure,
* DDiagramElement)
*/
+ @Override
public IBorderItemLocator createBorderItemLocator(final IFigure figure, final DDiagramElement vpElementBorderItem) {
return AbstractDiagramNodeEditPartOperation.createBorderItemLocator(this, figure, vpElementBorderItem);
}
@@ -224,6 +234,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
*
* @see org.eclipse.sirius.diagram.edit.api.part.IDiagramElementEditPart#getLabelIcon()
*/
+ @Override
public Image getLabelIcon() {
return DiagramElementEditPartOperation.getLabelIcon(this);
}
@@ -248,6 +259,7 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
* the tooltip's text.
* @since 0.9.0
*/
+ @Override
public void setTooltipText(final String text) {
AbstractDiagramNodeEditPartOperation.setTooltipText(this, text);
}
@@ -257,7 +269,16 @@ public abstract class AbstractBorderedDiagramElementEditPart extends AbstractBor
*
* @see org.eclipse.sirius.diagram.edit.api.part.IAbstractDiagramNodeEditPart#getZoomManager()
*/
+ @Override
public ZoomManager getZoomManager() {
return AbstractDiagramNodeEditPartOperation.getZoomManager(this);
}
+
+ @Override
+ public Object getAdapter(Class key) {
+ if (key == SnapToHelper.class) {
+ return SiriusSnapToHelperUtil.getSnapHelper(this);
+ }
+ return super.getAdapter(key);
+ }
}
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SiriusResizeTracker.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SiriusResizeTracker.java
index 460c6c0bb1..4f4ff5ebeb 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SiriusResizeTracker.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SiriusResizeTracker.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 THALES GLOBAL SERVICES.
+ * Copyright (c) 2014, 2015 THALES GLOBAL SERVICES.
* 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,7 +11,10 @@
package org.eclipse.sirius.diagram.ui.graphical.edit.policies;
import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.tools.ResizeTracker;
+import org.eclipse.sirius.diagram.ui.tools.internal.ui.NoCopyDragEditPartsTrackerEx;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
@@ -55,6 +58,16 @@ public class SiriusResizeTracker extends ResizeTracker {
boolean childrenMoveMode = DEFAULT_CHILDREN_MOVE_MODE;
/**
+ * The mode of this tracker concerning the snap to shape:
+ * <UL>
+ * <LI>true to snap to all shapes and not only brothers ones,</LI>
+ * <LI>false otherwise.</LI>
+ * </UL>
+ * This variable is used to update the request.
+ */
+ boolean snapToAllShape = NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE;
+
+ /**
* Default constructor.
*
* @param owner
@@ -67,19 +80,43 @@ public class SiriusResizeTracker extends ResizeTracker {
}
@Override
+ protected Request createSourceRequest() {
+ ChangeBoundsRequest request;
+ // Create a specific request (see javadoc of SnapChangeBoundsRequest for
+ // more details).
+ request = new SnapChangeBoundsRequest(REQ_RESIZE);
+ request.setResizeDirection(getResizeDirection());
+ return request;
+ }
+
+ @Override
protected boolean handleKeyDown(KeyEvent event) {
+ boolean keyHandled = false;
if (SiriusResizeTracker.CHILDREN_MOVE_MODE_SHORTCUT_KEY == event.keyCode) {
childrenMoveMode = !SiriusResizeTracker.DEFAULT_CHILDREN_MOVE_MODE;
- return true;
+ keyHandled = true;
+ } else if (NoCopyDragEditPartsTrackerEx.SNAP_TO_ALL == event.keyCode) {
+ snapToAllShape = !NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE;
+ keyHandled = true;
+ }
+ if (keyHandled) {
+ return keyHandled;
}
return super.handleKeyDown(event);
}
@Override
protected boolean handleKeyUp(KeyEvent event) {
+ boolean keyHandled = false;
if (SiriusResizeTracker.CHILDREN_MOVE_MODE_SHORTCUT_KEY == event.keyCode) {
childrenMoveMode = SiriusResizeTracker.DEFAULT_CHILDREN_MOVE_MODE;
- return true;
+ keyHandled = true;
+ } else if (NoCopyDragEditPartsTrackerEx.SNAP_TO_ALL == event.keyCode) {
+ snapToAllShape = NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE;
+ keyHandled = true;
+ }
+ if (keyHandled) {
+ return keyHandled;
}
return super.handleKeyUp(event);
}
@@ -87,11 +124,19 @@ public class SiriusResizeTracker extends ResizeTracker {
/**
* Set {@link CHILDREN_MOVE_MODE_KEY} extended data after update of request
* (the extended data are cleaned during the
- * {@link ResizeTracker#updateSourceRequest()}).
+ * {@link ResizeTracker#updateSourceRequest()}). Also update the request
+ * with information about snapToAll mode.
*/
@SuppressWarnings("unchecked")
@Override
protected void updateSourceRequest() {
+ if (getSourceRequest() instanceof SnapChangeBoundsRequest) {
+ if (snapToAllShape) {
+ ((SnapChangeBoundsRequest) getSourceRequest()).setSnapToAllShape(true);
+ } else {
+ ((SnapChangeBoundsRequest) getSourceRequest()).setSnapToAllShape(false);
+ }
+ }
super.updateSourceRequest();
if (childrenMoveMode) {
getSourceRequest().getExtendedData().put(SiriusResizeTracker.CHILDREN_MOVE_MODE_KEY, Boolean.TRUE);
@@ -110,7 +155,9 @@ public class SiriusResizeTracker extends ResizeTracker {
@Override
protected boolean handleButtonUp(int button) {
boolean result = super.handleButtonUp(button);
+ // Clean up the mode to original state.
childrenMoveMode = SiriusResizeTracker.DEFAULT_CHILDREN_MOVE_MODE;
+ snapToAllShape = NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE;
return result;
}
}
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SnapChangeBoundsRequest.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SnapChangeBoundsRequest.java
new file mode 100644
index 0000000000..a2d181c5c5
--- /dev/null
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SnapChangeBoundsRequest.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.diagram.ui.graphical.edit.policies;
+
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.sirius.diagram.ui.tools.internal.ui.NoCopyDragEditPartsTrackerEx;
+
+/**
+ * A ChangeBoundsRequest with a specific data concerning the snapToAll feature.
+ * The {@link org.eclipse.gef.tools.ResizeTracker} does not allow to use the
+ * extendedMetaData of the Request because it is clean before it can be used in
+ * the {@link org.eclipse.gef.SnapToGeometry}.
+ *
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public class SnapChangeBoundsRequest extends ChangeBoundsRequest {
+ /**
+ * Reflect the mode of the tracker concerning the snap to shape:
+ * <UL>
+ * <LI>true to snap to all shapes and not only brothers ones,</LI>
+ * <LI>false otherwise.</LI>
+ * </UL>
+ */
+ boolean snapToAllShape = NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE;
+
+ /**
+ * Creates a ChangeBoundsRequest with the given type.
+ *
+ * @param type
+ * The type of Request.
+ */
+ public SnapChangeBoundsRequest(Object type) {
+ super(type);
+ }
+
+ /**
+ * Return true if the snap to all shape mode is activated, false otherwise.
+ *
+ * @return the snapToAllShape status
+ */
+ public boolean isSnapToAllShape() {
+ return snapToAllShape;
+ }
+
+ /**
+ * Activate or deactivate the snap to all shape mode.
+ *
+ * @param snapToAllShape
+ * the snapToAllShape to set
+ */
+ public void setSnapToAllShape(boolean snapToAllShape) {
+ this.snapToAllShape = snapToAllShape;
+ }
+}
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/AbstractDNodeContainerCompartmentEditPart.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/AbstractDNodeContainerCompartmentEditPart.java
index 19040919bb..7e0cb0bc4c 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/AbstractDNodeContainerCompartmentEditPart.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/AbstractDNodeContainerCompartmentEditPart.java
@@ -32,6 +32,7 @@ import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
+import org.eclipse.gef.SnapToHelper;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.ReconnectRequest;
@@ -73,6 +74,7 @@ import org.eclipse.sirius.diagram.ui.tools.api.figure.ViewNodeContainerFigureDes
import org.eclipse.sirius.diagram.ui.tools.api.requests.RequestConstants;
import org.eclipse.sirius.diagram.ui.tools.internal.figure.LabelBorderStyleIds;
import org.eclipse.sirius.diagram.ui.tools.internal.graphical.edit.policies.ContainerCompartmentNodeEditPolicy;
+import org.eclipse.sirius.diagram.ui.tools.internal.ruler.SiriusSnapToHelperUtil;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.ext.base.Options;
import org.eclipse.sirius.ext.gef.editpolicies.SiriusSnapFeedbackPolicy;
@@ -549,4 +551,12 @@ public abstract class AbstractDNodeContainerCompartmentEditPart extends ShapeCom
return bounds;
}
};
+
+ @Override
+ public Object getAdapter(Class key) {
+ if (key == SnapToHelper.class) {
+ return SiriusSnapToHelperUtil.getSnapHelper(this);
+ }
+ return super.getAdapter(key);
+ }
}
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/DDiagramEditPart.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/DDiagramEditPart.java
index 2872bbe630..a18978a4e3 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/DDiagramEditPart.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/edit/parts/DDiagramEditPart.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2008 THALES GLOBAL SERVICES.
+ * Copyright (c) 2007, 2015 THALES GLOBAL SERVICES.
* 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
@@ -12,6 +12,7 @@ package org.eclipse.sirius.diagram.ui.internal.edit.parts;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.SnapToHelper;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
@@ -31,6 +32,7 @@ import org.eclipse.sirius.diagram.ui.internal.edit.policies.DDiagramItemSemantic
import org.eclipse.sirius.diagram.ui.internal.edit.policies.canonicals.DumnySiriusCanonicalConnectionEditPolicy;
import org.eclipse.sirius.diagram.ui.tools.api.policy.CompoundEditPolicy;
import org.eclipse.sirius.diagram.ui.tools.api.requests.RequestConstants;
+import org.eclipse.sirius.diagram.ui.tools.internal.ruler.SiriusSnapToHelperUtil;
import org.eclipse.sirius.tools.api.command.SiriusCommand;
/**
@@ -48,6 +50,7 @@ public class DDiagramEditPart extends AbstractDDiagramEditPart {
*/
public static final int VISUAL_ID = 1000;
+ @Override
protected void refreshBackgroundColor() {
super.refreshBackgroundColor();
};
@@ -62,6 +65,7 @@ public class DDiagramEditPart extends AbstractDDiagramEditPart {
/**
* @not-generated add the compound edit policy
*/
+ @Override
protected void createDefaultEditPolicies() {
super.createDefaultEditPolicies();
installEditPolicy(EditPolicyRoles.SEMANTIC_ROLE, new DDiagramItemSemanticEditPolicy());
@@ -168,4 +172,11 @@ public class DDiagramEditPart extends AbstractDDiagramEditPart {
}
+ @Override
+ public Object getAdapter(Class key) {
+ if (key == SnapToHelper.class) {
+ return SiriusSnapToHelperUtil.getSnapHelper(this);
+ }
+ return super.getAdapter(key);
+ }
}
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ruler/SiriusSnapToGeometry.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ruler/SiriusSnapToGeometry.java
new file mode 100644
index 0000000000..c1bb672c86
--- /dev/null
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ruler/SiriusSnapToGeometry.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.diagram.ui.tools.internal.ruler;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.geometry.PrecisionRectangle;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.internal.ruler.SnapToGeometryEx;
+import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractBorderedDiagramElementEditPart;
+import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramBorderNodeEditPart;
+import org.eclipse.sirius.diagram.ui.graphical.edit.policies.SnapChangeBoundsRequest;
+import org.eclipse.sirius.diagram.ui.tools.internal.ui.NoCopyDragEditPartsTrackerEx;
+import org.eclipse.sirius.ext.gef.query.EditPartQuery;
+import org.eclipse.sirius.ext.gmf.runtime.editparts.GraphicalHelper;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Overridden to support all visible shapes in SnapToShape and not only brothers
+ * ones. See {@link NoCopyDragEditPartsTrackerEx#SNAP_TO_ALL_SHAPE_KEY}.
+ *
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public class SiriusSnapToGeometry extends SnapToGeometryEx {
+
+ boolean snapToAll;
+
+ /**
+ * A vertical or horizontal snapping point.<BR>
+ * Only overridden to have access to constructor.
+ */
+ class SiriusEntry extends Entry {
+ protected SiriusEntry(int type, int location) {
+ super(type, location);
+ }
+ }
+
+ /**
+ * Default constructor.
+ *
+ * @param container
+ * the container editpart
+ */
+ public SiriusSnapToGeometry(GraphicalEditPart container) {
+ super(container);
+ }
+
+ @Override
+ public int snapRectangle(Request request, int snapOrientation, PrecisionRectangle baseRect, PrecisionRectangle result) {
+ // Get snapToAll mode from request (set by the
+ // SiriusDragEditPartsTrackerEx or by the SiriusResizeTracker)
+ Object snapToAllExtendedData = request.getExtendedData().get(NoCopyDragEditPartsTrackerEx.SNAP_TO_ALL_SHAPE_KEY);
+ boolean oldSnapToAll = snapToAll;
+ snapToAll = (snapToAllExtendedData == null && NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE) || (snapToAllExtendedData != null && ((Boolean) snapToAllExtendedData).booleanValue());
+ if (!snapToAll && request instanceof SnapChangeBoundsRequest) {
+ snapToAll = ((SnapChangeBoundsRequest) request).isSnapToAllShape();
+ }
+
+ if (oldSnapToAll != snapToAll) {
+ // Reset previous computed horizontal rows and vertical column
+ // being snapped to.
+ rows = null;
+ cols = null;
+ }
+
+ return super.snapRectangle(request, snapOrientation, baseRect, result);
+ }
+
+ @Override
+ protected List generateSnapPartsList(List exclusions) {
+ if (!snapToAll) {
+ return super.generateSnapPartsList(exclusions);
+ } else {
+ // Get all potential snap targets
+ List<Class<?>> expectedClasses = Lists.newArrayList();
+ expectedClasses.add(AbstractBorderedDiagramElementEditPart.class);
+ expectedClasses.add(AbstractDiagramBorderNodeEditPart.class);
+ List<EditPart> snapPartsList = new ArrayList<EditPart>(new EditPartQuery(container.getRoot()).getAllChildren(false, expectedClasses));
+ // Add children of elements that are being dragged
+ List<EditPart> exclusionsWithChildren = new ArrayList<EditPart>();
+ for (Object editPart : exclusions) {
+ if (editPart instanceof EditPart) {
+ exclusionsWithChildren.add((EditPart) editPart);
+ exclusionsWithChildren.addAll(new EditPartQuery((EditPart) editPart).getAllChildren(false, expectedClasses));
+ }
+ }
+ // Don't snap to any figure that is being dragged
+ snapPartsList.removeAll(exclusionsWithChildren);
+
+ // Don't snap to hidden figures (not visible for end-user)
+ for (Iterator<EditPart> iter = snapPartsList.iterator(); iter.hasNext(); /* */) {
+ EditPart snapPart = iter.next();
+ if (snapPart instanceof IGraphicalEditPart && !new org.eclipse.sirius.diagram.ui.tools.internal.util.EditPartQuery((IGraphicalEditPart) snapPart).isVisibleOnViewport()) {
+ iter.remove();
+ }
+ }
+
+ return snapPartsList;
+ }
+
+ }
+
+ @Override
+ protected void populateRowsAndCols(List parts) {
+ if (!snapToAll) {
+ super.populateRowsAndCols(parts);
+ } else {
+ rows = new Entry[parts.size() * 3];
+ cols = new Entry[parts.size() * 3];
+ for (int i = 0; i < parts.size(); i++) {
+ IGraphicalEditPart child = (IGraphicalEditPart) parts.get(i);
+ Rectangle bounds = GraphicalHelper.getAbsoluteBounds(child);
+ makeRelative(container.getContentPane(), bounds);
+ cols[i * 3] = new SiriusEntry(-1, bounds.x);
+ rows[i * 3] = new SiriusEntry(-1, bounds.y);
+ cols[i * 3 + 1] = new SiriusEntry(0, bounds.x + (bounds.width - 1) / 2);
+ rows[i * 3 + 1] = new SiriusEntry(0, bounds.y + (bounds.height - 1) / 2);
+ cols[i * 3 + 2] = new SiriusEntry(1, bounds.right() - 1);
+ rows[i * 3 + 2] = new SiriusEntry(1, bounds.bottom() - 1);
+ }
+ }
+ }
+}
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ruler/SiriusSnapToHelperUtil.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ruler/SiriusSnapToHelperUtil.java
new file mode 100644
index 0000000000..e9d07512e6
--- /dev/null
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ruler/SiriusSnapToHelperUtil.java
@@ -0,0 +1,95 @@
+/******************************************************************************
+ * Copyright (c) 2007, 2015 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.sirius.diagram.ui.tools.internal.ruler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.SnapToGeometry;
+import org.eclipse.gef.SnapToGrid;
+import org.eclipse.gef.SnapToHelper;
+import org.eclipse.gef.rulers.RulerProvider;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.internal.editparts.ISurfaceEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.internal.ruler.CompoundSnapToHelperEx;
+import org.eclipse.gmf.runtime.diagram.ui.internal.ruler.SnapToGridEx;
+import org.eclipse.gmf.runtime.diagram.ui.internal.ruler.SnapToGuidesEx;
+import org.eclipse.gmf.runtime.diagram.ui.internal.ruler.SnapToHelperUtil;
+
+/**
+ * Utility class for the snapping behavior. This class adds the capability to
+ * snap to all visible figures.
+ *
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public class SiriusSnapToHelperUtil extends SnapToHelperUtil {
+ // CHECKSTYLE:OFF Method duplicate from SnapToHelperUtil and not formatted
+ // to facilitate comparison.
+ /**
+ * returns the the appropriate snap helper(s), this method will always reach
+ * for the first reachable DiagramEditPart using the passed edit part, then
+ * use this Diagram edit part to get the snap helper
+ *
+ * @param editPart
+ * , edit part to get the snap helper for
+ * @return
+ */
+ static public Object getSnapHelper(GraphicalEditPart editPart) {
+ // get the diagram Edit Part
+ GraphicalEditPart diagramEditPart = editPart;
+ while (diagramEditPart != null && !(diagramEditPart instanceof DiagramEditPart)) {
+ diagramEditPart = (GraphicalEditPart) diagramEditPart.getParent();
+ }
+
+ if (diagramEditPart == null)
+ return null;
+
+ // for snap to geometry, attempt to locate a compartment as a parent
+ GraphicalEditPart parent = editPart;
+ while (parent != null && !(parent instanceof ISurfaceEditPart)) {
+ parent = (GraphicalEditPart) parent.getParent();
+ }
+
+ if (parent == null)
+ parent = diagramEditPart;
+
+ List<SnapToHelper> snapStrategies = new ArrayList<SnapToHelper>();
+ EditPartViewer viewer = diagramEditPart.getViewer();
+
+ Boolean val = (Boolean) editPart.getViewer().getProperty(RulerProvider.PROPERTY_RULER_VISIBILITY);
+
+ if (val != null && val.booleanValue())
+ snapStrategies.add(new SnapToGuidesEx(diagramEditPart));
+
+ val = (Boolean) viewer.getProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED);
+ if (val != null && val.booleanValue())
+ snapStrategies.add(new SiriusSnapToGeometry(parent));
+
+ val = (Boolean) viewer.getProperty(SnapToGrid.PROPERTY_GRID_ENABLED);
+
+ if (val != null && val.booleanValue())
+ snapStrategies.add(new SnapToGridEx(diagramEditPart));
+
+ if (snapStrategies.size() == 0)
+ return null;
+
+ if (snapStrategies.size() == 1)
+ return snapStrategies.get(0);
+
+ SnapToHelper ss[] = new SnapToHelper[snapStrategies.size()];
+ for (int i = 0; i < snapStrategies.size(); i++)
+ ss[i] = snapStrategies.get(i);
+ return new CompoundSnapToHelperEx(ss);
+ }
+ // CHECKSTYLE:ON
+}
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ui/NoCopyDragEditPartsTrackerEx.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ui/NoCopyDragEditPartsTrackerEx.java
index 85335ba7ba..84cdfc0a84 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ui/NoCopyDragEditPartsTrackerEx.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/ui/NoCopyDragEditPartsTrackerEx.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011 THALES GLOBAL SERVICES.
+ * Copyright (c) 2011, 2015 THALES GLOBAL SERVICES.
* 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,12 +11,18 @@
package org.eclipse.sirius.diagram.ui.tools.internal.ui;
import org.eclipse.gef.EditPart;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gmf.runtime.diagram.ui.tools.DragEditPartsTrackerEx;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
/**
* A specific dragEditPartTracket that disable the clone feature. Indeed, in
- * Sirius it's not natural to clone a graphical element that will be removed
- * on the next refresh.
+ * Sirius it's not natural to clone a graphical element that will be removed on
+ * the next refresh.
+ *
+ * This tracker also allows to change the behavior of SnapToShape (capability to
+ * snap to all shapes and not only brothers one).
*
* @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
*
@@ -24,6 +30,33 @@ import org.eclipse.gmf.runtime.diagram.ui.tools.DragEditPartsTrackerEx;
public class NoCopyDragEditPartsTrackerEx extends DragEditPartsTrackerEx {
/**
+ * Constant passed to extended data of the request to keep the chosen mode
+ * (with KEY {@link #SNAP_TO_ALL}.
+ */
+ public static final String SNAP_TO_ALL_SHAPE_KEY = "snapToAllShape";
+
+ /**
+ * The default mode for {@link #snapToAllShape}.
+ */
+ public static final boolean DEFAULT_SNAP_TO_SHAPE_MODE = false;
+
+ /**
+ * The key shortcut used to change the default behavior of snap to shape.
+ */
+ public static final int SNAP_TO_ALL = SWT.F4;
+
+ /**
+ * The mode of this tracker concerning the snap to shape:
+ * <UL>
+ * <LI>true to snap to all shapes and not only brothers ones,</LI>
+ * <LI>false otherwise.</LI>
+ * </UL>
+ * This variable is used when the request is updated to add an extended data
+ * to the request.
+ */
+ boolean snapToAllShape = NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE;
+
+ /**
* Defaul constructor.
*
* @param sourceEditPart
@@ -48,7 +81,6 @@ public class NoCopyDragEditPartsTrackerEx extends DragEditPartsTrackerEx {
/*
* (non-Javadoc)
- *
* @see
* org.eclipse.gmf.runtime.diagram.ui.tools.DragEditPartsTrackerEx#reveal
* (org.eclipse.gef.EditPart)
@@ -63,4 +95,46 @@ public class NoCopyDragEditPartsTrackerEx extends DragEditPartsTrackerEx {
super.reveal(editpart);
}
}
+
+ /**
+ * Overridden to update the {@link ChangeBoundsRequest} with information
+ * about snapToAll mode.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ protected void snapPoint(ChangeBoundsRequest request) {
+ if (snapToAllShape) {
+ getTargetRequest().getExtendedData().put(NoCopyDragEditPartsTrackerEx.SNAP_TO_ALL_SHAPE_KEY, Boolean.TRUE);
+ } else {
+ getTargetRequest().getExtendedData().put(NoCopyDragEditPartsTrackerEx.SNAP_TO_ALL_SHAPE_KEY, Boolean.FALSE);
+ }
+ super.snapPoint(request);
+ }
+
+ @Override
+ protected boolean handleKeyDown(KeyEvent event) {
+ if (NoCopyDragEditPartsTrackerEx.SNAP_TO_ALL == event.keyCode) {
+ snapToAllShape = !NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE;
+ return true;
+ }
+ return super.handleKeyDown(event);
+ }
+
+ @Override
+ protected boolean handleKeyUp(KeyEvent event) {
+ if (NoCopyDragEditPartsTrackerEx.SNAP_TO_ALL == event.keyCode) {
+ snapToAllShape = NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE;
+ return true;
+ }
+ return super.handleKeyUp(event);
+ }
+
+ @Override
+ protected boolean handleButtonUp(int button) {
+ boolean result = super.handleButtonUp(button);
+ // Clean up the mode to original state.
+ snapToAllShape = NoCopyDragEditPartsTrackerEx.DEFAULT_SNAP_TO_SHAPE_MODE;
+ return result;
+ }
}
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/util/EditPartQuery.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/util/EditPartQuery.java
index 24c6e4a5e3..179366205b 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/util/EditPartQuery.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/util/EditPartQuery.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010 THALES GLOBAL SERVICES.
+ * Copyright (c) 2010, 2015 THALES GLOBAL SERVICES.
* 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
@@ -17,8 +17,11 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.Viewport;
+import org.eclipse.draw2d.ViewportUtilities;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.ecore.EObject;
@@ -147,6 +150,7 @@ public class EditPartQuery {
public List<IBorderItemEditPart> getBorderNodeEditParts(final int expectedSide) {
if (part instanceof IBorderedShapeEditPart) {
Iterable<IBorderItemEditPart> bordersItemPart = Iterables.filter(part.getChildren(), Predicates.and(Predicates.instanceOf(IBorderItemEditPart.class), new Predicate<IBorderItemEditPart>() {
+ @Override
public boolean apply(IBorderItemEditPart input) {
int currentSide = input.getBorderItemLocator().getCurrentSideOfParent();
return expectedSide == currentSide;
@@ -226,6 +230,90 @@ public class EditPartQuery {
}
/**
+ * Return true if the figure of the current part is currently visible (by
+ * the end-user), false otherwise.
+ *
+ * @return true if the figure of the current part is currently visible (by
+ * the end-user), false otherwise.
+ */
+ @SuppressWarnings("unchecked")
+ public boolean isVisibleOnViewport() {
+ // Traverse the viewport path of the figure (and reduce clipRect
+ // to what is actually visible); process all viewports up to the
+ // root viewport
+ Viewport topViewport = ((FigureCanvas) part.getViewer().getControl()).getViewport();
+ IFigure figure = part.getFigure();
+ Viewport nearestEnclosingViewport = ViewportUtilities.getNearestEnclosingViewport(figure);
+ List<Viewport> enclosingViewportsPath;
+ if (topViewport.equals(nearestEnclosingViewport)) {
+ enclosingViewportsPath = Lists.newArrayList(topViewport);
+ } else {
+ enclosingViewportsPath = ViewportUtilities.getViewportsPath(nearestEnclosingViewport, topViewport, true);
+ }
+ Rectangle clipRect = getAbsoluteBoundsAsCopy(figure);
+ clipAtViewports(clipRect, enclosingViewportsPath);
+ return !clipRect.isEmpty();
+ }
+
+ /**
+ * Clips the given clipRect at all given viewports. Method copied from
+ * {@link org.eclipse.draw2d.ViewportAwareConnectionLayerClippingStrategy}.
+ *
+ * @param clipRect
+ * Rectangle to clip
+ * @param enclosingViewportsPath
+ * All viewports to use to clip
+ */
+ protected void clipAtViewports(Rectangle clipRect, List<Viewport> enclosingViewportsPath) {
+ for (Viewport viewport : enclosingViewportsPath) {
+ clipRect.intersect(getAbsoluteViewportAreaAsCopy(viewport));
+ }
+ }
+
+ /**
+ * Returns the area covered by the viewport in absolute coordinates. Method
+ * copied from
+ * {@link org.eclipse.draw2d.ViewportAwareConnectionLayerClippingStrategy}.
+ *
+ * @param viewport
+ * Concerned Viewport
+ * @return the area covered by the viewport in absolute coordinates.
+ */
+ protected Rectangle getAbsoluteViewportAreaAsCopy(Viewport viewport) {
+ return getAbsoluteClientAreaAsCopy(viewport);
+ }
+
+ /**
+ * Returns the viewport's client area in absolute coordinates. Method copied
+ * from
+ * {@link org.eclipse.draw2d.ViewportAwareConnectionLayerClippingStrategy}.
+ *
+ * @param figure
+ * Concerned figure
+ * @return a copy of the client area of this figure
+ */
+ protected Rectangle getAbsoluteClientAreaAsCopy(IFigure figure) {
+ Rectangle absoluteClientArea = figure.getClientArea();
+ figure.translateToParent(absoluteClientArea);
+ figure.translateToAbsolute(absoluteClientArea);
+ return absoluteClientArea;
+ }
+
+ /**
+ * Returns the figure's bounds in absolute coordinates. Method copied from
+ * {@link org.eclipse.draw2d.ViewportAwareConnectionLayerClippingStrategy}.
+ *
+ * @param figure
+ * Concerned figure
+ * @return the figure's bounds in absolute coordinates
+ */
+ protected Rectangle getAbsoluteBoundsAsCopy(IFigure figure) {
+ Rectangle absoluteFigureBounds = figure.getBounds().getCopy();
+ figure.translateToAbsolute(absoluteFigureBounds);
+ return absoluteFigureBounds;
+ }
+
+ /**
* Check that the container of the <code>part</code> is layouted with
* "FreeForm" style.
*
@@ -331,8 +419,8 @@ public class EditPartQuery {
expectedNewBounds = borderItemLocator.getValidLocation(expectedNewBounds, borderItemEditPart.getFigure());
}
if (PositionConstants.NORTH == resizedSide) {
- shiftingAccordingToBorderItemLocator.put((Node) borderItemEditPart.getModel(), new Dimension(expectedNewBounds.x - currentBounds.x, expectedNewBounds.y - currentBounds.y
- + parentResizeSize));
+ shiftingAccordingToBorderItemLocator.put((Node) borderItemEditPart.getModel(),
+ new Dimension(expectedNewBounds.x - currentBounds.x, expectedNewBounds.y - currentBounds.y + parentResizeSize));
} else {
shiftingAccordingToBorderItemLocator.put((Node) borderItemEditPart.getModel(), new Dimension(expectedNewBounds.x - currentBounds.x, expectedNewBounds.y - currentBounds.y));
}
@@ -429,8 +517,8 @@ public class EditPartQuery {
expectedNewBounds = borderItemLocator.getValidLocation(expectedNewBounds, borderItemEditPart.getFigure());
}
if (PositionConstants.WEST == resizedSide) {
- shiftingAccordingToBorderItemLocator.put((Node) borderItemEditPart.getModel(), new Dimension(expectedNewBounds.x - currentBounds.x + parentResizeSize, expectedNewBounds.y
- - currentBounds.y));
+ shiftingAccordingToBorderItemLocator.put((Node) borderItemEditPart.getModel(),
+ new Dimension(expectedNewBounds.x - currentBounds.x + parentResizeSize, expectedNewBounds.y - currentBounds.y));
} else {
shiftingAccordingToBorderItemLocator.put((Node) borderItemEditPart.getModel(), new Dimension(expectedNewBounds.x - currentBounds.x, expectedNewBounds.y - currentBounds.y));
}
@@ -469,6 +557,7 @@ public class EditPartQuery {
if (PositionConstants.NORTH == resizedSide) {
// Smaller y in first
getValueToCompareFunction = new Function<IBorderItemEditPart, Integer>() {
+ @Override
public Integer apply(IBorderItemEditPart from) {
Node node = (Node) from.getModel();
if (node.getLayoutConstraint() instanceof Bounds) {
@@ -481,6 +570,7 @@ public class EditPartQuery {
} else if (PositionConstants.SOUTH == resizedSide) {
// Greater (y+height) in first
getValueToCompareFunction = new Function<IBorderItemEditPart, Integer>() {
+ @Override
public Integer apply(IBorderItemEditPart from) {
Node node = (Node) from.getModel();
if (node.getLayoutConstraint() instanceof Bounds) {
@@ -493,6 +583,7 @@ public class EditPartQuery {
} else if (PositionConstants.EAST == resizedSide) {
// Greater (x+width) in first
getValueToCompareFunction = new Function<IBorderItemEditPart, Integer>() {
+ @Override
public Integer apply(IBorderItemEditPart from) {
Node node = (Node) from.getModel();
if (node.getLayoutConstraint() instanceof Bounds) {
@@ -505,6 +596,7 @@ public class EditPartQuery {
} else {
// Smaller x in first
getValueToCompareFunction = new Function<IBorderItemEditPart, Integer>() {
+ @Override
public Integer apply(IBorderItemEditPart from) {
Node node = (Node) from.getModel();
if (node.getLayoutConstraint() instanceof Bounds) {
diff --git a/plugins/org.eclipse.sirius.doc/.settings/org.eclipse.core.resources.prefs b/plugins/org.eclipse.sirius.doc/.settings/org.eclipse.core.resources.prefs
index 2627c83efb..f30aa98400 100644
--- a/plugins/org.eclipse.sirius.doc/.settings/org.eclipse.core.resources.prefs
+++ b/plugins/org.eclipse.sirius.doc/.settings/org.eclipse.core.resources.prefs
@@ -6,11 +6,11 @@ encoding//doc/specifier/general/Colors.html=utf-8
encoding//doc/specifier/general/Introduction.html=utf-8
encoding//doc/specifier/general/Model_Operations.html=utf-8
encoding//doc/specifier/general/Writing_Queries.html=utf-8
+encoding//specs/accepted/463485_snapToAllShapes/463485.html=utf-8
encoding//specs/archived/435507_SnapToGridForCreation/435507.html=utf-8
encoding//specs/archived/437097-moveEdgeClosestSegmentWhenMovingNode/437097-moveEdgeClosestSegmentWhenMovingNode.html=utf-8
encoding//specs/archived/441090_ResizeNodeWithoutModifyingContainedElementsLocation/441090.html=utf-8
encoding//specs/archived/442289_DistributeShapesActions/442289_DistributeShapesActions.html=utf-8
-encoding//specs/proposal/463485_snapToAllShapes/463485.html=utf-8
encoding//specs/proposal/464269_selectElementsAfterToolExecution/464269.html=utf-8
encoding//specs/proposal/465328_edgeLabelLocation/465328.html=utf-8
encoding//specs/proposal/471104_edgeAndPortsCompoundMoves/471104.html=utf-8
diff --git a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
index 44a180c3e1..8e70782444 100644
--- a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
+++ b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
@@ -16,6 +16,9 @@
<a href="#sirius3.1.0">Changes in Sirius 3.1.0</a>
<ol style="list-style: disc;">
<li>
+ <a href="#UserVisibleChanges">User-Visible Changes</a>
+ </li>
+ <li>
<a href="#DeveloperVisibleChanges">Developer-Visible Changes</a>
</li>
</ol>
@@ -24,7 +27,7 @@
<a href="#sirius3.0.0">Changes in Sirius 3.0.0</a>
<ol style="list-style: disc;">
<li>
- <a href="#UserVisibleChanges">User-Visible Changes</a>
+ <a href="#UserVisibleChanges2">User-Visible Changes</a>
</li>
<li>
<a href="#SpecifierVisibleChanges">Specifier-Visible Changes</a>
@@ -38,7 +41,7 @@
<a href="#sirius2.0.0">Changes in Sirius 2.0.0</a>
<ol style="list-style: disc;">
<li>
- <a href="#UserVisibleChanges2">User-Visible Changes</a>
+ <a href="#UserVisibleChanges3">User-Visible Changes</a>
</li>
<li>
<a href="#SpecifierVisibleChanges2">Specifier-Visible Changes</a>
@@ -55,7 +58,21 @@
<a href="Release_Notes_Previous.html">the release notes from previous versions</a> for details about older releases.
</p>
<h2 id="sirius3.1.0">Changes in Sirius 3.1.0</h2>
+ <h3 id="UserVisibleChanges">User-Visible Changes</h3>
+ <ul>
+ <li><span class="label label-success">Added</span> A new feature allows to snap to all shapes (instead of just to snap to brother shapes). The <kdb>F4</kdb> shortcut key activates this mode when you resize a node, move a node or move a bendpoint of edge, see
+ <a href="./user/diagrams/Diagrams.html#snap_to_shapes">documentation</a> for details.
+ </li>
+ </ul>
<h3 id="DeveloperVisibleChanges">Developer-Visible Changes</h3>
+ <h4 id="Changesinorg.eclipse.sirius.ext.gef">Changes in
+ <code>org.eclipse.sirius.ext.gef</code>
+ </h4>
+ <ul>
+ <li><span class="label label-success">Added</span> The new class
+ <code>org.eclipse.sirius.ext.gef.query.EditPartQuery</code> has been added. It allows to retrieve all children of the current part.
+ </li>
+ </ul>
<h4 id="Changesinorg.eclipse.sirius.tests.swtbot.support">Changes in
<code>org.eclipse.sirius.tests.swtbot.support</code>
</h4>
@@ -76,9 +93,12 @@
<code>drag(int, int, int, int)</code> method, to precise the key code to press during the drag&#8217;n&#8217;drop. It is possible to call this method with SWT.None to retrieve the standard behavior of
<code>drag</code> method. This method also has a correct behavior for the move of bendpoints of edges.
</li>
+ <li><span class="label label-success">Added</span>
+ <code>org.eclipse.sirius.tests.swtbot.support.api.condition.TopCondition</code>: New condition to wait that top of the edit part is on the expected location.
+ </li>
</ul>
<h2 id="sirius3.0.0">Changes in Sirius 3.0.0</h2>
- <h3 id="UserVisibleChanges">User-Visible Changes</h3>
+ <h3 id="UserVisibleChanges2">User-Visible Changes</h3>
<ul>
<li><span class="label label-success">Added</span> The ability to print table representations has been re-introduced.</li>
<li><span class="label label-success">Added</span> The quick outline feature has been added for tree and table editors, see documentation for details.</li>
@@ -1021,7 +1041,7 @@
<code>org.eclipse.sirius.xxx.ui.ext</code>, allowing them not have all that functionalities they may not want.
</p>
<h2 id="sirius2.0.0">Changes in Sirius 2.0.0</h2>
- <h3 id="UserVisibleChanges2">User-Visible Changes</h3>
+ <h3 id="UserVisibleChanges3">User-Visible Changes</h3>
<ul>
<li>It is now possible to select element that intersects the selection rectangle and not that is completely contained by the selection rectangle. This new behavior is enabled when user selects elements from right to left. The normal mode (previous mode) remains when the user selects elements from left to right.</li>
<li>The edges appearance is now kept, as much as possible, when one of its extremity is moved. A move of an extremity should move only the closest segment of the edge.</li>
diff --git a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
index b51b58b4d1..1f43fc6ed7 100644
--- a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
+++ b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
@@ -6,13 +6,23 @@ This document contains the release notes for recent major releases of Sirius. Se
h2(#sirius3.1.0). Changes in Sirius 3.1.0
+h3. User-Visible Changes
+
+* <span class="label label-success">Added</span> A new feature allows to snap to all shapes (instead of just to snap to brother shapes). The <kdb>F4</kdb> shortcut key activates this mode when you resize a node, move a node or move a bendpoint of edge, see "documentation":./user/diagrams/Diagrams.html#snap_to_shapes for details.
+
h3. Developer-Visible Changes
+h4. Changes in @org.eclipse.sirius.ext.gef@
+
+* <span class="label label-success">Added</span> The new class @org.eclipse.sirius.ext.gef.query.EditPartQuery@ has been added. It allows to retrieve all children of the current part.
+
h4. Changes in @org.eclipse.sirius.tests.swtbot.support@
* <span class="label label-success">Added</span> The methods @closePerspective(String)@, @closeSiriusPerspective()@ and @closeModelingPerspective()@ have been added in class @org.eclipse.sirius.tests.swtbot.support.api.perspective.DesignerPerspectives@ to allow the closing of perspectives.
* <span class="label label-success">Added</span> The @org.eclipse.sirius.tests.swtbot.support.api.condition.PerspectiveActivatedCondition@ new offers the capability to inverse the test. This condition becomes a DeactivatedCondition instead of an ActivatedCondition by using the new constructor with inverse parameter.
* <span class="label label-success">Added</span> The method @org.eclipse.sirius.tests.swtbot.support.api.editor.SWTBotSiriusDiagramEditor.dragWithKey(int, int, int, int, int)@, and so @SWTBotSiriusGefViewer.dragWithKey@ and @SWTBotSiriusFigureCanvas.mouseDragWithKey@), has an additional parameter, compared to @drag(int, int, int, int)@ method, to precise the key code to press during the drag'n'drop. It is possible to call this method with SWT.None to retrieve the standard behavior of @drag@ method. This method also has a correct behavior for the move of bendpoints of edges.
+* <span class="label label-success">Added</span> @org.eclipse.sirius.tests.swtbot.support.api.condition.TopCondition@: New condition to wait that top of the edit part is on the expected location.
+
h2(#sirius3.0.0). Changes in Sirius 3.0.0
diff --git a/plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.html b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.html
index 18f578947d..9a58eae756 100644
--- a/plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.html
+++ b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.html
@@ -29,6 +29,9 @@
<a href="#Resizingelements">Resizing elements</a>
</li>
<li>
+ <a href="#Movingelements">Moving elements</a>
+ </li>
+ <li>
<a href="#Manageedges">Manage edges</a>
</li>
<li>
@@ -185,6 +188,39 @@
<p>Opening existing diagrams and renaming or deleting them works exactly as for any other kind of representation. Refer to the general documentation about the
<em>Modeling Project</em> UI for details.
</p>
+ <h4 id="RulersGrid">Rulers &amp; Grid</h4>
+ <p>Several behaviors concerning the diagram elements editing is conditioned by properties of the diagram accessible through the
+ <em>Rulers &amp; Grid</em> tab of the
+ <em>Properties</em> view of the diagram.
+ <br/>
+ <img border="0" src="images/properties_view_rulers_and_grid_tab.png"/>
+ </p>
+ <h5 id="ShowRuler">Show Ruler</h5>
+ <p>
+ <em>Display/Show Ruler</em>: Display an horizonal and vertical ruler according to
+ <em>Measurement/Ruler Units</em> property.
+ </p>
+ <h5 id="ShowGrid">Show Grid </h5>
+ <p>
+ <em>Display/Show Grid</em>: Display a grid in background of the diagram according to
+ <em>Measurement/Grid Spacing</em> and
+ <em>Grid Line</em> properties. This grid can be in front of all figures if the property
+ <em>Grid In Front</em> is enabled.
+ </p>
+ <h5 id="Snaptogrid">Snap to grid</h5>
+ <p>Capability to allow edit parts to snap to the grid when editing (during creation, moving or resizing). It is also possible to have connection bendpoints snap to it. Grid snapping and visibility are two distinct properties, and it is possible to enable one without the other.</p>
+ <h5 id="snap_to_shapes">Snap to shapes</h5>
+ <p>The
+ <em>Snap to shapes</em> feature allows you to quickly align parts being dragged or resized to other parts in the diagram or that share the same parent (e.g: edit parts inside a compartment can only snap to each other). The snap is effective on top, bottom, right, left and center of the figure. Feedback is shown in the form of a gray line when a part is being attached to another part. This feature is not enabled on border nodes.
+ <br/>
+ <img border="0" src="images/snap_to_shape.png"/>
+ </p>
+ <p>By pressing the <kdb>F4</kdb> shortcut key, it is possible to temporarily enable the snap to all shapes currently visible on the diagram. Some screenshots of this feature are shown below.
+ <br/>
+ <img border="0" src="images/snap_to_all_shapes.png"/>
+ <br/>
+ <img border="0" src="images/snap_to_all_shapes_2.png"/>
+ </p>
<h3 id="Resizingelements">Resizing elements</h3>
<p>If the specifier has authorized it, it is possible to resize a shape by dragging them until they are the size that you want.</p>
<p>There are specific shortcuts to change the resize behavior:</p>
@@ -193,8 +229,25 @@
<li>SHIFT: Resize that keeps the ratio</li>
<li>ALT (or CTRL for Mac users): Resize without snap (temporarily disables the snap during the resize if it is activated). </li>
<li>F3: Resize with children location relative to the parent. If the shape is resized to the left, upwards, or both, the children (contained nodes for container and border nodes for all shapes) are moved with the same offset that the resize.</li>
+ <li>F4: Resize with snap to all shapes (if the
+ <a href="#snap_to_shapes">Snap to shapes</a> is already activated for the current diagram)
+ </li>
+ </ul>
+ <h3 id="Movingelements">Moving elements</h3>
+ <p>There are specific shortcuts to change the move behavior:</p>
+ <ul>
+ <li>SHIFT: Constrained move (only vertical or horizontal move is authorized at once).</li>
+ <li>ALT (or CTRL for Mac users): Ignore snap while dragging (temporarily disables the snap during the move if it is activated).</li>
+ <li>F4: Move with snap to all shapes (if the
+ <a href="#snap_to_shapes">Snap to shapes</a> is already activated for the current diagram)
+ </li>
</ul>
<h3 id="Manageedges">Manage edges</h3>
+ <h4 id="Movebendpoints">Move bend-points</h4>
+ <p>It is possible to snap the bend-points to all shapes by pressing kdb&gt;F4</kdb> shortcut key during the move. This feature is only available if the
+ <a href="#snap_to_shapes">Snap to shapes</a> is already activated for the current diagram. As for
+ <em>Snap to grid</em>, and unlike to snap for node, there is no guide drawn during the move.
+ </p>
<h4 id="RemoveBendpoints">Remove Bend-points</h4>
<p>You can define some bend-points (or inflection points) on an edge. It is possible to remove all these bend-points to retrieve the original Straight edge. This action is available within the edge context menu or by using the shortcut &#171;Ctrl&#187; + &#171;Shift&#187; + &#171;-&#187;. This action is only available on edges with a &#171;Straight&#187; routing style.</p>
<p>The edge state just after its creation:
diff --git a/plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.textile b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.textile
index 72a8719e0a..17648bd4c9 100644
--- a/plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.textile
+++ b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/Diagrams.textile
@@ -42,6 +42,32 @@ h3. Managing Diagrams
Opening existing diagrams and renaming or deleting them works exactly as for any other kind of representation. Refer to the general documentation about the _Modeling Project_ UI for details.
+h4. Rulers & Grid
+
+Several behaviors concerning the diagram elements editing is conditioned by properties of the diagram accessible through the _Rulers & Grid_ tab of the _Properties_ view of the diagram.
+!images/properties_view_rulers_and_grid_tab.png!
+
+h5. Show Ruler
+
+_Display/Show Ruler_: Display an horizonal and vertical ruler according to _Measurement/Ruler Units_ property.
+
+h5. Show Grid
+
+_Display/Show Grid_: Display a grid in background of the diagram according to _Measurement/Grid Spacing_ and _Grid Line_ properties. This grid can be in front of all figures if the property _Grid In Front_ is enabled.
+
+h5. Snap to grid
+
+Capability to allow edit parts to snap to the grid when editing (during creation, moving or resizing). It is also possible to have connection bendpoints snap to it. Grid snapping and visibility are two distinct properties, and it is possible to enable one without the other.
+
+h5(#snap_to_shapes). Snap to shapes
+
+The _Snap to shapes_ feature allows you to quickly align parts being dragged or resized to other parts in the diagram or that share the same parent (e.g: edit parts inside a compartment can only snap to each other). The snap is effective on top, bottom, right, left and center of the figure. Feedback is shown in the form of a gray line when a part is being attached to another part. This feature is not enabled on border nodes.
+!images/snap_to_shape.png!
+
+By pressing the <kdb>F4</kdb> shortcut key, it is possible to temporarily enable the snap to all shapes currently visible on the diagram. Some screenshots of this feature are shown below.
+!images/snap_to_all_shapes.png!
+!images/snap_to_all_shapes_2.png!
+
h3. Resizing elements
If the specifier has authorized it, it is possible to resize a shape by dragging them until they are the size that you want.
@@ -51,9 +77,22 @@ There are specific shortcuts to change the resize behavior:
* SHIFT: Resize that keeps the ratio
* ALT (or CTRL for Mac users): Resize without snap (temporarily disables the snap during the resize if it is activated).
* F3: Resize with children location relative to the parent. If the shape is resized to the left, upwards, or both, the children (contained nodes for container and border nodes for all shapes) are moved with the same offset that the resize.
+* F4: Resize with snap to all shapes (if the "Snap to shapes":#snap_to_shapes is already activated for the current diagram)
+
+
+h3. Moving elements
+
+There are specific shortcuts to change the move behavior:
+* SHIFT: Constrained move (only vertical or horizontal move is authorized at once).
+* ALT (or CTRL for Mac users): Ignore snap while dragging (temporarily disables the snap during the move if it is activated).
+* F4: Move with snap to all shapes (if the "Snap to shapes":#snap_to_shapes is already activated for the current diagram)
h3. Manage edges
+h4. Move bend-points
+
+It is possible to snap the bend-points to all shapes by pressing kdb>F4</kdb> shortcut key during the move. This feature is only available if the "Snap to shapes":#snap_to_shapes is already activated for the current diagram. As for _Snap to grid_, and unlike to snap for node, there is no guide drawn during the move.
+
h4. Remove Bend-points
You can define some bend-points (or inflection points) on an edge. It is possible to remove all these bend-points to retrieve the original Straight edge. This action is available within the edge context menu or by using the shortcut "Ctrl" + "Shift" + "-". This action is only available on edges with a "Straight" routing style.
diff --git a/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/properties_view_rulers_and_grid_tab.png b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/properties_view_rulers_and_grid_tab.png
new file mode 100644
index 0000000000..ed89cf93d6
--- /dev/null
+++ b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/properties_view_rulers_and_grid_tab.png
Binary files differ
diff --git a/plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/images/snapToAllShapes.png b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_all_shapes.png
index 9e4c69dc79..9e4c69dc79 100644
--- a/plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/images/snapToAllShapes.png
+++ b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_all_shapes.png
Binary files differ
diff --git a/plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/images/snapToAllShapes_2.png b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_all_shapes_2.png
index 2bb1bbbac7..2bb1bbbac7 100644
--- a/plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/images/snapToAllShapes_2.png
+++ b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_all_shapes_2.png
Binary files differ
diff --git a/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_shape.png b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_shape.png
new file mode 100644
index 0000000000..dab9d6d0f6
--- /dev/null
+++ b/plugins/org.eclipse.sirius.doc/doc/user/diagrams/images/snap_to_shape.png
Binary files differ
diff --git a/plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/463485.html b/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/463485.html
index da43bec486..da43bec486 100644
--- a/plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/463485.html
+++ b/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/463485.html
diff --git a/plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/463485.textile b/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/463485.textile
index f47e3363ee..f47e3363ee 100644
--- a/plugins/org.eclipse.sirius.doc/specs/proposal/463485_snapToAllShapes/463485.textile
+++ b/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/463485.textile
diff --git a/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/images/snapToAllShapes.png b/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/images/snapToAllShapes.png
new file mode 100644
index 0000000000..9e4c69dc79
--- /dev/null
+++ b/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/images/snapToAllShapes.png
Binary files differ
diff --git a/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/images/snapToAllShapes_2.png b/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/images/snapToAllShapes_2.png
new file mode 100644
index 0000000000..2bb1bbbac7
--- /dev/null
+++ b/plugins/org.eclipse.sirius.doc/specs/accepted/463485_snapToAllShapes/images/snapToAllShapes_2.png
Binary files differ
diff --git a/plugins/org.eclipse.sirius.ext.emf.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.ext.emf.ui/META-INF/MANIFEST.MF
index b28e15bbfe..89f9ff4b89 100644
--- a/plugins/org.eclipse.sirius.ext.emf.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.sirius.ext.emf.ui/META-INF/MANIFEST.MF
@@ -7,5 +7,5 @@ Bundle-Vendor: %providerName
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-Localization: plugin
Require-Bundle: org.eclipse.emf.edit.ui;bundle-version="2.8.0"
-Export-Package: org.eclipse.sirius.ext.emf.ui,
- org.eclipse.sirius.ext.emf.ui.properties
+Export-Package: org.eclipse.sirius.ext.emf.ui;version="3.0.0",
+ org.eclipse.sirius.ext.emf.ui.properties;version="3.0.0"
diff --git a/plugins/org.eclipse.sirius.ext.gef/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.ext.gef/META-INF/MANIFEST.MF
index 790cc0cecf..cc99e373d6 100644
--- a/plugins/org.eclipse.sirius.ext.gef/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.sirius.ext.gef/META-INF/MANIFEST.MF
@@ -8,4 +8,7 @@ Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.gef;bundle-version="3.9.0",
org.eclipse.equinox.common;bundle-version="3.6.100"
-Export-Package: org.eclipse.sirius.ext.gef.editpolicies;version="2.0.4"
+Export-Package: org.eclipse.sirius.ext.gef.editpolicies;version="2.0.4",
+ org.eclipse.sirius.ext.gef.query;version="3.1.0"
+Import-Package: com.google.common.base;version="[11.0.2,16.0)",
+ com.google.common.collect;version="[11.0.2,16.0)"
diff --git a/plugins/org.eclipse.sirius.ext.gef/src/org/eclipse/sirius/ext/gef/query/EditPartQuery.java b/plugins/org.eclipse.sirius.ext.gef/src/org/eclipse/sirius/ext/gef/query/EditPartQuery.java
new file mode 100644
index 0000000000..f6540e8588
--- /dev/null
+++ b/plugins/org.eclipse.sirius.ext.gef/src/org/eclipse/sirius/ext/gef/query/EditPartQuery.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.ext.gef.query;
+
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.gef.EditPart;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+
+/**
+ * Queries on GEF edit parts.
+ *
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public class EditPartQuery {
+ private final EditPart part;
+
+ /**
+ * Constructor.
+ *
+ * @param part
+ * the graphical edit part to query.
+ */
+ public EditPartQuery(EditPart part) {
+ this.part = Preconditions.checkNotNull(part);
+ }
+
+ /**
+ * Returns a list including all of the children of the edit part passed in.
+ *
+ * @param includeSelf
+ * true if the edit part must be include in result, false
+ * otherwise
+ * @return list of children
+ */
+ public Set<EditPart> getAllChildren(boolean includeSelf) {
+ return getAllChildren(includeSelf, null);
+ }
+
+ /**
+ * Returns a list including all of the children of the edit part passed in.
+ *
+ * @param includeSelf
+ * true if the edit part must be include in result, false
+ * otherwise
+ * @param includedKind
+ * List of expected editPart classes
+ * @return list of children
+ */
+ public Set<EditPart> getAllChildren(boolean includeSelf, List<Class<?>> includedKind) {
+ Set<EditPart> result = Sets.newHashSet();
+ if (includeSelf) {
+ if (includedKind == null || isAssignable(part.getClass(), includedKind)) {
+ result.add(part);
+ }
+ }
+ result.addAll(getAllChildren(part, includedKind));
+ return result;
+ }
+
+ /**
+ * Returns a list including all of the children of the edit part passed in.
+ */
+ private Set<EditPart> getAllChildren(EditPart editPart, List<Class<?>> includedKind) {
+ Set<EditPart> result = Sets.newHashSet();
+ for (EditPart child : Iterables.filter(editPart.getChildren(), EditPart.class)) {
+ if (includedKind == null || isAssignable(child.getClass(), includedKind)) {
+ result.add(child);
+ }
+ result.addAll(getAllChildren(child, includedKind));
+ }
+ return result;
+ }
+
+ private boolean isAssignable(Class<?> aClass, List<Class<?>> assignementTypes) {
+ for (Class<?> class1 : assignementTypes) {
+ if (class1.isAssignableFrom(aClass)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/editparts/GraphicalHelper.java b/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/editparts/GraphicalHelper.java
index 93c2c5280b..92c4dc5256 100644
--- a/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/editparts/GraphicalHelper.java
+++ b/plugins/org.eclipse.sirius.ext.gmf.runtime/src/org/eclipse/sirius/ext/gmf/runtime/editparts/GraphicalHelper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2014 THALES GLOBAL SERVICES.
+ * Copyright (c) 2011, 2015 THALES GLOBAL SERVICES.
* 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 org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
@@ -117,7 +118,8 @@ public final class GraphicalHelper {
}
/**
- * Applies inverse zoom on a point and returns this point for convenience.<BR>
+ * Applies inverse zoom on a point and returns this point for convenience.
+ * <BR>
* For example:
* <UL>
* <LI>For a zoom of 200%, the result of this method for the point (100,
@@ -311,11 +313,11 @@ public final class GraphicalHelper {
* @return The corresponding point to this anchor
*/
public static Point getAnchorPoint(IGraphicalEditPart parent, IdentityAnchor anchor) {
- Rectangle bounds;
+ PrecisionRectangle bounds;
if (parent.getFigure() instanceof HandleBounds) {
- bounds = ((HandleBounds) parent.getFigure()).getHandleBounds();
+ bounds = new PrecisionRectangle(((HandleBounds) parent.getFigure()).getHandleBounds());
} else {
- bounds = parent.getFigure().getBounds();
+ bounds = new PrecisionRectangle(parent.getFigure().getBounds());
}
parent.getFigure().translateToAbsolute(bounds);
@@ -326,7 +328,7 @@ public final class GraphicalHelper {
// If anchor is null, the default value is (0.5, 0.5)
rel = new PrecisionPoint(0.5, 0.5);
}
- Point location = new PrecisionPoint(bounds.getLocation().x + bounds.width * rel.preciseX(), bounds.getLocation().y + bounds.height * rel.preciseY());
+ Point location = new PrecisionPoint(bounds.preciseX() + bounds.preciseWidth() * rel.preciseX(), bounds.preciseY() + bounds.preciseHeight() * rel.preciseY());
return location;
}
@@ -438,11 +440,11 @@ public final class GraphicalHelper {
* @return The absolute bounds.
*/
public static Rectangle getAbsoluteBounds(IGraphicalEditPart part) {
- Rectangle bounds;
+ PrecisionRectangle bounds;
if (part.getFigure() instanceof HandleBounds) {
- bounds = ((HandleBounds) part.getFigure()).getHandleBounds().getCopy();
+ bounds = new PrecisionRectangle(((HandleBounds) part.getFigure()).getHandleBounds());
} else {
- bounds = part.getFigure().getBounds().getCopy();
+ bounds = new PrecisionRectangle(part.getFigure().getBounds());
}
part.getFigure().translateToAbsolute(bounds);
return bounds;
@@ -457,11 +459,11 @@ public final class GraphicalHelper {
* @return The absolute bounds.
*/
public static Rectangle getAbsoluteBoundsIn100Percent(GraphicalEditPart part) {
- Rectangle bounds;
+ PrecisionRectangle bounds;
if (part.getFigure() instanceof HandleBounds) {
- bounds = ((HandleBounds) part.getFigure()).getHandleBounds().getCopy();
+ bounds = new PrecisionRectangle(((HandleBounds) part.getFigure()).getHandleBounds());
} else {
- bounds = part.getFigure().getBounds().getCopy();
+ bounds = new PrecisionRectangle(part.getFigure().getBounds());
}
part.getFigure().translateToAbsolute(bounds);
screen2logical(bounds, part);
diff --git a/plugins/org.eclipse.sirius.tests.swtbot.support/src/org/eclipse/sirius/tests/swtbot/support/api/condition/TopCondition.java b/plugins/org.eclipse.sirius.tests.swtbot.support/src/org/eclipse/sirius/tests/swtbot/support/api/condition/TopCondition.java
new file mode 100644
index 0000000000..983d83c4a0
--- /dev/null
+++ b/plugins/org.eclipse.sirius.tests.swtbot.support/src/org/eclipse/sirius/tests/swtbot/support/api/condition/TopCondition.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.tests.swtbot.support.api.condition;
+
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.sirius.ext.gmf.runtime.editparts.GraphicalHelper;
+import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
+
+/**
+ * A specific condition to wait that the top of the edit part is on the expected
+ * axis.
+ *
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public final class TopCondition extends DefaultCondition {
+ /** Element to move. */
+ private final GraphicalEditPart part;
+
+ /** The expected y location */
+ private int expectedYLocation;
+
+ /**
+ * A delta of one pixel can be tolerated, in case of zoom different from
+ * 100% for example.
+ */
+ private boolean addOnePixelDelta;
+
+ /** Failure message when a test fails */
+ private String failureMessage = "";
+
+ private int actual;
+
+ /**
+ * Default constructor.
+ *
+ * @param part
+ * Part to check
+ * @param expectedYLocation
+ * The expected y location
+ * @param failureMessage
+ * Failure message when a test fails
+ * @param addOnePixelDelta
+ * A delta of one pixel can be tolerated, in case of zoom
+ * different from 100% for example
+ */
+ public TopCondition(GraphicalEditPart part, int expectedYLocation, String failureMessage, boolean addOnePixelDelta) {
+ this.expectedYLocation = expectedYLocation;
+ this.part = part;
+ this.failureMessage = failureMessage;
+ this.addOnePixelDelta = addOnePixelDelta;
+ }
+
+ @Override
+ public boolean test() throws Exception {
+ Rectangle newBounds = GraphicalHelper.getAbsoluteBoundsIn100Percent(part);
+ actual = newBounds.getTop().y;
+ if (addOnePixelDelta) {
+ return (expectedYLocation - 1) <= actual && actual <= (expectedYLocation + 1);
+ } else {
+ return expectedYLocation == actual;
+ }
+ }
+
+ @Override
+ public String getFailureMessage() {
+ return failureMessage + ", expected:<" + expectedYLocation + "> but was:<" + actual + ">";
+ }
+}
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/My.ecore b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/My.ecore
new file mode 100644
index 0000000000..2246cb4eb9
--- /dev/null
+++ b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/My.ecore
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="root">
+ <eSubpackages name="p1">
+ <eClassifiers xsi:type="ecore:EClass" name="C1">
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="att1"/>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="toC2" eType="#//p2/C2"/>
+ </eClassifiers>
+ <eSubpackages name="subP1">
+ <eClassifiers xsi:type="ecore:EClass" name="C1Sub"/>
+ </eSubpackages>
+ </eSubpackages>
+ <eSubpackages name="p2">
+ <eClassifiers xsi:type="ecore:EClass" name="C2">
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="att2"/>
+ </eClassifiers>
+ </eSubpackages>
+</ecore:EPackage>
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/representations.aird b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/representations.aird
new file mode 100644
index 0000000000..50565baacd
--- /dev/null
+++ b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/representations.aird
@@ -0,0 +1,443 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<viewpoint:DAnalysis xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:description="http://www.eclipse.org/sirius/description/1.1.0" xmlns:description_1="http://www.eclipse.org/sirius/diagram/description/1.1.0" xmlns:diagram="http://www.eclipse.org/sirius/diagram/1.1.0" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/sirius/diagram/description/style/1.1.0" xmlns:viewpoint="http://www.eclipse.org/sirius/1.1.0" xsi:schemaLocation="http://www.eclipse.org/sirius/description/1.1.0 http://www.eclipse.org/sirius/1.1.0#//description http://www.eclipse.org/sirius/diagram/description/1.1.0 http://www.eclipse.org/sirius/diagram/1.1.0#//description http://www.eclipse.org/sirius/diagram/description/style/1.1.0 http://www.eclipse.org/sirius/diagram/1.1.0#//description/style" xmi:id="_mXL0MBWbEeW7GcqVYwuCiQ" selectedViews="_LWb4wBWdEeW7GcqVYwuCiQ" version="10.0.0.201505222000">
+ <semanticResources>My.ecore</semanticResources>
+ <ownedViews xmi:type="viewpoint:DRepresentationContainer" xmi:id="_LWb4wBWdEeW7GcqVYwuCiQ">
+ <ownedRepresentations xmi:type="diagram:DSemanticDiagram" xmi:id="_M0HXsBWdEeW7GcqVYwuCiQ" name="snapToAllDiagram">
+ <ownedAnnotationEntries xmi:type="description:AnnotationEntry" xmi:id="_M0HXsRWdEeW7GcqVYwuCiQ" source="DANNOTATION_CUSTOMIZATION_KEY">
+ <data xmi:type="diagram:ComputedStyleDescriptionRegistry" xmi:id="_M0HXshWdEeW7GcqVYwuCiQ"/>
+ </ownedAnnotationEntries>
+ <ownedAnnotationEntries xmi:type="description:AnnotationEntry" xmi:id="_M0a5sBWdEeW7GcqVYwuCiQ" source="GMF_DIAGRAMS">
+ <data xmi:type="notation:Diagram" xmi:id="_M0bgwBWdEeW7GcqVYwuCiQ" type="Sirius" element="_M0HXsBWdEeW7GcqVYwuCiQ" measurementUnit="Pixel">
+ <children xmi:type="notation:Node" xmi:id="_OrCLQBaIEeWQ3O79R6E3Ug" type="2001" element="_OpprMBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrI48BaIEeWQ3O79R6E3Ug" type="5002">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OrI48RaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrRb0BaIEeWQ3O79R6E3Ug" type="3001" element="_OpyOEBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrSC4BaIEeWQ3O79R6E3Ug" type="5001">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OrSC4RaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OralwBaIEeWQ3O79R6E3Ug" type="3003" element="_OpyOERaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OralwRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OralwhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrbM0BaIEeWQ3O79R6E3Ug" type="3001" element="_Op0qUBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_Orbz4BaIEeWQ3O79R6E3Ug" type="5001">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Orbz4RaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Orca8BaIEeWQ3O79R6E3Ug" type="3003" element="_Op0qURaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Orca8RaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Orca8haIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrbM0RaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrbM0haIEeWQ3O79R6E3Ug" x="-83" width="91" height="51"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrRb0RaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrRb0haIEeWQ3O79R6E3Ug" x="-92" width="100" height="101"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrZ-sBaIEeWQ3O79R6E3Ug" type="3003" element="_OpujsBaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrZ-sRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrZ-shaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrCLQRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrCLQhaIEeWQ3O79R6E3Ug" x="198" y="88" width="126" height="250"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrKuIBaIEeWQ3O79R6E3Ug" type="2001" element="_OpwY4BaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrLVMBaIEeWQ3O79R6E3Ug" type="5002">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OrLVMRaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrdpEBaIEeWQ3O79R6E3Ug" type="3001" element="_Op2fgBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OreQIBaIEeWQ3O79R6E3Ug" type="5001">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OreQIRaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrgFUBaIEeWQ3O79R6E3Ug" type="3003" element="_Op2fgRaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrgFURaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrgFUhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrgsYBaIEeWQ3O79R6E3Ug" type="3001" element="_Op6J4BaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrhTcBaIEeWQ3O79R6E3Ug" type="5001">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OrhTcRaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Orh6gBaIEeWQ3O79R6E3Ug" type="3003" element="_Op6w8BaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Orh6gRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Orh6ghaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrgsYRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrgsYhaIEeWQ3O79R6E3Ug" x="-102" y="10" width="110" height="38"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrdpERaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrdpEhaIEeWQ3O79R6E3Ug" x="-92" width="100" height="60"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Ore3MBaIEeWQ3O79R6E3Ug" type="3003" element="_Opw_8BaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Ore3MRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Ore3MhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrKuIRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrKuIhaIEeWQ3O79R6E3Ug" x="275" y="-100" width="250" height="118"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrNxcBaIEeWQ3O79R6E3Ug" type="2002" element="_Op7_EBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrO_kBaIEeWQ3O79R6E3Ug" type="5006"/>
+ <children xmi:type="notation:Node" xmi:id="_OrPmoBaIEeWQ3O79R6E3Ug" type="7001">
+ <children xmi:type="notation:Node" xmi:id="_OrmL8BaIEeWQ3O79R6E3Ug" type="3008" element="_OqCswBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrmzABaIEeWQ3O79R6E3Ug" type="5005"/>
+ <children xmi:type="notation:Node" xmi:id="_OrnaEBaIEeWQ3O79R6E3Ug" type="7002">
+ <children xmi:type="notation:Node" xmi:id="_OrsSkBaIEeWQ3O79R6E3Ug" type="3007" element="_OqFJABaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_Ors5oBaIEeWQ3O79R6E3Ug" type="5003">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Ors5oRaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrtgsBaIEeWQ3O79R6E3Ug" type="3003" element="_OqFwEBaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrtgsRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrtgshaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrsSkRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrsSkhaIEeWQ3O79R6E3Ug" x="31" y="33" width="100" height="36"/>
+ </children>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_OrnaERaIEeWQ3O79R6E3Ug"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_OrnaEhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrqdYBaIEeWQ3O79R6E3Ug" type="3012" element="_OqDT0BaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrrEcBaIEeWQ3O79R6E3Ug" type="5010">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OrrEcRaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OruHwBaIEeWQ3O79R6E3Ug" type="3003" element="_OqD64BaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OruHwRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OruHwhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrqdYRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrqdYhaIEeWQ3O79R6E3Ug" x="-92" y="11" width="100" height="31"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrmL8RaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrmL8haIEeWQ3O79R6E3Ug" x="169" y="-55" width="168" height="52"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OroBIBaIEeWQ3O79R6E3Ug" type="3007" element="_OqG-MBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrooMBaIEeWQ3O79R6E3Ug" type="5003">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OrooMRaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Oruu0BaIEeWQ3O79R6E3Ug" type="3001" element="_OqKBgBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrvV4BaIEeWQ3O79R6E3Ug" type="5001">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OrvV4RaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrwkABaIEeWQ3O79R6E3Ug" type="3003" element="_OqKBgRaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrwkARaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrwkAhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Oruu0RaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Oruu0haIEeWQ3O79R6E3Ug" x="-90" width="98" height="50"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Orv88BaIEeWQ3O79R6E3Ug" type="3003" element="_OqHlQBaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Orv88RaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Orv88haIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OroBIRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OroBIhaIEeWQ3O79R6E3Ug" x="128" y="33" width="100" height="100"/>
+ </children>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_OrPmoRaIEeWQ3O79R6E3Ug"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_OrPmohaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrjIoBaIEeWQ3O79R6E3Ug" type="3012" element="_Op-bUBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrjvsBaIEeWQ3O79R6E3Ug" type="5010">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OrjvsRaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OryZMBaIEeWQ3O79R6E3Ug" type="3003" element="_Op_CYBaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OryZMRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OryZMhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrzAQBaIEeWQ3O79R6E3Ug" type="3012" element="_OqA3kBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrznUBaIEeWQ3O79R6E3Ug" type="5010">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_OrznURaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Or0OYBaIEeWQ3O79R6E3Ug" type="3003" element="_OqA3kRaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Or0OYRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Or0OYhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrzAQRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrzAQhaIEeWQ3O79R6E3Ug" x="-49" y="50" width="84" height="50"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrjIoRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrjIohaIEeWQ3O79R6E3Ug" x="-92" y="225" width="100" height="100"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrNxcRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrNxchaIEeWQ3O79R6E3Ug" x="351" y="182" width="403" height="378"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_OrQNsBaIEeWQ3O79R6E3Ug" type="2002" element="_Op9NMBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_OrQ0wBaIEeWQ3O79R6E3Ug" type="5006"/>
+ <children xmi:type="notation:Node" xmi:id="_OrQ0wRaIEeWQ3O79R6E3Ug" type="7001">
+ <children xmi:type="notation:Node" xmi:id="_Or4f0BaIEeWQ3O79R6E3Ug" type="3007" element="_OqO6ABaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_Or5G4BaIEeWQ3O79R6E3Ug" type="5003">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Or5G4RaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Or5t8BaIEeWQ3O79R6E3Ug" type="3001" element="_OqQvMBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_Or6VABaIEeWQ3O79R6E3Ug" type="5001">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Or6VARaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Or7jIBaIEeWQ3O79R6E3Ug" type="3003" element="_OqRWQBaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Or7jIRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Or7jIhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Or5t8RaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Or5t8haIEeWQ3O79R6E3Ug" x="243" y="25" width="184" height="50"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Or68EBaIEeWQ3O79R6E3Ug" type="3003" element="_OqPhEBaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Or68ERaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Or68EhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Or4f0RaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Or4f0haIEeWQ3O79R6E3Ug" x="17" y="256" width="251" height="101"/>
+ </children>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_OrQ0whaIEeWQ3O79R6E3Ug"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_OrQ0wxaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Or1cgBaIEeWQ3O79R6E3Ug" type="3012" element="_OqLPoBaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_Or3RsBaIEeWQ3O79R6E3Ug" type="5010">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Or3RsRaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Or8KMBaIEeWQ3O79R6E3Ug" type="3003" element="_OqL2sBaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Or8KMRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Or8KMhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Or8xQBaIEeWQ3O79R6E3Ug" type="3012" element="_OqNE0BaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_Or9YUBaIEeWQ3O79R6E3Ug" type="5010">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Or9YURaIEeWQ3O79R6E3Ug" y="5"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_Or9_YBaIEeWQ3O79R6E3Ug" type="3003" element="_OqNr4BaIEeWQ3O79R6E3Ug">
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Or9_YRaIEeWQ3O79R6E3Ug" fontName="Ubuntu"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Or9_YhaIEeWQ3O79R6E3Ug"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Or8xQRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Or8xQhaIEeWQ3O79R6E3Ug" x="-175" y="28" width="176" height="26"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_Or1cgRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Or1cghaIEeWQ3O79R6E3Ug" x="448" y="150" width="100" height="104"/>
+ </children>
+ <styles xmi:type="notation:ShapeStyle" xmi:id="_OrQNsRaIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrQNshaIEeWQ3O79R6E3Ug" x="1024" y="112" width="458" height="578"/>
+ </children>
+ <styles xmi:type="notation:DiagramStyle" xmi:id="_M0bgwRWdEeW7GcqVYwuCiQ"/>
+ <edges xmi:type="notation:Edge" xmi:id="_UTFY4BaIEeWQ3O79R6E3Ug" type="4001" element="_US1hQBaIEeWQ3O79R6E3Ug" source="_OroBIBaIEeWQ3O79R6E3Ug" target="_Or4f0BaIEeWQ3O79R6E3Ug">
+ <children xmi:type="notation:Node" xmi:id="_UTF_8BaIEeWQ3O79R6E3Ug" type="6001">
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_UTF_8RaIEeWQ3O79R6E3Ug" y="-10"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_UTGnABaIEeWQ3O79R6E3Ug" type="6002">
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_UTGnARaIEeWQ3O79R6E3Ug" y="10"/>
+ </children>
+ <children xmi:type="notation:Node" xmi:id="_UTHOEBaIEeWQ3O79R6E3Ug" type="6003">
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_UTHOERaIEeWQ3O79R6E3Ug" y="10"/>
+ </children>
+ <styles xmi:type="notation:ConnectorStyle" xmi:id="_UTFY4RaIEeWQ3O79R6E3Ug"/>
+ <styles xmi:type="notation:FontStyle" xmi:id="_UTFY4haIEeWQ3O79R6E3Ug" fontName="Ubuntu" fontHeight="8"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_UTFY4xaIEeWQ3O79R6E3Ug" points="[8, -13, -467, -91]$[197, -300, -278, -378]$[352, 141, -123, 63]$[470, 80, -5, 2]"/>
+ <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_UTNUsBaIEeWQ3O79R6E3Ug" id="(0.92,0.71)"/>
+ <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_UTNUsRaIEeWQ3O79R6E3Ug" id="(0.0199203187250996,0.504950495049505)"/>
+ </edges>
+ </data>
+ </ownedAnnotationEntries>
+ <ownedDiagramElements xmi:type="diagram:DNode" xmi:id="_OpprMBaIEeWQ3O79R6E3Ug" name="Node_p1" width="25" height="25" resizeKind="NSEW">
+ <target xmi:type="ecore:EPackage" href="My.ecore#//p1"/>
+ <semanticElements xmi:type="ecore:EPackage" href="My.ecore#//p1"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_OpyOEBaIEeWQ3O79R6E3Ug" name="BNN_C1" width="10" height="10" resizeKind="NSEW">
+ <target xmi:type="ecore:EClass" href="My.ecore#//p1/C1"/>
+ <semanticElements xmi:type="ecore:EClass" href="My.ecore#//p1/C1"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_Op0qUBaIEeWQ3O79R6E3Ug" name="BNBNN_att1" width="5" height="5" resizeKind="NSEW">
+ <target xmi:type="ecore:EAttribute" href="My.ecore#//p1/C1/att1"/>
+ <semanticElements xmi:type="ecore:EAttribute" href="My.ecore#//p1/C1/att1"/>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_Op0qURaIEeWQ3O79R6E3Ug" borderColor="204,242,166" labelPosition="node" width="5" height="5" color="255,245,181">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@borderedNodeMappings[name='EClassOnNode']/@borderedNodeMappings[name='EAttributeOnEClassOnNode']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@borderedNodeMappings[name='EClassOnNode']/@borderedNodeMappings[name='EAttributeOnEClassOnNode']"/>
+ </ownedBorderedNodes>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OpyOERaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="10" height="10" color="246,139,139">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@borderedNodeMappings[name='EClassOnNode']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@borderedNodeMappings[name='EClassOnNode']"/>
+ </ownedBorderedNodes>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OpujsBaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="25" height="25" color="217,196,215">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']"/>
+ </ownedDiagramElements>
+ <ownedDiagramElements xmi:type="diagram:DNode" xmi:id="_OpwY4BaIEeWQ3O79R6E3Ug" name="Node_p2" width="25" height="25" resizeKind="NSEW">
+ <target xmi:type="ecore:EPackage" href="My.ecore#//p2"/>
+ <semanticElements xmi:type="ecore:EPackage" href="My.ecore#//p2"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_Op2fgBaIEeWQ3O79R6E3Ug" name="BNN_C2" width="10" height="10" resizeKind="NSEW">
+ <target xmi:type="ecore:EClass" href="My.ecore#//p2/C2"/>
+ <semanticElements xmi:type="ecore:EClass" href="My.ecore#//p2/C2"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_Op6J4BaIEeWQ3O79R6E3Ug" name="BNBNN_att2" width="5" height="5" resizeKind="NSEW">
+ <target xmi:type="ecore:EAttribute" href="My.ecore#//p2/C2/att2"/>
+ <semanticElements xmi:type="ecore:EAttribute" href="My.ecore#//p2/C2/att2"/>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_Op6w8BaIEeWQ3O79R6E3Ug" borderColor="204,242,166" labelPosition="node" width="5" height="5" color="255,245,181">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@borderedNodeMappings[name='EClassOnNode']/@borderedNodeMappings[name='EAttributeOnEClassOnNode']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@borderedNodeMappings[name='EClassOnNode']/@borderedNodeMappings[name='EAttributeOnEClassOnNode']"/>
+ </ownedBorderedNodes>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_Op2fgRaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="10" height="10" color="246,139,139">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@borderedNodeMappings[name='EClassOnNode']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@borderedNodeMappings[name='EClassOnNode']"/>
+ </ownedBorderedNodes>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_Opw_8BaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="25" height="25" color="217,196,215">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@nodeMappings[name='NodePackage']"/>
+ </ownedDiagramElements>
+ <ownedDiagramElements xmi:type="diagram:DNodeContainer" xmi:id="_Op7_EBaIEeWQ3O79R6E3Ug" name="Container_p1">
+ <target xmi:type="ecore:EPackage" href="My.ecore#//p1"/>
+ <semanticElements xmi:type="ecore:EPackage" href="My.ecore#//p1"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_Op-bUBaIEeWQ3O79R6E3Ug" name="BNC_C1" width="10" height="10" resizeKind="NSEW">
+ <target xmi:type="ecore:EClass" href="My.ecore#//p1/C1"/>
+ <semanticElements xmi:type="ecore:EClass" href="My.ecore#//p1/C1"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_OqA3kBaIEeWQ3O79R6E3Ug" name="BNBNC_att1" width="5" height="5" resizeKind="NSEW">
+ <target xmi:type="ecore:EAttribute" href="My.ecore#//p1/C1/att1"/>
+ <semanticElements xmi:type="ecore:EAttribute" href="My.ecore#//p1/C1/att1"/>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OqA3kRaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="5" height="5" color="246,139,139">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']/@borderedNodeMappings[name='EAttribute']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']/@borderedNodeMappings[name='EAttribute']"/>
+ </ownedBorderedNodes>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_Op_CYBaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="10" height="10" color="217,196,215">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']"/>
+ </ownedBorderedNodes>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:FlatContainerStyle" xmi:id="_Op8mIBaIEeWQ3O79R6E3Ug" borderColor="39,76,114" foregroundColor="194,239,255">
+ <description xmi:type="style:FlatContainerStyleDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:ContainerMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']"/>
+ <ownedDiagramElements xmi:type="diagram:DNodeContainer" xmi:id="_OqCswBaIEeWQ3O79R6E3Ug" name="Container_subP1">
+ <target xmi:type="ecore:EPackage" href="My.ecore#//p1/subP1"/>
+ <semanticElements xmi:type="ecore:EPackage" href="My.ecore#//p1/subP1"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_OqDT0BaIEeWQ3O79R6E3Ug" name="BNC_C1Sub" width="10" height="10" resizeKind="NSEW">
+ <target xmi:type="ecore:EClass" href="My.ecore#//p1/subP1/C1Sub"/>
+ <semanticElements xmi:type="ecore:EClass" href="My.ecore#//p1/subP1/C1Sub"/>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OqD64BaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="10" height="10" color="217,196,215">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']"/>
+ </ownedBorderedNodes>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:FlatContainerStyle" xmi:id="_OqCswRaIEeWQ3O79R6E3Ug" borderColor="39,76,114" foregroundColor="194,239,255">
+ <description xmi:type="style:FlatContainerStyleDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:ContainerMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']"/>
+ <ownedDiagramElements xmi:type="diagram:DNode" xmi:id="_OqFJABaIEeWQ3O79R6E3Ug" name="NC_C1Sub" width="10" height="10" resizeKind="NSEW">
+ <target xmi:type="ecore:EClass" href="My.ecore#//p1/subP1/C1Sub"/>
+ <semanticElements xmi:type="ecore:EClass" href="My.ecore#//p1/subP1/C1Sub"/>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OqFwEBaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="10" height="10" color="217,196,215">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']"/>
+ </ownedDiagramElements>
+ </ownedDiagramElements>
+ <ownedDiagramElements xmi:type="diagram:DNode" xmi:id="_OqG-MBaIEeWQ3O79R6E3Ug" name="NC_C1" outgoingEdges="_US1hQBaIEeWQ3O79R6E3Ug" width="10" height="10" resizeKind="NSEW">
+ <target xmi:type="ecore:EClass" href="My.ecore#//p1/C1"/>
+ <semanticElements xmi:type="ecore:EClass" href="My.ecore#//p1/C1"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_OqKBgBaIEeWQ3O79R6E3Ug" name="BNNC_att1" width="5" height="5" resizeKind="NSEW">
+ <target xmi:type="ecore:EAttribute" href="My.ecore#//p1/C1/att1"/>
+ <semanticElements xmi:type="ecore:EAttribute" href="My.ecore#//p1/C1/att1"/>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OqKBgRaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="5" height="5" color="246,139,139">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']/@borderedNodeMappings[name='EAttribute']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']/@borderedNodeMappings[name='EAttribute']"/>
+ </ownedBorderedNodes>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OqHlQBaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="10" height="10" color="217,196,215">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']"/>
+ </ownedDiagramElements>
+ </ownedDiagramElements>
+ <ownedDiagramElements xmi:type="diagram:DNodeContainer" xmi:id="_Op9NMBaIEeWQ3O79R6E3Ug" name="Container_p2">
+ <target xmi:type="ecore:EPackage" href="My.ecore#//p2"/>
+ <semanticElements xmi:type="ecore:EPackage" href="My.ecore#//p2"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_OqLPoBaIEeWQ3O79R6E3Ug" name="BNC_C2" width="10" height="10" resizeKind="NSEW">
+ <target xmi:type="ecore:EClass" href="My.ecore#//p2/C2"/>
+ <semanticElements xmi:type="ecore:EClass" href="My.ecore#//p2/C2"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_OqNE0BaIEeWQ3O79R6E3Ug" name="BNBNC_att2" width="5" height="5" resizeKind="NSEW">
+ <target xmi:type="ecore:EAttribute" href="My.ecore#//p2/C2/att2"/>
+ <semanticElements xmi:type="ecore:EAttribute" href="My.ecore#//p2/C2/att2"/>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OqNr4BaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="5" height="5" color="246,139,139">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']/@borderedNodeMappings[name='EAttribute']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']/@borderedNodeMappings[name='EAttribute']"/>
+ </ownedBorderedNodes>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OqL2sBaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="10" height="10" color="217,196,215">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@borderedNodeMappings[name='EClassOnContainer']"/>
+ </ownedBorderedNodes>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:FlatContainerStyle" xmi:id="_Op9NMRaIEeWQ3O79R6E3Ug" borderColor="39,76,114" foregroundColor="194,239,255">
+ <description xmi:type="style:FlatContainerStyleDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:ContainerMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']"/>
+ <ownedDiagramElements xmi:type="diagram:DNode" xmi:id="_OqO6ABaIEeWQ3O79R6E3Ug" name="NC_C2" incomingEdges="_US1hQBaIEeWQ3O79R6E3Ug" width="10" height="10" resizeKind="NSEW">
+ <target xmi:type="ecore:EClass" href="My.ecore#//p2/C2"/>
+ <semanticElements xmi:type="ecore:EClass" href="My.ecore#//p2/C2"/>
+ <ownedBorderedNodes xmi:type="diagram:DNode" xmi:id="_OqQvMBaIEeWQ3O79R6E3Ug" name="BNNC_att2" width="5" height="5" resizeKind="NSEW">
+ <target xmi:type="ecore:EAttribute" href="My.ecore#//p2/C2/att2"/>
+ <semanticElements xmi:type="ecore:EAttribute" href="My.ecore#//p2/C2/att2"/>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OqRWQBaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="5" height="5" color="246,139,139">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']/@borderedNodeMappings[name='EAttribute']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']/@borderedNodeMappings[name='EAttribute']"/>
+ </ownedBorderedNodes>
+ <arrangeConstraints>KEEP_LOCATION</arrangeConstraints>
+ <arrangeConstraints>KEEP_SIZE</arrangeConstraints>
+ <arrangeConstraints>KEEP_RATIO</arrangeConstraints>
+ <ownedStyle xmi:type="diagram:Square" xmi:id="_OqPhEBaIEeWQ3O79R6E3Ug" borderColor="114,73,110" labelPosition="node" width="10" height="10" color="217,196,215">
+ <description xmi:type="style:SquareDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']/@style"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:NodeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']"/>
+ </ownedDiagramElements>
+ </ownedDiagramElements>
+ <ownedDiagramElements xmi:type="diagram:DEdge" xmi:id="_US1hQBaIEeWQ3O79R6E3Ug" name="toC2" sourceNode="_OqG-MBaIEeWQ3O79R6E3Ug" targetNode="_OqO6ABaIEeWQ3O79R6E3Ug">
+ <target xmi:type="ecore:EReference" href="My.ecore#//p1/C1/toC2"/>
+ <semanticElements xmi:type="ecore:EReference" href="My.ecore#//p1/C1/toC2"/>
+ <ownedStyle xmi:type="diagram:EdgeStyle" xmi:id="_US4kkBaIEeWQ3O79R6E3Ug" size="2">
+ <description xmi:type="style:EdgeStyleDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@edgeMappings[name='Reference']/@style"/>
+ <centerLabelStyle xmi:type="diagram:CenterLabelStyle" xmi:id="_US4kkRaIEeWQ3O79R6E3Ug"/>
+ </ownedStyle>
+ <actualMapping xmi:type="description_1:EdgeMapping" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@edgeMappings[name='Reference']"/>
+ </ownedDiagramElements>
+ <description xmi:type="description_1:DiagramDescription" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']"/>
+ <filterVariableHistory xmi:type="diagram:FilterVariableHistory" xmi:id="_M0HXtxWdEeW7GcqVYwuCiQ"/>
+ <activatedLayers xmi:type="description_1:Layer" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer"/>
+ <target xmi:type="ecore:EPackage" href="My.ecore#/"/>
+ </ownedRepresentations>
+ <viewpoint xmi:type="description:Viewpoint" href="snapToAll.odesign#//@ownedViewpoints[name='snapToAll']"/>
+ </ownedViews>
+</viewpoint:DAnalysis>
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/snapToAll.odesign b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/snapToAll.odesign
new file mode 100644
index 0000000000..b94721d7e6
--- /dev/null
+++ b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/snap/snapToAll.odesign
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="ASCII"?>
+<description:Group xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:description="http://www.eclipse.org/sirius/description/1.1.0" xmlns:description_1="http://www.eclipse.org/sirius/diagram/description/1.1.0" xmlns:style="http://www.eclipse.org/sirius/diagram/description/style/1.1.0" name="snapToAll" version="10.0.0.201505222000">
+ <ownedViewpoints name="snapToAll" modelFileExtension="ecore">
+ <ownedRepresentations xsi:type="description_1:DiagramDescription" name="snapToAllDiagram" domainClass="EPackage">
+ <defaultLayer name="Default">
+ <nodeMappings name="NodePackage" semanticCandidatesExpression="feature:eContents" domainClass="EPackage">
+ <borderedNodeMappings name="EClassOnNode" semanticCandidatesExpression="feature:eContents" domainClass="EClass">
+ <borderedNodeMappings name="EAttributeOnEClassOnNode" semanticCandidatesExpression="feature:eContents" domainClass="EAttribute">
+ <style xsi:type="style:SquareDescription" labelExpression="aql:'BNBNN_' + self.name" labelPosition="node" resizeKind="NSEW" width="5" height="5">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_green']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <color xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_yellow']"/>
+ </style>
+ </borderedNodeMappings>
+ <style xsi:type="style:SquareDescription" labelExpression="aql:'BNN_' + self.name" labelPosition="node" resizeKind="NSEW" width="10" height="10">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='dark_purple']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <color xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_red']"/>
+ </style>
+ </borderedNodeMappings>
+ <style xsi:type="style:SquareDescription" labelExpression="aql:'Node_' + self.name" labelPosition="node" resizeKind="NSEW" width="25" height="25">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='dark_purple']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <color xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_purple']"/>
+ </style>
+ </nodeMappings>
+ <edgeMappings name="Reference" sourceMapping="//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']" targetMapping="//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']/@subNodeMappings[name='EClassInContainer']" targetFinderExpression="feature:eType" sourceFinderExpression="feature:eContainer" domainClass="EReference" useDomainElement="true">
+ <style sizeComputationExpression="2">
+ <strokeColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='gray']"/>
+ <centerLabelStyleDescription labelExpression="feature:name">
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ </centerLabelStyleDescription>
+ </style>
+ </edgeMappings>
+ <containerMappings name="ContainerPackage" semanticCandidatesExpression="feature:eContents" domainClass="EPackage" reusedContainerMappings="//@ownedViewpoints[name='snapToAll']/@ownedRepresentations[name='snapToAllDiagram']/@defaultLayer/@containerMappings[name='ContainerPackage']">
+ <borderedNodeMappings name="EClassOnContainer" semanticCandidatesExpression="feature:eContents" domainClass="EClass">
+ <borderedNodeMappings name="EAttribute" semanticCandidatesExpression="feature:eContents" domainClass="EAttribute">
+ <style xsi:type="style:SquareDescription" labelExpression="aql:'BNBNC_' + self.name" labelPosition="node" resizeKind="NSEW" width="5" height="5">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='dark_purple']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <color xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_red']"/>
+ </style>
+ </borderedNodeMappings>
+ <style xsi:type="style:SquareDescription" labelExpression="aql:'BNC_' + self.name" labelPosition="node" resizeKind="NSEW" width="10" height="10">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='dark_purple']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <color xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_purple']"/>
+ </style>
+ </borderedNodeMappings>
+ <subNodeMappings name="EClassInContainer" semanticCandidatesExpression="feature:eContents" domainClass="EClass">
+ <borderedNodeMappings name="EAttribute" semanticCandidatesExpression="feature:eContents" domainClass="EAttribute">
+ <style xsi:type="style:SquareDescription" labelExpression="aql:'BNNC_' + self.name" labelPosition="node" resizeKind="NSEW" width="5" height="5">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='dark_purple']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <color xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_red']"/>
+ </style>
+ </borderedNodeMappings>
+ <style xsi:type="style:SquareDescription" labelExpression="aql:'NC_' + self.name" labelPosition="node" resizeKind="NSEW" width="10" height="10">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='dark_purple']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <color xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_purple']"/>
+ </style>
+ </subNodeMappings>
+ <style xsi:type="style:FlatContainerStyleDescription" arcWidth="1" arcHeight="1" labelExpression="aql:'Container_' + self.name">
+ <borderColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='dark_blue']"/>
+ <labelColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='black']"/>
+ <backgroundColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='white']"/>
+ <foregroundColor xsi:type="description:SystemColor" href="environment:/viewpoint#//@systemColors/@entries[name='light_blue']"/>
+ </style>
+ </containerMappings>
+ </defaultLayer>
+ </ownedRepresentations>
+ </ownedViewpoints>
+</description:Group>
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/SnapAllShapesTest.java b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/SnapAllShapesTest.java
new file mode 100644
index 0000000000..dbbe3c4431
--- /dev/null
+++ b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/SnapAllShapesTest.java
@@ -0,0 +1,295 @@
+/*******************************************************************************
+ * Copyright (c) 2015 THALES GLOBAL SERVICES.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.tests.swtbot;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.sirius.diagram.DDiagram;
+import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramBorderNodeEditPart;
+import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramContainerEditPart;
+import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramNodeEditPart;
+import org.eclipse.sirius.ext.gmf.runtime.editparts.GraphicalHelper;
+import org.eclipse.sirius.tests.swtbot.support.api.AbstractSiriusSwtBotGefTestCase;
+import org.eclipse.sirius.tests.swtbot.support.api.business.UIDiagramRepresentation.ZoomLevel;
+import org.eclipse.sirius.tests.swtbot.support.api.business.UIResource;
+import org.eclipse.sirius.tests.swtbot.support.api.condition.TopCondition;
+import org.eclipse.sirius.tests.swtbot.support.api.editor.SWTBotSiriusDiagramEditor;
+import org.eclipse.sirius.tests.swtbot.support.api.view.DesignerViews;
+import org.eclipse.sirius.tests.swtbot.support.utils.SWTBotUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swtbot.eclipse.gef.finder.widgets.SWTBotGefEditPart;
+
+/**
+ * Check the snap to all feature (move and resize).
+ *
+ * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
+ */
+public class SnapAllShapesTest extends AbstractSiriusSwtBotGefTestCase {
+ private static final String SEMANTIC_RESOURCE_NAME = "My.ecore";
+
+ private static final String SESSION_RESOURCE_NAME = "representations.aird";
+
+ private static final String MODELER_RESOURCE_NAME = "snapToAll.odesign";
+
+ private static final String DATA_UNIT_DIR = "data/unit/snap/";
+
+ @Override
+ protected void onSetUpBeforeClosingWelcomePage() throws Exception {
+ copyFileToTestProject(Activator.PLUGIN_ID, DATA_UNIT_DIR, SEMANTIC_RESOURCE_NAME, SESSION_RESOURCE_NAME, MODELER_RESOURCE_NAME);
+ }
+
+ @Override
+ protected void onSetUpAfterOpeningDesignerPerspective() throws Exception {
+ // Close the outline view
+ bot.viewById("org.eclipse.ui.views.ContentOutline").close();
+ SWTBotUtils.waitAllUiEvents();
+
+ // Open the session
+ UIResource sessionAirdResource = new UIResource(designerProject, SESSION_RESOURCE_NAME);
+ localSession = designerPerspective.openSessionFromFile(sessionAirdResource, true);
+
+ // Open the editor
+ editor = (SWTBotSiriusDiagramEditor) openRepresentation(localSession.getOpenedSession(), "snapToAllDiagram", "snapToAllDiagram", DDiagram.class, true, false);
+ editor.maximize();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (editor != null) {
+ editor.zoom(ZoomLevel.ZOOM_100);
+ editor.restore();
+ editor.scrollTo(0, 0);
+ }
+ // Close the editor before opening the outline
+ if (editor != null) {
+ editor.close();
+ SWTBotUtils.waitAllUiEvents();
+ }
+
+ // Reopen outline
+ new DesignerViews(bot).openOutlineView();
+ SWTBotUtils.waitAllUiEvents();
+ super.tearDown();
+ }
+
+ /**
+ * Move a container a first time without F4 and check the location is the
+ * expected one.<BR>
+ * Move a container a second time with F4 and check the location is the
+ * expected one (snap to another figure).<BR>
+ * This test also handles the case of scroll bar in diagram.
+ */
+ public void testMoveContainer() {
+ moveTopOfElementNearBottomOfAnother("Container_p1", AbstractDiagramContainerEditPart.class, "BNBNN_att1", AbstractDiagramBorderNodeEditPart.class);
+ }
+
+ /**
+ * Move a node a first time without F4 and check the location is the
+ * expected one.<BR>
+ * Move a node a second time with F4 and check the location is the expected
+ * one (snap to another figure).<BR>
+ * This test also handles the case of scroll bar in diagram.
+ */
+ public void testMoveNode() {
+ moveTopOfElementNearBottomOfAnother("Node_p1", AbstractDiagramNodeEditPart.class, "BNNC_att1", AbstractDiagramBorderNodeEditPart.class);
+ }
+
+ /**
+ * Move a node in container a first time without F4 and check the location
+ * is the expected one.<BR>
+ * Move a node in container a second time with F4 and check the location is
+ * the expected one (snap to another figure).<BR>
+ * This test also handles the case of scroll bar in diagram and in
+ * container.
+ */
+
+ public void testMoveNodeInContainer() {
+ moveTopOfElementNearBottomOfAnother("NC_C1", AbstractDiagramNodeEditPart.class, "Node_p1", AbstractDiagramNodeEditPart.class);
+ }
+
+ /**
+ * Move a node in container a first time without F4 and check the location
+ * is the expected one.<BR>
+ * Move a node in container a second time with F4 and check the location is
+ * the expected one (snap to another figure).<BR>
+ * This test also handles the case of scroll bar in diagram and in container
+ * and with zoom different from 100%.
+ */
+ public void testMoveNodeInContainerWithZoom125() {
+ moveTopOfElementNearBottomOfAnother("NC_C1", AbstractDiagramNodeEditPart.class, "Node_p1", AbstractDiagramNodeEditPart.class, ZoomLevel.ZOOM_125);
+ }
+
+ /**
+ * Resize a container a first time without F4 and check the location is the
+ * expected one.<BR>
+ * Resize a container a second time with F4 and check the location is the
+ * expected one (snap to another figure).<BR>
+ * This test also handles the case of scroll bar in diagram.
+ */
+ public void testResizeContainer() {
+ resizeTopOfElementNearBottomOfAnother("Container_p1", AbstractDiagramContainerEditPart.class, "BNBNN_att1", AbstractDiagramBorderNodeEditPart.class);
+ }
+
+ /**
+ * Resize a node a first time without F4 and check the location is the
+ * expected one.<BR>
+ * Resize a node a second time with F4 and check the location is the
+ * expected one (snap to another figure).<BR>
+ * This test also handles the case of scroll bar in diagram.
+ */
+ public void testResizeNode() {
+ resizeTopOfElementNearBottomOfAnother("Node_p1", AbstractDiagramNodeEditPart.class, "BNNC_att1", AbstractDiagramBorderNodeEditPart.class);
+ }
+
+ /**
+ * Resize a node in container a first time without F4 and check the location
+ * is the expected one.<BR>
+ * Resize a node in container a second time with F4 and check the location
+ * is the expected one (snap to another figure).<BR>
+ * This test also handles the case of scroll bar in diagram and in
+ * container.
+ */
+
+ public void testResizeNodeInContainer() {
+ resizeTopOfElementNearBottomOfAnother("NC_C1", AbstractDiagramNodeEditPart.class, "Node_p1", AbstractDiagramNodeEditPart.class);
+ }
+
+ /**
+ * Resize a node in container a first time without F4 and check the location
+ * is the expected one.<BR>
+ * Resize a node in container a second time with F4 and check the location
+ * is the expected one (snap to another figure).<BR>
+ * This test also handles the case of scroll bar in diagram and in container
+ * and with zoom different from 100%.
+ */
+ public void testResizeNodeInContainerWithZoom125() {
+ resizeTopOfElementNearBottomOfAnother("NC_C1", AbstractDiagramNodeEditPart.class, "Node_p1", AbstractDiagramNodeEditPart.class, ZoomLevel.ZOOM_125);
+ }
+
+ private void moveTopOfElementNearBottomOfAnother(String elementNameToMove, Class<? extends EditPart> expectedEditPartTypeOfMovedElement, String referenceElementName,
+ Class<? extends EditPart> expectedEditPartTypeOfReferenceElement) {
+ moveTopOfElementNearBottomOfAnother(elementNameToMove, expectedEditPartTypeOfMovedElement, referenceElementName, expectedEditPartTypeOfReferenceElement, ZoomLevel.ZOOM_100);
+ }
+
+ /**
+ * Move element a first time without F4 and check the location is the
+ * expected one.<BR>
+ * Move element a second time with F4 and check the location is the expected
+ * one (snap to another figure).<BR>
+ */
+ private void moveTopOfElementNearBottomOfAnother(String elementNameToMove, Class<? extends EditPart> expectedEditPartTypeOfMovedElement, String referenceElementName,
+ Class<? extends EditPart> expectedEditPartTypeOfReferenceElement, ZoomLevel zoomLevel) {
+ editor.zoom(zoomLevel);
+ editor.scrollTo(0, 0);
+
+ SWTBotGefEditPart elementToMove = editor.getEditPart(elementNameToMove, expectedEditPartTypeOfMovedElement);
+ // Select the element to move
+ editor.select(elementToMove);
+
+ // Get the top center coordinates, just a little below, of the element
+ // to move
+ final Rectangle originalBounds = GraphicalHelper.getAbsoluteBoundsIn100Percent((GraphicalEditPart) elementToMove.part());
+ final Point pointToDrag = originalBounds.getTop().getTranslated(0, 3);
+ Point scaledPointToDrag = new PrecisionPoint(pointToDrag);
+ GraphicalHelper.logical2screen(scaledPointToDrag, (IGraphicalEditPart) elementToMove.part());
+ // Compute the drop destination (at 4 pixels of the bottom of another
+ // part)
+ final Rectangle targetNodeBounds = GraphicalHelper.getAbsoluteBoundsIn100Percent((GraphicalEditPart) editor.getEditPart(referenceElementName, expectedEditPartTypeOfReferenceElement).part());
+ final Point endpoint = new Point(pointToDrag.x, targetNodeBounds.getBottom().y - 1);
+ Point scaledEndpoint = new PrecisionPoint(endpoint);
+ GraphicalHelper.logical2screen(scaledEndpoint, (IGraphicalEditPart) elementToMove.part());
+
+ // First move without F4 key pressed
+ editor.drag(scaledPointToDrag.x, scaledPointToDrag.y, scaledEndpoint.x, scaledEndpoint.y);
+ SWTBotUtils.waitAllUiEvents();
+ // Get the new bounds and compare with the expected. It should be
+ // precisely where the drag has been done: at 4 pixels of the bottom of
+ // the other figure
+ Rectangle newBounds = GraphicalHelper.getAbsoluteBoundsIn100Percent((GraphicalEditPart) elementToMove.part());
+ assertEquals("Element \"" + elementNameToMove + "\" is not at expected y location after move without F4 key pressed", targetNodeBounds.getBottom().y - 4, newBounds.getTop().y);
+
+ // Move to initial location
+ undo(localSession.getOpenedSession());
+ // Scroll to 0, 0 is needed because the first move can cause a scroll of
+ // the diagram not reverted by the Undo.
+ editor.scrollTo(0, 0);
+
+ // Second move with F4 key pressed
+ editor.dragWithKey(scaledPointToDrag.x, scaledPointToDrag.y, scaledEndpoint.x, scaledEndpoint.y, SWT.F4);
+ SWTBotUtils.waitAllUiEvents();
+ // Get the new bounds and compare with the expected. It should be
+ // aligned to the bottom of the other figure: at 1 pixel of the bottom
+ // as computed guide in SiriusSnapToGeometry.populateRowsAndCols(List)
+ newBounds = GraphicalHelper.getAbsoluteBoundsIn100Percent((GraphicalEditPart) elementToMove.part());
+ assertEquals("Element \"" + elementNameToMove + "\" is not at expected location after move with F4 key pressed", targetNodeBounds.getBottom().y - 1, newBounds.getTop().y);
+ }
+
+ private void resizeTopOfElementNearBottomOfAnother(String elementNameToMove, Class<? extends EditPart> expectedEditPartTypeOfMovedElement, String referenceElementName,
+ Class<? extends EditPart> expectedEditPartTypeOfReferenceElement) {
+ resizeTopOfElementNearBottomOfAnother(elementNameToMove, expectedEditPartTypeOfMovedElement, referenceElementName, expectedEditPartTypeOfReferenceElement, ZoomLevel.ZOOM_100);
+ }
+
+ /**
+ * Resize element a first time without F4 and check the location is the
+ * expected one.<BR>
+ * Resize element a second time with F4 and check the location is the
+ * expected one (snap to another figure).<BR>
+ */
+ private void resizeTopOfElementNearBottomOfAnother(String elementNameToMove, Class<? extends EditPart> expectedEditPartTypeOfMovedElement, String referenceElementName,
+ Class<? extends EditPart> expectedEditPartTypeOfReferenceElement, final ZoomLevel zoomLevel) {
+ editor.zoom(zoomLevel);
+ editor.scrollTo(0, 0);
+
+ final SWTBotGefEditPart elementToMove = editor.getEditPart(elementNameToMove, expectedEditPartTypeOfMovedElement);
+ // Select the element to move
+ editor.select(elementToMove);
+
+ // Get the top center coordinates of the element to move
+ final Rectangle originalBounds = GraphicalHelper.getAbsoluteBoundsIn100Percent((GraphicalEditPart) elementToMove.part());
+ final Point pointToDrag = originalBounds.getTop();
+ Point scaledPointToDrag = new PrecisionPoint(pointToDrag);
+ GraphicalHelper.logical2screen(scaledPointToDrag, (IGraphicalEditPart) elementToMove.part());
+ // Compute the drop destination (at 4 pixels of the bottom of another
+ // part)
+ final Rectangle targetNodeBounds = GraphicalHelper.getAbsoluteBoundsIn100Percent((GraphicalEditPart) editor.getEditPart(referenceElementName, expectedEditPartTypeOfReferenceElement).part());
+ final Point endpoint = new Point(pointToDrag.x, targetNodeBounds.getBottom().y - 4);
+ Point scaledEndpoint = new PrecisionPoint(endpoint);
+ GraphicalHelper.logical2screen(scaledEndpoint, (IGraphicalEditPart) elementToMove.part());
+
+ // First move without F4 key pressed
+ editor.drag(scaledPointToDrag.x, scaledPointToDrag.y, scaledEndpoint.x, scaledEndpoint.y);
+ SWTBotUtils.waitAllUiEvents();
+ // Get the new bounds and compare with the expected. It should be
+ // precisely where the drag has been done: at 4 pixels of the bottom of
+ // the other figure
+ bot.waitUntil(new TopCondition((GraphicalEditPart) elementToMove.part(), targetNodeBounds.getBottom().y - 4,
+ "Element \"" + elementNameToMove + "\" is not at expected y location after resize without F4 key pressed", !ZoomLevel.ZOOM_100.equals(zoomLevel)));
+
+ // Move to initial location
+ undo(localSession.getOpenedSession());
+ // Scroll to 0, 0 is needed because the first move can cause a scroll of
+ // the diagram not reverted by the Undo.
+ editor.scrollTo(0, 0);
+
+ // Second move with F4 key pressed
+ editor.dragWithKey(scaledPointToDrag.x, scaledPointToDrag.y, scaledEndpoint.x, scaledEndpoint.y, SWT.F4);
+ SWTBotUtils.waitAllUiEvents();
+ // Get the new bounds and compare with the expected. It should be
+ // aligned to the bottom of the other figure: at 1 pixel of the bottom
+ // as computed guide in SiriusSnapToGeometry.populateRowsAndCols(List)
+ bot.waitUntil(new TopCondition((GraphicalEditPart) elementToMove.part(), targetNodeBounds.getBottom().y - 1,
+ "Element \"" + elementNameToMove + "\" is not at expected y location after resize with F4 key pressed", !ZoomLevel.ZOOM_100.equals(zoomLevel)));
+ }
+}
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java
index 34f69a03c9..bee4f57362 100644
--- a/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java
+++ b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java
@@ -181,6 +181,7 @@ public class AllTestSuite extends TestCase {
suite.addTestSuite(CloseWithoutSavingTest.class);
suite.addTestSuite(CreateMandatoryElementsTest.class);
suite.addTestSuite(LockedModelExplorerTest.class);
+ suite.addTestSuite(SnapAllShapesTest.class);
}
/**

Back to the top