Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Lorenzo2014-05-16 09:20:46 +0000
committerVincent Lorenzo2014-05-16 09:26:45 +0000
commite53d232d74b5793daeae3b49d14db54b7fab75b6 (patch)
treeb93816d89deb3e3b646671d2cccd82fadbf10d5d
parentcb6d4ab4464a93406f22b1a8ca85a04b1538c18b (diff)
downloadorg.eclipse.papyrus-e53d232d74b5793daeae3b49d14db54b7fab75b6.tar.gz
org.eclipse.papyrus-e53d232d74b5793daeae3b49d14db54b7fab75b6.tar.xz
org.eclipse.papyrus-e53d232d74b5793daeae3b49d14db54b7fab75b6.zip
https://bugs.eclipse.org/bugs/show_bug.cgi?id=435032 First grid router version
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java30
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/FixEdgeAnchorAfterCreationCommand.java153
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/figure/layer/CustomConnectionLayerEx.java83
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/CustomRouterHelper.java238
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/ObliqueGridRouter.java63
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/RectilinearGridRouter.java129
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/MathUtil.java41
7 files changed, 690 insertions, 47 deletions
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java
index b2933ddcb06..8a60d5f0952 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java
@@ -18,21 +18,28 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import org.eclipse.draw2d.FreeformLayeredPane;
+import org.eclipse.draw2d.IFigure;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.GraphicalViewer;
+import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.commands.CommandStack;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IPrimaryEditPart;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain;
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.resources.editor.parts.DiagramDocumentEditor;
import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.papyrus.commands.CheckedDiagramCommandStack;
+import org.eclipse.papyrus.infra.gmfdiag.common.figure.layer.CustomConnectionLayerEx;
import org.eclipse.papyrus.infra.gmfdiag.common.preferences.PreferencesConstantsHelper;
import org.eclipse.papyrus.infra.gmfdiag.common.utils.CommandIds;
import org.eclipse.papyrus.infra.tools.util.EclipseCommandUtils;
@@ -199,6 +206,29 @@ public class SynchronizableGmfDiagramEditor extends DiagramDocumentEditor implem
/**
*
+ * @see org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor#configureGraphicalViewer()
+ *
+ */
+ @Override
+ protected void configureGraphicalViewer() {
+ super.configureGraphicalViewer();
+ final IDiagramGraphicalViewer viewer = getDiagramGraphicalViewer();
+ final RootEditPart rootEP = viewer.getRootEditPart();
+ if(rootEP instanceof AbstractGraphicalEditPart){
+ IFigure contentPane = ((AbstractGraphicalEditPart)rootEP).getContentPane();
+ IFigure parent = contentPane.getParent();
+ if(parent instanceof FreeformLayeredPane){
+ FreeformLayeredPane layerPane = (FreeformLayeredPane)parent;
+
+ //we replace the connection layer by our to be able to change the routers
+ layerPane.removeLayer(DiagramRootEditPart.CONNECTION_LAYER);
+ layerPane.add(new CustomConnectionLayerEx(rootEP), DiagramRootEditPart.CONNECTION_LAYER);
+ }
+ }
+ }
+
+ /**
+ *
* @see org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor#addDefaultPreferences()
*
*/
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/FixEdgeAnchorAfterCreationCommand.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/FixEdgeAnchorAfterCreationCommand.java
index a539432c081..c825b3a5a6d 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/FixEdgeAnchorAfterCreationCommand.java
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/FixEdgeAnchorAfterCreationCommand.java
@@ -1,43 +1,57 @@
/*****************************************************************************
* Copyright (c) 2014 CEA LIST.
*
+ *
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- *
- * CEA LIST - Initial API and implementation
+ * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
*
*****************************************************************************/
+
package org.eclipse.papyrus.infra.gmfdiag.common.commands;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.ConnectionRouter;
import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
-import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gef.LayerConstants;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
-import org.eclipse.gmf.runtime.diagram.core.edithelpers.CreateElementRequestAdapter;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest.ConnectionViewDescriptor;
import org.eclipse.gmf.runtime.draw2d.ui.figures.BaseSlidableAnchor;
import org.eclipse.gmf.runtime.draw2d.ui.figures.IAnchorableFigure;
+import org.eclipse.gmf.runtime.draw2d.ui.figures.PolylineConnectionEx;
+import org.eclipse.gmf.runtime.draw2d.ui.internal.figures.ConnectionLayerEx;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.IdentityAnchor;
import org.eclipse.gmf.runtime.notation.NotationFactory;
+import org.eclipse.gmf.runtime.notation.NotationPackage;
+import org.eclipse.gmf.runtime.notation.RelativeBendpoints;
+import org.eclipse.gmf.runtime.notation.Routing;
+import org.eclipse.gmf.runtime.notation.RoutingStyle;
import org.eclipse.gmf.runtime.notation.View;
-import org.eclipse.papyrus.infra.gmfdiag.common.geometry.RectangleUtils;
-import org.eclipse.papyrus.infra.gmfdiag.common.geometry.Segment;
+import org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint;
+import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil;
import org.eclipse.papyrus.infra.services.edit.utils.RequestParameterConstants;
@@ -50,12 +64,9 @@ import org.eclipse.papyrus.infra.services.edit.utils.RequestParameterConstants;
*
* see bug 430702: [Diagram] Moving source of a link moves the target too.
*/
-
-public class FixEdgeAnchorAfterCreationCommand extends AbstractTransactionalCommand {
-
- private static final String RECT_RIGHT_MIDDLE_ANCHOR = "(1.0,0.5)";
- private static final String RECT_BOTTOM_MIDDLE_ANCHOR = "(0.5,1.0)";
+@SuppressWarnings("restriction")
+public class FixEdgeAnchorAfterCreationCommand extends AbstractTransactionalCommand {
/**
* the request used to create connection view
@@ -83,62 +94,110 @@ public class FixEdgeAnchorAfterCreationCommand extends AbstractTransactionalComm
* Executes a fix anchor command for the created edge
*
*/
+ @Override
protected CommandResult doExecuteWithResult(final IProgressMonitor progressMonitor, final IAdaptable info) throws ExecutionException {
final ConnectionViewDescriptor connectionViewDescriptor = this.request.getConnectionViewDescriptor();
final Edge createdEdge = (Edge)connectionViewDescriptor.getAdapter(View.class);
- final IAdaptable adaptable = (CreateElementRequestAdapter)connectionViewDescriptor.getElementAdapter();
+
+ final IAdaptable adaptable = connectionViewDescriptor.getElementAdapter();
final CreateRelationshipRequest createRelationShipRequest = (CreateRelationshipRequest)adaptable.getAdapter(CreateRelationshipRequest.class);
final Map<?, ?> requestParameters = createRelationShipRequest.getParameters();
- final IFigure sourceFigure = (IFigure)requestParameters.get(RequestParameterConstants.EDGE_SOURCE_FIGURE);
- final IFigure targetFigure = (IFigure)requestParameters.get(RequestParameterConstants.EDGE_TARGET_FIGURE);
- final Point sourcePoint = (Point)requestParameters.get(RequestParameterConstants.EDGE_SOURCE_POINT);
- final Point targetPoint = (Point)requestParameters.get(RequestParameterConstants.EDGE_TARGET_POINT);
- if(createdEdge != null && sourceFigure instanceof IAnchorableFigure && targetFigure instanceof IAnchorableFigure && sourcePoint!=null && targetPoint!=null) {
- final String sourceTerminal;
- final String targetTerminal;
- if(sourceFigure == targetFigure) {
- sourceTerminal = RECT_RIGHT_MIDDLE_ANCHOR.toString();
- targetTerminal = RECT_BOTTOM_MIDDLE_ANCHOR.toString();
- } else {
-
- final Rectangle sourceBds = sourceFigure.getBounds().getCopy();
- final Rectangle targetBds = targetFigure.getBounds().getCopy();
- sourceFigure.translateToAbsolute(sourceBds);
- targetFigure.translateToAbsolute(targetBds);
-
- final Segment segment = new Segment(sourcePoint, targetPoint);
- final Point realSourcePoint = RectangleUtils.getIntersectionPoint(sourceBds, segment);
- final Point realTargetPoint = RectangleUtils.getIntersectionPoint(targetBds, segment);
+ final Point sourcePoint = ((Point)requestParameters.get(RequestParameterConstants.EDGE_SOURCE_POINT)).getCopy();
+ final Point targetPoint = ((Point)requestParameters.get(RequestParameterConstants.EDGE_TARGET_POINT)).getCopy();
+ final IFigure fig1 = (IFigure)requestParameters.get(RequestParameterConstants.EDGE_SOURCE_FIGURE);
+ final IFigure fig2 = (IFigure)requestParameters.get(RequestParameterConstants.EDGE_TARGET_FIGURE);
+ if(fig1 instanceof IAnchorableFigure && fig2 instanceof IAnchorableFigure) {
+ final IAnchorableFigure sourceFigure = (IAnchorableFigure)fig1;
+ final IAnchorableFigure targetFigure = (IAnchorableFigure)fig2;
+
+ //we route the future connection to find its anchors and its bendpoints
+ final ConnectionRouter router = getRouterToUse(createdEdge);
+ final Connection dummyConnection = new PolylineConnectionEx();
+
+ final PointList pointsList = new PointList();
+ pointsList.addPoint(sourcePoint);
+ pointsList.addPoint(targetPoint);
+
+ final ConnectionAnchor arg0 = sourceFigure.getSourceConnectionAnchorAt(sourcePoint);
+ dummyConnection.setSourceAnchor(arg0);
+
+ final ConnectionAnchor arg1 = targetFigure.getTargetConnectionAnchorAt(targetPoint);
+ dummyConnection.setTargetAnchor(arg1);
+
+ router.route(dummyConnection);
+
+ if(createdEdge != null && sourcePoint != null && targetPoint != null) {
+ Point realSourcePoint = dummyConnection.getPoints().getFirstPoint();
+ Point realTargetPoint = dummyConnection.getPoints().getLastPoint();
//get source anchor terminal
- final BaseSlidableAnchor anchorSource = (BaseSlidableAnchor)((IAnchorableFigure)sourceFigure).getSourceConnectionAnchorAt(realSourcePoint);
- sourceTerminal = anchorSource.getTerminal();
+ final BaseSlidableAnchor anchorSource = (BaseSlidableAnchor)sourceFigure.getSourceConnectionAnchorAt(realSourcePoint);
+ final String sourceTerminal = anchorSource.getTerminal();
//get target anchor terminal
- final BaseSlidableAnchor anchorTarget = (BaseSlidableAnchor)((IAnchorableFigure)targetFigure).getTargetConnectionAnchorAt(realTargetPoint);
- targetTerminal = anchorTarget.getTerminal();
+ final BaseSlidableAnchor anchorTarget = (BaseSlidableAnchor)targetFigure.getTargetConnectionAnchorAt(realTargetPoint);
+ final String targetTerminal = anchorTarget.getTerminal();
+
//create and set the source anchor
+ final IdentityAnchor sourceAnchor = NotationFactory.eINSTANCE.createIdentityAnchor();
+ sourceAnchor.setId(sourceTerminal);
+ createdEdge.setSourceAnchor(sourceAnchor);
+
+ //create an set the target anchor
+ final IdentityAnchor targetAnchor = NotationFactory.eINSTANCE.createIdentityAnchor();
+ targetAnchor.setId(targetTerminal);
+ createdEdge.setTargetAnchor(targetAnchor);
+
+
+ //serialize bendpoints
+ int numOfPoints = dummyConnection.getPoints().size();
+ final List<RelativeBendpoint> newBendpoints = new ArrayList<RelativeBendpoint>();
+ for(int i = 0; i < numOfPoints; i++) {
+ Dimension s = dummyConnection.getPoints().getPoint(i).getDifference(dummyConnection.getPoints().getFirstPoint());
+ Dimension t = dummyConnection.getPoints().getPoint(i).getDifference(dummyConnection.getPoints().getLastPoint());
+ newBendpoints.add(new RelativeBendpoint(s.width, s.height, t.width, t.height));
+ }
+
+ final RelativeBendpoints points = (RelativeBendpoints)createdEdge.getBendpoints();
+ points.setPoints(newBendpoints);
+ return CommandResult.newOKCommandResult();
}
- //TODO : it is possible that the result will be not correct when the preferred routing for the link is not the oblique router
- final IdentityAnchor sourceAnchor = NotationFactory.eINSTANCE.createIdentityAnchor();
- sourceAnchor.setId(sourceTerminal);
- createdEdge.setSourceAnchor(sourceAnchor);
-
- //create an set the target anchor
- final IdentityAnchor targetAnchor = NotationFactory.eINSTANCE.createIdentityAnchor();
- targetAnchor.setId(targetTerminal);
- createdEdge.setTargetAnchor(targetAnchor);
-
- return CommandResult.newOKCommandResult();
}
return CommandResult.newOKCommandResult();
}
/**
*
+ * @param edge
+ * an edge
+ * @return
+ * the router to use to calculte bendpoints
+ */
+ //remove warning for ConnectionLayerEx
+ protected ConnectionRouter getRouterToUse(final Edge edge) {
+ final DiagramEditPart rootEP = DiagramEditPartsUtil.getDiagramEditPart(this.request.getSourceEditPart());
+ final IFigure layer = rootEP.getLayer(LayerConstants.CONNECTION_LAYER);
+ RoutingStyle style = (RoutingStyle)edge.getStyle(NotationPackage.Literals.ROUTING_STYLE);
+ if(style != null && layer instanceof ConnectionLayerEx) {
+ ConnectionLayerEx cLayerEx = (ConnectionLayerEx)layer;
+ final Routing routing = style.getRouting();
+ if(Routing.MANUAL_LITERAL == routing) {
+ return cLayerEx.getObliqueRouter();
+ } else if(Routing.RECTILINEAR_LITERAL == routing) {
+ return cLayerEx.getRectilinearRouter();
+ } else if(Routing.TREE_LITERAL == routing) {
+ return cLayerEx.getTreeRouter();
+ }
+ }
+ return null;
+ }
+
+ /**
+ *
* @see org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand#cleanup()
*
*/
+ @Override
protected void cleanup() {
this.request = null;
super.cleanup();
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/figure/layer/CustomConnectionLayerEx.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/figure/layer/CustomConnectionLayerEx.java
new file mode 100644
index 00000000000..b58e8af4eee
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/figure/layer/CustomConnectionLayerEx.java
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * Copyright (c) 2014 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.common.figure.layer;
+
+import org.eclipse.draw2d.ConnectionRouter;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gmf.runtime.draw2d.ui.internal.figures.ConnectionLayerEx;
+import org.eclipse.papyrus.infra.gmfdiag.common.routers.ObliqueGridRouter;
+import org.eclipse.papyrus.infra.gmfdiag.common.routers.RectilinearGridRouter;
+
+/**
+ *
+ * A Custom Connnection Layer to use to change the router used by diagrams
+ *
+ */
+@SuppressWarnings("restriction")
+public class CustomConnectionLayerEx extends ConnectionLayerEx {
+
+ /**
+ * RectilinearRouter using diagram Grid
+ */
+ protected ConnectionRouter rectilinearGridRouter;
+
+ /**
+ * ObliqueRouter using Diagram Grid
+ */
+ protected ConnectionRouter obliqueGridRouter;
+
+ /**
+ * An edit part
+ */
+ protected final EditPart anyEditPart;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param anyEditPart
+ * an edit part of the diagram
+ */
+ public CustomConnectionLayerEx(final EditPart anyEditPart) {
+ this.anyEditPart = anyEditPart;
+ }
+
+ /**
+ *
+ * @see org.eclipse.gmf.runtime.draw2d.ui.internal.figures.ConnectionLayerEx#getRectilinearRouter()
+ *
+ * @return
+ */
+ @Override
+ public ConnectionRouter getRectilinearRouter() {
+ if(this.rectilinearGridRouter == null) {
+ this.rectilinearGridRouter = new RectilinearGridRouter(this.anyEditPart);
+ }
+ return this.rectilinearGridRouter;
+ }
+
+ /**
+ *
+ * @see org.eclipse.gmf.runtime.draw2d.ui.internal.figures.ConnectionLayerEx#getObliqueRouter()
+ *
+ * @return
+ */
+ @Override
+ public ConnectionRouter getObliqueRouter() {
+ if(this.obliqueGridRouter == null) {
+ this.obliqueGridRouter = new ObliqueGridRouter(this.anyEditPart);
+ }
+ return this.obliqueGridRouter;
+ }
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/CustomRouterHelper.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/CustomRouterHelper.java
new file mode 100644
index 00000000000..5971492aaeb
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/CustomRouterHelper.java
@@ -0,0 +1,238 @@
+/*****************************************************************************
+ * Copyright (c) 2014 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.common.routers;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.Viewport;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gmf.runtime.draw2d.ui.geometry.LineSeg;
+import org.eclipse.papyrus.infra.tools.util.MathUtil;
+
+
+/**
+ *
+ * @author VL222926
+ *
+ */
+public class CustomRouterHelper {
+
+ static private CustomRouterHelper sprm = new CustomRouterHelper();
+
+ /**
+ * @return the <code>CustomRouterHelper</code> singleton instance
+ */
+ static public CustomRouterHelper getInstance() {
+ return sprm;
+ }
+
+ /**
+ *
+ * Constructor.
+ *
+ */
+ private CustomRouterHelper() {
+ //to prevent instanciation
+ }
+
+
+ /**
+ * We developer must call RouterHelper.getInstance.resetEndPointsToEdge before to call this method
+ *
+ * @param conn
+ * the connection
+ * @param newLine
+ * the point list
+ * @param gridSpacing
+ * the grid spacing
+ */
+ public void resetEndPointsToEdgeOnGrid(final Connection conn, final PointList newLine, final double gridSpacing) {
+ if(newLine.size() >= 2) {
+ //source anchor
+ Point newSourcePoint = getGridPoint(conn, conn.getSourceAnchor(), newLine.getFirstPoint(), newLine.getPoint(1), gridSpacing);
+ newLine.setPoint(newSourcePoint, 0);
+
+ //target anchor
+ Point newTargetPoint = getGridPoint(conn, conn.getTargetAnchor(), newLine.getLastPoint(), newLine.getPoint(newLine.size() - 2), gridSpacing);
+ newLine.setPoint(newTargetPoint, newLine.size() - 1);
+ }
+
+ }
+
+ /**
+ *
+ * @param anchor
+ * a connection anchor
+ * @param spacing
+ * the grid spacing
+ * @return
+ * the point on which snap
+ */
+ public Point getGridPoint(final Connection conn, final ConnectionAnchor anchor, final Point calculatedPoint, final Point secondPoint, final double spacing) {
+ final IFigure figure = anchor.getOwner();
+ if(figure == null) {
+ return calculatedPoint;
+ }
+
+ final LineSeg seg1 = new LineSeg(calculatedPoint.getCopy(), secondPoint.getCopy());
+ final Rectangle bounds = figure.getBounds().getCopy();
+
+ //we translate the bounds of the figure to the absolute bounds
+ figure.getParent().translateToAbsolute(bounds);
+ IFigure parentFigure = figure.getParent();
+ Viewport lastViewport = null;
+ while(parentFigure != null) {
+ if(parentFigure instanceof Viewport) {
+ lastViewport = (Viewport)parentFigure;
+ parentFigure = parentFigure.getParent();
+ } else {
+ parentFigure = parentFigure.getParent();
+ }
+ }
+ //required!
+ bounds.translate(lastViewport.getHorizontalRangeModel().getValue(), lastViewport.getVerticalRangeModel().getValue());
+
+ int tolerance = 1;
+
+ //north intersection
+ final LineSeg northSeg = new LineSeg(bounds.getTopLeft(), bounds.getTopRight());
+ final Point northIntersection = seg1.intersect(northSeg, tolerance);
+
+ //south intersection
+ final LineSeg southSeg = new LineSeg(bounds.getBottomLeft(), bounds.getBottomRight());
+ final Point southIntersection = seg1.intersect(southSeg, tolerance);
+
+ //east intersection
+ final LineSeg eastSeg = new LineSeg(bounds.getTopRight(), bounds.getBottomRight());
+ final Point eastIntersection = seg1.intersect(eastSeg, tolerance);
+
+ //west intersection
+ final LineSeg westSeg = new LineSeg(bounds.getTopLeft(), bounds.getBottomLeft());
+ final Point westIntersection = seg1.intersect(westSeg, tolerance);
+
+ int nbIntersection = 0;
+ int position = PositionConstants.NONE;
+ if(northIntersection != null) {
+ nbIntersection++;
+ position = PositionConstants.NORTH;
+ }
+ if(eastIntersection != null) {
+ nbIntersection++;
+ position = PositionConstants.EAST;
+ }
+
+ if(westIntersection != null) {
+ nbIntersection++;
+ position = PositionConstants.WEST;
+ }
+
+ if(southIntersection != null) {
+ nbIntersection++;
+ position = PositionConstants.SOUTH;
+ }
+
+ final PrecisionPoint result = new PrecisionPoint(calculatedPoint);
+
+ if(nbIntersection > 2) {
+ //no obvious case
+ }
+ if(nbIntersection == 2) {
+ if(northIntersection == eastIntersection || northIntersection == westIntersection) {
+ //arbitrary choice
+ position = PositionConstants.NORTH;
+ nbIntersection = 1;
+ }
+ if(southIntersection == eastIntersection || southIntersection == westIntersection) {
+ position = PositionConstants.SOUTH;
+ nbIntersection = 1;
+ }
+ if(nbIntersection == 2) {
+ //no obvious case
+ }
+ }
+ if(nbIntersection == 1) {
+ //determine first coordinate
+ switch(position) {
+ case PositionConstants.NORTH:
+ result.setPreciseY(bounds.getTop().y);
+ break;
+
+ case PositionConstants.SOUTH:
+ result.setPreciseY(bounds.getBottom().y);
+ break;
+ case PositionConstants.EAST:
+ result.setPreciseX(bounds.getRight().x);
+ break;
+
+ case PositionConstants.WEST:
+ result.setPreciseX(bounds.getLeft().x);
+ break;
+ default:
+ break;
+ }
+
+ //determine second coordinate
+ switch(position) {
+ case PositionConstants.NORTH:
+ case PositionConstants.SOUTH:
+ double x = MathUtil.getClosestMultiple(calculatedPoint.x, spacing);
+
+ //verify that x value is included inside the figure
+ if(!(x >= bounds.getLeft().x && x <= bounds.getRight().x)) {
+ while(x < bounds.getLeft().x) {
+ x = x + spacing;
+ }
+ while(x > bounds.getRight().x) {
+ x = x - spacing;
+ }
+ if(!(x >= bounds.getLeft().x && x <= bounds.getRight().x)) {
+ //the figure width<spacing && there is no grid point on the witdh
+ x = calculatedPoint.x;
+ }
+ }
+ result.setPreciseX(x);
+ break;
+ case PositionConstants.EAST:
+ case PositionConstants.WEST:
+ double y = MathUtil.getClosestMultiple(calculatedPoint.y, spacing);
+
+ //verify that y value is inside the figure
+ if(!(y >= bounds.getTop().y && y <= bounds.getBottom().y)) {
+ while(y <= bounds.getTop().y) {
+ y = y + spacing;
+ }
+ while(y >= bounds.getBottom().y) {
+ y = y - spacing;
+ }
+ if(!(y >= bounds.getTop().y && y <= bounds.getBottom().y)) {
+ //the figure height<spacing && there is no grid point on the height
+ y = calculatedPoint.y;
+ }
+ }
+ result.setPreciseY(y);
+ break;
+
+ default:
+ break;
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/ObliqueGridRouter.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/ObliqueGridRouter.java
new file mode 100644
index 00000000000..7643d790e42
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/ObliqueGridRouter.java
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * Copyright (c) 2014 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.common.routers;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gmf.runtime.draw2d.ui.internal.routers.ObliqueRouter;
+import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil;
+
+/**
+ *
+ * Oblique Router snapping to grid anchor when snap to grid is activated
+ *
+ */
+@SuppressWarnings("restriction")
+public class ObliqueGridRouter extends ObliqueRouter {
+
+ /**
+ * an editpart of the diagram
+ */
+ private final EditPart anyEditPart;
+
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param anyEditPart
+ * an editpart of the diagram
+ */
+ public ObliqueGridRouter(final EditPart anyEditPart) {
+ this.anyEditPart = anyEditPart;
+ }
+
+ /**
+ *
+ * @see org.eclipse.gmf.runtime.draw2d.ui.internal.routers.ObliqueRouter#resetEndPointsToEdge(org.eclipse.draw2d.Connection,
+ * org.eclipse.draw2d.geometry.PointList)
+ *
+ * @param conn
+ * @param newLine
+ */
+ @Override
+ protected void resetEndPointsToEdge(Connection conn, PointList newLine) {
+ super.resetEndPointsToEdge(conn, newLine);
+ if(DiagramEditPartsUtil.isSnapToGridActive(this.anyEditPart)) {
+ int spacing = (int)DiagramEditPartsUtil.getDiagramGridSpacing(this.anyEditPart);
+ CustomRouterHelper.getInstance().resetEndPointsToEdgeOnGrid(conn, newLine, spacing);
+ }
+ }
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/RectilinearGridRouter.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/RectilinearGridRouter.java
new file mode 100644
index 00000000000..a232b9d42d9
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/routers/RectilinearGridRouter.java
@@ -0,0 +1,129 @@
+/*****************************************************************************
+ * Copyright (c) 2014 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.gmfdiag.common.routers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gmf.runtime.draw2d.ui.internal.routers.RectilinearRouter;
+import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil;
+import org.eclipse.papyrus.infra.tools.util.MathUtil;
+
+/**
+ *
+ * A rectilinear router which use the grid, when Snap To Grid is activated on the diagram
+ *
+ */
+@SuppressWarnings("restriction")
+public class RectilinearGridRouter extends RectilinearRouter {
+
+ /**
+ * an edit part of the diagram
+ */
+ private final EditPart anyEditPart;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param anyEditPart
+ * an edit part of the diagram
+ */
+ public RectilinearGridRouter(final EditPart anyEditPart) {
+ this.anyEditPart = anyEditPart;
+ }
+
+ /**
+ *
+ * @see org.eclipse.gmf.runtime.draw2d.ui.internal.routers.RectilinearRouter#routeLine(org.eclipse.draw2d.Connection, int,
+ * org.eclipse.draw2d.geometry.PointList)
+ *
+ * @param conn
+ * @param nestedRoutingDepth
+ * @param newLine
+ */
+ @Override
+ public void routeLine(final Connection conn, final int nestedRoutingDepth, final PointList newLine) {
+ List<Point> initialPoints = new ArrayList<Point>(newLine.size());
+ for(int i = 0; i < newLine.size(); i++) {
+ initialPoints.add(newLine.getPoint(i));
+ }
+
+ super.routeLine(conn, nestedRoutingDepth, newLine);
+
+ if(DiagramEditPartsUtil.isSnapToGridActive(anyEditPart)) {
+ double gridSpacing = DiagramEditPartsUtil.getDiagramGridSpacing(this.anyEditPart);
+ final int nbPoints = newLine.size();
+ if(nbPoints >= 3) {
+ //we don't move the anchor, we only move the intermediate points
+ PointList newLineCopy = newLine.getCopy();
+
+ for(int i = 1; i < newLine.size() - 1; i++) {
+ Point previousPoint = newLineCopy.getPoint(i - 1);
+ Point current = newLineCopy.getPoint(i);
+ PrecisionPoint newPoint = new PrecisionPoint(current.getCopy());
+ if(i > 0 && i < (nbPoints - 1)) {
+ boolean copyX = previousPoint.x == current.x;
+ boolean copyY = previousPoint.y == current.y;
+
+ if(!copyX) {
+ newPoint.setPreciseX(MathUtil.getClosestMultiple(current.x, gridSpacing));
+ } else {
+ newPoint.setPreciseX(newLine.getPoint(i - 1).x);
+ }
+ if(!copyY) {
+ newPoint.setPreciseY(MathUtil.getClosestMultiple(current.y, gridSpacing));
+ } else {
+ newPoint.setPreciseY(newLine.getPoint(i - 1).y);
+ }
+ }
+
+ if(i == nbPoints - 2) {
+ if(current.x == newLineCopy.getPoint(i + 1).x) {
+ newPoint.x = current.x;
+ }
+ if(current.y == newLineCopy.getPoint(i + 1).y) {
+ newPoint.y = current.y;
+ }
+ }
+ newLine.setPoint(newPoint, i);
+ }
+ }
+
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.gmf.runtime.draw2d.ui.internal.routers.ObliqueRouter#resetEndPointsToEdge(org.eclipse.draw2d.Connection,
+ * org.eclipse.draw2d.geometry.PointList)
+ *
+ * @param conn
+ * @param newLine
+ */
+ @Override
+ protected void resetEndPointsToEdge(Connection conn, PointList newLine) {
+ super.resetEndPointsToEdge(conn, newLine);
+ if(DiagramEditPartsUtil.isSnapToGridActive(this.anyEditPart)) {
+ double spacing = DiagramEditPartsUtil.getDiagramGridSpacing(this.anyEditPart);
+ //force end points on the grid!
+ CustomRouterHelper.getInstance().resetEndPointsToEdgeOnGrid(conn, newLine, spacing);
+ }
+ }
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/MathUtil.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/MathUtil.java
new file mode 100644
index 00000000000..a533c512c22
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/MathUtil.java
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * Copyright (c) 2014 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.tools.util;
+
+/**
+ *
+ * This class provides utils methods for mathematics
+ *
+ */
+public class MathUtil {
+
+ /**
+ *
+ * @param aValue
+ * a value
+ * @param base
+ * the base to use to find closest multiple
+ * @return
+ * the closed multiple
+ */
+ public static final double getClosestMultiple(final double aValue, final double base) {
+ int div = (int)(aValue / base);
+
+ double remainder = aValue % base;
+ if((remainder * 2) > base) {
+ div++;
+ }
+ return div * base;
+ }
+}

Back to the top