package org.archstudio.bna.utils;
import java.awt.geom.Point2D;
import java.util.List;
import org.archstudio.bna.IThing;
import org.archstudio.bna.facets.IHasAnchorPoint;
import org.archstudio.bna.facets.IHasBoundingBox;
import org.archstudio.bna.facets.IHasEndpoints;
import org.archstudio.bna.facets.IHasMutableAnchorPoint;
import org.archstudio.bna.facets.IHasMutableBoundingBox;
import org.archstudio.bna.facets.IHasMutableEndpoints;
import org.archstudio.bna.facets.IHasMutableMidpoints;
import org.archstudio.bna.facets.IHasMutableReferencePoint;
import org.archstudio.bna.facets.IHasStickyShape;
import org.archstudio.bna.keys.IThingKey;
import org.archstudio.bna.logics.coordinating.StickPointLogic;
import org.archstudio.bna.logics.coordinating.StickPointLogic.IStuckThing;
import org.archstudio.swtutils.constants.HorizontalAlignment;
import org.archstudio.swtutils.constants.VerticalAlignment;
import org.archstudio.sysutils.SystemUtils;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import com.google.common.base.Predicate;
public class BNAAlignUtils {
private BNAAlignUtils() {
}
public static void align(IThing[] things, VerticalAlignment a) {
switch (a) {
case TOP: {
double y = Double.POSITIVE_INFINITY;
for (IThing t : things) {
if (t instanceof IHasBoundingBox) {
Rectangle boundingBox = ((IHasBoundingBox) t).getBoundingBox();
y = Math.min(boundingBox.y, y);
}
else if (t instanceof IHasAnchorPoint) {
Point2D anchorPoint = ((IHasAnchorPoint) t).getAnchorPoint();
y = Math.min(anchorPoint.getY(), y);
}
}
for (IThing t : things) {
if (t instanceof IHasMutableBoundingBox) {
Rectangle boundingBox = ((IHasMutableBoundingBox) t).getBoundingBox();
boundingBox.y = SystemUtils.round(y);
((IHasMutableBoundingBox) t).setBoundingBox(boundingBox);
}
else if (t instanceof IHasMutableAnchorPoint) {
Point2D anchorPoint = ((IHasMutableAnchorPoint) t).getAnchorPoint();
anchorPoint.setLocation(anchorPoint.getX(), y);
((IHasMutableAnchorPoint) t).setAnchorPoint(anchorPoint);
}
}
}
break;
case MIDDLE: {
double y = 0;
int i = 0;
for (IThing t : things) {
if (t instanceof IHasBoundingBox) {
Rectangle boundingBox = ((IHasBoundingBox) t).getBoundingBox();
y += boundingBox.y + boundingBox.height / 2;
i++;
}
else if (t instanceof IHasAnchorPoint) {
Point2D anchorPoint = ((IHasAnchorPoint) t).getAnchorPoint();
y += anchorPoint.getY();
i++;
}
}
y = y / i;
for (IThing t : things) {
if (t instanceof IHasMutableBoundingBox) {
Rectangle boundingBox = ((IHasMutableBoundingBox) t).getBoundingBox();
boundingBox.y = SystemUtils.round(y) - boundingBox.height / 2;
((IHasMutableBoundingBox) t).setBoundingBox(boundingBox);
}
else if (t instanceof IHasMutableAnchorPoint) {
Point2D anchorPoint = ((IHasMutableAnchorPoint) t).getAnchorPoint();
anchorPoint.setLocation(anchorPoint.getX(), y);
((IHasMutableAnchorPoint) t).setAnchorPoint(anchorPoint);
}
}
}
break;
case BOTTOM: {
double y = Double.NEGATIVE_INFINITY;
for (IThing t : things) {
if (t instanceof IHasBoundingBox) {
Rectangle boundingBox = ((IHasBoundingBox) t).getBoundingBox();
y = Math.max(boundingBox.y + boundingBox.height, y);
}
else if (t instanceof IHasAnchorPoint) {
Point2D anchorPoint = ((IHasAnchorPoint) t).getAnchorPoint();
y = Math.max(anchorPoint.getY(), y);
}
}
for (IThing t : things) {
if (t instanceof IHasMutableBoundingBox) {
Rectangle boundingBox = ((IHasMutableBoundingBox) t).getBoundingBox();
boundingBox.y = SystemUtils.round(y) - boundingBox.height;
((IHasMutableBoundingBox) t).setBoundingBox(boundingBox);
}
else if (t instanceof IHasMutableAnchorPoint) {
Point2D anchorPoint = ((IHasMutableAnchorPoint) t).getAnchorPoint();
anchorPoint.setLocation(anchorPoint.getX(), y);
((IHasMutableAnchorPoint) t).setAnchorPoint(anchorPoint);
}
}
}
break;
}
}
public static void align(IThing[] things, HorizontalAlignment a) {
switch (a) {
case LEFT: {
double x = Double.POSITIVE_INFINITY;
for (IThing t : things) {
if (t instanceof IHasBoundingBox) {
Rectangle boundingBox = ((IHasBoundingBox) t).getBoundingBox();
x = Math.min(boundingBox.x, x);
}
else if (t instanceof IHasAnchorPoint) {
Point2D anchorPoint = ((IHasAnchorPoint) t).getAnchorPoint();
x = Math.min(anchorPoint.getX(), x);
}
}
for (IThing t : things) {
if (t instanceof IHasMutableBoundingBox) {
Rectangle boundingBox = ((IHasMutableBoundingBox) t).getBoundingBox();
boundingBox.x = SystemUtils.round(x);
((IHasMutableBoundingBox) t).setBoundingBox(boundingBox);
}
else if (t instanceof IHasMutableAnchorPoint) {
Point2D anchorPoint = ((IHasMutableAnchorPoint) t).getAnchorPoint();
anchorPoint.setLocation(x, anchorPoint.getY());
((IHasMutableAnchorPoint) t).setAnchorPoint(anchorPoint);
}
}
}
break;
case CENTER: {
double x = 0;
int i = 0;
for (IThing t : things) {
if (t instanceof IHasBoundingBox) {
Rectangle boundingBox = ((IHasBoundingBox) t).getBoundingBox();
x += boundingBox.x + boundingBox.width / 2;
i++;
}
else if (t instanceof IHasAnchorPoint) {
Point2D anchorPoint = ((IHasAnchorPoint) t).getAnchorPoint();
x += anchorPoint.getX();
i++;
}
}
x = x / i;
for (IThing t : things) {
if (t instanceof IHasMutableBoundingBox) {
Rectangle boundingBox = ((IHasMutableBoundingBox) t).getBoundingBox();
boundingBox.x = SystemUtils.round(x) - boundingBox.width / 2;
((IHasMutableBoundingBox) t).setBoundingBox(boundingBox);
}
else if (t instanceof IHasMutableAnchorPoint) {
Point2D anchorPoint = ((IHasMutableAnchorPoint) t).getAnchorPoint();
anchorPoint.setLocation(x, anchorPoint.getY());
((IHasMutableAnchorPoint) t).setAnchorPoint(anchorPoint);
}
}
}
break;
case RIGHT: {
double x = Double.NEGATIVE_INFINITY;
for (IThing t : things) {
if (t instanceof IHasBoundingBox) {
Rectangle boundingBox = ((IHasBoundingBox) t).getBoundingBox();
x = Math.max(boundingBox.x + boundingBox.width, x);
}
else if (t instanceof IHasAnchorPoint) {
Point2D anchorPoint = ((IHasAnchorPoint) t).getAnchorPoint();
x = Math.max(anchorPoint.getX(), x);
}
}
for (IThing t : things) {
if (t instanceof IHasMutableBoundingBox) {
Rectangle boundingBox = ((IHasMutableBoundingBox) t).getBoundingBox();
boundingBox.x = SystemUtils.round(x) - boundingBox.width;
((IHasMutableBoundingBox) t).setBoundingBox(boundingBox);
}
else if (t instanceof IHasMutableAnchorPoint) {
Point2D anchorPoint = ((IHasMutableAnchorPoint) t).getAnchorPoint();
anchorPoint.setLocation(x, anchorPoint.getY());
((IHasMutableAnchorPoint) t).setAnchorPoint(anchorPoint);
}
}
}
break;
}
}
private static Rectangle union(Rectangle r, Point2D p2d) {
Point p = BNAUtils.toPoint(p2d);
if (r == null) {
r = new Rectangle(p.x, p.y, 1, 1);
}
else {
r = r.union(new Rectangle(p.x, p.y, 1, 1));
}
return r;
}
private static Rectangle union(Rectangle r, IThing t, StickPointLogic stickLogic, IThingKey<Point2D> pKey) {
if (stickLogic.getStickyThing(t, pKey) == null) {
return union(r, t.get(pKey));
}
return r;
}
private static Rectangle getBounds(StickPointLogic stickLogic, Iterable<IThing> thingsToFlip) {
Rectangle r = null;
for (IThing t : thingsToFlip) {
if (t instanceof IHasMutableBoundingBox
&& UserEditableUtils.isEditableForAllQualities(t, IHasMutableReferencePoint.USER_MAY_MOVE)) {
if (r == null) {
r = ((IHasMutableBoundingBox) t).getBoundingBox();
}
else {
r = r.union(((IHasMutableBoundingBox) t).getBoundingBox());
}
}
if (t instanceof IHasMutableAnchorPoint
&& UserEditableUtils.isEditableForAllQualities(t, IHasMutableReferencePoint.USER_MAY_MOVE)) {
r = union(r, t, stickLogic, IHasAnchorPoint.ANCHOR_POINT_KEY);
}
if (t instanceof IHasMutableEndpoints) {
if (UserEditableUtils.isEditableForAllQualities(t, IHasMutableEndpoints.USER_MAY_MOVE_ENDPOINT_1)) {
r = union(r, t, stickLogic, IHasEndpoints.ENDPOINT_1_KEY);
}
if (UserEditableUtils.isEditableForAllQualities(t, IHasMutableEndpoints.USER_MAY_MOVE_ENDPOINT_2)) {
r = union(r, t, stickLogic, IHasEndpoints.ENDPOINT_2_KEY);
}
}
if (t instanceof IHasMutableMidpoints) {
if (UserEditableUtils.isEditableForAllQualities(t, IHasMutableMidpoints.USER_MAY_MOVE_MIDPOINTS)) {
for (Point2D p2d : ((IHasMutableMidpoints) t).getMidpoints()) {
r = union(r, p2d);
}
}
}
}
if (r == null) {
throw new IllegalArgumentException("No things to create bounds with.");
}
return r;
}
private static Point2D flip(Rectangle bounds, Point2D p, boolean horizontal) {
if (horizontal) {
return new Point2D.Double(bounds.x + bounds.width - (p.getX() - bounds.x), p.getY());
}
else {
return new Point2D.Double(p.getX(), bounds.y + bounds.height - (p.getY() - bounds.y));
}
}
private static void flip(IThing t, Rectangle bounds, StickPointLogic stickLogic, IThingKey<Point2D> pKey,
boolean horizontal) {
if (stickLogic == null || stickLogic.getStickyThing(t, pKey) == null) {
t.set(pKey, flip(bounds, t.get(pKey), horizontal));
}
}
public static void flip(StickPointLogic stickLogic, Iterable<IThing> thingsToFlip, boolean horizontal) {
Rectangle bounds = getBounds(stickLogic, thingsToFlip);
for (IThing t : thingsToFlip) {
if (t instanceof IHasMutableBoundingBox
&& UserEditableUtils.isEditableForAllQualities(t, IHasMutableReferencePoint.USER_MAY_MOVE)) {
Rectangle r = ((IHasMutableBoundingBox) t).getBoundingBox();
if (horizontal) {
r.x = bounds.x + bounds.width - (r.x - bounds.x + r.width);
}
else {
r.y = bounds.y + bounds.height - (r.y - bounds.y + r.height);
}
((IHasMutableBoundingBox) t).setBoundingBox(r);
}
if (t instanceof IHasMutableAnchorPoint
&& UserEditableUtils.isEditableForAllQualities(t, IHasMutableReferencePoint.USER_MAY_MOVE)) {
flip(t, bounds, stickLogic, IHasAnchorPoint.ANCHOR_POINT_KEY, horizontal);
}
if (t instanceof IHasMutableEndpoints) {
if (UserEditableUtils.isEditableForAllQualities(t, IHasMutableEndpoints.USER_MAY_MOVE_ENDPOINT_1)) {
flip(t, bounds, stickLogic, IHasEndpoints.ENDPOINT_1_KEY, horizontal);
}
if (UserEditableUtils.isEditableForAllQualities(t, IHasMutableEndpoints.USER_MAY_MOVE_ENDPOINT_2)) {
flip(t, bounds, stickLogic, IHasEndpoints.ENDPOINT_2_KEY, horizontal);
}
}
if (t instanceof IHasMutableMidpoints) {
if (UserEditableUtils.isEditableForAllQualities(t, IHasMutableMidpoints.USER_MAY_MOVE_MIDPOINTS)) {
List<Point2D> midpoints = ((IHasMutableMidpoints) t).getMidpoints();
for (int i = 0; i < midpoints.size(); ++i) {
midpoints.set(i, flip(bounds, midpoints.get(i), horizontal));
}
((IHasMutableMidpoints) t).setMidpoints(midpoints);
}
}
}
// Now flip sticky things.
for (IThing t : thingsToFlip) {
if (t instanceof IHasBoundingBox && t instanceof IHasStickyShape) {
bounds = ((IHasBoundingBox) t).getBoundingBox();
for (IStuckThing stuckThing : stickLogic.getStuckThings((IHasStickyShape) t)) {
flip(stuckThing.getStuckThing(), bounds, null, stuckThing.getStuckPointKey(), horizontal);
}
}
}
}
public static final Predicate<IThing> FLIP_THING_PREDICATE = new Predicate<IThing>() {
@Override
public boolean apply(IThing t) {
if (t instanceof IHasMutableBoundingBox) {
return UserEditableUtils.isEditableForAllQualities(t, IHasMutableReferencePoint.USER_MAY_MOVE);
}
if (t instanceof IHasMutableAnchorPoint) {
return UserEditableUtils.isEditableForAllQualities(t, IHasMutableReferencePoint.USER_MAY_MOVE);
}
if (t instanceof IHasMutableEndpoints) {
return UserEditableUtils.isEditableForAllQualities(t, IHasMutableEndpoints.USER_MAY_MOVE_ENDPOINT_1)
|| UserEditableUtils.isEditableForAllQualities(t,
IHasMutableEndpoints.USER_MAY_MOVE_ENDPOINT_2);
}
if (t instanceof IHasMutableMidpoints) {
return UserEditableUtils.isEditableForAllQualities(t, IHasMutableMidpoints.USER_MAY_MOVE_MIDPOINTS);
}
return false;
}
};
}