#!/usr/bin/env python ########################################################################### # # UndoRedoStack implements the usual undo/redo capabilities of a GUI # # Author: Orest Shardt # Created: July 23, 2007 # ########################################################################### class action: def __init__(self,act,inv): self.act = act self.inv = inv def undo(self): #print "Undo:",self self.inv() def redo(self): #print "Redo:",self self.act() def __str__(self): return "A generic action" class beginActionGroup: pass class endActionGroup: pass class actionStack: def __init__(self): self.clear() def add(self,action): self.undoStack.append(action) #print "Added",action self.redoStack = [] def undo(self): if len(self.undoStack) > 0: op = self.undoStack.pop() if op is beginActionGroup: level = 1 self.redoStack.append(endActionGroup) while level > 0: op=self.undoStack.pop() if op is endActionGroup: level -= 1 self.redoStack.append(beginActionGroup) elif op is beginActionGroup: level += 1 self.redoStack.append(endActionGroup) else: op.undo() self.redoStack.append(op) elif op is endActionGroup: raise Exception,"endActionGroup without previous beginActionGroup" else: self.redoStack.append(op) op.undo() #print "undid",op else: pass #print "nothing to undo" def redo(self): if len(self.redoStack) > 0: op = self.redoStack.pop() if op is beginActionGroup: level = 1 self.undoStack.append(endActionGroup) while level > 0: op = self.redoStack.pop() if op is endActionGroup: level -= 1 self.undoStack.append(beginActionGroup) elif op is beginActionGroup: level += 1 self.undoStack.append(endActionGroup) else: op.redo() self.undoStack.append(op) elif op is endActionGroup: raise Exception,"endActionGroup without previous beginActionGroup" else: self.undoStack.append(op) op.redo() #print "redid",op else: pass #print "nothing to redo" def setCommitLevel(self): self.commitLevel = len(self.undoStack) def changesMade(self): if len(self.undoStack) != self.commitLevel: return True else: return False def clear(self): self.redoStack = [] self.undoStack = [] self.commitLevel = 0 if __name__=='__main__': import sys def opq(): print "action1" def unopq(): print "inverse1" q = action(opq,unopq) w = action(lambda:sys.stdout.write("action2\n"),lambda:sys.stdout.write("inverse2\n")) e = action(lambda:sys.stdout.write("action3\n"),lambda:sys.stdout.write("inverse3\n")) s = actionStack() s.add(q) s.add(w) s.add(e)