diff options
| author | Laurent Redor | 2015-08-12 15:27:38 +0000 |
|---|---|---|
| committer | Laurent Redor | 2015-08-13 08:02:51 +0000 |
| commit | 8085750cb2c0dcb3b6099043741e8cd275d02407 (patch) | |
| tree | 0057a2a4090117152b9916074990a768a78aa0f5 | |
| parent | 7320302765c72ab0cac9b2cdf90f9331c18d0ff3 (diff) | |
| download | org.eclipse.sirius-8085750cb2c0dcb3b6099043741e8cd275d02407.tar.gz org.eclipse.sirius-8085750cb2c0dcb3b6099043741e8cd275d02407.tar.xz org.eclipse.sirius-8085750cb2c0dcb3b6099043741e8cd275d02407.zip | |
[474828] Merge segment, at GMF level, if needed
Bug: 474828
Change-Id: Ic329f56392ec5e8db5e2e0b7c88bf6b94b9d1194
Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
2 files changed, 242 insertions, 102 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 0300df9f0a..086f068ba1 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 @@ -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 @@ -25,6 +25,7 @@ import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.internal.commands.SetConnectionBendpointsCommand; import org.eclipse.gmf.runtime.draw2d.ui.geometry.LineSeg; +import org.eclipse.gmf.runtime.draw2d.ui.geometry.PointListUtilities; import org.eclipse.sirius.diagram.ui.business.api.query.ConnectionEditPartQuery; import org.eclipse.sirius.ext.base.Option; import org.eclipse.sirius.ext.gmf.runtime.editparts.GraphicalHelper; @@ -144,53 +145,144 @@ public class SetConnectionBendpointsAccordingToExtremityMoveCommmand extends Set public static void adaptPointListAndRefPoints(boolean sourceMove, Point moveDelta, boolean isEdgeWithRectilinearRoutingStyle, Rectangle bounds, Point sourceRefPoint, Point targetRefPoint, PointList connectionPointList) { if (sourceMove) { - // Move reference point - sourceRefPoint.performTranslate(moveDelta.x, moveDelta.y); - // Move second point in case of rectilinear router - if (isEdgeWithRectilinearRoutingStyle) { - LineSeg firstSegment = new LineSeg(connectionPointList.getPoint(0), connectionPointList.getPoint(1)); - if (firstSegment.isHorizontal()) { - connectionPointList.setPoint(connectionPointList.getPoint(0).translate(moveDelta.x, moveDelta.y), 0); - connectionPointList.setPoint(connectionPointList.getPoint(1).translate(0, moveDelta.y), 1); - } else { - connectionPointList.setPoint(connectionPointList.getPoint(0).translate(moveDelta.x, moveDelta.y), 0); - connectionPointList.setPoint(connectionPointList.getPoint(1).translate(moveDelta.x, 0), 1); - } + moveFirstSegmentAndRefPointAccordingToSourcetMove(moveDelta, isEdgeWithRectilinearRoutingStyle, bounds, sourceRefPoint, connectionPointList); + } else { + moveLastSegmentAndRefPointAccordingToTargetMove(moveDelta, isEdgeWithRectilinearRoutingStyle, bounds, targetRefPoint, connectionPointList); + } + } + + /** + * Adapt the point list and the source reference point according to a move + * of the source. + * + * @param moveDelta + * the delta of the move of the extremity (source or target) + * @param isEdgeWithRectilinearRoutingStyle + * True if the edge is rectilinear (one more point is adapted in + * this case), false otherwise + * @param bounds + * The bounds of the moved node + * @param sourceRefPoint + * The source reference point to adapt + * @param connectionPointList + * The point list to adapt + */ + private static void moveFirstSegmentAndRefPointAccordingToSourcetMove(Point moveDelta, boolean isEdgeWithRectilinearRoutingStyle, Rectangle bounds, Point sourceRefPoint, + PointList connectionPointList) { + // Move reference point + sourceRefPoint.performTranslate(moveDelta.x, moveDelta.y); + // Move second point in case of rectilinear router + if (isEdgeWithRectilinearRoutingStyle) { + LineSeg firstSegment = new LineSeg(connectionPointList.getPoint(0), connectionPointList.getPoint(1)); + if (firstSegment.isHorizontal()) { + connectionPointList.setPoint(connectionPointList.getPoint(0).translate(moveDelta.x, moveDelta.y), 0); + connectionPointList.setPoint(connectionPointList.getPoint(1).translate(0, moveDelta.y), 1); + normalizeAndStraight(connectionPointList); } else { - // Compute intersection between the line - // (tempSourceRefPoint<-->second point) and the source node - // 2-Compute intersection - Option<Point> intersectionPoint = GraphicalHelper.getIntersection(sourceRefPoint, connectionPointList.getPoint(1), bounds.getTranslated(moveDelta), false); - if (intersectionPoint.some()) { - connectionPointList.setPoint(intersectionPoint.get(), 0); - } else { - connectionPointList.setPoint(connectionPointList.getPoint(0).translate(moveDelta), 0); - } + connectionPointList.setPoint(connectionPointList.getPoint(0).translate(moveDelta.x, moveDelta.y), 0); + connectionPointList.setPoint(connectionPointList.getPoint(1).translate(moveDelta.x, 0), 1); + normalizeAndStraight(connectionPointList); } } else { - // Move reference point - targetRefPoint.performTranslate(moveDelta.x, moveDelta.y); - // Move second last point in case of rectilinear router - if (isEdgeWithRectilinearRoutingStyle) { - LineSeg lastSegment = new LineSeg(connectionPointList.getPoint(connectionPointList.size() - 2), connectionPointList.getPoint(connectionPointList.size() - 1)); - if (lastSegment.isHorizontal()) { - connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 2).translate(0, moveDelta.y), connectionPointList.size() - 2); - connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 1).translate(moveDelta.x, moveDelta.y), connectionPointList.size() - 1); - } else { - connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 2).translate(moveDelta.x, 0), connectionPointList.size() - 2); - connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 1).translate(moveDelta.x, moveDelta.y), connectionPointList.size() - 1); - } + // Compute intersection between the line + // (tempSourceRefPoint<-->second point) and the source node + // 2-Compute intersection + Option<Point> intersectionPoint = GraphicalHelper.getIntersection(sourceRefPoint, connectionPointList.getPoint(1), bounds.getTranslated(moveDelta), false); + if (intersectionPoint.some()) { + connectionPointList.setPoint(intersectionPoint.get(), 0); } else { - // Compute intersection between the line - // (tempTargetRefPoint<-->second to last point) and the target - // node - // 2-Compute intersection - Option<Point> intersectionPoint = GraphicalHelper.getIntersection(targetRefPoint, connectionPointList.getPoint(connectionPointList.size() - 2), bounds.getTranslated(moveDelta), false); - if (intersectionPoint.some()) { - connectionPointList.setPoint(intersectionPoint.get(), connectionPointList.size() - 1); - } else { - connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 1).translate(moveDelta), connectionPointList.size() - 1); - } + connectionPointList.setPoint(connectionPointList.getPoint(0).translate(moveDelta), 0); + } + } + } + + /** + * Adapt the point list and the target reference point according to a move + * of the target. + * + * @param moveDelta + * the delta of the move of the extremity (source or target) + * @param isEdgeWithRectilinearRoutingStyle + * True if the edge is rectilinear (one more point is adapted in + * this case), false otherwise + * @param bounds + * The bounds of the moved node + * @param targetRefPoint + * The target reference point to adapt + * @param connectionPointList + * The point list to adapt + */ + private static void moveLastSegmentAndRefPointAccordingToTargetMove(Point moveDelta, boolean isEdgeWithRectilinearRoutingStyle, Rectangle bounds, Point targetRefPoint, + PointList connectionPointList) { + // Move reference point + targetRefPoint.performTranslate(moveDelta.x, moveDelta.y); + // Move second last point in case of rectilinear router + if (isEdgeWithRectilinearRoutingStyle) { + LineSeg lastSegment = new LineSeg(connectionPointList.getPoint(connectionPointList.size() - 2), connectionPointList.getPoint(connectionPointList.size() - 1)); + if (lastSegment.isHorizontal()) { + connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 2).translate(0, moveDelta.y), connectionPointList.size() - 2); + connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 1).translate(moveDelta.x, moveDelta.y), connectionPointList.size() - 1); + normalizeAndStraight(connectionPointList); + } else { + connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 2).translate(moveDelta.x, 0), connectionPointList.size() - 2); + connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 1).translate(moveDelta.x, moveDelta.y), connectionPointList.size() - 1); + normalizeAndStraight(connectionPointList); + } + } else { + // Compute intersection between the line + // (tempTargetRefPoint<-->second to last point) and the target node + // 2-Compute intersection + Option<Point> intersectionPoint = GraphicalHelper.getIntersection(targetRefPoint, connectionPointList.getPoint(connectionPointList.size() - 2), bounds.getTranslated(moveDelta), false); + if (intersectionPoint.some()) { + connectionPointList.setPoint(intersectionPoint.get(), connectionPointList.size() - 1); + } else { + connectionPointList.setPoint(connectionPointList.getPoint(connectionPointList.size() - 1).translate(moveDelta), connectionPointList.size() - 1); + } + + } + } + + /** + * Check if the segment will be merged with next or previous segment with + * draw2d rectilinear router. In this case, we remove the useless points. + * <BR> + * Logic extracted from + * {@link org.eclipse.gmf.runtime.draw2d.ui.internal.routers.RectilinearRouter.routeLine(Connection, + * int, PointList)}. + * + * @param connectionPointList + * <code>PointList</code> to normalize + */ + private static void normalizeAndStraight(PointList connectionPointList) { + if (PointListUtilities.normalizeSegments(connectionPointList, 3)) { + /* + * Normalization can make our polyline not rectilinear. Hence, we + * need to normalize segments of polyline to straight line + * tolerance. + */ + normalizeToStraightLineTolerance(connectionPointList, 3); + } + } + + /** + * Goes through line segments of a polyline and makes strict straight + * segments from nearly straight segments.<BR> + * Copied from + * {@link org.eclipse.gmf.runtime.draw2d.ui.internal.routers.RectilinearRouter} + * + * @param line + * polyline + * @param tolerance + * tolerance value specifying nearly straight lines. + */ + private static void normalizeToStraightLineTolerance(PointList line, int tolerance) { + for (int i = 0; i < line.size() - 1; i++) { + Point pt1 = line.getPoint(i); + Point pt2 = line.getPoint(i + 1); + if (Math.abs(pt1.x - pt2.x) < tolerance) { + line.setPoint(new Point(pt1.x, pt2.y), i + 1); + } else if (Math.abs(pt1.y - pt2.y) < tolerance) { + line.setPoint(new Point(pt2.x, pt1.y), i + 1); } } } 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 e4cb43e074..9307197d6e 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 @@ -83,10 +83,15 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS } } }); + + // Open the testing diagram editor + editor = (SWTBotSiriusDiagramEditor) openRepresentation(localSession.getOpenedSession(), DIAGRAM_DESCRIPTION_NAME, "rectilinearCase1", DSemanticDiagram.class, true, true); } @Override protected void tearDown() throws Exception { + editor.close(); + SWTBotUtils.waitAllUiEvents(); if (isOutlineViewOpened) { designerViews.openOutlineView(); } @@ -107,93 +112,136 @@ public class BendpointsStabilityOnMovesSpecificCasesTest extends AbstractSiriusS } /** + * Test that first point is moved has expected and that draw2d and GMF last + * points are consistency. + */ + public void testFirstPointConsistency() { + testFirstPointConsistency(new Point(20, 20), false); + } + + /** + * Test that first point is moved has expected and that draw2d and GMF last + * points are consistency. In this case, the first segment is merged with + * the second one. + */ + public void testFirstPointConsistencyWithMergeSegment() { + testFirstPointConsistency(new Point(0, 99), true); + } + + /** * Test that last point is moved has expected and that draw2d and GMF last * points are consistency. */ public void testLastPointConsistency() { - // Step 1: open the testing diagram editor - SWTBotSiriusDiagramEditor diagramEditor = (SWTBotSiriusDiagramEditor) openRepresentation(localSession.getOpenedSession(), DIAGRAM_DESCRIPTION_NAME, "rectilinearCase1", DSemanticDiagram.class, - true, true); - try { - String nodeToMoveName = "C2"; - diagramEditor.reveal(nodeToMoveName); - // Step 2: store the previous bendpoints - SWTBotGefEditPart editPartToMove = diagramEditor.getEditPart(nodeToMoveName, IAbstractDiagramNodeEditPart.class); - SWTBotGefConnectionEditPart connectionEditPart = editPartToMove.targetConnections().get(0); - PointList previousPoints = ((PolylineConnectionEx) connectionEditPart.part().getFigure()).getPoints(); - - // Step 3: Drag node - Point moveDelta = new Point(-20, 50); - Point initialLocation = diagramEditor.getBounds(editPartToMove).getCenter(); - Point targetLocation = new Point(initialLocation.x + moveDelta.x, initialLocation.y + moveDelta.y); - ICondition editPartMovedCondition = new CheckEditPartMoved(editPartToMove); - diagramEditor.drag(initialLocation, targetLocation); - bot.waitUntil(editPartMovedCondition); - assertEquals("Drag as failed: selection should be the same before and after drag.", editPartToMove, diagramEditor.selectedEditParts().get(0)); - // Step 4: Check bendpoints - compareActualBendpointsWithExpected(diagramEditor, connectionEditPart, previousPoints, moveDelta, false); - } finally { - diagramEditor.close(); - SWTBotUtils.waitAllUiEvents(); - } + testLastPointConsistency(new Point(-20, 50), false); + } + + /** + * Test that last point is moved has expected and that draw2d and GMF last + * points are consistency. In this case, the last segment is merged with the + * previous one. + */ + public void testLastPointConsistencyWithMergeSegment() { + testLastPointConsistency(new Point(0, -139), true); + } + + /** + * Test that last point is moved has expected and that draw2d and GMF last + * points are consistency. + * + * @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. + */ + protected void testLastPointConsistency(Point moveDelta, boolean segmentMerged) { + String nodeToMoveName = "C2"; + editor.reveal(nodeToMoveName); + // Step 2: store the previous bendpoints + SWTBotGefEditPart editPartToMove = editor.getEditPart(nodeToMoveName, IAbstractDiagramNodeEditPart.class); + SWTBotGefConnectionEditPart connectionEditPart = editPartToMove.targetConnections().get(0); + PointList previousPoints = ((PolylineConnectionEx) connectionEditPart.part().getFigure()).getPoints(); + + // Step 3: Drag node + Point initialLocation = editor.getBounds(editPartToMove).getCenter(); + Point targetLocation = new Point(initialLocation.x + moveDelta.x, initialLocation.y + moveDelta.y); + ICondition editPartMovedCondition = new CheckEditPartMoved(editPartToMove); + editor.drag(initialLocation, targetLocation); + 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, false, segmentMerged); } /** * Test that first point is moved has expected and that draw2d and GMF last * points are consistency. + * + * @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. */ - public void testFirstPointConsistency() { - // Step 1: open the testing diagram editor - SWTBotSiriusDiagramEditor diagramEditor = (SWTBotSiriusDiagramEditor) openRepresentation(localSession.getOpenedSession(), DIAGRAM_DESCRIPTION_NAME, "rectilinearCase1", DSemanticDiagram.class, - true, true); - try { - String nodeToMoveName = "C1"; - diagramEditor.reveal(nodeToMoveName); - // Step 2: store the previous bendpoints - SWTBotGefEditPart editPartToMove = diagramEditor.getEditPart(nodeToMoveName, IAbstractDiagramNodeEditPart.class); - SWTBotGefConnectionEditPart connectionEditPart = editPartToMove.sourceConnections().get(0); - PointList previousPoints = ((PolylineConnectionEx) connectionEditPart.part().getFigure()).getPoints(); - - // Step 3: Drag node - Point moveDelta = new Point(20, 20); - Point initialLocation = diagramEditor.getBounds(editPartToMove).getCenter(); - Point targetLocation = new Point(initialLocation.x + moveDelta.x, initialLocation.y + moveDelta.y); - ICondition editPartMovedCondition = new CheckEditPartMoved(editPartToMove); - diagramEditor.drag(initialLocation, targetLocation); - bot.waitUntil(editPartMovedCondition); - assertEquals("Drag as failed: selection should be the same before and after drag.", editPartToMove, diagramEditor.selectedEditParts().get(0)); - // Step 4: Check bendpoints - compareActualBendpointsWithExpected(diagramEditor, connectionEditPart, previousPoints, moveDelta, true); - } finally { - diagramEditor.close(); - SWTBotUtils.waitAllUiEvents(); - } + protected void testFirstPointConsistency(Point moveDelta, boolean segmentMerged) { + String nodeToMoveName = "C1"; + editor.reveal(nodeToMoveName); + // Step 2: store the previous bendpoints + SWTBotGefEditPart editPartToMove = editor.getEditPart(nodeToMoveName, IAbstractDiagramNodeEditPart.class); + SWTBotGefConnectionEditPart connectionEditPart = editPartToMove.sourceConnections().get(0); + PointList previousPoints = ((PolylineConnectionEx) connectionEditPart.part().getFigure()).getPoints(); + + // Step 3: Drag node + Point initialLocation = editor.getBounds(editPartToMove).getCenter(); + Point targetLocation = new Point(initialLocation.x + moveDelta.x, initialLocation.y + moveDelta.y); + ICondition editPartMovedCondition = new CheckEditPartMoved(editPartToMove); + editor.drag(initialLocation, targetLocation); + 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, true, segmentMerged); } // Check the first or last benpoint of the connection. private void compareActualBendpointsWithExpected(SWTBotSiriusDiagramEditor diagramEditor, SWTBotGefConnectionEditPart connectionEditPart, PointList expectedBendPoints, Point moveDelta, - boolean firstPoint) { - PointList actualBendPoints = ((PolylineConnectionEx) connectionEditPart.part().getFigure()).getPoints(); + boolean firstPoint, boolean segmentMerged) { 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 points less.", expectedBendPoints.size() - 2, newGMFBendpointsFromSource.size()); + } Point expectedDraw2dPoint; + Point expectedMergedPoint; Point actualDraw2dPoint; Point actualGmfPoint; + PointList actualBendPoints = ((PolylineConnectionEx) connectionEditPart.part().getFigure()).getPoints(); if (firstPoint) { expectedDraw2dPoint = expectedBendPoints.getFirstPoint(); + expectedMergedPoint = expectedBendPoints.getPoint(2); actualDraw2dPoint = actualBendPoints.getFirstPoint(); actualGmfPoint = newGMFBendpointsFromSource.get(0); } else { expectedDraw2dPoint = expectedBendPoints.getLastPoint(); + expectedMergedPoint = expectedBendPoints.getPoint(expectedBendPoints.size() - 3); actualDraw2dPoint = actualBendPoints.getLastPoint(); actualGmfPoint = newGMFBendpointsFromSource.get(newGMFBendpointsFromSource.size() - 1); } // The first (or last) bendpoint should have moved. - String messagePrefix = "First"; - if (!firstPoint) { - messagePrefix = "Last"; - } assertNotEquals(messagePrefix + " point should have moved", expectedDraw2dPoint, actualDraw2dPoint); - assertEquals(messagePrefix + " point should have moved at the expected location", expectedDraw2dPoint.getTranslated(moveDelta), actualDraw2dPoint); + if (segmentMerged) { + Point expectedPoint = expectedDraw2dPoint.getTranslated(moveDelta); + Point otherExpectedPoint = new Point(expectedPoint.x, expectedMergedPoint.y); + assertTrue(messagePrefix + " point should have moved at the expected location. expected:<" + expectedPoint + "or " + otherExpectedPoint + "> but was:<" + actualBendPoints + ">", + expectedPoint.equals(actualDraw2dPoint) || otherExpectedPoint.equals(actualDraw2dPoint)); + } else { + assertEquals(messagePrefix + " point should have moved at the expected location", expectedDraw2dPoint.getTranslated(moveDelta), actualDraw2dPoint); + } // The draw2d and GMF point should be the same. assertEquals(messagePrefix + " draw2d and GMF points should be the same", actualDraw2dPoint, actualGmfPoint); } |
