editors/CodeFileEditor.py
changeset 1412 50192dd2f5ff
parent 1178 3e2aebc9c7c0
child 1448 20ff66dcc31d
equal deleted inserted replaced
1411:805d13d216c0 1412:50192dd2f5ff
     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 plcopen.plcopen import TestTextElement
     9 from plcopen.structures import TestIdentifier, IEC_KEYWORDS
     9 from plcopen.structures import TestIdentifier, IEC_KEYWORDS, DefaultType
    10 from controls import CustomGrid, CustomTable
    10 from controls import CustomGrid, CustomTable
    11 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
    11 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
    12 from util.BitmapLibrary import GetBitmap
    12 from util.BitmapLibrary import GetBitmap
    13 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos, NAVIGATION_KEYS
    13 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos, NAVIGATION_KEYS
    14 from controls.VariablePanel import VARIABLE_NAME_SUFFIX_MODEL
    14 from controls.VariablePanel import VARIABLE_NAME_SUFFIX_MODEL
    15 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
    15 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
    16 
    16 
    17 [STC_CODE_ERROR, STC_CODE_SEARCH_RESULT, 
    17 [STC_CODE_ERROR, STC_CODE_SEARCH_RESULT,
    18  STC_CODE_SECTION] = range(15, 18)
    18  STC_CODE_SECTION] = range(15, 18)
    19 
    19 
    20 HIGHLIGHT_TYPES = {
    20 HIGHLIGHT_TYPES = {
    21     ERROR_HIGHLIGHT: STC_CODE_ERROR,
    21     ERROR_HIGHLIGHT: STC_CODE_ERROR,
    22     SEARCH_RESULT_HIGHLIGHT: STC_CODE_SEARCH_RESULT,
    22     SEARCH_RESULT_HIGHLIGHT: STC_CODE_SEARCH_RESULT,
    23 }
    23 }
    24 
    24 
    25 EDGE_COLUMN = 80
    25 EDGE_COLUMN = 80
    26 
    26 
    27 class CodeEditor(CustomStyledTextCtrl):
    27 class CodeEditor(CustomStyledTextCtrl):
    28     
    28 
    29     KEYWORDS = []
    29     KEYWORDS = []
    30     COMMENT_HEADER = ""
    30     COMMENT_HEADER = ""
    31 
    31 
    32     def __init__(self, parent, window, controler):
    32     def __init__(self, parent, window, controler):
    33         CustomStyledTextCtrl.__init__(self, parent, -1, wx.DefaultPosition, 
    33         CustomStyledTextCtrl.__init__(self, parent, -1, wx.DefaultPosition,
    34                  wx.Size(-1, 300), 0)
    34                  wx.Size(-1, 300), 0)
    35         
    35 
    36         self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
    36         self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
    37         self.SetMarginWidth(1, 25)
    37         self.SetMarginWidth(1, 25)
    38 
    38 
    39         self.SetProperty("fold", "1")
    39         self.SetProperty("fold", "1")
    40         self.SetProperty("tab.timmy.whinge.level", "1")
    40         self.SetProperty("tab.timmy.whinge.level", "1")
    41         self.SetMargins(0,0)
    41         self.SetMargins(0,0)
    42 
    42 
    43         self.SetViewWhiteSpace(False)
    43         self.SetViewWhiteSpace(False)
    44         
    44 
    45         self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
    45         self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
    46         self.SetEdgeColumn(EDGE_COLUMN)
    46         self.SetEdgeColumn(EDGE_COLUMN)
    47 
    47 
    48         # Setup a margin to hold fold markers
    48         # Setup a margin to hold fold markers
    49         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
    49         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
    57         self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
    57         self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
    58         self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
    58         self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
    59         self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
    59         self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
    60         self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
    60         self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
    61         self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
    61         self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
    62         
    62 
    63         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
    63         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
    64         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
    64         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
    65         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
    65         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
    66 
    66 
    67         # Make some styles,  The lexer defines what each style is used for, we
    67         # Make some styles,  The lexer defines what each style is used for, we
    76         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
    76         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
    77         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size)d" % faces)
    77         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size)d" % faces)
    78         self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces)
    78         self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces)
    79         self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
    79         self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
    80         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
    80         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
    81         
    81 
    82         # Highlighting styles
    82         # Highlighting styles
    83         self.StyleSetSpec(STC_CODE_ERROR, 'fore:#FF0000,back:#FFFF00,size:%(size)d' % faces)
    83         self.StyleSetSpec(STC_CODE_ERROR, 'fore:#FF0000,back:#FFFF00,size:%(size)d' % faces)
    84         self.StyleSetSpec(STC_CODE_SEARCH_RESULT, 'fore:#FFFFFF,back:#FFA500,size:%(size)d' % faces)
    84         self.StyleSetSpec(STC_CODE_SEARCH_RESULT, 'fore:#FFFFFF,back:#FFA500,size:%(size)d' % faces)
    85         
    85 
    86         # Section style
    86         # Section style
    87         self.StyleSetSpec(STC_CODE_SECTION, 'fore:#808080,size:%(size)d')
    87         self.StyleSetSpec(STC_CODE_SECTION, 'fore:#808080,size:%(size)d')
    88         self.StyleSetChangeable(STC_CODE_SECTION, False)
    88         self.StyleSetChangeable(STC_CODE_SECTION, False)
    89         
    89 
    90         # Indentation size
    90         # Indentation size
    91         self.SetTabWidth(4)
    91         self.SetTabWidth(4)
    92         self.SetUseTabs(0)
    92         self.SetUseTabs(0)
    93         
    93 
    94         self.SetCodeLexer()
    94         self.SetCodeLexer()
    95         self.SetKeyWords(0, " ".join(self.KEYWORDS))
    95         self.SetKeyWords(0, " ".join(self.KEYWORDS))
    96         
    96 
    97         self.Controler = controler
    97         self.Controler = controler
    98         self.ParentWindow = window
    98         self.ParentWindow = window
    99         
    99 
   100         self.DisableEvents = True
   100         self.DisableEvents = True
   101         self.CurrentAction = None
   101         self.CurrentAction = None
   102         
   102 
   103         self.ResetSearchResults()
   103         self.ResetSearchResults()
   104         
   104 
   105         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   105         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   106         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
   106         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
   107         
   107 
   108         self.SectionsComments = {}
   108         self.SectionsComments = {}
   109         for section in self.Controler.SECTIONS_NAMES:
   109         for section in self.Controler.SECTIONS_NAMES:
   110             section_comment = " %s section " % (section)
   110             section_comment = " %s section " % (section)
   111             len_headers = EDGE_COLUMN - len(section_comment)
   111             len_headers = EDGE_COLUMN - len(section_comment)
   112             section_comment = self.COMMENT_HEADER * (len_headers / 2) + \
   112             section_comment = self.COMMENT_HEADER * (len_headers / 2) + \
   113                               section_comment + \
   113                               section_comment + \
   114                               self.COMMENT_HEADER * (len_headers - len_headers / 2)
   114                               self.COMMENT_HEADER * (len_headers - len_headers / 2)
   115             
   115 
   116             self.SectionsComments[section] = {
   116             self.SectionsComments[section] = {
   117                  "comment": section_comment,
   117                  "comment": section_comment,
   118             }
   118             }
   119             
   119 
   120         for i, section in enumerate(self.Controler.SECTIONS_NAMES):
   120         for i, section in enumerate(self.Controler.SECTIONS_NAMES):
   121             section_infos = self.SectionsComments[section]
   121             section_infos = self.SectionsComments[section]
   122             if i + 1 < len(self.Controler.SECTIONS_NAMES):
   122             if i + 1 < len(self.Controler.SECTIONS_NAMES):
   123                 section_end = self.SectionsComments[
   123                 section_end = self.SectionsComments[
   124                     self.Controler.SECTIONS_NAMES[i + 1]]["comment"]
   124                     self.Controler.SECTIONS_NAMES[i + 1]]["comment"]
   125             else:
   125             else:
   126                 section_end = "$"
   126                 section_end = "$"
   127             section_infos["pattern"] = re.compile(
   127             section_infos["pattern"] = re.compile(
   128                 section_infos["comment"] + "(.*)" + 
   128                 section_infos["comment"] + "(.*)" +
   129                 section_end, re.DOTALL)
   129                 section_end, re.DOTALL)
   130             
   130 
   131         self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
   131         self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
   132 
   132 
   133         self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop)
   133         self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop)
   134         self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
   134         self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
   135         self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification)
   135         self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification)
   136     
   136 
   137     def SetCodeLexer(self):
   137     def SetCodeLexer(self):
   138         pass
   138         pass
   139     
   139 
   140     def ResetSearchResults(self):
   140     def ResetSearchResults(self):
   141         self.Highlights = []
   141         self.Highlights = []
   142         self.SearchParams = None
   142         self.SearchParams = None
   143         self.SearchResults = None
   143         self.SearchResults = None
   144         self.CurrentFindHighlight = None
   144         self.CurrentFindHighlight = None
   145     
   145 
   146     def OnModification(self, event):
   146     def OnModification(self, event):
   147         if not self.DisableEvents:
   147         if not self.DisableEvents:
   148             mod_type = event.GetModificationType()
   148             mod_type = event.GetModificationType()
   149             if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
   149             if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
   150                 if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
   150                 if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
   163                         self.StartBuffering()
   163                         self.StartBuffering()
   164                     self.CurrentAction = ("Delete", event.GetPosition())
   164                     self.CurrentAction = ("Delete", event.GetPosition())
   165                     wx.CallAfter(self.RefreshModel)
   165                     wx.CallAfter(self.RefreshModel)
   166         wx.CallAfter(self.RefreshSectionStyling)
   166         wx.CallAfter(self.RefreshSectionStyling)
   167         event.Skip()
   167         event.Skip()
   168     
   168 
   169     def OnDoDrop(self, event):
   169     def OnDoDrop(self, event):
   170         try:
   170         try:
   171             values = eval(event.GetDragText())
   171             values = eval(event.GetDragText())
   172         except:
   172         except:
   173             values = event.GetDragText()
   173             values = event.GetDragText()
   190         if self.ParentWindow is not None:
   190         if self.ParentWindow is not None:
   191             self.ParentWindow.RefreshTitle()
   191             self.ParentWindow.RefreshTitle()
   192             self.ParentWindow.RefreshFileMenu()
   192             self.ParentWindow.RefreshFileMenu()
   193             self.ParentWindow.RefreshEditMenu()
   193             self.ParentWindow.RefreshEditMenu()
   194             self.ParentWindow.RefreshPageTitles()
   194             self.ParentWindow.RefreshPageTitles()
   195     
   195 
   196     def StartBuffering(self):
   196     def StartBuffering(self):
   197         self.Controler.StartBuffering()
   197         self.Controler.StartBuffering()
   198         if self.ParentWindow is not None:
   198         if self.ParentWindow is not None:
   199             self.ParentWindow.RefreshTitle()
   199             self.ParentWindow.RefreshTitle()
   200             self.ParentWindow.RefreshFileMenu()
   200             self.ParentWindow.RefreshFileMenu()
   201             self.ParentWindow.RefreshEditMenu()
   201             self.ParentWindow.RefreshEditMenu()
   202             self.ParentWindow.RefreshPageTitles()
   202             self.ParentWindow.RefreshPageTitles()
   203     
   203 
   204     def ResetBuffer(self):
   204     def ResetBuffer(self):
   205         if self.CurrentAction != None:
   205         if self.CurrentAction != None:
   206             self.Controler.EndBuffering()
   206             self.Controler.EndBuffering()
   207             self.CurrentAction = None
   207             self.CurrentAction = None
   208 
   208 
   238                 self.GotoPos(new_cursor_pos)
   238                 self.GotoPos(new_cursor_pos)
   239             else:
   239             else:
   240                 self.GotoPos(old_cursor_pos)
   240                 self.GotoPos(old_cursor_pos)
   241             self.EmptyUndoBuffer()
   241             self.EmptyUndoBuffer()
   242         self.DisableEvents = False
   242         self.DisableEvents = False
   243         
   243 
   244         self.RefreshSectionStyling()
   244         self.RefreshSectionStyling()
   245         
   245 
   246         self.ShowHighlights()
   246         self.ShowHighlights()
   247         
   247 
   248     def RefreshSectionStyling(self):
   248     def RefreshSectionStyling(self):
   249         self.Colourise(0, -1)
   249         self.Colourise(0, -1)
   250         
   250 
   251         text = self.GetText()
   251         text = self.GetText()
   252         for line in xrange(self.GetLineCount()):
   252         for line in xrange(self.GetLineCount()):
   253             self.SetLineState(line, 0)
   253             self.SetLineState(line, 0)
   254         
   254 
   255         for section in self.Controler.SECTIONS_NAMES:
   255         for section in self.Controler.SECTIONS_NAMES:
   256             section_comments = self.SectionsComments[section]
   256             section_comments = self.SectionsComments[section]
   257             start_pos = text.find(section_comments["comment"])
   257             start_pos = text.find(section_comments["comment"])
   258             end_pos = start_pos + len(section_comments["comment"])
   258             end_pos = start_pos + len(section_comments["comment"])
   259             self.StartStyling(start_pos, 0xff)
   259             self.StartStyling(start_pos, 0xff)
   260             self.SetStyling(end_pos - start_pos, STC_CODE_SECTION)
   260             self.SetStyling(end_pos - start_pos, STC_CODE_SECTION)
   261             self.SetLineState(self.LineFromPosition(start_pos), 1)
   261             self.SetLineState(self.LineFromPosition(start_pos), 1)
   262             
   262 
   263         self.StartStyling(end_pos, 0x00)
   263         self.StartStyling(end_pos, 0x00)
   264         self.SetStyling(len(self.GetText()) - end_pos, stc.STC_STYLE_DEFAULT)
   264         self.SetStyling(len(self.GetText()) - end_pos, stc.STC_STYLE_DEFAULT)
   265 
   265 
   266     def DoGetBestSize(self):
   266     def DoGetBestSize(self):
   267         return self.ParentWindow.GetPanelBestSize()
   267         return self.ParentWindow.GetPanelBestSize()
   276                 parts[section] = result.group(1)
   276                 parts[section] = result.group(1)
   277             else:
   277             else:
   278                 parts[section] = ""
   278                 parts[section] = ""
   279         self.Controler.SetTextParts(parts)
   279         self.Controler.SetTextParts(parts)
   280         self.ResetSearchResults()
   280         self.ResetSearchResults()
   281     
   281 
   282     def OnKeyPressed(self, event):
   282     def OnKeyPressed(self, event):
   283         if self.CallTipActive():
   283         if self.CallTipActive():
   284             self.CallTipCancel()
   284             self.CallTipCancel()
   285         key = event.GetKeyCode()
   285         key = event.GetKeyCode()
   286         current_pos = self.GetCurrentPos()
   286         current_pos = self.GetCurrentPos()
   287         selected = self.GetSelection()
   287         selected = self.GetSelection()
   288         text_selected = selected[0] != selected[1]
   288         text_selected = selected[0] != selected[1]
   289         
   289 
   290         # Test if caret is before Windows like new line
   290         # Test if caret is before Windows like new line
   291         text = self.GetText()
   291         text = self.GetText()
   292         if current_pos < len(text) and ord(text[current_pos]) == 13:
   292         if current_pos < len(text) and ord(text[current_pos]) == 13:
   293             newline_size = 2
   293             newline_size = 2
   294         else:
   294         else:
   295             newline_size = 1
   295             newline_size = 1
   296         
   296 
   297         # Disable to type any character in section header lines
   297         # Disable to type any character in section header lines
   298         if (self.GetLineState(self.LineFromPosition(current_pos)) and
   298         if (self.GetLineState(self.LineFromPosition(current_pos)) and
   299             not text_selected and
   299             not text_selected and
   300             key not in NAVIGATION_KEYS + [
   300             key not in NAVIGATION_KEYS + [
   301                 wx.WXK_RETURN,
   301                 wx.WXK_RETURN,
   302                 wx.WXK_NUMPAD_ENTER]):
   302                 wx.WXK_NUMPAD_ENTER]):
   303             return
   303             return
   304         
   304 
   305         # Disable to delete line between code and header lines
   305         # Disable to delete line between code and header lines
   306         elif (self.GetCurLine()[0].strip() != "" and not text_selected and
   306         elif (self.GetCurLine()[0].strip() != "" and not text_selected and
   307               (key == wx.WXK_BACK and
   307               (key == wx.WXK_BACK and
   308                self.GetLineState(self.LineFromPosition(max(0, current_pos - 1))) or
   308                self.GetLineState(self.LineFromPosition(max(0, current_pos - 1))) or
   309                key in [wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE] and
   309                key in [wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE] and
   310                self.GetLineState(self.LineFromPosition(min(len(text), current_pos + newline_size))))):
   310                self.GetLineState(self.LineFromPosition(min(len(text), current_pos + newline_size))))):
   311             return
   311             return
   312         
   312 
   313         elif key == 32 and event.ControlDown():
   313         elif key == 32 and event.ControlDown():
   314             pos = self.GetCurrentPos()
   314             pos = self.GetCurrentPos()
   315 
   315 
   316             # Tips
   316             # Tips
   317             if event.ShiftDown():
   317             if event.ShiftDown():
   318                 pass
   318                 pass
   319             # Code completion
   319             # Code completion
   320             else:
   320             else:
   321                 self.AutoCompSetIgnoreCase(False)  # so this needs to match
   321                 self.AutoCompSetIgnoreCase(False)  # so this needs to match
   322                 
   322 
   323                 keywords = self.KEYWORDS + [var["Name"]
   323                 keywords = self.KEYWORDS + [var["Name"]
   324                                             for var in self.Controler.GetVariables()]
   324                                             for var in self.Controler.GetVariables()]
   325                 keywords.sort()
   325                 keywords.sort()
   326                 self.AutoCompShow(0, " ".join(keywords))
   326                 self.AutoCompShow(0, " ".join(keywords))
   327         else:
   327         else:
   359 
   359 
   360         if braceAtCaret != -1  and braceOpposite == -1:
   360         if braceAtCaret != -1  and braceOpposite == -1:
   361             self.BraceBadLight(braceAtCaret)
   361             self.BraceBadLight(braceAtCaret)
   362         else:
   362         else:
   363             self.BraceHighlight(braceAtCaret, braceOpposite)
   363             self.BraceHighlight(braceAtCaret, braceOpposite)
   364         
   364 
   365         selected_text = self.GetSelectedText()
   365         selected_text = self.GetSelectedText()
   366         if selected_text:
   366         if selected_text:
   367             self.ParentWindow.SetCopyBuffer(selected_text, True)
   367             self.ParentWindow.SetCopyBuffer(selected_text, True)
   368     
   368 
   369     def OnMarginClick(self, event):
   369     def OnMarginClick(self, event):
   370         # fold and unfold as needed
   370         # fold and unfold as needed
   371         if evt.GetMargin() == 2:
   371         if evt.GetMargin() == 2:
   372             if evt.GetShift() and evt.GetControl():
   372             if evt.GetShift() and evt.GetControl():
   373                 self.FoldAll()
   373                 self.FoldAll()
   462         self.DisableEvents = True
   462         self.DisableEvents = True
   463         self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
   463         self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
   464         self.DisableEvents = False
   464         self.DisableEvents = False
   465         self.RefreshModel()
   465         self.RefreshModel()
   466         self.RefreshBuffer()
   466         self.RefreshBuffer()
   467     
   467 
   468     def Copy(self):
   468     def Copy(self):
   469         self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
   469         self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
   470         self.ParentWindow.RefreshEditMenu()
   470         self.ParentWindow.RefreshEditMenu()
   471     
   471 
   472     def Paste(self):
   472     def Paste(self):
   473         self.ResetBuffer()
   473         self.ResetBuffer()
   474         self.DisableEvents = True
   474         self.DisableEvents = True
   475         self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
   475         self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
   476         self.DisableEvents = False
   476         self.DisableEvents = False
   478         self.RefreshBuffer()
   478         self.RefreshBuffer()
   479 
   479 
   480     def Find(self, direction, search_params):
   480     def Find(self, direction, search_params):
   481         if self.SearchParams != search_params:
   481         if self.SearchParams != search_params:
   482             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
   482             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
   483             
   483 
   484             self.SearchParams = search_params
   484             self.SearchParams = search_params
   485             criteria = {
   485             criteria = {
   486                 "raw_pattern": search_params["find_pattern"], 
   486                 "raw_pattern": search_params["find_pattern"],
   487                 "pattern": re.compile(search_params["find_pattern"]),
   487                 "pattern": re.compile(search_params["find_pattern"]),
   488                 "case_sensitive": search_params["case_sensitive"],
   488                 "case_sensitive": search_params["case_sensitive"],
   489                 "regular_expression": search_params["regular_expression"],
   489                 "regular_expression": search_params["regular_expression"],
   490                 "filter": "all"}
   490                 "filter": "all"}
   491             
   491 
   492             self.SearchResults = [
   492             self.SearchResults = [
   493                 (start, end, SEARCH_RESULT_HIGHLIGHT)
   493                 (start, end, SEARCH_RESULT_HIGHLIGHT)
   494                 for start, end, text in 
   494                 for start, end, text in
   495                 TestTextElement(self.GetText(), criteria)]
   495                 TestTextElement(self.GetText(), criteria)]
   496             self.CurrentFindHighlight = None
   496             self.CurrentFindHighlight = None
   497         
   497 
   498         if len(self.SearchResults) > 0:
   498         if len(self.SearchResults) > 0:
   499             if self.CurrentFindHighlight is not None:
   499             if self.CurrentFindHighlight is not None:
   500                 old_idx = self.SearchResults.index(self.CurrentFindHighlight)
   500                 old_idx = self.SearchResults.index(self.CurrentFindHighlight)
   501                 if self.SearchParams["wrap"]:
   501                 if self.SearchParams["wrap"]:
   502                     idx = (old_idx + direction) % len(self.SearchResults)
   502                     idx = (old_idx + direction) % len(self.SearchResults)
   520                     if highlight_start_pos >= caret_pos:
   520                     if highlight_start_pos >= caret_pos:
   521                         self.CurrentFindHighlight = (start, end, highlight_type)
   521                         self.CurrentFindHighlight = (start, end, highlight_type)
   522                         break
   522                         break
   523                 if self.CurrentFindHighlight is not None:
   523                 if self.CurrentFindHighlight is not None:
   524                     self.AddHighlight(*self.CurrentFindHighlight)
   524                     self.AddHighlight(*self.CurrentFindHighlight)
   525             
   525 
   526             self.ScrollToLine(self.CurrentFindHighlight[0][0])
   526             self.ScrollToLine(self.CurrentFindHighlight[0][0])
   527             
   527 
   528         else:
   528         else:
   529             if self.CurrentFindHighlight is not None:
   529             if self.CurrentFindHighlight is not None:
   530                 self.RemoveHighlight(*self.CurrentFindHighlight)
   530                 self.RemoveHighlight(*self.CurrentFindHighlight)
   531             self.CurrentFindHighlight = None
   531             self.CurrentFindHighlight = None
   532 
   532 
   555             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
   555             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
   556             self.RefreshView()
   556             self.RefreshView()
   557 
   557 
   558     def RemoveHighlight(self, start, end, highlight_type):
   558     def RemoveHighlight(self, start, end, highlight_type):
   559         highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
   559         highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
   560         if (highlight_type is not None and 
   560         if (highlight_type is not None and
   561             (start, end, highlight_type) in self.Highlights):
   561             (start, end, highlight_type) in self.Highlights):
   562             self.Highlights.remove((start, end, highlight_type))
   562             self.Highlights.remove((start, end, highlight_type))
   563             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
   563             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
   564     
   564 
   565     def ShowHighlights(self):
   565     def ShowHighlights(self):
   566         for start, end, highlight_type in self.Highlights:
   566         for start, end, highlight_type in self.Highlights:
   567             if start[0] == 0:
   567             if start[0] == 0:
   568                 highlight_start_pos = start[1]
   568                 highlight_start_pos = start[1]
   569             else:
   569             else:
   581 #-------------------------------------------------------------------------------
   581 #-------------------------------------------------------------------------------
   582 #                         Helper for VariablesGrid values
   582 #                         Helper for VariablesGrid values
   583 #-------------------------------------------------------------------------------
   583 #-------------------------------------------------------------------------------
   584 
   584 
   585 class VariablesTable(CustomTable):
   585 class VariablesTable(CustomTable):
   586     
   586 
   587     def GetValue(self, row, col):
   587     def GetValue(self, row, col):
   588         if row < self.GetNumberRows():
   588         if row < self.GetNumberRows():
   589             if col == 0:
   589             if col == 0:
   590                 return row + 1
   590                 return row + 1
   591             else:
   591             else:
   592                 return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
   592                 return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
   593     
   593 
   594     def _updateColAttrs(self, grid):
   594     def _updateColAttrs(self, grid):
   595         """
   595         """
   596         wxGrid -> update the column attributes to add the
   596         wxGrid -> update the column attributes to add the
   597         appropriate renderer given the column name.
   597         appropriate renderer given the column name.
   598 
   598 
   599         Otherwise default to the default renderer.
   599         Otherwise default to the default renderer.
   600         """
   600         """
   601         
   601 
   602         typelist = None
   602         typelist = None
   603         accesslist = None
   603         accesslist = None
   604         for row in range(self.GetNumberRows()):
   604         for row in range(self.GetNumberRows()):
   605             for col in range(self.GetNumberCols()):
   605             for col in range(self.GetNumberCols()):
   606                 editor = None
   606                 editor = None
   607                 renderer = None
   607                 renderer = None
   608                 colname = self.GetColLabelValue(col, False)
   608                 colname = self.GetColLabelValue(col, False)
   609                 
   609 
   610                 if colname in ["Name", "Initial"]:
   610                 if colname in ["Name", "Initial"]:
   611                     editor = wx.grid.GridCellTextEditor()
   611                     editor = wx.grid.GridCellTextEditor()
   612                 elif colname == "Class":
   612                 elif colname == "Class":
   613                     editor = wx.grid.GridCellChoiceEditor()
   613                     editor = wx.grid.GridCellChoiceEditor()
   614                     editor.SetParameters("input,memory,output")
   614                     editor.SetParameters("input,memory,output")
   615                 elif colname == "Type":
   615                 elif colname == "Type":
   616                     pass
   616                     pass
   617                 else:
   617                 else:
   618                     grid.SetReadOnly(row, col, True)
   618                     grid.SetReadOnly(row, col, True)
   619                 
   619 
   620                 grid.SetCellEditor(row, col, editor)
   620                 grid.SetCellEditor(row, col, editor)
   621                 grid.SetCellRenderer(row, col, renderer)
   621                 grid.SetCellRenderer(row, col, renderer)
   622                 
   622 
   623                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
   623                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
   624             self.ResizeRow(grid, row)
   624             self.ResizeRow(grid, row)
   625 
   625 
   626 
   626 
   627 class VariablesEditor(wx.Panel):
   627 class VariablesEditor(wx.Panel):
   628     
   628 
   629     def __init__(self, parent, window, controler):
   629     def __init__(self, parent, window, controler):
   630         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
   630         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
   631         
   631 
   632         main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=4)
   632         main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=4)
   633         main_sizer.AddGrowableCol(1)
   633         main_sizer.AddGrowableCol(1)
   634         main_sizer.AddGrowableRow(0)
   634         main_sizer.AddGrowableRow(0)
   635         
   635 
   636         controls_sizer = wx.BoxSizer(wx.VERTICAL)
   636         controls_sizer = wx.BoxSizer(wx.VERTICAL)
   637         main_sizer.AddSizer(controls_sizer, border=5, flag=wx.ALL)
   637         main_sizer.AddSizer(controls_sizer, border=5, flag=wx.ALL)
   638         
   638 
   639         for name, bitmap, help in [
   639         for name, bitmap, help in [
   640                 ("AddVariableButton", "add_element", _("Add variable")),
   640                 ("AddVariableButton", "add_element", _("Add variable")),
   641                 ("DeleteVariableButton", "remove_element", _("Remove variable")),
   641                 ("DeleteVariableButton", "remove_element", _("Remove variable")),
   642                 ("UpVariableButton", "up", _("Move variable up")),
   642                 ("UpVariableButton", "up", _("Move variable up")),
   643                 ("DownVariableButton", "down", _("Move variable down"))]:
   643                 ("DownVariableButton", "down", _("Move variable down"))]:
   644             button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), 
   644             button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap),
   645                   size=wx.Size(28, 28), style=wx.NO_BORDER)
   645                   size=wx.Size(28, 28), style=wx.NO_BORDER)
   646             button.SetToolTipString(help)
   646             button.SetToolTipString(help)
   647             setattr(self, name, button)
   647             setattr(self, name, button)
   648             controls_sizer.AddWindow(button, border=5, flag=wx.BOTTOM)
   648             controls_sizer.AddWindow(button, border=5, flag=wx.BOTTOM)
   649         
   649 
   650         self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL)
   650         self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL)
   651         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
   651         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
   652         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
   652         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
   653         self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
   653         self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
   654         main_sizer.AddWindow(self.VariablesGrid, flag=wx.GROW)
   654         main_sizer.AddWindow(self.VariablesGrid, flag=wx.GROW)
   655         
   655 
   656         self.SetSizer(main_sizer)
   656         self.SetSizer(main_sizer)
   657                 
   657 
   658         self.ParentWindow = window
   658         self.ParentWindow = window
   659         self.Controler = controler
   659         self.Controler = controler
   660         
   660 
   661         self.VariablesDefaultValue = {"Name" : "", "Type" : "INT", "Initial": ""}
   661         self.VariablesDefaultValue = {"Name" : "", "Type" : DefaultType, "Initial": ""}
   662         self.Table = VariablesTable(self, [], ["#", "Name", "Type", "Initial"])
   662         self.Table = VariablesTable(self, [], ["#", "Name", "Type", "Initial"])
   663         self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
   663         self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
   664         self.ColSizes = [40, 200, 150, 150]
   664         self.ColSizes = [40, 200, 150, 150]
   665         self.VariablesGrid.SetTable(self.Table)
   665         self.VariablesGrid.SetTable(self.Table)
   666         self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
   666         self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
   667                                        "Delete": self.DeleteVariableButton,
   667                                        "Delete": self.DeleteVariableButton,
   668                                        "Up": self.UpVariableButton,
   668                                        "Up": self.UpVariableButton,
   669                                        "Down": self.DownVariableButton})
   669                                        "Down": self.DownVariableButton})
   670         
   670 
   671         def _AddVariable(new_row):
   671         def _AddVariable(new_row):
   672             if new_row > 0:
   672             if new_row > 0:
   673                 row_content = self.Table.data[new_row - 1].copy()
   673                 row_content = self.Table.data[new_row - 1].copy()
   674                 result = VARIABLE_NAME_SUFFIX_MODEL.search(row_content["Name"])
   674                 result = VARIABLE_NAME_SUFFIX_MODEL.search(row_content["Name"])
   675                 if result is not None:
   675                 if result is not None:
   689             self.Table.InsertRow(new_row, row_content)
   689             self.Table.InsertRow(new_row, row_content)
   690             self.RefreshModel()
   690             self.RefreshModel()
   691             self.RefreshView()
   691             self.RefreshView()
   692             return new_row
   692             return new_row
   693         setattr(self.VariablesGrid, "_AddRow", _AddVariable)
   693         setattr(self.VariablesGrid, "_AddRow", _AddVariable)
   694         
   694 
   695         def _DeleteVariable(row):
   695         def _DeleteVariable(row):
   696             self.Table.RemoveRow(row)
   696             self.Table.RemoveRow(row)
   697             self.RefreshModel()
   697             self.RefreshModel()
   698             self.RefreshView()
   698             self.RefreshView()
   699         setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
   699         setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
   700         
   700 
   701         def _MoveVariable(row, move):
   701         def _MoveVariable(row, move):
   702             new_row = self.Table.MoveRow(row, move)
   702             new_row = self.Table.MoveRow(row, move)
   703             if new_row != row:
   703             if new_row != row:
   704                 self.RefreshModel()
   704                 self.RefreshModel()
   705                 self.RefreshView()
   705                 self.RefreshView()
   706             return new_row
   706             return new_row
   707         setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
   707         setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
   708         
   708 
   709         self.VariablesGrid.SetRowLabelSize(0)
   709         self.VariablesGrid.SetRowLabelSize(0)
   710         for col in range(self.Table.GetNumberCols()):
   710         for col in range(self.Table.GetNumberCols()):
   711             attr = wx.grid.GridCellAttr()
   711             attr = wx.grid.GridCellAttr()
   712             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
   712             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
   713             self.VariablesGrid.SetColAttr(col, attr)
   713             self.VariablesGrid.SetColAttr(col, attr)
   715         self.Table.ResetView(self.VariablesGrid)
   715         self.Table.ResetView(self.VariablesGrid)
   716 
   716 
   717     def RefreshModel(self):
   717     def RefreshModel(self):
   718         self.Controler.SetVariables(self.Table.GetData())
   718         self.Controler.SetVariables(self.Table.GetData())
   719         self.RefreshBuffer()
   719         self.RefreshBuffer()
   720         
   720 
   721     # Buffer the last model state
   721     # Buffer the last model state
   722     def RefreshBuffer(self):
   722     def RefreshBuffer(self):
   723         self.Controler.BufferCodeFile()
   723         self.Controler.BufferCodeFile()
   724         self.ParentWindow.RefreshTitle()
   724         self.ParentWindow.RefreshTitle()
   725         self.ParentWindow.RefreshFileMenu()
   725         self.ParentWindow.RefreshFileMenu()
   728 
   728 
   729     def RefreshView(self):
   729     def RefreshView(self):
   730         self.Table.SetData(self.Controler.GetVariables())
   730         self.Table.SetData(self.Controler.GetVariables())
   731         self.Table.ResetView(self.VariablesGrid)
   731         self.Table.ResetView(self.VariablesGrid)
   732         self.VariablesGrid.RefreshButtons()
   732         self.VariablesGrid.RefreshButtons()
   733     
   733 
   734     def DoGetBestSize(self):
   734     def DoGetBestSize(self):
   735         return self.ParentWindow.GetPanelBestSize()
   735         return self.ParentWindow.GetPanelBestSize()
   736     
   736 
   737     def OnVariablesGridCellChange(self, event):
   737     def OnVariablesGridCellChange(self, event):
   738         row, col = event.GetRow(), event.GetCol()
   738         row, col = event.GetRow(), event.GetCol()
   739         colname = self.Table.GetColLabelValue(col, False)
   739         colname = self.Table.GetColLabelValue(col, False)
   740         value = self.Table.GetValue(row, col)
   740         value = self.Table.GetValue(row, col)
   741         message = None
   741         message = None
   742         
   742 
   743         if colname == "Name" and value != "":
   743         if colname == "Name" and value != "":
   744             if not TestIdentifier(value):
   744             if not TestIdentifier(value):
   745                 message = _("\"%s\" is not a valid identifier!") % value
   745                 message = _("\"%s\" is not a valid identifier!") % value
   746             elif value.upper() in IEC_KEYWORDS:
   746             elif value.upper() in IEC_KEYWORDS:
   747                 message = _("\"%s\" is a keyword. It can't be used!") % value
   747                 message = _("\"%s\" is a keyword. It can't be used!") % value
   748             elif value.upper() in [var["Name"].upper() 
   748             elif value.upper() in [var["Name"].upper()
   749                                    for var_row, var in enumerate(self.Table.data) 
   749                                    for var_row, var in enumerate(self.Table.data)
   750                                    if var_row != row]:
   750                                    if var_row != row]:
   751                 message = _("A variable with \"%s\" as name already exists!") % value
   751                 message = _("A variable with \"%s\" as name already exists!") % value
   752             else:
   752             else:
   753                 self.RefreshModel()
   753                 self.RefreshModel()
   754                 wx.CallAfter(self.RefreshView)
   754                 wx.CallAfter(self.RefreshView)
   755         else:
   755         else:
   756             self.RefreshModel()
   756             self.RefreshModel()
   757             wx.CallAfter(self.RefreshView)
   757             wx.CallAfter(self.RefreshView)
   758         
   758 
   759         if message is not None:
   759         if message is not None:
   760             dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   760             dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   761             dialog.ShowModal()
   761             dialog.ShowModal()
   762             dialog.Destroy()
   762             dialog.Destroy()
   763             event.Veto()
   763             event.Veto()
   764         else:
   764         else:
   765             event.Skip()
   765             event.Skip()
   766 
   766 
   767     def OnVariablesGridEditorShown(self, event):
   767     def OnVariablesGridEditorShown(self, event):
   768         row, col = event.GetRow(), event.GetCol() 
   768         row, col = event.GetRow(), event.GetCol()
   769         if self.Table.GetColLabelValue(col, False) == "Type":
   769         if self.Table.GetColLabelValue(col, False) == "Type":
   770             type_menu = wx.Menu(title='')
   770             type_menu = wx.Menu(title='')
   771             base_menu = wx.Menu(title='')
   771             base_menu = wx.Menu(title='')
   772             for base_type in self.Controler.GetBaseTypes():
   772             for base_type in self.Controler.GetBaseTypes():
   773                 new_id = wx.NewId()
   773                 new_id = wx.NewId()
   779                 new_id = wx.NewId()
   779                 new_id = wx.NewId()
   780                 datatype_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   780                 datatype_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   781                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   781                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   782             type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
   782             type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
   783             rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
   783             rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
   784             
   784 
   785             self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
   785             self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
   786             type_menu.Destroy()
   786             type_menu.Destroy()
   787             event.Veto()
   787             event.Veto()
   788         else:
   788         else:
   789             event.Skip()
   789             event.Skip()
   801     def OnVariablesGridCellLeftClick(self, event):
   801     def OnVariablesGridCellLeftClick(self, event):
   802         if event.GetCol() == 0:
   802         if event.GetCol() == 0:
   803             row = event.GetRow()
   803             row = event.GetRow()
   804             data_type = self.Table.GetValueByName(row, "Type")
   804             data_type = self.Table.GetValueByName(row, "Type")
   805             var_name = self.Table.GetValueByName(row, "Name")
   805             var_name = self.Table.GetValueByName(row, "Name")
   806             data = wx.TextDataObject(str((var_name, "Global", data_type, 
   806             data = wx.TextDataObject(str((var_name, "Global", data_type,
   807                     self.Controler.GetCurrentLocation())))
   807                     self.Controler.GetCurrentLocation())))
   808             dragSource = wx.DropSource(self.VariablesGrid)
   808             dragSource = wx.DropSource(self.VariablesGrid)
   809             dragSource.SetData(data)
   809             dragSource.SetData(data)
   810             dragSource.DoDragDrop()
   810             dragSource.DoDragDrop()
   811             return
   811             return
   812         event.Skip()
   812         event.Skip()
   813     
   813 
   814 
   814 
   815 #-------------------------------------------------------------------------------
   815 #-------------------------------------------------------------------------------
   816 #                          CodeFileEditor Main Frame Class
   816 #                          CodeFileEditor Main Frame Class
   817 #-------------------------------------------------------------------------------
   817 #-------------------------------------------------------------------------------
   818 
   818 
   819 class CodeFileEditor(ConfTreeNodeEditor):
   819 class CodeFileEditor(ConfTreeNodeEditor):
   820     
   820 
   821     CONFNODEEDITOR_TABS = []
   821     CONFNODEEDITOR_TABS = []
   822     CODE_EDITOR = None
   822     CODE_EDITOR = None
   823     
   823 
   824     def _create_CodePanel(self, prnt):
   824     def _create_CodePanel(self, prnt):
   825         self.CodeEditorPanel = wx.SplitterWindow(prnt)
   825         self.CodeEditorPanel = wx.SplitterWindow(prnt)
   826         self.CodeEditorPanel.SetMinimumPaneSize(1)
   826         self.CodeEditorPanel.SetMinimumPaneSize(1)
   827         
   827 
   828         self.VariablesPanel = VariablesEditor(self.CodeEditorPanel, 
   828         self.VariablesPanel = VariablesEditor(self.CodeEditorPanel,
   829                 self.ParentWindow, self.Controler)
   829                 self.ParentWindow, self.Controler)
   830         
   830 
   831         if self.CODE_EDITOR is not None:
   831         if self.CODE_EDITOR is not None:
   832             self.CodeEditor = self.CODE_EDITOR(self.CodeEditorPanel, 
   832             self.CodeEditor = self.CODE_EDITOR(self.CodeEditorPanel,
   833                         self.ParentWindow, self.Controler)
   833                         self.ParentWindow, self.Controler)
   834             
   834 
   835             self.CodeEditorPanel.SplitHorizontally(self.VariablesPanel, 
   835             self.CodeEditorPanel.SplitHorizontally(self.VariablesPanel,
   836                     self.CodeEditor, 150)
   836                     self.CodeEditor, 150)
   837         else:
   837         else:
   838             self.CodeEditorPanel.Initialize(self.VariablesPanel)
   838             self.CodeEditorPanel.Initialize(self.VariablesPanel)
   839         
   839 
   840         return self.CodeEditorPanel
   840         return self.CodeEditorPanel
   841     
   841 
   842     def __init__(self, parent, controler, window):
   842     def __init__(self, parent, controler, window):
   843         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   843         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   844         
   844 
   845         wx.CallAfter(self.CodeEditorPanel.SetSashPosition, 150)
   845         wx.CallAfter(self.CodeEditorPanel.SetSashPosition, 150)
   846     
   846 
   847     def GetBufferState(self):
   847     def GetBufferState(self):
   848         return self.Controler.GetBufferState()
   848         return self.Controler.GetBufferState()
   849         
   849 
   850     def Undo(self):
   850     def Undo(self):
   851         self.Controler.LoadPrevious()
   851         self.Controler.LoadPrevious()
   852         self.RefreshView()
   852         self.RefreshView()
   853             
   853 
   854     def Redo(self):
   854     def Redo(self):
   855         self.Controler.LoadNext()
   855         self.Controler.LoadNext()
   856         self.RefreshView()
   856         self.RefreshView()
   857     
   857 
   858     def RefreshView(self):
   858     def RefreshView(self):
   859         ConfTreeNodeEditor.RefreshView(self)
   859         ConfTreeNodeEditor.RefreshView(self)
   860         
   860 
   861         self.VariablesPanel.RefreshView()
   861         self.VariablesPanel.RefreshView()
   862         self.CodeEditor.RefreshView()
   862         self.CodeEditor.RefreshView()
   863     
   863 
   864     def Find(self, direction, search_params):
   864     def Find(self, direction, search_params):
   865         self.CodeEditor.Find(direction, search_params)
   865         self.CodeEditor.Find(direction, search_params)
   866         
   866