package org.archstudio.bna.logics.editing;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import org.archstudio.bna.IBNAWorld;
import org.archstudio.bna.facets.IHasMutableReferencePoint;
import org.archstudio.bna.facets.IHasReferencePoint;
import org.archstudio.bna.facets.IHasSelected;
import org.archstudio.bna.logics.AbstractThingLogic;
import org.archstudio.bna.logics.events.DragMoveEvent;
import org.archstudio.bna.logics.events.DragMoveEventsLogic;
import org.archstudio.bna.logics.events.IDragMoveListener;
import org.archstudio.bna.logics.tracking.ThingValueTrackingLogic;
import org.archstudio.bna.things.shapes.ReshapeHandleThing;
import org.archstudio.bna.utils.Assemblies;
import org.archstudio.bna.utils.BNAUtils;
import org.archstudio.sysutils.Finally;
import org.eclipse.swt.graphics.Point;
import com.google.common.collect.Maps;
public class DragMovableLogic extends AbstractThingLogic implements IDragMoveListener {
protected final ThingValueTrackingLogic valueLogic;
protected final Map<IHasMutableReferencePoint, Point> movingThings = Maps.newHashMap();
protected Runnable initialSnapshot = null;
protected Point totalRelativePoint = new Point(0, 0);
protected Point lastAdjustedMousePoint = new Point(0, 0);
public DragMovableLogic(IBNAWorld world) {
super(world);
this.valueLogic = logics.addThingLogic(ThingValueTrackingLogic.class);
logics.addThingLogic(DragMoveEventsLogic.class);
}
@Override
public void dispose() {
BNAUtils.checkLock();
movingThings.clear();
super.dispose();
}
@Override
public void dragStarted(DragMoveEvent evt) {
BNAUtils.checkLock();
movingThings.clear();
totalRelativePoint.x = 0;
totalRelativePoint.y = 0;
lastAdjustedMousePoint = evt.getAdjustedThingLocation().getWorldPoint();
IHasMutableReferencePoint movingThing = Assemblies.getEditableThing(model, evt.getInitialThing(),
IHasMutableReferencePoint.class, IHasMutableReferencePoint.USER_MAY_MOVE);
if (movingThing != null) {
Collection<IHasMutableReferencePoint> selectedThings = valueLogic.getThings(IHasSelected.SELECTED_KEY,
Boolean.TRUE, IHasMutableReferencePoint.class);
if (selectedThings.contains(movingThing)) {
for (IHasMutableReferencePoint rmt : selectedThings) {
movingThings.put(rmt, rmt.getReferencePoint());
}
}
else {
if (movingThing instanceof IHasReferencePoint) {
movingThings.put(movingThing, movingThing.getReferencePoint());
}
else {
movingThings.put(movingThing, null);
}
}
initialSnapshot = BNAOperations.takeSnapshotOfLocations(model, movingThings.keySet());
}
}
@Override
public void dragMoved(DragMoveEvent evt) {
BNAUtils.checkLock();
try (Finally bulkChange = model.beginBulkChange()) {
Point referencePointDelta = evt.getAdjustedThingLocation().getWorldPoint();
Point initialLocation = evt.getInitialLocation().getWorldPoint();
referencePointDelta.x -= initialLocation.x;
referencePointDelta.y -= initialLocation.y;
Point relativePointDelta = evt.getAdjustedThingLocation().getWorldPoint();
relativePointDelta.x -= lastAdjustedMousePoint.x;
relativePointDelta.y -= lastAdjustedMousePoint.y;
totalRelativePoint.x += relativePointDelta.x;
totalRelativePoint.y += relativePointDelta.y;
for (Entry<IHasMutableReferencePoint, Point> e : movingThings.entrySet()) {
if (e.getKey() instanceof IHasMutableReferencePoint) {
Point referencePoint = BNAUtils.clone(e.getValue());
referencePoint.x += referencePointDelta.x;
referencePoint.y += referencePointDelta.y;
e.getKey().setReferencePoint(referencePoint);
}
}
}
finally {
lastAdjustedMousePoint = evt.getAdjustedThingLocation().getWorldPoint();
}
}
@Override
public void dragFinished(DragMoveEvent evt) {
BNAUtils.checkLock();
// if we moved a handle, let the reshape logic handle the undo
if (!(movingThings.size() == 1 && movingThings.keySet().iterator().next() instanceof ReshapeHandleThing)) {
if (totalRelativePoint.x != 0 || totalRelativePoint.y != 0) {
BNAOperations.runnable("Drag", initialSnapshot,
BNAOperations.takeSnapshotOfLocations(model, movingThings.keySet()), false);
}
}
initialSnapshot = null;
movingThings.clear();
}
}