package org.archstudio.bna.logics.coordinating; import static com.google.common.base.Preconditions.checkNotNull; import static org.archstudio.sysutils.SystemUtils.castOrNull; import org.archstudio.bna.IBNAModelListener; import org.archstudio.bna.IBNAWorld; import org.archstudio.bna.IThing; import org.archstudio.bna.ThingEvent; import org.archstudio.bna.facets.IHasBoundingBox; import org.archstudio.bna.facets.IHasOrientation; import org.archstudio.bna.logics.AbstractCoordinatingThingLogic; import org.archstudio.bna.logics.coordinating.OrientDirectionalLabelLogic.OrientationUpdater; import org.archstudio.bna.things.labels.DirectionalLabelThing; import org.archstudio.bna.utils.BNAUtils; import org.archstudio.swtutils.constants.Orientation; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; public class OrientDirectionalLabelLogic extends AbstractCoordinatingThingLogic<OrientationUpdater> implements IBNAModelListener { private static Orientation getOnEdgeOrientation(int x1, int x2, int y1, int y2, int x, int y) { if (y == y1) { return getOnLineSegmentOrientation(x1, x, x2, Orientation.NORTHWEST, Orientation.NORTH, Orientation.NORTHEAST); } else if (y == y2) { return getOnLineSegmentOrientation(x1, x, x2, Orientation.SOUTHWEST, Orientation.SOUTH, Orientation.SOUTHEAST); } else if (x == x1) { return getOnLineSegmentOrientation(y1, y, y2, Orientation.NORTHWEST, Orientation.WEST, Orientation.SOUTHWEST); } else if (x == x2) { return getOnLineSegmentOrientation(y1, y, y2, Orientation.NORTHEAST, Orientation.EAST, Orientation.SOUTHEAST); } return Orientation.NONE; } private static Orientation getOnLineSegmentOrientation(int p1, int p, int p2, Orientation o1, Orientation o, Orientation o2) { if (p == p1) { return o1; } if (p == p2) { return o2; } if (p >= p1 && p <= p2) { return o; } return Orientation.NONE; } protected class OrientationUpdater extends AbstractCoordinatingThingLogic.Updater { final Object rectangleThingID; final Object labelThingID; boolean updating; public OrientationUpdater(IHasBoundingBox rectangleThing, DirectionalLabelThing labelThing) { this.rectangleThingID = rectangleThing.getID(); this.labelThingID = labelThing.getID(); } @Override public void update(ThingEvent event) { if (updating) { return; } if (event != null) { if (event.getTargetThing().getID().equals(rectangleThingID)) { if (!event.getPropertyName().equals(IHasBoundingBox.BOUNDING_BOX_KEY)) { return; } } else { if (!event.getPropertyName().equals(IHasBoundingBox.BOUNDING_BOX_KEY) && !event.getPropertyName().equals(IHasOrientation.ORIENTATION_KEY)) { return; } } } IHasBoundingBox rectangleThing = castOrNull(model.getThing(rectangleThingID), IHasBoundingBox.class); if (rectangleThing != null) { DirectionalLabelThing labelThing = castOrNull(model.getThing(labelThingID), DirectionalLabelThing.class); if (labelThing != null) { Rectangle r = rectangleThing.getBoundingBox(); Point p = labelThing.getReferencePoint(); Orientation orientation = getOnEdgeOrientation(r.x, r.x + r.width, r.y, r.y + r.height, p.x, p.y); updating = true; try { labelThing.setOrientation(orientation); } finally { updating = false; } } } } } public OrientDirectionalLabelLogic(IBNAWorld world) { super(world); } public void orient(IHasBoundingBox rectangleThing, DirectionalLabelThing labelThing) { checkNotNull(rectangleThing); checkNotNull(labelThing); BNAUtils.checkLock(); OrientationUpdater updater = new OrientationUpdater(rectangleThing, labelThing); register(updater, labelThing); removeWithThing(updater, rectangleThing, labelThing); track(updater, rectangleThing, labelThing); } public void unorient(IThing labelThing) { checkNotNull(labelThing); BNAUtils.checkLock(); unregister(labelThing); } }