package org.archstudio.bna.utils;
import java.awt.geom.Point2D;
import java.util.Arrays;
import java.util.Comparator;
import org.archstudio.bna.IThing;
import org.archstudio.bna.facets.IHasAnchorPoint;
import org.archstudio.bna.facets.IHasBoundingBox;
import org.archstudio.bna.facets.IHasMutableAnchorPoint;
import org.archstudio.bna.facets.IHasMutableBoundingBox;
import org.archstudio.sysutils.SystemUtils;
import org.eclipse.swt.graphics.Rectangle;
public class BNADistributeUtils {
private BNADistributeUtils() {
}
static final XComparator xComparator = new XComparator();
static final YComparator yComparator = new YComparator();
public static double getX(IThing t) {
if (t instanceof IHasBoundingBox) {
return ((IHasBoundingBox) t).getBoundingBox().x;
}
else if (t instanceof IHasAnchorPoint) {
return ((IHasAnchorPoint) t).getAnchorPoint().getX();
}
else {
return 0;
}
}
public static double getY(IThing t) {
if (t instanceof IHasBoundingBox) {
return ((IHasBoundingBox) t).getBoundingBox().y;
}
else if (t instanceof IHasAnchorPoint) {
return ((IHasAnchorPoint) t).getAnchorPoint().getY();
}
else {
return 0;
}
}
public static int getWidth(IThing t) {
if (t instanceof IHasBoundingBox) {
return ((IHasBoundingBox) t).getBoundingBox().width;
}
else if (t instanceof IHasAnchorPoint) {
return 1;
}
else {
return 0;
}
}
public static int getHeight(IThing t) {
if (t instanceof IHasBoundingBox) {
return ((IHasBoundingBox) t).getBoundingBox().height;
}
else if (t instanceof IHasAnchorPoint) {
return 1;
}
else {
return 0;
}
}
public static void distributeHorizontalTight(IThing[] distributableThings) {
Arrays.sort(distributableThings, xComparator);
double distributeAt = getX(distributableThings[0]) + getWidth(distributableThings[0]) + 10;
for (int i = 1; i < distributableThings.length; i++) {
if (distributableThings[i] instanceof IHasMutableBoundingBox) {
Rectangle currentBounds = ((IHasMutableBoundingBox) distributableThings[i]).getBoundingBox();
currentBounds.x = SystemUtils.round(distributeAt);
((IHasMutableBoundingBox) distributableThings[i]).setBoundingBox(currentBounds);
distributeAt = distributeAt + getWidth(distributableThings[i]) + 10;
}
else if (distributableThings[i] instanceof IHasMutableAnchorPoint
&& distributableThings[i] instanceof IHasBoundingBox) {
Rectangle currentBounds = ((IHasBoundingBox) distributableThings[i]).getBoundingBox();
Point2D currentPoint = ((IHasAnchorPoint) distributableThings[i]).getAnchorPoint();
currentPoint.setLocation(distributeAt + currentPoint.getX() - currentBounds.x, currentBounds.y);
((IHasMutableAnchorPoint) distributableThings[i]).setAnchorPoint(currentPoint);
distributeAt = distributeAt + getWidth(distributableThings[i]) + 10;
}
else if (distributableThings[i] instanceof IHasMutableAnchorPoint) {
Point2D currentPoint = ((IHasMutableAnchorPoint) distributableThings[i]).getAnchorPoint();
currentPoint.setLocation(distributeAt, currentPoint.getY());
((IHasMutableAnchorPoint) distributableThings[i]).setAnchorPoint(currentPoint);
distributeAt = distributeAt + 1 + 10;
}
}
}
public static void distributeVerticalTight(IThing[] distributableThings) {
Arrays.sort(distributableThings, yComparator);
double distributeAt = getY(distributableThings[0]) + getHeight(distributableThings[0]) + 10;
for (int i = 1; i < distributableThings.length; i++) {
if (distributableThings[i] instanceof IHasMutableBoundingBox) {
Rectangle currentBounds = ((IHasMutableBoundingBox) distributableThings[i]).getBoundingBox();
currentBounds.y = SystemUtils.round(distributeAt);
((IHasMutableBoundingBox) distributableThings[i]).setBoundingBox(currentBounds);
distributeAt = distributeAt + getHeight(distributableThings[i]) + 10;
}
else if (distributableThings[i] instanceof IHasMutableAnchorPoint
&& distributableThings[i] instanceof IHasBoundingBox) {
Rectangle currentBounds = ((IHasBoundingBox) distributableThings[i]).getBoundingBox();
Point2D currentPoint = ((IHasMutableAnchorPoint) distributableThings[i]).getAnchorPoint();
currentPoint.setLocation(currentPoint.getX(), distributeAt + currentPoint.getY() - currentBounds.y);
((IHasMutableAnchorPoint) distributableThings[i]).setAnchorPoint(currentPoint);
distributeAt = distributeAt + getHeight(distributableThings[i]) + 10;
}
else if (distributableThings[i] instanceof IHasMutableAnchorPoint) {
Point2D currentPoint = ((IHasMutableAnchorPoint) distributableThings[i]).getAnchorPoint();
currentPoint.setLocation(currentPoint.getX(), distributeAt);
((IHasMutableAnchorPoint) distributableThings[i]).setAnchorPoint(currentPoint);
distributeAt = distributeAt + 1 + 10;
}
}
}
public static void distributeHorizontalLoose(IThing[] distributableThings) {
Arrays.sort(distributableThings, xComparator);
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
int widthSum = 0;
int count = 0;
for (IThing t : distributableThings) {
if (!(t instanceof IHasMutableBoundingBox || t instanceof IHasMutableAnchorPoint)) {
continue;
}
count++;
double x = getX(t);
int width = getWidth(t);
double x2 = x + width;
min = Math.min(x, min);
max = Math.max(x2, max);
widthSum += width;
}
if (count == 0) {
return;
}
double leftoverSpace = max - min - widthSum;
if (leftoverSpace < (distributableThings.length - 1) * 10) {
distributeHorizontalTight(distributableThings);
return;
}
double delta = leftoverSpace / count;
double distributeAt = getX(distributableThings[0]);
for (IThing distributableThing : distributableThings) {
if (distributableThing instanceof IHasMutableBoundingBox) {
Rectangle currentBounds = ((IHasMutableBoundingBox) distributableThing).getBoundingBox();
currentBounds.x = SystemUtils.round(distributeAt);
((IHasMutableBoundingBox) distributableThing).setBoundingBox(currentBounds);
distributeAt += currentBounds.width + delta;
}
else if (distributableThing instanceof IHasMutableAnchorPoint
&& distributableThing instanceof IHasBoundingBox) {
Rectangle currentBounds = ((IHasBoundingBox) distributableThing).getBoundingBox();
Point2D currentPoint = ((IHasMutableAnchorPoint) distributableThing).getAnchorPoint();
currentPoint.setLocation(
distributeAt + currentPoint.getX() - currentBounds.x - currentBounds.width / 2,
currentPoint.getY());
((IHasMutableAnchorPoint) distributableThing).setAnchorPoint(currentPoint);
distributeAt += currentBounds.width + delta;
}
else if (distributableThing instanceof IHasMutableAnchorPoint) {
Point2D currentPoint = ((IHasMutableAnchorPoint) distributableThing).getAnchorPoint();
currentPoint.setLocation(distributeAt, currentPoint.getY());
((IHasMutableAnchorPoint) distributableThing).setAnchorPoint(currentPoint);
distributeAt += 1 + delta;
}
}
}
public static void distributeVerticalLoose(IThing[] distributableThings) {
Arrays.sort(distributableThings, yComparator);
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
int heightSum = 0;
int count = 0;
for (IThing t : distributableThings) {
if (!(t instanceof IHasMutableBoundingBox || t instanceof IHasMutableAnchorPoint)) {
continue;
}
count++;
double y = getY(t);
int height = getHeight(t);
double y2 = y + height;
min = Math.min(y, min);
max = Math.max(y2, max);
heightSum += height;
}
if (count == 0) {
return;
}
double leftoverSpace = max - min - heightSum;
if (leftoverSpace < (distributableThings.length - 1) * 10) {
distributeVerticalTight(distributableThings);
return;
}
double delta = leftoverSpace / count;
double distributeAt = getY(distributableThings[0]);
for (IThing distributableThing : distributableThings) {
if (distributableThing instanceof IHasMutableBoundingBox) {
Rectangle currentBounds = ((IHasMutableBoundingBox) distributableThing).getBoundingBox();
currentBounds.y = SystemUtils.round(distributeAt);
((IHasMutableBoundingBox) distributableThing).setBoundingBox(currentBounds);
distributeAt += currentBounds.height + delta;
}
else if (distributableThing instanceof IHasMutableAnchorPoint
&& distributableThing instanceof IHasBoundingBox) {
Rectangle currentBounds = ((IHasBoundingBox) distributableThing).getBoundingBox();
Point2D currentPoint = ((IHasMutableAnchorPoint) distributableThing).getAnchorPoint();
currentPoint.setLocation(currentPoint.getX(), distributeAt - currentBounds.y + currentPoint.getY());
((IHasMutableAnchorPoint) distributableThing).setAnchorPoint(currentPoint);
distributeAt += currentBounds.height + delta;
}
else if (distributableThing instanceof IHasMutableAnchorPoint) {
Point2D currentPoint = ((IHasMutableAnchorPoint) distributableThing).getAnchorPoint();
currentPoint.setLocation(currentPoint.getX(), distributeAt);
((IHasMutableAnchorPoint) distributableThing).setAnchorPoint(currentPoint);
distributeAt += 1 + delta;
}
}
}
static class XComparator implements Comparator<IThing> {
@Override
public int compare(IThing o1, IThing o2) {
double x1, x2;
if (o1 instanceof IHasBoundingBox) {
Rectangle r1 = ((IHasBoundingBox) o1).getBoundingBox();
x1 = r1.x + r1.width / 2;
}
else if (o1 instanceof IHasAnchorPoint) {
Point2D p1 = ((IHasAnchorPoint) o1).getAnchorPoint();
x1 = p1.getX();
}
else {
return 1;
}
if (o2 instanceof IHasBoundingBox) {
Rectangle r2 = ((IHasBoundingBox) o2).getBoundingBox();
x2 = r2.x + r2.width / 2;
}
else if (o2 instanceof IHasAnchorPoint) {
Point2D p2 = ((IHasAnchorPoint) o2).getAnchorPoint();
x2 = p2.getX();
}
else {
return -1;
}
if (x1 < x2) {
return -1;
}
else if (x1 == x2) {
return 0;
}
else {
return 1;
}
}
}
static class YComparator implements Comparator<IThing> {
@Override
public int compare(IThing o1, IThing o2) {
double y1, y2;
if (o1 instanceof IHasBoundingBox) {
Rectangle r1 = ((IHasBoundingBox) o1).getBoundingBox();
y1 = r1.y + r1.height / 2;
}
else if (o1 instanceof IHasAnchorPoint) {
Point2D p1 = ((IHasAnchorPoint) o1).getAnchorPoint();
y1 = p1.getY();
}
else {
return 1;
}
if (o2 instanceof IHasBoundingBox) {
Rectangle r2 = ((IHasBoundingBox) o2).getBoundingBox();
y2 = r2.y + r2.height / 2;
}
else if (o2 instanceof IHasAnchorPoint) {
Point2D p2 = ((IHasAnchorPoint) o2).getAnchorPoint();
y2 = p2.getY();
}
else {
return -1;
}
if (y1 < y2) {
return -1;
}
else if (y1 == y2) {
return 0;
}
else {
return 1;
}
}
}
}