How to create and augment custom arrow styles
Applies to: yFiles 2.4 print article email article

Type: Tips & Tricks

This article demonstrates how to create new custom arrow styles or augment existing ones.

Class y.view.Arrow already defines some predefined arrow types that should suffice for most basic needs. Of course, creating custom arrows is also possible.

To change the appearance of the arrow completely, it is possible to register an own Shape or Drawable with several variants of the static methods Arrow.addCustomArrow. The following snippet changes the arrow to a red circle:
Graph2D g = new Graph2D();  
// Take a default PolyLineEdgeRealizer...
EdgeRealizer er = new PolyLineEdgeRealizer();
//the head of the shape should be at (0,0), the tail should be at (x, 0), where x < 0
//for a circle with diameter 10, this leads to the following coordinates
Drawable redCircle = new ShapeDrawable( new Ellipse2D.Double( -10, -5, 10, 10 ), Color.RED );
//add custom arrow
Arrow.addCustomArrow( "red circle", redCircle);
//set this custom arrow as target arrow for the realizer
ger.setTargetArrow( Arrow.getCustomArrow( "red circle"));
g.setDefaultEdgeRealizer( er );
If you just want to augment the appearance of an (existing or custom) arrow, you need a bit more work. Since class y.view.Arrow is final, it is not possible to overwrite its paintmethod. However, it is possible to delegate the painting of the base arrow to a Drawable, which can be decorated at will and registered with Arrow.addCustomArrow. The following snippet outlines this approach, where a predefined arrow is decorated with a green circle:
public DecoratingEdgeRealizerDemo() {
    super();
    Graph2D g = new Graph2D();	
    // Take a default PolyLineEdgeRealizer...
    EdgeRealizer ger = new PolyLineEdgeRealizer();

    Arrow baseArrow = Arrow.DELTA;
    //the location of the drawable is calculated like in the first example
    Drawable decoration = new ShapeDrawable( 
		new Ellipse2D.Double( -baseArrow.getArrowLength() - 10 - 1, -5, 10, 10 ), Color.GREEN );
    //create new drawable that augments the original arrow with the decoration
    Drawable drawable = new DecoratedArrowDrawable( baseArrow, decoration, false );
    Arrow.addCustomArrow( "decorated", drawable, drawable.getBounds().getWidth(), 0 );
    ger.setTargetArrow( Arrow.getCustomArrow( "decorated") );
    g.setDefaultEdgeRealizer( ger );
 }

  public static class DecoratedArrowDrawable implements Drawable {

    private Arrow delegateArrow;
    private Drawable decoration;
    private boolean drawDecorationFirst;

    /** Create a new drawable object that wraps an existing arrow.
     *
     * @param delegateArrow The base arrow that is decorated
     * @param decoration the decoration that is drawn additionally
     * @param drawDecorationFirst true iff decoration should be drawn first (below) the delegate arrow
     */
    public DecoratedArrowDrawable( Arrow delegateArrow, Drawable decoration, boolean drawDecorationFirst ) {
      this.delegateArrow = delegateArrow;
      this.decoration = decoration;
      this.drawDecorationFirst = drawDecorationFirst;
    }

    public void paint( Graphics2D g ) {
      if ( drawDecorationFirst ) {
        decoration.paint( g );
//dx and dy are measured in "arrow length" dimensions
        delegateArrow.paint( g, 0, 0, 1, 0 );
      } else {
        delegateArrow.paint( g, 0, 0, 1, 0 );
        decoration.paint( g );
      }
    }

    public Rectangle getBounds() {
      Rectangle unionRect = decoration.getBounds().union( new Rectangle(-1, -1, 1,1));
      return unionRect;
    }
  }

Keywords: EdgeRealizer - Arrow

Provide feedback:
How useful was this article?    less 1 2 3 4 5 more
Email address (optional):
COPYRIGHT © 2008 yWorks · ALL RIGHTS RESERVED imprint | top | home