Undo
- Enables exploratory learning
- Try the unknowns
- Allows you to recover from errors
- Input errors (human) and interpretation errors (computer)
- Allows you to evaluate modification
- Fast undo/redo cycle
Undo Design Choices
Undoable Actions
- Which actions should/can be undone
Possible actions
- Some actions may be omitted from udo
- Change to selection, window resizing etc.
- Some actions are destructive and not easily undone
- e.g. equitting program with unsaved data
- Some actions can't be undone
- e.g. printing
In general
- All change sto the model should be undoable
- Changes to the view, or docuemnt's interface state should be undoable if they are extremely tedious or require significant effort
- Prompt the user before performing destructive actions
State Restoration
- User interface state should be meaningful after undo/redo action
- Change selection (focus) to object(s) changed as a result of undo/redo
- Scroll to show selection, if neccessary
- Given focus to the control that is hosting the changed state
Granularity
Define undoable "chunk"
The conceptual change from one document state to another
In our drawing example
- MousePress to start line
- MouseDrag to define line path
- MouseRelease to end line
- MousePress + MouseDrag + MouseRelease = 1 chunk
Ignore direct manipulation intermediate states
- e.g. the intermediate states when you drag the shape to anothe position on canvas
Chunk all changes resulting from an interface event
Delimit on discrete input breaks
Scope
- Where does undo happen?
- System level
- Application level
- Document level
- Widget level
Implementing Undo
- Implement an undo stack
Forward Undo
- Save complete baseline document state at some past point
- Save change records to transform baseline docment into current document state
- To do last action, don't apply last change record
Reverse Undo
- Save complete current document state
- Save reverse change records to return to previous state
- To undo last action, apply last reverse change records
Change Record Implementation
Memento pattern
- Save snapshot of each documents tate
- Could be complete state or difference from "last" state
Command pattern
Save commands to execute to change state
Java platform uses reverse undo with command pattern
Implementation
- User issues command
- Execute command to create a new current document state
- Push reverse command onto undo stack
- Clear redo stack
- Undo
- Pop reverse command from undo stack and execute it to create new current document state
- Push original command on redo stack
Redo
- Pop command off redo stack and execute it to create new current document state
- Push reverse command on undo stack
See slides for sample code
Destructive Commands
- Use forward command undo
Use reverse command undo, but un-execute command stores previous state for "destructive" commands
- That's Memento, which may require a lot of memory