diff options
| author | Laurent Redor | 2015-08-24 12:20:44 +0000 |
|---|---|---|
| committer | Laurent Redor | 2015-08-25 12:45:34 +0000 |
| commit | 22a545643fcb6b6306405803b2d2f8c22ed7ca25 (patch) | |
| tree | ac4fc5be2cd073a7e4a875b9218eb2a26e2c87a2 | |
| parent | b22416bcb1bd3a670fd44b629a1e5a2a4bdd67da (diff) | |
| download | org.eclipse.sirius-22a545643fcb6b6306405803b2d2f8c22ed7ca25.tar.gz org.eclipse.sirius-22a545643fcb6b6306405803b2d2f8c22ed7ca25.tar.xz org.eclipse.sirius-22a545643fcb6b6306405803b2d2f8c22ed7ca25.zip | |
[474688] Handle case of segment inverted
Segment inverted == a node is moved along a segment so that segment is
inverted (origin of segment at right side became origin at left side or
the contrary)
The SetConnectionBendpointsAccordingToExtremityMoveCommmand now handles
correctly this case.
Bug: 474688
Change-Id: I9b69b8228873c6965f264c5d3a922d400eb4e8cb
Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
2 files changed, 267 insertions, 57 deletions
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SetConnectionBendpointsAccordingToExtremityMoveCommmand.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SetConnectionBendpointsAccordingToExtremityMoveCommmand.java index a7e190e3d8..50a66cc1bd 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SetConnectionBendpointsAccordingToExtremityMoveCommmand.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/SetConnectionBendpointsAccordingToExtremityMoveCommmand.java @@ -299,9 +299,9 @@ public class SetConnectionBendpointsAccordingToExtremityMoveCommmand extends Set for (int i = 0; i < newLine.size() && sourcePointList.polygonContainsPoint(newLine.getPoint(i).x, newLine.getPoint(i).y); i++) { nbIncludedPoints++; } - // Do nothing if there is only one point inside. This is the first - // point that is on the border. - if (nbIncludedPoints > 1) { + // Do nothing if there is only one point inside and no other + // intersection. This is the first point that is on the border. + if (nbIncludedPoints > 1 || (nbIncludedPoints == 1 && newLine.size() > 1 && isAnotherIntersection(newLine.getFirstPoint(), newLine.getPoint(1), sourcePointList))) { for (int i = 0; i < nbIncludedPoints; i++) { lastRemovedFromSource = newLine.removePoint(0); } @@ -320,9 +320,9 @@ public class SetConnectionBendpointsAccordingToExtremityMoveCommmand extends Set for (int i = newLine.size() - 1; i > 0 && targetPointList.polygonContainsPoint(newLine.getPoint(i).x, newLine.getPoint(i).y); i--) { nbIncludedPoints++; } - // Do nothing if there is only one point inside. This is the last - // point that is on the border. - if (nbIncludedPoints > 1) { + // Do nothing if there is only one point inside and no other + // intersection. This is the last point that is on the border. + if (nbIncludedPoints > 1 || (nbIncludedPoints == 1 && newLine.size() > 1 && isAnotherIntersection(newLine.getLastPoint(), newLine.getPoint(newLine.size() - 2), targetPointList))) { for (int i = 0; i < nbIncludedPoints; i++) { lastRemovedFromTarget = newLine.removePoint(newLine.size() - 1); } @@ -332,9 +332,9 @@ public class SetConnectionBendpointsAccordingToExtremityMoveCommmand extends Set /* * Handle the special case of all points removed from polyline. */ + Dimension tolerance = new Dimension(1, 0); + int toleranceValue = tolerance.width; if (newLine.size() == 0) { - Dimension tolerance = new Dimension(1, 0); - int toleranceValue = tolerance.width; if (lastRemovedFromSource == null) { lastRemovedFromSource = start; } @@ -369,12 +369,13 @@ public class SetConnectionBendpointsAccordingToExtremityMoveCommmand extends Set // Add necessary point to complete the first (or last) segment if // points have been removed from source (or target). if (lastRemovedFromSource != null) { - Option<Point> optionalIntersection = GraphicalHelper.getIntersection(lastRemovedFromSource, newLine.getFirstPoint(), source, true); + Option<Point> optionalIntersection = getComplementaryPoint(newLine, source, lastRemovedFromSource, newLine.getFirstPoint(), toleranceValue); if (optionalIntersection.some()) { newLine.insertPoint(optionalIntersection.get(), 0); } - } else if (lastRemovedFromTarget != null) { - Option<Point> optionalIntersection = GraphicalHelper.getIntersection(lastRemovedFromTarget, newLine.getLastPoint(), target, false); + } + if (lastRemovedFromTarget != null) { + Option<Point> optionalIntersection = getComplementaryPoint(newLine, target, lastRemovedFromTarget, newLine.getLastPoint(), toleranceValue); if (optionalIntersection.some()) { newLine.addPoint(optionalIntersection.get()); } @@ -383,6 +384,55 @@ public class SetConnectionBendpointsAccordingToExtremityMoveCommmand extends Set } /** + * Get a complementary point to go from the <code>otherPointExtremity</code> + * to the <code>nodeBouds</code> through <code>lastRemoved</code> point. + * + * @param pointsList + * Current points of the edge + * @param nodeBouds + * Bounds of the node to connect + * @param lastRemoved + * Last removed point from the points list of the edge + * @param otherPointExtremity + * First/Last point from the points list of the edge (on the same + * side as <code>lastRemoved</code>) + * @param toleranceValue + * A tolerance. + * @return An optional point corresponding to the intersection between a + * line from <code>otherPointExtremity</code> to + * <code>lastRemoved</code> and <code>nodeBouds</code>. + */ + private static Option<Point> getComplementaryPoint(PointList pointsList, PrecisionRectangle nodeBouds, Point lastRemoved, Point otherPointExtremity, int toleranceValue) { + Option<Point> optionalIntersection; + if (Math.abs(lastRemoved.x - otherPointExtremity.x) < toleranceValue) { + // Vertical + if (lastRemoved.preciseY() < otherPointExtremity.preciseY()) { + optionalIntersection = GraphicalHelper.getIntersection(lastRemoved, otherPointExtremity, nodeBouds, false); + } else { + optionalIntersection = GraphicalHelper.getIntersection(otherPointExtremity, lastRemoved, nodeBouds, true); + } + } else { + // Horizontal + if (lastRemoved.preciseX() < otherPointExtremity.preciseX()) { + optionalIntersection = GraphicalHelper.getIntersection(lastRemoved, otherPointExtremity, nodeBouds, false); + } else { + optionalIntersection = GraphicalHelper.getIntersection(otherPointExtremity, lastRemoved, nodeBouds, true); + } + } + return optionalIntersection; + } + + private static boolean isAnotherIntersection(Point origin, Point terminus, PointList pointList) { + PointList line = new PointList(); + line.addPoint(origin); + line.addPoint(terminus); + PointList distances = new PointList(); + PointList intersections = new PointList(); + PointListUtilities.findIntersections(line, pointList, intersections, distances); + return intersections.size() > 1; + } + + /** * Set if the source is moved, or if the target is moved. * * @param sourceMove diff --git a/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/BendpointsStabilityOnMovesSpecificCasesTest.java b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/BendpointsStabilityOnMovesSpecificCasesTest.java index 254405b306..a9e3a7f8cb 100644 --- a/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/BendpointsStabilityOnMovesSpecificCasesTest.java +++ b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/BendpointsStabilityOnMovesSpecificCasesTest.java @@ -37,6 +37,8 @@ import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; +import com.google.common.base.Function; + /** * This class is complementary to {@link BendpointsStabilityOnMovesTest} but * with specific cases detected after. @@ -59,6 +61,91 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS boolean isPropertiesViewOpened; + /** + * Function to check if a point is at the expected location. The + * {@link #setData(Point, Point, Rectangle)} method must be called before + * calling {@link #apply(Point)} method.<BR> + * If the {@link #apply(Point)} method return false, the method + * {@link #getErrorMessage()} can be called to display the corresponding + * error message.<BR> + * The methods {@link #apply(Point)}, {@link #getErrorMessage()}, and/or + * {@link #getExpectedPoint()} can be override to handle specific cases. + * + * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a> + */ + public class AssertPointLocationFunction implements Function<Point, Boolean> { + /** Original point from which to find the expected one. */ + protected Point originalPoint; + + /** The delta of the move. */ + protected Point moveDelta; + + /** + * Another point (3rd for first point and n-3 for the last point) to + * retrieve other axis in case of segment merge. + */ + protected Point previousMergedPoint; + + /** The bounds of the moved node (before move). */ + protected Rectangle movedNodeBounds; + + /** Store the last input to use it in the {@link #getErrorMessage()}. */ + protected Point lastInputUsedForThisFunction; + + /** + * Default constructor. + * + * @param moveDelta + * The delta of the move. + */ + public AssertPointLocationFunction(Point moveDelta) { + this.moveDelta = moveDelta; + } + + /** + * + * @param originalPoint + * Original point from which to find the expected one. + * @param previousMergedPoint + * Another point (3rd for first point and n-3 for the last + * point) to retrieve other axis in case of segment merge. + * @param movedNodeBounds + * The bounds of the moved node (before move) + */ + public void setData(Point originalPoint, Point previousMergedPoint, Rectangle movedNodeBounds) { + this.originalPoint = originalPoint; + this.previousMergedPoint = previousMergedPoint; + this.movedNodeBounds = movedNodeBounds; + } + + @Override + public Boolean apply(Point input) { + if (originalPoint != null && previousMergedPoint != null) { + lastInputUsedForThisFunction = input; + return lastInputUsedForThisFunction.equals(getExpectedPoint()); + } else { + return false; + } + } + + /** + * @return The expected point according to data. + */ + public Point getExpectedPoint() { + return originalPoint.getTranslated(moveDelta); + } + + /** + * Must be called only in case of failing of {@link #apply(Point)} + * method. This method returns the message to display. + * + * @return the message to display. + */ + public String getErrorMessage() { + return "Point should have moved at the expected location. Expected:<" + getExpectedPoint() + "> but was:<" + lastInputUsedForThisFunction + ">"; + } + } + @Override protected void onSetUpBeforeClosingWelcomePage() throws Exception { copyFileToTestProject(Activator.PLUGIN_ID, DATA_UNIT_DIR, MODEL, SESSION_FILE); @@ -119,7 +206,9 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS * points are consistency. */ public void testFirstPointConsistency() { - testFirstPointConsistency(new Point(20, 20), false, false); + final Point moveDelta = new Point(20, 20); + AssertPointLocationFunction assertPointLocationFunction = new AssertPointLocationFunction(moveDelta); + testFirstPointConsistency(moveDelta, 0, assertPointLocationFunction); } /** @@ -128,7 +217,28 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS * the second one. */ public void testFirstPointConsistencyWithMergeSegment() { - testFirstPointConsistency(new Point(0, 99), true, false); + final Point moveDelta = new Point(0, 99); + AssertPointLocationFunction assertPointLocationFunction = new AssertPointLocationFunction(moveDelta) { + Point otherExpectedPoint; + + @Override + public Boolean apply(Point input) { + if (originalPoint != null && previousMergedPoint != null) { + Point lastInputUsedForThisFunction = input; + Point expectedPoint = originalPoint.getTranslated(moveDelta); + otherExpectedPoint = new Point(expectedPoint.x, previousMergedPoint.y); + return lastInputUsedForThisFunction.equals(expectedPoint) || lastInputUsedForThisFunction.equals(otherExpectedPoint); + } else { + return false; + } + } + + @Override + public String getErrorMessage() { + return "First point should have moved at the expected location. Expected:<" + getExpectedPoint() + "or " + otherExpectedPoint + "> but was:<" + lastInputUsedForThisFunction + ">"; + } + }; + testFirstPointConsistency(moveDelta, -2, assertPointLocationFunction); } /** @@ -136,7 +246,29 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS * points are consistency (when the first segment is removed). */ public void testFirstPointConsistencyWithFirstSegmentRemoval() { - testFirstPointConsistency(new Point(60, 20), false, true); + final Point moveDelta = new Point(60, 20); + AssertPointLocationFunction assertPointLocationFunction = new AssertPointLocationFunction(moveDelta) { + @Override + public Point getExpectedPoint() { + return new Point(previousMergedPoint.x, movedNodeBounds.getTranslated(moveDelta).getBottom().y); + } + }; + testFirstPointConsistency(moveDelta, -1, assertPointLocationFunction); + } + + /** + * Test that first point is moved has expected and that draw2d and GMF last + * points are consistency (when the first segment is inverted). + */ + public void testFirstPointConsistencyWithFirstSegmentInverted() { + final Point moveDelta = new Point(340, 0); + AssertPointLocationFunction assertPointLocationFunction = new AssertPointLocationFunction(moveDelta) { + @Override + public Point getExpectedPoint() { + return originalPoint.getTranslated(moveDelta).getTranslated(new Point(-movedNodeBounds.width(), 0)); + } + }; + testFirstPointConsistency(moveDelta, 0, assertPointLocationFunction); } /** @@ -144,7 +276,9 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS * points are consistency. */ public void testLastPointConsistency() { - testLastPointConsistency(new Point(-20, 50), false, false); + Point moveDelta = new Point(-20, 50); + AssertPointLocationFunction assertPointLocationFunction = new AssertPointLocationFunction(moveDelta); + testLastPointConsistency(moveDelta, 0, assertPointLocationFunction); } /** @@ -153,7 +287,28 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS * previous one. */ public void testLastPointConsistencyWithMergeSegment() { - testLastPointConsistency(new Point(0, -139), true, false); + Point moveDelta = new Point(0, -139); + AssertPointLocationFunction assertPointLocationFunction = new AssertPointLocationFunction(moveDelta) { + Point otherExpectedPoint; + + @Override + public Boolean apply(Point input) { + if (originalPoint != null && previousMergedPoint != null) { + Point lastInputUsedForThisFunction = input; + Point expectedPoint = originalPoint.getTranslated(moveDelta); + otherExpectedPoint = new Point(expectedPoint.x, previousMergedPoint.y); + return lastInputUsedForThisFunction.equals(expectedPoint) || lastInputUsedForThisFunction.equals(otherExpectedPoint); + } else { + return false; + } + } + + @Override + public String getErrorMessage() { + return "Last point should have moved at the expected location. Expected:<" + getExpectedPoint() + "or " + otherExpectedPoint + "> but was:<" + lastInputUsedForThisFunction + ">"; + } + }; + testLastPointConsistency(moveDelta, -2, assertPointLocationFunction); } /** @@ -161,7 +316,29 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS * points are consistency (when the last segment is removed). */ public void testLastPointConsistencyWithLastSegmentRemoval() { - testLastPointConsistency(new Point(-120, 50), false, true); + final Point moveDelta = new Point(-120, 50); + AssertPointLocationFunction assertPointLocationFunction = new AssertPointLocationFunction(moveDelta) { + @Override + public Point getExpectedPoint() { + return new Point(previousMergedPoint.x, movedNodeBounds.getTranslated(moveDelta).y); + } + }; + testLastPointConsistency(moveDelta, -1, assertPointLocationFunction); + } + + /** + * Test that last point is moved has expected and that draw2d and GMF last + * points are consistency (when the last segment is inverted). + */ + public void testLastPointConsistencyWithLastSegmentInverted() { + final Point moveDelta = new Point(-340, 0); + AssertPointLocationFunction assertPointLocationFunction = new AssertPointLocationFunction(moveDelta) { + @Override + public Point getExpectedPoint() { + return originalPoint.getTranslated(moveDelta).getTranslated(new Point(movedNodeBounds.width(), 0)); + } + }; + testLastPointConsistency(moveDelta, 0, assertPointLocationFunction); } /** @@ -170,15 +347,14 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS * * @param moveDelta * The delta from which the source node will be moved - * @param segmentMerged - * true if the corresponding segment is merged with the next one - * (2 points less and segments normalize and straight), false - * otherwise. Exclusive with segmentRemoved. - * @param segmentRemoved - * true if the corresponding segment is removed (absorbed by the - * moved node), false otherwise. Exclusive with segmentMerged. + * @param nbGMFPointsDelta + * Number of GMF points that are added (or removed) after the + * move. + * @param assertPointLocationFunction + * the function to use to check the expected last point location + * after move */ - protected void testLastPointConsistency(Point moveDelta, boolean segmentMerged, boolean segmentRemoved) { + private void testLastPointConsistency(Point moveDelta, int nbGMFPointsDelta, AssertPointLocationFunction assertPointLocationFunction) { String nodeToMoveName = "C2"; editor.reveal(nodeToMoveName); // Step 2: store the previous bendpoints @@ -195,7 +371,8 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS bot.waitUntil(editPartMovedCondition); assertEquals("Drag as failed: selection should be the same before and after drag.", editPartToMove, editor.selectedEditParts().get(0)); // Step 4: Check bendpoints - compareActualBendpointsWithExpected(editor, connectionEditPart, previousPoints, moveDelta, nodeBounds, false, segmentMerged, segmentRemoved); + assertPointLocationFunction.setData(previousPoints.getLastPoint(), previousPoints.getPoint(previousPoints.size() - 3), nodeBounds); + compareActualBendpointsWithExpected(editor, connectionEditPart, previousPoints, moveDelta, nodeBounds, false, nbGMFPointsDelta, assertPointLocationFunction); } /** @@ -204,15 +381,14 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS * * @param moveDelta * The delta from which the source node will be moved - * @param segmentMerged - * true if the corresponding segment is merged with the next one - * (2 points less and segments normalize and straight), false - * otherwise. Exclusive with segmentRemoved. - * @param segmentRemoved - * true if the corresponding segment is removed (absorbed by the - * moved node), false otherwise. Exclusive with segmentMerged. + * @param nbGMFPointsDelta + * Number of GMF points that are added (or removed) after the + * move. + * @param assertPointLocationFunction + * the function to use to check the expected last point location + * after move */ - protected void testFirstPointConsistency(Point moveDelta, boolean segmentMerged, boolean segmentRemoved) { + private void testFirstPointConsistency(Point moveDelta, int nbGMFPointsDelta, AssertPointLocationFunction assertPointLocationFunction) { String nodeToMoveName = "C1"; editor.reveal(nodeToMoveName); // Step 2: store the previous bendpoints @@ -229,53 +405,37 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS bot.waitUntil(editPartMovedCondition); assertEquals("Drag as failed: selection should be the same before and after drag.", editPartToMove, editor.selectedEditParts().get(0)); // Step 4: Check bendpoints - compareActualBendpointsWithExpected(editor, connectionEditPart, previousPoints, moveDelta, nodeBounds, true, segmentMerged, segmentRemoved); + assertPointLocationFunction.setData(previousPoints.getFirstPoint(), previousPoints.getPoint(2), nodeBounds); + compareActualBendpointsWithExpected(editor, connectionEditPart, previousPoints, moveDelta, nodeBounds, true, nbGMFPointsDelta, assertPointLocationFunction); } // Check the first or last bendpoint of the connection. private void compareActualBendpointsWithExpected(SWTBotSiriusDiagramEditor diagramEditor, SWTBotGefConnectionEditPart connectionEditPart, PointList previousPoints, Point moveDelta, - Rectangle movedNodeBounds, boolean firstPoint, boolean segmentMerged, boolean segmentRemoved) { + Rectangle movedNodeBounds, boolean firstPoint, int nbGMFPointsDelta, AssertPointLocationFunction assertPointLocationFunction) { List<Point> newGMFBendpointsFromSource = GMFHelper.getPointsFromSource(connectionEditPart.part()); String messagePrefix = "First"; if (!firstPoint) { messagePrefix = "Last"; } - if (segmentMerged) { - assertEquals(messagePrefix + " segment must me merged. We should have 2 GMF points less.", previousPoints.size() - 2, newGMFBendpointsFromSource.size()); - } else if (segmentRemoved) { - assertEquals(messagePrefix + " segment must me removed. We should have 1 GMF point less.", previousPoints.size() - 1, newGMFBendpointsFromSource.size()); - } + assertEquals("We should have a delta of " + nbGMFPointsDelta + " GMF points.", previousPoints.size() + nbGMFPointsDelta, newGMFBendpointsFromSource.size()); + Point previousDraw2dPoint; - Point previousMergedPoint; Point currentDraw2dPoint; Point currentGmfPoint; - int yNodeBorder; PointList actualBendPoints = ((PolylineConnectionEx) connectionEditPart.part().getFigure()).getPoints(); if (firstPoint) { previousDraw2dPoint = previousPoints.getFirstPoint(); - previousMergedPoint = previousPoints.getPoint(2); currentDraw2dPoint = actualBendPoints.getFirstPoint(); currentGmfPoint = newGMFBendpointsFromSource.get(0); - yNodeBorder = movedNodeBounds.getTranslated(moveDelta).getBottom().y; } else { previousDraw2dPoint = previousPoints.getLastPoint(); - previousMergedPoint = previousPoints.getPoint(previousPoints.size() - 3); currentDraw2dPoint = actualBendPoints.getLastPoint(); currentGmfPoint = newGMFBendpointsFromSource.get(newGMFBendpointsFromSource.size() - 1); - yNodeBorder = movedNodeBounds.getTranslated(moveDelta).y; } // The first (or last) bendpoint should have moved. assertNotEquals(messagePrefix + " point should have moved", previousDraw2dPoint, currentDraw2dPoint); - if (segmentMerged) { - Point expectedPoint = previousDraw2dPoint.getTranslated(moveDelta); - Point otherExpectedPoint = new Point(expectedPoint.x, previousMergedPoint.y); - assertTrue(messagePrefix + " point should have moved at the expected location. expected:<" + expectedPoint + "or " + otherExpectedPoint + "> but was:<" + currentDraw2dPoint + ">", - expectedPoint.equals(currentDraw2dPoint) || otherExpectedPoint.equals(currentDraw2dPoint)); - } else if (segmentRemoved) { - Point otherExpectedPoint = new Point(previousMergedPoint.x, yNodeBorder); - assertEquals(messagePrefix + " point should have moved at the expected location", otherExpectedPoint, currentDraw2dPoint); - } else { - assertEquals(messagePrefix + " point should have moved at the expected location", previousDraw2dPoint.getTranslated(moveDelta), currentDraw2dPoint); + if (!assertPointLocationFunction.apply(currentDraw2dPoint)) { + fail(assertPointLocationFunction.getErrorMessage()); } // The draw2d and GMF point should be the same. assertEquals(messagePrefix + " draw2d and GMF points should be the same", currentDraw2dPoint, currentGmfPoint); |
