--- a/DataTypeEditor.py Tue Aug 12 18:15:35 2008 +0200
+++ b/DataTypeEditor.py Tue Aug 12 18:16:09 2008 +0200
@@ -25,7 +25,7 @@
import wx
import wx.grid
import wx.gizmos
-from plcopen.structures import GetDataTypeRange, IEC_KEYWORDS
+from plcopen.structures import IEC_KEYWORDS
import re
@@ -165,7 +165,7 @@
self.staticbox = wx.StaticBox(id=ID_DATATYPEEDITORSTATICBOX,
label='Type infos:', name='staticBox1', parent=self,
- pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0)
+ pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0)
self.staticText1 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT1,
label='Derivation Type:', name='staticText1', parent=self,
@@ -197,8 +197,8 @@
self.DirectlyInitialValue = wx.TextCtrl(id=ID_DATATYPEEDITORDIRECTLYINITIALVALUE,
name='DirectlyInitialValue', parent=self.DirectlyPanel, pos=wx.Point(0, 0),
- size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER)
- self.Bind(wx.EVT_TEXT_ENTER, self.OnInfosChanged, id=ID_DATATYPEEDITORDIRECTLYINITIALVALUE)
+ size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER|wx.TE_MULTILINE|wx.TE_RICH)
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnReturnKeyPressed, id=ID_DATATYPEEDITORDIRECTLYINITIALVALUE)
# Panel for Subrange data types
@@ -296,8 +296,8 @@
self.ArrayInitialValue = wx.TextCtrl(id=ID_DATATYPEEDITORARRAYINITIALVALUE,
name='ArrayInitialValue', parent=self.ArrayPanel, pos=wx.Point(0, 0),
- size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER)
- self.Bind(wx.EVT_TEXT_ENTER, self.OnInfosChanged, id=ID_DATATYPEEDITORARRAYINITIALVALUE)
+ size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER|wx.TE_MULTILINE|wx.TE_RICH)
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnReturnKeyPressed, id=ID_DATATYPEEDITORARRAYINITIALVALUE)
self._init_sizers()
@@ -312,6 +312,7 @@
self.EnumeratedPanel.Hide()
self.ArrayPanel.Hide()
self.CurrentPanel = "Directly"
+ self.Errors = []
self.Initializing = False
self.ParentWindow = window
@@ -371,7 +372,7 @@
self.DirectlyBaseType.SetSelection(0)
self.SubrangeBaseType.Clear()
words = self.TagName.split("::")
- for base_type in self.Controler.GetSubrangeTypes():
+ for base_type in self.Controler.GetSubrangeBaseTypes(words[1]):
self.SubrangeBaseType.Append(base_type)
self.SubrangeBaseType.SetSelection(0)
self.RefreshBoundsRange()
@@ -400,6 +401,7 @@
self.ArrayDimensions.SetStrings(map(lambda x : "..".join(map(str, x)), type_infos["dimensions"]))
self.ArrayInitialValue.SetValue(type_infos["initial"])
self.RefreshDisplayedInfos()
+ self.ShowErrors()
self.Initializing = False
def RefreshScaling(self, refresh=True):
@@ -410,6 +412,9 @@
self.RefreshTypeInfos()
event.Skip()
+ def OnReturnKeyPressed(self, event):
+ self.RefreshTypeInfos()
+
def OnInfosChanged(self, event):
self.RefreshTypeInfos()
event.Skip()
@@ -468,7 +473,7 @@
self.EnumeratedInitialValue.SetStringSelection(selected)
def RefreshBoundsRange(self):
- range = GetDataTypeRange(self.SubrangeBaseType.GetStringSelection())
+ range = self.Controler.GetDataTypeRange(self.SubrangeBaseType.GetStringSelection())
if range is not None:
min_value, max_value = range
self.SubrangeMinimum.SetRange(min_value, max_value)
@@ -521,3 +526,64 @@
self.ParentWindow.RefreshTitle()
self.ParentWindow.RefreshEditMenu()
+#-------------------------------------------------------------------------------
+# Errors showing functions
+#-------------------------------------------------------------------------------
+
+ def ClearErrors(self):
+ self.Errors = []
+ self.RefreshView()
+
+ def AddShownError(self, infos, start, end):
+ self.Errors.append((infos, start, end))
+
+ def ShowErrors(self):
+ type_infos = self.Controler.GetDataTypeInfos(self.TagName)
+ for infos, start, end in self.Errors:
+ if infos[0] == "base":
+ if type_infos["type"] == "Directly":
+ self.DirectlyBaseType.SetBackgroundColour(wx.Colour(255, 255, 0))
+ self.DirectlyBaseType.SetForegroundColour(wx.RED)
+ elif type_infos["type"] == "Subrange":
+ self.SubrangeBaseType.SetBackgroundColour(wx.Colour(255, 255, 0))
+ self.SubrangeBaseType.SetForegroundColour(wx.RED)
+ elif type_infos["type"] == "Array":
+ self.ArrayBaseType.SetBackgroundColour(wx.Colour(255, 255, 0))
+ self.ArrayBaseType.SetForegroundColour(wx.RED)
+ elif infos[0] == "lower":
+ self.SubrangeMinimum.SetBackgroundColour(wx.Colour(255, 255, 0))
+ self.SubrangeMaximum.SetForegroundColour(wx.RED)
+ elif infos[0] == "upper":
+ self.SubrangeMinimum.SetBackgroundColour(wx.Colour(255, 255, 0))
+ self.SubrangeMaximum.SetForegroundColour(wx.RED)
+ elif infos[0] == "value":
+ listctrl = self.EnumeratedValues.GetListCtrl()
+ listctrl.SetItemBackgroundColour(infos[1], wx.Colour(255, 255, 0))
+ listctrl.SetItemTextColour(infos[1], wx.RED)
+ listctrl.Select(listctrl.FocusedItem, False)
+ elif infos[0] == "range":
+ listctrl = self.EnumeratedValues.GetListCtrl()
+ listctrl.SetItemBackgroundColour(infos[1], wx.Colour(255, 255, 0))
+ listctrl.SetItemTextColour(infos[1], wx.RED)
+ listctrl.SetStringSelection("")
+ elif infos[0] == "initial":
+ if type_infos["type"] == "Directly":
+ text = self.DirectlyInitialValue.GetValue()
+ self.DirectlyInitialValue.SetValue(text[:start[1]])
+ self.DirectlyInitialValue.SetDefaultStyle(wx.TextAttr(wx.RED, wx.Colour(255, 255, 0)))
+ self.DirectlyInitialValue.AppendText(text[start[1]:end[1] + 1])
+ self.DirectlyInitialValue.SetDefaultStyle(wx.TextAttr(wx.BLACK, wx.WHITE))
+ self.DirectlyInitialValue.AppendText(text[end[1] + 1:])
+ elif type_infos["type"] == "Subrange":
+ self.SubrangeInitialValue.SetBackgroundColour(wx.Colour(255, 255, 0))
+ self.SubrangeInitialValue.SetForegroundColour(wx.RED)
+ elif type_infos["type"] == "Enumerated":
+ self.EnumeratedInitialValue.SetBackgroundColour(wx.Colour(255, 255, 0))
+ self.EnumeratedInitialValue.SetForegroundColour(wx.RED)
+ elif type_infos["type"] == "Array":
+ text = self.ArrayInitialValue.GetValue()
+ self.ArrayInitialValue.SetValue(text[:start[1]])
+ self.ArrayInitialValue.SetDefaultStyle(wx.TextAttr(wx.RED, wx.Colour(255, 255, 0)))
+ self.ArrayInitialValue.AppendText(text[start[1]:end[1] + 1])
+ self.ArrayInitialValue.SetDefaultStyle(wx.TextAttr(wx.BLACK, wx.WHITE))
+ self.ArrayInitialValue.AppendText(text[end[1] + 1:])
--- a/PLCOpenEditor.py Tue Aug 12 18:15:35 2008 +0200
+++ b/PLCOpenEditor.py Tue Aug 12 18:16:09 2008 +0200
@@ -265,6 +265,9 @@
def _init_coll_EditMenu_Items(self, parent):
AppendMenu(parent, help='', id=wx.ID_REFRESH,
kind=wx.ITEM_NORMAL, text=u'Refresh\tCTRL+R')
+ if not self.ModeSolo:
+ AppendMenu(parent, help='', id=wx.ID_CLEAR,
+ kind=wx.ITEM_NORMAL, text=u'Clear Errors\tCTRL+K')
AppendMenu(parent, help='', id=wx.ID_UNDO,
kind=wx.ITEM_NORMAL, text=u'Undo\tCTRL+Z')
AppendMenu(parent, help='', id=wx.ID_REDO,
@@ -292,6 +295,8 @@
AppendMenu(parent, help='', id=wx.ID_DELETE,
kind=wx.ITEM_NORMAL, text=u'Delete')
self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
+ if not self.ModeSolo:
+ self.Bind(wx.EVT_MENU, self.OnClearErrorsMenu, id=wx.ID_CLEAR)
self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
self.Bind(wx.EVT_MENU, self.OnCutMenu, id=wx.ID_CUT)
@@ -489,6 +494,7 @@
self.CurrentToolBar = []
self.CurrentLanguage = ""
self.SelectedItem = None
+ self.Errors = []
self.DrawingMode = FREEDRAWING_MODE
#self.DrawingMode = DRIVENDRAWING_MODE
@@ -936,6 +942,10 @@
self.VariablePanelIndexer.RefreshVariablePanel(window.GetTagName())
event.Skip()
+ def OnClearErrorsMenu(self, event):
+ self.ClearErrors()
+ event.Skip()
+
def OnUndoMenu(self, event):
self.Controler.LoadPrevious()
idxs = range(self.GetPageCount())
@@ -1085,19 +1095,7 @@
else:
window = None
if window:
- if self.ProjectTree:
- root = self.ProjectTree.GetRootItem()
- words = window.GetTagName().split("::")
- if words[0] == "P":
- self.SelectProjectTreeItem(root, [(words[1], ITEM_POU)])
- elif words[0] == "T":
- self.SelectProjectTreeItem(root, [(words[1], ITEM_POU), (words[2], ITEM_TRANSITION)])
- elif words[0] == "A":
- self.SelectProjectTreeItem(root, [(words[1], ITEM_POU), (words[2], ITEM_ACTION)])
- elif words[0] == "C":
- self.SelectProjectTreeItem(root, [(words[1], ITEM_CONFIGURATION)])
- elif words[0] == "R":
- self.SelectProjectTreeItem(root, [(words[1], ITEM_CONFIGURATION), (words[2], ITEM_RESOURCE)])
+ self.SelectProjectTreeItem(window.GetTagName())
window.RefreshView()
self.VariablePanelIndexer.ChangeVariablePanel(window.GetTagName())
self.RefreshFileMenu()
@@ -1168,6 +1166,12 @@
to_delete = []
self.ProjectTree.SetItemText(root, infos["name"])
self.ProjectTree.SetPyData(root, infos["type"])
+ if infos["tagname"] in self.Errors:
+ self.ProjectTree.SetItemBackgroundColour(root, wx.Colour(255, 255, 0))
+ self.ProjectTree.SetItemTextColour(root, wx.RED)
+ else:
+ self.ProjectTree.SetItemBackgroundColour(root, wx.WHITE)
+ self.ProjectTree.SetItemTextColour(root, wx.BLACK)
if infos["type"] == ITEM_POU :
self.ProjectTree.SetItemImage(root,self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])])
else:
@@ -1190,7 +1194,25 @@
for item in to_delete:
self.ProjectTree.Delete(item)
- def SelectProjectTreeItem(self, root, items):
+ def SelectProjectTreeItem(self, tagname):
+ if self.ProjectTree:
+ root = self.ProjectTree.GetRootItem()
+ words = tagname.split("::")
+ if words[0] == "D":
+ return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_DATATYPE)])
+ elif words[0] == "P":
+ return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU)])
+ elif words[0] == "T":
+ return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_TRANSITION)])
+ elif words[0] == "A":
+ return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_ACTION)])
+ elif words[0] == "C":
+ return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION)])
+ elif words[0] == "R":
+ return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION), (words[2], ITEM_RESOURCE)])
+ return False
+
+ def RecursiveProjectTreeItemSelection(self, root, items):
found = False
if self.ProjectTree:
if wx.VERSION >= (2, 6, 0):
@@ -1205,9 +1227,9 @@
wx.CallAfter(self.ResetSelectedItem)
return True
else:
- found = self.SelectProjectTreeItem(item, items[1:])
+ found = self.RecursiveProjectTreeItemSelection(item, items[1:])
else:
- found = self.SelectProjectTreeItem(item, items)
+ found = self.RecursiveProjectTreeItemSelection(item, items)
item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
return found
@@ -1697,7 +1719,7 @@
#-------------------------------------------------------------------------------
-# Tool Bar Items Functions
+# ToolBar Items Functions
#-------------------------------------------------------------------------------
def ResetCurrentMode(self):
@@ -2072,7 +2094,36 @@
def OnAboutMenu(self, event):
OpenHtmlFrame(self,"About PLCOpenEditor", os.path.join(CWD, "doc","about.html"), wx.Size(350, 350))
event.Skip()
-
+
+
+#-------------------------------------------------------------------------------
+# Errors showing functions
+#-------------------------------------------------------------------------------
+
+ def ShowError(self, infos, start, end):
+ print infos
+ self.EditProjectElement(self.Controler.GetElementType(infos[0]), infos[0])
+ self.SelectProjectTreeItem(infos[0])
+ if infos[1] == "name":
+ self.Errors.append(infos[0])
+ self.RefreshProjectTree()
+ self.ProjectTree.Unselect()
+ elif infos[1] == "variable":
+ self.VariablePanelIndexer.AddVariableError(infos)
+ else:
+ selected = self.GetPageSelection()
+ if selected != -1:
+ viewer = self.GetPage(selected)
+ viewer.AddShownError(infos[1:], start, end)
+ viewer.RefreshView()
+
+ def ClearErrors(self):
+ self.Errors = []
+ self.RefreshProjectTree()
+ self.VariablePanelIndexer.ClearErrors()
+ for i in xrange(self.GetPageCount()):
+ viewer = self.GetPage(i)
+ viewer.ClearErrors()
current_num = 0
def GetNewNum():
@@ -3228,6 +3279,15 @@
if tagname in self.VariablePanelList:
self.VariablePanelList[self.CurrentPanel].RefreshView()
+ def AddVariableError(self, infos):
+ self.ChangeVariablePanel(infos[0])
+ if self.CurrentPanel is not None:
+ self.VariablePanelList[self.CurrentPanel].AddVariableError(infos[2:])
+
+ def ClearErrors(self):
+ for panel in self.VariablePanelList.values():
+ panel.ClearErrors()
+
#-------------------------------------------------------------------------------
# Variables Editor Panel
#-------------------------------------------------------------------------------
@@ -3243,6 +3303,7 @@
self.data = data
self.old_value = None
self.colnames = colnames
+ self.Errors = {}
self.Parent = parent
# XXX
# we need to store the row length and collength to
@@ -3374,7 +3435,13 @@
grid.SetCellEditor(row, col, editor)
grid.SetCellRenderer(row, col, renderer)
- grid.SetCellBackgroundColour(row, col, wx.WHITE)
+ if row in self.Errors and self.Errors[row][0] == colname.lower():
+ grid.SetCellBackgroundColour(row, col, wx.Colour(255, 255, 0))
+ grid.SetCellTextColour(row, col, wx.RED)
+ grid.MakeCellVisible(row, col)
+ else:
+ grid.SetCellTextColour(row, col, wx.BLACK)
+ grid.SetCellBackgroundColour(row, col, wx.WHITE)
def SetData(self, data):
self.data = data
@@ -3401,6 +3468,12 @@
self.data = []
self.editors = []
+ def AddError(self, infos):
+ self.Errors[infos[0]] = infos[1:]
+
+ def ClearErrors(self):
+ self.Errors = {}
+
class VariableDropTarget(wx.TextDropTarget):
def __init__(self, parent):
@@ -3891,6 +3964,18 @@
self.ParentWindow.RefreshTitle()
self.ParentWindow.RefreshEditMenu()
+ def AddVariableError(self, infos):
+ if isinstance(infos[0], TupleType):
+ for i in xrange(*infos[0]):
+ self.Table.AddError((i,) + infos[1:])
+ else:
+ self.Table.AddError(infos)
+ self.Table.ResetView(self.VariablesGrid)
+
+ def ClearErrors(self):
+ self.Table.ClearErrors()
+ self.Table.ResetView(self.VariablesGrid)
+
UPPER_DIV = lambda x, y: (x / y) + {True : 0, False : 1}[(x % y) == 0]
class GraphicPrintout(wx.Printout):
--- a/RessourceEditor.py Tue Aug 12 18:15:35 2008 +0200
+++ b/RessourceEditor.py Tue Aug 12 18:16:09 2008 +0200
@@ -113,6 +113,7 @@
wx.grid.PyGridTableBase.__init__(self)
self.data = data
self.colnames = colnames
+ self.Errors = {}
self.Parent = parent
self.ColAlignements = []
@@ -241,7 +242,13 @@
grid.SetCellEditor(row, col, editor)
grid.SetCellRenderer(row, col, renderer)
- grid.SetCellBackgroundColour(row, col, wx.WHITE)
+ if row in self.Errors and self.Errors[row][0] == colname.lower():
+ grid.SetCellBackgroundColour(row, col, wx.Colour(255, 255, 0))
+ grid.SetCellTextColour(row, col, wx.RED)
+ grid.MakeCellVisible(row, col)
+ else:
+ grid.SetCellTextColour(row, col, wx.BLACK)
+ grid.SetCellBackgroundColour(row, col, wx.WHITE)
def SetData(self, data):
self.data = data
@@ -271,6 +278,11 @@
self.data = []
self.editors = []
+ def AddError(self, infos):
+ self.Errors[infos[0]] = infos[1:]
+
+ def ClearErrors(self):
+ self.Errors = {}
[ID_RESOURCEEDITOR, ID_RESOURCEEDITORSTATICTEXT1,
ID_RESOURCEEDITORSTATICTEXT2, ID_RESOURCEEDITORINSTANCESGRID,
@@ -589,3 +601,20 @@
self.RefreshModel()
self.RefreshView()
event.Skip()
+
+#-------------------------------------------------------------------------------
+# Errors showing functions
+#-------------------------------------------------------------------------------
+
+ def ClearErrors(self):
+ self.TasksTable.ClearErrors()
+ self.InstancesTable.ClearErrors()
+ self.TasksTable.ResetView(self.TasksGrid)
+ self.InstancesTable.ResetView(self.InstancesGrid)
+
+ def AddShownError(self, infos, start, end):
+ if infos[0] == "task":
+ self.TasksTable.AddError(infos[1:])
+ elif infos[0] == "instance":
+ self.InstancesTable.AddError(infos[1:])
+
\ No newline at end of file
--- a/TextViewer.py Tue Aug 12 18:15:35 2008 +0200
+++ b/TextViewer.py Tue Aug 12 18:16:09 2008 +0200
@@ -41,7 +41,7 @@
LETTERS.append(chr(ord('A') + i))
[STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_VARIABLE,
- STC_PLC_FUNCTION, STC_PLC_JUMP] = range(6)
+ STC_PLC_FUNCTION, STC_PLC_JUMP, STC_PLC_ERROR] = range(7)
[SPACE, WORD, NUMBER, COMMENT] = range(4)
[ID_TEXTVIEWER,
@@ -140,6 +140,7 @@
self.StyleSetSpec(STC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces)
self.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
self.StyleSetSpec(STC_PLC_JUMP, "fore:#007F00,size:%(size)d" % faces)
+ self.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
# Indicators styles
self.IndicatorSetStyle(0, wx.stc.STC_INDIC_SQUIGGLE)
@@ -165,6 +166,7 @@
self.TextSyntax = "ST"
self.CurrentAction = None
self.TagName = tagname
+ self.Errors = []
self.ParentWindow = window
self.Controler = controler
@@ -294,7 +296,7 @@
self.EnumeratedValues.append(value.upper())
self.Colourise(0, -1)
-
+
def RefreshScaling(self, refresh=True):
pass
@@ -302,118 +304,119 @@
self.TextChanged = True
line = self.LineFromPosition(self.GetEndStyled())
if line == 0:
- start_pos = 0
- else:
- start_pos = self.GetLineEndPosition(line - 1) + 1
+ start_pos = last_styled_pos = 0
+ else:
+ start_pos = last_styled_pos = self.GetLineEndPosition(line - 1) + 1
end_pos = event.GetPosition()
self.StartStyling(start_pos, 0xff)
- i = start_pos
+ current_pos = last_styled_pos
state = SPACE
line = ""
word = ""
- while i < end_pos:
- char = chr(self.GetCharAt(i)).upper()
+ while current_pos < end_pos:
+ char = chr(self.GetCharAt(current_pos)).upper()
line += char
if char == NEWLINE:
if state == COMMENT:
- self.SetStyling(i - start_pos + 1, STC_PLC_COMMENT)
+ self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_COMMENT)
elif state == NUMBER:
- self.SetStyling(i - start_pos, STC_PLC_NUMBER)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
elif state == WORD:
if word in self.Keywords:
- self.SetStyling(i - start_pos, STC_PLC_WORD)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
elif word in self.Variables:
- self.SetStyling(i - start_pos, STC_PLC_VARIABLE)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
elif word in self.Functions:
- self.SetStyling(i - start_pos, STC_PLC_FUNCTION)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
elif word in self.Jumps:
- self.SetStyling(i - start_pos, STC_PLC_JUMP)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
elif word in self.EnumeratedValues:
- self.SetStyling(i - start_pos, STC_PLC_NUMBER)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
else:
- self.SetStyling(i - start_pos, 31)
- if self.GetCurrentPos() < start_pos or self.GetCurrentPos() > i:
- self.StartStyling(start_pos, wx.stc.STC_INDICS_MASK)
- self.SetStyling(i - start_pos, wx.stc.STC_INDIC0_MASK)
- self.StartStyling(i, 0xff)
+ self.SetStyling(current_pos - last_styled_pos, 31)
+ if self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos:
+ self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK)
+ self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
+ self.StartStyling(current_pos, 0xff)
else:
- self.SetStyling(i - start_pos, 31)
- start_pos = i
+ self.SetStyling(current_pos - last_styled_pos, 31)
+ last_styled_pos = current_pos
state = SPACE
line = ""
elif line.endswith("(*") and state != COMMENT:
- self.SetStyling(i - start_pos - 1, 31)
- start_pos = i
+ self.SetStyling(current_pos - last_styled_pos - 1, 31)
+ last_styled_pos = current_pos
state = COMMENT
elif state == COMMENT:
if line.endswith("*)"):
- self.SetStyling(i - start_pos + 2, STC_PLC_COMMENT)
- start_pos = i + 1
+ self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
+ last_styled_pos = current_pos + 1
state = SPACE
elif char in LETTERS:
if state == NUMBER:
word = "#"
state = WORD
elif state == SPACE:
- self.SetStyling(i - start_pos, 31)
+ self.SetStyling(current_pos - last_styled_pos, 31)
word = char
- start_pos = i
+ last_styled_pos = current_pos
state = WORD
else:
word += char
elif char in NUMBERS or char == '.' and state != WORD:
if state == SPACE:
- self.SetStyling(i - start_pos, 31)
- start_pos = i
+ self.SetStyling(current_pos - last_styled_pos, 31)
+ last_styled_pos = current_pos
state = NUMBER
if state == WORD and char != '.':
word += char
else:
if state == WORD:
if word in self.Keywords:
- self.SetStyling(i - start_pos, STC_PLC_WORD)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
elif word in self.Variables:
- self.SetStyling(i - start_pos, STC_PLC_VARIABLE)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
elif word in self.Functions:
- self.SetStyling(i - start_pos, STC_PLC_FUNCTION)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
elif word in self.Jumps:
- self.SetStyling(i - start_pos, STC_PLC_JUMP)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
elif word in self.EnumeratedValues:
- self.SetStyling(i - start_pos, STC_PLC_NUMBER)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
else:
- self.SetStyling(i - start_pos, 31)
- if self.GetCurrentPos() < start_pos or self.GetCurrentPos() > i:
- self.StartStyling(start_pos, wx.stc.STC_INDICS_MASK)
- self.SetStyling(i - start_pos, wx.stc.STC_INDIC0_MASK)
- self.StartStyling(i, 0xff)
+ self.SetStyling(current_pos - last_styled_pos, 31)
+ if self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos:
+ self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK)
+ self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
+ self.StartStyling(current_pos, 0xff)
word = ""
- start_pos = i
+ last_styled_pos = current_pos
state = SPACE
elif state == NUMBER:
- self.SetStyling(i - start_pos, STC_PLC_NUMBER)
- start_pos = i
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
+ last_styled_pos = current_pos
state = SPACE
- i += 1
+ current_pos += 1
if state == COMMENT:
- self.SetStyling(i - start_pos + 2, STC_PLC_COMMENT)
+ self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
elif state == NUMBER:
- self.SetStyling(i - start_pos, STC_PLC_NUMBER)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
elif state == WORD:
if word in self.Keywords:
- self.SetStyling(i - start_pos, STC_PLC_WORD)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
elif word in self.Variables:
- self.SetStyling(i - start_pos, STC_PLC_VARIABLE)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
elif word in self.Functions:
- self.SetStyling(i - start_pos, STC_PLC_FUNCTION)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
elif word in self.Jumps:
- self.SetStyling(i - start_pos, STC_PLC_JUMP)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
elif word in self.EnumeratedValues:
- self.SetStyling(i - start_pos, STC_PLC_NUMBER)
- else:
- self.SetStyling(i - start_pos, 31)
- else:
- self.SetStyling(i - start_pos, 31)
+ self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
+ else:
+ self.SetStyling(current_pos - last_styled_pos, 31)
+ else:
+ self.SetStyling(current_pos - start_pos, 31)
+ self.ShowErrors(start_pos, end_pos)
event.Skip()
def Cut(self):
@@ -480,3 +483,28 @@
self.AutoCompCancel()
event.Skip()
+#-------------------------------------------------------------------------------
+# Errors showing functions
+#-------------------------------------------------------------------------------
+
+ def ClearErrors(self):
+ self.Errors = []
+ self.RefreshView()
+
+ def AddShownError(self, infos, start, end):
+ if infos[0] == "body":
+ self.Errors.append((infos[1], start, end))
+
+ def ShowErrors(self, start_pos, end_pos):
+ for indent, start, end in self.Errors:
+ if start[0] == 0:
+ error_start_pos = start[1] - indent
+ else:
+ error_start_pos = self.GetLineEndPosition(start[0] - 1) + start[1] - indent + 1
+ if end[0] == 0:
+ error_end_pos = end[1] - indent + 1
+ else:
+ error_end_pos = self.GetLineEndPosition(end[0] - 1) + end[1] - indent + 2
+ if start_pos <= error_start_pos <= end_pos or start_pos <= error_end_pos <= end_pos:
+ self.StartStyling(error_start_pos, 0xff)
+ self.SetStyling(error_end_pos - error_start_pos, STC_PLC_ERROR)
--- a/Viewer.py Tue Aug 12 18:15:35 2008 +0200
+++ b/Viewer.py Tue Aug 12 18:16:09 2008 +0200
@@ -316,6 +316,7 @@
self.DrawingWire = False
self.current_id = 0
self.TagName = tagname
+ self.Errors = []
# Initialize Block, Wire and Comment numbers
self.block_id = self.wire_id = self.comment_id = 0
@@ -533,6 +534,7 @@
if not wire.IsConnectedCompatible():
wire.MarkAsInvalid()
+ self.ShowErrors()
self.Refresh(False)
def GetMaxSize(self):
@@ -823,6 +825,15 @@
wire.ConnectEndPoint(None, end_connector)
self.AddWire(wire)
+ def IsOfType(self, type, reference):
+ return self.Controler.IsOfType(type, reference)
+
+ def IsEndType(self, type):
+ return self.Controler.IsEndType(type)
+
+ def GetBlockType(self, type, inputs = None):
+ return self.Controler.GetBlockType(type, inputs)
+
#-------------------------------------------------------------------------------
# Search Element functions
#-------------------------------------------------------------------------------
@@ -1417,7 +1428,7 @@
return width, height
def AddNewBlock(self, bbox):
- dialog = BlockPropertiesDialog(self.ParentWindow)
+ dialog = BlockPropertiesDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetBlockList(self.Controler.GetBlockTypes(self.TagName))
dialog.SetPouNames(self.Controler.GetProjectPouNames())
@@ -1442,7 +1453,7 @@
dialog.Destroy()
def AddNewVariable(self, bbox):
- dialog = VariablePropertiesDialog(self.ParentWindow)
+ dialog = VariablePropertiesDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinVariableSize((bbox.width, bbox.height))
varlist = []
@@ -1470,7 +1481,7 @@
dialog.Destroy()
def AddNewConnection(self, bbox):
- dialog = ConnectionPropertiesDialog(self.ParentWindow)
+ dialog = ConnectionPropertiesDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinConnectionSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
@@ -1508,7 +1519,7 @@
dialog.Destroy()
def AddNewContact(self, bbox):
- dialog = LDElementDialog(self.ParentWindow, "contact")
+ dialog = LDElementDialog(self.ParentWindow, self.Controler, "contact")
dialog.SetPreviewFont(self.GetFont())
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName)
@@ -1534,7 +1545,7 @@
dialog.Destroy()
def AddNewCoil(self, bbox):
- dialog = LDElementDialog(self.ParentWindow, "coil")
+ dialog = LDElementDialog(self.ParentWindow, self.Controler, "coil")
dialog.SetPreviewFont(self.GetFont())
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName)
@@ -1563,7 +1574,7 @@
dialog.Destroy()
def AddNewPowerRail(self, bbox):
- dialog = LDPowerRailDialog(self.ParentWindow)
+ dialog = LDPowerRailDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
@@ -1581,7 +1592,7 @@
dialog.Destroy()
def AddNewStep(self, bbox, initial = False):
- dialog = StepContentDialog(self.ParentWindow, initial)
+ dialog = StepContentDialog(self.ParentWindow, self.Controler, initial)
dialog.SetPreviewFont(self.GetFont())
dialog.SetPouNames(self.Controler.GetProjectPouNames())
dialog.SetVariables(self.Controler.GetEditedElementInterfaceVars(self.TagName))
@@ -1615,7 +1626,7 @@
dialog.Destroy()
def AddNewTransition(self, bbox):
- dialog = TransitionContentDialog(self.ParentWindow, self.GetDrawingMode() == FREEDRAWING_MODE)
+ dialog = TransitionContentDialog(self.ParentWindow, self.Controler, self.GetDrawingMode() == FREEDRAWING_MODE)
dialog.SetPreviewFont(self.GetFont())
dialog.SetTransitions(self.Controler.GetEditedElementTransitions(self.TagName))
if dialog.ShowModal() == wx.ID_OK:
@@ -1634,7 +1645,7 @@
dialog.Destroy()
def AddNewDivergence(self, bbox):
- dialog = DivergenceCreateDialog(self.ParentWindow)
+ dialog = DivergenceCreateDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinSize((bbox.width, bbox.height))
if dialog.ShowModal() == wx.ID_OK:
@@ -1698,7 +1709,7 @@
#-------------------------------------------------------------------------------
def EditBlockContent(self, block):
- dialog = BlockPropertiesDialog(self.ParentWindow)
+ dialog = BlockPropertiesDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetBlockList(self.Controler.GetBlockTypes(self.TagName))
dialog.SetPouNames(self.Controler.GetProjectPouNames())
@@ -1731,7 +1742,7 @@
dialog.Destroy()
def EditVariableContent(self, variable):
- dialog = VariablePropertiesDialog(self.ParentWindow)
+ dialog = VariablePropertiesDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinVariableSize(variable.GetSize())
varlist = []
@@ -1768,7 +1779,7 @@
dialog.Destroy()
def EditConnectionContent(self, connection):
- dialog = ConnectionPropertiesDialog(self.ParentWindow)
+ dialog = ConnectionPropertiesDialog(self.ParentWindow, self.Controler)
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinConnectionSize(connection.GetSize())
values = {"name" : connection.GetName(), "type" : connection.GetType()}
@@ -1792,7 +1803,7 @@
dialog.Destroy()
def EditContactContent(self, contact):
- dialog = LDElementDialog(self.ParentWindow, "contact")
+ dialog = LDElementDialog(self.ParentWindow, self.Controler, "contact")
dialog.SetPreviewFont(self.GetFont())
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName)
@@ -1818,7 +1829,7 @@
dialog.Destroy()
def EditCoilContent(self, coil):
- dialog = LDElementDialog(self.ParentWindow, "coil")
+ dialog = LDElementDialog(self.ParentWindow, self.Controler, "coil")
dialog.SetPreviewFont(self.GetFont())
varlist = []
vars = self.Controler.GetEditedElementInterfaceVars(self.TagName)
@@ -1847,7 +1858,7 @@
dialog.Destroy()
def EditPowerRailContent(self, powerrail):
- dialog = LDPowerRailDialog(self.ParentWindow, powerrail.GetType(), len(powerrail.GetConnectors()))
+ dialog = LDPowerRailDialog(self.ParentWindow, self.Controler, powerrail.GetType(), len(powerrail.GetConnectors()))
dialog.SetPreviewFont(self.GetFont())
dialog.SetMinSize(powerrail.GetSize())
if dialog.ShowModal() == wx.ID_OK:
@@ -1868,7 +1879,7 @@
dialog.Destroy()
def EditStepContent(self, step):
- dialog = StepContentDialog(self.ParentWindow, step.GetInitial())
+ dialog = StepContentDialog(self.ParentWindow, self.Controler, step.GetInitial())
dialog.SetPreviewFont(self.GetFont())
dialog.SetPouNames(self.Controler.GetProjectPouNames())
dialog.SetVariables(self.Controler.GetEditedElementInterfaceVars(self.TagName))
@@ -1904,7 +1915,7 @@
step.Refresh(rect)
def EditTransitionContent(self, transition):
- dialog = TransitionContentDialog(self.ParentWindow, self.GetDrawingMode() == FREEDRAWING_MODE)
+ dialog = TransitionContentDialog(self.ParentWindow, self.Controler, self.GetDrawingMode() == FREEDRAWING_MODE)
dialog.SetPreviewFont(self.GetFont())
dialog.SetTransitions(self.Controler.GetEditedElementTransitions(self.TagName))
dialog.SetValues({"type":transition.GetType(),"value":transition.GetCondition(), "priority":transition.GetPriority()})
@@ -2328,8 +2339,26 @@
self.Controler.AddEditedElementActionBlock(self.TagName, id)
self.RefreshActionBlockModel(block)
return block
-
-
+
+
+#-------------------------------------------------------------------------------
+# Errors showing functions
+#-------------------------------------------------------------------------------
+
+ def ClearErrors(self):
+ self.Errors = []
+ self.RefreshView()
+
+ def AddShownError(self, infos, start, end):
+ self.Errors.append((infos, start, end))
+
+ def ShowErrors(self):
+ for infos, start, end in self.Errors:
+ if infos[0] in ["io_variable", "block", "coil", "contact", "transition", "step", "action_block"]:
+ block = self.FindElementById(infos[1])
+ if block is not None:
+ block.AddError(infos[2:], start, end)
+
#-------------------------------------------------------------------------------
# Drawing functions
#-------------------------------------------------------------------------------
--- a/graphics/FBD_Objects.py Tue Aug 12 18:15:35 2008 +0200
+++ b/graphics/FBD_Objects.py Tue Aug 12 18:16:09 2008 +0200
@@ -26,7 +26,6 @@
from GraphicCommons import *
from plcopen.structures import *
-from plcopen.structures import IsOfType
#-------------------------------------------------------------------------------
# Function Block Diagram Block
@@ -51,6 +50,7 @@
self.Colour = wx.BLACK
self.Pen = wx.BLACK_PEN
self.SetType(type, extension, inputs, connectors)
+ self.Errors = {}
# Make a clone of this FBD_Block
def Clone(self, parent, id = None, name = "", pos = None):
@@ -183,13 +183,13 @@
name = input.GetName()
if input != connector and (name.startswith("IN") or name in ["MN", "MX"]):
inputtype = input.GetConnectedType()
- if resulttype is None or inputtype is not None and IsOfType(inputtype, resulttype):
+ if resulttype is None or inputtype is not None and self.IsOfType(inputtype, resulttype):
resulttype = inputtype
for output in self.Outputs:
name = output.GetName()
- if output != connector and name == "OUT" and not IsEndType(output.GetType()):
+ if output != connector and name == "OUT" and not self.IsEndType(output.GetType()):
outputtype = output.GetConnectedType()
- if resulttype is None or outputtype is not None and IsOfType(outputtype, resulttype):
+ if resulttype is None or outputtype is not None and self.IsOfType(outputtype, resulttype):
resulttype = outputtype
return resulttype
@@ -218,7 +218,7 @@
self.Extension = extension
# Find the block definition from type given and create the corresponding
# inputs and outputs
- blocktype = GetBlockType(type, inputs)
+ blocktype = self.Parent.GetBlockType(type, inputs)
if blocktype:
self.Colour = wx.BLACK
inputs = [input for input in blocktype["inputs"]]
@@ -350,6 +350,14 @@
for output in self.Outputs:
output.RefreshWires()
+ def AddError(self, infos, start, end):
+ if infos[0] in ["type", "name"] and start[0] == 0 and end[0] == 0:
+ self.Errors[infos[0]] = (start, end)
+ elif infos[0] == "input" and infos[1] < len(self.Inputs):
+ self.Inputs[infos[1]].AddError(infos[2:], start, end)
+ elif infos[0] == "output" and infos[1] < len(self.Outputs):
+ self.Outputs[infos[1]].AddError(infos[2:], start, end)
+
# Draws block
def Draw(self, dc):
Graphic_Element.Draw(self, dc)
@@ -369,10 +377,12 @@
# Draw a rectangle with the block size
dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
# Draw block name and block type
- dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - name_size[0]) / 2,
- self.Pos.y - (name_size[1] + 2))
- dc.DrawText(self.Type, self.Pos.x + (self.Size[0] - type_size[0]) / 2,
- self.Pos.y + 5)
+ name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
+ self.Pos.y - (name_size[1] + 2))
+ type_pos = (self.Pos.x + (self.Size[0] - type_size[0]) / 2,
+ self.Pos.y + 5)
+ dc.DrawText(self.Name, name_pos[0], name_pos[1])
+ dc.DrawText(self.Type, type_pos[0], type_pos[1])
# Draw inputs and outputs connectors
for input in self.Inputs:
input.Draw(dc)
@@ -382,6 +392,10 @@
# Draw block execution order
dc.DrawText(str(self.ExecutionOrder), self.Pos.x + self.Size[0] - executionorder_size[0],
self.Pos.y + self.Size[1] + 2)
+ if "name" in self.Errors:
+ HighlightErrorZone(dc, name_pos[0], name_pos[1], name_size[0], name_size[1])
+ if "type" in self.Errors:
+ HighlightErrorZone(dc, type_pos[0], type_pos[1], type_size[0], type_size[1])
dc.SetTextForeground(wx.BLACK)
@@ -406,6 +420,7 @@
self.Input = None
self.Output = None
self.SetType(type, value_type)
+ self.Errors = []
# Make a clone of this FBD_Variable
def Clone(self, parent, id = None, pos = None):
@@ -594,6 +609,10 @@
if self.Output:
self.Output.RefreshWires()
+ def AddError(self, infos, start, end):
+ if infos[0] == "expression" and start[0] == 0 and end[0] == 0:
+ self.Errors.append((start[1], end[1]))
+
# Draws variable
def Draw(self, dc):
Graphic_Element.Draw(self, dc)
@@ -607,11 +626,12 @@
name_size = self.NameSize
executionorder_size = self.ExecutionOrderSize
+ text_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
+ self.Pos.y + (self.Size[1] - name_size[1]) / 2)
# Draw a rectangle with the variable size
dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
# Draw variable name
- dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - name_size[0]) / 2,
- self.Pos.y + (self.Size[1] - name_size[1]) / 2)
+ dc.DrawText(self.Name, text_pos[0], text_pos[1])
# Draw connectors
if self.Input:
self.Input.Draw(dc)
@@ -621,7 +641,10 @@
# Draw variable execution order
dc.DrawText(str(self.ExecutionOrder), self.Pos.x + self.Size[0] - executionorder_size[0],
self.Pos.y + self.Size[1] + 2)
-
+ for start, end in self.Errors:
+ offset = dc.GetTextExtent(self.Name[:start])
+ size = dc.GetTextExtent(self.Name[start:end + 1])
+ HighlightErrorZone(dc, text_pos[0] + offset[0], text_pos[1], size[0], size[1])
#-------------------------------------------------------------------------------
# Function Block Diagram Connector
--- a/graphics/GraphicCommons.py Tue Aug 12 18:15:35 2008 +0200
+++ b/graphics/GraphicCommons.py Tue Aug 12 18:16:09 2008 +0200
@@ -24,7 +24,6 @@
import wx
from math import *
-from plcopen.structures import IsOfType, IsEndType
#-------------------------------------------------------------------------------
# Common constants
@@ -275,6 +274,20 @@
self.currentBox.height)
#-------------------------------------------------------------------------------
+# Helper for highlighting error in drawn text
+#-------------------------------------------------------------------------------
+
+def HighlightErrorZone(dc, x, y, width, height):
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.SetLogicalFunction(wx.AND)
+ dc.SetBrush(wx.Brush(wx.Colour(0,255,0)))
+ dc.DrawRectangle(x, y, width, height)
+ dc.SetLogicalFunction(wx.XOR)
+ dc.SetBrush(wx.Brush(wx.Colour(255,0,0)))
+ dc.DrawRectangle(x, y, width, height)
+ dc.SetLogicalFunction(wx.COPY)
+
+#-------------------------------------------------------------------------------
# Graphic element base class
#-------------------------------------------------------------------------------
@@ -299,6 +312,12 @@
self.CurrentCursor = 0
ResetCursors()
+ def IsOfType(self, type, reference):
+ return self.Parent.IsOfType(type, reference)
+
+ def IsEndType(self, type):
+ return self.Parent.IsEndType(type)
+
def GetDragging(self):
return self.Dragging
@@ -586,6 +605,9 @@
return movex, movey
return 0, 0
+ def AddError(self, infos, start, end):
+ pass
+
# Override this method for defining the method to call for refreshing the model of this element
def RefreshModel(self, move=True):
pass
@@ -833,7 +855,7 @@
self.Pos = position
self.Direction = direction
self.Wires = []
- if IsOfType("BOOL", type):
+ if self.ParentBlock.IsOfType("BOOL", type):
self.Negated = negated
self.Edge = edge
else:
@@ -841,6 +863,7 @@
self.Edge = "none"
self.OneConnected = onlyone
self.Pen = wx.BLACK_PEN
+ self.Errors = {}
self.RefreshNameSize()
# Returns the RedrawRect
@@ -875,16 +898,16 @@
# Returns the connector type
def GetType(self, raw = False):
- if IsEndType(self.Type) or raw:
+ if self.ParentBlock.IsEndType(self.Type) or raw:
return self.Type
- elif (self.Negated or self.Edge != "none") and IsOfType("BOOL", self.Type):
+ elif (self.Negated or self.Edge != "none") and self.ParentBlock.IsOfType("BOOL", self.Type):
return "BOOL"
else:
return self.ParentBlock.GetConnectionResultType(self, self.Type)
# Returns the connector type
def GetConnectedType(self):
- if IsEndType(self.Type):
+ if self.ParentBlock.IsEndType(self.Type):
return self.Type
elif len(self.Wires) == 1:
return self.Wires[0][0].GetOtherConnectedType(self.Wires[0][1])
@@ -903,7 +926,7 @@
# Returns if connector type is compatible with type given
def IsCompatible(self, type):
reference = self.GetType()
- return IsOfType(type, reference) or IsOfType(reference, type)
+ return self.ParentBlock.IsOfType(type, reference) or self.ParentBlock.IsOfType(reference, type)
# Changes the connector name
def SetType(self, type):
@@ -1065,7 +1088,7 @@
# Changes the connector negated property
def SetNegated(self, negated):
- if IsOfType("BOOL", self.Type):
+ if self.ParentBlock.IsOfType("BOOL", self.Type):
self.Negated = negated
self.Edge = "none"
@@ -1075,7 +1098,7 @@
# Changes the connector edge property
def SetEdge(self, edge):
- if IsOfType("BOOL", self.Type):
+ if self.ParentBlock.IsOfType("BOOL", self.Type):
self.Edge = edge
self.Negated = False
@@ -1115,10 +1138,21 @@
dc.DrawRectangle(posx, posy, width, height)
dc.SetLogicalFunction(wx.COPY)
+ def AddError(self, infos, start, end):
+ if len(infos) == 0:
+ for wire, handle in self.Wires:
+ wire.MarkAsInvalid()
+ else:
+ self.Errors[infos[0]] = (start, end)
+
# Draws the connector
def Draw(self, dc):
- dc.SetPen(self.Pen)
- dc.SetBrush(wx.WHITE_BRUSH)
+ if len(self.Errors) > 0:
+ dc.SetPen(wx.RED_PEN)
+ dc.SetBrush(wx.Brush(wx.Colour(255, 255, 0)))
+ else:
+ dc.SetPen(self.Pen)
+ dc.SetBrush(wx.WHITE_BRUSH)
parent_pos = self.ParentBlock.GetPosition()
if getattr(dc, "printing", False):
@@ -1145,6 +1179,9 @@
xend = xstart + CONNECTOR_SIZE * self.Direction[0]
yend = ystart + CONNECTOR_SIZE * self.Direction[1]
dc.DrawLine(xstart + self.Direction[0], ystart + self.Direction[1], xend, yend)
+ if len(self.Errors) > 0:
+ dc.SetPen(self.Pen)
+ dc.SetBrush(wx.WHITE_BRUSH)
if self.Direction[0] != 0:
ytext = parent_pos[1] + self.Pos.y - name_size[1] / 2
if self.Direction[0] < 0:
--- a/graphics/LD_Objects.py Tue Aug 12 18:15:35 2008 +0200
+++ b/graphics/LD_Objects.py Tue Aug 12 18:16:09 2008 +0200
@@ -372,6 +372,7 @@
self.Name = name
self.Id = id
self.Size = wx.Size(LD_ELEMENT_SIZE[0], LD_ELEMENT_SIZE[1])
+ self.Errors = {}
# Create an input and output connector
self.Input = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] / 2 + 1), WEST)
self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] / 2 + 1), EAST)
@@ -558,6 +559,10 @@
dc.DrawRectangle(self.Pos.x + self.Size[0] - 3, self.Pos.y - 2, 6, self.Size[1] + 5)
dc.SetLogicalFunction(wx.COPY)
+ def AddError(self, infos, start, end):
+ print infos
+ self.Errors[infos[0]] = (start[1], end[1])
+
# Draws contact
def Draw(self, dc):
Graphic_Element.Draw(self, dc)
@@ -586,15 +591,21 @@
dc.DrawRectangle(self.Pos.x, self.Pos.y, 2, self.Size[1] + 1)
dc.DrawRectangle(self.Pos.x + self.Size[0] - 1, self.Pos.y, 2, self.Size[1] + 1)
# Draw contact name
- dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - name_size[0]) / 2,
- self.Pos.y - (name_size[1] + 2))
+ name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
+ self.Pos.y - (name_size[1] + 2))
+ dc.DrawText(self.Name, name_pos[0], name_pos[1])
# Draw the modifier symbol in the middle of contact
if typetext != "":
- dc.DrawText(typetext, self.Pos.x + (self.Size[0] - type_size[0]) / 2 + 1,
- self.Pos.y + (self.Size[1] - type_size[1]) / 2)
+ type_pos = (self.Pos.x + (self.Size[0] - type_size[0]) / 2 + 1,
+ self.Pos.y + (self.Size[1] - type_size[1]) / 2)
+ dc.DrawText(typetext, type_pos[0], type_pos[1])
# Draw input and output connectors
self.Input.Draw(dc)
self.Output.Draw(dc)
+ if "reference" in self.Errors:
+ HighlightErrorZone(dc, name_pos[0], name_pos[1], name_size[0], name_size[1])
+ if typetext != "" and ("negated" in self.Errors or "rising" in self.Errors or "falling" in self.Errors):
+ HighlightErrorZone(dc, type_pos[0], type_pos[1], type_size[0], type_size[1])
#-------------------------------------------------------------------------------
@@ -614,6 +625,7 @@
self.Name = name
self.Id = id
self.Size = wx.Size(LD_ELEMENT_SIZE[0], LD_ELEMENT_SIZE[1])
+ self.Errors = {}
# Create an input and output connector
self.Input = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] / 2 + 1), WEST)
self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] / 2 + 1), EAST)
@@ -800,6 +812,9 @@
dc.DrawEllipticArc(self.Pos.x, self.Pos.y - int(self.Size[1] * (sqrt(2) - 1.) / 2.) + 1, self.Size[0], int(self.Size[1] * sqrt(2)) - 1, -45, 45)
dc.SetLogicalFunction(wx.COPY)
+ def AddError(self, infos, start, end):
+ self.Errors[infos[0]] = (start[1], end[1])
+
# Draws coil
def Draw(self, dc):
Graphic_Element.Draw(self, dc)
@@ -839,13 +854,20 @@
type_size = self.TypeSize
# Draw coil name
- dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - name_size[0]) / 2,
- self.Pos.y - (name_size[1] + 2))
+ name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
+ self.Pos.y - (name_size[1] + 2))
+ dc.DrawText(self.Name, name_pos[0], name_pos[1])
# Draw the modifier symbol in the middle of coil
if typetext != "":
- dc.DrawText(typetext, self.Pos.x + (self.Size[0] - type_size[0]) / 2 + 1,
- self.Pos.y + (self.Size[1] - type_size[1]) / 2)
+ type_pos = (self.Pos.x + (self.Size[0] - type_size[0]) / 2 + 1,
+ self.Pos.y + (self.Size[1] - type_size[1]) / 2)
+ dc.DrawText(typetext, type_pos[0], type_pos[1])
# Draw input and output connectors
self.Input.Draw(dc)
self.Output.Draw(dc)
-
+ if "reference" in self.Errors:
+ HighlightErrorZone(dc, name_pos[0], name_pos[1], name_size[0], name_size[1])
+ if typetext != "" and ("negated" in self.Errors or "rising" in self.Errors or "falling" in self.Errors):
+ HighlightErrorZone(dc, type_pos[0], type_pos[1], type_size[0], type_size[1])
+
+
--- a/graphics/SFC_Objects.py Tue Aug 12 18:15:35 2008 +0200
+++ b/graphics/SFC_Objects.py Tue Aug 12 18:16:09 2008 +0200
@@ -49,6 +49,7 @@
self.SetName(name)
self.Initial = initial
self.Id = id
+ self.Error = None
self.Size = wx.Size(SFC_STEP_DEFAULT_SIZE[0], SFC_STEP_DEFAULT_SIZE[1])
# Create an input and output connector
if not self.Initial:
@@ -459,6 +460,10 @@
elif self.Output:
self.Output.RefreshWires()
+ def AddError(self, infos, start, end):
+ if infos[0] == "name" and start[0] == 0 and end[0] == 0:
+ self.Error = (start[1], end[1])
+
# Draws step
def Draw(self, dc):
Graphic_Element.Draw(self, dc)
@@ -475,8 +480,9 @@
if self.Initial:
dc.DrawRectangle(self.Pos.x + 2, self.Pos.y + 2, self.Size[0] - 3, self.Size[1] - 3)
# Draw step name
- dc.DrawText(self.Name, self.Pos.x + (self.Size[0] - name_size[0]) / 2,
+ name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
self.Pos.y + (self.Size[1] - name_size[1]) / 2)
+ dc.DrawText(self.Name, name_pos[0], name_pos[1])
# Draw input and output connectors
if self.Input:
self.Input.Draw(dc)
@@ -484,6 +490,8 @@
self.Output.Draw(dc)
if self.Action:
self.Action.Draw(dc)
+ if self.Error is not None:
+ HighlightErrorZone(dc, name_pos[0], name_pos[1], name_size[0], name_size[1])
#-------------------------------------------------------------------------------
@@ -508,6 +516,7 @@
self.Output = Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone = True)
self.SetType(type, condition)
self.SetPriority(priority)
+ self.Errors = {}
# Destructor
def __del__(self):
@@ -820,6 +829,16 @@
else:
self.Output.RefreshWires()
+ def AddError(self, infos, start, end):
+ if infos[0] == "priority" and start[0] == 0 and start[1] == 0:
+ self.Errors[infos[0]] = (start[1], end[1])
+ elif infos[0] == "inline":
+ if infos[0] not in self.Errors:
+ self.Errors[infos[0]] = []
+ self.Errors[infos[0]].append((start[1], end[1]))
+ else:
+ pass
+
# Draws transition
def Draw(self, dc):
Graphic_Element.Draw(self, dc)
@@ -850,17 +869,26 @@
condition = self.Condition
else:
condition = "Transition"
- dc.DrawText(condition, self.Pos.x + self.Size[0] + 5,
- self.Pos.y + (self.Size[1] - condition_size[1]) / 2)
+ condition_pos = (self.Pos.x + self.Size[0] + 5,
+ self.Pos.y + (self.Size[1] - condition_size[1]) / 2)
+ dc.DrawText(condition, condition_pos[0], condition_pos[1])
# Draw priority number
if self.Priority != 0:
- dc.DrawText(str(self.Priority), self.Pos.x, self.Pos.y - priority_size[1] - 2)
+ priority_pos = (self.Pos.x, self.Pos.y - priority_size[1] - 2)
+ dc.DrawText(str(self.Priority), priority_pos[0], priority_pos[1])
# Draw input and output connectors
self.Input.Draw(dc)
self.Output.Draw(dc)
if self.Type == "connection":
self.Condition.Draw(dc)
-
+ if "priority" in self.Errors:
+ HighlightErrorZone(dc, priority_pos[0], priority_pos[1], priority_size[0], priority_size[1])
+ if "inline" in self.Errors:
+ for start, end in self.Errors["inline"]:
+ offset = dc.GetTextExtent(self.Condition[:start])
+ size = dc.GetTextExtent(self.Condition[start:end + 1])
+ HighlightErrorZone(dc, condition_pos[0] + offset[0], condition_pos[1], size[0], size[1])
+
#-------------------------------------------------------------------------------
# Sequencial Function Chart Divergence and Convergence
@@ -1306,6 +1334,7 @@
self.SetTarget(target)
self.Id = id
self.Size = wx.Size(SFC_JUMP_SIZE[0], SFC_JUMP_SIZE[1])
+ self.Errors = {}
# Create an input and output connector
self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone = True)
@@ -1471,6 +1500,10 @@
if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
self.RefreshInputModel()
+ def AddError(self, infos, start, end):
+ if infos[0] == "target" and start[0] == 0 and end[0] == 0:
+ self.Errors[infos[0]] = (start[1], end[1])
+
# Draws the highlightment of this element if it is highlighted
def DrawHighlightment(self, dc):
dc.SetPen(wx.Pen(HIGHLIGHTCOLOR))
@@ -1500,11 +1533,14 @@
wx.Point(self.Pos.x + self.Size[0], self.Pos.y),
wx.Point(self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1])]
dc.DrawPolygon(points)
- dc.DrawText(self.Target, self.Pos.x + self.Size[0] + 2,
- self.Pos.y + (self.Size[1] - target_size[1]) / 2)
+ target_pos = (self.Pos.x + self.Size[0] + 2,
+ self.Pos.y + (self.Size[1] - target_size[1]) / 2)
+ dc.DrawText(self.Target, target_pos[0], target_pos[1])
# Draw input connector
if self.Input:
self.Input.Draw(dc)
+ if "target" in self.Errors:
+ HighlightErrorZone(dc, target_pos[0], target_pos[1], target_size[0], target_size[1])
#-------------------------------------------------------------------------------
@@ -1523,6 +1559,7 @@
self.Id = id
self.Size = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
self.MinSize = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
+ self.Errors = {}
# Create an input and output connector
self.Input = Connector(self, "", None, wx.Point(0, SFC_ACTION_MIN_SIZE[1] / 2), WEST, onlyone = True)
self.SetActions(actions)
@@ -1686,6 +1723,17 @@
def RefreshModel(self, move=True):
self.Parent.RefreshActionBlockModel(self)
+ def AddError(self, infos, start, end):
+ if infos[0] == "action" and infos[1] < len(self.Actions):
+ if infos[1] not in self.Errors:
+ self.Errors[infos[1]] = {}
+ if infos[2] == "inline":
+ if infos[2] not in self.Errors[infos[1]]:
+ self.Errors[infos[1]][infos[2]] = []
+ self.Errors[infos[1]][infos[2]].append((start[1], end[1]))
+ else:
+ self.Errors[infos[1]][infos[2]] = (start[1], end[1])
+
# Draws divergence
def Draw(self, dc):
Graphic_Element.Draw(self, dc)
@@ -1703,23 +1751,41 @@
if i != 0:
dc.DrawLine(self.Pos.x, self.Pos.y + i * line_size,
self.Pos.x + self.Size[0], self.Pos.y + i * line_size)
- text_width, text_height = dc.GetTextExtent(action["qualifier"])
+ qualifier_size = dc.GetTextExtent(action["qualifier"])
if "duration" in action:
- dc.DrawText(action["qualifier"], self.Pos.x + (colsize[0] - text_width) / 2,
- self.Pos.y + i * line_size + line_size / 2 - text_height)
- text_width, text_height = dc.GetTextExtent(action["duration"])
- dc.DrawText(action["duration"], self.Pos.x + (colsize[0] - text_width) / 2,
- self.Pos.y + i * line_size + line_size / 2)
+ qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) / 2,
+ self.Pos.y + i * line_size + line_size / 2 - qualifier_size[1])
+ duration_size = dc.GetTextExtent(action["duration"])
+ duration_pos = (self.Pos.x + (colsize[0] - duration_size[0]) / 2,
+ self.Pos.y + i * line_size + line_size / 2)
+ dc.DrawText(action["duration"], duration_pos[0], duration_pos[1])
else:
- dc.DrawText(action["qualifier"], self.Pos.x + (colsize[0] - text_width) / 2,
- self.Pos.y + i * line_size + (line_size - text_height) / 2)
- text_width, text_height = dc.GetTextExtent(action["value"])
- dc.DrawText(action["value"], self.Pos.x + colsize[0] + (colsize[1] - text_width) / 2,
- self.Pos.y + i * line_size + (line_size - text_height) / 2)
+ qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) / 2,
+ self.Pos.y + i * line_size + (line_size - qualifier_size[1]) / 2)
+ dc.DrawText(action["qualifier"], qualifier_pos[0], qualifier_pos[1])
+ content_size = dc.GetTextExtent(action["value"])
+ content_pos = (self.Pos.x + colsize[0] + (colsize[1] - content_size[0]) / 2,
+ self.Pos.y + i * line_size + (line_size - content_size[1]) / 2)
+ dc.DrawText(action["value"], content_pos[0], content_pos[1])
if "indicator" in action:
- text_width, text_height = dc.GetTextExtent(action["indicator"])
- dc.DrawText(action["indicator"], self.Pos.x + colsize[0] + colsize[1] + (colsize[2] - text_width) / 2,
- self.Pos.y + i * line_size + (line_size - text_height) / 2)
+ indicator_size = dc.GetTextExtent(action["indicator"])
+ indicator_pos = (self.Pos.x + colsize[0] + colsize[1] + (colsize[2] - indicator_size[0]) / 2,
+ self.Pos.y + i * line_size + (line_size - indicator_size[1]) / 2)
+ dc.DrawText(action["indicator"], indicator_pos[0], indicator_pos[1])
+ if i in self.Errors:
+ if "duration" in self.Errors[i] and "duration" in action:
+ HighlightErrorZone(dc, duration_pos[0], duration_pos[1], duration_size[0], duration_size[1])
+ if "qualifier" in self.Errors[i]:
+ HighlightErrorZone(dc, qualifier_pos[0], qualifier_pos[1], qualifier_size[0], qualifier_size[1])
+ if "reference" in self.Errors[i]:
+ HighlightErrorZone(dc, content_pos[0], content_pos[1], content_size[0], content_size[1])
+ elif "inline" in self.Errors[i]:
+ for start, end in self.Errors[i]["inline"]:
+ offset = dc.GetTextExtent(action["value"][:start])
+ size = dc.GetTextExtent(action["value"][start:end + 1])
+ HighlightErrorZone(dc, content_pos[0] + offset[0], content_pos[1], size[0], size[1])
+ if "indicator" in self.Errors[i]:
+ HighlightErrorZone(dc, indicator_pos[0], indicator_pos[1], indicator_size[0], indicator_size[1])
# Draw input connector
self.Input.Draw(dc)