Creating a Custom Grapher link

In this section, IlvLinkImage is subclassed to create a grapher link that meets the following specifications:

  • The link is always drawn as a straight line between its two nodes.

  • The start point is either defined by a connection pin or located at the center of the start node.

  • The end point is such that the link stays perpendicular to the face of the end node closest to the start point. If this cannot be done, the end point is located on the closest corner of the node bounding box.

The link is drawn the same way as in the base class IlvLinkImage. Therefore, the corresponding methods inherited from IlvGraphic are left unchanged. Also, there are only two points defining the shape of the link (the two end points, and no intermediate points). There are two possibilities for defining the link: overloading the ::getLinkPoints method or the ::computePoints method. The second alternative has been chosen for this example:

void

MyLink::computePoints(IlvPoint& src,

IlvPoint& dst,

const IlvTransformer* t) const

{

//== [1] ==

IlvGrapherPin* pin = IlvGrapherPin::Get(getFrom());

if (!pin || !pin->getLinkLocation(getFrom(),this,t,src)) {

IlvRect bbox;

getFrom()->boundingBox(bbox,t);

src.move(bbox.centerx(),bbox.centery());

}

 

//== [2] ==

IlvRect toBBox;

getTo()->boundingBox(toBBox,t);

if (src.x()<toBBox.x()) {

if (src.y() < toBBox.y()) // Upper left quadrant

dst.move(toBBox.x(),

toBBox.y());

else if (src.y() >= toBBox.bottom()) // Lower left quadrant

dst.move(toBBox.x(),

toBBox.y()+toBBox.h()-1);

else // Left quadrant

dst.move(toBBox.x(),

src.y());

} else if (src.x()>=toBBox.right()) {

 

if (src.y() < toBBox.y()) // Upper right quadrant

dst.move(toBBox.x()+toBBox.w()-1,

toBBox.y());

else if (src.y() >= toBBox.bottom()) // Lower right quadrant

dst.move(toBBox.x()+toBBox.w()-1,

toBBox.y()+toBBox.h()-1);

else // Right quadrant

dst.move(toBBox.x()+toBBox.w()-1,

src.y());

} else {

if (src.y() < toBBox.y()) // Upper quadrant

dst.move(src.x(),

toBBox.y());

else if (src.y() >= toBBox.bottom()) // Lower quadrant

dst.move(src.x(),

toBBox.y()+toBBox.h()-1);

else // src inside toBBox

dst.move(toBBox.centerx(),toBBox.centery());

}

}

In the first part ([1]) of the code, a verification is made to see whether the link is attached to a connection pin defined on its start node. If this is not the case, the center of the bounding box of this node is taken.

Once the location of the start point has been computed, the position of the start point with respect to the bounding box of the end node is verified ([2]). There are nine possible cases (the eight quadrants defined by toBBox, plus the case where the start point is inside toBBox), each defining a unique location.