TextViewer.py
changeset 56 7187e1c00975
parent 53 4988262d03e3
child 58 39cd981ff242
equal deleted inserted replaced
55:e24d2f917c7e 56:7187e1c00975
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24 
    24 
    25 from wxPython.wx import *
    25 from wxPython.wx import *
    26 from wxPython.stc import * 
    26 from wxPython.stc import * 
    27 import wx
    27 import wx
       
    28 from types import *
    28 
    29 
    29 import re
    30 import re
    30 
    31 
    31 #-------------------------------------------------------------------------------
    32 #-------------------------------------------------------------------------------
    32 #                         Textual programs Viewer class
    33 #                         Textual programs Viewer class
    66 re_texts["digit"] = "[0-9]"
    67 re_texts["digit"] = "[0-9]"
    67 re_texts["identifier"] = "((?:%(letter)s|(?:_(?:%(letter)s|%(digit)s)))(?:_?(?:%(letter)s|%(digit)s))*)"%re_texts
    68 re_texts["identifier"] = "((?:%(letter)s|(?:_(?:%(letter)s|%(digit)s)))(?:_?(?:%(letter)s|%(digit)s))*)"%re_texts
    68 IDENTIFIER_MODEL = re.compile(re_texts["identifier"])
    69 IDENTIFIER_MODEL = re.compile(re_texts["identifier"])
    69 LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]"%re_texts)
    70 LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]"%re_texts)
    70 
    71 
       
    72 def GetCursorPos(old, new):
       
    73     old_length = len(old)
       
    74     new_length = len(new)
       
    75     common_length = min(old_length, new_length)
       
    76     i = 0
       
    77     for i in xrange(common_length):
       
    78         if old[i] != new[i]:
       
    79             break
       
    80     if old_length < new_length:
       
    81         if common_length > 0 and old[i] != new[i]:
       
    82             return i + new_length - old_length
       
    83         else:
       
    84             return i + new_length - old_length + 1
       
    85     elif old_length > new_length or i < min(old_length, new_length) - 1:
       
    86         if common_length > 0 and old[i] != new[i]:
       
    87             return i
       
    88         else:
       
    89             return i + 1
       
    90     else:
       
    91         return None
       
    92 
    71 class TextViewer(wxStyledTextCtrl):
    93 class TextViewer(wxStyledTextCtrl):
    72     
    94     
    73     def __init__(self, parent, window, controler):
    95     def __init__(self, parent, window, controler):
    74         wxStyledTextCtrl.__init__(self, parent, wxID_TEXTVIEWER, style=0)
    96         wxStyledTextCtrl.__init__(self, parent, wxID_TEXTVIEWER, style=0)
    75         
    97         
   110         self.Keywords = []
   132         self.Keywords = []
   111         self.Variables = []
   133         self.Variables = []
   112         self.Functions = []
   134         self.Functions = []
   113         self.Jumps = []
   135         self.Jumps = []
   114         self.TextChanged = False
   136         self.TextChanged = False
       
   137         self.DisableEvents = True
   115         self.TextSyntax = "ST"
   138         self.TextSyntax = "ST"
   116         
   139         self.CurrentAction = None
       
   140         
       
   141         self.Parent = window
   117         self.Controler = controler
   142         self.Controler = controler
       
   143 
       
   144         self.SetModEventMask(wxSTC_MOD_BEFOREINSERT|wxSTC_MOD_BEFOREDELETE)
   118 
   145 
   119         EVT_KEY_DOWN(self, self.OnKeyDown)
   146         EVT_KEY_DOWN(self, self.OnKeyDown)
   120         EVT_STC_STYLENEEDED(self, wxID_TEXTVIEWER, self.OnStyleNeeded)
   147         EVT_STC_STYLENEEDED(self, wxID_TEXTVIEWER, self.OnStyleNeeded)
   121         EVT_STC_DO_DROP(self, wxID_TEXTVIEWER, self.OnDoDrop)
   148         EVT_STC_DO_DROP(self, wxID_TEXTVIEWER, self.OnDoDrop)
   122         EVT_KILL_FOCUS(self, self.OnKillFocus)
   149         EVT_KILL_FOCUS(self, self.OnKillFocus)
       
   150         EVT_STC_MODIFIED(self, wxID_TEXTVIEWER, self.OnModification)
       
   151     
       
   152     def OnModification(self, event):
       
   153         if not self.DisableEvents:
       
   154             mod_type = event.GetModificationType()
       
   155             if not (mod_type&wxSTC_PERFORMED_UNDO or mod_type&wxSTC_PERFORMED_REDO):
       
   156                 if mod_type&wxSTC_MOD_BEFOREINSERT:
       
   157                     if self.CurrentAction == None:
       
   158                         self.StartBuffering()
       
   159                     elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
       
   160                         self.Controler.EndBuffering()
       
   161                         self.StartBuffering()
       
   162                     self.CurrentAction = ("Add", event.GetPosition())
       
   163                 elif mod_type&wxSTC_MOD_BEFOREDELETE:
       
   164                     if self.CurrentAction == None:
       
   165                         self.StartBuffering()
       
   166                     elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
       
   167                         self.Controler.EndBuffering()
       
   168                         self.StartBuffering()
       
   169                     self.CurrentAction = ("Delete", event.GetPosition())
       
   170         event.Skip()
   123     
   171     
   124     def OnDoDrop(self, event):
   172     def OnDoDrop(self, event):
   125         try:
   173         try:
   126             values = eval(event.GetDragText())
   174             values = eval(event.GetDragText())
   127         except:
   175         except:
   154     
   202     
   155     def RefreshJumpList(self):
   203     def RefreshJumpList(self):
   156         self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
   204         self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
   157         self.Colourise(0, -1)
   205         self.Colourise(0, -1)
   158     
   206     
       
   207     # Buffer the last model state
       
   208     def RefreshBuffer(self):
       
   209         self.Controler.BufferProject()
       
   210         self.Parent.RefreshTitle()
       
   211         self.Parent.RefreshEditMenu()
       
   212     
       
   213     def StartBuffering(self):
       
   214         self.Controler.StartBuffering()
       
   215         self.Parent.RefreshTitle()
       
   216         self.Parent.RefreshEditMenu()
       
   217     
       
   218     def ResetBuffer(self):
       
   219         if self.CurrentAction != None:
       
   220             self.Controler.EndBuffering()
       
   221             self.CurrentAction = None
       
   222     
   159     def RefreshView(self):
   223     def RefreshView(self):
   160         self.SetText(self.Controler.GetCurrentElementEditingText())
   224         self.ResetBuffer()
       
   225         self.DisableEvents = True
       
   226         old_cursor_pos = self.GetCurrentPos()
       
   227         old_text = self.GetText()
       
   228         new_text = self.Controler.GetCurrentElementEditingText()
       
   229         self.SetText(new_text)
       
   230         new_cursor_pos = GetCursorPos(old_text, new_text)
       
   231         if new_cursor_pos != None:
       
   232             self.SetSelection(new_cursor_pos, new_cursor_pos)
       
   233             self.EnsureCaretVisible()
       
   234         else:
       
   235             self.SetSelection(old_cursor_pos, old_cursor_pos)
   161         self.RefreshJumpList()
   236         self.RefreshJumpList()
   162     
   237         self.EmptyUndoBuffer()
       
   238         self.DisableEvents = False
       
   239         
   163     def OnStyleNeeded(self, event):
   240     def OnStyleNeeded(self, event):
   164         self.TextChanged = True
   241         self.TextChanged = True
   165         line = self.LineFromPosition(self.GetEndStyled())
   242         line = self.LineFromPosition(self.GetEndStyled())
   166         if line == 0:
   243         if line == 0:
   167             start_pos = 0
   244             start_pos = 0
   271         else:
   348         else:
   272             self.SetStyling(i - start_pos, 31)
   349             self.SetStyling(i - start_pos, 31)
   273         event.Skip()
   350         event.Skip()
   274     
   351     
   275     def Cut(self):
   352     def Cut(self):
       
   353         self.ResetBuffer()
   276         self.CmdKeyExecute(wxSTC_CMD_CUT)
   354         self.CmdKeyExecute(wxSTC_CMD_CUT)
   277         
   355         self.RefreshBuffer()
       
   356     
   278     def Copy(self):
   357     def Copy(self):
   279         self.CmdKeyExecute(wxSTC_CMD_COPY)
   358         self.CmdKeyExecute(wxSTC_CMD_COPY)
   280     
   359     
   281     def Paste(self):
   360     def Paste(self):
       
   361         self.ResetBuffer()
   282         self.CmdKeyExecute(wxSTC_CMD_PASTE)
   362         self.CmdKeyExecute(wxSTC_CMD_PASTE)
       
   363         self.RefreshBuffer()
   283     
   364     
   284     def RefreshModel(self):
   365     def RefreshModel(self):
   285         if self.TextChanged:
   366         if self.TextChanged:
   286             self.RefreshJumpList()
   367             self.RefreshJumpList()
   287             self.Controler.SetCurrentElementEditingText(self.GetText())
   368             self.Controler.SetCurrentElementEditingText(self.GetText())