/* * @(#)ArrowTip.java * * Copyright (c) 1996-2010 The authors and contributors of JHotDraw. * You may not use, copy or modify this file, except in compliance with the * accompanying license terms. */ package org.jhotdraw.draw.decoration; import org.jhotdraw.draw.*; import java.awt.geom.*; import org.jhotdraw.xml.DOMInput; import org.jhotdraw.xml.DOMOutput; import org.jhotdraw.xml.DOMStorable; /** * A {@link LineDecoration} which can draws an arrow tip. * <p> * The shape of the arrow can be controlled with three parameters: * <ul> * <li>angle - the angle in radians at which the two legs of the arrow meet.</li> * <li>outer radius - the length of the two legs of the arrow.</li> * <li>inner radius - the distance from the tip of the arrow to the point where * its end meets the line.</li> * </ul> * * @author Werner Randelshofer * @version $Id$ */ public class ArrowTip extends AbstractLineDecoration implements DOMStorable { private static final long serialVersionUID = 1L; /** * Pointiness of arrow. */ private double angle; private double outerRadius; private double innerRadius; public ArrowTip() { this(0.35, 12, 11.3); } /** * Constructs an arrow tip with the specified angle and outer and inner * radius. */ public ArrowTip(double angle, double outerRadius, double innerRadius) { this(angle, outerRadius, innerRadius, true, false, true); } /** * Constructs an arrow tip with the specified parameters. */ public ArrowTip(double angle, double outerRadius, double innerRadius, boolean isFilled, boolean isStroked, boolean isSolid) { super(isFilled, isStroked, isSolid); this.angle = angle; this.outerRadius = outerRadius; this.innerRadius = innerRadius; } @Override protected Path2D.Double getDecoratorPath(Figure f) { // FIXME - This should take the stroke join an the outer radius into // account to compute the offset properly. double offset = (isStroked()) ? 1 : 0; Path2D.Double path = new Path2D.Double(); path.moveTo((outerRadius * Math.sin(-angle)), (offset + outerRadius * Math.cos(-angle))); path.lineTo(0, offset); path.lineTo((outerRadius * Math.sin(angle)), (offset + outerRadius * Math.cos(angle))); if (innerRadius != 0) { path.lineTo(0, (innerRadius + offset)); path.closePath(); } return path; } @Override protected double getDecoratorPathRadius(Figure f) { double offset = (isStroked()) ? 0.5 : -0.1; return innerRadius + offset; } public double getAngle() { return angle; } public double getInnerRadius() { return innerRadius; } public double getOuterRadius() { return outerRadius; } @Override public void read(DOMInput in) { angle = in.getAttribute("angle", 0.35f); innerRadius = in.getAttribute("innerRadius", 12f); outerRadius = in.getAttribute("outerRadius", 12f); setFilled(in.getAttribute("isFilled", false)); setStroked(in.getAttribute("isStroked", false)); setSolid(in.getAttribute("isSolid", false)); } @Override public void write(DOMOutput out) { out.addAttribute("angle", angle); out.addAttribute("innerRadius", innerRadius); out.addAttribute("outerRadius", outerRadius); out.addAttribute("isFilled", isFilled()); out.addAttribute("isStroked", isStroked()); out.addAttribute("isSolid", isSolid()); } }