| package org.eclipse.gmf.tooling.runtime.linklf; |
| |
| import java.util.Arrays; |
| import java.util.Map; |
| |
| import org.eclipse.draw2d.Connection; |
| import org.eclipse.draw2d.ConnectionAnchor; |
| import org.eclipse.draw2d.ConnectionRouter; |
| import org.eclipse.draw2d.geometry.Point; |
| import org.eclipse.draw2d.geometry.PointList; |
| import org.eclipse.gef.NodeEditPart; |
| import org.eclipse.gef.Request; |
| import org.eclipse.gef.editparts.AbstractConnectionEditPart; |
| import org.eclipse.gef.requests.DropRequest; |
| import org.eclipse.gef.requests.ReconnectRequest; |
| import org.eclipse.gmf.runtime.diagram.ui.editparts.INodeEditPart; |
| import org.eclipse.gmf.runtime.diagram.ui.editpolicies.GraphicalNodeEditPolicy; |
| import org.eclipse.gmf.runtime.draw2d.ui.internal.routers.OrthogonalRouter; |
| import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure; |
| import org.eclipse.gmf.tooling.runtime.linklf.editparts.LinkLFAnchorsDelegatingEditPart.ConnectionAnchorDelegate; |
| |
| /** |
| * Shared delegate for creation of the {@link SlidableSnapToGridAnchor} for host |
| * {@link INodeEditPart}s. |
| * <p/> |
| * Implemented as a delegate to be easily installed to different |
| * {@link NodeEditPart} sub-classes that does not share common diagram-specific |
| * base class. |
| * <p/> |
| * |
| * @since 3.3 |
| */ |
| public class LinkLFShapeNodeAnchorDelegate implements ConnectionAnchorDelegate { |
| |
| /** |
| * The {@link LinkLFShapeNodeAnchorDelegate} performs additional routing to |
| * adjust anchor's position for {@link ReconnectRequest}. In some cases, |
| * when active router is {@link OrthogonalRouter}, adjusted anchor position |
| * requires also changing the other link bendpoints. However, GEF/GMF |
| * Runtime' API does not allow to return the already recomputed bendpoints |
| * directly. |
| * <p/> |
| * The only way we found to pass them to {@link GraphicalNodeEditPolicy} is |
| * to put them into the {@link Request#getExtendedData()}. |
| * <p/> |
| * and This constant will be used as a key for the adjusted link bendpoints |
| * after rerouting. |
| */ |
| public static final String KEY_ROUTED_LINK_POINTS = LinkLFShapeNodeAnchorDelegate.class |
| .getName() + ":RoutedPoints"; |
| |
| private NodeFigure myNodeFigure; |
| |
| public LinkLFShapeNodeAnchorDelegate(NodeFigure nodeFigure) { |
| myNodeFigure = nodeFigure; |
| } |
| |
| public NodeFigure getNodeFigure() { |
| return myNodeFigure; |
| } |
| |
| @Override |
| public ConnectionAnchor getSourceConnectionAnchor(Request request) { |
| Point fromRequest = safeGetPointFromLinkRequest(request); |
| ConnectionAnchor result = getNodeFigure().getSourceConnectionAnchorAt( |
| fromRequest); |
| if (request instanceof ReconnectRequest) { |
| ReconnectRequest reqImpl = (ReconnectRequest) request; |
| AbstractConnectionEditPart linkEP = (AbstractConnectionEditPart) reqImpl |
| .getConnectionEditPart(); |
| Connection conn = linkEP.getConnectionFigure(); |
| ConnectionRouter router = conn.getConnectionRouter(); |
| PointList pointsBefore = conn.getPoints().getCopy(); |
| ConnectionAnchor oldSourceAnchor = conn.getSourceAnchor(); |
| conn.setSourceAnchor(result); |
| router.route(conn); |
| PointList pointsAfter = conn.getPoints().getCopy(); |
| Point routedLocation = pointsAfter.getFirstPoint(); |
| conn.translateToAbsolute(routedLocation); |
| result = getNodeFigure() |
| .getSourceConnectionAnchorAt(routedLocation); |
| if (!Arrays.equals(pointsAfter.toIntArray(), |
| pointsBefore.toIntArray())) { |
| conn.setPoints(pointsBefore); |
| if (router instanceof OrthogonalRouter) { |
| @SuppressWarnings("unchecked") |
| Map<String, Object> extData = request.getExtendedData(); |
| extData.put(KEY_ROUTED_LINK_POINTS, pointsAfter); |
| } |
| } |
| conn.setSourceAnchor(oldSourceAnchor); |
| } |
| return result; |
| } |
| |
| @Override |
| public ConnectionAnchor getTargetConnectionAnchor(Request request) { |
| Point fromRequestAbs = safeGetPointFromLinkRequest(request); |
| ConnectionAnchor result = getNodeFigure().getTargetConnectionAnchorAt( |
| fromRequestAbs); |
| if (request instanceof ReconnectRequest) { |
| ReconnectRequest reqImpl = (ReconnectRequest) request; |
| AbstractConnectionEditPart linkEP = (AbstractConnectionEditPart) reqImpl |
| .getConnectionEditPart(); |
| Connection conn = linkEP.getConnectionFigure(); |
| ConnectionRouter router = conn.getConnectionRouter(); |
| PointList pointsBefore = conn.getPoints().getCopy(); |
| ConnectionAnchor oldTargetAnchor = conn.getTargetAnchor(); |
| conn.setTargetAnchor(result); |
| router.route(conn); |
| PointList pointsAfter = conn.getPoints().getCopy(); |
| Point routedTarget = pointsAfter.getLastPoint(); |
| conn.translateToAbsolute(routedTarget); |
| result = getNodeFigure().getTargetConnectionAnchorAt(routedTarget); |
| if (!Arrays.equals(pointsAfter.toIntArray(), |
| pointsBefore.toIntArray())) { |
| conn.setPoints(pointsBefore); |
| if (router instanceof OrthogonalRouter) { |
| @SuppressWarnings("unchecked") |
| Map<String, Object> extData = request.getExtendedData(); |
| extData.put(KEY_ROUTED_LINK_POINTS, pointsAfter); |
| } |
| } |
| conn.setTargetAnchor(oldTargetAnchor); |
| } |
| return result; |
| } |
| |
| private Point safeGetPointFromLinkRequest(Request request) { |
| Point result = null; |
| if (request instanceof DropRequest) { |
| result = ((DropRequest) request).getLocation(); |
| } |
| // additional copy for ReconnectRequest, dont know why, |
| // but see, e.g, ShapeNodeEditPart#getSourceConnectionAnchor |
| if (result != null && request instanceof ReconnectRequest) { |
| result = result.getCopy(); |
| } |
| return result; |
| } |
| |
| } |