lbessard@125: #!/usr/bin/env python lbessard@125: # -*- coding: utf-8 -*- lbessard@125: lbessard@125: #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor lbessard@125: #based on the plcopen standard. lbessard@125: # lbessard@125: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD lbessard@125: # lbessard@125: #See COPYING file for copyrights details. lbessard@125: # lbessard@125: #This library is free software; you can redistribute it and/or lbessard@125: #modify it under the terms of the GNU General Public lbessard@125: #License as published by the Free Software Foundation; either lbessard@125: #version 2.1 of the License, or (at your option) any later version. lbessard@125: # lbessard@125: #This library is distributed in the hope that it will be useful, lbessard@125: #but WITHOUT ANY WARRANTY; without even the implied warranty of lbessard@125: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU lbessard@125: #General Public License for more details. lbessard@125: # lbessard@125: #You should have received a copy of the GNU General Public lbessard@125: #License along with this library; if not, write to the Free Software lbessard@125: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA lbessard@125: lbessard@125: import wx lbessard@125: import wx.grid lbessard@125: import wx.gizmos lbessard@295: from plcopen.structures import IEC_KEYWORDS, TestIdentifier lbessard@125: lbessard@207: import re lbessard@207: lbessard@207: DIMENSION_MODEL = re.compile("([0-9]+)\.\.([0-9]+)$") lbessard@207: lbessard@295: def AppendMenu(parent, help, id, kind, text): lbessard@295: if wx.VERSION >= (2, 6, 0): lbessard@295: parent.Append(help=help, id=id, kind=kind, text=text) lbessard@295: else: lbessard@295: parent.Append(helpString=help, id=id, kind=kind, item=text) lbessard@295: lbessard@295: #------------------------------------------------------------------------------- lbessard@295: # Structure Elements Table lbessard@295: #------------------------------------------------------------------------------- lbessard@295: laurent@391: def GetElementsTableColnames(): laurent@391: _ = lambda x : x laurent@391: return ["#", _("Name"), _("Type"), _("Initial Value")] laurent@391: lbessard@295: class ElementsTable(wx.grid.PyGridTableBase): lbessard@295: lbessard@295: """ lbessard@295: A custom wx.grid.Grid Table using user supplied data lbessard@295: """ lbessard@295: def __init__(self, parent, data, colnames): lbessard@295: # The base class must be initialized *first* lbessard@295: wx.grid.PyGridTableBase.__init__(self) lbessard@295: self.data = data lbessard@295: self.old_value = None lbessard@295: self.colnames = colnames lbessard@295: self.Errors = {} lbessard@295: self.Parent = parent lbessard@295: # XXX lbessard@295: # we need to store the row length and collength to lbessard@295: # see if the table has changed size lbessard@295: self._rows = self.GetNumberRows() lbessard@295: self._cols = self.GetNumberCols() lbessard@295: lbessard@295: def GetNumberCols(self): lbessard@295: return len(self.colnames) lbessard@295: lbessard@295: def GetNumberRows(self): lbessard@295: return len(self.data) lbessard@295: laurent@391: def GetColLabelValue(self, col, translate=True): lbessard@295: if col < len(self.colnames): laurent@391: if translate: laurent@391: return _(self.colnames[col]) lbessard@295: return self.colnames[col] lbessard@295: laurent@391: def GetRowLabelValues(self, row, translate=True): lbessard@295: return row lbessard@295: lbessard@295: def GetValue(self, row, col): lbessard@295: if row < self.GetNumberRows(): lbessard@295: if col == 0: lbessard@295: return row + 1 laurent@391: name = str(self.data[row].get(self.GetColLabelValue(col, False), "")) lbessard@295: return name lbessard@295: lbessard@295: def SetValue(self, row, col, value): lbessard@295: if col < len(self.colnames): laurent@391: colname = self.GetColLabelValue(col, False) lbessard@295: if colname == "Name": lbessard@295: self.old_value = self.data[row][colname] lbessard@295: self.data[row][colname] = value lbessard@295: lbessard@295: def GetValueByName(self, row, colname): lbessard@295: if row < self.GetNumberRows(): lbessard@295: return self.data[row].get(colname) lbessard@295: lbessard@295: def SetValueByName(self, row, colname, value): lbessard@295: if row < self.GetNumberRows(): lbessard@295: self.data[row][colname] = value lbessard@295: lbessard@295: def GetOldValue(self): lbessard@295: return self.old_value lbessard@295: lbessard@295: def ResetView(self, grid): lbessard@295: """ lbessard@295: (wx.grid.Grid) -> Reset the grid view. Call this to lbessard@295: update the grid if rows and columns have been added or deleted lbessard@295: """ lbessard@295: grid.BeginBatch() lbessard@295: for current, new, delmsg, addmsg in [ lbessard@295: (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED), lbessard@295: (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED), lbessard@295: ]: lbessard@295: if new < current: lbessard@295: msg = wx.grid.GridTableMessage(self,delmsg,new,current-new) lbessard@295: grid.ProcessTableMessage(msg) lbessard@295: elif new > current: lbessard@295: msg = wx.grid.GridTableMessage(self,addmsg,new-current) lbessard@295: grid.ProcessTableMessage(msg) lbessard@295: self.UpdateValues(grid) lbessard@295: grid.EndBatch() lbessard@295: lbessard@295: self._rows = self.GetNumberRows() lbessard@295: self._cols = self.GetNumberCols() lbessard@295: # update the column rendering scheme lbessard@295: self._updateColAttrs(grid) lbessard@295: lbessard@295: # update the scrollbars and the displayed part of the grid lbessard@295: grid.AdjustScrollbars() lbessard@295: grid.ForceRefresh() lbessard@295: lbessard@295: def UpdateValues(self, grid): lbessard@295: """Update all displayed values""" lbessard@295: # This sends an event to the grid table to update all of the values lbessard@295: msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES) lbessard@295: grid.ProcessTableMessage(msg) lbessard@295: lbessard@295: def _updateColAttrs(self, grid): lbessard@295: """ lbessard@295: wx.grid.Grid -> update the column attributes to add the lbessard@295: appropriate renderer given the column name. lbessard@295: lbessard@295: Otherwise default to the default renderer. lbessard@295: """ lbessard@295: lbessard@295: for row in range(self.GetNumberRows()): lbessard@295: for col in range(self.GetNumberCols()): lbessard@295: editor = None lbessard@295: renderer = None laurent@391: colname = self.GetColLabelValue(col, False) lbessard@295: if col != 0: lbessard@295: grid.SetReadOnly(row, col, False) lbessard@295: if colname == "Name": lbessard@295: editor = wx.grid.GridCellTextEditor() lbessard@295: renderer = wx.grid.GridCellStringRenderer() lbessard@295: elif colname == "Initial Value": lbessard@295: editor = wx.grid.GridCellTextEditor() lbessard@295: renderer = wx.grid.GridCellStringRenderer() lbessard@295: elif colname == "Type": lbessard@295: editor = wx.grid.GridCellTextEditor() lbessard@295: else: lbessard@295: grid.SetReadOnly(row, col, True) lbessard@295: lbessard@295: grid.SetCellEditor(row, col, editor) lbessard@295: grid.SetCellRenderer(row, col, renderer) lbessard@295: laurent@379: if self.Errors.has_key(row) and self.Errors[row][0] == colname.lower(): lbessard@295: grid.SetCellBackgroundColour(row, col, wx.Colour(255, 255, 0)) lbessard@295: grid.SetCellTextColour(row, col, wx.RED) lbessard@295: grid.MakeCellVisible(row, col) lbessard@295: else: lbessard@295: grid.SetCellTextColour(row, col, wx.BLACK) lbessard@295: grid.SetCellBackgroundColour(row, col, wx.WHITE) lbessard@295: lbessard@295: def SetData(self, data): lbessard@295: self.data = data lbessard@295: lbessard@295: def GetData(self): lbessard@295: return self.data lbessard@295: lbessard@295: def AppendRow(self, row_content): lbessard@295: self.data.append(row_content) lbessard@295: lbessard@295: def RemoveRow(self, row_index): lbessard@295: self.data.pop(row_index) lbessard@295: lbessard@295: def MoveRow(self, idx, move): lbessard@295: new_idx = max(0, min(idx + move, len(self.data) - 1)) lbessard@295: if new_idx != idx: lbessard@295: self.data.insert(new_idx, self.data.pop(idx)) lbessard@295: return new_idx lbessard@295: return None lbessard@295: lbessard@295: def GetRow(self, row_index): lbessard@295: return self.data[row_index] lbessard@295: lbessard@295: def Empty(self): lbessard@295: self.data = [] lbessard@295: self.editors = [] lbessard@295: lbessard@295: def AddError(self, infos): lbessard@295: self.Errors[infos[0]] = infos[1:] lbessard@295: lbessard@295: def ClearErrors(self): lbessard@295: self.Errors = {} lbessard@125: lbessard@125: #------------------------------------------------------------------------------- laurent@379: # Datatype Editor class lbessard@125: #------------------------------------------------------------------------------- lbessard@125: lbessard@125: [ID_DATATYPEEDITOR, ID_DATATYPEEDITORSTATICBOX, lbessard@125: ID_DATATYPEEDITORDERIVATIONTYPE, ID_DATATYPEEDITORDIRECTLYPANEL, lbessard@125: ID_DATATYPEEDITORSUBRANGEPANEL, ID_DATATYPEEDITORDIRECTLYBASETYPE, lbessard@125: ID_DATATYPEEDITORSUBRANGEBASETYPE, ID_DATATYPEEDITORSUBRANGEMINIMUM, lbessard@125: ID_DATATYPEEDITORSUBRANGEMAXIMUM, ID_DATATYPEEDITORDIRECTLYINITIALVALUE, lbessard@125: ID_DATATYPEEDITORSUBRANGEINITIALVALUE, ID_DATATYPEEDITORENUMERATEDPANEL, lbessard@125: ID_DATATYPEEDITORENUMERATEDVALUES, ID_DATATYPEEDITORENUMERATEDINITIALVALUE, lbessard@125: ID_DATATYPEEDITORARRAYPANEL, ID_DATATYPEEDITORARRAYBASETYPE, lbessard@125: ID_DATATYPEEDITORARRAYDIMENSIONS, ID_DATATYPEEDITORARRAYINITIALVALUE, lbessard@295: ID_DATATYPEEDITORSTRUCTUREPANEL, ID_DATATYPEEDITORSTRUCTUREELEMENTSGRID, lbessard@295: ID_DATATYPEEDITORSTRUCTUREADDBUTTON, ID_DATATYPEEDITORSTRUCTUREDELETEBUTTON, lbessard@295: ID_DATATYPEEDITORSTRUCTUREUPBUTTON, ID_DATATYPEEDITORSTRUCTUREDOWNBUTTON, lbessard@125: ID_DATATYPEEDITORSTATICTEXT1, ID_DATATYPEEDITORSTATICTEXT2, lbessard@125: ID_DATATYPEEDITORSTATICTEXT3, ID_DATATYPEEDITORSTATICTEXT4, lbessard@125: ID_DATATYPEEDITORSTATICTEXT5, ID_DATATYPEEDITORSTATICTEXT6, lbessard@125: ID_DATATYPEEDITORSTATICTEXT7, ID_DATATYPEEDITORSTATICTEXT8, lbessard@125: ID_DATATYPEEDITORSTATICTEXT9, ID_DATATYPEEDITORSTATICTEXT10, lbessard@295: ID_DATATYPEEDITORSTATICTEXT11, lbessard@295: ] = [wx.NewId() for _init_ctrls in range(35)] lbessard@125: laurent@391: def GetDatatypeTypes(): laurent@391: _ = lambda x : x laurent@391: return [_("Directly"), _("Subrange"), _("Enumerated"), _("Array"), _("Structure")] laurent@391: DATATYPE_TYPES_DICT = dict([(_(datatype), datatype) for datatype in GetDatatypeTypes()]) laurent@391: lbessard@125: class DataTypeEditor(wx.Panel): lbessard@125: lbessard@125: def _init_coll_MainSizer_Items(self, parent): lbessard@125: parent.AddSizer(self.TopSizer, 0, border=5, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) lbessard@125: parent.AddSizer(self.TypeInfosSizer, 0, border=5, flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT) lbessard@125: lbessard@125: def _init_coll_MainSizer_Growables(self, parent): lbessard@125: parent.AddGrowableCol(0) lbessard@125: parent.AddGrowableRow(1) lbessard@125: lbessard@125: def _init_coll_TopSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText1, 0, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT) laurent@391: parent.AddWindow(self.DerivationType, 0, border=5, flag=wx.GROW|wx.RIGHT) lbessard@125: lbessard@125: def _init_coll_TypeInfosSizer_Items(self, parent): lbessard@125: parent.AddWindow(self.DirectlyPanel, 1, border=0, flag=wx.ALL) lbessard@125: parent.AddWindow(self.SubrangePanel, 1, border=0, flag=wx.ALL) lbessard@125: parent.AddWindow(self.EnumeratedPanel, 1, border=0, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(self.ArrayPanel, 1, border=0, flag=wx.ALL) lbessard@295: parent.AddWindow(self.StructurePanel, 1, border=0, flag=wx.GROW|wx.ALL) lbessard@125: lbessard@125: def _init_coll_DirectlyPanelSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText2, 1, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL) lbessard@125: parent.AddWindow(self.DirectlyBaseType, 1, border=5, flag=wx.GROW|wx.ALL) laurent@391: parent.AddWindow(self.staticText3, 1, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL) lbessard@125: parent.AddWindow(self.DirectlyInitialValue, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: lbessard@125: def _init_coll_SubrangePanelSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText4, 1, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL) lbessard@125: parent.AddWindow(self.SubrangeBaseType, 1, border=5, flag=wx.GROW|wx.ALL) laurent@391: parent.AddWindow(self.staticText5, 1, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL) lbessard@125: parent.AddWindow(self.SubrangeInitialValue, 1, border=5, flag=wx.GROW|wx.ALL) laurent@391: parent.AddWindow(self.staticText6, 1, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL) lbessard@125: parent.AddWindow(self.SubrangeMinimum, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(wx.Size(0, 0), 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(wx.Size(0, 0), 1, border=5, flag=wx.GROW|wx.ALL) laurent@391: parent.AddWindow(self.staticText7, 1, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL) lbessard@125: parent.AddWindow(self.SubrangeMaximum, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: lbessard@125: def _init_coll_EnumeratedPanelSizer_Items(self, parent): laurent@391: parent.AddWindow(self.EnumeratedValues, 1, border=5, flag=wx.GROW|wx.ALL) laurent@391: parent.AddSizer(self.EnumeratedPanelRightSizer, 1, border=0, flag=0) laurent@391: laurent@391: def _init_coll_EnumeratedPanelRightSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText8, 1, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL) lbessard@125: parent.AddWindow(self.EnumeratedInitialValue, 1, border=5, flag=wx.ALL) lbessard@125: lbessard@125: def _init_coll_ArrayPanelSizer_Items(self, parent): lbessard@125: parent.AddSizer(self.ArrayPanelLeftSizer, 0, border=0, flag=wx.GROW) laurent@391: parent.AddSizer(self.ArrayPanelRightSizer, 0, border=0, flag=0) lbessard@125: parent.AddWindow(self.ArrayDimensions, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@125: lbessard@125: def _init_coll_ArrayPanelSizer_Growables(self, parent): lbessard@125: parent.AddGrowableCol(0) lbessard@125: parent.AddGrowableCol(1) lbessard@125: parent.AddGrowableRow(1) lbessard@125: lbessard@125: def _init_coll_ArrayPanelLeftSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText9, 1, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL) lbessard@125: parent.AddWindow(self.ArrayBaseType, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: lbessard@125: def _init_coll_ArrayPanelRightSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText10, 1, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL) lbessard@125: parent.AddWindow(self.ArrayInitialValue, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: lbessard@295: def _init_coll_StructurePanelSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText11, 0, border=5, flag=wx.ALL) lbessard@295: parent.AddWindow(self.StructureElementsGrid, 0, border=0, flag=wx.GROW) lbessard@295: parent.AddSizer(self.StructurePanelButtonSizer, 0, border=0, flag=wx.ALIGN_RIGHT) lbessard@295: lbessard@295: def _init_coll_StructurePanelSizer_Growables(self, parent): lbessard@295: parent.AddGrowableCol(0) lbessard@295: parent.AddGrowableRow(1) lbessard@295: lbessard@295: def _init_coll_StructurePanelButtonSizer_Items(self, parent): laurent@391: parent.AddWindow(self.StructureAddButton, 0, border=5, flag=wx.ALL) laurent@391: parent.AddWindow(self.StructureDeleteButton, 0, border=5, flag=wx.ALL) laurent@391: parent.AddWindow(self.StructureUpButton, 0, border=5, flag=wx.ALL) laurent@391: parent.AddWindow(self.StructureDownButton, 0, border=5, flag=wx.ALL) lbessard@295: lbessard@125: def _init_sizers(self): lbessard@125: self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) lbessard@125: self.TopSizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@125: self.TypeInfosSizer = wx.StaticBoxSizer(self.staticbox, wx.HORIZONTAL) lbessard@125: self.DirectlyPanelSizer = wx.BoxSizer(wx.HORIZONTAL) laurent@391: self.SubrangePanelSizer = wx.GridSizer(cols=4, hgap=5, rows=3, vgap=0) lbessard@125: self.EnumeratedPanelSizer = wx.BoxSizer(wx.HORIZONTAL) laurent@391: self.EnumeratedPanelRightSizer = wx.BoxSizer(wx.HORIZONTAL) laurent@391: self.ArrayPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=0) lbessard@125: self.ArrayPanelLeftSizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@125: self.ArrayPanelRightSizer = wx.BoxSizer(wx.HORIZONTAL) laurent@391: self.StructurePanelSizer = wx.FlexGridSizer(cols=1, hgap=5, rows=3, vgap=0) lbessard@295: self.StructurePanelButtonSizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@125: self._init_coll_MainSizer_Items(self.MainSizer) lbessard@125: self._init_coll_MainSizer_Growables(self.MainSizer) lbessard@125: self._init_coll_TopSizer_Items(self.TopSizer) lbessard@125: self._init_coll_TypeInfosSizer_Items(self.TypeInfosSizer) lbessard@125: self._init_coll_DirectlyPanelSizer_Items(self.DirectlyPanelSizer) lbessard@125: self._init_coll_SubrangePanelSizer_Items(self.SubrangePanelSizer) lbessard@125: self._init_coll_EnumeratedPanelSizer_Items(self.EnumeratedPanelSizer) laurent@391: self._init_coll_EnumeratedPanelRightSizer_Items(self.EnumeratedPanelRightSizer) lbessard@125: self._init_coll_ArrayPanelSizer_Items(self.ArrayPanelSizer) lbessard@125: self._init_coll_ArrayPanelSizer_Growables(self.ArrayPanelSizer) lbessard@125: self._init_coll_ArrayPanelLeftSizer_Items(self.ArrayPanelLeftSizer) lbessard@125: self._init_coll_ArrayPanelRightSizer_Items(self.ArrayPanelRightSizer) lbessard@295: self._init_coll_StructurePanelSizer_Items(self.StructurePanelSizer) lbessard@295: self._init_coll_StructurePanelSizer_Growables(self.StructurePanelSizer) lbessard@295: self._init_coll_StructurePanelButtonSizer_Items(self.StructurePanelButtonSizer) lbessard@125: lbessard@125: self.SetSizer(self.MainSizer) lbessard@125: self.DirectlyPanel.SetSizer(self.DirectlyPanelSizer) lbessard@125: self.SubrangePanel.SetSizer(self.SubrangePanelSizer) lbessard@125: self.EnumeratedPanel.SetSizer(self.EnumeratedPanelSizer) lbessard@125: self.ArrayPanel.SetSizer(self.ArrayPanelSizer) lbessard@295: self.StructurePanel.SetSizer(self.StructurePanelSizer) lbessard@125: lbessard@125: def _init_ctrls(self, prnt): lbessard@125: wx.Panel.__init__(self, id=ID_DATATYPEEDITOR, name='', parent=prnt, lbessard@125: size=wx.Size(0, 0), style=wx.SUNKEN_BORDER) lbessard@125: lbessard@125: self.staticbox = wx.StaticBox(id=ID_DATATYPEEDITORSTATICBOX, laurent@391: label=_('Type infos:'), name='staticBox1', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@125: self.staticText1 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT1, laurent@391: label=_('Derivation Type:'), name='staticText1', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@304: self.DerivationType = wx.ComboBox(id=ID_DATATYPEEDITORDERIVATIONTYPE, lbessard@125: name='DerivationType', parent=self, pos=wx.Point(0, 0), lbessard@313: size=wx.Size(200, 28), style=wx.CB_READONLY) lbessard@304: self.Bind(wx.EVT_COMBOBOX, self.OnDerivationTypeChanged, id=ID_DATATYPEEDITORDERIVATIONTYPE) lbessard@125: lbessard@125: # Panel for Directly derived data types lbessard@125: lbessard@125: self.DirectlyPanel = wx.Panel(id=ID_DATATYPEEDITORDIRECTLYPANEL, lbessard@125: name='DirectlyPanel', parent=self, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@125: lbessard@125: self.staticText2 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT2, laurent@391: label=_('Base Type:'), name='staticText2', parent=self.DirectlyPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@304: self.DirectlyBaseType = wx.ComboBox(id=ID_DATATYPEEDITORDIRECTLYBASETYPE, lbessard@125: name='DirectlyBaseType', parent=self.DirectlyPanel, pos=wx.Point(0, 0), lbessard@313: size=wx.Size(0, 28), style=wx.CB_READONLY) lbessard@304: self.Bind(wx.EVT_COMBOBOX, self.OnInfosChanged, id=ID_DATATYPEEDITORDIRECTLYBASETYPE) lbessard@125: lbessard@125: self.staticText3 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT3, laurent@391: label=_('Initial Value:'), name='staticText3', parent=self.DirectlyPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@125: self.DirectlyInitialValue = wx.TextCtrl(id=ID_DATATYPEEDITORDIRECTLYINITIALVALUE, lbessard@125: name='DirectlyInitialValue', parent=self.DirectlyPanel, pos=wx.Point(0, 0), lbessard@231: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER|wx.TE_MULTILINE|wx.TE_RICH) lbessard@231: self.Bind(wx.EVT_TEXT_ENTER, self.OnReturnKeyPressed, id=ID_DATATYPEEDITORDIRECTLYINITIALVALUE) lbessard@125: lbessard@125: # Panel for Subrange data types lbessard@125: lbessard@125: self.SubrangePanel = wx.Panel(id=ID_DATATYPEEDITORSUBRANGEPANEL, lbessard@125: name='SubrangePanel', parent=self, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@125: lbessard@125: self.staticText4 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT4, laurent@391: label=_('Base Type:'), name='staticText4', parent=self.SubrangePanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@304: self.SubrangeBaseType = wx.ComboBox(id=ID_DATATYPEEDITORSUBRANGEBASETYPE, lbessard@125: name='SubrangeBaseType', parent=self.SubrangePanel, pos=wx.Point(0, 0), lbessard@313: size=wx.Size(0, 28), style=wx.CB_READONLY) lbessard@304: self.Bind(wx.EVT_COMBOBOX, self.OnSubrangeBaseTypeChanged, id=ID_DATATYPEEDITORSUBRANGEBASETYPE) lbessard@125: lbessard@125: self.staticText5 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT5, laurent@391: label=_('Initial Value:'), name='staticText5', parent=self.SubrangePanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@125: self.SubrangeInitialValue = wx.SpinCtrl(id=ID_DATATYPEEDITORSUBRANGEINITIALVALUE, lbessard@125: name='SubrangeInitialValue', parent=self.SubrangePanel, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL) lbessard@125: self.Bind(wx.EVT_SPINCTRL, self.OnInfosChanged, id=ID_DATATYPEEDITORSUBRANGEINITIALVALUE) lbessard@125: lbessard@125: self.staticText6 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT6, laurent@391: label=_('Minimum:'), name='staticText6', parent=self.SubrangePanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@125: self.SubrangeMinimum = wx.SpinCtrl(id=ID_DATATYPEEDITORSUBRANGEMINIMUM, lbessard@125: name='SubrangeMinimum', parent=self.SubrangePanel, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL) lbessard@125: self.Bind(wx.EVT_SPINCTRL, self.OnSubrangeMinimumChanged, id=ID_DATATYPEEDITORSUBRANGEMINIMUM) lbessard@125: lbessard@125: self.staticText7 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT7, laurent@391: label=_('Maximum:'), name='staticText7', parent=self.SubrangePanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@125: self.SubrangeMaximum = wx.SpinCtrl(id=ID_DATATYPEEDITORSUBRANGEMAXIMUM, lbessard@125: name='SubrangeMaximum', parent=self.SubrangePanel, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL) lbessard@125: self.Bind(wx.EVT_SPINCTRL, self.OnSubrangeMaximumChanged, id=ID_DATATYPEEDITORSUBRANGEMAXIMUM) lbessard@125: lbessard@125: # Panel for Enumerated data types lbessard@125: lbessard@125: self.EnumeratedPanel = wx.Panel(id=ID_DATATYPEEDITORENUMERATEDPANEL, lbessard@125: name='EnumeratedPanel', parent=self, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@125: lbessard@125: self.EnumeratedValues = wx.gizmos.EditableListBox(id=ID_DATATYPEEDITORENUMERATEDVALUES, laurent@391: name='EnumeratedValues', parent=self.EnumeratedPanel, label=_("Values:"), pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 0), style=wx.gizmos.EL_ALLOW_NEW | wx.gizmos.EL_ALLOW_EDIT | wx.gizmos.EL_ALLOW_DELETE) lbessard@125: self.EnumeratedValues.GetListCtrl().Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEnumeratedValueEndEdit) laurent@391: self.EnumeratedValues.GetEditButton().SetToolTipString(_("Edit item")) laurent@391: new_button = self.EnumeratedValues.GetNewButton() laurent@391: new_button.SetToolTipString(_("New item")) laurent@391: new_button.Bind(wx.EVT_BUTTON, self.OnEnumeratedValuesChanged) laurent@391: del_button = self.EnumeratedValues.GetDelButton() laurent@391: del_button.SetToolTipString(_("Delete item")) laurent@391: del_button.Bind(wx.EVT_BUTTON, self.OnEnumeratedValuesChanged) laurent@391: up_button = self.EnumeratedValues.GetUpButton() laurent@391: up_button.SetToolTipString(_("Move up")) laurent@391: up_button.Bind(wx.EVT_BUTTON, self.OnEnumeratedValuesChanged) laurent@391: down_button = self.EnumeratedValues.GetDownButton() laurent@391: down_button.SetToolTipString(_("Move down")) laurent@391: down_button.Bind(wx.EVT_BUTTON, self.OnEnumeratedValuesChanged) lbessard@125: lbessard@125: self.staticText8 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT8, laurent@391: label=_('Initial Value:'), name='staticText8', parent=self.EnumeratedPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@304: self.EnumeratedInitialValue = wx.ComboBox(id=ID_DATATYPEEDITORENUMERATEDINITIALVALUE, lbessard@125: name='EnumeratedInitialValue', parent=self.EnumeratedPanel, pos=wx.Point(0, 0), lbessard@313: size=wx.Size(0, 28), style=wx.CB_READONLY) lbessard@304: self.Bind(wx.EVT_COMBOBOX, self.OnInfosChanged, id=ID_DATATYPEEDITORENUMERATEDINITIALVALUE) lbessard@125: lbessard@125: # Panel for Array data types lbessard@125: lbessard@125: self.ArrayPanel = wx.Panel(id=ID_DATATYPEEDITORARRAYPANEL, lbessard@125: name='ArrayPanel', parent=self, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@125: lbessard@125: self.staticText9 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT9, laurent@391: label=_('Base Type:'), name='staticText9', parent=self.ArrayPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@304: self.ArrayBaseType = wx.ComboBox(id=ID_DATATYPEEDITORARRAYBASETYPE, laurent@507: name='ArrayBaseType', parent=self.ArrayPanel, pos=wx.Point(0, 0), lbessard@313: size=wx.Size(0, 28), style=wx.CB_READONLY) lbessard@304: self.Bind(wx.EVT_COMBOBOX, self.OnInfosChanged, id=ID_DATATYPEEDITORARRAYBASETYPE) lbessard@125: lbessard@125: self.ArrayDimensions = wx.gizmos.EditableListBox(id=ID_DATATYPEEDITORARRAYDIMENSIONS, laurent@391: name='ArrayDimensions', parent=self.ArrayPanel, label=_("Dimensions:"), pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 24), style=wx.gizmos.EL_ALLOW_NEW | wx.gizmos.EL_ALLOW_EDIT | wx.gizmos.EL_ALLOW_DELETE) lbessard@125: self.ArrayDimensions.GetListCtrl().Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnDimensionsChanged) laurent@391: self.ArrayDimensions.GetEditButton().SetToolTipString(_("Edit item")) laurent@391: new_button = self.ArrayDimensions.GetNewButton() laurent@391: new_button.SetToolTipString(_("New item")) laurent@391: new_button.Bind(wx.EVT_BUTTON, self.OnDimensionsChanged) laurent@391: del_button = self.ArrayDimensions.GetDelButton() laurent@391: del_button.SetToolTipString(_("Delete item")) laurent@391: del_button.Bind(wx.EVT_BUTTON, self.OnDimensionsChanged) laurent@391: up_button = self.ArrayDimensions.GetUpButton() laurent@391: up_button.SetToolTipString(_("Move up")) laurent@391: up_button.Bind(wx.EVT_BUTTON, self.OnDimensionsChanged) laurent@391: down_button = self.ArrayDimensions.GetDownButton() laurent@391: down_button.SetToolTipString(_("Move down")) laurent@391: down_button.Bind(wx.EVT_BUTTON, self.OnDimensionsChanged) lbessard@125: lbessard@125: self.staticText10 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT10, laurent@391: label=_('Initial Value:'), name='staticText10', parent=self.ArrayPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@125: lbessard@125: self.ArrayInitialValue = wx.TextCtrl(id=ID_DATATYPEEDITORARRAYINITIALVALUE, lbessard@125: name='ArrayInitialValue', parent=self.ArrayPanel, pos=wx.Point(0, 0), lbessard@231: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER|wx.TE_MULTILINE|wx.TE_RICH) lbessard@231: self.Bind(wx.EVT_TEXT_ENTER, self.OnReturnKeyPressed, id=ID_DATATYPEEDITORARRAYINITIALVALUE) lbessard@125: lbessard@295: # Panel for Structure data types lbessard@295: lbessard@295: self.StructurePanel = wx.Panel(id=ID_DATATYPEEDITORSTRUCTUREPANEL, lbessard@295: name='StructurePanel', parent=self, pos=wx.Point(0, 0), lbessard@295: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@295: lbessard@295: self.staticText11 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT11, laurent@391: label=_('Elements :'), name='staticText11', parent=self.StructurePanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@295: lbessard@295: self.StructureElementsGrid = wx.grid.Grid(id=ID_DATATYPEEDITORSTRUCTUREELEMENTSGRID, lbessard@295: name='StructureElementsGrid', parent=self.StructurePanel, pos=wx.Point(0, 0), lbessard@295: size=wx.Size(0, 150), style=wx.VSCROLL) lbessard@295: self.StructureElementsGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, lbessard@295: 'Sans')) lbessard@295: self.StructureElementsGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, lbessard@295: False, 'Sans')) lbessard@295: self.StructureElementsGrid.SetSelectionBackground(wx.WHITE) lbessard@295: self.StructureElementsGrid.SetSelectionForeground(wx.BLACK) lbessard@295: if wx.VERSION >= (2, 6, 0): lbessard@295: self.StructureElementsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnStructureElementsGridCellChange) lbessard@295: self.StructureElementsGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnStructureElementsGridEditorShown) lbessard@295: else: lbessard@295: wx.grid.EVT_GRID_CELL_CHANGE(self.StructureElementsGrid, self.OnStructureElementsGridCellChange) lbessard@295: wx.grid.EVT_GRID_EDITOR_SHOWN(self.StructureElementsGrid, self.OnStructureElementsGridEditorShown) lbessard@295: laurent@391: self.StructureAddButton = wx.Button(id=ID_DATATYPEEDITORSTRUCTUREADDBUTTON, label=_('Add'), lbessard@295: name='StructureAddButton', parent=self.StructurePanel, pos=wx.Point(0, 0), laurent@391: size=wx.DefaultSize, style=0) lbessard@295: self.Bind(wx.EVT_BUTTON, self.OnStructureAddButton, id=ID_DATATYPEEDITORSTRUCTUREADDBUTTON) lbessard@295: laurent@391: self.StructureDeleteButton = wx.Button(id=ID_DATATYPEEDITORSTRUCTUREDELETEBUTTON, label=_('Delete'), lbessard@295: name='StructureDeleteButton', parent=self.StructurePanel, pos=wx.Point(0, 0), laurent@391: size=wx.DefaultSize, style=0) lbessard@295: self.Bind(wx.EVT_BUTTON, self.OnStructureDeleteButton, id=ID_DATATYPEEDITORSTRUCTUREDELETEBUTTON) lbessard@295: lbessard@295: self.StructureUpButton = wx.Button(id=ID_DATATYPEEDITORSTRUCTUREUPBUTTON, label='^', lbessard@295: name='StructureUpButton', parent=self.StructurePanel, pos=wx.Point(0, 0), lbessard@295: size=wx.Size(32, 32), style=0) lbessard@295: self.Bind(wx.EVT_BUTTON, self.OnStructureUpButton, id=ID_DATATYPEEDITORSTRUCTUREUPBUTTON) lbessard@295: lbessard@295: self.StructureDownButton = wx.Button(id=ID_DATATYPEEDITORSTRUCTUREDOWNBUTTON, label='v', lbessard@295: name='StructureDownButton', parent=self.StructurePanel, pos=wx.Point(0, 0), lbessard@295: size=wx.Size(32, 32), style=0) lbessard@295: self.Bind(wx.EVT_BUTTON, self.OnStructureDownButton, id=ID_DATATYPEEDITORSTRUCTUREDOWNBUTTON) lbessard@295: lbessard@125: self._init_sizers() lbessard@125: lbessard@125: def __init__(self, parent, tagname, window, controler): lbessard@125: self._init_ctrls(parent) lbessard@125: lbessard@295: self.StructureElementDefaultValue = {"Name" : "", "Type" : "INT", "Initial Value" : ""} laurent@391: self.StructureElementsTable = ElementsTable(self, [], GetElementsTableColnames()) lbessard@295: self.StructureColSizes = [40, 150, 100, 250] lbessard@295: self.StructureColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT] lbessard@295: lbessard@295: self.StructureElementsGrid.SetTable(self.StructureElementsTable) lbessard@295: self.StructureElementsGrid.SetRowLabelSize(0) lbessard@295: for col in range(self.StructureElementsTable.GetNumberCols()): lbessard@295: attr = wx.grid.GridCellAttr() lbessard@295: attr.SetAlignment(self.StructureColAlignements[col], wx.ALIGN_CENTRE) lbessard@295: self.StructureElementsGrid.SetColAttr(col, attr) laurent@391: self.StructureElementsGrid.SetColMinimalWidth(col, self.StructureColSizes[col]) laurent@391: self.StructureElementsGrid.AutoSizeColumn(col, False) laurent@391: laurent@391: for datatype in GetDatatypeTypes(): laurent@391: self.DerivationType.Append(_(datatype)) lbessard@125: self.SubrangePanel.Hide() lbessard@125: self.EnumeratedPanel.Hide() lbessard@125: self.ArrayPanel.Hide() lbessard@295: self.StructurePanel.Hide() lbessard@125: self.CurrentPanel = "Directly" lbessard@231: self.Errors = [] lbessard@130: self.Initializing = False lbessard@125: lbessard@125: self.ParentWindow = window lbessard@125: self.Controler = controler lbessard@125: self.TagName = tagname lbessard@125: lbessard@125: def SetTagName(self, tagname): lbessard@125: self.TagName = tagname lbessard@125: lbessard@125: def GetTagName(self): lbessard@125: return self.TagName lbessard@125: lbessard@125: def IsViewing(self, tagname): lbessard@125: return self.TagName == tagname lbessard@125: laurent@407: def IsDebugging(self): laurent@407: return False laurent@407: lbessard@125: def SetMode(self, mode): lbessard@125: pass lbessard@125: lbessard@125: def ResetBuffer(self): lbessard@125: pass lbessard@125: lbessard@125: def RefreshView(self): lbessard@130: self.Initializing = True lbessard@125: self.DirectlyBaseType.Clear() lbessard@125: self.ArrayBaseType.Clear() lbessard@125: for datatype in self.Controler.GetDataTypes(self.TagName): lbessard@125: self.DirectlyBaseType.Append(datatype) lbessard@125: self.ArrayBaseType.Append(datatype) lbessard@125: self.DirectlyBaseType.SetSelection(0) lbessard@125: self.SubrangeBaseType.Clear() lbessard@125: words = self.TagName.split("::") lbessard@231: for base_type in self.Controler.GetSubrangeBaseTypes(words[1]): lbessard@125: self.SubrangeBaseType.Append(base_type) lbessard@125: self.SubrangeBaseType.SetSelection(0) lbessard@125: self.RefreshBoundsRange() lbessard@125: type_infos = self.Controler.GetDataTypeInfos(self.TagName) lbessard@125: if type_infos is not None: laurent@391: datatype = type_infos["type"] laurent@391: self.DerivationType.SetStringSelection(_(datatype)) lbessard@125: if type_infos["type"] == "Directly": lbessard@125: self.DirectlyBaseType.SetStringSelection(type_infos["base_type"]) lbessard@125: self.DirectlyInitialValue.SetValue(type_infos["initial"]) lbessard@125: elif type_infos["type"] == "Subrange": lbessard@125: self.SubrangeBaseType.SetStringSelection(type_infos["base_type"]) lbessard@125: self.RefreshBoundsRange() laurent@389: self.SubrangeMinimum.SetValue(int(type_infos["min"])) laurent@389: self.SubrangeMaximum.SetValue(int(type_infos["max"])) lbessard@125: self.RefreshSubrangeInitialValueRange() lbessard@125: if type_infos["initial"] != "": lbessard@125: self.SubrangeInitialValue.SetValue(int(type_infos["initial"])) lbessard@125: else: lbessard@125: self.SubrangeInitialValue.SetValue(type_infos["min"]) lbessard@125: elif type_infos["type"] == "Enumerated": lbessard@125: self.EnumeratedValues.SetStrings(type_infos["values"]) lbessard@125: self.RefreshEnumeratedValues() lbessard@125: self.EnumeratedInitialValue.SetStringSelection(type_infos["initial"]) lbessard@125: elif type_infos["type"] == "Array": lbessard@125: self.ArrayBaseType.SetStringSelection(type_infos["base_type"]) laurent@389: self.ArrayDimensions.SetStrings(map(lambda x : "..".join(x), type_infos["dimensions"])) lbessard@125: self.ArrayInitialValue.SetValue(type_infos["initial"]) lbessard@295: elif type_infos["type"] == "Structure": lbessard@295: self.StructureElementsTable.SetData(type_infos["elements"]) lbessard@295: self.StructureElementsTable.ResetView(self.StructureElementsGrid) lbessard@125: self.RefreshDisplayedInfos() lbessard@231: self.ShowErrors() lbessard@130: self.Initializing = False lbessard@125: lbessard@205: def RefreshScaling(self, refresh=True): lbessard@205: pass lbessard@205: lbessard@125: def OnDerivationTypeChanged(self, event): lbessard@125: self.RefreshDisplayedInfos() lbessard@125: self.RefreshTypeInfos() lbessard@125: event.Skip() lbessard@125: lbessard@231: def OnReturnKeyPressed(self, event): lbessard@231: self.RefreshTypeInfos() lbessard@231: lbessard@125: def OnInfosChanged(self, event): lbessard@125: self.RefreshTypeInfos() lbessard@125: event.Skip() lbessard@125: lbessard@125: def OnSubrangeBaseTypeChanged(self, event): lbessard@125: self.RefreshBoundsRange() lbessard@125: self.RefreshTypeInfos() lbessard@125: event.Skip() lbessard@125: lbessard@125: def OnSubrangeMinimumChanged(self, event): etisserant@215: if not self.Initializing: lbessard@130: wx.CallAfter(self.SubrangeMinimum.SetValue, min(self.SubrangeMaximum.GetValue(), self.SubrangeMinimum.GetValue())) lbessard@130: wx.CallAfter(self.RefreshSubrangeInitialValueRange) lbessard@130: wx.CallAfter(self.RefreshTypeInfos) lbessard@125: event.Skip() lbessard@125: lbessard@125: def OnSubrangeMaximumChanged(self, event): etisserant@215: if not self.Initializing: lbessard@130: wx.CallAfter(self.SubrangeMaximum.SetValue, max(self.SubrangeMinimum.GetValue(), self.SubrangeMaximum.GetValue())) lbessard@130: wx.CallAfter(self.RefreshSubrangeInitialValueRange) lbessard@130: wx.CallAfter(self.RefreshTypeInfos) lbessard@125: event.Skip() lbessard@125: lbessard@125: def OnDimensionsChanged(self, event): lbessard@125: wx.CallAfter(self.RefreshTypeInfos) lbessard@125: event.Skip() lbessard@125: lbessard@295: def OnEnumeratedValueEndEdit(self, event): lbessard@295: text = event.GetText() lbessard@295: values = self.EnumeratedValues.GetStrings() lbessard@295: index = event.GetIndex() lbessard@295: if index >= len(values) or values[index].upper() != text.upper(): lbessard@295: if text.upper() in [value.upper() for value in values]: laurent@391: message = wx.MessageDialog(self, _("\"%s\" value already defined!")%text, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@295: message.ShowModal() lbessard@295: message.Destroy() lbessard@295: event.Veto() lbessard@295: elif text.upper() in IEC_KEYWORDS: laurent@391: message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%text, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@295: message.ShowModal() lbessard@295: message.Destroy() lbessard@295: else: lbessard@295: wx.CallAfter(self.RefreshEnumeratedValues) lbessard@295: wx.CallAfter(self.RefreshTypeInfos) lbessard@295: event.Skip() lbessard@295: else: lbessard@295: wx.CallAfter(self.RefreshEnumeratedValues) lbessard@295: wx.CallAfter(self.RefreshTypeInfos) lbessard@295: event.Skip() lbessard@295: lbessard@295: def OnEnumeratedValuesChanged(self, event): lbessard@295: wx.CallAfter(self.RefreshEnumeratedValues) lbessard@295: wx.CallAfter(self.RefreshTypeInfos) lbessard@295: event.Skip() lbessard@295: lbessard@295: def OnStructureAddButton(self, event): lbessard@295: new_row = self.StructureElementDefaultValue.copy() lbessard@295: self.StructureElementsTable.AppendRow(new_row) lbessard@295: self.RefreshTypeInfos() lbessard@295: self.StructureElementsTable.ResetView(self.StructureElementsGrid) lbessard@295: event.Skip() lbessard@295: lbessard@295: def OnStructureDeleteButton(self, event): lbessard@295: row = self.StructureElementsGrid.GetGridCursorRow() lbessard@295: self.StructureElementsTable.RemoveRow(row) lbessard@295: self.RefreshTypeInfos() lbessard@295: self.StructureElementsTable.ResetView(self.StructureElementsGrid) lbessard@295: event.Skip() lbessard@295: lbessard@295: def OnStructureUpButton(self, event): lbessard@295: row = self.StructureElementsGrid.GetGridCursorRow() lbessard@295: new_index = self.StructureElementsTable.MoveRow(row, -1) lbessard@295: if new_index is not None: lbessard@295: self.RefreshTypeInfos() lbessard@295: self.StructureElementsTable.ResetView(self.StructureElementsGrid) lbessard@295: self.StructureElementsGrid.SetGridCursor(new_index, self.StructureElementsGrid.GetGridCursorCol()) lbessard@295: event.Skip() lbessard@295: lbessard@295: def OnStructureDownButton(self, event): lbessard@295: row = self.StructureElementsGrid.GetGridCursorRow() lbessard@295: new_index = self.StructureElementsTable.MoveRow(row, 1) lbessard@295: if new_index is not None: lbessard@295: self.RefreshTypeInfos() lbessard@295: self.StructureElementsTable.ResetView(self.StructureElementsGrid) lbessard@295: self.StructureElementsGrid.SetGridCursor(new_index, self.StructureElementsGrid.GetGridCursorCol()) lbessard@295: event.Skip() lbessard@295: lbessard@295: def OnStructureElementsGridCellChange(self, event): lbessard@295: row, col = event.GetRow(), event.GetCol() lbessard@295: colname = self.StructureElementsTable.GetColLabelValue(col) lbessard@295: value = self.StructureElementsTable.GetValue(row, col) lbessard@295: if colname == "Name": lbessard@295: if not TestIdentifier(value): laurent@391: message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%value, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@295: message.ShowModal() lbessard@295: message.Destroy() lbessard@295: event.Veto() lbessard@295: elif value.upper() in IEC_KEYWORDS: laurent@391: message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%value, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@295: message.ShowModal() lbessard@295: message.Destroy() lbessard@295: event.Veto() lbessard@295: ## elif value.upper() in self.PouNames: lbessard@295: ## message = wx.MessageDialog(self, "A pou with \"%s\" as name exists!"%value, "Error", wx.OK|wx.ICON_ERROR) lbessard@295: ## message.ShowModal() lbessard@295: ## message.Destroy() lbessard@295: ## event.Veto() lbessard@295: elif value.upper() in [var["Name"].upper() for idx, var in enumerate(self.StructureElementsTable.GetData()) if idx != row]: b@427: message = wx.MessageDialog(self, _("An element named \"%s\" already exists in this structure!")%value, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@295: message.ShowModal() lbessard@295: message.Destroy() lbessard@295: event.Veto() lbessard@295: else: lbessard@295: self.RefreshTypeInfos() lbessard@295: self.StructureElementsTable.ResetView(self.StructureElementsGrid) lbessard@295: ## old_value = self.Table.GetOldValue() lbessard@295: ## if old_value != "": lbessard@295: ## self.Controler.UpdateEditedElementUsedVariable(self.TagName, old_value, value) lbessard@295: ## self.Controler.BufferProject() lbessard@295: event.Skip() lbessard@295: else: lbessard@295: self.RefreshTypeInfos() lbessard@295: self.StructureElementsTable.ResetView(self.StructureElementsGrid) lbessard@295: event.Skip() lbessard@295: lbessard@295: def OnStructureElementsGridEditorShown(self, event): lbessard@295: row, col = event.GetRow(), event.GetCol() lbessard@295: if self.StructureElementsTable.GetColLabelValue(col) == "Type": lbessard@295: type_menu = wx.Menu(title='') lbessard@295: base_menu = wx.Menu(title='') lbessard@295: for base_type in self.Controler.GetBaseTypes(): lbessard@295: new_id = wx.NewId() lbessard@295: AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type) lbessard@295: self.Bind(wx.EVT_MENU, self.GetElementTypeFunction(base_type), id=new_id) laurent@391: type_menu.AppendMenu(wx.NewId(), _("Base Types"), base_menu) lbessard@295: datatype_menu = wx.Menu(title='') laurent@462: for datatype in self.Controler.GetDataTypes(self.TagName, False): lbessard@295: new_id = wx.NewId() lbessard@295: AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype) lbessard@295: self.Bind(wx.EVT_MENU, self.GetElementTypeFunction(datatype), id=new_id) laurent@391: type_menu.AppendMenu(wx.NewId(), _("User Data Types"), datatype_menu) lbessard@295: ## functionblock_menu = wx.Menu(title='') laurent@462: ## bodytype = self.Controler.GetEditedElementBodyType(self.TagName) laurent@462: ## pouname, poutype = self.Controler.GetEditedElementType(self.TagName) lbessard@295: ## if classtype in ["Input","Output","InOut","External","Global"] or poutype != "function" and bodytype in ["ST", "IL"]: laurent@462: ## for functionblock_type in self.Controler.GetFunctionBlockTypes(self.TagName): lbessard@295: ## new_id = wx.NewId() lbessard@295: ## AppendMenu(functionblock_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=functionblock_type) lbessard@295: ## self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(functionblock_type), id=new_id) laurent@391: ## type_menu.AppendMenu(wx.NewId(), _("Function Block Types"), functionblock_menu) lbessard@295: rect = self.StructureElementsGrid.BlockToDeviceRect((row, col), (row, col)) lbessard@295: self.StructureElementsGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.StructureElementsGrid.GetColLabelSize()) lbessard@295: event.Veto() lbessard@295: else: lbessard@295: event.Skip() lbessard@295: lbessard@295: def GetElementTypeFunction(self, base_type): lbessard@295: def ElementTypeFunction(event): lbessard@295: row = self.StructureElementsGrid.GetGridCursorRow() lbessard@295: self.StructureElementsTable.SetValueByName(row, "Type", base_type) lbessard@295: self.RefreshTypeInfos() lbessard@295: self.StructureElementsTable.ResetView(self.StructureElementsGrid) lbessard@295: return ElementTypeFunction lbessard@295: lbessard@125: def RefreshDisplayedInfos(self): laurent@391: selected = DATATYPE_TYPES_DICT[self.DerivationType.GetStringSelection()] lbessard@125: if selected != self.CurrentPanel: lbessard@125: if self.CurrentPanel == "Directly": lbessard@125: self.DirectlyPanel.Hide() lbessard@125: elif self.CurrentPanel == "Subrange": lbessard@125: self.SubrangePanel.Hide() lbessard@125: elif self.CurrentPanel == "Enumerated": lbessard@125: self.EnumeratedPanel.Hide() lbessard@125: elif self.CurrentPanel == "Array": lbessard@125: self.ArrayPanel.Hide() lbessard@295: elif self.CurrentPanel == "Structure": lbessard@295: self.StructurePanel.Hide() lbessard@125: self.CurrentPanel = selected lbessard@125: if selected == "Directly": lbessard@125: self.DirectlyPanel.Show() lbessard@125: elif selected == "Subrange": lbessard@125: self.SubrangePanel.Show() lbessard@125: elif selected == "Enumerated": lbessard@125: self.EnumeratedPanel.Show() lbessard@125: elif selected == "Array": lbessard@125: self.ArrayPanel.Show() lbessard@295: elif selected == "Structure": lbessard@295: self.StructurePanel.Show() lbessard@125: self.MainSizer.Layout() lbessard@125: lbessard@125: def RefreshEnumeratedValues(self): lbessard@125: selected = self.EnumeratedInitialValue.GetStringSelection() lbessard@125: self.EnumeratedInitialValue.Clear() lbessard@125: self.EnumeratedInitialValue.Append("") lbessard@125: for value in self.EnumeratedValues.GetStrings(): lbessard@125: self.EnumeratedInitialValue.Append(value) lbessard@125: self.EnumeratedInitialValue.SetStringSelection(selected) lbessard@125: lbessard@125: def RefreshBoundsRange(self): lbessard@231: range = self.Controler.GetDataTypeRange(self.SubrangeBaseType.GetStringSelection()) lbessard@125: if range is not None: lbessard@125: min_value, max_value = range lbessard@125: self.SubrangeMinimum.SetRange(min_value, max_value) lbessard@125: self.SubrangeMinimum.SetValue(min(max(min_value, self.SubrangeMinimum.GetValue()), max_value)) lbessard@125: self.SubrangeMaximum.SetRange(min_value, max_value) lbessard@125: self.SubrangeMaximum.SetValue(min(max(min_value, self.SubrangeMaximum.GetValue()), max_value)) lbessard@125: lbessard@125: def RefreshSubrangeInitialValueRange(self): lbessard@125: self.SubrangeInitialValue.SetRange(self.SubrangeMinimum.GetValue(), self.SubrangeMaximum.GetValue()) lbessard@125: lbessard@125: def RefreshTypeInfos(self): laurent@391: selected = DATATYPE_TYPES_DICT[self.DerivationType.GetStringSelection()] lbessard@125: infos = {"type" : selected} lbessard@125: if selected == "Directly": lbessard@125: infos["base_type"] = self.DirectlyBaseType.GetStringSelection() lbessard@125: infos["initial"] = self.DirectlyInitialValue.GetValue() lbessard@125: elif selected == "Subrange": lbessard@125: infos["base_type"] = self.SubrangeBaseType.GetStringSelection() laurent@389: infos["min"] = str(self.SubrangeMinimum.GetValue()) laurent@389: infos["max"] = str(self.SubrangeMaximum.GetValue()) lbessard@125: initial_value = self.SubrangeInitialValue.GetValue() lbessard@125: if initial_value == infos["min"]: lbessard@125: infos["initial"] = "" lbessard@125: else: lbessard@125: infos["initial"] = str(initial_value) lbessard@125: elif selected == "Enumerated": lbessard@125: infos["values"] = self.EnumeratedValues.GetStrings() lbessard@125: infos["initial"] = self.EnumeratedInitialValue.GetStringSelection() lbessard@125: elif selected == "Array": lbessard@125: infos["base_type"] = self.ArrayBaseType.GetStringSelection() lbessard@207: infos["dimensions"] = [] lbessard@207: for dimensions in self.ArrayDimensions.GetStrings(): lbessard@207: result = DIMENSION_MODEL.match(dimensions) lbessard@207: if result is None: laurent@391: message = wx.MessageDialog(self, _("\"%s\" value isn't a valid array dimension!")%dimensions, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@207: message.ShowModal() lbessard@207: message.Destroy() lbessard@207: self.RefreshView() lbessard@207: return lbessard@207: bounds = result.groups() laurent@460: if int(bounds[0]) >= int(bounds[1]): laurent@391: message = wx.MessageDialog(self, _("\"%s\" value isn't a valid array dimension!\nRight value must be greater than left value.")%dimensions, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@207: message.ShowModal() lbessard@207: message.Destroy() lbessard@207: self.RefreshView() lbessard@207: return laurent@389: infos["dimensions"].append(bounds) lbessard@125: infos["initial"] = self.ArrayInitialValue.GetValue() lbessard@295: elif selected == "Structure": lbessard@295: infos["elements"] = self.StructureElementsTable.GetData() lbessard@295: infos["initial"] = "" lbessard@125: self.Controler.SetDataTypeInfos(self.TagName, infos) lbessard@125: self.ParentWindow.RefreshTitle() laurent@494: self.ParentWindow.RefreshFileMenu() lbessard@125: self.ParentWindow.RefreshEditMenu() lbessard@125: lbessard@231: #------------------------------------------------------------------------------- lbessard@231: # Errors showing functions lbessard@231: #------------------------------------------------------------------------------- lbessard@231: lbessard@231: def ClearErrors(self): lbessard@231: self.Errors = [] lbessard@231: self.RefreshView() lbessard@231: lbessard@231: def AddShownError(self, infos, start, end): lbessard@231: self.Errors.append((infos, start, end)) lbessard@231: lbessard@231: def ShowErrors(self): lbessard@231: type_infos = self.Controler.GetDataTypeInfos(self.TagName) lbessard@231: for infos, start, end in self.Errors: lbessard@231: if infos[0] == "base": lbessard@231: if type_infos["type"] == "Directly": lbessard@231: self.DirectlyBaseType.SetBackgroundColour(wx.Colour(255, 255, 0)) lbessard@231: self.DirectlyBaseType.SetForegroundColour(wx.RED) lbessard@231: elif type_infos["type"] == "Subrange": lbessard@231: self.SubrangeBaseType.SetBackgroundColour(wx.Colour(255, 255, 0)) lbessard@231: self.SubrangeBaseType.SetForegroundColour(wx.RED) lbessard@231: elif type_infos["type"] == "Array": lbessard@231: self.ArrayBaseType.SetBackgroundColour(wx.Colour(255, 255, 0)) lbessard@231: self.ArrayBaseType.SetForegroundColour(wx.RED) lbessard@231: elif infos[0] == "lower": lbessard@231: self.SubrangeMinimum.SetBackgroundColour(wx.Colour(255, 255, 0)) lbessard@231: self.SubrangeMaximum.SetForegroundColour(wx.RED) lbessard@231: elif infos[0] == "upper": lbessard@231: self.SubrangeMinimum.SetBackgroundColour(wx.Colour(255, 255, 0)) lbessard@231: self.SubrangeMaximum.SetForegroundColour(wx.RED) lbessard@231: elif infos[0] == "value": lbessard@231: listctrl = self.EnumeratedValues.GetListCtrl() lbessard@231: listctrl.SetItemBackgroundColour(infos[1], wx.Colour(255, 255, 0)) lbessard@231: listctrl.SetItemTextColour(infos[1], wx.RED) lbessard@231: listctrl.Select(listctrl.FocusedItem, False) lbessard@231: elif infos[0] == "range": lbessard@231: listctrl = self.EnumeratedValues.GetListCtrl() lbessard@231: listctrl.SetItemBackgroundColour(infos[1], wx.Colour(255, 255, 0)) lbessard@231: listctrl.SetItemTextColour(infos[1], wx.RED) lbessard@231: listctrl.SetStringSelection("") lbessard@231: elif infos[0] == "initial": lbessard@231: if type_infos["type"] == "Directly": lbessard@231: text = self.DirectlyInitialValue.GetValue() lbessard@231: self.DirectlyInitialValue.SetValue(text[:start[1]]) lbessard@231: self.DirectlyInitialValue.SetDefaultStyle(wx.TextAttr(wx.RED, wx.Colour(255, 255, 0))) lbessard@231: self.DirectlyInitialValue.AppendText(text[start[1]:end[1] + 1]) lbessard@231: self.DirectlyInitialValue.SetDefaultStyle(wx.TextAttr(wx.BLACK, wx.WHITE)) lbessard@231: self.DirectlyInitialValue.AppendText(text[end[1] + 1:]) lbessard@231: elif type_infos["type"] == "Subrange": lbessard@231: self.SubrangeInitialValue.SetBackgroundColour(wx.Colour(255, 255, 0)) lbessard@231: self.SubrangeInitialValue.SetForegroundColour(wx.RED) lbessard@231: elif type_infos["type"] == "Enumerated": lbessard@231: self.EnumeratedInitialValue.SetBackgroundColour(wx.Colour(255, 255, 0)) lbessard@231: self.EnumeratedInitialValue.SetForegroundColour(wx.RED) lbessard@231: elif type_infos["type"] == "Array": lbessard@231: text = self.ArrayInitialValue.GetValue() lbessard@231: self.ArrayInitialValue.SetValue(text[:start[1]]) lbessard@231: self.ArrayInitialValue.SetDefaultStyle(wx.TextAttr(wx.RED, wx.Colour(255, 255, 0))) lbessard@231: self.ArrayInitialValue.AppendText(text[start[1]:end[1] + 1]) lbessard@231: self.ArrayInitialValue.SetDefaultStyle(wx.TextAttr(wx.BLACK, wx.WHITE)) lbessard@231: self.ArrayInitialValue.AppendText(text[end[1] + 1:])