]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/XRCed/undo.py
- undo/redo fixes for moving and cut/paste;
[wxWidgets.git] / wxPython / wx / tools / XRCed / undo.py
1 # Name: undo.py
2 # Purpose: XRC editor, undo/redo module
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
4 # Created: 01.12.2002
5 # RCS-ID: $Id$
6
7 from globals import *
8 from xxx import MakeXXXFromDOM
9 from tree import *
10 #from panel import *
11
12 # Undo/redo classes
13 class UndoManager:
14 # Undo/redo stacks
15 undo = []
16 redo = []
17 def RegisterUndo(self, undoObj):
18 self.undo.append(undoObj)
19 for i in self.redo: i.destroy()
20 self.redo = []
21 def Undo(self):
22 undoObj = self.undo.pop()
23 undoObj.undo()
24 self.redo.append(undoObj)
25 g.frame.SetModified()
26 g.frame.SetStatusText('Undone')
27 def Redo(self):
28 undoObj = self.redo.pop()
29 undoObj.redo()
30 self.undo.append(undoObj)
31 g.frame.SetModified()
32 g.frame.SetStatusText('Redone')
33 def Clear(self):
34 for i in self.undo: i.destroy()
35 self.undo = []
36 for i in self.redo: i.destroy()
37 self.redo = []
38 def CanUndo(self):
39 return not not self.undo
40 def CanRedo(self):
41 return not not self.redo
42
43 class UndoCutDelete:
44 def __init__(self, itemIndex, parent, elem):
45 self.itemIndex = itemIndex
46 self.parent = parent
47 self.elem = elem
48 def destroy(self):
49 if self.elem: self.elem.unlink()
50 def undo(self):
51 item = g.tree.InsertNode(g.tree.ItemAtFullIndex(self.itemIndex[:-1]),
52 self.parent, self.elem,
53 g.tree.ItemAtFullIndex(self.itemIndex))
54 # Scroll to show new item (!!! redundant?)
55 g.tree.EnsureVisible(item)
56 g.tree.SelectItem(item)
57 self.elem = None
58 # Update testWin if needed
59 if g.testWin and g.tree.IsHighlatable(item):
60 if g.conf.autoRefresh:
61 g.tree.needUpdate = True
62 g.tree.pendingHighLight = item
63 else:
64 g.tree.pendingHighLight = None
65 def redo(self):
66 item = g.tree.ItemAtFullIndex(self.itemIndex)
67 # Delete testWin?
68 if g.testWin:
69 # If deleting top-level item, delete testWin
70 if item == g.testWin.item:
71 g.testWin.Destroy()
72 g.testWin = None
73 else:
74 # Remove highlight, update testWin
75 if g.testWin.highLight:
76 g.testWin.highLight.Remove()
77 g.tree.needUpdate = True
78 self.elem = g.tree.RemoveLeaf(item)
79 g.tree.UnselectAll()
80 g.panel.Clear()
81
82 class UndoPasteCreate:
83 def __init__(self, itemParent, parent, item, selected):
84 self.itemParentIndex = g.tree.ItemFullIndex(itemParent)
85 self.parent = parent
86 self.itemIndex = g.tree.ItemFullIndex(item) # pasted item
87 self.selectedIndex = g.tree.ItemFullIndex(selected) # maybe different from item
88 self.elem = None
89 def destroy(self):
90 if self.elem: self.elem.unlink()
91 def undo(self):
92 self.elem = g.tree.RemoveLeaf(g.tree.ItemAtFullIndex(self.itemIndex))
93 # Restore old selection
94 selected = g.tree.ItemAtFullIndex(self.selectedIndex)
95 g.tree.EnsureVisible(selected)
96 g.tree.SelectItem(selected)
97 # Delete testWin?
98 if g.testWin:
99 # If deleting top-level item, delete testWin
100 if selected == g.testWin.item:
101 g.testWin.Destroy()
102 g.testWin = None
103 else:
104 # Remove highlight, update testWin
105 if g.testWin.highLight:
106 g.testWin.highLight.Remove()
107 g.tree.needUpdate = True
108 def redo(self):
109 item = g.tree.InsertNode(g.tree.ItemAtFullIndex(self.itemParentIndex),
110 self.parent, self.elem,
111 g.tree.ItemAtFullIndex(self.itemIndex))
112 # Scroll to show new item
113 g.tree.EnsureVisible(item)
114 g.tree.SelectItem(item)
115 self.elem = None
116 # Update testWin if needed
117 if g.testWin and g.tree.IsHighlatable(item):
118 if g.conf.autoRefresh:
119 g.tree.needUpdate = True
120 g.tree.pendingHighLight = item
121 else:
122 g.tree.pendingHighLight = None
123
124 class UndoReplace:
125 def __init__(self, item):
126 self.itemIndex = g.tree.ItemFullIndex(item)
127 #self.xxx = g.tree.GetPyData(item)
128 self.elem = None
129 def destroy(self):
130 if self.elem: self.elem.unlink()
131 def undo(self):
132 print 'Sorry, UndoReplace is not yet implemented.'
133 return
134 item = g.tree.ItemAtFullIndex(self.itemIndex)
135 xxx = g.tree.GetPyData(item)
136 # Replace with old element
137 parent = xxx.parent.node
138 if xxx is self.xxx: # sizeritem or notebookpage - replace child
139 parent.replaceChild(self.xxx.child.node, xxx.child.node)
140 else:
141 parent.replaceChild(self.xxx.node, xxx.node)
142 self.xxx.parent = xxx.parent
143 xxx = self.xxx
144 g.tree.SetPyData(item, xxx)
145 g.tree.SetItemText(item, xxx.treeName())
146 g.tree.SetItemImage(item, xxx.treeImage())
147
148 # Update panel
149 g.panel.SetData(xxx)
150 # Update tools
151 g.tools.UpdateUI()
152 g.tree.EnsureVisible(item)
153 g.tree.SelectItem(item)
154 # Delete testWin?
155 if g.testWin:
156 # If deleting top-level item, delete testWin
157 if selected == g.testWin.item:
158 g.testWin.Destroy()
159 g.testWin = None
160 else:
161 # Remove highlight, update testWin
162 if g.testWin.highLight:
163 g.testWin.highLight.Remove()
164 g.tree.needUpdate = True
165 def redo(self):
166 return
167
168 class UndoMove:
169 def __init__(self, oldParent, oldIndex, newParent, newIndex):
170 # Store indexes because items can be invalid already
171 self.oldParentIndex = g.tree.ItemFullIndex(oldParent)
172 self.oldIndex = oldIndex
173 self.newParentIndex = g.tree.ItemFullIndex(newParent)
174 self.newIndex = newIndex
175 def destroy(self):
176 pass
177 def undo(self):
178 oldParent = g.tree.ItemAtFullIndex(self.oldParentIndex)
179 newParent = g.tree.ItemAtFullIndex(self.newParentIndex)
180 item = g.tree.GetFirstChild(newParent)[0]
181 for i in range(self.newIndex): item = g.tree.GetNextSibling(item)
182 elem = g.tree.RemoveLeaf(item)
183 nextItem = g.tree.GetFirstChild(oldParent)[0]
184 for i in range(self.oldIndex): nextItem = g.tree.GetNextSibling(nextItem)
185
186 parent = g.tree.GetPyData(oldParent).treeObject()
187
188 # Check parent and child relationships.
189 # If parent is sizer or notebook, child is of wrong class or
190 # parent is normal window, child is child container then detach child.
191 xxx = MakeXXXFromDOM(parent, elem)
192 isChildContainer = isinstance(xxx, xxxChildContainer)
193 if isChildContainer and \
194 ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
195 (isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
196 not (parent.isSizer or isinstance(parent, xxxNotebook))):
197 elem.removeChild(xxx.child.node) # detach child
198 elem.unlink() # delete child container
199 elem = xxx.child.node # replace
200 # This may help garbage collection
201 xxx.child.parent = None
202 isChildContainer = False
203 # Parent is sizer or notebook, child is not child container
204 if parent.isSizer and not isChildContainer and not isinstance(xxx, xxxSpacer):
205 # Create sizer item element
206 sizerItemElem = MakeEmptyDOM('sizeritem')
207 sizerItemElem.appendChild(elem)
208 elem = sizerItemElem
209 elif isinstance(parent, xxxNotebook) and not isChildContainer:
210 pageElem = MakeEmptyDOM('notebookpage')
211 pageElem.appendChild(elem)
212 elem = pageElem
213
214 selected = g.tree.InsertNode(oldParent, parent, elem, nextItem)
215 g.tree.EnsureVisible(selected)
216 # Highlight is outdated
217 if g.testWin and g.testWin.highLight:
218 g.testWin.highLight.Remove()
219 g.tree.needUpdate = True
220 g.tree.SelectItem(selected)
221 def redo(self):
222 oldParent = g.tree.ItemAtFullIndex(self.oldParentIndex)
223 newParent = g.tree.ItemAtFullIndex(self.newParentIndex)
224 item = g.tree.GetFirstChild(oldParent)[0]
225 for i in range(self.oldIndex): item = g.tree.GetNextSibling(item)
226 elem = g.tree.RemoveLeaf(item)
227
228 parent = g.tree.GetPyData(newParent).treeObject()
229
230 # Check parent and child relationships.
231 # If parent is sizer or notebook, child is of wrong class or
232 # parent is normal window, child is child container then detach child.
233 xxx = MakeXXXFromDOM(parent, elem)
234 isChildContainer = isinstance(xxx, xxxChildContainer)
235 if isChildContainer and \
236 ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
237 (isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
238 not (parent.isSizer or isinstance(parent, xxxNotebook))):
239 elem.removeChild(xxx.child.node) # detach child
240 elem.unlink() # delete child container
241 elem = xxx.child.node # replace
242 # This may help garbage collection
243 xxx.child.parent = None
244 isChildContainer = False
245 # Parent is sizer or notebook, child is not child container
246 if parent.isSizer and not isChildContainer and not isinstance(xxx, xxxSpacer):
247 # Create sizer item element
248 sizerItemElem = MakeEmptyDOM('sizeritem')
249 sizerItemElem.appendChild(elem)
250 elem = sizerItemElem
251 elif isinstance(parent, xxxNotebook) and not isChildContainer:
252 pageElem = MakeEmptyDOM('notebookpage')
253 pageElem.appendChild(elem)
254 elem = pageElem
255
256 nextItem = g.tree.GetFirstChild(newParent)[0]
257 for i in range(self.newIndex): nextItem = g.tree.GetNextSibling(nextItem)
258 selected = g.tree.InsertNode(newParent, parent, elem, nextItem)
259 g.tree.EnsureVisible(selected)
260 # Highlight is outdated
261 if g.testWin and g.testWin.highLight:
262 g.testWin.highLight.Remove()
263 g.tree.needUpdate = True
264 g.tree.SelectItem(selected)
265
266 class UndoEdit:
267 def __init__(self):
268 self.pages = map(ParamPage.GetState, g.panel.pages)
269 self.selectedIndex = g.tree.ItemFullIndex(g.tree.GetSelection())
270 def destroy(self):
271 pass
272 # Update test view
273 def update(self, selected):
274 g.tree.Apply(g.tree.GetPyData(selected), selected)
275 # Update view
276 if g.testWin:
277 if g.testWin.highLight:
278 g.testWin.highLight.Remove()
279 g.tree.pendingHighLight = selected
280 if g.testWin:
281 g.tree.needUpdate = True
282 def undo(self):
283 # Restore selection
284 selected = g.tree.ItemAtFullIndex(self.selectedIndex)
285 if selected != g.tree.GetSelection():
286 g.tree.SelectItem(selected)
287 # Save current state for redo
288 map(ParamPage.SaveState, g.panel.pages)
289 pages = map(ParamPage.GetState, g.panel.pages)
290 if self.pages:
291 map(ParamPage.SetState, g.panel.pages, self.pages)
292 self.pages = pages
293 self.update(selected)
294 def redo(self):
295 self.undo()
296 self.update(g.tree.GetSelection())