package com.kreative.paint.material.shape; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; public class PowerShape implements Cloneable, Shape { private final SortedMap<String,Parameter> parameters; private final SortedMap<String,Point2D> parameterValues; private final Bindings parameterBindings; private final List<ParameterizedShape> shapes; private transient GeneralPath awtShape; public final WindingRule windingRule; public final String name; public PowerShape(WindingRule windingRule, String name) { this.parameters = new TreeMap<String,Parameter>(); this.parameterValues = new TreeMap<String,Point2D>(); this.parameterBindings = new ParameterBindings(parameters, parameterValues); this.shapes = new ArrayList<ParameterizedShape>(); this.awtShape = null; this.windingRule = windingRule; this.name = name; } @Override public PowerShape clone() { PowerShape clone = new PowerShape(this.windingRule, this.name); clone.parameters.putAll(this.parameters); for (Map.Entry<String,Point2D> e : this.parameterValues.entrySet()) { Point2D p = e.getValue(); p = new Point2D.Double(p.getX(), p.getY()); clone.parameterValues.put(e.getKey(), p); } clone.shapes.addAll(this.shapes); return clone; } public void addParameter(Parameter p) { parameters.put(p.name, p); awtShape = null; } public List<String> getParameterNames() { List<String> names = new ArrayList<String>(); names.addAll(parameters.keySet()); return Collections.unmodifiableList(names); } public Parameter getParameter(String name) { return parameters.get(name); } public Point2D getParameterValue(String name) { Parameter p = parameters.get(name); if (p == null) return null; return p.getLocation(parameterValues); } public void setParameterValue(String name, double x, double y) { Parameter p = parameters.get(name); if (p == null) return; p.setLocation(parameterValues, x, y); awtShape = null; } public void addShape(ParameterizedShape shape) { shapes.add(shape); awtShape = null; } public List<ParameterizedShape> getShapes() { return Collections.unmodifiableList(shapes); } @Override public boolean equals(Object that) { if (that instanceof PowerShape) { return this.equals((PowerShape)that, false); } else { return false; } } public boolean equals(PowerShape that, boolean withName) { if (!this.parameters.equals(that.parameters)) return false; if (!this.parameterValues.equals(that.parameterValues)) return false; if (!this.shapes.equals(that.shapes)) return false; if (this.windingRule != that.windingRule) return false; if (!withName) return true; if (this.name == null) return (that.name == null); if (that.name == null) return (this.name == null); return this.name.equals(that.name); } @Override public int hashCode() { return parameters.hashCode() ^ parameterValues.hashCode() ^ shapes.hashCode(); } private void makeAWTShape() { awtShape = new GeneralPath(); if (windingRule != null) { awtShape.setWindingRule(windingRule.awtValue); } for (ParameterizedShape shape : shapes) { awtShape.append(shape.awtShape(parameterBindings), false); } } @Override public boolean contains(Point2D p) { if (awtShape == null) makeAWTShape(); return awtShape.contains(p); } @Override public boolean contains(Rectangle2D r) { if (awtShape == null) makeAWTShape(); return awtShape.contains(r); } @Override public boolean contains(double x, double y) { if (awtShape == null) makeAWTShape(); return awtShape.contains(x, y); } @Override public boolean contains(double x, double y, double w, double h) { if (awtShape == null) makeAWTShape(); return awtShape.contains(x, y, w, h); } @Override public Rectangle getBounds() { if (awtShape == null) makeAWTShape(); return awtShape.getBounds(); } @Override public Rectangle2D getBounds2D() { if (awtShape == null) makeAWTShape(); return awtShape.getBounds2D(); } @Override public PathIterator getPathIterator(AffineTransform t) { if (awtShape == null) makeAWTShape(); return awtShape.getPathIterator(t); } @Override public PathIterator getPathIterator(AffineTransform t, double s) { if (awtShape == null) makeAWTShape(); return awtShape.getPathIterator(t, s); } @Override public boolean intersects(Rectangle2D r) { if (awtShape == null) makeAWTShape(); return awtShape.intersects(r); } @Override public boolean intersects(double x, double y, double w, double h) { if (awtShape == null) makeAWTShape(); return awtShape.intersects(x, y, w, h); } }