|
1 import re |
|
2 import keyword |
|
3 |
1 import wx |
4 import wx |
2 import wx.grid |
5 import wx.grid |
3 import wx.stc as stc |
6 import wx.stc as stc |
4 import keyword |
7 |
5 |
8 from plcopen.plcopen import TestTextElement |
|
9 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD |
6 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor |
10 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor |
|
11 |
|
12 [STC_PYTHON_ERROR, STC_PYTHON_SEARCH_RESULT] = range(15, 17) |
|
13 |
|
14 HIGHLIGHT_TYPES = { |
|
15 ERROR_HIGHLIGHT: STC_PYTHON_ERROR, |
|
16 SEARCH_RESULT_HIGHLIGHT: STC_PYTHON_SEARCH_RESULT, |
|
17 } |
7 |
18 |
8 if wx.Platform == '__WXMSW__': |
19 if wx.Platform == '__WXMSW__': |
9 faces = { 'times': 'Times New Roman', |
20 faces = { 'times': 'Times New Roman', |
10 'mono' : 'Courier New', |
21 'mono' : 'Courier New', |
11 'helv' : 'Arial', |
22 'helv' : 'Arial', |
153 |
164 |
154 # Following style specs only indicate differences from default. |
165 # Following style specs only indicate differences from default. |
155 # The rest remains unchanged. |
166 # The rest remains unchanged. |
156 |
167 |
157 # Line numbers in margin |
168 # Line numbers in margin |
158 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') |
169 self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') |
159 # Highlighted brace |
170 # Highlighted brace |
160 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00') |
171 self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00') |
161 # Unmatched brace |
172 # Unmatched brace |
162 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000') |
173 self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000') |
163 # Indentation guide |
174 # Indentation guide |
164 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD") |
175 self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD") |
165 |
176 |
166 # Python styles |
177 # Python styles |
167 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000') |
178 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_DEFAULT, 'fore:#000000') |
168 # Comments |
179 # Comments |
169 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0') |
180 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0') |
170 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0') |
181 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0') |
171 # Numbers |
182 # Numbers |
172 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080') |
183 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_NUMBER, 'fore:#008080') |
173 # Strings and characters |
184 # Strings and characters |
174 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080') |
185 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_STRING, 'fore:#800080') |
175 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080') |
186 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_CHARACTER, 'fore:#800080') |
176 # Keywords |
187 # Keywords |
177 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold') |
188 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_WORD, 'fore:#000080,bold') |
178 # Triple quotes |
189 # Triple quotes |
179 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA') |
190 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA') |
180 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA') |
191 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA') |
181 # Class names |
192 # Class names |
182 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold') |
193 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_CLASSNAME, 'fore:#0000FF,bold') |
183 # Function names |
194 # Function names |
184 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold') |
195 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_DEFNAME, 'fore:#008080,bold') |
185 # Operators |
196 # Operators |
186 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold') |
197 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_OPERATOR, 'fore:#800000,bold') |
187 # Identifiers. I leave this as not bold because everything seems |
198 # Identifiers. I leave this as not bold because everything seems |
188 # to be an identifier if it doesn't match the above criterae |
199 # to be an identifier if it doesn't match the above criterae |
189 self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000') |
200 self.PythonCodeEditor.StyleSetSpec(stc.STC_P_IDENTIFIER, 'fore:#000000') |
190 |
201 |
|
202 # Highlighting styles |
|
203 self.PythonCodeEditor.StyleSetSpec(STC_PYTHON_ERROR, "fore:#FF0000,back:#FFFF00") |
|
204 self.PythonCodeEditor.StyleSetSpec(STC_PYTHON_SEARCH_RESULT, "fore:#FFFFFF,back:#FFA500") |
|
205 |
191 # Caret color |
206 # Caret color |
192 self.PythonCodeEditor.SetCaretForeground("BLUE") |
207 self.PythonCodeEditor.SetCaretForeground("BLUE") |
193 # Selection background |
208 # Selection background |
194 self.PythonCodeEditor.SetSelBackground(1, '#66CCFF') |
209 self.PythonCodeEditor.SetSelBackground(1, '#66CCFF') |
195 |
210 |
217 self.PythonCodeEditor.SetViewWhiteSpace(False) # Don't view white space |
232 self.PythonCodeEditor.SetViewWhiteSpace(False) # Don't view white space |
218 |
233 |
219 # EOL: Since we are loading/saving ourselves, and the |
234 # EOL: Since we are loading/saving ourselves, and the |
220 # strings will always have \n's in them, set the STC to |
235 # strings will always have \n's in them, set the STC to |
221 # edit them that way. |
236 # edit them that way. |
222 self.PythonCodeEditor.SetEOLMode(wx.stc.STC_EOL_LF) |
237 self.PythonCodeEditor.SetEOLMode(stc.STC_EOL_LF) |
223 self.PythonCodeEditor.SetViewEOL(False) |
238 self.PythonCodeEditor.SetViewEOL(False) |
224 |
239 |
225 # No right-edge mode indicator |
240 # No right-edge mode indicator |
226 self.PythonCodeEditor.SetEdgeMode(stc.STC_EDGE_NONE) |
241 self.PythonCodeEditor.SetEdgeMode(stc.STC_EDGE_NONE) |
227 |
242 |
228 self.PythonCodeEditor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE) |
243 self.PythonCodeEditor.SetModEventMask(stc.STC_MOD_BEFOREINSERT|stc.STC_MOD_BEFOREDELETE) |
229 |
244 |
230 self.PythonCodeEditor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR) |
245 self.PythonCodeEditor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR) |
231 self.PythonCodeEditor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) |
246 self.PythonCodeEditor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) |
232 self.PythonCodeEditor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR) |
247 self.PythonCodeEditor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR) |
233 |
248 |
236 def __init__(self, parent, controler, window): |
251 def __init__(self, parent, controler, window): |
237 ConfTreeNodeEditor.__init__(self, parent, controler, window) |
252 ConfTreeNodeEditor.__init__(self, parent, controler, window) |
238 |
253 |
239 self.DisableEvents = False |
254 self.DisableEvents = False |
240 self.CurrentAction = None |
255 self.CurrentAction = None |
|
256 |
|
257 self.Highlights = [] |
|
258 self.SearchParams = None |
|
259 self.SearchResults = None |
|
260 self.CurrentFindHighlight = None |
|
261 |
|
262 self.RefreshHighlightsTimer = wx.Timer(self, -1) |
|
263 self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer) |
241 |
264 |
242 def GetBufferState(self): |
265 def GetBufferState(self): |
243 return self.Controler.GetBufferState() |
266 return self.Controler.GetBufferState() |
244 |
267 |
245 def Undo(self): |
268 def Undo(self): |
481 self.DisableEvents = True |
506 self.DisableEvents = True |
482 self.PythonCodeEditor.CmdKeyExecute(wx.stc.STC_CMD_PASTE) |
507 self.PythonCodeEditor.CmdKeyExecute(wx.stc.STC_CMD_PASTE) |
483 self.DisableEvents = False |
508 self.DisableEvents = False |
484 self.RefreshModel() |
509 self.RefreshModel() |
485 self.RefreshBuffer() |
510 self.RefreshBuffer() |
|
511 |
|
512 def Find(self, direction, search_params): |
|
513 if self.SearchParams != search_params: |
|
514 self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT) |
|
515 |
|
516 self.SearchParams = search_params |
|
517 criteria = { |
|
518 "raw_pattern": search_params["find_pattern"], |
|
519 "pattern": re.compile(search_params["find_pattern"]), |
|
520 "case_sensitive": search_params["case_sensitive"], |
|
521 "regular_expression": search_params["regular_expression"], |
|
522 "filter": "all"} |
|
523 |
|
524 self.SearchResults = [ |
|
525 (start, end, SEARCH_RESULT_HIGHLIGHT) |
|
526 for start, end, text in |
|
527 TestTextElement(self.PythonCodeEditor.GetText(), criteria)] |
|
528 self.CurrentFindHighlight = None |
|
529 |
|
530 if len(self.SearchResults) > 0: |
|
531 if self.CurrentFindHighlight is not None: |
|
532 old_idx = self.SearchResults.index(self.CurrentFindHighlight) |
|
533 if self.SearchParams["wrap"]: |
|
534 idx = (old_idx + direction) % len(self.SearchResults) |
|
535 else: |
|
536 idx = max(0, min(old_idx + direction, len(self.SearchResults) - 1)) |
|
537 if idx != old_idx: |
|
538 self.RemoveHighlight(*self.CurrentFindHighlight) |
|
539 self.CurrentFindHighlight = self.SearchResults[idx] |
|
540 self.AddHighlight(*self.CurrentFindHighlight) |
|
541 else: |
|
542 self.CurrentFindHighlight = self.SearchResults[0] |
|
543 self.AddHighlight(*self.CurrentFindHighlight) |
|
544 |
|
545 else: |
|
546 if self.CurrentFindHighlight is not None: |
|
547 self.RemoveHighlight(*self.CurrentFindHighlight) |
|
548 self.CurrentFindHighlight = None |
|
549 |
|
550 #------------------------------------------------------------------------------- |
|
551 # Highlights showing functions |
|
552 #------------------------------------------------------------------------------- |
|
553 |
|
554 def OnRefreshHighlightsTimer(self, event): |
|
555 self.RefreshView() |
|
556 event.Skip() |
|
557 |
|
558 def ClearHighlights(self, highlight_type=None): |
|
559 if highlight_type is None: |
|
560 self.Highlights = [] |
|
561 else: |
|
562 highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) |
|
563 if highlight_type is not None: |
|
564 self.Highlights = [(start, end, highlight) for (start, end, highlight) in self.Highlights if highlight != highlight_type] |
|
565 self.RefreshView() |
|
566 |
|
567 def AddHighlight(self, start, end, highlight_type): |
|
568 highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) |
|
569 if highlight_type is not None: |
|
570 self.Highlights.append((start, end, highlight_type)) |
|
571 self.PythonCodeEditor.GotoPos(self.PythonCodeEditor.PositionFromLine(start[0]) + start[1]) |
|
572 self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) |
|
573 self.RefreshView() |
|
574 |
|
575 def RemoveHighlight(self, start, end, highlight_type): |
|
576 highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) |
|
577 if (highlight_type is not None and |
|
578 (start, end, highlight_type) in self.Highlights): |
|
579 self.Highlights.remove((start, end, highlight_type)) |
|
580 self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) |
|
581 |
|
582 def ShowHighlights(self): |
|
583 for start, end, highlight_type in self.Highlights: |
|
584 if start[0] == 0: |
|
585 highlight_start_pos = start[1] |
|
586 else: |
|
587 highlight_start_pos = self.PythonCodeEditor.GetLineEndPosition(start[0] - 1) + start[1] + 1 |
|
588 if end[0] == 0: |
|
589 highlight_end_pos = end[1] - indent + 1 |
|
590 else: |
|
591 highlight_end_pos = self.PythonCodeEditor.GetLineEndPosition(end[0] - 1) + end[1] + 2 |
|
592 self.PythonCodeEditor.StartStyling(highlight_start_pos, 0xff) |
|
593 self.PythonCodeEditor.SetStyling(highlight_end_pos - highlight_start_pos, highlight_type) |
|
594 self.PythonCodeEditor.StartStyling(highlight_start_pos, 0x00) |
|
595 self.PythonCodeEditor.SetStyling(len(self.PythonCodeEditor.GetText()) - highlight_end_pos, stc.STC_STYLE_DEFAULT) |
|
596 |