blob: 021649c024917c0490d3306a38e5a76cea7edc7a [file] [log] [blame]
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;
}
}