TextViewer.py
changeset 586 9aa96a36cf33
parent 582 aa41547baa2a
child 589 e3a1d9a59c97
equal deleted inserted replaced
585:bd8c7a033b17 586:9aa96a36cf33
    27 from types import *
    27 from types import *
    28 
    28 
    29 import re
    29 import re
    30 
    30 
    31 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
    31 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
    32 from plcopen.structures import ST_BLOCK_START_KEYWORDS, ST_BLOCK_END_KEYWORDS
    32 from plcopen.structures import ST_BLOCK_START_KEYWORDS, ST_BLOCK_END_KEYWORDS, IEC_BLOCK_START_KEYWORDS, IEC_BLOCK_END_KEYWORDS
       
    33 from controls import EditorPanel
    33 
    34 
    34 #-------------------------------------------------------------------------------
    35 #-------------------------------------------------------------------------------
    35 #                         Textual programs Viewer class
    36 #                         Textual programs Viewer class
    36 #-------------------------------------------------------------------------------
    37 #-------------------------------------------------------------------------------
    37 
    38 
    46 [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING, 
    47 [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING, 
    47  STC_PLC_VARIABLE, STC_PLC_PARAMETER, STC_PLC_FUNCTION, STC_PLC_JUMP, 
    48  STC_PLC_VARIABLE, STC_PLC_PARAMETER, STC_PLC_FUNCTION, STC_PLC_JUMP, 
    48  STC_PLC_ERROR, STC_PLC_SEARCH_RESULT] = range(10)
    49  STC_PLC_ERROR, STC_PLC_SEARCH_RESULT] = range(10)
    49 [SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT] = range(6)
    50 [SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT] = range(6)
    50 
    51 
    51 [ID_TEXTVIEWER,
    52 [ID_TEXTVIEWER, ID_TEXTVIEWERTEXTCTRL,
    52 ] = [wx.NewId() for _init_ctrls in range(1)]
    53 ] = [wx.NewId() for _init_ctrls in range(2)]
    53 
    54 
    54 if wx.Platform == '__WXMSW__':
    55 if wx.Platform == '__WXMSW__':
    55     faces = { 'times': 'Times New Roman',
    56     faces = { 'times': 'Times New Roman',
    56               'mono' : 'Courier New',
    57               'mono' : 'Courier New',
    57               'helv' : 'Arial',
    58               'helv' : 'Arial',
   100         return None
   101         return None
   101 
   102 
   102 def LineStartswith(line, symbols):
   103 def LineStartswith(line, symbols):
   103     return reduce(lambda x, y: x or y, map(lambda x: line.startswith(x), symbols), False)
   104     return reduce(lambda x, y: x or y, map(lambda x: line.startswith(x), symbols), False)
   104 
   105 
   105 class TextViewer(wx.stc.StyledTextCtrl):
   106 class TextViewer(EditorPanel):
       
   107     
       
   108     ID = ID_TEXTVIEWER
   106     
   109     
   107     if wx.VERSION < (2, 6, 0):
   110     if wx.VERSION < (2, 6, 0):
   108         def Bind(self, event, function, id = None):
   111         def Bind(self, event, function, id = None):
   109             if id is not None:
   112             if id is not None:
   110                 event(self, id, function)
   113                 event(self, id, function)
   111             else:
   114             else:
   112                 event(self, function)
   115                 event(self, function)
   113     
   116     
       
   117     def _init_Editor(self, prnt):
       
   118         self.Editor = wx.stc.StyledTextCtrl(id=ID_TEXTVIEWERTEXTCTRL, 
       
   119                 parent=prnt, name="TextViewer", size=wx.Size(0, 0), style=0)
       
   120         
       
   121         self.Editor.CmdKeyAssign(ord('+'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMIN)
       
   122         self.Editor.CmdKeyAssign(ord('-'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMOUT)
       
   123         
       
   124         self.Editor.SetViewWhiteSpace(False)
       
   125         
       
   126         self.Editor.SetLexer(wx.stc.STC_LEX_CONTAINER)
       
   127         
       
   128         # Global default styles for all languages
       
   129         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
       
   130         self.Editor.StyleClearAll()  # Reset all to be like the default
       
   131         
       
   132         self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,size:%(size)d" % faces)
       
   133         self.Editor.SetSelBackground(1, "#E0E0E0")
       
   134         
       
   135         # Highlighting styles
       
   136         self.Editor.StyleSetSpec(STC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
       
   137         self.Editor.StyleSetSpec(STC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces)
       
   138         self.Editor.StyleSetSpec(STC_PLC_PARAMETER, "fore:#7F007F,size:%(size)d" % faces)
       
   139         self.Editor.StyleSetSpec(STC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces)
       
   140         self.Editor.StyleSetSpec(STC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces)
       
   141         self.Editor.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
       
   142         self.Editor.StyleSetSpec(STC_PLC_STRING, "fore:#007F00,size:%(size)d" % faces)
       
   143         self.Editor.StyleSetSpec(STC_PLC_JUMP, "fore:#FF7FFF,size:%(size)d" % faces)
       
   144         self.Editor.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
       
   145         self.Editor.StyleSetSpec(STC_PLC_SEARCH_RESULT, "fore:#FFFFFF,back:#FFA500,size:%(size)d" % faces)
       
   146         
       
   147         # Indicators styles
       
   148         self.Editor.IndicatorSetStyle(0, wx.stc.STC_INDIC_SQUIGGLE)
       
   149         if self.ParentWindow is not None and self.Controler is not None:
       
   150             self.Editor.IndicatorSetForeground(0, wx.RED)
       
   151         else:
       
   152             self.Editor.IndicatorSetForeground(0, wx.WHITE)
       
   153         
       
   154         # Line numbers in the margin
       
   155         self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
       
   156         self.Editor.SetMarginWidth(1, 50)
       
   157         
       
   158         # Folding
       
   159         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPEN,    wx.stc.STC_MARK_BOXMINUS,          "white", "#808080")
       
   160         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDER,        wx.stc.STC_MARK_BOXPLUS,           "white", "#808080")
       
   161         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERSUB,     wx.stc.STC_MARK_VLINE,             "white", "#808080")
       
   162         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERTAIL,    wx.stc.STC_MARK_LCORNER,           "white", "#808080")
       
   163         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEREND,     wx.stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
       
   164         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPENMID, wx.stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
       
   165         self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERMIDTAIL, wx.stc.STC_MARK_TCORNER,           "white", "#808080")
       
   166         
       
   167         # Indentation size
       
   168         self.Editor.SetTabWidth(2)
       
   169         self.Editor.SetUseTabs(0)
       
   170         
       
   171         self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|
       
   172                                     wx.stc.STC_MOD_BEFOREDELETE|
       
   173                                     wx.stc.STC_PERFORMED_USER)
       
   174 
       
   175         self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyleNeeded, id=ID_TEXTVIEWERTEXTCTRL)
       
   176         self.Editor.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
       
   177         self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
       
   178         if self.Controler is not None:
       
   179             self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
       
   180             self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_TEXTVIEWERTEXTCTRL)
       
   181             self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_TEXTVIEWERTEXTCTRL)
       
   182         
   114     def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""):
   183     def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""):
   115         wx.stc.StyledTextCtrl.__init__(self, parent, ID_TEXTVIEWER, size=wx.Size(0, 0), style=0)
   184         if tagname != "" and controler is not None:
   116         
   185             self.VARIABLE_PANEL_TYPE = controler.GetPouType(tagname.split("::")[1])
   117         self.CmdKeyAssign(ord('+'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMIN)
   186         
   118         self.CmdKeyAssign(ord('-'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMOUT)
   187         EditorPanel.__init__(self, parent, tagname, window, controler)
   119         
       
   120         self.SetViewWhiteSpace(False)
       
   121         
       
   122         self.SetLexer(wx.stc.STC_LEX_CONTAINER)
       
   123         
       
   124         # Global default styles for all languages
       
   125         self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
       
   126         self.StyleClearAll()  # Reset all to be like the default
       
   127         
       
   128         self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,size:%(size)d" % faces)
       
   129         self.SetSelBackground(1, "#E0E0E0")
       
   130         
       
   131         # Highlighting styles
       
   132         self.StyleSetSpec(STC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
       
   133         self.StyleSetSpec(STC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces)
       
   134         self.StyleSetSpec(STC_PLC_PARAMETER, "fore:#7F007F,size:%(size)d" % faces)
       
   135         self.StyleSetSpec(STC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces)
       
   136         self.StyleSetSpec(STC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces)
       
   137         self.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
       
   138         self.StyleSetSpec(STC_PLC_STRING, "fore:#007F00,size:%(size)d" % faces)
       
   139         self.StyleSetSpec(STC_PLC_JUMP, "fore:#FF7FFF,size:%(size)d" % faces)
       
   140         self.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
       
   141         self.StyleSetSpec(STC_PLC_SEARCH_RESULT, "fore:#FFFFFF,back:#FFA500,size:%(size)d" % faces)
       
   142         
       
   143         # Indicators styles
       
   144         self.IndicatorSetStyle(0, wx.stc.STC_INDIC_SQUIGGLE)
       
   145         if window and controler:
       
   146             self.IndicatorSetForeground(0, wx.RED)
       
   147         else:
       
   148             self.IndicatorSetForeground(0, wx.WHITE)
       
   149         
       
   150         # Line numbers in the margin
       
   151         self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
       
   152         self.SetMarginWidth(1, 50)
       
   153         
       
   154         # Folding
       
   155         self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPEN,    wx.stc.STC_MARK_BOXMINUS,          "white", "#808080")
       
   156         self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDER,        wx.stc.STC_MARK_BOXPLUS,           "white", "#808080")
       
   157         self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERSUB,     wx.stc.STC_MARK_VLINE,             "white", "#808080")
       
   158         self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERTAIL,    wx.stc.STC_MARK_LCORNER,           "white", "#808080")
       
   159         self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEREND,     wx.stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
       
   160         self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPENMID, wx.stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
       
   161         self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERMIDTAIL, wx.stc.STC_MARK_TCORNER,           "white", "#808080")
       
   162         
       
   163         # Indentation size
       
   164         self.SetTabWidth(2)
       
   165         self.SetUseTabs(0)
       
   166         
   188         
   167         self.Keywords = []
   189         self.Keywords = []
   168         self.Variables = {}
   190         self.Variables = {}
   169         self.Functions = {}
   191         self.Functions = {}
   170         self.TypeNames = []
   192         self.TypeNames = []
   171         self.Jumps = []
   193         self.Jumps = []
   172         self.EnumeratedValues = []
   194         self.EnumeratedValues = []
   173         self.DisableEvents = True
   195         self.DisableEvents = True
   174         self.TextSyntax = "ST"
   196         self.TextSyntax = None
   175         self.CurrentAction = None
   197         self.CurrentAction = None
   176         self.TagName = tagname
       
   177         self.Highlights = []
   198         self.Highlights = []
   178         self.Debug = debug
   199         self.Debug = debug
   179         self.InstancePath = instancepath
   200         self.InstancePath = instancepath
   180         self.ContextStack = []
   201         self.ContextStack = []
   181         self.CallStack = []
   202         self.CallStack = []
   182         
   203         
   183         self.ParentWindow = window
       
   184         self.Controler = controler
       
   185 
       
   186         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   204         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   187         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
   205         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
   188 
       
   189         self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|
       
   190                              wx.stc.STC_MOD_BEFOREDELETE|
       
   191                              wx.stc.STC_PERFORMED_USER)
       
   192 
       
   193         self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyleNeeded, id=ID_TEXTVIEWER)
       
   194         self.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
       
   195         if controler:
       
   196             self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
       
   197             self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_TEXTVIEWER)
       
   198             self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
       
   199             self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_TEXTVIEWER)
       
   200     
   206     
   201     def __del__(self):
   207     def __del__(self):
   202         self.RefreshHighlightsTimer.Stop()
   208         self.RefreshHighlightsTimer.Stop()
   203     
   209     
   204     def SetTagName(self, tagname):
   210     def GetTitle(self):
   205         self.TagName = tagname
   211         if self.Debug or self.TagName == "":
   206         
   212             if len(self.InstancePath) > 15:
   207     def GetTagName(self):
   213                 return "..." + self.InstancePath[-12:]
   208         return self.TagName
   214             return self.InstancePath
       
   215         return EditorPanel.GetTitle(self)
   209     
   216     
   210     def GetInstancePath(self):
   217     def GetInstancePath(self):
   211         return self.InstancePath
   218         return self.InstancePath
   212     
   219     
   213     def IsViewing(self, tagname):
   220     def IsViewing(self, tagname):
   214         if self.Debug:
   221         if self.Debug or self.TagName == "":
   215             return self.InstancePath == tagname
   222             return self.InstancePath == tagname
   216         else:
   223         else:
   217             return self.TagName == tagname
   224             return self.TagName == tagname
   218     
   225     
   219     def IsDebugging(self):
   226     def IsDebugging(self):
   220         return self.Debug
   227         return self.Debug
   221     
   228     
   222     def SetMode(self, mode):
   229     def GetText(self):
   223         pass
   230         return self.Editor.GetText()
       
   231     
       
   232     def SetText(self, text):
       
   233         self.Editor.SetText(text)
       
   234     
       
   235     def SelectAll(self):
       
   236         self.Editor.SelectAll()
       
   237     
       
   238     def Colourise(self, start, end):
       
   239         self.Editor.Colourise(start, end)
       
   240     
       
   241     def StartStyling(self, pos, mask):
       
   242         self.Editor.StartStyling(pos, mask)
       
   243     
       
   244     def SetStyling(self, length, style):
       
   245         self.Editor.SetStyling(length, style)
       
   246     
       
   247     def GetCurrentPos(self):
       
   248         return self.Editor.GetCurrentPos()
   224     
   249     
   225     def OnModification(self, event):
   250     def OnModification(self, event):
   226         if not self.DisableEvents:
   251         if not self.DisableEvents:
   227             mod_type = event.GetModificationType()
   252             mod_type = event.GetModificationType()
   228             if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
   253             if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
   270                         message = _("\"%s\" pou already exists!")%blockname
   295                         message = _("\"%s\" pou already exists!")%blockname
   271                     elif blockname.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
   296                     elif blockname.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
   272                         message = _("\"%s\" element for this pou already exists!")%blockname
   297                         message = _("\"%s\" element for this pou already exists!")%blockname
   273                     else:
   298                     else:
   274                         self.Controler.AddEditedElementPouVar(self.TagName, values[0], blockname)
   299                         self.Controler.AddEditedElementPouVar(self.TagName, values[0], blockname)
   275                         self.ParentWindow.RefreshVariablePanel(self.TagName)
   300                         self.RefreshVariablePanel()
   276                         self.RefreshVariableTree()
   301                         self.RefreshVariableTree()
   277                 blockinfo = self.Controler.GetBlockType(values[0], blockinputs, self.Debug)
   302                 blockinfo = self.Controler.GetBlockType(values[0], blockinputs, self.Debug)
   278                 hint = ',\n    '.join(
   303                 hint = ',\n    '.join(
   279                             [ " " + fctdecl[0]+" := (*"+fctdecl[1]+"*)" for fctdecl in blockinfo["inputs"]] +
   304                             [ " " + fctdecl[0]+" := (*"+fctdecl[1]+"*)" for fctdecl in blockinfo["inputs"]] +
   280                             [ " " + fctdecl[0]+" => (*"+fctdecl[1]+"*)" for fctdecl in blockinfo["outputs"]])
   305                             [ " " + fctdecl[0]+" => (*"+fctdecl[1]+"*)" for fctdecl in blockinfo["outputs"]])
   291                         if values[2] is not None:
   316                         if values[2] is not None:
   292                             var_type = values[2]
   317                             var_type = values[2]
   293                         else:
   318                         else:
   294                             var_type = LOCATIONDATATYPES.get(values[0][2], ["BOOL"])[0]
   319                             var_type = LOCATIONDATATYPES.get(values[0][2], ["BOOL"])[0]
   295                         self.Controler.AddEditedElementPouVar(self.TagName, var_type, var_name, values[0], values[4])
   320                         self.Controler.AddEditedElementPouVar(self.TagName, var_type, var_name, values[0], values[4])
   296                         self.ParentWindow.RefreshVariablePanel(self.TagName)
   321                         self.RefreshVariablePanel()
   297                         self.RefreshVariableTree()
   322                         self.RefreshVariableTree()
   298                         event.SetDragText(var_name)
   323                         event.SetDragText(var_name)
   299                 else:
   324                 else:
   300                     event.SetDragText("")
   325                     event.SetDragText("")
   301             elif values[3] == self.TagName:
   326             elif values[3] == self.TagName:
   311                 event.SetDragText("")
   336                 event.SetDragText("")
   312         event.Skip()
   337         event.Skip()
   313     
   338     
   314     def SetTextSyntax(self, syntax):
   339     def SetTextSyntax(self, syntax):
   315         self.TextSyntax = syntax
   340         self.TextSyntax = syntax
   316         if syntax == "ST":
   341         if syntax in ["ST", "ALL"]:
   317             self.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL)
   342             self.Editor.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL)
   318             self.SetMarginMask(2, wx.stc.STC_MASK_FOLDERS)
   343             self.Editor.SetMarginMask(2, wx.stc.STC_MASK_FOLDERS)
   319             self.SetMarginSensitive(2, 1)
   344             self.Editor.SetMarginSensitive(2, 1)
   320             self.SetMarginWidth(2, 12)
   345             self.Editor.SetMarginWidth(2, 12)
       
   346             if syntax == "ST":
       
   347                 self.BlockStartKeywords = ST_BLOCK_START_KEYWORDS
       
   348                 self.BlockEndKeywords = ST_BLOCK_START_KEYWORDS
       
   349             else:
       
   350                 self.BlockStartKeywords = IEC_BLOCK_START_KEYWORDS
       
   351                 self.BlockEndKeywords = IEC_BLOCK_START_KEYWORDS
       
   352         else:
       
   353             self.BlockStartKeywords = []
       
   354             self.BlockEndKeywords = []
   321     
   355     
   322     def SetKeywords(self, keywords):
   356     def SetKeywords(self, keywords):
   323         self.Keywords = [keyword.upper() for keyword in keywords]
   357         self.Keywords = [keyword.upper() for keyword in keywords]
   324         self.Colourise(0, -1)
   358         self.Colourise(0, -1)
   325     
   359     
   346     def ResetBuffer(self):
   380     def ResetBuffer(self):
   347         if self.CurrentAction != None:
   381         if self.CurrentAction != None:
   348             self.Controler.EndBuffering()
   382             self.Controler.EndBuffering()
   349             self.CurrentAction = None
   383             self.CurrentAction = None
   350     
   384     
   351     def RefreshView(self):
   385     def GetBufferState(self):
   352         self.ResetBuffer()
   386         if not self.Debug and self.TextSyntax != "ALL":
   353         self.DisableEvents = True
   387             return self.Controler.GetBufferState()
   354         old_cursor_pos = self.GetCurrentPos()
   388         return False, False
   355         old_text = self.GetText()
   389     
   356         new_text = self.Controler.GetEditedElementText(self.TagName, self.Debug)
   390     def Undo(self):
   357         self.SetText(new_text)
   391         if not self.Debug and self.TextSyntax != "ALL":
   358         new_cursor_pos = GetCursorPos(old_text, new_text)
   392             self.Controler.LoadPrevious()
   359         if new_cursor_pos != None:
   393             self.ParentWindow.CloseTabsWithoutModel()
   360             self.GotoPos(new_cursor_pos)
   394             self.ParentWindow.RefreshEditor()
   361         else:
   395             
   362             self.GotoPos(old_cursor_pos)
   396     def Redo(self):
   363         self.ScrollToColumn(0)
   397         if not self.Debug and self.TextSyntax != "ALL":
   364         self.RefreshJumpList()
   398             self.Controler.LoadNext()
   365         self.EmptyUndoBuffer()
   399             self.ParentWindow.CloseTabsWithoutModel()
   366         self.DisableEvents = False
   400             self.ParentWindow.RefreshEditor()
   367         
   401     
   368         self.RefreshVariableTree()
   402     def HasNoModel(self):
   369         
   403         if not self.Debug and self.TextSyntax != "ALL":
   370         self.TypeNames = [typename.upper() for typename in self.Controler.GetDataTypes(self.TagName, True, self.Debug)]
   404             return self.Controler.GetEditedElement(self.TagName) is None
   371         self.EnumeratedValues = [value.upper() for value in self.Controler.GetEnumeratedDataValues()]
   405         return False
   372         
   406     
   373         self.Functions = {}
   407     def RefreshView(self, variablepanel=True):
   374         for category in self.Controler.GetBlockTypes(self.TagName, self.Debug):
   408         EditorPanel.RefreshView(self, variablepanel)
   375             for blocktype in category["list"]:
   409         
   376                 blockname = blocktype["name"].upper()
   410         if self.Controler is not None:
   377                 if blocktype["type"] == "function" and blockname not in self.Keywords and blockname not in self.Variables.keys():
   411             self.ResetBuffer()
   378                     interface = dict([(name, {}) for name, type, modifier in blocktype["inputs"] + blocktype["outputs"] if name != ''])
   412             self.DisableEvents = True
   379                     for param in ["EN", "ENO"]:
   413             old_cursor_pos = self.GetCurrentPos()
   380                         if not interface.has_key(param):
   414             old_text = self.GetText()
   381                             interface[param] = {}
   415             new_text = self.Controler.GetEditedElementText(self.TagName, self.Debug)
   382                     if self.Functions.has_key(blockname):
   416             self.SetText(new_text)
   383                         self.Functions[blockname]["interface"].update(interface)
   417             new_cursor_pos = GetCursorPos(old_text, new_text)
   384                         self.Functions[blockname]["extensible"] |= blocktype["extensible"]
   418             if new_cursor_pos != None:
   385                     else:
   419                 self.Editor.GotoPos(new_cursor_pos)
   386                         self.Functions[blockname] = {"interface": interface,
   420             else:
   387                                                      "extensible": blocktype["extensible"]}
   421                 self.Editor.GotoPos(old_cursor_pos)
       
   422             self.Editor.ScrollToColumn(0)
       
   423             self.RefreshJumpList()
       
   424             self.Editor.EmptyUndoBuffer()
       
   425             self.DisableEvents = False
       
   426             
       
   427             self.RefreshVariableTree()
       
   428             
       
   429             self.TypeNames = [typename.upper() for typename in self.Controler.GetDataTypes(self.TagName, True, self.Debug)]
       
   430             self.EnumeratedValues = [value.upper() for value in self.Controler.GetEnumeratedDataValues()]
       
   431             
       
   432             self.Functions = {}
       
   433             for category in self.Controler.GetBlockTypes(self.TagName, self.Debug):
       
   434                 for blocktype in category["list"]:
       
   435                     blockname = blocktype["name"].upper()
       
   436                     if blocktype["type"] == "function" and blockname not in self.Keywords and blockname not in self.Variables.keys():
       
   437                         interface = dict([(name, {}) for name, type, modifier in blocktype["inputs"] + blocktype["outputs"] if name != ''])
       
   438                         for param in ["EN", "ENO"]:
       
   439                             if not interface.has_key(param):
       
   440                                 interface[param] = {}
       
   441                         if self.Functions.has_key(blockname):
       
   442                             self.Functions[blockname]["interface"].update(interface)
       
   443                             self.Functions[blockname]["extensible"] |= blocktype["extensible"]
       
   444                         else:
       
   445                             self.Functions[blockname] = {"interface": interface,
       
   446                                                          "extensible": blocktype["extensible"]}
       
   447         
   388         self.Colourise(0, -1)
   448         self.Colourise(0, -1)
   389             
   449             
   390     def RefreshVariableTree(self):
   450     def RefreshVariableTree(self):
   391         words = self.TagName.split("::")
   451         words = self.TagName.split("::")
   392         self.Variables = self.GenerateVariableTree([(variable["Name"], variable["Type"], variable["Tree"]) for variable in self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)])
   452         self.Variables = self.GenerateVariableTree([(variable["Name"], variable["Type"], variable["Tree"]) for variable in self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)])
   402         tree = {}
   462         tree = {}
   403         for var_name, var_type, (var_tree, var_dimension) in list:
   463         for var_name, var_type, (var_tree, var_dimension) in list:
   404             tree[var_name.upper()] = self.GenerateVariableTree(var_tree)
   464             tree[var_name.upper()] = self.GenerateVariableTree(var_tree)
   405         return tree
   465         return tree
   406     
   466     
   407     def RefreshScaling(self, refresh=True):
       
   408         pass
       
   409     
       
   410     def IsValidVariable(self, name, context):
   467     def IsValidVariable(self, name, context):
   411         return context is not None and context.get(name, None) is not None
   468         return context is not None and context.get(name, None) is not None
   412 
   469 
   413     def IsCallParameter(self, name, call):
   470     def IsCallParameter(self, name, call):
   414         if call is not None:
   471         if call is not None:
   415             return (call["interface"].get(name.upper(), None) is not None or 
   472             return (call["interface"].get(name.upper(), None) is not None or 
   416                     call["extensible"] and EXTENSIBLE_PARAMETER.match(name.upper()) is not None)
   473                     call["extensible"] and EXTENSIBLE_PARAMETER.match(name.upper()) is not None)
   417         return False
   474         return False
   418     
   475     
   419     def RefreshLineFolding(self, line_number):
   476     def RefreshLineFolding(self, line_number):
   420         if self.TextSyntax == "ST":
   477         if self.TextSyntax in ["ST", "ALL"]:
   421             level = wx.stc.STC_FOLDLEVELBASE + self.GetLineIndentation(line_number)
   478             level = wx.stc.STC_FOLDLEVELBASE + self.Editor.GetLineIndentation(line_number)
   422             line = self.GetLine(line_number).strip()
   479             line = self.Editor.GetLine(line_number).strip()
   423             if line == "":
   480             if line == "":
   424                 if line_number > 0:
   481                 if line_number > 0:
   425                     if LineStartswith(self.GetLine(line_number - 1).strip(), ST_BLOCK_END_KEYWORDS):
   482                     if LineStartswith(self.Editor.GetLine(line_number - 1).strip(), self.BlockEndKeywords):
   426                         level = self.GetFoldLevel(self.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
   483                         level = self.Editor.GetFoldLevel(self.Editor.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
   427                     else:
   484                     else:
   428                         level = self.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
   485                         level = self.Editor.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
   429                 if level != wx.stc.STC_FOLDLEVELBASE:
   486                 if level != wx.stc.STC_FOLDLEVELBASE:
   430                     level |=  wx.stc.STC_FOLDLEVELWHITEFLAG 
   487                     level |=  wx.stc.STC_FOLDLEVELWHITEFLAG 
   431             elif LineStartswith(line, ST_BLOCK_START_KEYWORDS):
   488             elif LineStartswith(line, self.BlockStartKeywords):
   432                 level |= wx.stc.STC_FOLDLEVELHEADERFLAG
   489                 level |= wx.stc.STC_FOLDLEVELHEADERFLAG
   433             elif LineStartswith(line, ST_BLOCK_END_KEYWORDS):
   490             elif LineStartswith(line, self.BlockEndKeywords):
   434                 if LineStartswith(self.GetLine(line_number - 1).strip(), ST_BLOCK_END_KEYWORDS):
   491                 if LineStartswith(self.Editor.GetLine(line_number - 1).strip(), self.BlockEndKeywords):
   435                     level = self.GetFoldLevel(self.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
   492                     level = self.Editor.GetFoldLevel(self.Editor.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
   436                 else:
   493                 else:
   437                     level = self.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
   494                     level = self.Editor.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
   438             self.SetFoldLevel(line_number, level)
   495             self.Editor.SetFoldLevel(line_number, level)
   439     
   496     
   440     def OnStyleNeeded(self, event):
   497     def OnStyleNeeded(self, event):
   441         self.TextChanged = True
   498         self.TextChanged = True
   442         line_number = self.LineFromPosition(self.GetEndStyled())
   499         line_number = self.Editor.LineFromPosition(self.Editor.GetEndStyled())
   443         if line_number == 0:
   500         if line_number == 0:
   444             start_pos = last_styled_pos = 0
   501             start_pos = last_styled_pos = 0
   445         else:
   502         else:
   446             start_pos = last_styled_pos = self.GetLineEndPosition(line_number - 1) + 1
   503             start_pos = last_styled_pos = self.Editor.GetLineEndPosition(line_number - 1) + 1
   447         self.RefreshLineFolding(line_number)
   504         self.RefreshLineFolding(line_number)
   448         end_pos = event.GetPosition()
   505         end_pos = event.GetPosition()
   449         self.StartStyling(start_pos, 0xff)
   506         self.StartStyling(start_pos, 0xff)
   450         
   507         
   451         current_context = self.Variables
   508         current_context = self.Variables
   454         current_pos = last_styled_pos
   511         current_pos = last_styled_pos
   455         state = SPACE
   512         state = SPACE
   456         line = ""
   513         line = ""
   457         word = ""
   514         word = ""
   458         while current_pos < end_pos:
   515         while current_pos < end_pos:
   459             char = chr(self.GetCharAt(current_pos)).upper()
   516             char = chr(self.Editor.GetCharAt(current_pos)).upper()
   460             line += char
   517             line += char
   461             if char == NEWLINE:
   518             if char == NEWLINE:
   462                 self.ContextStack = []
   519                 self.ContextStack = []
   463                 current_context = self.Variables
   520                 current_context = self.Variables
   464                 if state == COMMENT:
   521                 if state == COMMENT:
   627         self.ShowHighlights(start_pos, end_pos)
   684         self.ShowHighlights(start_pos, end_pos)
   628         event.Skip()
   685         event.Skip()
   629     
   686     
   630     def OnMarginClick(self, event):
   687     def OnMarginClick(self, event):
   631         if event.GetMargin() == 2:
   688         if event.GetMargin() == 2:
   632             self.ToggleFold(self.LineFromPosition(event.GetPosition()))
   689             line = self.Editor.LineFromPosition(event.GetPosition())
       
   690             if self.Editor.GetFoldLevel(line) & wx.stc.STC_FOLDLEVELHEADERFLAG:
       
   691                 self.Editor.ToggleFold(line)
   633         event.Skip()
   692         event.Skip()
   634         
   693         
   635     def Cut(self):
   694     def Cut(self):
   636         self.ResetBuffer()
   695         self.ResetBuffer()
   637         self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
   696         self.DisableEvents = True
       
   697         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
       
   698         self.DisableEvents = False
   638         self.RefreshModel()
   699         self.RefreshModel()
   639         self.RefreshBuffer()
   700         self.RefreshBuffer()
   640     
   701     
   641     def Copy(self):
   702     def Copy(self):
   642         self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
   703         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
   643     
   704     
   644     def Paste(self):
   705     def Paste(self):
   645         self.ResetBuffer()
   706         self.ResetBuffer()
   646         self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
   707         self.DisableEvents = True
       
   708         self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
       
   709         self.DisableEvents = False
   647         self.RefreshModel()
   710         self.RefreshModel()
   648         self.RefreshBuffer()
   711         self.RefreshBuffer()
   649     
   712     
   650     def RefreshModel(self):
   713     def RefreshModel(self):
   651         self.RefreshJumpList()
   714         self.RefreshJumpList()
   652         self.Controler.SetEditedElementText(self.TagName, self.GetText())
   715         self.Controler.SetEditedElementText(self.TagName, self.GetText())
   653     
   716     
   654     def OnKeyDown(self, event):
   717     def OnKeyDown(self, event):
   655         if self.CallTipActive():
   718         if self.Controler is not None:
   656             self.CallTipCancel()
   719         
   657         key = event.GetKeyCode()
   720             if self.Editor.CallTipActive():
   658         key_handled = False
   721                 self.Editor.CallTipCancel()
   659         
   722             key = event.GetKeyCode()
   660         # Code completion
   723             key_handled = False
   661         if key == wx.WXK_SPACE and event.ControlDown():
   724 
   662             
   725             line = self.Editor.GetCurrentLine()
   663             line = self.GetCurrentLine()
       
   664             if line == 0:
   726             if line == 0:
   665                 start_pos = 0
   727                 start_pos = 0
   666             else:
   728             else:
   667                 start_pos = self.GetLineEndPosition(line - 1) + 1
   729                 start_pos = self.Editor.GetLineEndPosition(line - 1) + 1
   668             end_pos = self.GetCurrentPos()
   730             end_pos = self.GetCurrentPos()
   669 
   731             lineText = self.Editor.GetTextRange(start_pos, end_pos).replace("\t", " ")
   670             lineText = self.GetTextRange(start_pos, end_pos).replace("\t", " ")
       
   671             words = lineText.split(" ")
       
   672             words = [word for i, word in enumerate(words) if word != '' or i == len(words) - 1]
       
   673                         
       
   674             kw = []
       
   675             
   732             
   676             if self.TextSyntax == "IL":
   733             # Code completion
   677                 if len(words) == 1:
   734             if key == wx.WXK_SPACE and event.ControlDown():
   678                     kw = self.Keywords
   735                 
   679                 elif len(words) == 2:
   736                 words = lineText.split(" ")
   680                     if words[0].upper() in ["CAL", "CALC", "CALNC"]:
   737                 words = [word for i, word in enumerate(words) if word != '' or i == len(words) - 1]
   681                         kw = self.Functions
   738                             
   682                     elif words[0].upper() in ["JMP", "JMPC", "JMPNC"]:
   739                 kw = []
   683                         kw = self.Jumps
   740                 
   684                     else:
   741                 if self.TextSyntax == "IL":
   685                         kw = self.Variables.keys()
   742                     if len(words) == 1:
   686             else:
   743                         kw = self.Keywords
   687                 kw = self.Keywords + self.Variables.keys() + self.Functions
   744                     elif len(words) == 2:
   688             if len(kw) > 0:
   745                         if words[0].upper() in ["CAL", "CALC", "CALNC"]:
   689                 if len(words[-1]) > 0:
   746                             kw = self.Functions
   690                     kw = [keyword for keyword in kw if keyword.startswith(words[-1])]
   747                         elif words[0].upper() in ["JMP", "JMPC", "JMPNC"]:
   691                 kw.sort()
   748                             kw = self.Jumps
   692                 self.AutoCompSetIgnoreCase(True)
   749                         else:
   693                 self.AutoCompShow(len(words[-1]), " ".join(kw))
   750                             kw = self.Variables.keys()
   694             key_handled = True
   751                 else:
   695         elif key == wx.WXK_RETURN or key == wx.WXK_NUMPAD_ENTER:
   752                     kw = self.Keywords + self.Variables.keys() + self.Functions
   696             if self.TextSyntax == "ST":
   753                 if len(kw) > 0:
   697                 line = self.GetCurrentLine()
   754                     if len(words[-1]) > 0:
   698                 indent = self.GetLineIndentation(line)
   755                         kw = [keyword for keyword in kw if keyword.startswith(words[-1])]
   699                 if LineStartswith(self.GetLine(line).strip(), ST_BLOCK_START_KEYWORDS):
   756                     kw.sort()
   700                     indent += 2
   757                     self.Editor.AutoCompSetIgnoreCase(True)
   701                 self.AddText("\n" + " " * indent)
   758                     self.Editor.AutoCompShow(len(words[-1]), " ".join(kw))
   702                 key_handled = True
   759                 key_handled = True
   703         elif key == wx.WXK_BACK:
   760             elif key == wx.WXK_RETURN or key == wx.WXK_NUMPAD_ENTER:
   704             if self.TextSyntax == "ST":
   761                 if self.TextSyntax in ["ST", "ALL"]:
   705                 line = self.GetCurrentLine()
   762                     indent = self.Editor.GetLineIndentation(line)
   706                 indent = self.GetLineIndentation(line)
   763                     if LineStartswith(lineText.strip(), self.BlockStartKeywords):
   707                 if self.GetLine(line).strip() == "" and indent > 0:
   764                         indent += 2
   708                     self.DelLineLeft()
   765                     self.Editor.AddText("\n" + " " * indent)
   709                     self.AddText(" " * max(0, indent - 2))
       
   710                     key_handled = True
   766                     key_handled = True
   711         if not key_handled:
   767             elif key == wx.WXK_BACK:
   712             event.Skip()
   768                 if self.TextSyntax in ["ST", "ALL"]:
       
   769                     indent = self.Editor.GetLineIndentation(line)
       
   770                     if lineText.strip() == "" and indent > 0:
       
   771                         self.Editor.DelLineLeft()
       
   772                         self.Editor.AddText(" " * max(0, indent - 2))
       
   773                         key_handled = True
       
   774             if not key_handled:
       
   775                 event.Skip()
   713 
   776 
   714     def OnKillFocus(self, event):
   777     def OnKillFocus(self, event):
   715         self.AutoCompCancel()
   778         self.Editor.AutoCompCancel()
   716         event.Skip()
   779         event.Skip()
   717 
   780 
   718 #-------------------------------------------------------------------------------
   781 #-------------------------------------------------------------------------------
   719 #                        Highlights showing functions
   782 #                        Highlights showing functions
   720 #-------------------------------------------------------------------------------
   783 #-------------------------------------------------------------------------------