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()) |