|
1 import wx, wx.grid |
|
2 import wx.stc as stc |
|
3 import keyword |
|
4 |
|
5 if wx.Platform == '__WXMSW__': |
|
6 faces = { 'times': 'Times New Roman', |
|
7 'mono' : 'Courier New', |
|
8 'helv' : 'Arial', |
|
9 'other': 'Comic Sans MS', |
|
10 'size' : 10, |
|
11 'size2': 8, |
|
12 } |
|
13 else: |
|
14 faces = { 'times': 'Times', |
|
15 'mono' : 'Courier', |
|
16 'helv' : 'Helvetica', |
|
17 'other': 'new century schoolbook', |
|
18 'size' : 12, |
|
19 'size2': 10, |
|
20 } |
|
21 |
|
22 if wx.VERSION >= (2, 8, 0): |
|
23 import wx.aui |
|
24 |
|
25 class MDICppEditor(wx.aui.AuiMDIChildFrame): |
|
26 def __init__(self, parent, name, window, controler): |
|
27 wx.aui.AuiMDIChildFrame.__init__(self, parent, -1, title = name) |
|
28 |
|
29 sizer = wx.BoxSizer(wx.HORIZONTAL) |
|
30 |
|
31 self.Viewer = CppEditor(self, name, window, controler) |
|
32 |
|
33 sizer.AddWindow(self.Viewer, 1, border=0, flag=wx.GROW) |
|
34 |
|
35 self.SetSizer(sizer) |
|
36 |
|
37 def GetViewer(self): |
|
38 return self.Viewer |
|
39 |
|
40 class MDIVariablesEditor(wx.aui.AuiMDIChildFrame): |
|
41 def __init__(self, parent, name, window, controler): |
|
42 wx.aui.AuiMDIChildFrame.__init__(self, parent, -1, title = name) |
|
43 |
|
44 sizer = wx.BoxSizer(wx.HORIZONTAL) |
|
45 |
|
46 self.Viewer = VariablesEditor(self, window, controler) |
|
47 |
|
48 sizer.AddWindow(self.Viewer, 1, border=0, flag=wx.GROW) |
|
49 |
|
50 self.SetSizer(sizer) |
|
51 |
|
52 def GetViewer(self): |
|
53 return self.Viewer |
|
54 |
|
55 |
|
56 def AppendMenu(parent, help, id, kind, text): |
|
57 if wx.VERSION >= (2, 6, 0): |
|
58 parent.Append(help=help, id=id, kind=kind, text=text) |
|
59 else: |
|
60 parent.Append(helpString=help, id=id, kind=kind, item=text) |
|
61 |
|
62 |
|
63 [ID_CPPEDITOR, |
|
64 ] = [wx.NewId() for _init_ctrls in range(1)] |
|
65 |
|
66 CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class", |
|
67 "const", "const_cast", "continue", "default", "delete", "do", "double", |
|
68 "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", |
|
69 "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", |
|
70 "namespace", "new", "operator", "private", "protected", "public", "register", |
|
71 "reinterpret_cast", "return", "short", "signed", "sizeof", "static", |
|
72 "static_cast", "struct", "switch", "template", "this", "throw", "true", "try", |
|
73 "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", |
|
74 "void", "volatile", "wchar_t", "while"] |
|
75 |
|
76 def GetCursorPos(old, new): |
|
77 old_length = len(old) |
|
78 new_length = len(new) |
|
79 common_length = min(old_length, new_length) |
|
80 i = 0 |
|
81 for i in xrange(common_length): |
|
82 if old[i] != new[i]: |
|
83 break |
|
84 if old_length < new_length: |
|
85 if common_length > 0 and old[i] != new[i]: |
|
86 return i + new_length - old_length |
|
87 else: |
|
88 return i + new_length - old_length + 1 |
|
89 elif old_length > new_length or i < min(old_length, new_length) - 1: |
|
90 if common_length > 0 and old[i] != new[i]: |
|
91 return i |
|
92 else: |
|
93 return i + 1 |
|
94 else: |
|
95 return None |
|
96 |
|
97 class CppEditor(stc.StyledTextCtrl): |
|
98 |
|
99 fold_symbols = 3 |
|
100 |
|
101 def __init__(self, parent, name, window, controler): |
|
102 stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition, |
|
103 wx.DefaultSize, 0) |
|
104 |
|
105 self.SetMarginType(1, stc.STC_MARGIN_NUMBER) |
|
106 self.SetMarginWidth(1, 25) |
|
107 |
|
108 self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN) |
|
109 self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT) |
|
110 |
|
111 self.SetLexer(stc.STC_LEX_CPP) |
|
112 self.SetKeyWords(0, " ".join(CPP_KEYWORDS)) |
|
113 |
|
114 self.SetProperty("fold", "1") |
|
115 self.SetProperty("tab.timmy.whinge.level", "1") |
|
116 self.SetMargins(0,0) |
|
117 |
|
118 self.SetViewWhiteSpace(False) |
|
119 #self.SetBufferedDraw(False) |
|
120 #self.SetViewEOL(True) |
|
121 #self.SetEOLMode(stc.STC_EOL_CRLF) |
|
122 #self.SetUseAntiAliasing(True) |
|
123 |
|
124 self.SetEdgeMode(stc.STC_EDGE_BACKGROUND) |
|
125 self.SetEdgeColumn(78) |
|
126 |
|
127 # Setup a margin to hold fold markers |
|
128 #self.SetFoldFlags(16) ### WHAT IS THIS VALUE? WHAT ARE THE OTHER FLAGS? DOES IT MATTER? |
|
129 self.SetMarginType(2, stc.STC_MARGIN_SYMBOL) |
|
130 self.SetMarginMask(2, stc.STC_MASK_FOLDERS) |
|
131 self.SetMarginSensitive(2, True) |
|
132 self.SetMarginWidth(2, 12) |
|
133 |
|
134 if self.fold_symbols == 0: |
|
135 # Arrow pointing right for contracted folders, arrow pointing down for expanded |
|
136 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black") |
|
137 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black") |
|
138 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black") |
|
139 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black") |
|
140 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") |
|
141 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") |
|
142 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") |
|
143 |
|
144 elif self.fold_symbols == 1: |
|
145 # Plus for contracted folders, minus for expanded |
|
146 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black") |
|
147 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black") |
|
148 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black") |
|
149 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black") |
|
150 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") |
|
151 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") |
|
152 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") |
|
153 |
|
154 elif self.fold_symbols == 2: |
|
155 # Like a flattened tree control using circular headers and curved joins |
|
156 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040") |
|
157 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040") |
|
158 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040") |
|
159 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040") |
|
160 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040") |
|
161 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040") |
|
162 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040") |
|
163 |
|
164 elif self.fold_symbols == 3: |
|
165 # Like a flattened tree control using square headers |
|
166 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080") |
|
167 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080") |
|
168 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080") |
|
169 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080") |
|
170 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080") |
|
171 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080") |
|
172 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080") |
|
173 |
|
174 |
|
175 self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) |
|
176 self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick) |
|
177 self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed) |
|
178 |
|
179 # Make some styles, The lexer defines what each style is used for, we |
|
180 # just have to define what each style looks like. This set is adapted from |
|
181 # Scintilla sample property files. |
|
182 |
|
183 # Global default styles for all languages |
|
184 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces) |
|
185 self.StyleClearAll() # Reset all to be like the default |
|
186 |
|
187 # Global default styles for all languages |
|
188 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces) |
|
189 self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces) |
|
190 self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces) |
|
191 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold") |
|
192 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold") |
|
193 |
|
194 self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060') |
|
195 self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060') |
|
196 self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060') |
|
197 self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE') |
|
198 self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056') |
|
199 self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff') |
|
200 self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056') |
|
201 self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold') |
|
202 self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF') |
|
203 |
|
204 # register some images for use in the AutoComplete box. |
|
205 #self.RegisterImage(1, images.getSmilesBitmap()) |
|
206 self.RegisterImage(1, |
|
207 wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16))) |
|
208 self.RegisterImage(2, |
|
209 wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16))) |
|
210 self.RegisterImage(3, |
|
211 wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16))) |
|
212 |
|
213 # Indentation size |
|
214 self.SetTabWidth(2) |
|
215 self.SetUseTabs(0) |
|
216 |
|
217 self.Controler = controler |
|
218 self.ParentWindow = window |
|
219 |
|
220 self.DisableEvents = True |
|
221 self.Name = name |
|
222 self.CurrentAction = None |
|
223 |
|
224 self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE) |
|
225 |
|
226 self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR) |
|
227 self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) |
|
228 self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR) |
|
229 |
|
230 def OnModification(self, event): |
|
231 if not self.DisableEvents: |
|
232 mod_type = event.GetModificationType() |
|
233 if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO): |
|
234 if mod_type&wx.stc.STC_MOD_BEFOREINSERT: |
|
235 if self.CurrentAction == None: |
|
236 self.StartBuffering() |
|
237 elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1: |
|
238 self.Controler.EndBuffering() |
|
239 self.StartBuffering() |
|
240 self.CurrentAction = ("Add", event.GetPosition()) |
|
241 elif mod_type&wx.stc.STC_MOD_BEFOREDELETE: |
|
242 if self.CurrentAction == None: |
|
243 self.StartBuffering() |
|
244 elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1: |
|
245 self.Controler.EndBuffering() |
|
246 self.StartBuffering() |
|
247 self.CurrentAction = ("Delete", event.GetPosition()) |
|
248 event.Skip() |
|
249 |
|
250 def OnDoDrop(self, event): |
|
251 self.ResetBuffer() |
|
252 wx.CallAfter(self.RefreshModel) |
|
253 event.Skip() |
|
254 |
|
255 def IsViewing(self, name): |
|
256 return self.Name == name |
|
257 |
|
258 # Buffer the last model state |
|
259 def RefreshBuffer(self): |
|
260 self.Controler.BufferCFile() |
|
261 if self.ParentWindow: |
|
262 self.ParentWindow.RefreshTitle() |
|
263 self.ParentWindow.RefreshEditMenu() |
|
264 |
|
265 def StartBuffering(self): |
|
266 self.Controler.StartBuffering() |
|
267 if self.ParentWindow: |
|
268 self.ParentWindow.RefreshTitle() |
|
269 self.ParentWindow.RefreshEditMenu() |
|
270 |
|
271 def ResetBuffer(self): |
|
272 if self.CurrentAction != None: |
|
273 self.Controler.EndBuffering() |
|
274 self.CurrentAction = None |
|
275 |
|
276 def RefreshView(self): |
|
277 self.ResetBuffer() |
|
278 self.DisableEvents = True |
|
279 old_cursor_pos = self.GetCurrentPos() |
|
280 old_text = self.GetText() |
|
281 new_text = self.Controler.GetPartText(self.Name) |
|
282 self.SetText(new_text) |
|
283 new_cursor_pos = GetCursorPos(old_text, new_text) |
|
284 if new_cursor_pos != None: |
|
285 self.GotoPos(new_cursor_pos) |
|
286 else: |
|
287 self.GotoPos(old_cursor_pos) |
|
288 self.ScrollToColumn(0) |
|
289 self.EmptyUndoBuffer() |
|
290 self.DisableEvents = False |
|
291 |
|
292 self.Colourise(0, -1) |
|
293 |
|
294 def RefreshModel(self): |
|
295 self.Controler.SetPartText(self.Name, self.GetText()) |
|
296 |
|
297 def OnKeyPressed(self, event): |
|
298 if self.CallTipActive(): |
|
299 self.CallTipCancel() |
|
300 key = event.GetKeyCode() |
|
301 |
|
302 if key == 32 and event.ControlDown(): |
|
303 pos = self.GetCurrentPos() |
|
304 |
|
305 # Tips |
|
306 if event.ShiftDown(): |
|
307 pass |
|
308 ## self.CallTipSetBackground("yellow") |
|
309 ## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n' |
|
310 ## 'show some suff, maybe parameters..\n\n' |
|
311 ## 'fubar(param1, param2)') |
|
312 # Code completion |
|
313 else: |
|
314 self.AutoCompSetIgnoreCase(False) # so this needs to match |
|
315 |
|
316 # Images are specified with a appended "?type" |
|
317 self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS])) |
|
318 else: |
|
319 wx.CallAfter(self.RefreshModel) |
|
320 event.Skip() |
|
321 |
|
322 def OnKillFocus(self, event): |
|
323 self.AutoCompCancel() |
|
324 event.Skip() |
|
325 |
|
326 def OnUpdateUI(self, evt): |
|
327 # check for matching braces |
|
328 braceAtCaret = -1 |
|
329 braceOpposite = -1 |
|
330 charBefore = None |
|
331 caretPos = self.GetCurrentPos() |
|
332 |
|
333 if caretPos > 0: |
|
334 charBefore = self.GetCharAt(caretPos - 1) |
|
335 styleBefore = self.GetStyleAt(caretPos - 1) |
|
336 |
|
337 # check before |
|
338 if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR: |
|
339 braceAtCaret = caretPos - 1 |
|
340 |
|
341 # check after |
|
342 if braceAtCaret < 0: |
|
343 charAfter = self.GetCharAt(caretPos) |
|
344 styleAfter = self.GetStyleAt(caretPos) |
|
345 |
|
346 if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR: |
|
347 braceAtCaret = caretPos |
|
348 |
|
349 if braceAtCaret >= 0: |
|
350 braceOpposite = self.BraceMatch(braceAtCaret) |
|
351 |
|
352 if braceAtCaret != -1 and braceOpposite == -1: |
|
353 self.BraceBadLight(braceAtCaret) |
|
354 else: |
|
355 self.BraceHighlight(braceAtCaret, braceOpposite) |
|
356 #pt = self.PointFromPosition(braceOpposite) |
|
357 #self.Refresh(True, wxRect(pt.x, pt.y, 5,5)) |
|
358 #print pt |
|
359 #self.Refresh(False) |
|
360 |
|
361 |
|
362 def OnMarginClick(self, evt): |
|
363 # fold and unfold as needed |
|
364 if evt.GetMargin() == 2: |
|
365 if evt.GetShift() and evt.GetControl(): |
|
366 self.FoldAll() |
|
367 else: |
|
368 lineClicked = self.LineFromPosition(evt.GetPosition()) |
|
369 |
|
370 if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG: |
|
371 if evt.GetShift(): |
|
372 self.SetFoldExpanded(lineClicked, True) |
|
373 self.Expand(lineClicked, True, True, 1) |
|
374 elif evt.GetControl(): |
|
375 if self.GetFoldExpanded(lineClicked): |
|
376 self.SetFoldExpanded(lineClicked, False) |
|
377 self.Expand(lineClicked, False, True, 0) |
|
378 else: |
|
379 self.SetFoldExpanded(lineClicked, True) |
|
380 self.Expand(lineClicked, True, True, 100) |
|
381 else: |
|
382 self.ToggleFold(lineClicked) |
|
383 |
|
384 |
|
385 def FoldAll(self): |
|
386 lineCount = self.GetLineCount() |
|
387 expanding = True |
|
388 |
|
389 # find out if we are folding or unfolding |
|
390 for lineNum in range(lineCount): |
|
391 if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG: |
|
392 expanding = not self.GetFoldExpanded(lineNum) |
|
393 break |
|
394 |
|
395 lineNum = 0 |
|
396 |
|
397 while lineNum < lineCount: |
|
398 level = self.GetFoldLevel(lineNum) |
|
399 if level & stc.STC_FOLDLEVELHEADERFLAG and \ |
|
400 (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: |
|
401 |
|
402 if expanding: |
|
403 self.SetFoldExpanded(lineNum, True) |
|
404 lineNum = self.Expand(lineNum, True) |
|
405 lineNum = lineNum - 1 |
|
406 else: |
|
407 lastChild = self.GetLastChild(lineNum, -1) |
|
408 self.SetFoldExpanded(lineNum, False) |
|
409 |
|
410 if lastChild > lineNum: |
|
411 self.HideLines(lineNum+1, lastChild) |
|
412 |
|
413 lineNum = lineNum + 1 |
|
414 |
|
415 |
|
416 |
|
417 def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): |
|
418 lastChild = self.GetLastChild(line, level) |
|
419 line = line + 1 |
|
420 |
|
421 while line <= lastChild: |
|
422 if force: |
|
423 if visLevels > 0: |
|
424 self.ShowLines(line, line) |
|
425 else: |
|
426 self.HideLines(line, line) |
|
427 else: |
|
428 if doExpand: |
|
429 self.ShowLines(line, line) |
|
430 |
|
431 if level == -1: |
|
432 level = self.GetFoldLevel(line) |
|
433 |
|
434 if level & stc.STC_FOLDLEVELHEADERFLAG: |
|
435 if force: |
|
436 if visLevels > 1: |
|
437 self.SetFoldExpanded(line, True) |
|
438 else: |
|
439 self.SetFoldExpanded(line, False) |
|
440 |
|
441 line = self.Expand(line, doExpand, force, visLevels-1) |
|
442 |
|
443 else: |
|
444 if doExpand and self.GetFoldExpanded(line): |
|
445 line = self.Expand(line, True, force, visLevels-1) |
|
446 else: |
|
447 line = self.Expand(line, False, force, visLevels-1) |
|
448 else: |
|
449 line = line + 1 |
|
450 |
|
451 return line |
|
452 |
|
453 |
|
454 #------------------------------------------------------------------------------- |
|
455 # Helper for VariablesGrid values |
|
456 #------------------------------------------------------------------------------- |
|
457 |
|
458 class VariablesTable(wx.grid.PyGridTableBase): |
|
459 |
|
460 """ |
|
461 A custom wxGrid Table using user supplied data |
|
462 """ |
|
463 def __init__(self, parent, data, colnames): |
|
464 # The base class must be initialized *first* |
|
465 wx.grid.PyGridTableBase.__init__(self) |
|
466 self.data = data |
|
467 self.colnames = colnames |
|
468 self.Parent = parent |
|
469 # XXX |
|
470 # we need to store the row length and collength to |
|
471 # see if the table has changed size |
|
472 self._rows = self.GetNumberRows() |
|
473 self._cols = self.GetNumberCols() |
|
474 |
|
475 def GetNumberCols(self): |
|
476 return len(self.colnames) |
|
477 |
|
478 def GetNumberRows(self): |
|
479 return len(self.data) |
|
480 |
|
481 def GetColLabelValue(self, col): |
|
482 if col < len(self.colnames): |
|
483 return self.colnames[col] |
|
484 |
|
485 def GetRowLabelValues(self, row): |
|
486 return row |
|
487 |
|
488 def GetValue(self, row, col): |
|
489 if row < self.GetNumberRows(): |
|
490 if col == 0: |
|
491 return row + 1 |
|
492 else: |
|
493 return str(self.data[row].get(self.GetColLabelValue(col), "")) |
|
494 |
|
495 def GetValueByName(self, row, colname): |
|
496 if row < self.GetNumberRows(): |
|
497 return self.data[row].get(colname, None) |
|
498 return None |
|
499 |
|
500 def SetValue(self, row, col, value): |
|
501 if col < len(self.colnames): |
|
502 self.data[row][self.GetColLabelValue(col)] = value |
|
503 |
|
504 def SetValueByName(self, row, colname, value): |
|
505 if row < self.GetNumberRows(): |
|
506 self.data[row][colname] = value |
|
507 |
|
508 def ResetView(self, grid): |
|
509 """ |
|
510 (wxGrid) -> Reset the grid view. Call this to |
|
511 update the grid if rows and columns have been added or deleted |
|
512 """ |
|
513 grid.BeginBatch() |
|
514 for current, new, delmsg, addmsg in [ |
|
515 (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED), |
|
516 (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED), |
|
517 ]: |
|
518 if new < current: |
|
519 msg = wx.grid.GridTableMessage(self,delmsg,new,current-new) |
|
520 grid.ProcessTableMessage(msg) |
|
521 elif new > current: |
|
522 msg = wx.grid.GridTableMessage(self,addmsg,new-current) |
|
523 grid.ProcessTableMessage(msg) |
|
524 self.UpdateValues(grid) |
|
525 grid.EndBatch() |
|
526 |
|
527 self._rows = self.GetNumberRows() |
|
528 self._cols = self.GetNumberCols() |
|
529 # update the column rendering scheme |
|
530 self._updateColAttrs(grid) |
|
531 |
|
532 # update the scrollbars and the displayed part of the grid |
|
533 grid.AdjustScrollbars() |
|
534 grid.ForceRefresh() |
|
535 |
|
536 def UpdateValues(self, grid): |
|
537 """Update all displayed values""" |
|
538 # This sends an event to the grid table to update all of the values |
|
539 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES) |
|
540 grid.ProcessTableMessage(msg) |
|
541 |
|
542 def _updateColAttrs(self, grid): |
|
543 """ |
|
544 wxGrid -> update the column attributes to add the |
|
545 appropriate renderer given the column name. |
|
546 |
|
547 Otherwise default to the default renderer. |
|
548 """ |
|
549 |
|
550 typelist = None |
|
551 accesslist = None |
|
552 for row in range(self.GetNumberRows()): |
|
553 for col in range(self.GetNumberCols()): |
|
554 editor = None |
|
555 renderer = None |
|
556 colname = self.GetColLabelValue(col) |
|
557 grid.SetReadOnly(row, col, False) |
|
558 |
|
559 if colname == "Name": |
|
560 editor = wx.grid.GridCellTextEditor() |
|
561 elif colname == "Class": |
|
562 editor = wx.grid.GridCellChoiceEditor() |
|
563 editor.SetParameters("input,output") |
|
564 elif colname == "Type": |
|
565 pass |
|
566 else: |
|
567 grid.SetReadOnly(row, col, True) |
|
568 |
|
569 grid.SetCellEditor(row, col, editor) |
|
570 grid.SetCellRenderer(row, col, renderer) |
|
571 |
|
572 grid.SetCellBackgroundColour(row, col, wx.WHITE) |
|
573 |
|
574 def SetData(self, data): |
|
575 self.data = data |
|
576 |
|
577 def GetData(self): |
|
578 return self.data |
|
579 |
|
580 def GetCurrentIndex(self): |
|
581 return self.CurrentIndex |
|
582 |
|
583 def SetCurrentIndex(self, index): |
|
584 self.CurrentIndex = index |
|
585 |
|
586 def AppendRow(self, row_content): |
|
587 self.data.append(row_content) |
|
588 |
|
589 def RemoveRow(self, row_index): |
|
590 self.data.pop(row_index) |
|
591 |
|
592 def MoveRow(self, row_index, move, grid): |
|
593 new_index = max(0, min(row_index + move, len(self.data) - 1)) |
|
594 if new_index != row_index: |
|
595 self.data.insert(new_index, self.data.pop(row_index)) |
|
596 grid.SetGridCursor(new_index, grid.GetGridCursorCol()) |
|
597 |
|
598 def GetRow(self, row_index): |
|
599 return self.data[row_index] |
|
600 |
|
601 def Empty(self): |
|
602 self.data = [] |
|
603 self.editors = [] |
|
604 |
|
605 |
|
606 [ID_VARIABLESEDITOR, ID_VARIABLESEDITORVARIABLESGRID, |
|
607 ID_VARIABLESEDITORADDVARIABLEBUTTON, ID_VARIABLESEDITORDELETEVARIABLEBUTTON, |
|
608 ID_VARIABLESEDITORUPVARIABLEBUTTON, ID_VARIABLESEDITORDOWNVARIABLEBUTTON |
|
609 ] = [wx.NewId() for _init_ctrls in range(6)] |
|
610 |
|
611 class VariablesEditor(wx.Panel): |
|
612 |
|
613 if wx.VERSION < (2, 6, 0): |
|
614 def Bind(self, event, function, id = None): |
|
615 if id is not None: |
|
616 event(self, id, function) |
|
617 else: |
|
618 event(self, function) |
|
619 |
|
620 def _init_coll_MainSizer_Growables(self, parent): |
|
621 parent.AddGrowableCol(0) |
|
622 parent.AddGrowableRow(0) |
|
623 |
|
624 def _init_coll_MainSizer_Items(self, parent): |
|
625 parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW) |
|
626 parent.AddSizer(self.ButtonsSizer, 0, border=0, flag=wx.GROW) |
|
627 |
|
628 def _init_coll_ButtonsSizer_Growables(self, parent): |
|
629 parent.AddGrowableCol(0) |
|
630 parent.AddGrowableRow(0) |
|
631 |
|
632 def _init_coll_ButtonsSizer_Items(self, parent): |
|
633 parent.AddWindow(self.AddVariableButton, 0, border=0, flag=wx.ALIGN_RIGHT) |
|
634 parent.AddWindow(self.DeleteVariableButton, 0, border=0, flag=0) |
|
635 parent.AddWindow(self.UpVariableButton, 0, border=0, flag=0) |
|
636 parent.AddWindow(self.DownVariableButton, 0, border=0, flag=0) |
|
637 |
|
638 def _init_sizers(self): |
|
639 self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4) |
|
640 self.ButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0) |
|
641 |
|
642 self._init_coll_MainSizer_Growables(self.MainSizer) |
|
643 self._init_coll_MainSizer_Items(self.MainSizer) |
|
644 self._init_coll_ButtonsSizer_Growables(self.ButtonsSizer) |
|
645 self._init_coll_ButtonsSizer_Items(self.ButtonsSizer) |
|
646 |
|
647 self.SetSizer(self.MainSizer) |
|
648 |
|
649 def _init_ctrls(self, prnt): |
|
650 wx.Panel.__init__(self, id=ID_VARIABLESEDITOR, name='', parent=prnt, |
|
651 size=wx.Size(0, 0), style=wx.SUNKEN_BORDER) |
|
652 |
|
653 self.VariablesGrid = wx.grid.Grid(id=ID_VARIABLESEDITORVARIABLESGRID, |
|
654 name='VariablesGrid', parent=self, pos=wx.Point(0, 0), |
|
655 size=wx.Size(-1, -1), style=wx.VSCROLL) |
|
656 self.VariablesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, |
|
657 'Sans')) |
|
658 self.VariablesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, |
|
659 False, 'Sans')) |
|
660 if wx.VERSION >= (2, 5, 0): |
|
661 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange) |
|
662 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick) |
|
663 self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown) |
|
664 else: |
|
665 wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange) |
|
666 wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick) |
|
667 wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown) |
|
668 |
|
669 self.AddVariableButton = wx.Button(id=ID_VARIABLESEDITORADDVARIABLEBUTTON, label='Add Variable', |
|
670 name='AddVariableButton', parent=self, pos=wx.Point(0, 0), |
|
671 size=wx.Size(122, 32), style=0) |
|
672 self.Bind(wx.EVT_BUTTON, self.OnAddVariableButton, id=ID_VARIABLESEDITORADDVARIABLEBUTTON) |
|
673 |
|
674 self.DeleteVariableButton = wx.Button(id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON, label='Delete Variable', |
|
675 name='DeleteVariableButton', parent=self, pos=wx.Point(0, 0), |
|
676 size=wx.Size(122, 32), style=0) |
|
677 self.Bind(wx.EVT_BUTTON, self.OnDeleteVariableButton, id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON) |
|
678 |
|
679 self.UpVariableButton = wx.Button(id=ID_VARIABLESEDITORUPVARIABLEBUTTON, label='^', |
|
680 name='UpVariableButton', parent=self, pos=wx.Point(0, 0), |
|
681 size=wx.Size(32, 32), style=0) |
|
682 self.Bind(wx.EVT_BUTTON, self.OnUpVariableButton, id=ID_VARIABLESEDITORUPVARIABLEBUTTON) |
|
683 |
|
684 self.DownVariableButton = wx.Button(id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON, label='v', |
|
685 name='DownVariableButton', parent=self, pos=wx.Point(0, 0), |
|
686 size=wx.Size(32, 32), style=0) |
|
687 self.Bind(wx.EVT_BUTTON, self.OnDownVariableButton, id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON) |
|
688 |
|
689 self._init_sizers() |
|
690 |
|
691 def __init__(self, parent, window, controler): |
|
692 self._init_ctrls(parent) |
|
693 |
|
694 self.ParentWindow = window |
|
695 self.Controler = controler |
|
696 |
|
697 self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""} |
|
698 self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"]) |
|
699 self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT] |
|
700 self.ColSizes = [40, 200, 150, 150] |
|
701 self.VariablesGrid.SetTable(self.Table) |
|
702 self.VariablesGrid.SetRowLabelSize(0) |
|
703 for col in range(self.Table.GetNumberCols()): |
|
704 attr = wx.grid.GridCellAttr() |
|
705 attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE) |
|
706 self.VariablesGrid.SetColAttr(col, attr) |
|
707 self.VariablesGrid.SetColSize(col, self.ColSizes[col]) |
|
708 self.Table.ResetView(self.VariablesGrid) |
|
709 |
|
710 def IsViewing(self, name): |
|
711 return name == "Variables" |
|
712 |
|
713 def RefreshModel(self): |
|
714 self.Controler.SetVariables(self.Table.GetData()) |
|
715 self.RefreshBuffer() |
|
716 |
|
717 def ResetBuffer(self): |
|
718 pass |
|
719 |
|
720 # Buffer the last model state |
|
721 def RefreshBuffer(self): |
|
722 self.Controler.BufferCFile() |
|
723 self.ParentWindow.RefreshTitle() |
|
724 self.ParentWindow.RefreshEditMenu() |
|
725 |
|
726 def RefreshView(self): |
|
727 self.Table.SetData(self.Controler.GetVariables()) |
|
728 self.Table.ResetView(self.VariablesGrid) |
|
729 |
|
730 def OnAddVariableButton(self, event): |
|
731 self.Table.AppendRow(self.VariablesDefaultValue.copy()) |
|
732 self.RefreshModel() |
|
733 self.RefreshView() |
|
734 event.Skip() |
|
735 |
|
736 def OnDeleteVariableButton(self, event): |
|
737 row = self.VariablesGrid.GetGridCursorRow() |
|
738 self.Table.RemoveRow(row) |
|
739 self.RefreshModel() |
|
740 self.RefreshView() |
|
741 event.Skip() |
|
742 |
|
743 def OnUpVariableButton(self, event): |
|
744 row = self.VariablesGrid.GetGridCursorRow() |
|
745 self.Table.MoveRow(row, -1, self.VariablesGrid) |
|
746 self.RefreshModel() |
|
747 self.RefreshView() |
|
748 event.Skip() |
|
749 |
|
750 def OnDownVariableButton(self, event): |
|
751 row = self.VariablesGrid.GetGridCursorRow() |
|
752 self.Table.MoveRow(row, 1, self.VariablesGrid) |
|
753 self.RefreshModel() |
|
754 self.RefreshView() |
|
755 event.Skip() |
|
756 |
|
757 def OnVariablesGridCellChange(self, event): |
|
758 self.RefreshModel() |
|
759 self.RefreshView() |
|
760 event.Skip() |
|
761 |
|
762 def OnVariablesGridEditorShown(self, event): |
|
763 row, col = event.GetRow(), event.GetCol() |
|
764 if self.Table.GetColLabelValue(col) == "Type": |
|
765 type_menu = wx.Menu(title='') |
|
766 base_menu = wx.Menu(title='') |
|
767 for base_type in self.Controler.GetBaseTypes(): |
|
768 new_id = wx.NewId() |
|
769 AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type) |
|
770 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id) |
|
771 type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu) |
|
772 datatype_menu = wx.Menu(title='') |
|
773 for datatype in self.Controler.GetDataTypes(basetypes = False): |
|
774 new_id = wx.NewId() |
|
775 AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype) |
|
776 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id) |
|
777 type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu) |
|
778 rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col)) |
|
779 self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize()) |
|
780 event.Veto() |
|
781 else: |
|
782 event.Skip() |
|
783 |
|
784 def GetVariableTypeFunction(self, base_type): |
|
785 def VariableTypeFunction(event): |
|
786 row = self.VariablesGrid.GetGridCursorRow() |
|
787 self.Table.SetValueByName(row, "Type", base_type) |
|
788 self.Table.ResetView(self.VariablesGrid) |
|
789 self.RefreshModel() |
|
790 self.RefreshView() |
|
791 event.Skip() |
|
792 return VariableTypeFunction |
|
793 |
|
794 def OnVariablesGridCellLeftClick(self, event): |
|
795 if event.GetCol() == 0: |
|
796 row = event.GetRow() |
|
797 num = 0 |
|
798 if self.Table.GetValueByName(row, "Class") == "input": |
|
799 dir = "%I" |
|
800 for i in xrange(row): |
|
801 if self.Table.GetValueByName(i, "Class") == "input": |
|
802 num += 1 |
|
803 else: |
|
804 dir = "%Q" |
|
805 for i in xrange(row): |
|
806 if self.Table.GetValueByName(i, "Class") == "input": |
|
807 num += 1 |
|
808 data_type = self.Table.GetValueByName(row, "Type") |
|
809 base_location = ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation())) |
|
810 location = "%s%s%s.%d"%(dir, self.Controler.GetSizeOfType(data_type), base_location, num) |
|
811 data = wx.TextDataObject(str((location, "location", data_type))) |
|
812 dragSource = wx.DropSource(self.VariablesGrid) |
|
813 dragSource.SetData(data) |
|
814 dragSource.DoDragDrop() |
|
815 event.Skip() |
|
816 |
|
817 |
|
818 #------------------------------------------------------------------------------- |
|
819 # SVGUIEditor Main Frame Class |
|
820 #------------------------------------------------------------------------------- |
|
821 |
|
822 if wx.VERSION >= (2, 8, 0): |
|
823 base_class = wx.aui.AuiMDIParentFrame |
|
824 else: |
|
825 base_class = wx.Frame |
|
826 |
|
827 CFILE_PARTS = ["Includes", "Variables", "Globals", "Init", "CleanUp", "Retrieve", |
|
828 "Publish"] |
|
829 |
|
830 [ID_CFILEEDITOR, ID_CFILEEDITORMAINSPLITTER, |
|
831 ID_CFILEEDITORCFILETREE, CFILEEDITORPARTSOPENED, |
|
832 ] = [wx.NewId() for _init_ctrls in range(4)] |
|
833 |
|
834 class CFileEditor(base_class): |
|
835 |
|
836 if wx.VERSION < (2, 6, 0): |
|
837 def Bind(self, event, function, id = None): |
|
838 if id is not None: |
|
839 event(self, id, function) |
|
840 else: |
|
841 event(self, function) |
|
842 |
|
843 def _init_coll_EditMenu_Items(self, parent): |
|
844 AppendMenu(parent, help='', id=wx.ID_REFRESH, |
|
845 kind=wx.ITEM_NORMAL, text=u'Refresh\tCTRL+R') |
|
846 AppendMenu(parent, help='', id=wx.ID_UNDO, |
|
847 kind=wx.ITEM_NORMAL, text=u'Undo\tCTRL+Z') |
|
848 AppendMenu(parent, help='', id=wx.ID_REDO, |
|
849 kind=wx.ITEM_NORMAL, text=u'Redo\tCTRL+Y') |
|
850 self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH) |
|
851 self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO) |
|
852 self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO) |
|
853 |
|
854 def _init_coll_MenuBar_Menus(self, parent): |
|
855 parent.Append(menu=self.EditMenu, title=u'&Edit') |
|
856 |
|
857 def _init_utils(self): |
|
858 self.MenuBar = wx.MenuBar() |
|
859 |
|
860 self.EditMenu = wx.Menu(title='') |
|
861 |
|
862 self._init_coll_MenuBar_Menus(self.MenuBar) |
|
863 self._init_coll_EditMenu_Items(self.EditMenu) |
|
864 |
|
865 def _init_ctrls(self, prnt): |
|
866 if wx.VERSION >= (2, 8, 0): |
|
867 wx.aui.AuiMDIParentFrame.__init__(self, winid=ID_CFILEEDITOR, name=u'CFileEditor', |
|
868 parent=prnt, pos=wx.DefaultPosition, size=wx.Size(800, 650), |
|
869 style=wx.DEFAULT_FRAME_STYLE|wx.SUNKEN_BORDER|wx.CLIP_CHILDREN, title=u'CFileEditor') |
|
870 else: |
|
871 wx.Frame.__init__(self, id=ID_CFILEEDITOR, name=u'CFileEditor', |
|
872 parent=prnt, pos=wx.DefaultPosition, size=wx.Size(800, 650), |
|
873 style=wx.DEFAULT_FRAME_STYLE, title=u'CFileEditor') |
|
874 self._init_utils() |
|
875 self.SetClientSize(wx.Size(1000, 600)) |
|
876 self.SetMenuBar(self.MenuBar) |
|
877 self.Bind(wx.EVT_CLOSE, self.OnCloseFrame) |
|
878 |
|
879 self.Bind(wx.EVT_MENU, self.OnSaveMenu, id=wx.ID_SAVE) |
|
880 accel = wx.AcceleratorTable([wx.AcceleratorEntry(wx.ACCEL_CTRL, 83, wx.ID_SAVE)]) |
|
881 self.SetAcceleratorTable(accel) |
|
882 |
|
883 if wx.VERSION >= (2, 8, 0): |
|
884 self.AUIManager = wx.aui.AuiManager(self) |
|
885 self.AUIManager.SetDockSizeConstraint(0.5, 0.5) |
|
886 |
|
887 if wx.VERSION < (2, 8, 0): |
|
888 self.MainSplitter = wx.SplitterWindow(id=ID_CFILEEDITORMAINSPLITTER, |
|
889 name='MainSplitter', parent=self, point=wx.Point(0, 0), |
|
890 size=wx.Size(-1, -1), style=wx.SP_3D) |
|
891 self.MainSplitter.SetNeedUpdating(True) |
|
892 self.MainSplitter.SetMinimumPaneSize(1) |
|
893 |
|
894 self.CFileTree = wx.TreeCtrl(id=ID_CFILEEDITORCFILETREE, |
|
895 name='CFileTree', parent=self.MainSplitter, pos=wx.Point(0, 0), |
|
896 size=wx.Size(-1, -1), style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER) |
|
897 else: |
|
898 self.CFileTree = wx.TreeCtrl(id=ID_CFILEEDITORCFILETREE, |
|
899 name='CFileTree', parent=self, pos=wx.Point(0, 0), |
|
900 size=wx.Size(-1, -1), style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER) |
|
901 self.AUIManager.AddPane(self.CFileTree, wx.aui.AuiPaneInfo().Caption("CFile Tree").Left().Layer(1).BestSize(wx.Size(200, 500)).CloseButton(False)) |
|
902 self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnCFileTreeItemSelected, |
|
903 id=ID_CFILEEDITORCFILETREE) |
|
904 self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnCFileTreeItemActivated, |
|
905 id=ID_CFILEEDITORCFILETREE) |
|
906 |
|
907 if wx.VERSION < (2, 8, 0): |
|
908 self.PartsOpened = wx.Notebook(id=ID_CFILEEDITORPARTSOPENED, |
|
909 name='PartsOpened', parent=self.MainSplitter, pos=wx.Point(0, |
|
910 0), size=wx.Size(0, 0), style=0) |
|
911 if wx.VERSION >= (2, 6, 0): |
|
912 self.PartsOpened.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, |
|
913 self.OnPartSelectedChanged, id=CFILEEDITORPARTSOPENED) |
|
914 else: |
|
915 wx.EVT_NOTEBOOK_PAGE_CHANGED(self.PartsOpened, CFILEEDITORPARTSOPENED, |
|
916 self.OnPartSelectedChanged) |
|
917 |
|
918 self.MainSplitter.SplitVertically(self.ProjectTree, self.PartsOpened, 200) |
|
919 |
|
920 self.StatusBar = wx.StatusBar( name='HelpBar', |
|
921 parent=self, style=wx.ST_SIZEGRIP) |
|
922 self.SetStatusBar(self.StatusBar) |
|
923 |
|
924 if wx.VERSION >= (2, 8, 0): |
|
925 self.AUIManager.Update() |
|
926 |
|
927 def __init__(self, parent, controler): |
|
928 self._init_ctrls(parent) |
|
929 |
|
930 self.Controler = controler |
|
931 |
|
932 self.InitCFileTree() |
|
933 self.RefreshTitle() |
|
934 self.RefreshEditMenu() |
|
935 |
|
936 def OnCloseFrame(self, event): |
|
937 if wx.VERSION >= (2, 8, 0): |
|
938 self.AUIManager.UnInit() |
|
939 if getattr(self, "_onclose", None) is not None: |
|
940 self._onclose() |
|
941 event.Skip() |
|
942 |
|
943 def OnCloseTabMenu(self, event): |
|
944 selected = self.GetPageSelection() |
|
945 if selected >= 0: |
|
946 self.DeletePage(selected) |
|
947 event.Skip() |
|
948 |
|
949 def OnSaveMenu(self, event): |
|
950 if getattr(self, "_onsave", None) != None: |
|
951 self._onsave() |
|
952 self.RefreshTitle() |
|
953 self.RefreshEditMenu() |
|
954 event.Skip() |
|
955 |
|
956 #------------------------------------------------------------------------------- |
|
957 # Notebook Unified Functions |
|
958 #------------------------------------------------------------------------------- |
|
959 |
|
960 def GetPageCount(self): |
|
961 if wx.VERSION >= (2, 8, 0): |
|
962 notebook = self.GetNotebook() |
|
963 if notebook is not None: |
|
964 return notebook.GetPageCount() |
|
965 else: |
|
966 return 0 |
|
967 else: |
|
968 return self.PartsOpened.GetPageCount() |
|
969 |
|
970 def GetPage(self, idx): |
|
971 if wx.VERSION >= (2, 8, 0): |
|
972 notebook = self.GetNotebook() |
|
973 if notebook is not None: |
|
974 return notebook.GetPage(idx).GetViewer() |
|
975 else: |
|
976 return None |
|
977 else: |
|
978 return self.PartsOpened.GetPage(idx) |
|
979 |
|
980 def GetPageSelection(self): |
|
981 if wx.VERSION >= (2, 8, 0): |
|
982 notebook = self.GetNotebook() |
|
983 if notebook is not None: |
|
984 return notebook.GetSelection() |
|
985 else: |
|
986 return -1 |
|
987 else: |
|
988 return self.PartsOpened.GetSelection() |
|
989 |
|
990 def SetPageSelection(self, idx): |
|
991 if wx.VERSION >= (2, 8, 0): |
|
992 notebook = self.GetNotebook() |
|
993 if notebook is not None: |
|
994 notebook.SetSelection(idx) |
|
995 else: |
|
996 self.PartsOpened.SetSelection(idx) |
|
997 |
|
998 def DeletePage(self, idx): |
|
999 if wx.VERSION >= (2, 8, 0): |
|
1000 notebook = self.GetNotebook() |
|
1001 if notebook is not None: |
|
1002 notebook.DeletePage(idx) |
|
1003 else: |
|
1004 self.PartsOpened.DeletePage(idx) |
|
1005 |
|
1006 def DeleteAllPages(self): |
|
1007 if wx.VERSION >= (2, 8, 0): |
|
1008 notebook = self.GetNotebook() |
|
1009 if notebook is not None: |
|
1010 for idx in xrange(notebook.GetPageCount()): |
|
1011 notebook.DeletePage(0) |
|
1012 else: |
|
1013 self.PartsOpened.DeleteAllPages() |
|
1014 |
|
1015 def SetPageText(self, idx, text): |
|
1016 if wx.VERSION >= (2, 8, 0): |
|
1017 notebook = self.GetNotebook() |
|
1018 if notebook is not None: |
|
1019 return notebook.SetPageText(idx, text) |
|
1020 else: |
|
1021 return self.PartsOpened.SetPageText(idx, text) |
|
1022 |
|
1023 def SetPageBitmap(self, idx, bitmap): |
|
1024 if wx.VERSION >= (2, 8, 0): |
|
1025 notebook = self.GetNotebook() |
|
1026 if notebook is not None: |
|
1027 return notebook.SetPageBitmap(idx, bitmap) |
|
1028 else: |
|
1029 return self.PartsOpened.SetPageImage(idx, bitmap) |
|
1030 |
|
1031 def GetPageText(self, idx): |
|
1032 if wx.VERSION >= (2, 8, 0): |
|
1033 notebook = self.GetNotebook() |
|
1034 if notebook is not None: |
|
1035 return notebook.GetPageText(idx) |
|
1036 else: |
|
1037 return "" |
|
1038 else: |
|
1039 return self.PartsOpened.GetPageText(idx) |
|
1040 |
|
1041 def IsOpened(self, name): |
|
1042 for idx in xrange(self.GetPageCount()): |
|
1043 if self.GetPage(idx).IsViewing(name): |
|
1044 return idx |
|
1045 return None |
|
1046 |
|
1047 def RefreshTitle(self): |
|
1048 self.SetTitle("CFileEditor - %s"%self.Controler.GetFilename()) |
|
1049 |
|
1050 #------------------------------------------------------------------------------- |
|
1051 # Edit Project Menu Functions |
|
1052 #------------------------------------------------------------------------------- |
|
1053 |
|
1054 def RefreshEditMenu(self): |
|
1055 if self.EditMenu: |
|
1056 undo, redo = self.Controler.GetBufferState() |
|
1057 self.EditMenu.Enable(wx.ID_UNDO, undo) |
|
1058 self.EditMenu.Enable(wx.ID_REDO, redo) |
|
1059 |
|
1060 def OnRefreshMenu(self, event): |
|
1061 selected = self.GetPageSelection() |
|
1062 if selected != -1: |
|
1063 window = self.GetPage(selected) |
|
1064 window.RefreshView() |
|
1065 event.Skip() |
|
1066 |
|
1067 def OnUndoMenu(self, event): |
|
1068 self.Controler.LoadPrevious() |
|
1069 selected = self.GetPageSelection() |
|
1070 if selected != -1: |
|
1071 window = self.GetPage(selected) |
|
1072 window.RefreshView() |
|
1073 self.RefreshTitle() |
|
1074 self.RefreshEditMenu() |
|
1075 event.Skip() |
|
1076 |
|
1077 def OnRedoMenu(self, event): |
|
1078 self.Controler.LoadNext() |
|
1079 selected = self.GetPageSelection() |
|
1080 if selected != -1: |
|
1081 window = self.GetPage(selected) |
|
1082 window.RefreshView() |
|
1083 self.RefreshTitle() |
|
1084 self.RefreshEditMenu() |
|
1085 event.Skip() |
|
1086 |
|
1087 #------------------------------------------------------------------------------- |
|
1088 # CFile Editor Panels Management Functions |
|
1089 #------------------------------------------------------------------------------- |
|
1090 |
|
1091 def OnPartSelectedChanged(self, event): |
|
1092 if wx.VERSION < (2, 8, 0) or event.GetActive(): |
|
1093 old_selected = self.GetPageSelection() |
|
1094 if old_selected >= 0: |
|
1095 self.GetPage(old_selected).ResetBuffer() |
|
1096 if wx.VERSION >= (2, 8, 0): |
|
1097 window = event.GetEventObject().GetViewer() |
|
1098 else: |
|
1099 selected = event.GetSelection() |
|
1100 if selected >= 0: |
|
1101 window = self.GetPage(selected) |
|
1102 else: |
|
1103 window = None |
|
1104 if window: |
|
1105 window.RefreshView() |
|
1106 event.Skip() |
|
1107 |
|
1108 #------------------------------------------------------------------------------- |
|
1109 # CFile Tree Management Functions |
|
1110 #------------------------------------------------------------------------------- |
|
1111 |
|
1112 def InitCFileTree(self): |
|
1113 root = self.CFileTree.AddRoot("C File") |
|
1114 for name in CFILE_PARTS: |
|
1115 self.CFileTree.AppendItem(root, name) |
|
1116 self.CFileTree.Expand(root) |
|
1117 |
|
1118 def OnCFileTreeItemActivated(self, event): |
|
1119 self.EditCFilePart(self.CFileTree.GetItemText(event.GetItem())) |
|
1120 event.Skip() |
|
1121 |
|
1122 def OnCFileTreeItemSelected(self, event): |
|
1123 select_item = event.GetItem() |
|
1124 self.EditCFilePart(self.CFileTree.GetItemText(event.GetItem()), True) |
|
1125 event.Skip() |
|
1126 |
|
1127 def EditCFilePart(self, name, onlyopened = False): |
|
1128 openedidx = self.IsOpened(name) |
|
1129 if openedidx is not None: |
|
1130 old_selected = self.GetPageSelection() |
|
1131 if old_selected != openedidx: |
|
1132 if old_selected >= 0: |
|
1133 self.GetPage(old_selected).ResetBuffer() |
|
1134 self.SetPageSelection(openedidx) |
|
1135 self.GetPage(openedidx).RefreshView() |
|
1136 elif not onlyopened: |
|
1137 if wx.VERSION >= (2, 8, 0): |
|
1138 if name == "Variables": |
|
1139 new_window = MDIVariablesEditor(self, name, self, self.Controler) |
|
1140 else: |
|
1141 new_window = MDICppEditor(self, name, self, self.Controler) |
|
1142 new_window.Bind(wx.EVT_ACTIVATE, self.OnPartSelectedChanged) |
|
1143 new_window.Layout() |
|
1144 else: |
|
1145 if name == "Variables": |
|
1146 new_window = VariablesEditor(self.TabsOpened, self, self.Controler) |
|
1147 self.TabsOpened.AddPage(new_window, name) |
|
1148 else: |
|
1149 new_window = CppEditor(self.TabsOpened, name, self, self.Controler) |
|
1150 self.TabsOpened.AddPage(new_window, name) |
|
1151 openedidx = self.IsOpened(name) |
|
1152 old_selected = self.GetPageSelection() |
|
1153 if old_selected != openedidx: |
|
1154 if old_selected >= 0: |
|
1155 self.GetPage(old_selected).ResetBuffer() |
|
1156 for i in xrange(self.GetPageCount()): |
|
1157 window = self.GetPage(i) |
|
1158 if window.IsViewing(name): |
|
1159 self.SetPageSelection(i) |
|
1160 window.RefreshView() |
|
1161 window.SetFocus() |