package org.archstudio.bna.logics.tracking; import org.archstudio.bna.BNAModelEvent; 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.IHasHidden; import org.archstudio.bna.logics.AbstractThingLogic; import org.archstudio.bna.utils.BNAUtils; import org.eclipse.swt.graphics.Rectangle; public class ModelBoundsTrackingLogic extends AbstractThingLogic implements IBNAModelListener { protected final ThingTypeTrackingLogic typeLogic; private Rectangle cachedBounds = null; public ModelBoundsTrackingLogic(IBNAWorld world) { super(world); typeLogic = logics.addThingLogic(ThingTypeTrackingLogic.class); } @Override public void bnaModelChanged(BNAModelEvent evt) { BNAUtils.checkLock(); switch (evt.getEventType()) { case THING_ADDED: { IThing thing = evt.getTargetThing(); if (thing instanceof IHasBoundingBox) { cachedBounds = null; } } break; case THING_REMOVED: { IThing thing = evt.getTargetThing(); if (thing instanceof IHasBoundingBox) { cachedBounds = null; } } break; case THING_CHANGED: { if (cachedBounds != null) { IThing thing = evt.getTargetThing(); if (thing instanceof IHasBoundingBox) { ThingEvent thingEvent = evt.getThingEvent(); if (IHasBoundingBox.BOUNDING_BOX_KEY.equals(thingEvent.getPropertyName())) { cachedBounds = null; } } } } break; default: // do nothing } } public Rectangle getModelBounds() { BNAUtils.checkLock(); if (cachedBounds == null) { int x1 = Integer.MAX_VALUE; int y1 = Integer.MAX_VALUE; int x2 = Integer.MIN_VALUE; int y2 = Integer.MIN_VALUE; for (IHasBoundingBox t : typeLogic.getThings(IHasBoundingBox.class)) { if (!t.has(IHasHidden.HIDDEN_KEY, true)) { Rectangle bb = t.getBoundingBox(); if (bb.x < x1) { x1 = bb.x; } if (bb.y < y1) { y1 = bb.y; } if (bb.x + bb.width > x2) { x2 = bb.x + bb.width; } if (bb.y + bb.height > y2) { y2 = bb.y + bb.height; } } } if (x1 >= x2 || y1 >= y2) { cachedBounds = new Rectangle(0, 0, 0, 0); } else { cachedBounds = new Rectangle(x1, y1, x2 - x1, y2 - y1); } } return BNAUtils.clone(cachedBounds); } }