Defining your own link shape policy
Describes the callback methods of the class
IlvLinkShapePolicy and uses an example to explain how you can define your own link shape policy.
Describes the callback methods of the link shape policy class and explains how they are used.
Uses an example to show how you can implement your own link shape policy.
Describes the relationships between the link shape policy classes with a class diagram.
Callback methods of IlvLinkShapePolicy
In addition to the predefined link shape policies, the JViews Framework allows you to define your own link shape policies.
In general, when a method of
IlvPolicyAwareLinkImage is called that may change the shape of the link, the following procedure is used by the policy-aware link image:
1. The link shape policy is temporary disabled to avoid endless recursion when calling methods on the link inside the link shape policy.
2. The link shape policy is asked whether the change is allowed. For instance, when the method link.insertPoint is called, the policy is asked by method policy.allowInsertPoint whether inserting the point is allowed.
3. If the change is allowed, it is done (for example, the point is inserted).
4. The “after change” callback method of the link shape policy is called. For instance, inside link.insertPoint, the method policy.afterInsertPoint is called. This allows the policy to react to the change.
5. The link shape policy is enabled again.
6. The method afterAny is called at the end. Since, at this point, the link shape policy is enabled, this method should not reshape the link any further. It can however perform cleanup operations.
Callback methods of IlvLinkShapePolicy used by IlvPolicyAwareLinkImage
Method of IlvPolicyAwareLinkImage | Test Method in IlvLinkShapePolicy | After Method in IlvLinkShapePolicy | Comment |
setLinkShapePolicy | | onInstall | Applied to the new policy |
setLinkShapePolicy | | onUninstall | Applied to the old policy |
insertPoint | allowInsertPoint | afterInsertPoint | |
removePoint | allowRemovePoint | afterRemovePoint | |
movePoint | allowMovePoint | afterMovePoint | |
setIntermediateLinkPoints | allowSetIntermediateLinkPoints | afterSetIntermediateLinkPoints | |
applyTransform | allowApplyTransform | afterApplyTransform | |
| | afterAdd | Applied after a link has been added to a grapher |
| | beforeRemove | Applied before a link is removed from a grapher |
| | afterFromNodeMoved | Applied when the source node of the link has been moved |
| | afterToNodeMoved | Applied when the destination node of the link has been moved |
| | afterAny | Applied after any of the methods mentioned above |
Creating a link shape policy with up to two bends
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.
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:
1. 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);
}
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 method 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);
}
3. 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 method onInstall is simpler.
public void onInstall(IlvLinkImage link)
{
verifyLinkPoints(link);
super.onInstall(link);
}
4. 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;
}
5. 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, 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);
}
6. 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);
}
7. 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);
}
8. 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.
Class diagram for link shape policies
The following UML class diagram summarizes all classes related to IlvLinkShapePolicy.
Subclasses of IlvPolicyAwareLinkImage can have link shape policies. Normally, link shape policies can be shared by different links. Subclasses of IlvAbstractLinkShapePolicy allow you to link the policies using the child policy handle. This allows you to install multiple policies on a link. The IlvCrossingLinkShapePolicy calculates the crossing points of an IlvCrossingAwareLinkImage. The crossings are drawn using a crossing graphic; that is, an IlvGraphic that additionally implements the IlvCrossingGraphic interface.
The classes related to IlvLinkShapePolicy
Copyright © 2018, Rogue Wave Software, Inc. All Rights Reserved.