package com.kreative.paint.draw;
import java.awt.Graphics2D;
import java.awt.Shape;
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;
import com.kreative.paint.document.draw.ControlPoint;
import com.kreative.paint.document.draw.ControlPointType;
import com.kreative.paint.document.draw.DrawObject;
import com.kreative.paint.document.draw.PaintSettings;
public class GridDrawObject extends DrawObject {
public static final int NONE = 0;
public static final int LINEAR = 1;
public static final int LOGARITHMIC = 2;
private double x1, y1, x2, y2;
private int horizGridType;
private double horizGridSpacing;
private int vertGridType;
private double vertGridSpacing;
public GridDrawObject(
PaintSettings ps,
double x, double y,
double w, double h,
int hgt, double hgs,
int vgt, double vgs
) {
super(ps);
this.x1 = x;
this.y1 = y;
this.x2 = x + w;
this.y2 = y + h;
this.horizGridType = hgt;
this.horizGridSpacing = hgs;
this.vertGridType = vgt;
this.vertGridSpacing = vgs;
}
private GridDrawObject(GridDrawObject o) {
super(o);
this.x1 = o.x1;
this.y1 = o.y1;
this.x2 = o.x2;
this.y2 = o.y2;
this.horizGridType = o.horizGridType;
this.horizGridSpacing = o.horizGridSpacing;
this.vertGridType = o.vertGridType;
this.vertGridSpacing = o.vertGridSpacing;
}
@Override
public GridDrawObject clone() {
return new GridDrawObject(this);
}
public Rectangle2D getGridBounds() {
return new Rectangle2D.Double(
Math.min(x1, x2), Math.min(y1, y2),
Math.abs(x2 - x1), Math.abs(y2 - y1)
);
}
public int getHorizGridType() { return horizGridType; }
public double getHorizGridSpacing() { return horizGridSpacing; }
public int getVertGridType() { return vertGridType; }
public double getVertGridSpacing() { return vertGridSpacing; }
@Override protected Shape getBoundaryImpl() { return getGridBounds(); }
@Override protected Shape getHitAreaImpl() { return getGridBounds(); }
@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 paintImpl(Graphics2D g) {
if (ps.isFilled()) {
ps.applyFill(g);
g.fill(getGridBounds());
}
if (ps.isDrawn()) {
ps.applyDraw(g);
paintGrid(
g,
Math.min(x1, x2), Math.min(y1, y2),
Math.max(x1, x2), Math.max(y1, y2)
);
}
}
private void paintGrid(Graphics2D g, double x1, double y1, double x2, double y2) {
switch (horizGridType) {
case LINEAR:
for (double y = y1; y <= y2; y += horizGridSpacing) {
g.draw(new Line2D.Double(x1, y, x2 - 1, y));
}
break;
case LOGARITHMIC:
double m = (1 - 1 / horizGridSpacing);
for (double h = (y2 - y1) * m; h >= 1; h *= m) {
g.draw(new Line2D.Double(x1, y1 + h - 1, x2 - 1, y1 + h - 1));
}
break;
}
switch (vertGridType) {
case LINEAR:
for (double x = x1; x <= x2; x += vertGridSpacing) {
g.draw(new Line2D.Double(x, y1, x, y2 - 1));
}
break;
case LOGARITHMIC:
double m = (1 - 1 / vertGridSpacing);
for (double w = (x2 - x1) * m; w >= 1; w *= m) {
g.draw(new Line2D.Double(x1 + w - 1, y1, x1 + w - 1, y2 - 1));
}
break;
}
}
}