| 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 panel import * |
| 9 | |
| 10 | # Undo/redo classes |
| 11 | class UndoManager: |
| 12 | # Undo/redo stacks |
| 13 | undo = [] |
| 14 | redo = [] |
| 15 | def RegisterUndo(self, undoObj): |
| 16 | self.undo.append(undoObj) |
| 17 | for i in self.redo: i.destroy() |
| 18 | self.redo = [] |
| 19 | def Undo(self): |
| 20 | undoObj = self.undo.pop() |
| 21 | undoObj.undo() |
| 22 | self.redo.append(undoObj) |
| 23 | g.frame.modified = True |
| 24 | g.frame.SetStatusText('Undone') |
| 25 | def Redo(self): |
| 26 | undoObj = self.redo.pop() |
| 27 | undoObj.redo() |
| 28 | self.undo.append(undoObj) |
| 29 | g.frame.modified = True |
| 30 | g.frame.SetStatusText('Redone') |
| 31 | def Clear(self): |
| 32 | for i in self.undo: i.destroy() |
| 33 | self.undo = [] |
| 34 | for i in self.redo: i.destroy() |
| 35 | self.redo = [] |
| 36 | def CanUndo(self): |
| 37 | return not not self.undo |
| 38 | def CanRedo(self): |
| 39 | return not not self.redo |
| 40 | |
| 41 | class UndoCutDelete: |
| 42 | def __init__(self, itemIndex, parent, elem): |
| 43 | self.itemIndex = itemIndex |
| 44 | self.parent = parent |
| 45 | self.elem = elem |
| 46 | def destroy(self): |
| 47 | if self.elem: self.elem.unlink() |
| 48 | def undo(self): |
| 49 | item = g.tree.InsertNode(g.tree.ItemAtFullIndex(self.itemIndex[:-1]), |
| 50 | self.parent, self.elem, |
| 51 | g.tree.ItemAtFullIndex(self.itemIndex)) |
| 52 | # Scroll to show new item (!!! redundant?) |
| 53 | g.tree.EnsureVisible(item) |
| 54 | g.tree.SelectItem(item) |
| 55 | self.elem = None |
| 56 | # Update testWin if needed |
| 57 | if g.testWin and g.tree.IsHighlatable(item): |
| 58 | if g.conf.autoRefresh: |
| 59 | g.tree.needUpdate = True |
| 60 | g.tree.pendingHighLight = item |
| 61 | else: |
| 62 | g.tree.pendingHighLight = None |
| 63 | def redo(self): |
| 64 | item = g.tree.ItemAtFullIndex(self.itemIndex) |
| 65 | # Delete testWin? |
| 66 | if g.testWin: |
| 67 | # If deleting top-level item, delete testWin |
| 68 | if item == g.testWin.item: |
| 69 | g.testWin.Destroy() |
| 70 | g.testWin = None |
| 71 | else: |
| 72 | # Remove highlight, update testWin |
| 73 | if g.testWin.highLight: |
| 74 | g.testWin.highLight.Remove() |
| 75 | g.tree.needUpdate = True |
| 76 | self.elem = g.tree.RemoveLeaf(item) |
| 77 | g.tree.Unselect() |
| 78 | g.panel.Clear() |
| 79 | |
| 80 | class UndoPasteCreate: |
| 81 | def __init__(self, itemParent, parent, item, selected): |
| 82 | self.itemParentIndex = g.tree.ItemFullIndex(itemParent) |
| 83 | self.parent = parent |
| 84 | self.itemIndex = g.tree.ItemFullIndex(item) # pasted item |
| 85 | self.selectedIndex = g.tree.ItemFullIndex(selected) # maybe different from item |
| 86 | self.elem = None |
| 87 | def destroy(self): |
| 88 | if self.elem: self.elem.unlink() |
| 89 | def undo(self): |
| 90 | self.elem = g.tree.RemoveLeaf(g.tree.ItemAtFullIndex(self.itemIndex)) |
| 91 | # Restore old selection |
| 92 | selected = g.tree.ItemAtFullIndex(self.selectedIndex) |
| 93 | g.tree.EnsureVisible(selected) |
| 94 | g.tree.SelectItem(selected) |
| 95 | # Delete testWin? |
| 96 | if g.testWin: |
| 97 | # If deleting top-level item, delete testWin |
| 98 | if selected == g.testWin.item: |
| 99 | g.testWin.Destroy() |
| 100 | g.testWin = None |
| 101 | else: |
| 102 | # Remove highlight, update testWin |
| 103 | if g.testWin.highLight: |
| 104 | g.testWin.highLight.Remove() |
| 105 | g.tree.needUpdate = True |
| 106 | def redo(self): |
| 107 | item = g.tree.InsertNode(g.tree.ItemAtFullIndex(self.itemParentIndex), |
| 108 | self.parent, self.elem, |
| 109 | g.tree.ItemAtFullIndex(self.itemIndex)) |
| 110 | # Scroll to show new item |
| 111 | g.tree.EnsureVisible(item) |
| 112 | g.tree.SelectItem(item) |
| 113 | self.elem = None |
| 114 | # Update testWin if needed |
| 115 | if g.testWin and g.tree.IsHighlatable(item): |
| 116 | if g.conf.autoRefresh: |
| 117 | g.tree.needUpdate = True |
| 118 | g.tree.pendingHighLight = item |
| 119 | else: |
| 120 | g.tree.pendingHighLight = None |
| 121 | |
| 122 | class UndoEdit: |
| 123 | def __init__(self): |
| 124 | self.pages = map(ParamPage.GetState, g.panel.pages) |
| 125 | self.selectedIndex = g.tree.ItemFullIndex(g.tree.GetSelection()) |
| 126 | def destroy(self): |
| 127 | pass |
| 128 | # Update test view |
| 129 | def update(self, selected): |
| 130 | g.tree.Apply(g.tree.GetPyData(selected), selected) |
| 131 | # Update view |
| 132 | if g.testWin: |
| 133 | if g.testWin.highLight: |
| 134 | g.testWin.highLight.Remove() |
| 135 | g.tree.pendingHighLight = selected |
| 136 | if g.testWin: |
| 137 | g.tree.needUpdate = True |
| 138 | def undo(self): |
| 139 | # Restore selection |
| 140 | selected = g.tree.ItemAtFullIndex(self.selectedIndex) |
| 141 | if selected != g.tree.GetSelection(): |
| 142 | g.tree.SelectItem(selected) |
| 143 | # Save current state for redo |
| 144 | map(ParamPage.SaveState, g.panel.pages) |
| 145 | pages = map(ParamPage.GetState, g.panel.pages) |
| 146 | map(ParamPage.SetState, g.panel.pages, self.pages) |
| 147 | self.pages = pages |
| 148 | self.update(selected) |
| 149 | def redo(self): |
| 150 | self.undo() |
| 151 | self.update(g.tree.GetSelection()) |