Add Undo/Redo to the Scene Editor - Rollback visibility is limited to 20 steps since it's ocpying the entire model at each step.

git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@900 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Mike Thomas
2010-03-11 00:54:14 +00:00
parent c2500248db
commit b8b1a414be
2 changed files with 78 additions and 3 deletions
@@ -272,6 +272,14 @@ public class EditorFrame extends ManagedJFrame
accel = KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.CTRL_MASK); accel = KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.CTRL_MASK);
MenuUtil.addMenuItem(menuActions, "Update mini view", MenuUtil.addMenuItem(menuActions, "Update mini view",
KeyEvent.VK_M, accel, this, "updateMiniView"); KeyEvent.VK_M, accel, this, "updateMiniView");
accel = KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK);
MenuUtil.addMenuItem(menuActions, "Undo",
KeyEvent.VK_Z, accel, this, "undo");
accel = KeyStroke.getKeyStroke(KeyEvent.VK_Y, ActionEvent.CTRL_MASK);
MenuUtil.addMenuItem(menuActions, "Redo",
KeyEvent.VK_Y, accel, this, "redo");
} }
protected void setScene (StageScene scene) protected void setScene (StageScene scene)
@@ -494,6 +502,16 @@ public class EditorFrame extends ManagedJFrame
_scrollBox.updateView(); _scrollBox.updateView();
} }
public void undo (ActionEvent evt)
{
_svpanel.undo();
}
public void redo (ActionEvent evt)
{
_svpanel.redo();
}
/** /**
* Handles a request to open the preferences dialog. * Handles a request to open the preferences dialog.
*/ */
@@ -23,6 +23,7 @@ package com.threerings.stage.tools.editor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.awt.AlphaComposite; import java.awt.AlphaComposite;
@@ -220,6 +221,8 @@ public class EditorScenePanel extends StageScenePanel
*/ */
protected void placeTile (int x, int y) protected void placeTile (int x, int y)
{ {
markCheckpoint();
Rectangle drag = clearTileSelectRegion(x, y); Rectangle drag = clearTileSelectRegion(x, y);
// sanity check // sanity check
@@ -250,6 +253,8 @@ public class EditorScenePanel extends StageScenePanel
*/ */
protected void deleteTile (int x, int y) protected void deleteTile (int x, int y)
{ {
markCheckpoint();
Rectangle drag = clearTileSelectRegion(x, y); Rectangle drag = clearTileSelectRegion(x, y);
log.info("Deleting " + drag); log.info("Deleting " + drag);
@@ -301,6 +306,8 @@ public class EditorScenePanel extends StageScenePanel
*/ */
protected void editTile (int x, int y) protected void editTile (int x, int y)
{ {
markCheckpoint();
// bail if we're not hovering over a scene object // bail if we're not hovering over a scene object
if (_hobject == null || !(_hobject instanceof SceneObject)) { if (_hobject == null || !(_hobject instanceof SceneObject)) {
return; return;
@@ -332,6 +339,8 @@ public class EditorScenePanel extends StageScenePanel
*/ */
protected void editPortal (EditablePortal portal) protected void editPortal (EditablePortal portal)
{ {
markCheckpoint();
// create our portal dialog if we haven't yet // create our portal dialog if we haven't yet
if (_dialogPortal == null) { if (_dialogPortal == null) {
_dialogPortal = new PortalDialog(_ctx, this); _dialogPortal = new PortalDialog(_ctx, this);
@@ -397,6 +406,8 @@ public class EditorScenePanel extends StageScenePanel
break; break;
case EditorModel.ACTION_PLACE_PORTAL: case EditorModel.ACTION_PLACE_PORTAL:
markCheckpoint();
Point fcoords = getFullCoords(mx, my); Point fcoords = getFullCoords(mx, my);
// mouse button three is delete // mouse button three is delete
if (event.getButton() == MouseEvent.BUTTON3) { if (event.getButton() == MouseEvent.BUTTON3) {
@@ -1118,6 +1129,49 @@ public class EditorScenePanel extends StageScenePanel
} }
} }
protected void markCheckpoint ()
{
_undo.preserve();
_redo.clear();
}
public void undo ()
{
if (_undo.size() > 0) {
_redo.preserve();
_undo.rollback();
}
}
public void redo ()
{
if (_redo.size() > 0) {
_undo.preserve();
_redo.rollback();
}
}
protected class UndoStack extends LinkedList<MisoSceneModel>
{
public void preserve () {
addFirst(_model.clone());
if (size() > MAX_UNDO_SIZE) {
removeLast();
}
}
public void rollback () {
if (size() > 0) {
_model = removeFirst();
_blocks.clear();
refreshScene();
}
}
}
protected static final int MAX_UNDO_SIZE = 20;
/** Provides access to stuff. */ /** Provides access to stuff. */
protected EditorContext _ctx; protected EditorContext _ctx;
@@ -1177,6 +1231,9 @@ public class EditorScenePanel extends StageScenePanel
/** The object currently being edited by the object editor dialog. */ /** The object currently being edited by the object editor dialog. */
protected SceneObject _eobject; protected SceneObject _eobject;
protected UndoStack _undo = new UndoStack();
protected UndoStack _redo = new UndoStack();
/** The triangle used to render a portal on-screen. */ /** The triangle used to render a portal on-screen. */
protected static Polygon _locTri; protected static Polygon _locTri;