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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
import Pmw
_ORIGINAL = 0
_MODIFIED = 1
_DISPLAY = 2
class HistoryText(Pmw.ScrolledText):
def __init__(self, parent = None, **kw):
# Define the megawidget options.
optiondefs = (
('compressany', 1, None),
('compresstail', 1, None),
('historycommand', None, None),
)
self.defineoptions(kw, optiondefs)
# Initialise the base class (after defining the options).
Pmw.ScrolledText.__init__(self, parent)
# Initialise instance variables.
self._list = []
self._currIndex = 0
self._pastIndex = None
self._lastIndex = 0 # pointer to end of history list
# Check keywords and initialise options.
self.initialiseoptions()
def addhistory(self):
text = self.get()
if text[-1] == '\n':
text = text[:-1]
if len(self._list) == 0:
# This is the first history entry. Add it.
self._list.append([text, text, _MODIFIED])
return
currentEntry = self._list[self._currIndex]
if text == currentEntry[_ORIGINAL]:
# The current history entry has not been modified. Check if
# we need to add it again.
if self['compresstail'] and self._currIndex == self._lastIndex:
return
if self['compressany']:
return
# Undo any changes for the current history entry, since they
# will now be available in the new entry.
currentEntry[_MODIFIED] = currentEntry[_ORIGINAL]
historycommand = self['historycommand']
if self._currIndex == self._lastIndex:
# The last history entry is currently being displayed,
# so disable the special meaning of the 'Next' button.
self._pastIndex = None
nextState = 'disabled'
else:
# A previous history entry is currently being displayed,
# so allow the 'Next' button to go to the entry after this one.
self._pastIndex = self._currIndex
nextState = 'normal'
if callable(historycommand):
historycommand('normal', nextState)
# Create the new history entry.
self._list.append([text, text, _MODIFIED])
# Move the pointer into the history entry list to the end.
self._lastIndex = self._lastIndex + 1
self._currIndex = self._lastIndex
def next(self):
if self._currIndex == self._lastIndex and self._pastIndex is None:
self.bell()
else:
self._modifyDisplay('next')
def prev(self):
self._pastIndex = None
if self._currIndex == 0:
self.bell()
else:
self._modifyDisplay('prev')
def undo(self):
if len(self._list) != 0:
self._modifyDisplay('undo')
def redo(self):
if len(self._list) != 0:
self._modifyDisplay('redo')
def gethistory(self):
return self._list
def _modifyDisplay(self, command):
# Modify the display to show either the next or previous
# history entry (next, prev) or the original or modified
# version of the current history entry (undo, redo).
# Save the currently displayed text.
currentText = self.get()
if currentText[-1] == '\n':
currentText = currentText[:-1]
currentEntry = self._list[self._currIndex]
if currentEntry[_DISPLAY] == _MODIFIED:
currentEntry[_MODIFIED] = currentText
elif currentEntry[_ORIGINAL] != currentText:
currentEntry[_MODIFIED] = currentText
if command in ('next', 'prev'):
currentEntry[_DISPLAY] = _MODIFIED
if command in ('next', 'prev'):
prevstate = 'normal'
nextstate = 'normal'
if command == 'next':
if self._pastIndex is not None:
self._currIndex = self._pastIndex
self._pastIndex = None
self._currIndex = self._currIndex + 1
if self._currIndex == self._lastIndex:
nextstate = 'disabled'
elif command == 'prev':
self._currIndex = self._currIndex - 1
if self._currIndex == 0:
prevstate = 'disabled'
historycommand = self['historycommand']
if callable(historycommand):
historycommand(prevstate, nextstate)
currentEntry = self._list[self._currIndex]
else:
if command == 'undo':
currentEntry[_DISPLAY] = _ORIGINAL
elif command == 'redo':
currentEntry[_DISPLAY] = _MODIFIED
# Display the new text.
self.delete('1.0', 'end')
self.insert('end', currentEntry[currentEntry[_DISPLAY]])
|