package org.archstudio.bna.logics.editing; import org.archstudio.bna.IBNAView; import org.archstudio.bna.IBNAWorld; import org.archstudio.bna.ICoordinate; import org.archstudio.bna.constants.MouseType; import org.archstudio.bna.facets.IHasBoundingBox; import org.archstudio.bna.facets.IHasMutableSelected; import org.archstudio.bna.logics.background.RotatingOffsetLogic; import org.archstudio.bna.logics.tracking.ThingTypeTrackingLogic; import org.archstudio.bna.things.borders.MarqueeBoxBorderThing; import org.archstudio.bna.ui.IBNAMouseClickListener2; import org.archstudio.bna.ui.IBNAMouseMoveListener2; import org.archstudio.bna.utils.BNAUtils; import org.archstudio.bna.utils.BNAUtils2.ThingsAtLocation; import org.archstudio.bna.utils.UserEditableUtils; import org.archstudio.sysutils.Finally; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; public class MarqueeSelectionLogic extends SelectionLogic implements IBNAMouseClickListener2, IBNAMouseMoveListener2 { protected final ThingTypeTrackingLogic typeLogic; protected MarqueeBoxBorderThing marqueeSelection = null; protected Point initDownWorldPoint = new Point(0, 0); public MarqueeSelectionLogic(IBNAWorld world) { super(world); this.typeLogic = logics.addThingLogic(ThingTypeTrackingLogic.class); logics.addThingLogic(RotatingOffsetLogic.class); } @Override public void dispose() { BNAUtils.checkLock(); if (marqueeSelection != null) { model.removeThing(marqueeSelection); } super.dispose(); } @Override public void mouseDown(IBNAView view, MouseType type, MouseEvent evt, ICoordinate location, ThingsAtLocation thingsAtLocation) { BNAUtils.checkLock(); if (marqueeSelection != null) { model.removeThing(marqueeSelection); marqueeSelection = null; } if (evt.button == 1) { if (thingsAtLocation.getThingAtLocation() == null) { setWorldWithSelectionFocus(world); initDownWorldPoint = view.getCoordinateMapper().localToWorld(thingsAtLocation.getOriginalLocation().getLocalPoint()); marqueeSelection = model.addThing(new MarqueeBoxBorderThing(null)); marqueeSelection.setBoundingBox(new Rectangle(initDownWorldPoint.x, initDownWorldPoint.y, 1, 1)); } } } @Override public void mouseMove(IBNAView view, MouseType type, MouseEvent evt, ICoordinate location, ThingsAtLocation thingsAtLocation) { BNAUtils.checkLock(); if (marqueeSelection != null) { Point worldPoint = view.getCoordinateMapper().localToWorld(new Point(evt.x, evt.y)); int x1 = Math.min(initDownWorldPoint.x, worldPoint.x); int x2 = Math.max(initDownWorldPoint.x, worldPoint.x); int y1 = Math.min(initDownWorldPoint.y, worldPoint.y); int y2 = Math.max(initDownWorldPoint.y, worldPoint.y); marqueeSelection.setBoundingBox(new Rectangle(x1, y1, x2 - x1, y2 - y1)); } } @Override public void mouseUp(IBNAView view, MouseType type, MouseEvent evt, ICoordinate location, ThingsAtLocation thingsAtLocation) { BNAUtils.checkLock(); try { if (evt.button == 1) { if (marqueeSelection != null) { Rectangle selectionRectangle = marqueeSelection.getBoundingBox(); selectionRectangle = BNAUtils.normalizeRectangle(selectionRectangle); try (Finally bulkChange = model.beginBulkChange()) { for (IHasMutableSelected mst : typeLogic.getThings(IHasMutableSelected.class)) { if (!BNAUtils.wasControlPressed(evt)) { mst.setSelected(false); } if (mst instanceof IHasBoundingBox && UserEditableUtils.isEditableForAllQualities(mst, IHasMutableSelected.USER_MAY_SELECT)) { Rectangle r = ((IHasBoundingBox) mst).getBoundingBox(); if (BNAUtils.isWithin(selectionRectangle, r)) { if (!BNAUtils.wasControlPressed(evt)) { mst.setSelected(true); } else { mst.setSelected(!mst.isSelected()); } } } } } } } } finally { if (marqueeSelection != null) { model.removeThing(marqueeSelection); marqueeSelection = null; } } } @Override public void mouseClick(IBNAView view, MouseType type, MouseEvent evt, ICoordinate location, ThingsAtLocation thingsAtLocation) { } }