editors/TextViewer.py
changeset 1409 48f5f2a622c8
parent 1406 82db84fe88ea
child 1417 374238039643
equal deleted inserted replaced
1408:eb2aa27602b7 1409:48f5f2a622c8
     1 #!/usr/bin/env python
     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     2 # -*- coding: utf-8 -*-
     3 
     3 
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     5 #based on the plcopen standard. 
     5 #based on the plcopen standard.
     6 #
     6 #
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     8 #
     8 #
     9 #See COPYING file for copyrights details.
     9 #See COPYING file for copyrights details.
    10 #
    10 #
    43 LETTERS = ['_']
    43 LETTERS = ['_']
    44 for i in xrange(26):
    44 for i in xrange(26):
    45     LETTERS.append(chr(ord('a') + i))
    45     LETTERS.append(chr(ord('a') + i))
    46     LETTERS.append(chr(ord('A') + i))
    46     LETTERS.append(chr(ord('A') + i))
    47 
    47 
    48 [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING, 
    48 [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING,
    49  STC_PLC_VARIABLE, STC_PLC_PARAMETER, STC_PLC_FUNCTION, STC_PLC_JUMP, 
    49  STC_PLC_VARIABLE, STC_PLC_PARAMETER, STC_PLC_FUNCTION, STC_PLC_JUMP,
    50  STC_PLC_ERROR, STC_PLC_SEARCH_RESULT] = range(10)
    50  STC_PLC_ERROR, STC_PLC_SEARCH_RESULT] = range(10)
    51 [SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT, PRAGMA, DPRAGMA] = range(8)
    51 [SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT, PRAGMA, DPRAGMA] = range(8)
    52 
    52 
    53 [ID_TEXTVIEWER, ID_TEXTVIEWERTEXTCTRL,
    53 [ID_TEXTVIEWER, ID_TEXTVIEWERTEXTCTRL,
    54 ] = [wx.NewId() for _init_ctrls in range(2)]
    54 ] = [wx.NewId() for _init_ctrls in range(2)]
    68 
    68 
    69 def LineStartswith(line, symbols):
    69 def LineStartswith(line, symbols):
    70     return reduce(lambda x, y: x or y, map(lambda x: line.startswith(x), symbols), False)
    70     return reduce(lambda x, y: x or y, map(lambda x: line.startswith(x), symbols), False)
    71 
    71 
    72 class TextViewer(EditorPanel):
    72 class TextViewer(EditorPanel):
    73     
    73 
    74     ID = ID_TEXTVIEWER
    74     ID = ID_TEXTVIEWER
    75     
    75 
    76     if wx.VERSION < (2, 6, 0):
    76     if wx.VERSION < (2, 6, 0):
    77         def Bind(self, event, function, id = None):
    77         def Bind(self, event, function, id = None):
    78             if id is not None:
    78             if id is not None:
    79                 event(self, id, function)
    79                 event(self, id, function)
    80             else:
    80             else:
    81                 event(self, function)
    81                 event(self, function)
    82     
    82 
    83     def _init_Editor(self, prnt):
    83     def _init_Editor(self, prnt):
    84         self.Editor = CustomStyledTextCtrl(id=ID_TEXTVIEWERTEXTCTRL, 
    84         self.Editor = CustomStyledTextCtrl(id=ID_TEXTVIEWERTEXTCTRL,
    85                 parent=prnt, name="TextViewer", size=wx.Size(0, 0), style=0)
    85                 parent=prnt, name="TextViewer", size=wx.Size(0, 0), style=0)
    86         self.Editor.ParentWindow = self
    86         self.Editor.ParentWindow = self
    87         
    87 
    88         self.Editor.CmdKeyAssign(ord('+'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMIN)
    88         self.Editor.CmdKeyAssign(ord('+'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMIN)
    89         self.Editor.CmdKeyAssign(ord('-'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMOUT)
    89         self.Editor.CmdKeyAssign(ord('-'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMOUT)
    90         
    90 
    91         self.Editor.SetViewWhiteSpace(False)
    91         self.Editor.SetViewWhiteSpace(False)
    92         
    92 
    93         self.Editor.SetLexer(wx.stc.STC_LEX_CONTAINER)
    93         self.Editor.SetLexer(wx.stc.STC_LEX_CONTAINER)
    94         
    94 
    95         # Global default styles for all languages
    95         # Global default styles for all languages
    96         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
    96         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
    97         self.Editor.StyleClearAll()  # Reset all to be like the default
    97         self.Editor.StyleClearAll()  # Reset all to be like the default
    98         
    98 
    99         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,size:%(size)d" % faces)
    99         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,size:%(size)d" % faces)
   100         self.Editor.SetSelBackground(1, "#E0E0E0")
   100         self.Editor.SetSelBackground(1, "#E0E0E0")
   101         
   101 
   102         # Highlighting styles
   102         # Highlighting styles
   103         self.Editor.StyleSetSpec(STC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
   103         self.Editor.StyleSetSpec(STC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
   104         self.Editor.StyleSetSpec(STC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces)
   104         self.Editor.StyleSetSpec(STC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces)
   105         self.Editor.StyleSetSpec(STC_PLC_PARAMETER, "fore:#7F007F,size:%(size)d" % faces)
   105         self.Editor.StyleSetSpec(STC_PLC_PARAMETER, "fore:#7F007F,size:%(size)d" % faces)
   106         self.Editor.StyleSetSpec(STC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces)
   106         self.Editor.StyleSetSpec(STC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces)
   108         self.Editor.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
   108         self.Editor.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
   109         self.Editor.StyleSetSpec(STC_PLC_STRING, "fore:#007F00,size:%(size)d" % faces)
   109         self.Editor.StyleSetSpec(STC_PLC_STRING, "fore:#007F00,size:%(size)d" % faces)
   110         self.Editor.StyleSetSpec(STC_PLC_JUMP, "fore:#FF7FFF,size:%(size)d" % faces)
   110         self.Editor.StyleSetSpec(STC_PLC_JUMP, "fore:#FF7FFF,size:%(size)d" % faces)
   111         self.Editor.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
   111         self.Editor.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
   112         self.Editor.StyleSetSpec(STC_PLC_SEARCH_RESULT, "fore:#FFFFFF,back:#FFA500,size:%(size)d" % faces)
   112         self.Editor.StyleSetSpec(STC_PLC_SEARCH_RESULT, "fore:#FFFFFF,back:#FFA500,size:%(size)d" % faces)
   113         
   113 
   114         # Indicators styles
   114         # Indicators styles
   115         self.Editor.IndicatorSetStyle(0, wx.stc.STC_INDIC_SQUIGGLE)
   115         self.Editor.IndicatorSetStyle(0, wx.stc.STC_INDIC_SQUIGGLE)
   116         if self.ParentWindow is not None and self.Controler is not None:
   116         if self.ParentWindow is not None and self.Controler is not None:
   117             self.Editor.IndicatorSetForeground(0, wx.RED)
   117             self.Editor.IndicatorSetForeground(0, wx.RED)
   118         else:
   118         else:
   119             self.Editor.IndicatorSetForeground(0, wx.WHITE)
   119             self.Editor.IndicatorSetForeground(0, wx.WHITE)
   120         
   120 
   121         # Line numbers in the margin
   121         # Line numbers in the margin
   122         self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
   122         self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
   123         self.Editor.SetMarginWidth(1, 50)
   123         self.Editor.SetMarginWidth(1, 50)
   124         
   124 
   125         # Folding
   125         # Folding
   126         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPEN,    wx.stc.STC_MARK_BOXMINUS,          "white", "#808080")
   126         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPEN,    wx.stc.STC_MARK_BOXMINUS,          "white", "#808080")
   127         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDER,        wx.stc.STC_MARK_BOXPLUS,           "white", "#808080")
   127         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDER,        wx.stc.STC_MARK_BOXPLUS,           "white", "#808080")
   128         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERSUB,     wx.stc.STC_MARK_VLINE,             "white", "#808080")
   128         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERSUB,     wx.stc.STC_MARK_VLINE,             "white", "#808080")
   129         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERTAIL,    wx.stc.STC_MARK_LCORNER,           "white", "#808080")
   129         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERTAIL,    wx.stc.STC_MARK_LCORNER,           "white", "#808080")
   130         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEREND,     wx.stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
   130         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEREND,     wx.stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
   131         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPENMID, wx.stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
   131         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPENMID, wx.stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
   132         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERMIDTAIL, wx.stc.STC_MARK_TCORNER,           "white", "#808080")
   132         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERMIDTAIL, wx.stc.STC_MARK_TCORNER,           "white", "#808080")
   133         
   133 
   134         # Indentation size
   134         # Indentation size
   135         self.Editor.SetTabWidth(2)
   135         self.Editor.SetTabWidth(2)
   136         self.Editor.SetUseTabs(0)
   136         self.Editor.SetUseTabs(0)
   137         
   137 
   138         self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|
   138         self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|
   139                                     wx.stc.STC_MOD_BEFOREDELETE|
   139                                     wx.stc.STC_MOD_BEFOREDELETE|
   140                                     wx.stc.STC_PERFORMED_USER)
   140                                     wx.stc.STC_PERFORMED_USER)
   141 
   141 
   142         self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyleNeeded, id=ID_TEXTVIEWERTEXTCTRL)
   142         self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyleNeeded, id=ID_TEXTVIEWERTEXTCTRL)
   145         self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
   145         self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
   146         if self.Controler is not None:
   146         if self.Controler is not None:
   147             self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
   147             self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
   148             self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_TEXTVIEWERTEXTCTRL)
   148             self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_TEXTVIEWERTEXTCTRL)
   149             self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_TEXTVIEWERTEXTCTRL)
   149             self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_TEXTVIEWERTEXTCTRL)
   150         
   150 
   151     def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""):
   151     def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""):
   152         if tagname != "" and controler is not None:
   152         if tagname != "" and controler is not None:
   153             self.VARIABLE_PANEL_TYPE = controler.GetPouType(tagname.split("::")[1])
   153             self.VARIABLE_PANEL_TYPE = controler.GetPouType(tagname.split("::")[1])
   154         
   154 
   155         EditorPanel.__init__(self, parent, tagname, window, controler, debug)
   155         EditorPanel.__init__(self, parent, tagname, window, controler, debug)
   156         
   156 
   157         self.Keywords = []
   157         self.Keywords = []
   158         self.Variables = {}
   158         self.Variables = {}
   159         self.Functions = {}
   159         self.Functions = {}
   160         self.TypeNames = []
   160         self.TypeNames = []
   161         self.Jumps = []
   161         self.Jumps = []
   162         self.EnumeratedValues = []
   162         self.EnumeratedValues = []
   163         self.DisableEvents = True
   163         self.DisableEvents = True
   164         self.TextSyntax = None
   164         self.TextSyntax = None
   165         self.CurrentAction = None
   165         self.CurrentAction = None
   166         
   166 
   167         self.InstancePath = instancepath
   167         self.InstancePath = instancepath
   168         self.ContextStack = []
   168         self.ContextStack = []
   169         self.CallStack = []
   169         self.CallStack = []
   170         
   170 
   171         self.ResetSearchResults()
   171         self.ResetSearchResults()
   172         
   172 
   173         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   173         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   174         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
   174         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
   175         
   175 
   176     def __del__(self):
   176     def __del__(self):
   177         self.RefreshHighlightsTimer.Stop()
   177         self.RefreshHighlightsTimer.Stop()
   178     
   178 
   179     def GetTitle(self):
   179     def GetTitle(self):
   180         if self.Debug or self.TagName == "":
   180         if self.Debug or self.TagName == "":
   181             if len(self.InstancePath) > 15:
   181             if len(self.InstancePath) > 15:
   182                 return "..." + self.InstancePath[-12:]
   182                 return "..." + self.InstancePath[-12:]
   183             return self.InstancePath
   183             return self.InstancePath
   184         return EditorPanel.GetTitle(self)
   184         return EditorPanel.GetTitle(self)
   185     
   185 
   186     def GetInstancePath(self):
   186     def GetInstancePath(self):
   187         return self.InstancePath
   187         return self.InstancePath
   188     
   188 
   189     def IsViewing(self, tagname):
   189     def IsViewing(self, tagname):
   190         if self.Debug or self.TagName == "":
   190         if self.Debug or self.TagName == "":
   191             return self.InstancePath == tagname
   191             return self.InstancePath == tagname
   192         else:
   192         else:
   193             return self.TagName == tagname
   193             return self.TagName == tagname
   194     
   194 
   195     def GetText(self):
   195     def GetText(self):
   196         return self.Editor.GetText()
   196         return self.Editor.GetText()
   197     
   197 
   198     def SetText(self, text):
   198     def SetText(self, text):
   199         self.Editor.SetText(text)
   199         self.Editor.SetText(text)
   200     
   200 
   201     def SelectAll(self):
   201     def SelectAll(self):
   202         self.Editor.SelectAll()
   202         self.Editor.SelectAll()
   203     
   203 
   204     def Colourise(self, start, end):
   204     def Colourise(self, start, end):
   205         self.Editor.Colourise(start, end)
   205         self.Editor.Colourise(start, end)
   206     
   206 
   207     def StartStyling(self, pos, mask):
   207     def StartStyling(self, pos, mask):
   208         self.Editor.StartStyling(pos, mask)
   208         self.Editor.StartStyling(pos, mask)
   209     
   209 
   210     def SetStyling(self, length, style):
   210     def SetStyling(self, length, style):
   211         self.Editor.SetStyling(length, style)
   211         self.Editor.SetStyling(length, style)
   212     
   212 
   213     def GetCurrentPos(self):
   213     def GetCurrentPos(self):
   214         return self.Editor.GetCurrentPos()
   214         return self.Editor.GetCurrentPos()
   215     
   215 
   216     def ResetSearchResults(self):
   216     def ResetSearchResults(self):
   217         self.Highlights = []
   217         self.Highlights = []
   218         self.SearchParams = None
   218         self.SearchParams = None
   219         self.SearchResults = None
   219         self.SearchResults = None
   220         self.CurrentFindHighlight = None
   220         self.CurrentFindHighlight = None
   221     
   221 
   222     def OnModification(self, event):
   222     def OnModification(self, event):
   223         if not self.DisableEvents:
   223         if not self.DisableEvents:
   224             mod_type = event.GetModificationType()
   224             mod_type = event.GetModificationType()
   225             if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
   225             if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
   226                 if self.CurrentAction == None:
   226                 if self.CurrentAction == None:
   237                     self.Controler.EndBuffering()
   237                     self.Controler.EndBuffering()
   238                     self.StartBuffering()
   238                     self.StartBuffering()
   239                 self.CurrentAction = ("Delete", event.GetPosition())
   239                 self.CurrentAction = ("Delete", event.GetPosition())
   240                 wx.CallAfter(self.RefreshModel)
   240                 wx.CallAfter(self.RefreshModel)
   241         event.Skip()
   241         event.Skip()
   242     
   242 
   243     def OnDoDrop(self, event):
   243     def OnDoDrop(self, event):
   244         try:
   244         try:
   245             values = eval(event.GetDragText())
   245             values = eval(event.GetDragText())
   246         except:
   246         except:
   247             values = event.GetDragText()
   247             values = event.GetDragText()
   254                 blockname = values[2]
   254                 blockname = values[2]
   255                 if len(values) > 3:
   255                 if len(values) > 3:
   256                     blockinputs = values[3]
   256                     blockinputs = values[3]
   257                 else:
   257                 else:
   258                     blockinputs = None
   258                     blockinputs = None
   259                 if values[1] != "function": 
   259                 if values[1] != "function":
   260                     if blockname == "":
   260                     if blockname == "":
   261                         dialog = wx.TextEntryDialog(self.ParentWindow, "Block name", "Please enter a block name", "", wx.OK|wx.CANCEL|wx.CENTRE)
   261                         dialog = wx.TextEntryDialog(self.ParentWindow, "Block name", "Please enter a block name", "", wx.OK|wx.CANCEL|wx.CENTRE)
   262                         if dialog.ShowModal() == wx.ID_OK:
   262                         if dialog.ShowModal() == wx.ID_OK:
   263                             blockname = dialog.GetValue()
   263                             blockname = dialog.GetValue()
   264                         else:
   264                         else:
   289                     elif var_name.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
   289                     elif var_name.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
   290                         message = _("\"%s\" element for this pou already exists!")%var_name
   290                         message = _("\"%s\" element for this pou already exists!")%var_name
   291                     else:
   291                     else:
   292                         location = values[0]
   292                         location = values[0]
   293                         if not location.startswith("%"):
   293                         if not location.startswith("%"):
   294                             dialog = wx.SingleChoiceDialog(self.ParentWindow, 
   294                             dialog = wx.SingleChoiceDialog(self.ParentWindow,
   295                                   _("Select a variable class:"), _("Variable class"), 
   295                                   _("Select a variable class:"), _("Variable class"),
   296                                   ["Input", "Output", "Memory"], 
   296                                   ["Input", "Output", "Memory"],
   297                                   wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   297                                   wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   298                             if dialog.ShowModal() == wx.ID_OK:
   298                             if dialog.ShowModal() == wx.ID_OK:
   299                                 selected = dialog.GetSelection()
   299                                 selected = dialog.GetSelection()
   300                             else:
   300                             else:
   301                                 selected = None
   301                                 selected = None
   312                         if values[2] is not None:
   312                         if values[2] is not None:
   313                             var_type = values[2]
   313                             var_type = values[2]
   314                         else:
   314                         else:
   315                             var_type = LOCATIONDATATYPES.get(location[2], ["BOOL"])[0]
   315                             var_type = LOCATIONDATATYPES.get(location[2], ["BOOL"])[0]
   316                         self.Controler.AddEditedElementPouVar(self.TagName,
   316                         self.Controler.AddEditedElementPouVar(self.TagName,
   317                             var_type, var_name, 
   317                             var_type, var_name,
   318                             location=location, description=values[4])
   318                             location=location, description=values[4])
   319                         self.RefreshVariablePanel()
   319                         self.RefreshVariablePanel()
   320                         self.RefreshVariableTree()
   320                         self.RefreshVariableTree()
   321                         event.SetDragText(var_name)
   321                         event.SetDragText(var_name)
   322                 else:
   322                 else:
   323                     event.SetDragText("")
   323                     event.SetDragText("")
       
   324             elif values[1] == "NamedConstant":
       
   325                 pou_name, pou_type = self.Controler.GetEditedElementType(self.TagName, self.Debug)
       
   326                 if pou_type == "program":
       
   327                     initval = values[0]
       
   328                     var_name = values[3]
       
   329                     if var_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
       
   330                         message = _("\"%s\" pou already exists!")%var_name
       
   331                     else:
       
   332                         var_type = values[2]
       
   333                         if not var_name.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
       
   334                             self.Controler.AddEditedElementPouVar(self.TagName,
       
   335                                                                   var_type,
       
   336                                                                   var_name,
       
   337                                                                   description=values[4], initval=initval)
       
   338                             self.RefreshVariablePanel()
       
   339                             self.RefreshVariableTree()
       
   340                         event.SetDragText(var_name)
   324             elif values[1] == "Global":
   341             elif values[1] == "Global":
   325                 var_name = values[0]
   342                 var_name = values[0]
   326                 if var_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
   343                 if var_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
   327                     message = _("\"%s\" pou already exists!")%var_name
   344                     message = _("\"%s\" pou already exists!")%var_name
   328                 else:
   345                 else:
   343                 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   360                 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   344                 dialog.ShowModal()
   361                 dialog.ShowModal()
   345                 dialog.Destroy()
   362                 dialog.Destroy()
   346                 event.SetDragText("")
   363                 event.SetDragText("")
   347         event.Skip()
   364         event.Skip()
   348     
   365 
   349     def SetTextSyntax(self, syntax):
   366     def SetTextSyntax(self, syntax):
   350         self.TextSyntax = syntax
   367         self.TextSyntax = syntax
   351         if syntax in ["ST", "ALL"]:
   368         if syntax in ["ST", "ALL"]:
   352             self.Editor.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL)
   369             self.Editor.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL)
   353             self.Editor.SetMarginMask(2, wx.stc.STC_MASK_FOLDERS)
   370             self.Editor.SetMarginMask(2, wx.stc.STC_MASK_FOLDERS)
   360                 self.BlockStartKeywords = IEC_BLOCK_START_KEYWORDS
   377                 self.BlockStartKeywords = IEC_BLOCK_START_KEYWORDS
   361                 self.BlockEndKeywords = IEC_BLOCK_START_KEYWORDS
   378                 self.BlockEndKeywords = IEC_BLOCK_START_KEYWORDS
   362         else:
   379         else:
   363             self.BlockStartKeywords = []
   380             self.BlockStartKeywords = []
   364             self.BlockEndKeywords = []
   381             self.BlockEndKeywords = []
   365     
   382 
   366     def SetKeywords(self, keywords):
   383     def SetKeywords(self, keywords):
   367         self.Keywords = [keyword.upper() for keyword in keywords]
   384         self.Keywords = [keyword.upper() for keyword in keywords]
   368         self.Colourise(0, -1)
   385         self.Colourise(0, -1)
   369     
   386 
   370     def RefreshJumpList(self):
   387     def RefreshJumpList(self):
   371         if self.TextSyntax != "IL":
   388         if self.TextSyntax != "IL":
   372             self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
   389             self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
   373             self.Colourise(0, -1)
   390             self.Colourise(0, -1)
   374     
   391 
   375     # Buffer the last model state
   392     # Buffer the last model state
   376     def RefreshBuffer(self):
   393     def RefreshBuffer(self):
   377         self.Controler.BufferProject()
   394         self.Controler.BufferProject()
   378         if self.ParentWindow:
   395         if self.ParentWindow:
   379             self.ParentWindow.RefreshTitle()
   396             self.ParentWindow.RefreshTitle()
   380             self.ParentWindow.RefreshFileMenu()
   397             self.ParentWindow.RefreshFileMenu()
   381             self.ParentWindow.RefreshEditMenu()
   398             self.ParentWindow.RefreshEditMenu()
   382     
   399 
   383     def StartBuffering(self):
   400     def StartBuffering(self):
   384         self.Controler.StartBuffering()
   401         self.Controler.StartBuffering()
   385         if self.ParentWindow:
   402         if self.ParentWindow:
   386             self.ParentWindow.RefreshTitle()
   403             self.ParentWindow.RefreshTitle()
   387             self.ParentWindow.RefreshFileMenu()
   404             self.ParentWindow.RefreshFileMenu()
   388             self.ParentWindow.RefreshEditMenu()
   405             self.ParentWindow.RefreshEditMenu()
   389     
   406 
   390     def ResetBuffer(self):
   407     def ResetBuffer(self):
   391         if self.CurrentAction != None:
   408         if self.CurrentAction != None:
   392             self.Controler.EndBuffering()
   409             self.Controler.EndBuffering()
   393             self.CurrentAction = None
   410             self.CurrentAction = None
   394     
   411 
   395     def GetBufferState(self):
   412     def GetBufferState(self):
   396         if not self.Debug and self.TextSyntax != "ALL":
   413         if not self.Debug and self.TextSyntax != "ALL":
   397             return self.Controler.GetBufferState()
   414             return self.Controler.GetBufferState()
   398         return False, False
   415         return False, False
   399     
   416 
   400     def Undo(self):
   417     def Undo(self):
   401         if not self.Debug and self.TextSyntax != "ALL":
   418         if not self.Debug and self.TextSyntax != "ALL":
   402             self.Controler.LoadPrevious()
   419             self.Controler.LoadPrevious()
   403             self.ParentWindow.CloseTabsWithoutModel()
   420             self.ParentWindow.CloseTabsWithoutModel()
   404             
   421 
   405     def Redo(self):
   422     def Redo(self):
   406         if not self.Debug and self.TextSyntax != "ALL":
   423         if not self.Debug and self.TextSyntax != "ALL":
   407             self.Controler.LoadNext()
   424             self.Controler.LoadNext()
   408             self.ParentWindow.CloseTabsWithoutModel()
   425             self.ParentWindow.CloseTabsWithoutModel()
   409         
   426 
   410     def HasNoModel(self):
   427     def HasNoModel(self):
   411         if not self.Debug and self.TextSyntax != "ALL":
   428         if not self.Debug and self.TextSyntax != "ALL":
   412             return self.Controler.GetEditedElement(self.TagName) is None
   429             return self.Controler.GetEditedElement(self.TagName) is None
   413         return False
   430         return False
   414     
   431 
   415     def RefreshView(self, variablepanel=True):
   432     def RefreshView(self, variablepanel=True):
   416         EditorPanel.RefreshView(self, variablepanel)
   433         EditorPanel.RefreshView(self, variablepanel)
   417         
   434 
   418         if self.Controler is not None:
   435         if self.Controler is not None:
   419             self.ResetBuffer()
   436             self.ResetBuffer()
   420             self.DisableEvents = True
   437             self.DisableEvents = True
   421             old_cursor_pos = self.GetCurrentPos()
   438             old_cursor_pos = self.GetCurrentPos()
   422             line = self.Editor.GetFirstVisibleLine()
   439             line = self.Editor.GetFirstVisibleLine()
   432                 else:
   449                 else:
   433                     self.Editor.GotoPos(old_cursor_pos)
   450                     self.Editor.GotoPos(old_cursor_pos)
   434                 self.RefreshJumpList()
   451                 self.RefreshJumpList()
   435                 self.Editor.EmptyUndoBuffer()
   452                 self.Editor.EmptyUndoBuffer()
   436             self.DisableEvents = False
   453             self.DisableEvents = False
   437             
   454 
   438             self.RefreshVariableTree()
   455             self.RefreshVariableTree()
   439             
   456 
   440             self.TypeNames = [typename.upper() for typename in self.Controler.GetDataTypes(self.TagName, True, self.Debug)]
   457             self.TypeNames = [typename.upper() for typename in self.Controler.GetDataTypes(self.TagName, True, self.Debug)]
   441             self.EnumeratedValues = [value.upper() for value in self.Controler.GetEnumeratedDataValues()]
   458             self.EnumeratedValues = [value.upper() for value in self.Controler.GetEnumeratedDataValues()]
   442             
   459 
   443             self.Functions = {}
   460             self.Functions = {}
   444             for category in self.Controler.GetBlockTypes(self.TagName, self.Debug):
   461             for category in self.Controler.GetBlockTypes(self.TagName, self.Debug):
   445                 for blocktype in category["list"]:
   462                 for blocktype in category["list"]:
   446                     blockname = blocktype["name"].upper()
   463                     blockname = blocktype["name"].upper()
   447                     if blocktype["type"] == "function" and blockname not in self.Keywords and blockname not in self.Variables.keys():
   464                     if blocktype["type"] == "function" and blockname not in self.Keywords and blockname not in self.Variables.keys():
   453                             self.Functions[blockname]["interface"].update(interface)
   470                             self.Functions[blockname]["interface"].update(interface)
   454                             self.Functions[blockname]["extensible"] |= blocktype["extensible"]
   471                             self.Functions[blockname]["extensible"] |= blocktype["extensible"]
   455                         else:
   472                         else:
   456                             self.Functions[blockname] = {"interface": interface,
   473                             self.Functions[blockname] = {"interface": interface,
   457                                                          "extensible": blocktype["extensible"]}
   474                                                          "extensible": blocktype["extensible"]}
   458         
   475 
   459         self.Colourise(0, -1)
   476         self.Colourise(0, -1)
   460             
   477 
   461     def RefreshVariableTree(self):
   478     def RefreshVariableTree(self):
   462         words = self.TagName.split("::")
   479         words = self.TagName.split("::")
   463         self.Variables = self.GenerateVariableTree(
   480         self.Variables = self.GenerateVariableTree(
   464             [(variable.Name, variable.Type, variable.Tree) 
   481             [(variable.Name, variable.Type, variable.Tree)
   465              for variable in self.Controler.GetEditedElementInterfaceVars(
   482              for variable in self.Controler.GetEditedElementInterfaceVars(
   466                 self.TagName, True, self.Debug)])
   483                 self.TagName, True, self.Debug)])
   467         if self.Controler.GetEditedElementType(self.TagName, self.Debug)[1] == "function" or words[0] == "T" and self.TextSyntax == "IL":
   484         if self.Controler.GetEditedElementType(self.TagName, self.Debug)[1] == "function" or words[0] == "T" and self.TextSyntax == "IL":
   468             return_type, (var_tree, var_dimension) = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, True, self.Debug)
   485             return_type, (var_tree, var_dimension) = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, True, self.Debug)
   469             if return_type is not None:
   486             if return_type is not None:
   470                 self.Variables[words[-1].upper()] = self.GenerateVariableTree(var_tree)
   487                 self.Variables[words[-1].upper()] = self.GenerateVariableTree(var_tree)
   471             else:
   488             else:
   472                 self.Variables[words[-1].upper()] = {}
   489                 self.Variables[words[-1].upper()] = {}
   473     
   490 
   474     def GenerateVariableTree(self, list):
   491     def GenerateVariableTree(self, list):
   475         tree = {}
   492         tree = {}
   476         for var_name, var_type, (var_tree, var_dimension) in list:
   493         for var_name, var_type, (var_tree, var_dimension) in list:
   477             tree[var_name.upper()] = self.GenerateVariableTree(var_tree)
   494             tree[var_name.upper()] = self.GenerateVariableTree(var_tree)
   478         return tree
   495         return tree
   479     
   496 
   480     def IsValidVariable(self, name, context):
   497     def IsValidVariable(self, name, context):
   481         return context is not None and context.get(name, None) is not None
   498         return context is not None and context.get(name, None) is not None
   482 
   499 
   483     def IsCallParameter(self, name, call):
   500     def IsCallParameter(self, name, call):
   484         if call is not None:
   501         if call is not None:
   485             return (call["interface"].get(name.upper(), None) is not None or 
   502             return (call["interface"].get(name.upper(), None) is not None or
   486                     call["extensible"] and EXTENSIBLE_PARAMETER.match(name.upper()) is not None)
   503                     call["extensible"] and EXTENSIBLE_PARAMETER.match(name.upper()) is not None)
   487         return False
   504         return False
   488     
   505 
   489     def RefreshLineFolding(self, line_number):
   506     def RefreshLineFolding(self, line_number):
   490         if self.TextSyntax in ["ST", "ALL"]:
   507         if self.TextSyntax in ["ST", "ALL"]:
   491             level = wx.stc.STC_FOLDLEVELBASE + self.Editor.GetLineIndentation(line_number)
   508             level = wx.stc.STC_FOLDLEVELBASE + self.Editor.GetLineIndentation(line_number)
   492             line = self.Editor.GetLine(line_number).strip()
   509             line = self.Editor.GetLine(line_number).strip()
   493             if line == "":
   510             if line == "":
   495                     if LineStartswith(self.Editor.GetLine(line_number - 1).strip(), self.BlockEndKeywords):
   512                     if LineStartswith(self.Editor.GetLine(line_number - 1).strip(), self.BlockEndKeywords):
   496                         level = self.Editor.GetFoldLevel(self.Editor.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
   513                         level = self.Editor.GetFoldLevel(self.Editor.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
   497                     else:
   514                     else:
   498                         level = self.Editor.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
   515                         level = self.Editor.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
   499                 if level != wx.stc.STC_FOLDLEVELBASE:
   516                 if level != wx.stc.STC_FOLDLEVELBASE:
   500                     level |=  wx.stc.STC_FOLDLEVELWHITEFLAG 
   517                     level |=  wx.stc.STC_FOLDLEVELWHITEFLAG
   501             elif LineStartswith(line, self.BlockStartKeywords):
   518             elif LineStartswith(line, self.BlockStartKeywords):
   502                 level |= wx.stc.STC_FOLDLEVELHEADERFLAG
   519                 level |= wx.stc.STC_FOLDLEVELHEADERFLAG
   503             elif LineStartswith(line, self.BlockEndKeywords):
   520             elif LineStartswith(line, self.BlockEndKeywords):
   504                 if LineStartswith(self.Editor.GetLine(line_number - 1).strip(), self.BlockEndKeywords):
   521                 if LineStartswith(self.Editor.GetLine(line_number - 1).strip(), self.BlockEndKeywords):
   505                     level = self.Editor.GetFoldLevel(self.Editor.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
   522                     level = self.Editor.GetFoldLevel(self.Editor.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
   506                 else:
   523                 else:
   507                     level = self.Editor.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
   524                     level = self.Editor.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
   508             self.Editor.SetFoldLevel(line_number, level)
   525             self.Editor.SetFoldLevel(line_number, level)
   509     
   526 
   510     def OnStyleNeeded(self, event):
   527     def OnStyleNeeded(self, event):
   511         self.TextChanged = True
   528         self.TextChanged = True
   512         line_number = self.Editor.LineFromPosition(self.Editor.GetEndStyled())
   529         line_number = self.Editor.LineFromPosition(self.Editor.GetEndStyled())
   513         if line_number == 0:
   530         if line_number == 0:
   514             start_pos = last_styled_pos = 0
   531             start_pos = last_styled_pos = 0
   515         else:
   532         else:
   516             start_pos = last_styled_pos = self.Editor.GetLineEndPosition(line_number - 1) + 1
   533             start_pos = last_styled_pos = self.Editor.GetLineEndPosition(line_number - 1) + 1
   517         self.RefreshLineFolding(line_number)
   534         self.RefreshLineFolding(line_number)
   518         end_pos = event.GetPosition()
   535         end_pos = event.GetPosition()
   519         self.StartStyling(start_pos, 0xff)
   536         self.StartStyling(start_pos, 0xff)
   520         
   537 
   521         current_context = self.Variables
   538         current_context = self.Variables
   522         current_call = None
   539         current_call = None
   523         
   540 
   524         current_pos = last_styled_pos
   541         current_pos = last_styled_pos
   525         state = SPACE
   542         state = SPACE
   526         line = ""
   543         line = ""
   527         word = ""
   544         word = ""
   528         while current_pos < end_pos:
   545         while current_pos < end_pos:
   640                     elif self.IsValidVariable(word, current_context):
   657                     elif self.IsValidVariable(word, current_context):
   641                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
   658                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
   642                     elif self.IsCallParameter(word, current_call):
   659                     elif self.IsCallParameter(word, current_call):
   643                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_PARAMETER)
   660                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_PARAMETER)
   644                     elif word in self.Functions:
   661                     elif word in self.Functions:
   645                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)    
   662                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
   646                     elif self.TextSyntax == "IL" and word in self.Jumps:
   663                     elif self.TextSyntax == "IL" and word in self.Jumps:
   647                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   664                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   648                     elif word in self.EnumeratedValues:
   665                     elif word in self.EnumeratedValues:
   649                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   666                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   650                     else:
   667                     else:
   668                         current_context = self.Variables
   685                         current_context = self.Variables
   669                     else:
   686                     else:
   670                         if char == '[' and current_context is not None:
   687                         if char == '[' and current_context is not None:
   671                             self.ContextStack.append(current_context.get(word, None))
   688                             self.ContextStack.append(current_context.get(word, None))
   672                         current_context = self.Variables
   689                         current_context = self.Variables
   673                     
   690 
   674                     word = ""
   691                     word = ""
   675                     last_styled_pos = current_pos
   692                     last_styled_pos = current_pos
   676                     state = SPACE
   693                     state = SPACE
   677                 elif state == NUMBER:
   694                 elif state == NUMBER:
   678                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   695                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   715                 self.SetStyling(current_pos - last_styled_pos, 31)
   732                 self.SetStyling(current_pos - last_styled_pos, 31)
   716         else:
   733         else:
   717             self.SetStyling(current_pos - start_pos, 31)
   734             self.SetStyling(current_pos - start_pos, 31)
   718         self.ShowHighlights(start_pos, end_pos)
   735         self.ShowHighlights(start_pos, end_pos)
   719         event.Skip()
   736         event.Skip()
   720     
   737 
   721     def OnMarginClick(self, event):
   738     def OnMarginClick(self, event):
   722         if event.GetMargin() == 2:
   739         if event.GetMargin() == 2:
   723             line = self.Editor.LineFromPosition(event.GetPosition())
   740             line = self.Editor.LineFromPosition(event.GetPosition())
   724             if self.Editor.GetFoldLevel(line) & wx.stc.STC_FOLDLEVELHEADERFLAG:
   741             if self.Editor.GetFoldLevel(line) & wx.stc.STC_FOLDLEVELHEADERFLAG:
   725                 self.Editor.ToggleFold(line)
   742                 self.Editor.ToggleFold(line)
   726         event.Skip()
   743         event.Skip()
   727     
   744 
   728     def OnUpdateUI(self, event):
   745     def OnUpdateUI(self, event):
   729         selected = self.Editor.GetSelectedText()
   746         selected = self.Editor.GetSelectedText()
   730         if self.ParentWindow and selected != "":
   747         if self.ParentWindow and selected != "":
   731             self.ParentWindow.SetCopyBuffer(selected, True)
   748             self.ParentWindow.SetCopyBuffer(selected, True)
   732         event.Skip()
   749         event.Skip()
   733     
   750 
   734     def Cut(self):
   751     def Cut(self):
   735         self.ResetBuffer()
   752         self.ResetBuffer()
   736         self.DisableEvents = True
   753         self.DisableEvents = True
   737         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
   754         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
   738         self.DisableEvents = False
   755         self.DisableEvents = False
   739         self.RefreshModel()
   756         self.RefreshModel()
   740         self.RefreshBuffer()
   757         self.RefreshBuffer()
   741     
   758 
   742     def Copy(self):
   759     def Copy(self):
   743         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
   760         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
   744         if self.ParentWindow:
   761         if self.ParentWindow:
   745             self.ParentWindow.RefreshEditMenu()
   762             self.ParentWindow.RefreshEditMenu()
   746     
   763 
   747     def Paste(self):
   764     def Paste(self):
   748         self.ResetBuffer()
   765         self.ResetBuffer()
   749         self.DisableEvents = True
   766         self.DisableEvents = True
   750         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
   767         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
   751         self.DisableEvents = False
   768         self.DisableEvents = False
   752         self.RefreshModel()
   769         self.RefreshModel()
   753         self.RefreshBuffer()
   770         self.RefreshBuffer()
   754     
   771 
   755     def Search(self, criteria):
   772     def Search(self, criteria):
   756         return self.Controler.SearchInPou(self.TagName, criteria, self.Debug)
   773         return self.Controler.SearchInPou(self.TagName, criteria, self.Debug)
   757     
   774 
   758     def Find(self, direction, search_params):
   775     def Find(self, direction, search_params):
   759         if self.SearchParams != search_params:
   776         if self.SearchParams != search_params:
   760             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
   777             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
   761             
   778 
   762             self.SearchParams = search_params
   779             self.SearchParams = search_params
   763             criteria = {
   780             criteria = {
   764                 "raw_pattern": search_params["find_pattern"], 
   781                 "raw_pattern": search_params["find_pattern"],
   765                 "pattern": re.compile(search_params["find_pattern"]),
   782                 "pattern": re.compile(search_params["find_pattern"]),
   766                 "case_sensitive": search_params["case_sensitive"],
   783                 "case_sensitive": search_params["case_sensitive"],
   767                 "regular_expression": search_params["regular_expression"],
   784                 "regular_expression": search_params["regular_expression"],
   768                 "filter": "all"}
   785                 "filter": "all"}
   769             
   786 
   770             self.SearchResults = [
   787             self.SearchResults = [
   771                 (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)
   788                 (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)
   772                 for infos, start, end, text in 
   789                 for infos, start, end, text in
   773                 self.Search(criteria)]
   790                 self.Search(criteria)]
   774             self.CurrentFindHighlight = None
   791             self.CurrentFindHighlight = None
   775         
   792 
   776         if len(self.SearchResults) > 0:
   793         if len(self.SearchResults) > 0:
   777             if self.CurrentFindHighlight is not None:
   794             if self.CurrentFindHighlight is not None:
   778                 old_idx = self.SearchResults.index(self.CurrentFindHighlight)
   795                 old_idx = self.SearchResults.index(self.CurrentFindHighlight)
   779                 if self.SearchParams["wrap"]:
   796                 if self.SearchParams["wrap"]:
   780                     idx = (old_idx + direction) % len(self.SearchResults)
   797                     idx = (old_idx + direction) % len(self.SearchResults)
   785                     self.CurrentFindHighlight = self.SearchResults[idx]
   802                     self.CurrentFindHighlight = self.SearchResults[idx]
   786                     self.AddHighlight(*self.CurrentFindHighlight)
   803                     self.AddHighlight(*self.CurrentFindHighlight)
   787             else:
   804             else:
   788                 self.CurrentFindHighlight = self.SearchResults[0]
   805                 self.CurrentFindHighlight = self.SearchResults[0]
   789                 self.AddHighlight(*self.CurrentFindHighlight)
   806                 self.AddHighlight(*self.CurrentFindHighlight)
   790             
   807 
   791         else:
   808         else:
   792             if self.CurrentFindHighlight is not None:
   809             if self.CurrentFindHighlight is not None:
   793                 self.RemoveHighlight(*self.CurrentFindHighlight)
   810                 self.RemoveHighlight(*self.CurrentFindHighlight)
   794             self.CurrentFindHighlight = None
   811             self.CurrentFindHighlight = None
   795     
   812 
   796     def RefreshModel(self):
   813     def RefreshModel(self):
   797         self.RefreshJumpList()
   814         self.RefreshJumpList()
   798         self.Controler.SetEditedElementText(self.TagName, self.GetText())
   815         self.Controler.SetEditedElementText(self.TagName, self.GetText())
   799         self.ResetSearchResults()
   816         self.ResetSearchResults()
   800     
   817 
   801     def OnKeyDown(self, event):
   818     def OnKeyDown(self, event):
   802         key = event.GetKeyCode()
   819         key = event.GetKeyCode()
   803         if self.Controler is not None:
   820         if self.Controler is not None:
   804         
   821 
   805             if self.Editor.CallTipActive():
   822             if self.Editor.CallTipActive():
   806                 self.Editor.CallTipCancel()
   823                 self.Editor.CallTipCancel()
   807             
   824 
   808             key_handled = False
   825             key_handled = False
   809 
   826 
   810             line = self.Editor.GetCurrentLine()
   827             line = self.Editor.GetCurrentLine()
   811             if line == 0:
   828             if line == 0:
   812                 start_pos = 0
   829                 start_pos = 0
   813             else:
   830             else:
   814                 start_pos = self.Editor.GetLineEndPosition(line - 1) + 1
   831                 start_pos = self.Editor.GetLineEndPosition(line - 1) + 1
   815             end_pos = self.GetCurrentPos()
   832             end_pos = self.GetCurrentPos()
   816             lineText = self.Editor.GetTextRange(start_pos, end_pos).replace("\t", " ")
   833             lineText = self.Editor.GetTextRange(start_pos, end_pos).replace("\t", " ")
   817             
   834 
   818             # Code completion
   835             # Code completion
   819             if key == wx.WXK_SPACE and event.ControlDown():
   836             if key == wx.WXK_SPACE and event.ControlDown():
   820                 
   837 
   821                 words = lineText.split(" ")
   838                 words = lineText.split(" ")
   822                 words = [word for i, word in enumerate(words) if word != '' or i == len(words) - 1]
   839                 words = [word for i, word in enumerate(words) if word != '' or i == len(words) - 1]
   823                             
   840 
   824                 kw = []
   841                 kw = []
   825                 
   842 
   826                 if self.TextSyntax == "IL":
   843                 if self.TextSyntax == "IL":
   827                     if len(words) == 1:
   844                     if len(words) == 1:
   828                         kw = self.Keywords
   845                         kw = self.Keywords
   829                     elif len(words) == 2:
   846                     elif len(words) == 2:
   830                         if words[0].upper() in ["CAL", "CALC", "CALNC"]:
   847                         if words[0].upper() in ["CAL", "CALC", "CALNC"]:
   873         self.RefreshView()
   890         self.RefreshView()
   874         event.Skip()
   891         event.Skip()
   875 
   892 
   876     def ClearHighlights(self, highlight_type=None):
   893     def ClearHighlights(self, highlight_type=None):
   877         EditorPanel.ClearHighlights(self, highlight_type)
   894         EditorPanel.ClearHighlights(self, highlight_type)
   878         
   895 
   879         if highlight_type is None:
   896         if highlight_type is None:
   880             self.Highlights = []
   897             self.Highlights = []
   881         else:
   898         else:
   882             highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
   899             highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
   883             if highlight_type is not None:
   900             if highlight_type is not None:
   884                 self.Highlights = [(infos, start, end, highlight) for (infos, start, end, highlight) in self.Highlights if highlight != highlight_type]
   901                 self.Highlights = [(infos, start, end, highlight) for (infos, start, end, highlight) in self.Highlights if highlight != highlight_type]
   885         self.RefreshView()
   902         self.RefreshView()
   886 
   903 
   887     def AddHighlight(self, infos, start, end, highlight_type):
   904     def AddHighlight(self, infos, start, end, highlight_type):
   888         EditorPanel.AddHighlight(self, infos, start, end, highlight_type)
   905         EditorPanel.AddHighlight(self, infos, start, end, highlight_type)
   889         
   906 
   890         highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
   907         highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
   891         if infos[0] == "body" and highlight_type is not None:
   908         if infos[0] == "body" and highlight_type is not None:
   892             self.Highlights.append((infos[1], start, end, highlight_type))
   909             self.Highlights.append((infos[1], start, end, highlight_type))
   893             self.Editor.GotoPos(self.Editor.PositionFromLine(start[0]) + start[1])
   910             self.Editor.GotoPos(self.Editor.PositionFromLine(start[0]) + start[1])
   894             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
   911             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
   895 
   912 
   896     def RemoveHighlight(self, infos, start, end, highlight_type):
   913     def RemoveHighlight(self, infos, start, end, highlight_type):
   897         EditorPanel.RemoveHighlight(self, infos, start, end, highlight_type)
   914         EditorPanel.RemoveHighlight(self, infos, start, end, highlight_type)
   898         
   915 
   899         highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
   916         highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
   900         if (infos[0] == "body" and highlight_type is not None and 
   917         if (infos[0] == "body" and highlight_type is not None and
   901             (infos[1], start, end, highlight_type) in self.Highlights):
   918             (infos[1], start, end, highlight_type) in self.Highlights):
   902             self.Highlights.remove((infos[1], start, end, highlight_type))
   919             self.Highlights.remove((infos[1], start, end, highlight_type))
   903             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
   920             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
   904     
   921 
   905     def ShowHighlights(self, start_pos, end_pos):
   922     def ShowHighlights(self, start_pos, end_pos):
   906         for indent, start, end, highlight_type in self.Highlights:
   923         for indent, start, end, highlight_type in self.Highlights:
   907             if start[0] == 0:
   924             if start[0] == 0:
   908                 highlight_start_pos = start[1] - indent
   925                 highlight_start_pos = start[1] - indent
   909             else:
   926             else:
   915             if highlight_start_pos < end_pos and highlight_end_pos > start_pos:
   932             if highlight_start_pos < end_pos and highlight_end_pos > start_pos:
   916                 self.StartStyling(highlight_start_pos, 0xff)
   933                 self.StartStyling(highlight_start_pos, 0xff)
   917                 self.SetStyling(highlight_end_pos - highlight_start_pos, highlight_type)
   934                 self.SetStyling(highlight_end_pos - highlight_start_pos, highlight_type)
   918                 self.StartStyling(highlight_start_pos, 0x00)
   935                 self.StartStyling(highlight_start_pos, 0x00)
   919                 self.SetStyling(len(self.Editor.GetText()) - highlight_end_pos, wx.stc.STC_STYLE_DEFAULT)
   936                 self.SetStyling(len(self.Editor.GetText()) - highlight_end_pos, wx.stc.STC_STYLE_DEFAULT)
   920                 
   937