diff options
| author | Laurent Redor | 2017-08-17 14:13:10 +0000 |
|---|---|---|
| committer | Florian Barbin | 2017-08-25 14:31:16 +0000 |
| commit | 4ffdecbf8a4dde5b7217e1657269d694030e4986 (patch) | |
| tree | 8feb2e41214f6b01d0796a0c1750db789dfbcb31 | |
| parent | add47270fc166182e7cc4ee6f777661fb0109ecd (diff) | |
| download | org.eclipse.sirius-4ffdecbf8a4dde5b7217e1657269d694030e4986.tar.gz org.eclipse.sirius-4ffdecbf8a4dde5b7217e1657269d694030e4986.tar.xz org.eclipse.sirius-4ffdecbf8a4dde5b7217e1657269d694030e4986.zip | |
[520881] Add snapToGrid notion in CanonicalDBorderItemLocator
This commit introduces the snapToGrid notion in
DDiagramCanonicalSynchronizer and CanonicalDBorderItemLocator. This is
the only way to have correct results (if snapToGrid is enabled). The
location stored in EdgeLayoutData was already snapped to the grid but
the CanonicalDBorderItemLocator broke this constraints as it had not
snapToGrid notion.
This commit does not fix all failing tests of previous commit but a
large part.
Bug: 520881
Change-Id: Ie61ef87284d13f535cfb037e3fe0cc51261d74ae
Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
3 files changed, 552 insertions, 100 deletions
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/AbstractCanonicalSynchronizer.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/AbstractCanonicalSynchronizer.java index b29656ea39..a65894d6a5 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/AbstractCanonicalSynchronizer.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/AbstractCanonicalSynchronizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2016 THALES GLOBAL SERVICES and others. + * Copyright (c) 2011, 2017 THALES GLOBAL SERVICES 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 @@ -106,6 +106,17 @@ public abstract class AbstractCanonicalSynchronizer implements CanonicalSynchron protected Map<View, Boolean> regionsContainersToLayoutWithImpactStatus = Maps.newHashMap(); /** + * True if the snap to grid is considered as activated. In this case, the returned location, by + * {@link #getValidLocation(Rectangle, Node, Collection<Node>)}, is snapped to the grid (if possible). + */ + private boolean snapToGrid; + + /** + * The grid step (it is mandatory if the {@link #snapToGrid} is true. + */ + private int gridSpacing = 0; + + /** * Default constructor. */ public AbstractCanonicalSynchronizer() { @@ -199,6 +210,22 @@ public abstract class AbstractCanonicalSynchronizer implements CanonicalSynchron return createdViews; } + protected boolean isSnapToGrid() { + return snapToGrid; + } + + protected void setSnapToGrid(boolean snapToGrid) { + this.snapToGrid = snapToGrid; + } + + protected int getGridSpacing() { + return gridSpacing; + } + + protected void setGridSpacing(int gridSpacing) { + this.gridSpacing = gridSpacing; + } + /** * Set the gmfView, or its ancestor representation the real regions * container, as impacted by the changes (new views, removed views or order @@ -539,7 +566,7 @@ public abstract class AbstractCanonicalSynchronizer implements CanonicalSynchron tempBounds = new Rectangle(location, size); } - CanonicalDBorderItemLocator locator = new CanonicalDBorderItemLocator(parentNode, PositionConstants.NSEW); + CanonicalDBorderItemLocator locator = new CanonicalDBorderItemLocator(parentNode, PositionConstants.NSEW, isSnapToGrid(), getGridSpacing()); if (new ViewQuery(createdView).isForNameEditPart()) { locator.setBorderItemOffset(IBorderItemOffsets.NO_OFFSET); } else { @@ -555,7 +582,7 @@ public abstract class AbstractCanonicalSynchronizer implements CanonicalSynchron locator.setConstraint(constraint); dummyFigure.setVisible(true); final Rectangle rect = new Rectangle(constraint); - Point parentAbsoluteLocation = GMFHelper.getAbsoluteLocation(parentNode); + Point parentAbsoluteLocation = GMFHelper.getAbsoluteLocation(parentNode, true); rect.translate(parentAbsoluteLocation.x, parentAbsoluteLocation.y); dummyFigure.setBounds(rect); final Point realLocation = locator.getValidLocation(rect, createdNode, Lists.newArrayList(createdNode)); diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/borderednode/CanonicalDBorderItemLocator.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/borderednode/CanonicalDBorderItemLocator.java index db145fb402..82da5444e0 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/borderednode/CanonicalDBorderItemLocator.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/borderednode/CanonicalDBorderItemLocator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2016 THALES GLOBAL SERVICES. + * Copyright (c) 2011, 2017 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 @@ -71,6 +71,17 @@ public class CanonicalDBorderItemLocator { private Rectangle parentBorder; /** + * True if the snap to grid is considered as activated. In this case, the returned location, by + * {@link #getValidLocation(Rectangle, Node, Collection<Node>)}, is snapped to the grid (if possible). + */ + private boolean snapToGrid; + + /** + * The grid step (it is mandatory if the {@link #snapToGrid} is true. + */ + private int gridSpacing = 0; + + /** * Default constructor. * * @param containerNode @@ -85,6 +96,24 @@ public class CanonicalDBorderItemLocator { } /** + * Constructor if the snapToGrid is enabled. + * + * @param containerNode + * the container + * @param preferredSide + * the preferred side + * @param snapToGrid + * true if the snapToGrid is enabled, false otherwise + * @param gridSpacing + * The grid step in pixels + */ + public CanonicalDBorderItemLocator(Node containerNode, int preferredSide, boolean snapToGrid, int gridSpacing) { + this(containerNode, preferredSide); + this.snapToGrid = snapToGrid; + this.gridSpacing = gridSpacing; + } + + /** * Set the border item offset. * * @param borderItemOffset @@ -152,31 +181,35 @@ public class CanonicalDBorderItemLocator { /** * Find the closest side when x,y is inside parent. * - * @param proposedLocation - * the proposed location + * @param proposedBounds + * the proposed bounds * @param parentBorder * the parent border * @return draw constant */ - public static int findClosestSideOfParent(final Rectangle proposedLocation, final Rectangle parentBorder) { - return findClosestSideOfParent(proposedLocation, parentBorder, null); + public static int findClosestSideOfParent(final Rectangle proposedBounds, final Rectangle parentBorder) { + return findClosestSideOfParent(proposedBounds, parentBorder, null, false, 0); } /** * Find the closest side when x,y is inside parent. * - * @param proposedLocation - * the proposed location + * @param proposedBounds + * the proposed bounds * @param parentBorder * the parent border * @param authorizedSides * the authorized sides. a BitSet using the {@link PositionConstants} values as index. All sides are * considered as authorized if the value is null or the bitSet is empty. + * @param snapToGrid + * true if the snapToGrid is enabled, false otherwise + * @param gridSpacing + * The grid step in pixels * @return draw constant */ - private static int findClosestSideOfParent(final Rectangle proposedLocation, final Rectangle parentBorder, BitSet authorizedSides) { + private static int findClosestSideOfParent(final Rectangle proposedBounds, final Rectangle parentBorder, BitSet authorizedSides, boolean snapToGrid, int gridSpacing) { final Point parentCenter = parentBorder.getCenter(); - final Point childCenter = proposedLocation.getCenter(); + final Point childCenter = proposedBounds.getCenter(); int position; boolean northAuthorized = true; @@ -193,9 +226,9 @@ public class CanonicalDBorderItemLocator { // natural. if (!eastAuthorized || canHandleWestSide(parentCenter, childCenter, northAuthorized, southAuthorized, westAuthorized)) { // West, North or South. - position = handleWestSide(parentBorder, parentCenter, childCenter, northAuthorized, southAuthorized, westAuthorized); + position = handleWestSide(parentBorder, parentCenter, proposedBounds, northAuthorized, southAuthorized, westAuthorized, snapToGrid, gridSpacing); } else { - position = handleEastSide(parentBorder, parentCenter, childCenter, northAuthorized, southAuthorized, eastAuthorized); + position = handleEastSide(parentBorder, parentCenter, proposedBounds, northAuthorized, southAuthorized, eastAuthorized, snapToGrid, gridSpacing); } return position; } @@ -204,20 +237,22 @@ public class CanonicalDBorderItemLocator { return (westAuthorized || southAuthorized || northAuthorized) && childCenter.x < parentCenter.x; } - private static int handleWestSide(final Rectangle parentBorder, final Point parentCenter, final Point childCenter, boolean northAuthorized, boolean southAuthorized, boolean westAuthorized) { + private static int handleWestSide(final Rectangle parentBorder, final Point parentCenter, final Rectangle borderNodeBounds, boolean northAuthorized, boolean southAuthorized, + boolean westAuthorized, boolean snapToGrid, int gridSpacing) { int position; - if (!southAuthorized || (westAuthorized || northAuthorized) && childCenter.y < parentCenter.y) { + if (!southAuthorized || (westAuthorized || northAuthorized) && borderNodeBounds.getCenter().y < parentCenter.y) { // west or north - position = handleNorthWest(parentBorder, childCenter, northAuthorized, westAuthorized); + position = handleNorthWest(parentBorder, borderNodeBounds, northAuthorized, westAuthorized, snapToGrid, gridSpacing); } else { // west or south - position = handleSouthWest(parentBorder, childCenter, southAuthorized, westAuthorized); + position = handleSouthWest(parentBorder, borderNodeBounds, southAuthorized, westAuthorized, snapToGrid, gridSpacing); } return position; } - private static int handleNorthWest(final Rectangle parentBorder, final Point childCenter, boolean northAuthorized, boolean westAuthorized) { - int position; + private static int handleNorthWest(final Rectangle parentBounds, final Rectangle borderNodeBounds, boolean northAuthorized, boolean westAuthorized, boolean snapToGrid, int gridSpacing) { + int position = PositionConstants.NONE; + Point borderNodeCenter = borderNodeBounds.getCenter(); // if one of these sides is not authorized, we retain the only // one authorized. if (!northAuthorized || !westAuthorized) { @@ -228,20 +263,29 @@ public class CanonicalDBorderItemLocator { } } else { // closer to west or north? - final Point parentTopLeft = parentBorder.getTopLeft(); - if (childCenter.y < parentTopLeft.y) { - position = PositionConstants.NORTH; - } else if ((childCenter.x - parentTopLeft.x) <= (childCenter.y - parentTopLeft.y)) { - position = PositionConstants.WEST; - } else { - position = PositionConstants.NORTH; + final Point parentTopLeft = parentBounds.getTopLeft(); + Point childLocation = borderNodeBounds.getTopLeft(); + if (snapToGrid && childLocation.y < parentTopLeft.y && childLocation.x < parentTopLeft.x) { + // The child location is outside the parent, if the snap to grid is enabled, we must find the next step + // with at least x or y inside the parent bounds. + position = findNorthOrWestPreviousLocationSnappedToGridAndInsideParentBounds(parentBounds, borderNodeBounds, gridSpacing); + } + if (position == PositionConstants.NONE) { + if (borderNodeCenter.y < parentTopLeft.y) { + position = PositionConstants.NORTH; + } else if ((borderNodeCenter.x - parentTopLeft.x) <= (borderNodeCenter.y - parentTopLeft.y)) { + position = PositionConstants.WEST; + } else { + position = PositionConstants.NORTH; + } } } return position; } - private static int handleSouthWest(final Rectangle parentBorder, final Point childCenter, boolean southAuthorized, boolean westAuthorized) { - int position; + private static int handleSouthWest(final Rectangle parentBounds, final Rectangle borderNodeBounds, boolean southAuthorized, boolean westAuthorized, boolean snapToGrid, int gridSpacing) { + int position = PositionConstants.NONE; + Point borderNodeCenter = borderNodeBounds.getCenter(); // if one of these sides is not authorized, we retain the only // one authorized. if (!southAuthorized || !westAuthorized) { @@ -251,32 +295,42 @@ public class CanonicalDBorderItemLocator { position = PositionConstants.WEST; } } else { - final Point parentBottomLeft = parentBorder.getBottomLeft(); - if (childCenter.y > parentBottomLeft.y) { - position = PositionConstants.SOUTH; - } else if ((childCenter.x - parentBottomLeft.x) <= (parentBottomLeft.y - childCenter.y)) { - position = PositionConstants.WEST; - } else { - position = PositionConstants.SOUTH; + final Point parentBottomLeft = parentBounds.getBottomLeft(); + Point childLocation = borderNodeBounds.getTopLeft(); + if (snapToGrid && childLocation.y > parentBottomLeft.y && childLocation.x < parentBottomLeft.x) { + // The child location is outside the parent, if the snap to grid is enabled, we must find the next step + // with at least x or y inside the parent bounds. + position = findWestOrSouthPreviousLocationSnappedToGridAndInsideParentBounds(parentBounds, borderNodeBounds, gridSpacing); + } + if (position == PositionConstants.NONE) { + if (borderNodeCenter.y > parentBottomLeft.y) { + position = PositionConstants.SOUTH; + } else if ((borderNodeCenter.x - parentBottomLeft.x) <= (parentBottomLeft.y - borderNodeCenter.y)) { + position = PositionConstants.WEST; + } else { + position = PositionConstants.SOUTH; + } } } return position; } - private static int handleEastSide(final Rectangle parentBorder, final Point parentCenter, final Point childCenter, boolean northAuthorized, boolean southAuthorized, boolean eastAuthorized) { + private static int handleEastSide(final Rectangle parentBounds, final Point parentCenter, final Rectangle borderNodeBounds, boolean northAuthorized, boolean southAuthorized, + boolean eastAuthorized, boolean snapToGrid, int gridSpacing) { int position; // EAST, NORTH or SOUTH - if (!southAuthorized || (eastAuthorized || northAuthorized) && childCenter.y < parentCenter.y) { + if (!southAuthorized || (eastAuthorized || northAuthorized) && borderNodeBounds.getCenter().y < parentCenter.y) { // north or east - position = handleNorthEast(parentBorder, childCenter, northAuthorized, eastAuthorized); + position = handleNorthEast(parentBounds, borderNodeBounds, northAuthorized, eastAuthorized, snapToGrid, gridSpacing); } else { // south or east. - position = handleSouthEast(parentBorder, childCenter, southAuthorized, eastAuthorized); + position = handleSouthEast(parentBounds, borderNodeBounds, southAuthorized, eastAuthorized, snapToGrid, gridSpacing); } return position; } - private static int handleNorthEast(final Rectangle parentBorder, final Point childCenter, boolean northAuthorized, boolean eastAuthorized) { - int position; + private static int handleNorthEast(final Rectangle parentBounds, final Rectangle borderNodeBounds, boolean northAuthorized, boolean eastAuthorized, boolean snapToGrid, int gridSpacing) { + int position = PositionConstants.NONE; + Point borderNodeCenter = borderNodeBounds.getCenter(); // if one of these sides is not authorized, we retain the only // one authorized. if (!eastAuthorized || !northAuthorized) { @@ -286,20 +340,29 @@ public class CanonicalDBorderItemLocator { position = PositionConstants.NORTH; } } else { - final Point parentTopRight = parentBorder.getTopRight(); - if (childCenter.y < parentTopRight.y) { - position = PositionConstants.NORTH; - } else if ((parentTopRight.x - childCenter.x) <= (childCenter.y - parentTopRight.y)) { - position = PositionConstants.EAST; - } else { - position = PositionConstants.NORTH; + final Point parentTopRight = parentBounds.getTopRight(); + Point childLocation = borderNodeBounds.getTopLeft(); + if (snapToGrid && childLocation.y < parentTopRight.y && childLocation.x > parentTopRight.x) { + // The child location is outside the parent, if the snap to grid is enabled, we must find the next step + // with at least x or y inside the parent bounds. + position = findNorthOrEastPreviousLocationSnappedToGridAndInsideParentBounds(parentBounds, borderNodeBounds, gridSpacing); + } + if (position == PositionConstants.NONE) { + if (borderNodeCenter.y < parentTopRight.y) { + position = PositionConstants.NORTH; + } else if ((parentTopRight.x - borderNodeCenter.x) <= (borderNodeCenter.y - parentTopRight.y)) { + position = PositionConstants.EAST; + } else { + position = PositionConstants.NORTH; + } } } return position; } - private static int handleSouthEast(final Rectangle parentBorder, final Point childCenter, boolean southAuthorized, boolean eastAuthorized) { - int position; + private static int handleSouthEast(final Rectangle parentBounds, final Rectangle borderNodeBounds, boolean southAuthorized, boolean eastAuthorized, boolean snapToGrid, int gridSpacing) { + int position = PositionConstants.NONE; + Point borderNodeCenter = borderNodeBounds.getCenter(); // if one of these sides is not authorized, we retain the only // one authorized. if (!eastAuthorized || !southAuthorized) { @@ -309,18 +372,207 @@ public class CanonicalDBorderItemLocator { position = PositionConstants.SOUTH; } } else { - final Point parentBottomRight = parentBorder.getBottomRight(); - if (childCenter.y > parentBottomRight.y) { + final Point parentBottomRight = parentBounds.getBottomRight(); + Point childLocation = borderNodeBounds.getTopLeft(); + if (snapToGrid && childLocation.y > parentBottomRight.y && childLocation.x > parentBottomRight.x) { + // The child location is outside the parent, if the snap to grid is enabled, we must find the next step + // with at least x or y inside the parent bounds. + position = findEastOrSouthPreviousLocationSnappedToGridAndInsideParentBounds(parentBounds, borderNodeBounds, gridSpacing); + } + if (position == PositionConstants.NONE) { + if (borderNodeCenter.y > parentBottomRight.y) { + position = PositionConstants.SOUTH; + } else if ((parentBottomRight.x - borderNodeCenter.x) <= (parentBottomRight.y - borderNodeCenter.y)) { + position = PositionConstants.EAST; + } else { + position = PositionConstants.SOUTH; + } + } + } + return position; + } + + /** + * Search the next location in the left and bottom direction where x or y is in the bounds of the parent by + * respecting a step of <code>gridSpacing</code>. If both x and y is in the bounds, PositionConstants.NONE is + * returned: there is no priority. If no location is found, PositionConstants.NONE is also returned: the default + * rules are used. Otherwise, the best side is returned. + * + * @param parentBounds + * The bounds of the parent of the border node + * @param borderNodeBounds + * The bounds of the border node + * @param gridSpacing + * The grid spacing + * @return The best side if any, PositionConstants.NONE otherwise. + */ + private static int findNorthOrWestPreviousLocationSnappedToGridAndInsideParentBounds(Rectangle parentBounds, Rectangle borderNodeBounds, int gridSpacing) { + int position = PositionConstants.NONE; + Point location = borderNodeBounds.getLocation(); + double parentMinX = parentBounds.getLocation().preciseX(); + double parentMaxX = parentMinX + parentBounds.preciseWidth(); + double parentMinY = parentBounds.getLocation().preciseY(); + double parentMaxY = parentMinY + parentBounds.preciseHeight(); + while (!(parentMaxX < location.preciseX() && parentMaxY < location.preciseY()) + && !(isInBounds(location.preciseX(), parentMinX, parentMaxX) || isInBounds(location.preciseY(), parentMinY, parentMaxY))) { + location.translate(getGapForNextGridStep(location.x, gridSpacing), getGapForNextGridStep(location.y, gridSpacing)); + } + if (!location.equals(borderNodeBounds.getLocation())) { + if (isInBounds(location.preciseX(), parentMinX, parentMaxX) && isInBounds(location.preciseY(), parentMinY, parentMaxY)) { + // Both x and y is in bounds no specific location caused by snapToGrid + } else if (isInBounds(location.preciseX(), parentMinX, parentMaxX)) { + position = PositionConstants.NORTH; + } else { + position = PositionConstants.WEST; + } + } + return position; + } + + /** + * Search the next location in the left and top direction where x or y is in the bounds of the parent by respecting + * a step of <code>gridSpacing</code>. If both x and y is in the bounds, PositionConstants.NONE is returned: there + * is no priority. If no location is found, PositionConstants.NONE is also returned: the default rules are used. + * Otherwise, the best side is returned. + * + * @param parentBounds + * The bounds of the parent of the border node + * @param borderNodeBounds + * The bounds of the border node + * @param gridSpacing + * The grid spacing + * @return The best side if any, PositionConstants.NONE otherwise. + */ + private static int findWestOrSouthPreviousLocationSnappedToGridAndInsideParentBounds(Rectangle parentBounds, Rectangle borderNodeBounds, int gridSpacing) { + int position = PositionConstants.NONE; + Point location = borderNodeBounds.getLocation(); + double parentMinX = parentBounds.getLocation().preciseX(); + double parentMaxX = parentMinX + parentBounds.preciseWidth(); + double parentMinY = parentBounds.getLocation().preciseY(); + double parentMaxY = parentMinY + parentBounds.preciseHeight(); + while (!(parentMaxX < location.preciseX() && parentMinY > location.preciseY()) + && !(isInBounds(location.preciseX(), parentMinX, parentMaxX) || isInBounds(location.preciseY(), parentMinY, parentMaxY))) { + location.translate(getGapForNextGridStep(location.x, gridSpacing), -getGapForPreviousGridStep(location.y, gridSpacing)); + } + if (!location.equals(borderNodeBounds.getLocation())) { + if (isInBounds(location.preciseX(), parentMinX, parentMaxX) && isInBounds(location.preciseY(), parentMinY, parentMaxY)) { + // Both x and y is in bounds no specific location caused by snapToGrid + } else if (isInBounds(location.preciseX(), parentMinX, parentMaxX)) { position = PositionConstants.SOUTH; - } else if ((parentBottomRight.x - childCenter.x) <= (parentBottomRight.y - childCenter.y)) { - position = PositionConstants.EAST; } else { + position = PositionConstants.WEST; + } + } + return position; + } + + /** + * Search the next location in the left and top direction where x or y is in the bounds of the parent by respecting + * a step of <code>gridSpacing</code>. If both x and y is in the bounds, PositionConstants.NONE is returned: there + * is no priority. If no location is found, PositionConstants.NONE is also returned: the default rules are used. + * Otherwise, the best side is returned. + * + * @param parentBounds + * The bounds of the parent of the border node + * @param borderNodeBounds + * The bounds of the border node + * @param gridSpacing + * The grid spacing + * @return The best side if any, PositionConstants.NONE otherwise. + */ + private static int findEastOrSouthPreviousLocationSnappedToGridAndInsideParentBounds(Rectangle parentBounds, Rectangle borderNodeBounds, int gridSpacing) { + int position = PositionConstants.NONE; + Point location = borderNodeBounds.getLocation(); + double parentMinX = parentBounds.getLocation().preciseX(); + double parentMaxX = parentMinX + parentBounds.preciseWidth(); + double parentMinY = parentBounds.getLocation().preciseY(); + double parentMaxY = parentMinY + parentBounds.preciseHeight(); + while (!(parentMinX > location.preciseX() && parentMinY > location.preciseY()) + && !(isInBounds(location.preciseX(), parentMinX, parentMaxX) || isInBounds(location.preciseY(), parentMinY, parentMaxY))) { + location.translate(-getGapForPreviousGridStep(location.x, gridSpacing), -getGapForPreviousGridStep(location.y, gridSpacing)); + } + if (!location.equals(borderNodeBounds.getLocation())) { + if (isInBounds(location.preciseX(), parentMinX, parentMaxX) && isInBounds(location.preciseY(), parentMinY, parentMaxY)) { + // Both x and y is in bounds no specific location caused by snapToGrid + } else if (isInBounds(location.preciseX(), parentMinX, parentMaxX)) { position = PositionConstants.SOUTH; + } else { + position = PositionConstants.EAST; + } + } + return position; + } + + /** + * Search the next location in the left and bottom direction where x or y is in the bounds of the parent by + * respecting a step of <code>gridSpacing</code>. If both x and y is in the bounds, PositionConstants.NONE is + * returned: there is no priority. If no location is found, PositionConstants.NONE is also returned: the default + * rules are used. Otherwise, the best side is returned. + * + * @param parentBounds + * The bounds of the parent of the border node + * @param borderNodeBounds + * The bounds of the border node + * @param gridSpacing + * The grid spacing + * @return The best side if any, PositionConstants.NONE otherwise. + */ + private static int findNorthOrEastPreviousLocationSnappedToGridAndInsideParentBounds(Rectangle parentBounds, Rectangle borderNodeBounds, int gridSpacing) { + int position = PositionConstants.NONE; + Point location = borderNodeBounds.getLocation(); + double parentMinX = parentBounds.getLocation().preciseX(); + double parentMaxX = parentMinX + parentBounds.preciseWidth(); + double parentMinY = parentBounds.getLocation().preciseY(); + double parentMaxY = parentMinY + parentBounds.preciseHeight(); + while (!(parentMinX > location.preciseX() && parentMaxY < location.preciseY()) + && !(isInBounds(location.preciseX(), parentMinX, parentMaxX) || isInBounds(location.preciseY(), parentMinY, parentMaxY))) { + location.translate(-getGapForPreviousGridStep(location.x, gridSpacing), -getGapForPreviousGridStep(location.y, gridSpacing)); + } + if (!location.equals(borderNodeBounds.getLocation())) { + if (isInBounds(location.preciseX(), parentMinX, parentMaxX) && isInBounds(location.preciseY(), parentMinY, parentMaxY)) { + // Both x and y is in bounds no specific location caused by snapToGrid + } else if (isInBounds(location.preciseX(), parentMinX, parentMaxX)) { + position = PositionConstants.NORTH; + } else { + position = PositionConstants.EAST; } } return position; } + private static int getGapForNextGridStep(int currentCoordinate, int gridSpacing) { + return getGapForNextGridStep(currentCoordinate, gridSpacing, Integer.MIN_VALUE); + } + + private static int getGapForNextGridStep(int currentCoordinate, int gridSpacing, int levelToPass) { + int remainder = Math.abs(currentCoordinate % gridSpacing); + int gap = gridSpacing - remainder; + if (levelToPass != Integer.MIN_VALUE && currentCoordinate + gap < levelToPass) { + return gap + getGapForNextGridStep(currentCoordinate + gap, gridSpacing, levelToPass); + } + return gap; + } + + private static int getGapForPreviousGridStep(int currentCoordinate, int gridSpacing) { + return getGapForPreviousGridStep(currentCoordinate, gridSpacing, Integer.MIN_VALUE); + } + + private static int getGapForPreviousGridStep(int currentCoordinate, int gridSpacing, int levelToPass) { + int gap = gridSpacing; + int remainder = Math.abs(currentCoordinate % gridSpacing); + if (remainder > 0) { + gap = remainder; + } + if (levelToPass != Integer.MIN_VALUE && currentCoordinate - gap > levelToPass) { + return gap + getGapForPreviousGridStep(currentCoordinate - gap, gridSpacing, levelToPass); + } + return gap; + } + + private static boolean isInBounds(double value, double min, double max) { + return min < value && value < max; + } + private void updateAuthorizedSide(DNode borderNode) { initAuthorizedSides(); DNodeQuery query = new DNodeQuery(borderNode); @@ -370,7 +622,7 @@ public class CanonicalDBorderItemLocator { // If the border item has moved, we change the preferred side, otherwise // we let the current side enabled if (borderItemHasMoved) { - final int closestSide = findClosestSideOfParent(rectSuggested, getParentBorder(), this.authorizedSides); + final int closestSide = findClosestSideOfParent(rectSuggested, getParentBorder(), this.authorizedSides, snapToGrid, gridSpacing); setPreferredSideOfParent(closestSide); setCurrentSideOfParent(closestSide); borderItemHasMoved = false; @@ -427,7 +679,7 @@ public class CanonicalDBorderItemLocator { if (borderItemLayoutConstraint instanceof Bounds) { Dimension extendedDimension = getExtendedDimension(borderItem); - Rectangle borderItemBounds = GMFHelper.getAbsoluteBounds(borderItem); + Rectangle borderItemBounds = GMFHelper.getAbsoluteBounds(borderItem, true); if (extendedDimension != null) { borderItemBounds = PortLayoutHelper.getUncollapseCandidateLocation(extendedDimension, borderItemBounds, getParentBorder()); @@ -485,51 +737,91 @@ public class CanonicalDBorderItemLocator { final int eastX = parentFigureX + parentFigureWidth - getBorderItemOffset().width; final int southY = parentFigureY + parentFigureHeight - getBorderItemOffset().height; final int northY = parentFigureY - borderItemSize.height + getBorderItemOffset().height; - if (suggestedSide == PositionConstants.WEST) { - if (suggestedLocation.x != westX) { + if (suggestedSide == PositionConstants.WEST || suggestedSide == PositionConstants.EAST) { + if (suggestedSide == PositionConstants.WEST && suggestedLocation.x != westX) { newX = westX; - } - if (suggestedLocation.y < parentFigureY) { - newY = parentFigureY; - } else if (suggestedLocation.y > bounds.getBottomLeft().y - borderItemSize.height) { - newY = bounds.getBottomLeft().y - borderItemSize.height; - } - } else if (suggestedSide == PositionConstants.EAST) { - if (suggestedLocation.x != eastX) { + } else if (suggestedSide == PositionConstants.EAST && suggestedLocation.x != eastX) { newX = eastX; } - if (suggestedLocation.y < parentFigureY) { - newY = parentFigureY; - } else if (suggestedLocation.y > bounds.getBottomLeft().y - borderItemSize.height) { - newY = bounds.getBottomLeft().y - borderItemSize.height; - } - } else if (suggestedSide == PositionConstants.SOUTH) { - if (suggestedLocation.y != southY) { - newY = southY; + int nextGap = 0; + int previousGap = 0; + if (snapToGrid) { + nextGap = getGapForNextGridStep(suggestedLocation.y, gridSpacing, parentFigureY); + previousGap = getGapForPreviousGridStep(suggestedLocation.y, gridSpacing, bounds.getBottomRight().y - borderItemSize.height); + if (suggestedLocation.y % gridSpacing != 0) { + // If the suggested location is not on the grid, we align it. + if (previousGap < nextGap) { + newY = suggestedLocation.y - previousGap; + } else { + newY = suggestedLocation.y + nextGap; + } + } } if (borderItemSize.width > bounds.width) { - // The border item width is larger than the parent item. In that - // case, we will center the border item on the south side of the - // parent. - newX = parentFigureX - (borderItemSize.width - bounds.width) / 2; - } else if (suggestedLocation.x < parentFigureX) { - newX = parentFigureX; - } else if (suggestedLocation.x > bounds.getBottomRight().x - borderItemSize.width) { - newX = bounds.getBottomRight().x - borderItemSize.width; + // The border item width is higher than the parent item. In that + // case, we will center the border item on this side. + newY = parentFigureY - (borderItemSize.height - bounds.height) / 2; + } else if (newY < parentFigureY) { + if (snapToGrid) { + newY = suggestedLocation.y + nextGap; + if (newY > bounds.getBottomLeft().y - borderItemSize.height) { + newY = parentFigureY; + } + } else { + newY = parentFigureY; + } + } else if (newY > bounds.getBottomLeft().y - borderItemSize.height) { + if (snapToGrid) { + newY = suggestedLocation.y - previousGap; + if (newY < parentFigureY) { + newY = bounds.getBottomLeft().y - borderItemSize.height; + } + } else { + newY = bounds.getBottomLeft().y - borderItemSize.height; + } } - } else { // NORTH - if (suggestedLocation.y != northY) { + } else if (suggestedSide == PositionConstants.SOUTH || suggestedSide == PositionConstants.NORTH) { + if (suggestedSide == PositionConstants.SOUTH && suggestedLocation.y != southY) { + newY = southY; + } else if (suggestedSide == PositionConstants.NORTH && suggestedLocation.y != northY) { newY = northY; } + int nextGap = 0; + int previousGap = 0; + if (snapToGrid) { + nextGap = getGapForNextGridStep(suggestedLocation.x, gridSpacing, parentFigureX); + previousGap = getGapForPreviousGridStep(suggestedLocation.x, gridSpacing, bounds.getBottomRight().x - borderItemSize.width); + if (suggestedLocation.x % gridSpacing != 0) { + // If the suggested location is not on the grid, we align it. + if (previousGap < nextGap) { + newX = suggestedLocation.x - previousGap; + } else { + newX = suggestedLocation.x + nextGap; + } + } + } if (borderItemSize.width > bounds.width) { // The border item width is larger than the parent item. In that - // case, we will center the border item on the north side of the - // parent. + // case, we will center the border item on this side. newX = parentFigureX - (borderItemSize.width - bounds.width) / 2; - } else if (suggestedLocation.x < parentFigureX) { - newX = parentFigureX; - } else if (suggestedLocation.x > bounds.getBottomRight().x - borderItemSize.width) { - newX = bounds.getBottomRight().x - borderItemSize.width; + } else if (newX < parentFigureX) { + if (snapToGrid) { + newX = suggestedLocation.x + nextGap; + if (newX > bounds.getBottomRight().x - borderItemSize.width) { + newX = parentFigureX; + } + } else { + newX = parentFigureX; + } + } else if (newX > bounds.getBottomRight().x - borderItemSize.width) { + if (snapToGrid) { + newX = suggestedLocation.x - previousGap; + if (newX < parentFigureX) { + newX = bounds.getBottomRight().x - borderItemSize.width; + } + } else { + newX = bounds.getBottomRight().x - borderItemSize.width; + } } } return new Point(newX, newY); @@ -579,6 +871,9 @@ public class CanonicalDBorderItemLocator { lastOptionalConflictingRectangleOnSameSide = optionalConflictingRectangle; } rightHorizontalGap = (optionalConflictingRectangle.get().x + optionalConflictingRectangle.get().width + 1) - rightTestPoint.x; + if (snapToGrid) { + rightHorizontalGap = Math.max(rightHorizontalGap, getGapForNextGridStep(rightTestPoint.x)); + } if (rightTestPoint.x + rightHorizontalGap + borderItemSize.width > getParentBorder().getBottomRight().x) { isStillFreeSpaceToTheRight = false; } @@ -597,6 +892,9 @@ public class CanonicalDBorderItemLocator { lastOptionalConflictingRectangleOnSameSide = optionalConflictingRectangle; } leftHorizontalGap = leftTestPoint.x - (optionalConflictingRectangle.get().x - borderItemSize.width - 1); + if (snapToGrid) { + leftHorizontalGap = Math.max(leftHorizontalGap, getGapForPreviousGridStep(leftTestPoint.x)); + } if (leftTestPoint.x - leftHorizontalGap < getParentBorder().getTopLeft().x) { isStillFreeSpaceToTheLeft = false; } @@ -618,7 +916,11 @@ public class CanonicalDBorderItemLocator { // We only compute the new recommended location for the next // side (following the anticlockwise) if it is authorized. else if (next == PositionConstants.EAST) { - recommendedLocationForNextSide = new Point(rightTestPoint.x + rightHorizontalGap, optionalConflictingRectangle.get().y - borderItemSize.height - 1); + int nextYLocation = optionalConflictingRectangle.get().y - borderItemSize.height - 1; + if (snapToGrid) { + nextYLocation = Math.min(nextYLocation, rightTestPoint.y - getGapForPreviousGridStep(rightTestPoint.y)); + } + recommendedLocationForNextSide = new Point(rightTestPoint.x + rightHorizontalGap, nextYLocation); } } } @@ -673,6 +975,9 @@ public class CanonicalDBorderItemLocator { lastOptionalConflictingRectangleOnSameSide = optionalConflictingRectangle; } rightHorizontalGap = (optionalConflictingRectangle.get().x + optionalConflictingRectangle.get().width + 1) - rightTestPoint.x; + if (snapToGrid) { + rightHorizontalGap = Math.max(rightHorizontalGap, getGapForNextGridStep(rightTestPoint.x)); + } if (rightTestPoint.x + rightHorizontalGap + borderItemSize.width > getParentBorder().getBottomRight().x) { isStillFreeSpaceToTheRight = false; } @@ -691,6 +996,9 @@ public class CanonicalDBorderItemLocator { lastOptionalConflictingRectangleOnSameSide = optionalConflictingRectangle; } leftHorizontalGap = leftTestPoint.x - (optionalConflictingRectangle.get().x - borderItemSize.width - 1); + if (snapToGrid) { + leftHorizontalGap = Math.max(leftHorizontalGap, getGapForPreviousGridStep(leftTestPoint.x)); + } if (leftTestPoint.x - leftHorizontalGap < getParentBorder().getTopLeft().x) { isStillFreeSpaceToTheLeft = false; } @@ -712,7 +1020,11 @@ public class CanonicalDBorderItemLocator { // We only compute the new recommended location for the next // side (following the anticlockwise) if it is authorized. else if (next == PositionConstants.WEST) { - recommendedLocationForNextSide = new Point(leftTestPoint.x - leftHorizontalGap, optionalConflictingRectangle.get().y + optionalConflictingRectangle.get().height + 1); + int nextYLocation = optionalConflictingRectangle.get().y + optionalConflictingRectangle.get().height + 1; + if (snapToGrid) { + nextYLocation = Math.max(nextYLocation, leftTestPoint.y + getGapForNextGridStep(leftTestPoint.y)); + } + recommendedLocationForNextSide = new Point(leftTestPoint.x - leftHorizontalGap, nextYLocation); } } } @@ -767,6 +1079,9 @@ public class CanonicalDBorderItemLocator { lastOptionalConflictingRectangleOnSameSide = optionalConflictingRectangle; } belowVerticalGap = optionalConflictingRectangle.get().y + optionalConflictingRectangle.get().height - belowTestPoint.y + 1; + if (snapToGrid) { + belowVerticalGap = Math.max(belowVerticalGap, getGapForNextGridStep(belowTestPoint.y)); + } if (belowTestPoint.y + belowVerticalGap + borderItemSize.height > getParentBorder().getBottomLeft().y) { isStillFreeSpaceBelow = false; } @@ -785,6 +1100,9 @@ public class CanonicalDBorderItemLocator { lastOptionalConflictingRectangleOnSameSide = optionalConflictingRectangle; } aboveVerticalGap = aboveTestPoint.y - (optionalConflictingRectangle.get().y - borderItemSize.height - 1); + if (snapToGrid) { + aboveVerticalGap = Math.max(aboveVerticalGap, getGapForPreviousGridStep(aboveTestPoint.y)); + } if (aboveTestPoint.y - aboveVerticalGap < getParentBorder().getTopRight().y) { isStillFreeSpaceAbove = false; } @@ -806,7 +1124,12 @@ public class CanonicalDBorderItemLocator { // We only compute the new recommended location for the next // side (following the anticlockwise) if it is authorized. else if (next == PositionConstants.SOUTH) { - recommendedLocationForNextSide = new Point(belowTestPoint.x + optionalConflictingRectangle.get().width + 1, belowTestPoint.y + belowVerticalGap); + int nextXLocation = belowTestPoint.x + optionalConflictingRectangle.get().width + 1; + if (snapToGrid) { + nextXLocation = Math.max(nextXLocation, belowTestPoint.x + getGapForNextGridStep(belowTestPoint.x)); + } + recommendedLocationForNextSide = new Point(nextXLocation, belowTestPoint.y + belowVerticalGap); + } } } @@ -861,6 +1184,9 @@ public class CanonicalDBorderItemLocator { lastOptionalConflictingRectangleOnSameSide = optionalConflictingRectangle; } belowVerticalGap = optionalConflictingRectangle.get().y + optionalConflictingRectangle.get().height - belowTestPoint.y + 1; + if (snapToGrid) { + belowVerticalGap = Math.max(belowVerticalGap, getGapForNextGridStep(belowTestPoint.y)); + } if (belowTestPoint.y + belowVerticalGap + borderItemSize.height > getParentBorder().getBottomLeft().y) { isStillFreeSpaceBelow = false; } @@ -879,6 +1205,9 @@ public class CanonicalDBorderItemLocator { lastOptionalConflictingRectangleOnSameSide = optionalConflictingRectangle; } aboveVerticalGap = aboveTestPoint.y - (optionalConflictingRectangle.get().y - borderItemSize.height - 1); + if (snapToGrid) { + aboveVerticalGap = Math.max(aboveVerticalGap, getGapForPreviousGridStep(aboveTestPoint.y)); + } if (aboveTestPoint.y - aboveVerticalGap < getParentBorder().getTopRight().y) { isStillFreeSpaceAbove = false; } @@ -899,8 +1228,12 @@ public class CanonicalDBorderItemLocator { } // We only compute the new recommended location for the next // side (following the anticlockwise) if it is authorized. - else if (next == PositionConstants.SOUTH) { - recommendedLocationForNextSide = new Point(optionalConflictingRectangle.get().x - borderItemSize.width - 1, aboveTestPoint.y - aboveVerticalGap); + else if (next == PositionConstants.NORTH) { + int nextXLocation = optionalConflictingRectangle.get().x - borderItemSize.width - 1; + if (snapToGrid) { + nextXLocation = Math.min(nextXLocation, aboveTestPoint.x - getGapForPreviousGridStep(aboveTestPoint.x)); + } + recommendedLocationForNextSide = new Point(nextXLocation, aboveTestPoint.y - aboveVerticalGap); } } } @@ -1007,7 +1340,7 @@ public class CanonicalDBorderItemLocator { } } - final int side = findClosestSideOfParent(proposedBounds, getParentBorder(), this.authorizedSides); + final int side = findClosestSideOfParent(proposedBounds, getParentBorder(), this.authorizedSides, snapToGrid, gridSpacing); Point newTopLeft = locateOnBorder(realBounds, side, NB_SIDES - getNumberOfAuthorizedSides(), borderItem, portsNodesToIgnore); if (isCollapsed) { setBorderItemOffset(oldOffset); @@ -1042,9 +1375,7 @@ public class CanonicalDBorderItemLocator { // recursively. nextAuthorized = getNextAuthorizedSide(nextSide, initialSide); } - return nextAuthorized; - } private int getNextSide(int current) { @@ -1071,4 +1402,12 @@ public class CanonicalDBorderItemLocator { private int getNumberOfAuthorizedSides() { return this.authorizedSides.cardinality(); } + + private int getGapForNextGridStep(int currentCoordinate) { + return CanonicalDBorderItemLocator.getGapForNextGridStep(currentCoordinate, gridSpacing); + } + + private int getGapForPreviousGridStep(int currentCoordinate) { + return CanonicalDBorderItemLocator.getGapForPreviousGridStep(currentCoordinate, gridSpacing); + } } diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/diagram/DDiagramCanonicalSynchronizer.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/diagram/DDiagramCanonicalSynchronizer.java index 88743ea427..22b4af7850 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/diagram/DDiagramCanonicalSynchronizer.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/diagram/DDiagramCanonicalSynchronizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2016 THALES GLOBAL SERVICES and others. + * Copyright (c) 2011, 2017 THALES GLOBAL SERVICES and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -20,6 +20,7 @@ import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Optional; import java.util.Set; import org.eclipse.emf.common.command.Command; @@ -28,13 +29,25 @@ import org.eclipse.emf.common.util.AbstractTreeIterator; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.transaction.RunnableWithResult; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; +import org.eclipse.gef.rulers.RulerProvider; +import org.eclipse.gmf.runtime.common.ui.services.editor.EditorService; +import org.eclipse.gmf.runtime.common.ui.util.DisplayUtils; +import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; +import org.eclipse.gmf.runtime.diagram.ui.internal.properties.WorkspaceViewerProperties; +import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor; +import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer; +import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer; +import org.eclipse.gmf.runtime.diagram.ui.util.MeasurementUnitHelper; +import org.eclipse.gmf.runtime.draw2d.ui.mapmode.IMapMode; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.gmf.runtime.notation.View; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.sirius.diagram.CollapseFilter; import org.eclipse.sirius.diagram.DDiagram; import org.eclipse.sirius.diagram.DDiagramElement; @@ -53,6 +66,8 @@ import org.eclipse.sirius.diagram.ui.part.SiriusLinkDescriptor; import org.eclipse.sirius.diagram.ui.part.SiriusVisualIDRegistry; import org.eclipse.sirius.ext.base.Options; import org.eclipse.sirius.viewpoint.description.AnnotationEntry; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Display; import com.google.common.base.Predicate; import com.google.common.base.Predicates; @@ -68,6 +83,7 @@ import com.google.common.collect.Sets; * * @since 0.9.0 */ +@SuppressWarnings("restriction") public class DDiagramCanonicalSynchronizer extends AbstractCanonicalSynchronizer { /** @@ -91,6 +107,76 @@ public class DDiagramCanonicalSynchronizer extends AbstractCanonicalSynchronizer super(); this.gmfDiagram = gmfDiagram; this.connectionsFactory = new ConnectionsFactory(gmfDiagram, viewpointViewProvider); + // Search if it possible to get snapToGrid and gridSpacing values from the store associated to an opened editor. + loadPreferencesFromOpenedDiagram(ViewUtil.getIdStr(gmfDiagram)); + } + + /** + * Load the preferences from an opened diagram that has the given guid.<BR> + * Inspired from + * {@link org.eclipse.sirius.diagram.ui.tools.internal.print.SiriusDiagramPrintPreviewHelper#loadPreferencesFromOpenDiagram(String)}. + * + * @param id + * guid of the opened diagram to load the preferences for + */ + private void loadPreferencesFromOpenedDiagram(String id) { + List<? extends Object> diagramEditors = EditorService.getInstance().getRegisteredEditorParts(); + @SuppressWarnings("unchecked") + Optional<DiagramEditor> diagramEditor = (Optional<DiagramEditor>) diagramEditors.stream().filter( + de -> de instanceof DiagramEditor && ((DiagramEditor) de).getDiagramEditPart() != null && id.equals(ViewUtil.getIdStr(((DiagramEditor) de).getDiagramEditPart().getDiagramView()))) + .findFirst(); + if (diagramEditor.isPresent()) { + IDiagramGraphicalViewer viewer = diagramEditor.get().getDiagramGraphicalViewer(); + if (viewer instanceof DiagramGraphicalViewer) { + DiagramGraphicalViewer diagramGraphicalViewer = (DiagramGraphicalViewer) viewer; + // Load preferences + IPreferenceStore store = diagramGraphicalViewer.getWorkspaceViewerPreferenceStore(); + setSnapToGrid(store.getBoolean(WorkspaceViewerProperties.SNAPTOGRID)); + setGridSpacing(convertGridSpacingInPixels(store.getDouble(WorkspaceViewerProperties.GRIDSPACING), store.getInt(WorkspaceViewerProperties.RULERUNIT), + MeasurementUnitHelper.getMapMode(gmfDiagram.getMeasurementUnit()))); + } + } + } + + /** + * This conversion method is inspired from + * {@link org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart#setGridSpacing(double)}. + * + * @param gridSpacing + * The current grid spacing respecting the ruler units. + * @param rulerUnits + * The ruler units. + * @return The grid spacing in pixels. + */ + private int convertGridSpacingInPixels(double gridSpacing, int rulerUnits, IMapMode mapMode) { + // Get the Displays DPIs + final Display display = DisplayUtils.getDisplay(); + final RunnableWithResult<Point> runnable = new RunnableWithResult.Impl<Point>() { + @Override + public void run() { + setResult(display.getDPI()); + } + }; + display.syncExec(runnable); + double dotsPerInch = runnable.getResult().x; + int spacingInPixels = 0; + + // Evaluate the Grid Spacing based on the ruler units + switch (rulerUnits) { + case RulerProvider.UNIT_INCHES: + spacingInPixels = (int) Math.round(dotsPerInch * gridSpacing); + break; + + case RulerProvider.UNIT_CENTIMETERS: + spacingInPixels = (int) Math.round(dotsPerInch * gridSpacing / 2.54); + break; + + default: + spacingInPixels = (int) gridSpacing; + } + + int spacing = mapMode.DPtoLP(spacingInPixels); + return spacing; } /** |
