--- a/editors/CodeFileEditor.py Mon May 26 14:44:03 2014 +0100
+++ b/editors/CodeFileEditor.py Fri Jun 06 18:30:49 2014 +0100
@@ -6,7 +6,7 @@
import wx.lib.buttons
from plcopen.plcopen import TestTextElement
-from plcopen.structures import TestIdentifier, IEC_KEYWORDS
+from plcopen.structures import TestIdentifier, IEC_KEYWORDS, DefaultType
from controls import CustomGrid, CustomTable
from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
from util.BitmapLibrary import GetBitmap
@@ -14,7 +14,7 @@
from controls.VariablePanel import VARIABLE_NAME_SUFFIX_MODEL
from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
-[STC_CODE_ERROR, STC_CODE_SEARCH_RESULT,
+[STC_CODE_ERROR, STC_CODE_SEARCH_RESULT,
STC_CODE_SECTION] = range(15, 18)
HIGHLIGHT_TYPES = {
@@ -25,14 +25,14 @@
EDGE_COLUMN = 80
class CodeEditor(CustomStyledTextCtrl):
-
+
KEYWORDS = []
COMMENT_HEADER = ""
def __init__(self, parent, window, controler):
- CustomStyledTextCtrl.__init__(self, parent, -1, wx.DefaultPosition,
+ CustomStyledTextCtrl.__init__(self, parent, -1, wx.DefaultPosition,
wx.Size(-1, 300), 0)
-
+
self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
self.SetMarginWidth(1, 25)
@@ -41,7 +41,7 @@
self.SetMargins(0,0)
self.SetViewWhiteSpace(False)
-
+
self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
self.SetEdgeColumn(EDGE_COLUMN)
@@ -59,7 +59,7 @@
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080")
-
+
self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
@@ -78,33 +78,33 @@
self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces)
self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
-
+
# Highlighting styles
self.StyleSetSpec(STC_CODE_ERROR, 'fore:#FF0000,back:#FFFF00,size:%(size)d' % faces)
self.StyleSetSpec(STC_CODE_SEARCH_RESULT, 'fore:#FFFFFF,back:#FFA500,size:%(size)d' % faces)
-
+
# Section style
self.StyleSetSpec(STC_CODE_SECTION, 'fore:#808080,size:%(size)d')
self.StyleSetChangeable(STC_CODE_SECTION, False)
-
+
# Indentation size
self.SetTabWidth(4)
self.SetUseTabs(0)
-
+
self.SetCodeLexer()
self.SetKeyWords(0, " ".join(self.KEYWORDS))
-
+
self.Controler = controler
self.ParentWindow = window
-
+
self.DisableEvents = True
self.CurrentAction = None
-
+
self.ResetSearchResults()
-
+
self.RefreshHighlightsTimer = wx.Timer(self, -1)
self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
-
+
self.SectionsComments = {}
for section in self.Controler.SECTIONS_NAMES:
section_comment = " %s section " % (section)
@@ -112,11 +112,11 @@
section_comment = self.COMMENT_HEADER * (len_headers / 2) + \
section_comment + \
self.COMMENT_HEADER * (len_headers - len_headers / 2)
-
+
self.SectionsComments[section] = {
"comment": section_comment,
}
-
+
for i, section in enumerate(self.Controler.SECTIONS_NAMES):
section_infos = self.SectionsComments[section]
if i + 1 < len(self.Controler.SECTIONS_NAMES):
@@ -125,24 +125,24 @@
else:
section_end = "$"
section_infos["pattern"] = re.compile(
- section_infos["comment"] + "(.*)" +
+ section_infos["comment"] + "(.*)" +
section_end, re.DOTALL)
-
+
self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop)
self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification)
-
+
def SetCodeLexer(self):
pass
-
+
def ResetSearchResults(self):
self.Highlights = []
self.SearchParams = None
self.SearchResults = None
self.CurrentFindHighlight = None
-
+
def OnModification(self, event):
if not self.DisableEvents:
mod_type = event.GetModificationType()
@@ -165,7 +165,7 @@
wx.CallAfter(self.RefreshModel)
wx.CallAfter(self.RefreshSectionStyling)
event.Skip()
-
+
def OnDoDrop(self, event):
try:
values = eval(event.GetDragText())
@@ -192,7 +192,7 @@
self.ParentWindow.RefreshFileMenu()
self.ParentWindow.RefreshEditMenu()
self.ParentWindow.RefreshPageTitles()
-
+
def StartBuffering(self):
self.Controler.StartBuffering()
if self.ParentWindow is not None:
@@ -200,7 +200,7 @@
self.ParentWindow.RefreshFileMenu()
self.ParentWindow.RefreshEditMenu()
self.ParentWindow.RefreshPageTitles()
-
+
def ResetBuffer(self):
if self.CurrentAction != None:
self.Controler.EndBuffering()
@@ -240,18 +240,18 @@
self.GotoPos(old_cursor_pos)
self.EmptyUndoBuffer()
self.DisableEvents = False
-
+
self.RefreshSectionStyling()
-
+
self.ShowHighlights()
-
+
def RefreshSectionStyling(self):
self.Colourise(0, -1)
-
+
text = self.GetText()
for line in xrange(self.GetLineCount()):
self.SetLineState(line, 0)
-
+
for section in self.Controler.SECTIONS_NAMES:
section_comments = self.SectionsComments[section]
start_pos = text.find(section_comments["comment"])
@@ -259,7 +259,7 @@
self.StartStyling(start_pos, 0xff)
self.SetStyling(end_pos - start_pos, STC_CODE_SECTION)
self.SetLineState(self.LineFromPosition(start_pos), 1)
-
+
self.StartStyling(end_pos, 0x00)
self.SetStyling(len(self.GetText()) - end_pos, stc.STC_STYLE_DEFAULT)
@@ -278,7 +278,7 @@
parts[section] = ""
self.Controler.SetTextParts(parts)
self.ResetSearchResults()
-
+
def OnKeyPressed(self, event):
if self.CallTipActive():
self.CallTipCancel()
@@ -286,14 +286,14 @@
current_pos = self.GetCurrentPos()
selected = self.GetSelection()
text_selected = selected[0] != selected[1]
-
+
# Test if caret is before Windows like new line
text = self.GetText()
if current_pos < len(text) and ord(text[current_pos]) == 13:
newline_size = 2
else:
newline_size = 1
-
+
# Disable to type any character in section header lines
if (self.GetLineState(self.LineFromPosition(current_pos)) and
not text_selected and
@@ -301,7 +301,7 @@
wx.WXK_RETURN,
wx.WXK_NUMPAD_ENTER]):
return
-
+
# Disable to delete line between code and header lines
elif (self.GetCurLine()[0].strip() != "" and not text_selected and
(key == wx.WXK_BACK and
@@ -309,7 +309,7 @@
key in [wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE] and
self.GetLineState(self.LineFromPosition(min(len(text), current_pos + newline_size))))):
return
-
+
elif key == 32 and event.ControlDown():
pos = self.GetCurrentPos()
@@ -319,7 +319,7 @@
# Code completion
else:
self.AutoCompSetIgnoreCase(False) # so this needs to match
-
+
keywords = self.KEYWORDS + [var["Name"]
for var in self.Controler.GetVariables()]
keywords.sort()
@@ -361,11 +361,11 @@
self.BraceBadLight(braceAtCaret)
else:
self.BraceHighlight(braceAtCaret, braceOpposite)
-
+
selected_text = self.GetSelectedText()
if selected_text:
self.ParentWindow.SetCopyBuffer(selected_text, True)
-
+
def OnMarginClick(self, event):
# fold and unfold as needed
if evt.GetMargin() == 2:
@@ -464,11 +464,11 @@
self.DisableEvents = False
self.RefreshModel()
self.RefreshBuffer()
-
+
def Copy(self):
self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
self.ParentWindow.RefreshEditMenu()
-
+
def Paste(self):
self.ResetBuffer()
self.DisableEvents = True
@@ -480,21 +480,21 @@
def Find(self, direction, search_params):
if self.SearchParams != search_params:
self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
-
+
self.SearchParams = search_params
criteria = {
- "raw_pattern": search_params["find_pattern"],
+ "raw_pattern": search_params["find_pattern"],
"pattern": re.compile(search_params["find_pattern"]),
"case_sensitive": search_params["case_sensitive"],
"regular_expression": search_params["regular_expression"],
"filter": "all"}
-
+
self.SearchResults = [
(start, end, SEARCH_RESULT_HIGHLIGHT)
- for start, end, text in
+ for start, end, text in
TestTextElement(self.GetText(), criteria)]
self.CurrentFindHighlight = None
-
+
if len(self.SearchResults) > 0:
if self.CurrentFindHighlight is not None:
old_idx = self.SearchResults.index(self.CurrentFindHighlight)
@@ -522,9 +522,9 @@
break
if self.CurrentFindHighlight is not None:
self.AddHighlight(*self.CurrentFindHighlight)
-
+
self.ScrollToLine(self.CurrentFindHighlight[0][0])
-
+
else:
if self.CurrentFindHighlight is not None:
self.RemoveHighlight(*self.CurrentFindHighlight)
@@ -557,11 +557,11 @@
def RemoveHighlight(self, start, end, highlight_type):
highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
- if (highlight_type is not None and
+ if (highlight_type is not None and
(start, end, highlight_type) in self.Highlights):
self.Highlights.remove((start, end, highlight_type))
self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
-
+
def ShowHighlights(self):
for start, end, highlight_type in self.Highlights:
if start[0] == 0:
@@ -583,14 +583,14 @@
#-------------------------------------------------------------------------------
class VariablesTable(CustomTable):
-
+
def GetValue(self, row, col):
if row < self.GetNumberRows():
if col == 0:
return row + 1
else:
return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
-
+
def _updateColAttrs(self, grid):
"""
wxGrid -> update the column attributes to add the
@@ -598,7 +598,7 @@
Otherwise default to the default renderer.
"""
-
+
typelist = None
accesslist = None
for row in range(self.GetNumberRows()):
@@ -606,7 +606,7 @@
editor = None
renderer = None
colname = self.GetColLabelValue(col, False)
-
+
if colname in ["Name", "Initial"]:
editor = wx.grid.GridCellTextEditor()
elif colname == "Class":
@@ -616,49 +616,49 @@
pass
else:
grid.SetReadOnly(row, col, True)
-
+
grid.SetCellEditor(row, col, editor)
grid.SetCellRenderer(row, col, renderer)
-
+
grid.SetCellBackgroundColour(row, col, wx.WHITE)
self.ResizeRow(grid, row)
class VariablesEditor(wx.Panel):
-
+
def __init__(self, parent, window, controler):
wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
-
+
main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=4)
main_sizer.AddGrowableCol(1)
main_sizer.AddGrowableRow(0)
-
+
controls_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.AddSizer(controls_sizer, border=5, flag=wx.ALL)
-
+
for name, bitmap, help in [
("AddVariableButton", "add_element", _("Add variable")),
("DeleteVariableButton", "remove_element", _("Remove variable")),
("UpVariableButton", "up", _("Move variable up")),
("DownVariableButton", "down", _("Move variable down"))]:
- button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap),
+ button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap),
size=wx.Size(28, 28), style=wx.NO_BORDER)
button.SetToolTipString(help)
setattr(self, name, button)
controls_sizer.AddWindow(button, border=5, flag=wx.BOTTOM)
-
+
self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL)
self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
main_sizer.AddWindow(self.VariablesGrid, flag=wx.GROW)
-
+
self.SetSizer(main_sizer)
-
+
self.ParentWindow = window
self.Controler = controler
-
- self.VariablesDefaultValue = {"Name" : "", "Type" : "INT", "Initial": ""}
+
+ self.VariablesDefaultValue = {"Name" : "", "Type" : DefaultType, "Initial": ""}
self.Table = VariablesTable(self, [], ["#", "Name", "Type", "Initial"])
self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
self.ColSizes = [40, 200, 150, 150]
@@ -667,7 +667,7 @@
"Delete": self.DeleteVariableButton,
"Up": self.UpVariableButton,
"Down": self.DownVariableButton})
-
+
def _AddVariable(new_row):
if new_row > 0:
row_content = self.Table.data[new_row - 1].copy()
@@ -691,13 +691,13 @@
self.RefreshView()
return new_row
setattr(self.VariablesGrid, "_AddRow", _AddVariable)
-
+
def _DeleteVariable(row):
self.Table.RemoveRow(row)
self.RefreshModel()
self.RefreshView()
setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
-
+
def _MoveVariable(row, move):
new_row = self.Table.MoveRow(row, move)
if new_row != row:
@@ -705,7 +705,7 @@
self.RefreshView()
return new_row
setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
-
+
self.VariablesGrid.SetRowLabelSize(0)
for col in range(self.Table.GetNumberCols()):
attr = wx.grid.GridCellAttr()
@@ -717,7 +717,7 @@
def RefreshModel(self):
self.Controler.SetVariables(self.Table.GetData())
self.RefreshBuffer()
-
+
# Buffer the last model state
def RefreshBuffer(self):
self.Controler.BufferCodeFile()
@@ -730,23 +730,23 @@
self.Table.SetData(self.Controler.GetVariables())
self.Table.ResetView(self.VariablesGrid)
self.VariablesGrid.RefreshButtons()
-
+
def DoGetBestSize(self):
return self.ParentWindow.GetPanelBestSize()
-
+
def OnVariablesGridCellChange(self, event):
row, col = event.GetRow(), event.GetCol()
colname = self.Table.GetColLabelValue(col, False)
value = self.Table.GetValue(row, col)
message = None
-
+
if colname == "Name" and value != "":
if not TestIdentifier(value):
message = _("\"%s\" is not a valid identifier!") % value
elif value.upper() in IEC_KEYWORDS:
message = _("\"%s\" is a keyword. It can't be used!") % value
- elif value.upper() in [var["Name"].upper()
- for var_row, var in enumerate(self.Table.data)
+ elif value.upper() in [var["Name"].upper()
+ for var_row, var in enumerate(self.Table.data)
if var_row != row]:
message = _("A variable with \"%s\" as name already exists!") % value
else:
@@ -755,7 +755,7 @@
else:
self.RefreshModel()
wx.CallAfter(self.RefreshView)
-
+
if message is not None:
dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
dialog.ShowModal()
@@ -765,7 +765,7 @@
event.Skip()
def OnVariablesGridEditorShown(self, event):
- row, col = event.GetRow(), event.GetCol()
+ row, col = event.GetRow(), event.GetCol()
if self.Table.GetColLabelValue(col, False) == "Type":
type_menu = wx.Menu(title='')
base_menu = wx.Menu(title='')
@@ -781,7 +781,7 @@
self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
-
+
self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
type_menu.Destroy()
event.Veto()
@@ -803,64 +803,64 @@
row = event.GetRow()
data_type = self.Table.GetValueByName(row, "Type")
var_name = self.Table.GetValueByName(row, "Name")
- data = wx.TextDataObject(str((var_name, "Global", data_type,
+ data = wx.TextDataObject(str((var_name, "Global", data_type,
self.Controler.GetCurrentLocation())))
dragSource = wx.DropSource(self.VariablesGrid)
dragSource.SetData(data)
dragSource.DoDragDrop()
return
event.Skip()
-
+
#-------------------------------------------------------------------------------
# CodeFileEditor Main Frame Class
#-------------------------------------------------------------------------------
class CodeFileEditor(ConfTreeNodeEditor):
-
+
CONFNODEEDITOR_TABS = []
CODE_EDITOR = None
-
+
def _create_CodePanel(self, prnt):
self.CodeEditorPanel = wx.SplitterWindow(prnt)
self.CodeEditorPanel.SetMinimumPaneSize(1)
-
- self.VariablesPanel = VariablesEditor(self.CodeEditorPanel,
+
+ self.VariablesPanel = VariablesEditor(self.CodeEditorPanel,
self.ParentWindow, self.Controler)
-
+
if self.CODE_EDITOR is not None:
- self.CodeEditor = self.CODE_EDITOR(self.CodeEditorPanel,
+ self.CodeEditor = self.CODE_EDITOR(self.CodeEditorPanel,
self.ParentWindow, self.Controler)
-
- self.CodeEditorPanel.SplitHorizontally(self.VariablesPanel,
+
+ self.CodeEditorPanel.SplitHorizontally(self.VariablesPanel,
self.CodeEditor, 150)
else:
self.CodeEditorPanel.Initialize(self.VariablesPanel)
-
+
return self.CodeEditorPanel
-
+
def __init__(self, parent, controler, window):
ConfTreeNodeEditor.__init__(self, parent, controler, window)
-
+
wx.CallAfter(self.CodeEditorPanel.SetSashPosition, 150)
-
+
def GetBufferState(self):
return self.Controler.GetBufferState()
-
+
def Undo(self):
self.Controler.LoadPrevious()
self.RefreshView()
-
+
def Redo(self):
self.Controler.LoadNext()
self.RefreshView()
-
+
def RefreshView(self):
ConfTreeNodeEditor.RefreshView(self)
-
+
self.VariablesPanel.RefreshView()
self.CodeEditor.RefreshView()
-
+
def Find(self, direction, search_params):
self.CodeEditor.Find(direction, search_params)
-
\ No newline at end of file
+