undo (was Re: Why does Dynamic Typing really matter?!?)

David Eppstein eppstein at ics.uci.edu
Sat Feb 8 00:41:09 EST 2003


In article <b21qof$sde$1 at slb5.atl.mindspring.net>,
 "Andrew Dalke" <adalke at mindspring.com> wrote:

> Can you or someone point me to a web page describing how to
> implement do/undo/redo frameworks?  I've been looking around
> and found a few references, but would like a few more to make sure
> I understand things rightly.  Eg, I found the Cocao undo manager example
> very interesting.

For anyone else looking for them, the Cocoa undo manager docs are at
<http://developer.apple.com/techpubs/macosx/Cocoa/Reference/Foundation/Ob
jC_classic/Classes/NSUndoManager.html>
it doesn't say what the implementation looks like, but at least I think 
the full API might be helpful. 

An alternative technique I tried before getting the Cocoa one to work 
for me: the undo controller stores two stacks of undo items, the undo 
stack and the redo stack.  Each item contains two functions, one to undo 
and one to redo.  To undo an action, pop the undo stack, call the popped 
item's undo function, and push the item onto the redo stack.  To redo an 
item, pop the redo stack, call the popped item's redo function, and push 
the item onto the undo stack.  To perform a new action that can be 
undone, put a new item onto the undo stack, clear out the redo stack, 
and call the new item's redo function.  It's a little less flexible and 
more cumbersome than the Cocoa version, but it works.

A couple things to be careful of:

- It's very important that you tell the undo manager about any change 
that any other undoable action depends on.  If you do an action, then 
change your data structures in a way that the undo manager doesn't see, 
then undo your action, you could easily end up in an inconsistent state.

- For similar reasons, you should make sure that all pending changes 
finish happening before you make an undoable action.  Specifically, in 
Cocoa, I was having a problem that when you edit a text item, the edit 
isn't visible to the code until you finish it and move to another item. 
 If you start an edit and hit undo, the undo manager undoes whatever 
you did previously, but you're still left in the middle of editing 
something that may not exist any more after the undo.  Result: 
inconsistencies again.  Solution: intercept undo/redo requests and force 
any pending edits to finish before the requests reach the undo manager.

-- 
David Eppstein       UC Irvine Dept. of Information & Computer Science
eppstein at ics.uci.edu http://www.ics.uci.edu/~eppstein/




More information about the Python-list mailing list