diff -r e24d2f917c7e -r 7187e1c00975 TextViewer.py --- 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: