package org.archstudio.bna.logics.editing; import java.awt.geom.Point2D; import java.util.List; import org.archstudio.bna.IBNAModel; import org.archstudio.bna.IThing; import org.archstudio.bna.facets.IHasMutableBoundingBox; import org.archstudio.bna.facets.IHasMutableEndpoints; import org.archstudio.bna.facets.IHasMutableMidpoints; import org.archstudio.bna.facets.IHasMutableReferencePoint; import org.archstudio.bna.facets.IHasMutableSize; import org.archstudio.bna.facets.IHasReferencePoint; import org.archstudio.bna.keys.IThingKey; import org.archstudio.bna.utils.UserEditableUtils; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.commands.operations.AbstractOperation; import org.eclipse.core.commands.operations.IOperationHistory; import org.eclipse.core.commands.operations.IUndoContext; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.ui.PlatformUI; import com.google.common.collect.Lists; public class BNAOperations { public static void runnable(String label, final Runnable undoRunnable, final Runnable redoRunnable, boolean execute) { if (execute) { redoRunnable.run(); } if (!Platform.isRunning() || !PlatformUI.isWorkbenchRunning()) { return; } IUndoContext undoContext = PlatformUI.getWorkbench().getOperationSupport().getUndoContext(); IOperationHistory operationHistory = PlatformUI.getWorkbench().getOperationSupport().getOperationHistory(); AbstractOperation bnaOperation = new AbstractOperation(label) { @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return Status.OK_STATUS; } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { undoRunnable.run(); return Status.OK_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { redoRunnable.run(); return Status.OK_STATUS; } }; bnaOperation.addContext(undoContext); operationHistory.add(bnaOperation); } public static <V> void set(String label, final IBNAModel model, IThing t, final IThingKey<V> key, final V newValue) { final V oldValue = t.get(key); t.set(key, newValue); final Object tID = t.getID(); IUndoContext undoContext = PlatformUI.getWorkbench().getOperationSupport().getUndoContext(); IOperationHistory operationHistory = PlatformUI.getWorkbench().getOperationSupport().getOperationHistory(); AbstractOperation bnaOperation = new AbstractOperation(label) { @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return Status.OK_STATUS; } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { IThing t = model.getThing(tID); if (t != null) { t.set(key, oldValue); } return Status.OK_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { IThing t = model.getThing(tID); if (t != null) { t.set(key, newValue); } return Status.OK_STATUS; } }; bnaOperation.addContext(undoContext); operationHistory.add(bnaOperation); } /** * Records a set of operations that will restore things to their current locations. Used for undo/redo. */ public static Runnable takeSnapshotOfLocations(final IBNAModel model, Iterable<? extends IThing> things) { final List<Runnable> runnables = Lists.newArrayList(); for (IThing t : things) { final Object tID = t.getID(); if (t instanceof IHasReferencePoint && UserEditableUtils.isEditableForAnyQualities(t, IHasMutableReferencePoint.USER_MAY_MOVE)) { final Point p = ((IHasReferencePoint) t).getReferencePoint(); runnables.add(new Runnable() { @Override public void run() { IThing t = model.getThing(tID); if (t != null) { ((IHasReferencePoint) t).setReferencePoint(p); } } }); continue; } if (t instanceof IHasMutableBoundingBox && UserEditableUtils.isEditableForAnyQualities(t, IHasMutableReferencePoint.USER_MAY_MOVE, IHasMutableSize.USER_MAY_RESIZE)) { final Rectangle r = ((IHasMutableBoundingBox) t).getBoundingBox(); runnables.add(new Runnable() { @Override public void run() { IThing t = model.getThing(tID); if (t != null) { ((IHasMutableBoundingBox) t).setBoundingBox(r); } } }); continue; } if (t instanceof IHasMutableEndpoints && UserEditableUtils.isEditableForAllQualities(t, IHasMutableEndpoints.USER_MAY_MOVE_ENDPOINT_1)) { final Point2D ep1 = ((IHasMutableEndpoints) t).getEndpoint1(); runnables.add(new Runnable() { @Override public void run() { IThing t = model.getThing(tID); if (t != null) { ((IHasMutableEndpoints) t).setEndpoint1(ep1); } } }); continue; } if (t instanceof IHasMutableEndpoints && UserEditableUtils.isEditableForAllQualities(t, IHasMutableEndpoints.USER_MAY_MOVE_ENDPOINT_2)) { final Point2D ep2 = ((IHasMutableEndpoints) t).getEndpoint2(); runnables.add(new Runnable() { @Override public void run() { IThing t = model.getThing(tID); if (t != null) { ((IHasMutableEndpoints) t).setEndpoint2(ep2); } } }); continue; } if (t instanceof IHasMutableMidpoints && UserEditableUtils.isEditableForAllQualities(t, IHasMutableMidpoints.USER_MAY_MOVE_MIDPOINTS)) { final List<Point2D> p = ((IHasMutableMidpoints) t).getMidpoints(); runnables.add(new Runnable() { @Override public void run() { IThing t = model.getThing(tID); if (t != null) { ((IHasMutableMidpoints) t).setMidpoints(p); } } }); continue; } } return new Runnable() { @Override public void run() { for (Runnable r : runnables) { r.run(); } } }; } }