laurent@2022: import wx laurent@2026: import wx.grid laurent@2022: laurent@2022: from controls import CustomGrid, CustomTable, EditorPanel laurent@2022: laurent@2022: [ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE] = range(3) laurent@2022: laurent@2022: def AppendMenu(parent, help, id, kind, text): laurent@2022: if wx.VERSION >= (2, 6, 0): laurent@2022: parent.Append(help=help, id=id, kind=kind, text=text) laurent@2022: else: laurent@2022: parent.Append(helpString=help, id=id, kind=kind, item=text) laurent@2022: laurent@2022: [ID_SLAVETYPECHOICEDIALOG, ID_SLAVETYPECHOICEDIALOGSTATICTEXT1, laurent@2022: ID_SLAVETYPECHOICEDIALOGSLAVETYPESLIBRARY laurent@2022: ] = [wx.NewId() for _init_ctrls in range(3)] laurent@2022: laurent@2022: class SlaveTypeChoiceDialog(wx.Dialog): laurent@2022: laurent@2022: if wx.VERSION < (2, 6, 0): laurent@2022: def Bind(self, event, function, id = None): laurent@2022: if id is not None: laurent@2022: event(self, id, function) laurent@2022: else: laurent@2022: event(self, function) laurent@2022: laurent@2022: def _init_coll_flexGridSizer1_Items(self, parent): laurent@2022: parent.AddWindow(self.staticText1, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) laurent@2022: parent.AddWindow(self.SlaveTypesLibrary, 0, border=20, flag=wx.GROW|wx.LEFT|wx.RIGHT) laurent@2022: parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) laurent@2022: laurent@2022: def _init_coll_flexGridSizer1_Growables(self, parent): laurent@2022: parent.AddGrowableCol(0) laurent@2022: parent.AddGrowableRow(1) laurent@2022: laurent@2022: def _init_sizers(self): laurent@2022: self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10) laurent@2022: laurent@2022: self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) laurent@2022: self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1) laurent@2022: laurent@2022: self.SetSizer(self.flexGridSizer1) laurent@2022: laurent@2022: def _init_ctrls(self, prnt): laurent@2022: wx.Dialog.__init__(self, id=ID_SLAVETYPECHOICEDIALOG, laurent@2022: name='SlaveTypeChoiceDialog', parent=prnt, laurent@2022: size=wx.Size(600, 400), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER, laurent@2022: title=_('Browse slave types library')) laurent@2022: self.SetClientSize(wx.Size(600, 400)) laurent@2022: laurent@2022: self.staticText1 = wx.StaticText(id=ID_SLAVETYPECHOICEDIALOGSTATICTEXT1, laurent@2022: label=_('Choose a slave type:'), name='staticText1', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2022: laurent@2022: self.SlaveTypesLibrary = wx.TreeCtrl(id=ID_SLAVETYPECHOICEDIALOGSLAVETYPESLIBRARY, laurent@2022: name='TypeTree', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 0), style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER|wx.TR_HIDE_ROOT|wx.TR_LINES_AT_ROOT) laurent@2022: laurent@2022: self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) laurent@2022: if wx.VERSION >= (2, 5, 0): laurent@2022: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId()) laurent@2022: else: laurent@2022: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId()) laurent@2022: laurent@2022: self._init_sizers() laurent@2022: laurent@2022: def __init__(self, parent, controler, default=None): laurent@2022: self._init_ctrls(parent) laurent@2022: laurent@2022: slaves_types = controler.GetSlaveTypesLibrary() laurent@2022: laurent@2022: root = self.SlaveTypesLibrary.AddRoot("") laurent@2022: self.GenerateSlaveTypesLibraryTreeBranch(root, slaves_types, default) laurent@2022: laurent@2022: def GenerateSlaveTypesLibraryTreeBranch(self, root, children, default): laurent@2022: for infos in children: laurent@2022: item = self.SlaveTypesLibrary.AppendItem(root, infos["name"]) laurent@2022: if infos["type"] == ETHERCAT_DEVICE: laurent@2022: self.SlaveTypesLibrary.SetPyData(item, infos["infos"]) laurent@2022: if infos["infos"] == default: laurent@2022: self.SlaveTypesLibrary.SelectItem(item) laurent@2022: self.SlaveTypesLibrary.EnsureVisible(item) laurent@2022: else: laurent@2022: self.GenerateSlaveTypesLibraryTreeBranch(item, infos["children"], default) laurent@2022: laurent@2022: def GetType(self): laurent@2022: selected = self.SlaveTypesLibrary.GetSelection() laurent@2022: return self.SlaveTypesLibrary.GetPyData(selected) laurent@2022: laurent@2022: def OnOK(self, event): laurent@2022: selected = self.SlaveTypesLibrary.GetSelection() laurent@2022: if not selected.IsOk() or self.SlaveTypesLibrary.GetPyData(selected) is None: laurent@2022: message = wx.MessageDialog(self, _("No valid slave type selected!"), _("Error"), wx.OK|wx.ICON_ERROR) laurent@2022: message.ShowModal() laurent@2022: message.Destroy() laurent@2022: else: laurent@2022: self.EndModal(wx.ID_OK) laurent@2022: laurent@2029: def GetSyncManagersTableColnames(): laurent@2029: _ = lambda x : x laurent@2029: return ["#", _("Name"), _("Start Address"), _("Default Size"), _("Control Byte"), _("Enable")] laurent@2029: laurent@2029: class SyncManagersTable(CustomTable): laurent@2029: laurent@2029: def GetValue(self, row, col): laurent@2029: if row < self.GetNumberRows(): laurent@2029: if col == 0: laurent@2029: return row laurent@2029: return self.data[row].get(self.GetColLabelValue(col, False), "") laurent@2022: laurent@2022: def GetVariablesTableColnames(): laurent@2022: _ = lambda x : x laurent@2023: return ["#", _("Index"), _("SubIndex"), _("Name"), _("Type"), _("PDO index"), _("PDO name"), _("PDO type")] laurent@2022: laurent@2022: class VariablesTable(CustomTable): laurent@2022: laurent@2022: def GetValue(self, row, col): laurent@2022: if row < self.GetNumberRows(): laurent@2022: if col == 0: laurent@2022: return row + 1 laurent@2022: return self.data[row].get(self.GetColLabelValue(col, False), "") laurent@2022: laurent@2029: def _updateColAttrs(self, grid): laurent@2029: """ laurent@2029: wx.grid.Grid -> update the column attributes to add the laurent@2029: appropriate renderer given the column name. laurent@2029: laurent@2029: Otherwise default to the default renderer. laurent@2029: """ laurent@2029: for row in range(self.GetNumberRows()): laurent@2029: row_highlights = self.Highlights.get(row, {}) laurent@2029: access = self.GetValueByName(row, "Access") laurent@2029: for col in range(self.GetNumberCols()): laurent@2029: colname = self.GetColLabelValue(col, False) laurent@2029: laurent@2029: if colname in ["PDO index", "PDO name", "PDO type"] and access == "": laurent@2029: highlight_colours = (wx.LIGHT_GREY, wx.WHITE) laurent@2029: else: laurent@2029: highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1] laurent@2029: grid.SetReadOnly(row, col, True) laurent@2029: grid.SetCellEditor(row, col, None) laurent@2029: grid.SetCellRenderer(row, col, None) laurent@2029: laurent@2029: grid.SetCellBackgroundColour(row, col, highlight_colours[0]) laurent@2029: grid.SetCellTextColour(row, col, highlight_colours[1]) laurent@2029: self.ResizeRow(grid, row) laurent@2029: laurent@2022: [ID_SLAVEPANEL, ID_SLAVEPANELTYPELABEL, laurent@2022: ID_SLAVEPANELTYPE, ID_SLAVEPANELTYPEBROWSE, laurent@2022: ID_SLAVEPANELALIASLABEL, ID_SLAVEPANELALIAS, laurent@2022: ID_SLAVEPANELPOSLABEL, ID_SLAVEPANELPOS, laurent@2022: ID_SLAVEPANELSLAVEINFOSSTATICBOX, ID_SLAVEPANELVENDORLABEL, laurent@2022: ID_SLAVEPANELVENDOR, ID_SLAVEPANELPRODUCTCODELABEL, laurent@2022: ID_SLAVEPANELPRODUCTCODE, ID_SLAVEPANELREVISIONNUMBERLABEL, laurent@2022: ID_SLAVEPANELREVISIONNUMBER, ID_SLAVEPANELPHYSICSLABEL, laurent@2029: ID_SLAVEPANELPHYSICS, ID_SLAVEPANELSYNCMANAGERSLABEL, laurent@2029: ID_SLAVEPANELSYNCMANAGERSGRID, ID_SLAVEPANELVARIABLESLABEL, laurent@2022: ID_SLAVEPANELVARIABLESGRID, laurent@2022: ] = [wx.NewId() for _init_ctrls in range(21)] laurent@2022: laurent@2022: class SlavePanel(wx.Panel): laurent@2022: laurent@2022: if wx.VERSION < (2, 6, 0): laurent@2022: def Bind(self, event, function, id = None): laurent@2022: if id is not None: laurent@2022: event(self, id, function) laurent@2022: else: laurent@2022: event(self, function) laurent@2022: laurent@2022: def _init_coll_MainSizer_Items(self, parent): laurent@2022: parent.AddSizer(self.PositionSizer, 0, border=5, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) laurent@2022: parent.AddSizer(self.SlaveInfosBoxSizer, 0, border=5, flag=wx.GROW|wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT) laurent@2022: laurent@2022: def _init_coll_MainSizer_Growables(self, parent): laurent@2022: parent.AddGrowableCol(0) laurent@2022: parent.AddGrowableRow(1) laurent@2022: laurent@2022: def _init_coll_PositionSizer_Items(self, parent): laurent@2022: parent.AddWindow(self.TypeLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL) laurent@2022: parent.AddSizer(self.TypeSizer, 0, border=0, flag=wx.GROW) laurent@2022: parent.AddWindow(self.AliasLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL) laurent@2022: parent.AddWindow(self.Alias, 0, border=0, flag=wx.GROW) laurent@2022: parent.AddWindow(self.PosLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL) laurent@2022: parent.AddWindow(self.Pos, 0, border=0, flag=wx.GROW) laurent@2022: laurent@2022: def _init_coll_PositionSizer_Growables(self, parent): laurent@2022: parent.AddGrowableCol(1) laurent@2022: parent.AddGrowableCol(3) laurent@2022: parent.AddGrowableCol(5) laurent@2022: parent.AddGrowableRow(0) laurent@2022: laurent@2022: def _init_coll_TypeSizer_Items(self, parent): laurent@2022: parent.AddWindow(self.Type, 1, border=0, flag=0) laurent@2022: parent.AddWindow(self.TypeBrowse, 0, border=0, flag=0) laurent@2022: laurent@2022: def _init_coll_SlaveInfosBoxSizer_Items(self, parent): laurent@2022: parent.AddSizer(self.SlaveInfosSizer, 1, border=5, flag=wx.GROW|wx.ALL) laurent@2022: laurent@2022: def _init_coll_SlaveInfosSizer_Items(self, parent): laurent@2022: parent.AddSizer(self.SlaveInfosDetailsSizer, 0, border=0, flag=wx.GROW) laurent@2029: parent.AddWindow(self.SyncManagersLabel, 0, border=0, flag=wx.GROW) laurent@2029: parent.AddWindow(self.SyncManagersGrid, 0, border=0, flag=wx.GROW) laurent@2022: parent.AddWindow(self.VariablesLabel, 0, border=0, flag=wx.GROW) laurent@2022: parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW) laurent@2022: laurent@2022: def _init_coll_SlaveInfosSizer_Growables(self, parent): laurent@2022: parent.AddGrowableCol(0) laurent@2029: parent.AddGrowableRow(2, 1) laurent@2029: parent.AddGrowableRow(4, 2) laurent@2023: laurent@2022: def _init_coll_SlaveInfosDetailsSizer_Items(self, parent): laurent@2022: parent.AddWindow(self.VendorLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.GROW) laurent@2022: parent.AddWindow(self.Vendor, 0, border=0, flag=wx.GROW) laurent@2022: parent.AddWindow(self.ProductCodeLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.GROW) laurent@2022: parent.AddWindow(self.ProductCode, 0, border=0, flag=wx.GROW) laurent@2022: parent.AddWindow(self.RevisionNumberLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.GROW) laurent@2022: parent.AddWindow(self.RevisionNumber, 0, border=0, flag=wx.GROW) laurent@2022: parent.AddWindow(self.PhysicsLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.GROW) laurent@2022: parent.AddWindow(self.Physics, 0, border=0, flag=wx.GROW) laurent@2022: laurent@2022: def _init_coll_SlaveInfosDetailsSizer_Growables(self, parent): laurent@2022: parent.AddGrowableCol(1) laurent@2022: parent.AddGrowableCol(3) laurent@2022: laurent@2022: def _init_sizers(self): laurent@2022: self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) laurent@2022: self.PositionSizer = wx.FlexGridSizer(cols=6, hgap=5, rows=1, vgap=0) laurent@2022: self.TypeSizer = wx.BoxSizer(wx.HORIZONTAL) laurent@2022: self.SlaveInfosBoxSizer = wx.StaticBoxSizer(self.SlaveInfosStaticBox, wx.VERTICAL) laurent@2029: self.SlaveInfosSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=5, vgap=5) laurent@2022: self.SlaveInfosDetailsSizer = wx.FlexGridSizer(cols=4, hgap=5, rows=2, vgap=5) laurent@2022: laurent@2022: self._init_coll_MainSizer_Growables(self.MainSizer) laurent@2022: self._init_coll_MainSizer_Items(self.MainSizer) laurent@2022: self._init_coll_PositionSizer_Growables(self.PositionSizer) laurent@2022: self._init_coll_PositionSizer_Items(self.PositionSizer) laurent@2022: self._init_coll_TypeSizer_Items(self.TypeSizer) laurent@2022: self._init_coll_SlaveInfosBoxSizer_Items(self.SlaveInfosBoxSizer) laurent@2022: self._init_coll_SlaveInfosSizer_Growables(self.SlaveInfosSizer) laurent@2022: self._init_coll_SlaveInfosSizer_Items(self.SlaveInfosSizer) laurent@2022: self._init_coll_SlaveInfosDetailsSizer_Growables(self.SlaveInfosDetailsSizer) laurent@2022: self._init_coll_SlaveInfosDetailsSizer_Items(self.SlaveInfosDetailsSizer) laurent@2022: laurent@2022: self.SetSizer(self.MainSizer) laurent@2022: laurent@2022: def _init_ctrls(self, prnt): laurent@2022: wx.Panel.__init__(self, id=ID_SLAVEPANEL, name='SlavePanel', parent=prnt, laurent@2022: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) laurent@2022: laurent@2022: self.TypeLabel = wx.StaticText(id=ID_SLAVEPANELTYPELABEL, laurent@2022: label=_('Type:'), name='TypeLabel', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2022: laurent@2022: self.Type = wx.TextCtrl(id=ID_SLAVEPANELTYPE, value='', laurent@2022: name='Type', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 24), style=wx.TE_READONLY) laurent@2022: laurent@2022: self.TypeBrowse = wx.Button(id=ID_SLAVEPANELTYPEBROWSE, label='...', laurent@2022: name='TypeBrowse', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(30, 24), style=0) laurent@2022: self.Bind(wx.EVT_BUTTON, self.OnTypeBrowseClick, id=ID_SLAVEPANELTYPEBROWSE) laurent@2022: laurent@2022: self.AliasLabel = wx.StaticText(id=ID_SLAVEPANELALIASLABEL, laurent@2022: label=_('Alias:'), name='AliasLabel', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2022: laurent@2022: self.Alias = wx.SpinCtrl(id=ID_SLAVEPANELALIAS, laurent@2022: name='Alias', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 24), style=wx.SP_ARROW_KEYS, min=0, max=0xffff) laurent@2022: self.Bind(wx.EVT_SPINCTRL, self.OnAliasChanged, id=ID_SLAVEPANELALIAS) laurent@2022: laurent@2022: self.PosLabel = wx.StaticText(id=ID_SLAVEPANELPOSLABEL, laurent@2022: label=_('Position:'), name='PositionLabel', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2022: laurent@2022: self.Pos = wx.SpinCtrl(id=ID_SLAVEPANELPOS, laurent@2022: name='Pos', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 24), style=wx.SP_ARROW_KEYS, min=0, max=0xffff) laurent@2022: self.Bind(wx.EVT_SPINCTRL, self.OnPositionChanged, id=ID_SLAVEPANELPOS) laurent@2022: laurent@2022: self.SlaveInfosStaticBox = wx.StaticBox(id=ID_SLAVEPANELSLAVEINFOSSTATICBOX, laurent@2022: label=_('Slave infos:'), name='SlaveInfosStaticBox', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0) laurent@2022: laurent@2022: self.VendorLabel = wx.StaticText(id=ID_SLAVEPANELVENDORLABEL, laurent@2022: label=_('Vendor:'), name='VendorLabel', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2022: laurent@2022: self.Vendor = wx.TextCtrl(id=ID_SLAVEPANELVENDOR, value='', laurent@2022: name='Vendor', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 24), style=wx.TE_READONLY) laurent@2022: laurent@2022: self.ProductCodeLabel = wx.StaticText(id=ID_SLAVEPANELPRODUCTCODELABEL, laurent@2022: label=_('Product code:'), name='ProductCodeLabel', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2022: laurent@2022: self.ProductCode = wx.TextCtrl(id=ID_SLAVEPANELPRODUCTCODE, value='', laurent@2022: name='ProductCode', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 24), style=wx.TE_READONLY) laurent@2022: laurent@2022: self.RevisionNumberLabel = wx.StaticText(id=ID_SLAVEPANELREVISIONNUMBERLABEL, laurent@2022: label=_('Revision number:'), name='RevisionNumberLabel', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2022: laurent@2022: self.RevisionNumber = wx.TextCtrl(id=ID_SLAVEPANELREVISIONNUMBER, value='', laurent@2022: name='RevisionNumber', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 24), style=wx.TE_READONLY) laurent@2022: laurent@2022: self.PhysicsLabel = wx.StaticText(id=ID_SLAVEPANELPHYSICSLABEL, laurent@2022: label=_('Physics:'), name='PhysicsLabel', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2022: laurent@2022: self.Physics = wx.TextCtrl(id=ID_SLAVEPANELPHYSICS, value='', laurent@2022: name='Physics', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 24), style=wx.TE_READONLY) laurent@2022: laurent@2029: self.SyncManagersLabel = wx.StaticText(id=ID_SLAVEPANELSYNCMANAGERSLABEL, laurent@2029: label=_('Sync managers:'), name='SyncManagersLabel', parent=self, laurent@2029: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2029: laurent@2029: self.SyncManagersGrid = CustomGrid(id=ID_SLAVEPANELSYNCMANAGERSGRID, laurent@2029: name='SyncManagersGrid', parent=self, pos=wx.Point(0, 0), laurent@2029: size=wx.Size(0, 0), style=wx.VSCROLL) laurent@2029: laurent@2022: self.VariablesLabel = wx.StaticText(id=ID_SLAVEPANELVARIABLESLABEL, laurent@2022: label=_('Variable entries:'), name='VariablesLabel', parent=self, laurent@2022: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) laurent@2022: laurent@2029: self.VariablesGrid = CustomGrid(id=ID_SLAVEPANELVARIABLESGRID, laurent@2029: name='VariablesGrid', parent=self, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 0), style=wx.VSCROLL) laurent@2022: if wx.VERSION >= (2, 5, 0): laurent@2022: self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick) laurent@2022: else: laurent@2022: wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick) laurent@2022: laurent@2022: self._init_sizers() laurent@2022: laurent@2022: def __init__(self, parent, controler, window, slave): laurent@2022: self._init_ctrls(parent) laurent@2022: laurent@2022: self.Controler = controler laurent@2022: self.ParentWindow = window laurent@2022: self.Slave = slave laurent@2022: laurent@2029: self.SyncManagersTable = SyncManagersTable(self, [], GetSyncManagersTableColnames()) laurent@2029: self.SyncManagersGrid.SetTable(self.SyncManagersTable) laurent@2029: self.SyncManagersGridColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, laurent@2029: wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT] laurent@2029: self.SyncManagersGridColSizes = [40, 150, 100, 100, 100, 100] laurent@2029: self.SyncManagersGrid.SetRowLabelSize(0) laurent@2029: for col in range(self.SyncManagersTable.GetNumberCols()): laurent@2029: attr = wx.grid.GridCellAttr() laurent@2029: attr.SetAlignment(self.SyncManagersGridColAlignements[col], wx.ALIGN_CENTRE) laurent@2029: self.SyncManagersGrid.SetColAttr(col, attr) laurent@2029: self.SyncManagersGrid.SetColMinimalWidth(col, self.SyncManagersGridColSizes[col]) laurent@2029: self.SyncManagersGrid.AutoSizeColumn(col, False) laurent@2029: laurent@2022: self.VariablesTable = VariablesTable(self, [], GetVariablesTableColnames()) laurent@2022: self.VariablesGrid.SetTable(self.VariablesTable) laurent@2023: self.VariablesGridColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, laurent@2023: wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, laurent@2023: wx.ALIGN_LEFT, wx.ALIGN_LEFT] laurent@2023: self.VariablesGridColSizes = [40, 100, 100, 150, 150, 100, 150, 100] laurent@2022: self.VariablesGrid.SetRowLabelSize(0) laurent@2022: for col in range(self.VariablesTable.GetNumberCols()): laurent@2022: attr = wx.grid.GridCellAttr() laurent@2022: attr.SetAlignment(self.VariablesGridColAlignements[col], wx.ALIGN_CENTRE) laurent@2022: self.VariablesGrid.SetColAttr(col, attr) laurent@2022: self.VariablesGrid.SetColMinimalWidth(col, self.VariablesGridColSizes[col]) laurent@2022: self.VariablesGrid.AutoSizeColumn(col, False) laurent@2022: laurent@2022: self.RefreshView() laurent@2022: laurent@2022: def GetSlaveTitle(self): laurent@2022: type_infos = self.Controler.GetSlaveType(self.Slave) laurent@2022: return "%s (%d:%d)" % (type_infos["device_type"], self.Slave[0], self.Slave[1]) laurent@2022: laurent@2022: def GetSlave(self): laurent@2022: return self.Slave laurent@2022: laurent@2022: def SetSlave(self, slave): laurent@2022: if self.Slave != slave: laurent@2022: self.Slave = slave laurent@2022: self.RefreshView() laurent@2022: laurent@2022: def RefreshView(self): laurent@2022: self.Alias.SetValue(self.Slave[0]) laurent@2022: self.Pos.SetValue(self.Slave[1]) laurent@2022: slave_infos = self.Controler.GetSlaveInfos(self.Slave) laurent@2022: if slave_infos is not None: laurent@2022: self.Type.SetValue(slave_infos["device_type"]) laurent@2022: self.Vendor.SetValue(slave_infos["vendor"]) laurent@2022: self.ProductCode.SetValue(slave_infos["product_code"]) laurent@2022: self.RevisionNumber.SetValue(slave_infos["revision_number"]) laurent@2022: self.Physics.SetValue(slave_infos["physics"]) laurent@2029: self.SyncManagersTable.SetData(slave_infos["sync_managers"]) laurent@2029: self.SyncManagersTable.ResetView(self.SyncManagersGrid) laurent@2029: self.VariablesTable.SetData(slave_infos["entries"]) laurent@2022: self.VariablesTable.ResetView(self.VariablesGrid) laurent@2022: else: laurent@2022: type_infos = self.Controler.GetSlaveType(self.Slave) laurent@2022: self.Type.SetValue(type_infos["device_type"]) laurent@2022: laurent@2022: def OnAliasChanged(self, event): laurent@2022: alias = self.Alias.GetValue() laurent@2022: if alias != self.Slave[0]: laurent@2022: result = self.Controler.SetSlavePos(self.Slave[:2], alias = alias) laurent@2022: if result is not None: laurent@2022: message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) laurent@2022: message.ShowModal() laurent@2022: message.Destroy() laurent@2022: else: laurent@2022: wx.CallAfter(self.ParentWindow.RefreshView, (alias, self.Slave[1])) laurent@2022: wx.CallAfter(self.ParentWindow.RefreshParentWindow) laurent@2022: event.Skip() laurent@2022: laurent@2022: def OnPositionChanged(self, event): laurent@2022: position = self.Pos.GetValue() laurent@2022: if position != self.Slave[1]: laurent@2022: result = self.Controler.SetSlavePos(self.Slave, position = position) laurent@2022: if result is not None: laurent@2022: message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) laurent@2022: message.ShowModal() laurent@2022: message.Destroy() laurent@2022: else: laurent@2022: wx.CallAfter(self.ParentWindow.RefreshView, (self.Slave[0], position)) laurent@2022: wx.CallAfter(self.ParentWindow.RefreshParentWindow) laurent@2022: event.Skip() laurent@2022: laurent@2022: def OnTypeBrowseClick(self, event): laurent@2022: dialog = SlaveTypeChoiceDialog(self, self.Controler, self.Controler.GetSlaveType(self.Slave)) laurent@2022: if dialog.ShowModal() == wx.ID_OK: laurent@2022: result = self.Controler.SetSlaveType(self.Slave, dialog.GetType()) laurent@2022: if result is not None: laurent@2022: message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) laurent@2022: message.ShowModal() laurent@2022: message.Destroy() laurent@2022: else: laurent@2022: wx.CallAfter(self.RefreshView) laurent@2022: wx.CallAfter(self.ParentWindow.RefreshSlaveNodesTitles) laurent@2022: wx.CallAfter(self.ParentWindow.RefreshParentWindow) laurent@2022: dialog.Destroy() laurent@2022: event.Skip() laurent@2022: laurent@2022: def OnVariablesGridCellLeftClick(self, event): laurent@2029: row = event.GetRow() laurent@2029: laurent@2029: data_type = self.VariablesTable.GetValueByName(row, "Type") laurent@2029: access = self.VariablesTable.GetValueByName(row, "Access") laurent@2029: if (event.GetCol() == 0 and access != "" and laurent@2029: self.Controler.GetSizeOfType(data_type) is not None): laurent@2029: laurent@2022: entry_index = self.Controler.ExtractHexDecValue(self.VariablesTable.GetValueByName(row, "Index")) laurent@2029: entry_subindex = self.Controler.ExtractHexDecValue(self.VariablesTable.GetValueByName(row, "SubIndex")) laurent@2029: var_name = "%s_%4.4x_%2.2x" % (self.Type.GetValue(), entry_index, entry_subindex) laurent@2029: if access in ["ro"]: laurent@2023: dir = "%I" laurent@2023: else: laurent@2023: dir = "%Q" laurent@2022: location = "%s%s" % (dir, self.Controler.GetSizeOfType(data_type)) + \ laurent@2022: ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation() + self.Slave + (entry_index, entry_subindex))) laurent@2029: laurent@2022: data = wx.TextDataObject(str((location, "location", data_type, var_name, ""))) laurent@2022: dragSource = wx.DropSource(self.VariablesGrid) laurent@2022: dragSource.SetData(data) laurent@2022: dragSource.DoDragDrop() laurent@2029: laurent@2022: event.Skip() laurent@2022: laurent@2022: [ID_CONFIGEDITOR, ID_CONFIGEDITORADDSLAVEBUTTON, laurent@2022: ID_CONFIGEDITORDELETESLAVEBUTTON, ID_CONFIGEDITORSLAVENODES, laurent@2022: ] = [wx.NewId() for _init_ctrls in range(4)] laurent@2022: laurent@2030: [ID_CONFIGEDITORPLUGINMENUADDSLAVE, ID_CONFIGEDITORPLUGINMENUDELETESLAVE, laurent@2030: ] = [wx.NewId() for _init_coll_PluginMenu_Items in range(2)] laurent@2030: laurent@2022: class ConfigEditor(EditorPanel): laurent@2022: laurent@2022: ID = ID_CONFIGEDITOR laurent@2022: laurent@2022: def _init_coll_MainSizer_Items(self, parent): laurent@2030: parent.AddWindow(self.SlaveNodes, 0, border=5, flag=wx.GROW|wx.ALL) laurent@2022: laurent@2022: def _init_coll_MainSizer_Growables(self, parent): laurent@2022: parent.AddGrowableCol(0) laurent@2030: parent.AddGrowableRow(0) laurent@2030: laurent@2022: def _init_sizers(self): laurent@2030: self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=0) laurent@2022: laurent@2022: self._init_coll_MainSizer_Items(self.MainSizer) laurent@2022: self._init_coll_MainSizer_Growables(self.MainSizer) laurent@2022: laurent@2022: self.Editor.SetSizer(self.MainSizer) laurent@2022: laurent@2022: def _init_Editor(self, prnt): laurent@2022: self.Editor = wx.Panel(id=-1, parent=prnt, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) laurent@2022: laurent@2022: self.SlaveNodes = wx.Notebook(id=ID_CONFIGEDITORSLAVENODES, laurent@2022: name='SlaveNodes', parent=self.Editor, pos=wx.Point(0, 0), laurent@2022: size=wx.Size(0, 0), style=wx.NB_LEFT) laurent@2022: laurent@2022: self._init_sizers() laurent@2022: laurent@2030: def _init_MenuItems(self): laurent@2030: self.MenuItems = [ laurent@2030: (wx.ITEM_NORMAL, (_("Add slave"), ID_CONFIGEDITORPLUGINMENUADDSLAVE, '', self.OnAddSlaveMenu)), laurent@2030: (wx.ITEM_NORMAL, (_("Delete slave"), ID_CONFIGEDITORPLUGINMENUDELETESLAVE, '', self.OnDeleteSlaveMenu)), laurent@2030: ] laurent@2030: laurent@2022: def __init__(self, parent, controler, window): laurent@2022: EditorPanel.__init__(self, parent, "", window, controler) laurent@2022: laurent@2022: img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage() laurent@2022: self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16))) laurent@2026: laurent@2026: def __del__(self): laurent@2030: self.Controler.OnCloseEditor(self) laurent@2026: laurent@2022: def GetTitle(self): laurent@2023: fullname = self.Controler.PlugFullName() laurent@2022: if not self.Controler.ConfigIsSaved(): laurent@2023: return "~%s~" % fullname laurent@2023: return fullname laurent@2022: laurent@2022: def GetBufferState(self): laurent@2022: return self.Controler.GetBufferState() laurent@2022: laurent@2022: def Undo(self): laurent@2022: self.Controler.LoadPrevious() laurent@2022: self.RefreshView() laurent@2022: laurent@2022: def Redo(self): laurent@2022: self.Controler.LoadNext() laurent@2022: self.RefreshView() laurent@2022: laurent@2022: def RefreshView(self, slave_pos=None): laurent@2022: slaves = self.Controler.GetSlaves() laurent@2022: for i, slave in enumerate(slaves): laurent@2022: if i < self.SlaveNodes.GetPageCount(): laurent@2022: panel = self.SlaveNodes.GetPage(i) laurent@2022: panel.SetSlave(slave) laurent@2022: else: laurent@2022: panel = SlavePanel(self.SlaveNodes, self.Controler, self, slave) laurent@2022: self.SlaveNodes.AddPage(panel, "") laurent@2022: while self.SlaveNodes.GetPageCount() > len(slaves): laurent@2022: self.SlaveNodes.RemovePage(len(slaves)) laurent@2022: self.RefreshSlaveNodesTitles() laurent@2022: if slave_pos is not None: laurent@2022: self.SelectSlave(slave_pos) laurent@2022: laurent@2022: def RefreshParentWindow(self): laurent@2022: self.ParentWindow.RefreshTitle() laurent@2022: self.ParentWindow.RefreshFileMenu() laurent@2022: self.ParentWindow.RefreshEditMenu() laurent@2030: self.ParentWindow.RefreshPluginMenu() laurent@2022: self.ParentWindow.RefreshPageTitles() laurent@2022: laurent@2022: def RefreshSlaveNodesTitles(self): laurent@2022: for idx in xrange(self.SlaveNodes.GetPageCount()): laurent@2022: panel = self.SlaveNodes.GetPage(idx) laurent@2022: self.SlaveNodes.SetPageText(idx, panel.GetSlaveTitle()) laurent@2022: laurent@2030: def RefreshPluginMenu(self, plugin_menu): laurent@2030: plugin_menu.Enable(ID_CONFIGEDITORPLUGINMENUDELETESLAVE, laurent@2030: self.SlaveNodes.GetPageCount() > 0) laurent@2022: laurent@2022: def SelectSlave(self, slave): laurent@2022: for idx in xrange(self.SlaveNodes.GetPageCount()): laurent@2022: panel = self.SlaveNodes.GetPage(idx) laurent@2022: if panel.GetSlave() == slave: laurent@2022: self.SlaveNodes.SetSelection(idx) laurent@2022: return laurent@2022: laurent@2030: def OnAddSlaveMenu(self, event): laurent@2022: slave = self.Controler.AddSlave() laurent@2022: self.RefreshParentWindow() laurent@2022: wx.CallAfter(self.RefreshView, slave) laurent@2030: laurent@2030: def OnDeleteSlaveMenu(self, event): laurent@2022: selected = self.SlaveNodes.GetSelection() laurent@2022: if selected != -1: laurent@2022: panel = self.SlaveNodes.GetPage(selected) laurent@2022: if self.Controler.RemoveSlave(panel.GetSlave()[:2]): laurent@2022: self.RefreshParentWindow() laurent@2022: wx.CallAfter(self.RefreshView) laurent@2022: