--- a/TextViewer.py Wed Jul 25 10:06:29 2007 +0200
+++ b/TextViewer.py Thu Jul 26 17:23:21 2007 +0200
@@ -25,6 +25,7 @@
from wxPython.wx import *
from wxPython.stc import *
import wx
+from types import *
import re
@@ -68,6 +69,27 @@
IDENTIFIER_MODEL = re.compile(re_texts["identifier"])
LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]"%re_texts)
+def GetCursorPos(old, new):
+ old_length = len(old)
+ new_length = len(new)
+ common_length = min(old_length, new_length)
+ i = 0
+ for i in xrange(common_length):
+ if old[i] != new[i]:
+ break
+ if old_length < new_length:
+ if common_length > 0 and old[i] != new[i]:
+ return i + new_length - old_length
+ else:
+ return i + new_length - old_length + 1
+ elif old_length > new_length or i < min(old_length, new_length) - 1:
+ if common_length > 0 and old[i] != new[i]:
+ return i
+ else:
+ return i + 1
+ else:
+ return None
+
class TextViewer(wxStyledTextCtrl):
def __init__(self, parent, window, controler):
@@ -112,14 +134,40 @@
self.Functions = []
self.Jumps = []
self.TextChanged = False
+ self.DisableEvents = True
self.TextSyntax = "ST"
-
+ self.CurrentAction = None
+
+ self.Parent = window
self.Controler = controler
+ self.SetModEventMask(wxSTC_MOD_BEFOREINSERT|wxSTC_MOD_BEFOREDELETE)
+
EVT_KEY_DOWN(self, self.OnKeyDown)
EVT_STC_STYLENEEDED(self, wxID_TEXTVIEWER, self.OnStyleNeeded)
EVT_STC_DO_DROP(self, wxID_TEXTVIEWER, self.OnDoDrop)
EVT_KILL_FOCUS(self, self.OnKillFocus)
+ EVT_STC_MODIFIED(self, wxID_TEXTVIEWER, self.OnModification)
+
+ def OnModification(self, event):
+ if not self.DisableEvents:
+ mod_type = event.GetModificationType()
+ if not (mod_type&wxSTC_PERFORMED_UNDO or mod_type&wxSTC_PERFORMED_REDO):
+ if mod_type&wxSTC_MOD_BEFOREINSERT:
+ if self.CurrentAction == None:
+ self.StartBuffering()
+ elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
+ self.Controler.EndBuffering()
+ self.StartBuffering()
+ self.CurrentAction = ("Add", event.GetPosition())
+ elif mod_type&wxSTC_MOD_BEFOREDELETE:
+ if self.CurrentAction == None:
+ self.StartBuffering()
+ elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
+ self.Controler.EndBuffering()
+ self.StartBuffering()
+ self.CurrentAction = ("Delete", event.GetPosition())
+ event.Skip()
def OnDoDrop(self, event):
try:
@@ -156,10 +204,39 @@
self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
self.Colourise(0, -1)
+ # Buffer the last model state
+ def RefreshBuffer(self):
+ self.Controler.BufferProject()
+ self.Parent.RefreshTitle()
+ self.Parent.RefreshEditMenu()
+
+ def StartBuffering(self):
+ self.Controler.StartBuffering()
+ self.Parent.RefreshTitle()
+ self.Parent.RefreshEditMenu()
+
+ def ResetBuffer(self):
+ if self.CurrentAction != None:
+ self.Controler.EndBuffering()
+ self.CurrentAction = None
+
def RefreshView(self):
- self.SetText(self.Controler.GetCurrentElementEditingText())
+ self.ResetBuffer()
+ self.DisableEvents = True
+ old_cursor_pos = self.GetCurrentPos()
+ old_text = self.GetText()
+ new_text = self.Controler.GetCurrentElementEditingText()
+ self.SetText(new_text)
+ new_cursor_pos = GetCursorPos(old_text, new_text)
+ if new_cursor_pos != None:
+ self.SetSelection(new_cursor_pos, new_cursor_pos)
+ self.EnsureCaretVisible()
+ else:
+ self.SetSelection(old_cursor_pos, old_cursor_pos)
self.RefreshJumpList()
-
+ self.EmptyUndoBuffer()
+ self.DisableEvents = False
+
def OnStyleNeeded(self, event):
self.TextChanged = True
line = self.LineFromPosition(self.GetEndStyled())
@@ -273,13 +350,17 @@
event.Skip()
def Cut(self):
+ self.ResetBuffer()
self.CmdKeyExecute(wxSTC_CMD_CUT)
-
+ self.RefreshBuffer()
+
def Copy(self):
self.CmdKeyExecute(wxSTC_CMD_COPY)
def Paste(self):
+ self.ResetBuffer()
self.CmdKeyExecute(wxSTC_CMD_PASTE)
+ self.RefreshBuffer()
def RefreshModel(self):
if self.TextChanged: