Creating a new class of link

The IlvPolylineLinkImage class

The following example shows the beginning of the class for the new link.
public class IlvPolylineLinkImage extends IlvLinkImage 
{ 
  private IlvPoint points[] = null;
 
  public IlvPolylineLinkImage(IlvGraphic from, IlvGraphic to, 
                              boolean oriented, IlvPoint[] points) 
  { 
    super(from, to, oriented);
    init(points); 
  ...
}
}
The new link is defined by a polyline, whose starting and ending positions are fixed and are based on the starting and ending positions of the nodes. This link is a subclass of the IlvLinkImage class.
The private field points will contain all the intermediate points of the link. The origin and destination points are not contained in this array.
The constructor calls the corresponding constructor of IlvLinkImage and initializes the object. The init method then fills the points field as follows.
private void init(IlvPoint[] pts) 
{ 
  if (pts == null) 
    return; 
  int i; 
  points = new IlvPoint[pts.length]; 
  for (i = 0; i < pts.length ; i++) 
    points[i] = new IlvPoint(pts[i].x, pts[i].y); 
}
There is also a copy constructor and a copy method that allow you to copy the object.
public IlvPolylineLinkImage(IlvPolylineLinkImage source) 
{ 
  super(source); 
  init(source.points); 
}

public IlvGraphic copy()
{
  return new IlvPolylineLinkImage(this);
}

getLinkPoints

The getLinkPoints method returns the points defining the shape of the link. This method is used by IlvLinkImage to draw the object and to define the bounding rectangle of the object. In the class IlvLinkImage , this method only returns the origin and destination points of the link. For the new polyline object, the getLinkPoints method adds the intermediate points of the link as follows.
public IlvPoint[] getLinkPoints(IlvTransformer t)
{ 
  int nbpoints = getPointsCardinal(); 
  IlvPoint[] pts = new IlvPoint[nbpoints]; 
  if (nbpoints > 2) 
    for (int i = 1 ; i < nbpoints-1; i++) {
      pts[i] = new IlvPoint(points[i-1]); 
      if (t != null) t.apply(pts[i]);
    } 
  pts[0] = new IlvPoint(); 
  pts[nbpoints-1] = new IlvPoint();
  getConnectionPoints(pts[0], pts[nbpoints-1], t); 
  return pts; 
}
The getConnectionPoints method is used to get the intermediate points. The getConnectionPoints method computes the origin and destination point of the link. These points may depend on the connection pins on the origin or destination object.

getPointCardinal, getPointAt

These methods, originating from the interface IlvPolyPointsInterface, are defined like this:
public int getPointsCardinal() 
{ 
  if (points == null) 
    return 2; 
  else 
    return points.length +2;
}
 
public IlvPoint getPointAt(int index, IlvTransformer t) 
{ 
  if (index == 0 || index == getPointsCardinal()-1) 
  { 
   IlvPoint[] pts = new IlvPoint[2]; 
   pts[0] = new IlvPoint(); 
   pts[1] = new IlvPoint(); 
   getConnectionPoints(pts[0], pts[1], t); 
   return pts[(index == 0) ? 0 : 1]; 
  }  
  else 
  { 
    IlvPoint p = new IlvPoint(points[index-1]); 
    if (t != null) 
      t.apply(p); 
    return p; 
  }
}

allowsPointInsertion, allowsPointRemoval

The allowPointAddition and allowPointRemoval methods are overridden to return true to allow the editing interactor associated with links (that is, IlvLinkImageEditInteractor), to add and remove points.:
public boolean allowsPointInsertion() 
{ 
  return true; 
}
 
public boolean allowsPointRemoval()
{   return points != null && points.length >= 1; 
}
Since these methods return true , the insertPoint and removePoint methods will be called from the interactor. They are defined as follows.
public void insertPoint(int index, float x, float y, 
                        IlvTransformer t) 
{
  if (points == null && index == 1) {
    points = new IlvPoint[1]; 
    points[0] = new IlvPoint(x,y);
  } 
  else if (index == 0) 
    throw new IllegalArgumentException("bad index");
  else if (index >= getPointsCardinal()) 
    throw new IllegalArgumentException("bad index"); 
  else index --; 
  if (index >= 0 && index <= points.length){ 
    IlvPoint[] oldp = points;
    points = new IlvPoint[oldp.length+1]; 
    System.arraycopy(oldp, index, points, index + 1, 
                     oldp.length - index);
    points[index] = new IlvPoint(x,y); 
    if (index > 0) 
      System.arraycopy(oldp, 0, points, 0, index);
  } 
  else throw new IllegalArgumentException("bad index");
}
 
public void removePoint(int index, IlvTransformer t) 
{ 
  if (index ==0) return;
  if (index == getPointsCardinal()-1) 
    return; 
  index --;
  if (points != null && index >= 0 && index < points.length) 
  {
    IlvPoint[] oldp = points;
    points = new IlvPoint[oldp.length-1];
    if (index > 0) 
      System.arraycopy(oldp, 0, points, 0, index); 
      int j = oldp.length - index - 1;
      if (j > 0) 
      System.arraycopy(oldp, index + 1, points, index, j); 
  } 
  else throw new IllegalArgumentException("bad index"); 
}

applyTransform

The method applyTransform is called when the bounding box is to be modified (when the object is moved or enlarged, for example). The transformation is applied to the intermediate points:
public void applyTransform(IlvTransformer t) 
{ 
  if (getPointsCardinal() > 2 && points != null) 
    for (int i = 0 ; i < points.length; i++) {
     if (t != null) t.apply(points[i]); 
    }
}

Input/Output

Input/output methods are needed to allow users to save and read the intermediate points.
The method write is defined as follows:
public void write(IlvOutputStream stream) throws IOException 
{ 
  super.write(stream); 
  stream.write("points", points);
}
The corresponding IlvInputStream constructor is as follows.
public IlvPolylineLinkImage(IlvInputStream stream) throws
                                              IlvReadFileException 
{ 
  super(stream); 
  IlvPoint[] points = stream.readPointArray("points");
  init(points); 
}