package org.archstudio.bna.logics.editing; import java.awt.geom.Point2D; import org.archstudio.bna.IBNAView; import org.archstudio.bna.IBNAWorld; import org.archstudio.bna.ICoordinate; import org.archstudio.bna.IThing; import org.archstudio.bna.constants.MouseType; import org.archstudio.bna.facets.IHasAnchorPoint; import org.archstudio.bna.facets.IHasAngle; import org.archstudio.bna.facets.IHasMutableAngle; import org.archstudio.bna.logics.AbstractThingLogic; import org.archstudio.bna.logics.coordinating.MirrorValueLogic; import org.archstudio.bna.things.labels.AnchoredLabelThing; import org.archstudio.bna.things.utility.RotaterThing; import org.archstudio.bna.ui.IBNAMenuListener2; import org.archstudio.bna.ui.IBNAMouseClickListener2; import org.archstudio.bna.ui.IBNAMouseMoveListener2; import org.archstudio.bna.utils.Assemblies; import org.archstudio.bna.utils.BNAAction; import org.archstudio.bna.utils.BNAUtils; import org.archstudio.bna.utils.BNAUtils2.ThingsAtLocation; import org.archstudio.sysutils.SystemUtils; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.ui.IWorkbenchActionConstants; public class RotaterLogic extends AbstractThingLogic implements IBNAMouseClickListener2, IBNAMouseMoveListener2, IBNAMenuListener2 { protected final MirrorValueLogic mirrorLogic; protected RotaterThing rt = null; protected boolean pressed = false; protected IThing originalThing = null; protected Integer originalValue = null; public RotaterLogic(IBNAWorld world) { super(world); mirrorLogic = logics.addThingLogic(MirrorValueLogic.class); } @Override public void fillMenu(final IBNAView view, ICoordinate location, ThingsAtLocation thingsAtLocation, IMenuManager menuManager) { BNAUtils.checkLock(); if (thingsAtLocation.getThing() != null) { final AnchoredLabelThing tt = Assemblies.getEditableThing(model, thingsAtLocation.getThing(), AnchoredLabelThing.class, IHasMutableAngle.USER_MAY_CHANGE_ANGLE); if (tt != null) { originalThing = tt; IAction rotateAction = new BNAAction("Rotate") { @Override public void runWithLock() { rt = view.getBNAWorld().getBNAModel().addThing(new RotaterThing(null)); rt.setAngle(tt.getAngle()); mirrorLogic.mirrorValue(tt, IHasAnchorPoint.ANCHOR_POINT_KEY, rt); mirrorLogic.mirrorValue(rt, IHasAngle.ANGLE_KEY, tt); } }; menuManager.add(rotateAction); menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } } } @Override public void mouseDown(IBNAView view, MouseType type, MouseEvent evt, ICoordinate location, ThingsAtLocation thingsAtLocation) { BNAUtils.checkLock(); if (evt.button == 1) { if (rt != null) { Point2D lap = view.getCoordinateMapper().worldToLocal(rt.getAnchorPoint()); Point lm = location.getLocalPoint(); if (Point2D.distance(lap.getX(), lap.getY(), lm.x, lm.y) > rt.getRadius()) { view.getBNAWorld().getBNAModel().removeThing(rt); rt = null; } else if (view.getThingPeer(rt).isInThing(location)) { pressed = true; originalValue = rt.get(IHasAngle.ANGLE_KEY); } } } } @Override public void mouseUp(IBNAView view, MouseType type, MouseEvent evt, ICoordinate location, ThingsAtLocation thingsAtLocation) { BNAUtils.checkLock(); if (pressed) { originalThing.set(IHasAngle.ANGLE_KEY, originalValue); BNAOperations.set("Rotate", model, originalThing, IHasAngle.ANGLE_KEY, rt.get(IHasAngle.ANGLE_KEY)); } pressed = false; } @Override public void mouseClick(IBNAView view, MouseType type, MouseEvent evt, ICoordinate location, ThingsAtLocation thingsAtLocation) { } @Override public void mouseMove(IBNAView view, MouseType type, MouseEvent evt, ICoordinate location, ThingsAtLocation thingsAtLocation) { BNAUtils.checkLock(); if (pressed) { Point2D anchorPointWorld = rt.getAnchorPoint(); Point wPoint = location.getWorldPoint(); double dx = wPoint.x - anchorPointWorld.getX(); double dy = wPoint.y - anchorPointWorld.getY(); double angleInRadians = Math.atan(dy / dx); double angleInDegrees = angleInRadians * 180 / Math.PI; if (dx < 0) { angleInDegrees = (angleInDegrees + 180) % 360; } // double rvsAngleInDegrees = 360 - angleInDegrees; int intAngle = SystemUtils.round(angleInDegrees); int increment = rt.getAdjustmentIncrement(); if (increment > 1) { while (intAngle % increment != 0) { intAngle = (intAngle + 1) % 360; } } rt.setAngle(intAngle); } } }