The example creates a link shape policy
that allows links to have 0, 1 or 2 bend points. With 1 or 2
bends, the link will have an orthogonal shape. The link shape
policy prohibits the creation of more than 2 bends.
![fwadv_linkshape5.gif](../../JViews_Framework/usradvfwork/_media/fwadv_linkshape5_default.gif)
Link shape policy for 0, 1 or 2 bends
In principle, this link shape policy is a combination of the
functionality of the classes IlvOneLinkImage and IlvDoubleLinkImage (see Links of The Essential JViews Framework). However,
using a link shape policy is more flexible, because the link shape
policy can be enabled and disabled on the link, and can change
from a 1-bend image to a 2-bend image.
The class IlvAbstractLinkShapePolicy is a suitable
base class for the new link shape policy because it defines all
the methods of the interface IlvLinkShapePolicy as empty methods.
public class MyLinkShapePolicy extends IlvAbstractLinkShapePolicy { ... }
You can concentrate on the few methods that
you need to override.
To create your link shape policy:
-
Create an auxiliary method that reshapes the link according to the policy. Depending on the number of bends and the horizontal and vertical distance, you can decide which shape the link should have. For instance:
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); }
-
When the link policy is set on a link, or when a link is added to the grapher, you have to ensure that the link shape is correct. Call the method
verifyLinkPoints
inside the appropriate callback methods of the link shape policy.The callback methodafterAdd
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 methodapplyToObject
: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); }
-
When you set the link shape policy, you can rely on the user to call
applyToObject
, therefore you do not need to use this method again inside the link shape policy. Hence, the code of the methodonInstall
is simpler.public void onInstall(IlvLinkImage link) { verifyLinkPoints(link); super.onInstall(link); }
-
The link shape policy allows the link to have 0, 1, or 2 bends. Since the two end points of the link are counted in the link cardinality, you just have to forbid insertion of more than four points, so that there will never be more than two bends:
public boolean allowInsertPoint(IlvLinkImage link, int index, float x, float y, IlvTransformer t) { int n = link.getPointsCardinal(); if (n >= 4) return false; return true; }
-
When bends are inserted or removed, the link policy must reshape the link so that it has the desired shape for this number of bends. Therefore, you override the methods
afterInsertPoint
,afterRemovePoint
, andafterSetIntermediateLinkPoints
to callverifyLinkPoints
. Note that all these methods are always called inside the methodapplyToObject
. Thus, the code can omit an additional call toapplyToObject
similar toonInstall
: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); }
-
Changing the transformation of a polyline link image usually also modifies the bends of the link. Therefore the link points need to be verified here as well.
public void afterApplyTransform(IlvLinkImage link, IlvTransformer t) { verifyLinkPoints(link); super.afterApplyTransform(link, t); }
-
When an end node of the link is moved, the 1 or 2 bends of the link must adjust accordingly. Therefore it is necessary to override the corresponding callback methods of the link shape policy.
public void afterFromNodeMoved(IlvLinkImage link) { verifyLinkPoints(link); super.afterFromNodeMoved(link); } public void afterToNodeMoved(IlvLinkImage link) { verifyLinkPoints(link); super.afterToNodeMoved(link); }
-
The link shape policy defines the positions of the bends completely. Therefore the policy forbids modification of the positions of the bends; that is, you are not allowed to move a point.
public boolean allowMovePoint(IlvLinkImage link, int index, float x, float y, IlvTransformer t) { return false; }
The callback method
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.
The new link shape policy works for all subclasses of IlvPolicyAwareLinkImage. It can be set on a
link as follows:
link.setLinkShapePolicy(new MyLinkShapePolicy());
Note
For simplicity, the example class
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.