editors/CodeFileEditor.py
changeset 1097 233681f2a00e
parent 1096 c9ace6a881c9
child 1101 5a0b439cf576
equal deleted inserted replaced
1096:c9ace6a881c9 1097:233681f2a00e
     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)
   192                 self.GotoPos(old_cursor_pos)
   213                 self.GotoPos(old_cursor_pos)
   193             self.EmptyUndoBuffer()
   214             self.EmptyUndoBuffer()
   194         self.DisableEvents = False
   215         self.DisableEvents = False
   195         
   216         
   196         self.Colourise(0, -1)
   217         self.Colourise(0, -1)
       
   218         
       
   219         self.ShowHighlights()
   197 
   220 
   198     def DoGetBestSize(self):
   221     def DoGetBestSize(self):
   199         return self.ParentWindow.GetPanelBestSize()
   222         return self.ParentWindow.GetPanelBestSize()
   200 
   223 
   201     def RefreshModel(self):
   224     def RefreshModel(self):
   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))