summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/GUI/UndoRedoStack.py
blob: 779d0330a81b5c9163a11d0c80a4a9576bfb5850 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/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)