3 import wx |
3 import wx |
4 import wx.grid |
4 import wx.grid |
5 import wx.stc as stc |
5 import wx.stc as stc |
6 import wx.lib.buttons |
6 import wx.lib.buttons |
7 |
7 |
|
8 from plcopen.plcopen import TestTextElement |
8 from controls import CustomGrid, CustomTable |
9 from controls import CustomGrid, CustomTable |
9 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor |
10 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor |
10 from util.BitmapLibrary import GetBitmap |
11 from util.BitmapLibrary import GetBitmap |
11 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos |
12 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos |
|
13 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD |
12 |
14 |
13 SECTIONS_NAMES = ["Includes", "Globals", "Init", |
15 SECTIONS_NAMES = ["Includes", "Globals", "Init", |
14 "CleanUp", "Retrieve", "Publish"] |
16 "CleanUp", "Retrieve", "Publish"] |
|
17 |
|
18 [STC_CODE_ERROR, STC_CODE_SEARCH_RESULT] = range(15, 17) |
|
19 |
|
20 HIGHLIGHT_TYPES = { |
|
21 ERROR_HIGHLIGHT: STC_CODE_ERROR, |
|
22 SEARCH_RESULT_HIGHLIGHT: STC_CODE_SEARCH_RESULT, |
|
23 } |
15 |
24 |
16 class CodeEditor(CustomStyledTextCtrl): |
25 class CodeEditor(CustomStyledTextCtrl): |
17 |
26 |
18 KEYWORDS = [] |
27 KEYWORDS = [] |
19 COMMENT_HEADER = "" |
28 COMMENT_HEADER = "" |
69 self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size)d" % faces) |
78 self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size)d" % faces) |
70 self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces) |
79 self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces) |
71 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold") |
80 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold") |
72 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold") |
81 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold") |
73 |
82 |
|
83 # Highlighting styles |
|
84 self.StyleSetSpec(STC_CODE_ERROR, 'fore:#FF0000,back:#FFFF00,size:%(size)d' % faces) |
|
85 self.StyleSetSpec(STC_CODE_SEARCH_RESULT, 'fore:#FFFFFF,back:#FFA500,size:%(size)d' % faces) |
|
86 |
74 # register some images for use in the AutoComplete box. |
87 # register some images for use in the AutoComplete box. |
75 #self.RegisterImage(1, images.getSmilesBitmap()) |
88 #self.RegisterImage(1, images.getSmilesBitmap()) |
76 self.RegisterImage(1, |
89 self.RegisterImage(1, |
77 wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16))) |
90 wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16))) |
78 self.RegisterImage(2, |
91 self.RegisterImage(2, |
90 self.Controler = controler |
103 self.Controler = controler |
91 self.ParentWindow = window |
104 self.ParentWindow = window |
92 |
105 |
93 self.DisableEvents = True |
106 self.DisableEvents = True |
94 self.CurrentAction = None |
107 self.CurrentAction = None |
|
108 |
|
109 self.Highlights = [] |
|
110 self.SearchParams = None |
|
111 self.SearchResults = None |
|
112 self.CurrentFindHighlight = None |
|
113 |
|
114 self.RefreshHighlightsTimer = wx.Timer(self, -1) |
|
115 self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer) |
95 |
116 |
96 self.SectionsComments = {} |
117 self.SectionsComments = {} |
97 for section in SECTIONS_NAMES: |
118 for section in SECTIONS_NAMES: |
98 section_start_comment = "%s %s section\n" % (self.COMMENT_HEADER, section) |
119 section_start_comment = "%s %s section\n" % (self.COMMENT_HEADER, section) |
99 section_end_comment = "\n%s End %s section\n\n" % (self.COMMENT_HEADER, section) |
120 section_end_comment = "\n%s End %s section\n\n" % (self.COMMENT_HEADER, section) |
372 self.DisableEvents = True |
395 self.DisableEvents = True |
373 self.CmdKeyExecute(wx.stc.STC_CMD_PASTE) |
396 self.CmdKeyExecute(wx.stc.STC_CMD_PASTE) |
374 self.DisableEvents = False |
397 self.DisableEvents = False |
375 self.RefreshModel() |
398 self.RefreshModel() |
376 self.RefreshBuffer() |
399 self.RefreshBuffer() |
|
400 |
|
401 def Find(self, direction, search_params): |
|
402 if self.SearchParams != search_params: |
|
403 self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT) |
|
404 |
|
405 self.SearchParams = search_params |
|
406 criteria = { |
|
407 "raw_pattern": search_params["find_pattern"], |
|
408 "pattern": re.compile(search_params["find_pattern"]), |
|
409 "case_sensitive": search_params["case_sensitive"], |
|
410 "regular_expression": search_params["regular_expression"], |
|
411 "filter": "all"} |
|
412 |
|
413 self.SearchResults = [ |
|
414 (start, end, SEARCH_RESULT_HIGHLIGHT) |
|
415 for start, end, text in |
|
416 TestTextElement(self.GetText(), criteria)] |
|
417 self.CurrentFindHighlight = None |
|
418 |
|
419 if len(self.SearchResults) > 0: |
|
420 if self.CurrentFindHighlight is not None: |
|
421 old_idx = self.SearchResults.index(self.CurrentFindHighlight) |
|
422 if self.SearchParams["wrap"]: |
|
423 idx = (old_idx + direction) % len(self.SearchResults) |
|
424 else: |
|
425 idx = max(0, min(old_idx + direction, len(self.SearchResults) - 1)) |
|
426 if idx != old_idx: |
|
427 self.RemoveHighlight(*self.CurrentFindHighlight) |
|
428 self.CurrentFindHighlight = self.SearchResults[idx] |
|
429 self.AddHighlight(*self.CurrentFindHighlight) |
|
430 else: |
|
431 self.CurrentFindHighlight = self.SearchResults[0] |
|
432 self.AddHighlight(*self.CurrentFindHighlight) |
|
433 |
|
434 else: |
|
435 if self.CurrentFindHighlight is not None: |
|
436 self.RemoveHighlight(*self.CurrentFindHighlight) |
|
437 self.CurrentFindHighlight = None |
|
438 |
|
439 #------------------------------------------------------------------------------- |
|
440 # Highlights showing functions |
|
441 #------------------------------------------------------------------------------- |
|
442 |
|
443 def OnRefreshHighlightsTimer(self, event): |
|
444 self.RefreshView() |
|
445 event.Skip() |
|
446 |
|
447 def ClearHighlights(self, highlight_type=None): |
|
448 if highlight_type is None: |
|
449 self.Highlights = [] |
|
450 else: |
|
451 highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) |
|
452 if highlight_type is not None: |
|
453 self.Highlights = [(start, end, highlight) for (start, end, highlight) in self.Highlights if highlight != highlight_type] |
|
454 self.RefreshView() |
|
455 |
|
456 def AddHighlight(self, start, end, highlight_type): |
|
457 highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) |
|
458 if highlight_type is not None: |
|
459 self.Highlights.append((start, end, highlight_type)) |
|
460 self.GotoPos(self.PositionFromLine(start[0]) + start[1]) |
|
461 self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) |
|
462 self.RefreshView() |
|
463 |
|
464 def RemoveHighlight(self, start, end, highlight_type): |
|
465 highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) |
|
466 if (highlight_type is not None and |
|
467 (start, end, highlight_type) in self.Highlights): |
|
468 self.Highlights.remove((start, end, highlight_type)) |
|
469 self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) |
|
470 |
|
471 def ShowHighlights(self): |
|
472 for start, end, highlight_type in self.Highlights: |
|
473 if start[0] == 0: |
|
474 highlight_start_pos = start[1] |
|
475 else: |
|
476 highlight_start_pos = self.GetLineEndPosition(start[0] - 1) + start[1] + 1 |
|
477 if end[0] == 0: |
|
478 highlight_end_pos = end[1] - indent + 1 |
|
479 else: |
|
480 highlight_end_pos = self.GetLineEndPosition(end[0] - 1) + end[1] + 2 |
|
481 self.StartStyling(highlight_start_pos, 0xff) |
|
482 self.SetStyling(highlight_end_pos - highlight_start_pos, highlight_type) |
|
483 self.StartStyling(highlight_start_pos, 0x00) |
|
484 self.SetStyling(len(self.GetText()) - highlight_end_pos, stc.STC_STYLE_DEFAULT) |
377 |
485 |
378 |
486 |
379 #------------------------------------------------------------------------------- |
487 #------------------------------------------------------------------------------- |
380 # Helper for VariablesGrid values |
488 # Helper for VariablesGrid values |
381 #------------------------------------------------------------------------------- |
489 #------------------------------------------------------------------------------- |
427 def __init__(self, parent, window, controler): |
535 def __init__(self, parent, window, controler): |
428 wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL) |
536 wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL) |
429 |
537 |
430 main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4) |
538 main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4) |
431 main_sizer.AddGrowableCol(0) |
539 main_sizer.AddGrowableCol(0) |
432 main_sizer.AddGrowableRow(0) |
540 main_sizer.AddGrowableRow(1) |
433 |
|
434 self.VariablesGrid = CustomGrid(self, size=wx.Size(-1, 300), style=wx.VSCROLL) |
|
435 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange) |
|
436 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick) |
|
437 self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown) |
|
438 main_sizer.AddWindow(self.VariablesGrid, flag=wx.GROW) |
|
439 |
541 |
440 controls_sizer = wx.BoxSizer(wx.HORIZONTAL) |
542 controls_sizer = wx.BoxSizer(wx.HORIZONTAL) |
441 main_sizer.AddSizer(controls_sizer, border=5, flag=wx.TOP|wx.ALIGN_RIGHT) |
543 main_sizer.AddSizer(controls_sizer, border=5, flag=wx.TOP|wx.ALIGN_RIGHT) |
442 |
544 |
443 for name, bitmap, help in [ |
545 for name, bitmap, help in [ |
447 ("DownVariableButton", "down", _("Move variable down"))]: |
549 ("DownVariableButton", "down", _("Move variable down"))]: |
448 button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), |
550 button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), |
449 size=wx.Size(28, 28), style=wx.NO_BORDER) |
551 size=wx.Size(28, 28), style=wx.NO_BORDER) |
450 button.SetToolTipString(help) |
552 button.SetToolTipString(help) |
451 setattr(self, name, button) |
553 setattr(self, name, button) |
452 controls_sizer.AddWindow(button, border=5, flag=wx.LEFT) |
554 controls_sizer.AddWindow(button, border=5, flag=wx.RIGHT) |
|
555 |
|
556 self.VariablesGrid = CustomGrid(self, size=wx.Size(-1, 300), style=wx.VSCROLL) |
|
557 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange) |
|
558 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick) |
|
559 self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown) |
|
560 main_sizer.AddWindow(self.VariablesGrid, flag=wx.GROW) |
453 |
561 |
454 self.SetSizer(main_sizer) |
562 self.SetSizer(main_sizer) |
455 |
563 |
456 self.ParentWindow = window |
564 self.ParentWindow = window |
457 self.Controler = controler |
565 self.Controler = controler |
529 new_id = wx.NewId() |
637 new_id = wx.NewId() |
530 base_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type) |
638 base_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type) |
531 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id) |
639 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id) |
532 type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu) |
640 type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu) |
533 datatype_menu = wx.Menu(title='') |
641 datatype_menu = wx.Menu(title='') |
534 for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True): |
642 for datatype in self.Controler.GetDataTypes(): |
535 new_id = wx.NewId() |
643 new_id = wx.NewId() |
536 datatype_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype) |
644 datatype_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype) |
537 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id) |
645 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id) |
538 type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu) |
646 type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu) |
539 rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col)) |
647 rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col)) |