public class MyLinkShapePolicy extends IlvAbstractLinkShapePolicy { ... }
private void verifyLinkPoints(IlvLinkImage link) { if (link == null) return; IlvPoint[] pts = link.getLinkPoints(null); int n = pts.length; if (n <= 2) return; IlvRect fromrect = link.getFromBoundingBox(null); IlvRect torect = link.getToBoundingBox(null); float fx = fromrect.x + 0.5f * fromrect.width; float fy = fromrect.y + 0.5f * fromrect.height; float tx = torect.x + 0.5f * torect.width; float ty = torect.y + 0.5f * torect.height; float dx = (fx < tx ? 0.5f : -0.5f); float dy = (fy < ty ? 0.5f : -0.5f); if (n == 3) { link.movePoint(0, fx + dx * fromrect.width, fy, null); link.movePoint(1, tx, fy, null); link.movePoint(2, tx, ty - dy * torect.height, null); return; } if (Math.abs(fx - tx) > Math.abs(fy - ty)) { float middleX = 0.5f * (fx + tx + dx * (fromrect.width - torect.width)); pts[1].move(middleX, fy); pts[2].move(middleX, ty); link.movePoint(0, fx + dx * fromrect.width, fy, null); link.movePoint(n-1, tx - dx * torect.width, ty, null); } else { float middleY = 0.5f * (fy + ty + dy * (fromrect.height - torect.height)); pts[1].move(fx, middleY); pts[2].move(tx, middleY); link.movePoint(0, fx, fy + dy * fromrect.height, null); link.movePoint(n-1, tx, ty - dy * torect.height, null); } link.setIntermediateLinkPoints(pts, 1, 2); }
verifyLinkPoints
inside
the appropriate callback methods of the link shape policy. afterAdd
is
called when the link is already in the grapher. Since the link shape
policy will reshape the link and might change the bounding box of
the link, you must call the method applyToObject
: public void afterAdd(IlvLinkImage link) { if (link.getGraphicBag() != null) { link.getGraphicBag().applyToObject(link, new IlvApplyObject() { public void apply(IlvGraphic obj, Object arg) { verifyLinkPoints((IlvLinkImage)obj); } }, null, true); } else verifyLinkPoints(link); super.afterAdd(link); }
applyToObject
, therefore you
do not need to use this method again inside the link shape policy.
Hence, the code of the method onInstall
is
simpler. public void onInstall(IlvLinkImage link) { verifyLinkPoints(link); super.onInstall(link); }
public boolean allowInsertPoint(IlvLinkImage link, int index, float x, float y, IlvTransformer t) { int n = link.getPointsCardinal(); if (n >= 4) return false; return true; }
afterInsertPoint
, afterRemovePoint
,
and afterSetIntermediateLinkPoints
to call verifyLinkPoints
.
Note that all these methods are always called inside the method applyToObject
.
Thus, the code can omit an additional call to applyToObject
similar
to onInstall
: public void afterInsertPoint(IlvLinkImage link, int index, IlvTransformer t) { verifyLinkPoints(link); super.afterInsertPoint(link, index, t); } public void afterRemovePoint(IlvLinkImage link, int index, IlvTransformer t) { verifyLinkPoints(link); super.afterRemovePoint(link, index, t); } public void afterSetIntermediateLinkPoints(IlvLinkImage link) { verifyLinkPoints(link); super.afterSetIntermediateLinkPoints(link); }
public void afterApplyTransform(IlvLinkImage link, IlvTransformer t) { verifyLinkPoints(link); super.afterApplyTransform(link, t); }
public void afterFromNodeMoved(IlvLinkImage link) { verifyLinkPoints(link); super.afterFromNodeMoved(link); } public void afterToNodeMoved(IlvLinkImage link) { verifyLinkPoints(link); super.afterToNodeMoved(link); }
public boolean allowMovePoint(IlvLinkImage link, int index, float x, float y, IlvTransformer t) { return false; }
afterMovePoint
of
the link shape policy could be used to adjust the link shape after
moving points. However, since this link shape policy does not allow
point movement, the method afterMovePoint
need
not be overridden because point movements will never be executed. link.setLinkShapePolicy(new MyLinkShapePolicy());
MyLinkShapePolicy
is
designed for zoomable, rectangular end nodes that have no link connector
or a free link connector ( IlvFreeLinkConnector). If this is not the case, the method verifyLinkPoints
needs
to be adjusted to analyze the current transformer, the shape of the
end nodes, and the link connector.