package com.kreative.paint.material.stroke;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class Arrowhead implements List<ArrowheadShape> {
public static final Arrowhead GENERAL_FILLED_ARROW = new Arrowhead(true, ArrowheadShape.GENERAL_FILLED_ARROW);
public static final Arrowhead GENERAL_STROKED_ARROW = new Arrowhead(true, ArrowheadShape.GENERAL_STROKED_ARROW);
public static final Arrowhead GENERAL_FILLED_CIRCLE = new Arrowhead(true, ArrowheadShape.GENERAL_FILLED_CIRCLE);
public static final Arrowhead GENERAL_STROKED_CIRCLE = new Arrowhead(true, ArrowheadShape.GENERAL_STROKED_CIRCLE);
private final List<ArrowheadShape> shapes;
public final boolean scale;
public Arrowhead(boolean scale) {
this.shapes = new ArrayList<ArrowheadShape>();
this.scale = scale;
}
private Arrowhead(boolean scale, ArrowheadShape... shapes) {
List<ArrowheadShape> shapesIntl = new ArrayList<ArrowheadShape>();
for (ArrowheadShape shape : shapes) shapesIntl.add(shape);
this.shapes = Collections.unmodifiableList(shapesIntl);
this.scale = scale;
}
public Shape createArrowhead(float prevX, float prevY, float endX, float endY, float lineWidth) {
float s = scale ? (((lineWidth-1)/2)+1) : 1;
double r = Math.atan2(endY-prevY, endX-prevX);
AffineTransform st = AffineTransform.getScaleInstance(s, s);
AffineTransform rt = AffineTransform.getRotateInstance(r);
AffineTransform tt = AffineTransform.getTranslateInstance(endX, endY);
Area a = new Area();
for (ArrowheadShape ash : shapes) {
Shape sh = st.createTransformedShape(ash);
if (ash.fill) {
a.add(new Area(sh));
}
if (ash.stroke) {
Stroke stroke = ash.getStroke(lineWidth);
a.add(new Area(stroke.createStrokedShape(sh)));
}
}
Shape sh = rt.createTransformedShape(a);
return tt.createTransformedShape(sh);
}
@Override
public boolean equals(Object that) {
if (that instanceof Arrowhead) {
return (this.shapes.equals(((Arrowhead)that).shapes))
&& (this.scale == ((Arrowhead)that).scale);
} else {
return false;
}
}
@Override
public int hashCode() {
int hashCode = shapes.hashCode();
if (scale) hashCode ^= -1;
return hashCode;
}
@Override
public boolean add(ArrowheadShape e) {
return shapes.add(e);
}
@Override
public void add(int index, ArrowheadShape element) {
shapes.add(index, element);
}
@Override
public boolean addAll(Collection<? extends ArrowheadShape> c) {
return shapes.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends ArrowheadShape> c) {
return shapes.addAll(index, c);
}
@Override
public void clear() {
shapes.clear();
}
@Override
public boolean contains(Object o) {
return shapes.contains(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return shapes.containsAll(c);
}
@Override
public ArrowheadShape get(int index) {
return shapes.get(index);
}
@Override
public int indexOf(Object o) {
return shapes.indexOf(o);
}
@Override
public boolean isEmpty() {
return shapes.isEmpty();
}
@Override
public Iterator<ArrowheadShape> iterator() {
return shapes.iterator();
}
@Override
public int lastIndexOf(Object o) {
return shapes.lastIndexOf(o);
}
@Override
public ListIterator<ArrowheadShape> listIterator() {
return shapes.listIterator();
}
@Override
public ListIterator<ArrowheadShape> listIterator(int index) {
return shapes.listIterator(index);
}
@Override
public boolean remove(Object o) {
return shapes.remove(o);
}
@Override
public ArrowheadShape remove(int index) {
return shapes.remove(index);
}
@Override
public boolean removeAll(Collection<?> c) {
return shapes.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return shapes.retainAll(c);
}
@Override
public ArrowheadShape set(int index, ArrowheadShape element) {
return shapes.set(index, element);
}
@Override
public int size() {
return shapes.size();
}
@Override
public List<ArrowheadShape> subList(int fromIndex, int toIndex) {
return shapes.subList(fromIndex, toIndex);
}
@Override
public Object[] toArray() {
return shapes.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return shapes.toArray(a);
}
}