# HG changeset patch # User lbessard # Date 1218557769 -7200 # Node ID fc2d6cbb8b39ba18119dbe9b3d64990079e615ac # Parent 45d70748e45a4cc8c8c6108ad5270d758e8426b4 Adding support for highlighing compiling errors from matiec diff -r 45d70748e45a -r fc2d6cbb8b39 DataTypeEditor.py --- 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:]) diff -r 45d70748e45a -r fc2d6cbb8b39 PLCOpenEditor.py --- 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): diff -r 45d70748e45a -r fc2d6cbb8b39 RessourceEditor.py --- 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 diff -r 45d70748e45a -r fc2d6cbb8b39 TextViewer.py --- 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) diff -r 45d70748e45a -r fc2d6cbb8b39 Viewer.py --- 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 #------------------------------------------------------------------------------- diff -r 45d70748e45a -r fc2d6cbb8b39 graphics/FBD_Objects.py --- 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 diff -r 45d70748e45a -r fc2d6cbb8b39 graphics/GraphicCommons.py --- 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: diff -r 45d70748e45a -r fc2d6cbb8b39 graphics/LD_Objects.py --- 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]) + + diff -r 45d70748e45a -r fc2d6cbb8b39 graphics/SFC_Objects.py --- 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)