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@125: from plcopen.structures import GetDataTypeRange, IEC_KEYWORDS lbessard@125: lbessard@207: import re lbessard@207: lbessard@207: DIMENSION_MODEL = re.compile("([0-9]+)\.\.([0-9]+)$") lbessard@207: lbessard@125: if wx.VERSION >= (2, 8, 0): lbessard@125: import wx.aui lbessard@125: lbessard@125: class MDIDataTypeEditor(wx.aui.AuiMDIChildFrame): lbessard@125: def __init__(self, parent, tagname, window, controler): lbessard@125: wx.aui.AuiMDIChildFrame.__init__(self, parent, -1, title = "") lbessard@125: lbessard@125: sizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@125: lbessard@125: self.Viewer = DataTypeEditor(self, tagname, window, controler) lbessard@125: lbessard@125: sizer.AddWindow(self.Viewer, 1, border=0, flag=wx.GROW) lbessard@125: lbessard@125: self.SetSizer(sizer) lbessard@125: lbessard@125: def GetViewer(self): lbessard@125: return self.Viewer lbessard@125: lbessard@125: #------------------------------------------------------------------------------- lbessard@125: # Configuration 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@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@125: ] = [wx.NewId() for _init_ctrls in range(28)] lbessard@125: 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): lbessard@125: parent.AddWindow(self.staticText1, 0, border=5, flag=wx.GROW|wx.LEFT) lbessard@125: parent.AddWindow(self.DerivationType, 0, border=0, flag=wx.GROW) 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@125: lbessard@125: def _init_coll_DirectlyPanelSizer_Items(self, parent): lbessard@125: parent.AddWindow(self.staticText2, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(self.DirectlyBaseType, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(self.staticText3, 1, border=5, flag=wx.GROW|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): lbessard@125: parent.AddWindow(self.staticText4, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(self.SubrangeBaseType, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(self.staticText5, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(self.SubrangeInitialValue, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(self.staticText6, 1, border=5, flag=wx.GROW|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) lbessard@125: parent.AddWindow(self.staticText7, 1, border=5, flag=wx.GROW|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): lbessard@125: parent.AddWindow(self.EnumeratedValues, 2, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(self.staticText8, 1, border=5, flag=wx.GROW|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) lbessard@125: parent.AddSizer(self.ArrayPanelRightSizer, 0, border=0, flag=wx.GROW) 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): lbessard@125: parent.AddWindow(self.staticText9, 1, border=5, flag=wx.GROW|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): lbessard@125: parent.AddWindow(self.staticText10, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: parent.AddWindow(self.ArrayInitialValue, 1, border=5, flag=wx.GROW|wx.ALL) lbessard@125: 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) lbessard@125: self.SubrangePanelSizer = wx.GridSizer(cols=4, hgap=0, rows=3, vgap=0) lbessard@125: self.EnumeratedPanelSizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@125: self.ArrayPanelSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=2, vgap=0) lbessard@125: self.ArrayPanelLeftSizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@125: self.ArrayPanelRightSizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@125: 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) 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@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@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, lbessard@125: label='Type infos:', name='staticBox1', parent=self, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0) lbessard@125: lbessard@125: self.staticText1 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT1, lbessard@125: label='Derivation Type:', name='staticText1', parent=self, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), style=0) lbessard@125: lbessard@125: self.DerivationType = wx.Choice(id=ID_DATATYPEEDITORDERIVATIONTYPE, lbessard@125: name='DerivationType', parent=self, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(200, 24), style=0) lbessard@125: self.Bind(wx.EVT_CHOICE, 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, lbessard@125: label='Base Type:', name='staticText2', parent=self.DirectlyPanel, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), style=0) lbessard@125: lbessard@125: self.DirectlyBaseType = wx.Choice(id=ID_DATATYPEEDITORDIRECTLYBASETYPE, lbessard@125: name='DirectlyBaseType', parent=self.DirectlyPanel, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL) lbessard@125: self.Bind(wx.EVT_CHOICE, self.OnInfosChanged, id=ID_DATATYPEEDITORDIRECTLYBASETYPE) lbessard@125: lbessard@125: self.staticText3 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT3, lbessard@125: label='Initial Value:', name='staticText3', parent=self.DirectlyPanel, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), 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@125: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER) lbessard@125: self.Bind(wx.EVT_TEXT_ENTER, self.OnInfosChanged, 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, lbessard@125: label='Base Type:', name='staticText4', parent=self.SubrangePanel, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), style=0) lbessard@125: lbessard@125: self.SubrangeBaseType = wx.Choice(id=ID_DATATYPEEDITORSUBRANGEBASETYPE, lbessard@125: name='SubrangeBaseType', 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_CHOICE, self.OnSubrangeBaseTypeChanged, id=ID_DATATYPEEDITORSUBRANGEBASETYPE) lbessard@125: lbessard@125: self.staticText5 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT5, lbessard@125: label='Initial Value:', name='staticText5', parent=self.SubrangePanel, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), 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, lbessard@125: label='Minimum:', name='staticText6', parent=self.SubrangePanel, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), 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, lbessard@125: label='Maximum:', name='staticText7', parent=self.SubrangePanel, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), 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, lbessard@125: 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) lbessard@125: self.EnumeratedValues.GetNewButton().Bind(wx.EVT_BUTTON, self.OnEnumeratedValuesChanged) lbessard@125: self.EnumeratedValues.GetDelButton().Bind(wx.EVT_BUTTON, self.OnEnumeratedValuesChanged) lbessard@125: self.EnumeratedValues.GetUpButton().Bind(wx.EVT_BUTTON, self.OnEnumeratedValuesChanged) lbessard@125: self.EnumeratedValues.GetDownButton().Bind(wx.EVT_BUTTON, self.OnEnumeratedValuesChanged) lbessard@125: lbessard@125: self.staticText8 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT8, lbessard@125: label='Initial Value:', name='staticText8', parent=self.EnumeratedPanel, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), style=0) lbessard@125: lbessard@125: self.EnumeratedInitialValue = wx.Choice(id=ID_DATATYPEEDITORENUMERATEDINITIALVALUE, lbessard@125: name='EnumeratedInitialValue', parent=self.EnumeratedPanel, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER) lbessard@125: self.Bind(wx.EVT_CHOICE, 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, lbessard@125: label='Base Type:', name='staticText9', parent=self.ArrayPanel, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), style=0) lbessard@125: lbessard@125: self.ArrayBaseType = wx.Choice(id=ID_DATATYPEEDITORARRAYBASETYPE, lbessard@125: name='SubrangeBaseType', parent=self.ArrayPanel, pos=wx.Point(0, 0), lbessard@125: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL) lbessard@125: self.Bind(wx.EVT_CHOICE, self.OnInfosChanged, id=ID_DATATYPEEDITORARRAYBASETYPE) lbessard@125: lbessard@125: self.ArrayDimensions = wx.gizmos.EditableListBox(id=ID_DATATYPEEDITORARRAYDIMENSIONS, lbessard@125: 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) lbessard@125: self.ArrayDimensions.GetNewButton().Bind(wx.EVT_BUTTON, self.OnDimensionsChanged) lbessard@125: self.ArrayDimensions.GetDelButton().Bind(wx.EVT_BUTTON, self.OnDimensionsChanged) lbessard@125: self.ArrayDimensions.GetUpButton().Bind(wx.EVT_BUTTON, self.OnDimensionsChanged) lbessard@125: self.ArrayDimensions.GetDownButton().Bind(wx.EVT_BUTTON, self.OnDimensionsChanged) lbessard@125: lbessard@125: self.staticText10 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT10, lbessard@125: label='Initial Value:', name='staticText10', parent=self.ArrayPanel, lbessard@125: pos=wx.Point(0, 0), size=wx.Size(150, 17), 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@125: size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER) lbessard@125: self.Bind(wx.EVT_TEXT_ENTER, self.OnInfosChanged, id=ID_DATATYPEEDITORARRAYINITIALVALUE) lbessard@125: 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@125: self.DerivationType.Append("Directly") lbessard@125: self.DerivationType.Append("Subrange") lbessard@125: self.DerivationType.Append("Enumerated") lbessard@125: self.DerivationType.Append("Array") lbessard@125: self.SubrangePanel.Hide() lbessard@125: self.EnumeratedPanel.Hide() lbessard@125: self.ArrayPanel.Hide() lbessard@125: self.CurrentPanel = "Directly" 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 OnEnumeratedValueEndEdit(self, event): lbessard@125: text = event.GetText() lbessard@192: values = self.EnumeratedValues.GetStrings() lbessard@192: index = event.GetIndex() lbessard@192: if index >= len(values) or values[index].upper() != text.upper(): lbessard@192: if text.upper() in [value.upper() for value in values]: lbessard@150: message = wx.MessageDialog(self, "\"%s\" value already defined!"%text, "Error", wx.OK|wx.ICON_ERROR) lbessard@150: message.ShowModal() lbessard@150: message.Destroy() lbessard@150: event.Veto() lbessard@150: elif text.upper() in IEC_KEYWORDS: lbessard@150: message = wx.MessageDialog(self, "\"%s\" is a keyword. It can't be used!"%text, "Error", wx.OK|wx.ICON_ERROR) lbessard@150: message.ShowModal() lbessard@150: message.Destroy() lbessard@150: else: lbessard@150: wx.CallAfter(self.RefreshEnumeratedValues) lbessard@150: wx.CallAfter(self.RefreshTypeInfos) lbessard@150: event.Skip() lbessard@125: else: lbessard@125: wx.CallAfter(self.RefreshEnumeratedValues) lbessard@125: wx.CallAfter(self.RefreshTypeInfos) lbessard@125: event.Skip() lbessard@125: lbessard@125: def OnEnumeratedValuesChanged(self, event): lbessard@125: wx.CallAfter(self.RefreshEnumeratedValues) lbessard@125: wx.CallAfter(self.RefreshTypeInfos) lbessard@125: event.Skip() 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: 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@125: for base_type in self.Controler.GetSubrangeTypes(): 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: lbessard@125: self.DerivationType.SetStringSelection(type_infos["type"]) 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() lbessard@125: self.SubrangeMinimum.SetValue(type_infos["min"]) lbessard@125: self.SubrangeMaximum.SetValue(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"]) lbessard@207: self.ArrayDimensions.SetStrings(map(lambda x : "..".join(map(str, x)), type_infos["dimensions"])) lbessard@125: self.ArrayInitialValue.SetValue(type_infos["initial"]) lbessard@125: self.RefreshDisplayedInfos() 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@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): lbessard@130: if 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): lbessard@130: if 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@125: def RefreshDisplayedInfos(self): lbessard@125: selected = 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@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@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@125: range = 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): lbessard@125: selected = 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() lbessard@125: infos["min"] = self.SubrangeMinimum.GetValue() lbessard@125: infos["max"] = 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: lbessard@207: 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() lbessard@207: if bounds[0] >= bounds[1]: lbessard@207: 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 lbessard@207: infos["dimensions"].append(map(int, bounds)) lbessard@125: infos["initial"] = self.ArrayInitialValue.GetValue() lbessard@125: self.Controler.SetDataTypeInfos(self.TagName, infos) lbessard@125: self.ParentWindow.RefreshTitle() lbessard@125: self.ParentWindow.RefreshEditMenu() lbessard@125: