package com.kreative.paint.document.draw;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class GroupDrawObject extends DrawObject {
private List<DrawObject> objects;
private Rectangle2D boundary;
private double x1, y1, x2, y2;
public GroupDrawObject(Collection<DrawObject> objects) {
super((PaintSettings)null);
this.objects = new ArrayList<DrawObject>();
Area ba = new Area();
for (DrawObject o : objects) {
this.objects.add(o.clone());
ba.add(new Area(o.getBounds2D()));
}
this.boundary = ba.getBounds2D();
this.x1 = boundary.getMinX();
this.y1 = boundary.getMinY();
this.x2 = boundary.getMaxX();
this.y2 = boundary.getMaxY();
}
public GroupDrawObject(Collection<DrawObject> objects, double x, double y, double width, double height) {
super((PaintSettings)null);
this.objects = new ArrayList<DrawObject>();
Area ba = new Area();
for (DrawObject o : objects) {
this.objects.add(o.clone());
ba.add(new Area(o.getBounds2D()));
}
this.boundary = ba.getBounds2D();
this.x1 = x;
this.y1 = y;
this.x2 = x + width;
this.y2 = y + height;
}
private GroupDrawObject(GroupDrawObject original) {
super(original);
this.objects = new ArrayList<DrawObject>();
Area ba = new Area();
for (DrawObject o : original.objects) {
this.objects.add(o.clone());
ba.add(new Area(o.getBounds2D()));
}
this.boundary = ba.getBounds2D();
this.x1 = original.x1;
this.y1 = original.y1;
this.x2 = original.x2;
this.y2 = original.y2;
}
@Override
public GroupDrawObject clone() {
return new GroupDrawObject(this);
}
public double getX() { return x1; }
public double getY() { return y1; }
public double getWidth() { return x2 - x1; }
public double getHeight() { return y2 - y1; }
private AffineTransform getGroupTransform() {
AffineTransform tx = new AffineTransform();
tx.translate(x1, y1);
tx.scale((x2 - x1) / boundary.getWidth(), (y2 - y1) / boundary.getHeight());
tx.translate(-boundary.getX(), -boundary.getY());
return tx;
}
@Override
protected Shape getBoundaryImpl() {
return getGroupTransform().createTransformedShape(boundary);
}
@Override
protected Shape getPostTxHitAreaImpl(AffineTransform tx) {
AffineTransform tx2 = new AffineTransform();
if (tx != null) tx2.concatenate(tx);
tx2.concatenate(getGroupTransform());
Area a = new Area();
for (DrawObject o : objects) {
a.add(new Area(o.getHitArea(tx2)));
}
return a;
}
@Override
protected Object getControlState() {
return new double[]{ x1, y1, x2, y2 };
}
@Override
protected void setControlState(Object o) {
double[] state = (double[])o;
x1 = state[0]; y1 = state[1];
x2 = state[2]; y2 = state[3];
}
@Override
public int getControlPointCount() {
return 9;
}
@Override
protected ControlPoint getControlPointImpl(int i) {
switch (i) {
case 0: return new ControlPoint(ControlPointType.CENTER, (x1 + x2) / 2, (y1 + y2) / 2);
case 1: return new ControlPoint(ControlPointType.NORTHWEST, x1, y1);
case 2: return new ControlPoint(ControlPointType.NORTHEAST, x2, y1);
case 3: return new ControlPoint(ControlPointType.SOUTHWEST, x1, y2);
case 4: return new ControlPoint(ControlPointType.SOUTHEAST, x2, y2);
case 5: return new ControlPoint(ControlPointType.NORTH, (x1 + x2) / 2, y1);
case 6: return new ControlPoint(ControlPointType.SOUTH, (x1 + x2) / 2, y2);
case 7: return new ControlPoint(ControlPointType.WEST, x1, (y1 + y2) / 2);
case 8: return new ControlPoint(ControlPointType.EAST, x2, (y1 + y2) / 2);
default: return null;
}
}
@Override
protected List<ControlPoint> getControlPointsImpl() {
List<ControlPoint> cpts = new ArrayList<ControlPoint>();
cpts.add(new ControlPoint(ControlPointType.CENTER, (x1 + x2) / 2, (y1 + y2) / 2));
cpts.add(new ControlPoint(ControlPointType.NORTHWEST, x1, y1));
cpts.add(new ControlPoint(ControlPointType.NORTHEAST, x2, y1));
cpts.add(new ControlPoint(ControlPointType.SOUTHWEST, x1, y2));
cpts.add(new ControlPoint(ControlPointType.SOUTHEAST, x2, y2));
cpts.add(new ControlPoint(ControlPointType.NORTH, (x1 + x2) / 2, y1));
cpts.add(new ControlPoint(ControlPointType.SOUTH, (x1 + x2) / 2, y2));
cpts.add(new ControlPoint(ControlPointType.WEST, x1, (y1 + y2) / 2));
cpts.add(new ControlPoint(ControlPointType.EAST, x2, (y1 + y2) / 2));
return cpts;
}
@Override
protected Collection<Line2D> getControlLinesImpl() {
return null;
}
@Override
protected int setControlPointImpl(int i, double x, double y) {
switch (i) {
case 0:
double width2 = (x2 - x1) / 2;
double height2 = (y2 - y1) / 2;
x1 = x - width2;
y1 = y - height2;
x2 = x + width2;
y2 = y + height2;
break;
case 1: x1 = x; y1 = y; break;
case 2: x2 = x; y1 = y; break;
case 3: x1 = x; y2 = y; break;
case 4: x2 = x; y2 = y; break;
case 5: y1 = y; break;
case 6: y2 = y; break;
case 7: x1 = x; break;
case 8: x2 = x; break;
}
return i;
}
@Override
protected Point2D getLocationImpl() {
return new Point2D.Double(x1, y1);
}
@Override
protected void setLocationImpl(double x, double y) {
this.x2 = x + (this.x2 - this.x1);
this.y2 = y + (this.y2 - this.y1);
this.x1 = x;
this.y1 = y;
}
@Override
protected void preTxPaintImpl(Graphics2D g, AffineTransform tx) {
AffineTransform tx2 = new AffineTransform();
if (tx != null) tx2.concatenate(tx);
tx2.concatenate(getGroupTransform());
for (DrawObject o : objects) {
if (o.visible) o.paint(g, tx2);
}
}
public List<DrawObject> getObjects() {
List<DrawObject> objects = new ArrayList<DrawObject>();
for (DrawObject o : this.objects) {
objects.add(o.clone());
}
return objects;
}
public List<DrawObject> ungroup() {
List<DrawObject> ungrouped = new ArrayList<DrawObject>();
for (DrawObject o : this.objects) {
o = o.clone();
AffineTransform tx = new AffineTransform();
if (this.tx != null) tx.concatenate(this.tx);
tx.concatenate(getGroupTransform());
if (o.tx != null) tx.concatenate(o.tx);
o.tx = tx;
ungrouped.add(o);
}
return ungrouped;
}
}