--- a/TextViewer.py Mon Oct 24 02:03:42 2011 +0200
+++ b/TextViewer.py Mon Oct 24 02:06:34 2011 +0200
@@ -29,6 +29,7 @@
import re
from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
+from plcopen.structures import ST_BLOCK_START_KEYWORDS, ST_BLOCK_END_KEYWORDS
#-------------------------------------------------------------------------------
# Textual programs Viewer class
@@ -98,6 +99,8 @@
else:
return None
+def LineStartswith(line, symbols):
+ return reduce(lambda x, y: x or y, map(lambda x: line.startswith(x), symbols), False)
class TextViewer(wx.stc.StyledTextCtrl):
@@ -148,6 +151,15 @@
self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
self.SetMarginWidth(1, 50)
+ # Folding
+ self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPEN, wx.stc.STC_MARK_BOXMINUS, "white", "#808080")
+ self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDER, wx.stc.STC_MARK_BOXPLUS, "white", "#808080")
+ self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERSUB, wx.stc.STC_MARK_VLINE, "white", "#808080")
+ self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERTAIL, wx.stc.STC_MARK_LCORNER, "white", "#808080")
+ self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEREND, wx.stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
+ self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPENMID, wx.stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
+ self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERMIDTAIL, wx.stc.STC_MARK_TCORNER, "white", "#808080")
+
# Indentation size
self.SetTabWidth(2)
self.SetUseTabs(0)
@@ -179,6 +191,7 @@
wx.stc.STC_PERFORMED_USER)
self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyleNeeded, id=ID_TEXTVIEWER)
+ self.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
if controler:
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_TEXTVIEWER)
@@ -300,6 +313,11 @@
def SetTextSyntax(self, syntax):
self.TextSyntax = syntax
+ if syntax == "ST":
+ self.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL)
+ self.SetMarginMask(2, wx.stc.STC_MASK_FOLDERS)
+ self.SetMarginSensitive(2, 1)
+ self.SetMarginWidth(2, 12)
def SetKeywords(self, keywords):
self.Keywords = [keyword.upper() for keyword in keywords]
@@ -368,7 +386,7 @@
self.Functions[blockname] = {"interface": interface,
"extensible": blocktype["extensible"]}
self.Colourise(0, -1)
-
+
def RefreshVariableTree(self):
words = self.TagName.split("::")
self.Variables = self.GenerateVariableTree([(variable["Name"], variable["Type"], variable["Tree"]) for variable in self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)])
@@ -397,14 +415,36 @@
return (call["interface"].get(name.upper(), None) is not None or
call["extensible"] and EXTENSIBLE_PARAMETER.match(name.upper()) is not None)
return False
-
+
+ def RefreshLineFolding(self, line_number):
+ if self.TextSyntax == "ST":
+ level = wx.stc.STC_FOLDLEVELBASE + self.GetLineIndentation(line_number)
+ line = self.GetLine(line_number).strip()
+ if line == "":
+ if line_number > 0:
+ if LineStartswith(self.GetLine(line_number - 1).strip(), ST_BLOCK_END_KEYWORDS):
+ level = self.GetFoldLevel(self.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
+ else:
+ level = self.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
+ if level != wx.stc.STC_FOLDLEVELBASE:
+ level |= wx.stc.STC_FOLDLEVELWHITEFLAG
+ elif LineStartswith(line, ST_BLOCK_START_KEYWORDS):
+ level |= wx.stc.STC_FOLDLEVELHEADERFLAG
+ elif LineStartswith(line, ST_BLOCK_END_KEYWORDS):
+ if LineStartswith(self.GetLine(line_number - 1).strip(), ST_BLOCK_END_KEYWORDS):
+ level = self.GetFoldLevel(self.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
+ else:
+ level = self.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
+ self.SetFoldLevel(line_number, level)
+
def OnStyleNeeded(self, event):
self.TextChanged = True
- line = self.LineFromPosition(self.GetEndStyled())
- if line == 0:
+ line_number = self.LineFromPosition(self.GetEndStyled())
+ if line_number == 0:
start_pos = last_styled_pos = 0
else:
- start_pos = last_styled_pos = self.GetLineEndPosition(line - 1) + 1
+ start_pos = last_styled_pos = self.GetLineEndPosition(line_number - 1) + 1
+ self.RefreshLineFolding(line_number)
end_pos = event.GetPosition()
self.StartStyling(start_pos, 0xff)
@@ -449,6 +489,8 @@
last_styled_pos = current_pos
state = SPACE
line = ""
+ line_number += 1
+ self.RefreshLineFolding(line_number)
elif line.endswith("(*") and state != COMMENT:
self.SetStyling(current_pos - last_styled_pos - 1, 31)
last_styled_pos = current_pos
@@ -585,6 +627,11 @@
self.ShowHighlights(start_pos, end_pos)
event.Skip()
+ def OnMarginClick(self, event):
+ if event.GetMargin() == 2:
+ self.ToggleFold(self.LineFromPosition(event.GetPosition()))
+ event.Skip()
+
def Cut(self):
self.ResetBuffer()
self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
@@ -608,7 +655,8 @@
if self.CallTipActive():
self.CallTipCancel()
key = event.GetKeyCode()
-
+ key_handled = False
+
# Code completion
if key == wx.WXK_SPACE and event.ControlDown():
@@ -643,7 +691,24 @@
kw.sort()
self.AutoCompSetIgnoreCase(True)
self.AutoCompShow(len(words[-1]), " ".join(kw))
- else:
+ key_handled = True
+ elif key == wx.WXK_RETURN or key == wx.WXK_NUMPAD_ENTER:
+ if self.TextSyntax == "ST":
+ line = self.GetCurrentLine()
+ indent = self.GetLineIndentation(line)
+ if LineStartswith(self.GetLine(line).strip(), ST_BLOCK_START_KEYWORDS):
+ indent += 2
+ self.AddText("\n" + " " * indent)
+ key_handled = True
+ elif key == wx.WXK_BACK:
+ if self.TextSyntax == "ST":
+ line = self.GetCurrentLine()
+ indent = self.GetLineIndentation(line)
+ if self.GetLine(line).strip() == "" and indent > 0:
+ self.DelLineLeft()
+ self.AddText(" " * max(0, indent - 2))
+ key_handled = True
+ if not key_handled:
event.Skip()
def OnKillFocus(self, event):
--- a/plcopen/structures.py Mon Oct 24 02:03:42 2011 +0200
+++ b/plcopen/structures.py Mon Oct 24 02:06:34 2011 +0200
@@ -639,10 +639,10 @@
# Keywords for Structured Text
-ST_KEYWORDS = ["TRUE", "FALSE", "IF", "THEN", "ELSIF", "ELSE", "END_IF", "CASE", "OF", "END_CASE",
- "FOR", "TO", "BY", "DO", "END_FOR", "WHILE", "DO", "END_WHILE", "REPEAT", "UNTIL",
- "END_REPEAT", "EXIT", "RETURN", "NOT", "MOD", "AND", "XOR", "OR"]
-
+ST_BLOCK_START_KEYWORDS = ["IF", "ELSIF", "ELSE", "CASE", "FOR", "WHILE", "REPEAT"]
+ST_BLOCK_END_KEYWORDS = ["END_IF", "END_CASE", "END_FOR", "END_WHILE", "END_REPEAT"]
+ST_KEYWORDS = ["TRUE", "FALSE", "THEN", "OF", "TO", "BY", "DO", "DO", "UNTIL", "EXIT",
+ "RETURN", "NOT", "MOD", "AND", "XOR", "OR"] + ST_BLOCK_START_KEYWORDS + ST_BLOCK_END_KEYWORDS
# All the keywords of IEC
IEC_KEYWORDS = ["E", "TRUE", "FALSE"]