package org.archstudio.bna.things.shapes;
import java.awt.geom.Point2D;
import java.util.List;
import org.archstudio.bna.IBNAModel;
import org.archstudio.bna.IThingListener;
import org.archstudio.bna.ThingEvent;
import org.archstudio.bna.keys.IThingKey;
import org.archstudio.bna.logics.coordinating.StickPointLogic;
import org.archstudio.bna.utils.BNAUtils;
import org.archstudio.sysutils.SystemUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import com.google.common.collect.Lists;
@NonNullByDefault
public class SplineThing extends SplineThingBase {
private Point referencePoint = new Point(0, 0);
public SplineThing(@Nullable Object id) {
super(id);
updateProperties();
addThingListener(new IThingListener() {
@Override
public void thingChanged(ThingEvent thingEvent) {
if (isShapeModifyingKey(thingEvent.getPropertyName())) {
updateProperties();
}
}
});
}
protected void updateProperties() {
List<Point2D> points = Lists.newArrayListWithCapacity(getMidpoints().size() + 2);
points.add(getEndpoint1());
points.addAll(getMidpoints());
points.add(getEndpoint2());
double x1 = Double.POSITIVE_INFINITY;
double y1 = Double.POSITIVE_INFINITY;
double x2 = Double.NEGATIVE_INFINITY;
double y2 = Double.NEGATIVE_INFINITY;
for (Point2D p : points) {
x1 = Math.min(x1, p.getX());
y1 = Math.min(y1, p.getY());
x2 = Math.max(x2, p.getX());
y2 = Math.max(y2, p.getY());
}
int ix = SystemUtils.floor(x1);
int iy = SystemUtils.floor(y1);
int iw = SystemUtils.ceil(x2 - ix);
int ih = SystemUtils.ceil(y2 - iy);
setPoints(points);
setBoundingBox(new Rectangle(ix, iy, iw, ih));
}
@Override
public Point getReferencePoint() {
return BNAUtils.clone(referencePoint);
}
@Override
public void setReferencePoint(Point value) {
double dx = value.x - referencePoint.x;
double dy = value.y - referencePoint.y;
referencePoint.x = value.x;
referencePoint.y = value.y;
List<Point2D> points = getPoints();
for (Point2D p : points) {
p.setLocation(p.getX() + dx, p.getY() + dy);
}
setEndpoint1(points.get(0));
setMidpoints(points.subList(1, points.size() - 1));
setEndpoint2(points.get(points.size() - 1));
}
@Override
public Point2D getSecondaryPoint(IBNAModel model, StickPointLogic stickLogic, IThingKey<Point2D> pointKey) {
if (pointKey.equals(ENDPOINT_1_KEY)) {
List<? extends Point2D> points = getPoints();
if (points.size() > 2) {
return points.get(1);
}
return stickLogic.getStuckPoint(this, ENDPOINT_2_KEY, points.get(1));
}
if (pointKey.equals(ENDPOINT_2_KEY)) {
List<? extends Point2D> points = getPoints();
if (points.size() > 2) {
return points.get(points.size() - 2);
}
return stickLogic.getStuckPoint(this, ENDPOINT_1_KEY, points.get(points.size() - 2));
}
throw new IllegalArgumentException(pointKey.toString());
}
@Override
public boolean shouldIncrementRotatingOffset() {
return isSelected();
}
}