// $Id: BoundingBox.java,v 1.8 2010/08/23 07:32:23 olga Exp $
package agg.editor.impl;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Vector;
import agg.gui.editor.GraphCanvas;
/**
* A BoundingBox specifies a bounding rectangle around the objects of the class
* agg.editor.impl.EdGraphObject
*/
@SuppressWarnings("serial")
public class BoundingBox extends Rectangle {
private Vector<EdGraphObject> objs;
private int space = 50;
private Point min, max; // min, max points of a bounding box
private Point upper_left = new Point(0, 0);
// private Point upper_right = new Point(0, 0);
private Rectangle anchorUL, // UPPER_LEFT
anchorUR, // UPPER_RIGHT
anchorBR, // BOTTOM_RIGHT
anchorBL; // BOTTOM_LEFT
private Point anchor; // current anchor
private int dx, dy; // only >= 0
private int maxX; //, maxY, minX, minY; // min, max size of the graphical area
/**
* Creates a bounding box with graphobjects within it. The elements of the
* objs are of class agg.editor.impl.EdGraphObject.
*/
public BoundingBox(Vector<EdGraphObject> objs) {
// System.out.println(">>> BoundingBox");
super();
this.objs = objs;
/* set a space area */
// space = 10;
/* initialize min and this.max points of the bounding box */
this.min = new Point(10000, 10000);
this.max = new Point(0, 0);
init();
}
public BoundingBox(Vector<EdGraphObject> objs, Point upper_left) {
// System.out.println(">>> BoundingBox");
super();
this.objs = objs;
/* set a space area */
// space = 10;
/* initialize this.min and this.max points of the bounding box */
this.min = new Point(10000, 10000);
this.max = new Point(0, 0);
this.upper_left = upper_left;
init();
}
private void init() {
/*
* set this.min and this.max points of a bounding box using the size of
* graphobjects and a space area
*/
for (int i = 0; i < this.objs.size(); i++) {
EdGraphObject elem = this.objs.elementAt(i);
if (elem.isNode() || (elem.isArc() && !((EdArc) elem).isLine())) {
if ((elem.getX() - elem.getWidth() / 2) < this.min.x)
this.min.x = elem.getX() - elem.getWidth() / 2;
if ((elem.getY() - elem.getHeight() / 2) < this.min.y)
this.min.y = elem.getY() - elem.getHeight() / 2;
if ((elem.getX() + elem.getWidth() / 2) > this.max.x)
this.max.x = elem.getX() + elem.getWidth() / 2;
if ((elem.getY() + elem.getHeight() / 2) > this.max.y)
this.max.y = elem.getY() + elem.getHeight() / 2;
}
}
/* add a space area to this.max points of a bounding box */
this.max.x = this.max.x + this.space;
this.max.y = this.max.y + this.space / 2;
/* set bounds of a bounding box */
setBounds(this.min.x, this.min.y, this.max.x - this.min.x, this.max.y - this.min.y);
// minX = 0; // 10;
// minY = 0;
this.maxX = GraphCanvas.MAX_XWIDTH;
// maxY = GraphCanvas.MAX_YHEIGHT;
/* set an anchor on each corner of a bounding box */
this.anchorUL = new Rectangle(this.min.x, this.min.y, 2, 2);
this.anchorUR = new Rectangle(this.max.x, this.min.y, 2, 2);
this.anchorBR = new Rectangle(this.max.x, this.max.y, 2, 2);
this.anchorBL = new Rectangle(this.min.x, this.max.y, 2, 2);
/* initialize a current anchor */
this.anchor = new Point(-1, -1);
/* initialize the overlapping of X and Y */
this.dx = 0;
this.dy = 0;
// System.out.println("BB: "+this.min.x+" , "+this.min.y +" "+this.max.x+" , "+this.max.y);
}
/** Checks whether the point(x,y) is contained within the bounding box */
public boolean contains(int ax, int ay) {
if (super.contains(ax, ay)) {
this.anchor.x = ax;
this.anchor.y = ay;
return true;
}
this.anchor.x = -1;
this.anchor.y = -1;
return false;
}
/** Computes new positions of the graphobjects within the bounding box */
public void compute() {
// System.out.println(">>> BoundingBox.compute");
// System.out.println(this.maxX);
int newX = 0, newY = 0;
/* set relative position of graph objects into a bounding box */
for (int i = 0; i < this.objs.size(); i++) {
EdGraphObject elem = this.objs.elementAt(i);
// System.out.println(">>> old Position: x,y "+elem.getX()+" ,
// "+elem.getY()+" w,h "+elem.getWidth()+" , "+elem.getHeight());
// System.out.println(">>> old abs Position: "+elem.getX()+"
// "+elem.getY());
elem.setXY(elem.getX() - this.min.x, elem.getY() - this.min.y);
// System.out.println(">>> rel Position: "+elem.getX()+"
// "+elem.getY());
if (elem.isArc() && elem.getArc().isLine()) {
if (elem.getArc().hasAnchor())
elem.getArc().setAnchor(
new Point(elem.getArc().getAnchor().x - this.min.x, elem
.getArc().getAnchor().y
- this.min.y));
} else if (elem.isArc() && !elem.getArc().isLine()) { // Loop
elem.getArc().setAnchor(
Loop.UPPER_LEFT,
new Point(elem.getArc().getAnchor(Loop.UPPER_LEFT).x
- this.min.x, elem.getArc().getAnchor(
Loop.UPPER_LEFT).y
- this.min.y));
}
}
/* compute newX, newY */
// correct this.min / this.max points to upper_left point
if (this.upper_left.x != 0 && this.upper_left.y != 0) {
newX = this.upper_left.x;
newY = this.upper_left.y;
} else {
newX = this.min.x + this.dx;
newY = this.min.y + this.dy;
}
// System.out.println("BoundBox: "+newX+" "+this.maxX);
if ((newX + getSize().width) > this.maxX) {
newX = 0;
newY = newY + getSize().height + 10;
}
// else newY = this.min.y; //this.max.y;
// System.out.println("newX newY "+ newX +" "+ newY);
/* set this.max (x,y) and this.min (x,y) of a bounding box */
this.min.x = newX;
this.min.y = newY;
this.max.x = this.min.x + getSize().width;
this.max.y = this.min.y + getSize().height;
setBounds(this.min.x, this.min.y, getSize().width, getSize().height);
// System.out.println("BB: "+this.min.x+" , "+this.min.y +" "+this.max.x+" , "+this.max.y);
/* set absolute Position of graph objects */
// System.out.println(">>> set absolute Position: ");
for (int i = 0; i < this.objs.size(); i++) {
EdGraphObject elem = this.objs.elementAt(i);
if (elem.isNode()) {
elem.setXY(elem.getX() + this.min.x, elem.getY() + this.min.y);
if ((elem.getX() - elem.getWidth() / 2) < 0)
elem.setX(elem.getX() + elem.getWidth() / 2 + 10);
// System.out.println(">>> new abs Position: x,y "+elem.getX()+"
// , "+elem.getY()+" w,h "+elem.getWidth()+" ,
// "+elem.getHeight());
} else if (elem.isArc() && elem.getArc().isLine()) {
if (elem.getArc().hasAnchor())
elem.getArc().setAnchor(
new Point(elem.getArc().getAnchor().x + this.min.x, elem
.getArc().getAnchor().y
+ this.min.y));
} else if (elem.isArc() && !elem.getArc().isLine()) { // Loop
elem.getArc().setAnchor(
Loop.UPPER_LEFT,
new Point(elem.getArc().getAnchor(Loop.UPPER_LEFT).x
+ this.min.x, elem.getArc().getAnchor(
Loop.UPPER_LEFT).y
+ this.min.y));
}
}
// System.out.println("BoundingBox.compute:: upper_right : "+new
// Point(this.max.x, this.min.y));
return;
}
/** Gets the current this.anchor of the bounding box */
public Point getAnchor() {
return this.anchor;
}
/** Sets the current this.anchor of the bounding box */
public void setAnchor(int x, int y) {
this.anchor.x = x;
this.anchor.y = y;
}
/**
* Returns TRUE if the current this.anchor is on the upper left corner of the
* bounding box
*/
public boolean isUpperLeft() {
return this.anchorUL.contains(this.anchor.x, this.anchor.y);
}
/**
* Returns TRUE if the current this.anchor is on the upper right corner of the
* bounding box
*/
public boolean isUpperRight() {
return this.anchorUR.contains(this.anchor.x, this.anchor.y);
}
/**
* Returns TRUE if the current this.anchor is on the bottom right corner of the
* bounding box
*/
public boolean isBottomRight() {
return this.anchorBR.contains(this.anchor.x, this.anchor.y);
}
/**
* Returns TRUE if the current this.anchor is on the bottom left corner of the
* bounding box
*/
public boolean isBottomLeft() {
return this.anchorBL.contains(this.anchor.x, this.anchor.y);
}
public Point getUpperLeft() {
return new Point(this.min.x, this.min.y);
}
public Point getUpperRight() {
return new Point(this.max.x, this.min.y);
}
public void setUpperLeft(Point p) {
this.min = p;
}
/**
* Moves the bounding box dragging the current this.anchor to the specified x,y
*/
public void moveTo(int ax, int ay) {
if (this.anchor.x == -1 || this.anchor.y == -1)
return;
int diffX = ax - this.anchor.x;
int diffY = ay - this.anchor.y;
this.min.x = this.min.x + diffX;
this.min.y = this.min.y + diffY;
this.max.x = this.max.x + diffX;
this.max.y = this.max.y + diffY;
makeAnchors();
}
/**
* Resizes the one selected corner of the bounding box to the specified x,y
*/
public void resizeTo(int ax, int ay) {
if (this.anchor.x == -1 || this.anchor.y == -1)
return;
if (isUpperLeft()) {
this.min.x = ax;
this.min.y = ay;
setBounds(this.min.x, this.min.y, this.max.x - this.min.x, this.max.y - this.min.y);
makeAnchors();
} else if (isUpperRight()) {
this.max.x = ax;
this.min.y = ay;
setBounds(this.min.x, this.min.y, this.max.x - this.min.x, this.max.y - this.min.y);
makeAnchors();
} else if (isBottomLeft()) {
this.min.x = ax;
this.max.y = ay;
setBounds(this.min.x, this.min.y, this.max.x - this.min.x, this.max.y - this.min.y);
makeAnchors();
} else if (isBottomRight()) {
this.max.x = ax;
this.max.y = ay;
setBounds(this.min.x, this.min.y, this.max.x - this.min.x, this.max.y - this.min.y);
makeAnchors();
}
}
/** Sets the this.max x of the bounding box */
public void setMaxX(int aMax) {
this.maxX = aMax;
}
/* Sets the this.max y of the bounding box */
// public void setMaxY(int this.max) {
// maxY = this.max;
// }
/* Sets the this.min x of the bounding box */
// public void setMinX(int this.min) {
// minX = this.min;
// }
/* Sets the this.min y of the bounding box */
// public void setMinY(int this.min) {
// minY = this.min;
// }
/** Sets the this.max overlapping of the graphobjects within the bounding box */
public void setOverlap(int overX, int overY) {
this.dx = overX;
this.dy = overY;
}
public void setOverlap(Rectangle rect) {
}
/** Shows the bounding box */
public void show(Graphics g) {
g.setColor(Color.black);
g.drawRect(this.min.x, this.min.y, getSize().width, getSize().height);
}
/** Hides the bounding box */
public void hide(Graphics g) {
g.setColor(Color.white);
g.drawRect(this.min.x, this.min.y, getSize().width, getSize().height);
}
/** Resets the corner anchors of the bounding box */
private void makeAnchors() {
this.anchorUL = new Rectangle(this.min.x, this.min.y, 2, 2);
this.anchorUR = new Rectangle(this.max.x, this.min.y, 2, 2);
this.anchorBR = new Rectangle(this.max.x, this.max.y, 2, 2);
this.anchorBL = new Rectangle(this.min.x, this.max.y, 2, 2);
}
}