/*
* @(#)CompositeLineDecoration.java
*
* Copyright (c) 2007 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.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jhotdraw.xml.DOMInput;
import org.jhotdraw.xml.DOMOutput;
import org.jhotdraw.xml.DOMStorable;
/**
* A {@link LineDecoration} which can compose multiple individual line
* decorations.
* <p>
* An composite implementation of a line decoration. It allows more than
* one line decoration shape to be rotated and moved to the end of the line.
* The shape is scaled by the stroke width.
*
* @author Huw Jones
*/
public class CompositeLineDecoration implements LineDecoration, DOMStorable {
private static final long serialVersionUID = 1L;
private List<LineDecoration> decorations = new ArrayList<LineDecoration>();
/**
* Constructs a composite line decoration with no decorations.
*/
public CompositeLineDecoration() {
}
/**
* Constructs a composite line decoration with the two supplied decorations.
*/
public CompositeLineDecoration(LineDecoration decoration1, LineDecoration decoration2) {
addDecoration(decoration1);
addDecoration(decoration2);
}
/**
* Add another line decoration into the composite line decoration.
* The new decoration will be appended to the existing decorations
* and is also the last drawn.
*/
public void addDecoration(LineDecoration decoration) {
if (decoration != null) {
decorations.add(decoration);
}
}
/**
* Draws the arrow tip in the direction specified by the given two
* Points.. (template method)
*/
@Override
public void draw(Graphics2D g, Figure f, Point2D.Double p1, Point2D.Double p2) {
for (LineDecoration decoration : decorations) {
decoration.draw(g, f, p1, p2);
}
}
/**
* Returns the drawing area of the decorator.
*/
@Override
public Rectangle2D.Double getDrawingArea(Figure f, Point2D.Double p1, Point2D.Double p2) {
Rectangle2D.Double r = null;
for (LineDecoration decoration : decorations) {
Rectangle2D.Double aR = decoration.getDrawingArea(f, p1, p2);
if (r == null)
r = aR;
else
r.add(aR);
}
return r;
}
/**
* Returns the radius of the decorator.
* This is used to crop the end of the line, to prevent it from being
* drawn it over the decorator.
*/
@Override
public double getDecorationRadius(Figure f) {
double radius = 0;
for (LineDecoration decoration : decorations) {
radius = Math.max(radius, decoration.getDecorationRadius(f));
}
return radius;
}
@Override
public void read(DOMInput in) throws IOException {
for (int i = in.getElementCount("decoration") - 1; i >= 0; i--) {
in.openElement("decoration", i);
Object value = in.readObject();
if (value instanceof LineDecoration)
addDecoration((LineDecoration)value);
in.closeElement();
}
}
@Override
public void write(DOMOutput out) throws IOException {
for (LineDecoration decoration : decorations) {
out.openElement("decoration");
out.writeObject(decoration);
out.closeElement();
}
}
}