etherlab/ConfigEditor.py
changeset 2097 58d07e039896
parent 2095 6733a7c5c897
child 2098 392791b5cc04
equal deleted inserted replaced
2096:c9b0340ea0f5 2097:58d07e039896
       
     1 import os
       
     2 
     1 import wx
     3 import wx
     2 import wx.grid
     4 import wx.grid
     3 import wx.gizmos
     5 import wx.gizmos
     4 
     6 import wx.lib.buttons
     5 from controls import CustomGrid, CustomTable
     7 
       
     8 from controls import CustomGrid, CustomTable, FolderTree
     6 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor, SCROLLBAR_UNIT
     9 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor, SCROLLBAR_UNIT
       
    10 from util.BitmapLibrary import GetBitmap
     7 
    11 
     8 [ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE] = range(3)
    12 [ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE] = range(3)
     9 
    13 
    10 def AppendMenu(parent, help, id, kind, text):
    14 def AppendMenu(parent, help, id, kind, text):
    11     if wx.VERSION >= (2, 6, 0):
    15     if wx.VERSION >= (2, 6, 0):
    12         parent.Append(help=help, id=id, kind=kind, text=text)
    16         parent.Append(help=help, id=id, kind=kind, text=text)
    13     else:
    17     else:
    14         parent.Append(helpString=help, id=id, kind=kind, item=text)
    18         parent.Append(helpString=help, id=id, kind=kind, item=text)
    15 
    19 
    16 def GetSyncManagersTableColnames():
       
    17     _ = lambda x : x
       
    18     return ["#", _("Name"), _("Start Address"), _("Default Size"), _("Control Byte"), _("Enable")]
       
    19 
       
    20 class SyncManagersTable(CustomTable):
       
    21     
       
    22     def GetValue(self, row, col):
       
    23         if row < self.GetNumberRows():
       
    24             if col == 0:
       
    25                 return row
       
    26             return self.data[row].get(self.GetColLabelValue(col, False), "")
       
    27 
       
    28 def GetVariablesTableColnames():
    20 def GetVariablesTableColnames():
    29     _ = lambda x : x
    21     _ = lambda x : x
    30     return ["#", _("Name"), _("Index"), _("SubIndex"), _("Type"), _("PDO index"), _("PDO name"), _("PDO type")]
    22     return ["#", _("Name"), _("Index"), _("SubIndex"), _("Type"), _("Access")]
    31 
    23 
    32 [ID_NODEEDITOR, ID_NODEEDITORVENDORLABEL, 
    24 ACCESS_TYPES = {
    33  ID_NODEEDITORVENDOR, ID_NODEEDITORPRODUCTCODELABEL, 
    25     'ro': 'R',
    34  ID_NODEEDITORPRODUCTCODE, ID_NODEEDITORREVISIONNUMBERLABEL, 
    26     'wo': 'W',
    35  ID_NODEEDITORREVISIONNUMBER, ID_NODEEDITORPHYSICSLABEL, 
    27     'rw': 'R/W'}
    36  ID_NODEEDITORPHYSICS, ID_NODEEDITORSYNCMANAGERSLABEL, 
    28 
    37  ID_NODEEDITORSYNCMANAGERSGRID, ID_NODEEDITORVARIABLESLABEL, 
    29 def GetAccessValue(access, pdo_mapping):
    38  ID_NODEEDITORVARIABLESGRID, 
    30     value = ACCESS_TYPES.get(access)
    39 ] = [wx.NewId() for _init_ctrls in range(13)]
    31     if pdo_mapping != "":
       
    32         value += "/P"
       
    33     return value
    40 
    34 
    41 class NodeEditor(ConfTreeNodeEditor):
    35 class NodeEditor(ConfTreeNodeEditor):
    42     
    36     
    43     ID = ID_NODEEDITOR
       
    44     CONFNODEEDITOR_TABS = [
    37     CONFNODEEDITOR_TABS = [
    45         (_("Ethercat node"), "_create_EthercatNodeEditor")]
    38         (_("Ethercat node"), "_create_EthercatNodeEditor")]
    46     
    39     
    47     def _init_coll_MainSizer_Items(self, parent):
       
    48         parent.AddSizer(self.SlaveInfosDetailsSizer, 0, border=5, flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.GROW)
       
    49         parent.AddWindow(self.SyncManagersLabel, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.GROW)
       
    50         parent.AddWindow(self.SyncManagersGrid, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.GROW)
       
    51         parent.AddWindow(self.VariablesLabel, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.GROW)
       
    52         parent.AddWindow(self.VariablesGrid, 0, border=5, flag=wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.GROW)
       
    53         
       
    54     def _init_coll_MainSizer_Growables(self, parent):
       
    55         parent.AddGrowableCol(0)
       
    56         parent.AddGrowableRow(2, 1)
       
    57         parent.AddGrowableRow(4, 2)
       
    58         
       
    59     def _init_coll_SlaveInfosDetailsSizer_Items(self, parent):
       
    60         parent.AddWindow(self.VendorLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.GROW)
       
    61         parent.AddWindow(self.Vendor, 0, border=0, flag=wx.GROW)
       
    62         parent.AddWindow(self.ProductCodeLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.GROW)
       
    63         parent.AddWindow(self.ProductCode, 0, border=0, flag=wx.GROW)
       
    64         parent.AddWindow(self.RevisionNumberLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.GROW)
       
    65         parent.AddWindow(self.RevisionNumber, 0, border=0, flag=wx.GROW)
       
    66         parent.AddWindow(self.PhysicsLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL|wx.GROW)
       
    67         parent.AddWindow(self.Physics, 0, border=0, flag=wx.GROW)
       
    68         
       
    69     def _init_coll_SlaveInfosDetailsSizer_Growables(self, parent):
       
    70         parent.AddGrowableCol(1)
       
    71         parent.AddGrowableCol(3)
       
    72     
       
    73     def _init_sizers(self):
       
    74         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=5, vgap=5)
       
    75         self.SlaveInfosDetailsSizer = wx.FlexGridSizer(cols=4, hgap=5, rows=2, vgap=5)
       
    76         
       
    77         self._init_coll_MainSizer_Growables(self.MainSizer)
       
    78         self._init_coll_MainSizer_Items(self.MainSizer)
       
    79         self._init_coll_SlaveInfosDetailsSizer_Growables(self.SlaveInfosDetailsSizer)
       
    80         self._init_coll_SlaveInfosDetailsSizer_Items(self.SlaveInfosDetailsSizer)
       
    81         
       
    82         self.EthercatNodeEditor.SetSizer(self.MainSizer)
       
    83 
       
    84     def _create_EthercatNodeEditor(self, prnt):
    40     def _create_EthercatNodeEditor(self, prnt):
    85         self.EthercatNodeEditor = wx.ScrolledWindow(id=-1, name='SlavePanel', parent=prnt,
    41         self.EthercatNodeEditor = wx.Panel(prnt, style=wx.TAB_TRAVERSAL)
    86               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL)
    42         
    87         self.EthercatNodeEditor.Bind(wx.EVT_SIZE, self.OnEthercatNodeEditorResize)
    43         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
    88         
    44         main_sizer.AddGrowableCol(0)
    89         self.VendorLabel = wx.StaticText(id=ID_NODEEDITORVENDORLABEL,
    45         main_sizer.AddGrowableRow(1)
    90               label=_('Vendor:'), name='VendorLabel', parent=self.EthercatNodeEditor,
    46         
    91               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
    47         variables_label = wx.StaticText(self.EthercatNodeEditor,
    92         
    48               label=_('Variable entries:'))
    93         self.Vendor = wx.TextCtrl(id=ID_NODEEDITORVENDOR, value='',
    49         main_sizer.AddWindow(variables_label, border=10, flag=wx.TOP|wx.LEFT|wx.RIGHT)
    94               name='Vendor', parent=self.EthercatNodeEditor, pos=wx.Point(0, 0),
    50         
    95               size=wx.Size(0, 24), style=wx.TE_READONLY)
    51         self.VariablesGrid = wx.gizmos.TreeListCtrl(self.EthercatNodeEditor,
    96         
    52               style=wx.TR_DEFAULT_STYLE |
    97         self.ProductCodeLabel = wx.StaticText(id=ID_NODEEDITORPRODUCTCODELABEL,
    53                     wx.TR_ROW_LINES |
    98               label=_('Product code:'), name='ProductCodeLabel', parent=self.EthercatNodeEditor,
    54                     wx.TR_COLUMN_LINES |
    99               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
    55                     wx.TR_HIDE_ROOT |
   100         
    56                     wx.TR_FULL_ROW_HIGHLIGHT)
   101         self.ProductCode = wx.TextCtrl(id=ID_NODEEDITORPRODUCTCODE, value='',
    57         self.VariablesGrid.GetMainWindow().Bind(wx.EVT_LEFT_DOWN, 
   102               name='ProductCode', parent=self.EthercatNodeEditor, pos=wx.Point(0, 0),
    58             self.OnVariablesGridLeftClick)
   103               size=wx.Size(0, 24), style=wx.TE_READONLY)
    59         main_sizer.AddWindow(self.VariablesGrid, border=10, 
   104         
    60             flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
   105         self.RevisionNumberLabel = wx.StaticText(id=ID_NODEEDITORREVISIONNUMBERLABEL,
       
   106               label=_('Revision number:'), name='RevisionNumberLabel', parent=self.EthercatNodeEditor,
       
   107               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
       
   108         
       
   109         self.RevisionNumber = wx.TextCtrl(id=ID_NODEEDITORREVISIONNUMBER, value='',
       
   110               name='RevisionNumber', parent=self.EthercatNodeEditor, pos=wx.Point(0, 0),
       
   111               size=wx.Size(0, 24), style=wx.TE_READONLY)
       
   112         
       
   113         self.PhysicsLabel = wx.StaticText(id=ID_NODEEDITORPHYSICSLABEL,
       
   114               label=_('Physics:'), name='PhysicsLabel', parent=self.EthercatNodeEditor,
       
   115               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
       
   116         
       
   117         self.Physics = wx.TextCtrl(id=ID_NODEEDITORPHYSICS, value='',
       
   118               name='Physics', parent=self.EthercatNodeEditor, pos=wx.Point(0, 0),
       
   119               size=wx.Size(0, 24), style=wx.TE_READONLY)
       
   120         
       
   121         self.SyncManagersLabel =  wx.StaticText(id=ID_NODEEDITORSYNCMANAGERSLABEL,
       
   122               label=_('Sync managers:'), name='SyncManagersLabel', parent=self.EthercatNodeEditor,
       
   123               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
       
   124         
       
   125         self.SyncManagersGrid = CustomGrid(id=ID_NODEEDITORSYNCMANAGERSGRID,
       
   126               name='SyncManagersGrid', parent=self.EthercatNodeEditor, pos=wx.Point(0, 0), 
       
   127               size=wx.Size(0, 200), style=wx.VSCROLL)
       
   128         
       
   129         self.VariablesLabel =  wx.StaticText(id=ID_NODEEDITORVARIABLESLABEL,
       
   130               label=_('Variable entries:'), name='VariablesLabel', parent=self.EthercatNodeEditor,
       
   131               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
       
   132         
       
   133         self.VariablesGrid = wx.gizmos.TreeListCtrl(id=ID_NODEEDITORVARIABLESGRID,
       
   134               name='VariablesGrid', parent=self.EthercatNodeEditor, pos=wx.Point(0, 0), 
       
   135               size=wx.Size(0, 400), style=wx.TR_DEFAULT_STYLE |
       
   136                                           wx.TR_ROW_LINES |
       
   137                                           wx.TR_COLUMN_LINES |
       
   138                                           wx.TR_HIDE_ROOT |
       
   139                                           wx.TR_FULL_ROW_HIGHLIGHT)
       
   140         self.VariablesGrid.GetMainWindow().Bind(wx.EVT_LEFT_DOWN, self.OnVariablesGridLeftClick)
       
   141                 
    61                 
   142         self._init_sizers()
    62         self.EthercatNodeEditor.SetSizer(main_sizer)
   143     
    63 
   144         return self.EthercatNodeEditor
    64         return self.EthercatNodeEditor
   145     
    65     
   146     def __init__(self, parent, controler, window):
    66     def __init__(self, parent, controler, window):
   147         ConfTreeNodeEditor.__init__(self, parent, controler, window)
    67         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   148     
    68     
   149         self.SyncManagersTable = SyncManagersTable(self, [], GetSyncManagersTableColnames())
       
   150         self.SyncManagersGrid.SetTable(self.SyncManagersTable)
       
   151         self.SyncManagersGridColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, 
       
   152                                                wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT]
       
   153         self.SyncManagersGridColSizes = [40, 150, 100, 100, 100, 100]
       
   154         self.SyncManagersGrid.SetRowLabelSize(0)
       
   155         for col in range(self.SyncManagersTable.GetNumberCols()):
       
   156             attr = wx.grid.GridCellAttr()
       
   157             attr.SetAlignment(self.SyncManagersGridColAlignements[col], wx.ALIGN_CENTRE)
       
   158             self.SyncManagersGrid.SetColAttr(col, attr)
       
   159             self.SyncManagersGrid.SetColMinimalWidth(col, self.SyncManagersGridColSizes[col])
       
   160             self.SyncManagersGrid.AutoSizeColumn(col, False)
       
   161         
       
   162         for colname, colsize, colalign in zip(GetVariablesTableColnames(),
    69         for colname, colsize, colalign in zip(GetVariablesTableColnames(),
   163                                               [40, 150, 100, 100, 150, 100, 150, 100],
    70                                               [40, 150, 100, 100, 150, 100],
   164                                               [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, 
    71                                               [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, 
   165                                                wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, 
    72                                                wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]):
   166                                                wx.ALIGN_LEFT, wx.ALIGN_LEFT]):
       
   167             self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
    73             self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
   168         self.VariablesGrid.SetMainColumn(1)
    74         self.VariablesGrid.SetMainColumn(1)
   169     
    75     
   170     def GetBufferState(self):
    76     def GetBufferState(self):
   171         return False, False
    77         return False, False
   176         self.RefreshSlaveInfos()
    82         self.RefreshSlaveInfos()
   177         
    83         
   178     def RefreshSlaveInfos(self):
    84     def RefreshSlaveInfos(self):
   179         slave_infos = self.Controler.GetSlaveInfos()
    85         slave_infos = self.Controler.GetSlaveInfos()
   180         if slave_infos is not None:
    86         if slave_infos is not None:
   181             self.Vendor.SetValue(slave_infos["vendor"])
       
   182             self.ProductCode.SetValue(slave_infos["product_code"])
       
   183             self.RevisionNumber.SetValue(slave_infos["revision_number"])
       
   184             self.Physics.SetValue(slave_infos["physics"])
       
   185             self.SyncManagersTable.SetData(slave_infos["sync_managers"])
       
   186             self.SyncManagersTable.ResetView(self.SyncManagersGrid)
       
   187             self.RefreshVariablesGrid(slave_infos["entries"])
    87             self.RefreshVariablesGrid(slave_infos["entries"])
   188         else:
    88         else:
   189             self.Vendor.SetValue("")
       
   190             self.ProductCode.SetValue("")
       
   191             self.RevisionNumber.SetValue("")
       
   192             self.Physics.SetValue("")
       
   193             self.SyncManagersTable.SetData([])
       
   194             self.SyncManagersTable.ResetView(self.SyncManagersGrid)
       
   195             self.RefreshVariablesGrid([])
    89             self.RefreshVariablesGrid([])
   196     
    90     
   197     def RefreshVariablesGrid(self, entries):
    91     def RefreshVariablesGrid(self, entries):
   198         root = self.VariablesGrid.GetRootItem()
    92         root = self.VariablesGrid.GetRootItem()
   199         if not root.IsOk():
    93         if not root.IsOk():
   200             root = self.VariablesGrid.AddRoot("Slave entries")
    94             root = self.VariablesGrid.AddRoot("Slave entries")
   201         self.GenerateVariablesGridBranch(root, entries, GetVariablesTableColnames())
    95         self.GenerateVariablesGridBranch(root, entries, GetVariablesTableColnames())
   202         self.VariablesGrid.Expand(root)
    96         self.VariablesGrid.Expand(root)
   203         
    97         
   204     def GenerateVariablesGridBranch(self, root, entries, colnames, idx=0):
    98     def GenerateVariablesGridBranch(self, root, entries, colnames, idx=0):
   205         if wx.VERSION >= (2, 6, 0):
    99         item, root_cookie = self.VariablesGrid.GetFirstChild(root)
   206             item, root_cookie = self.VariablesGrid.GetFirstChild(root)
       
   207         else:
       
   208             item, root_cookie = self.VariablesGrid.GetFirstChild(root, 0)
       
   209         
   100         
   210         no_more_items = not item.IsOk()
   101         no_more_items = not item.IsOk()
   211         for entry in entries:
   102         for entry in entries:
   212             idx += 1
   103             idx += 1
   213             if no_more_items:
   104             if no_more_items:
   214                 item = self.VariablesGrid.AppendItem(root, "")
   105                 item = self.VariablesGrid.AppendItem(root, "")
   215             for col, colname in enumerate(colnames):
   106             for col, colname in enumerate(colnames):
   216                 if col == 0:
   107                 if col == 0:
   217                     self.VariablesGrid.SetItemText(item, str(idx), 0)
   108                     self.VariablesGrid.SetItemText(item, str(idx), 0)
   218                 else:
   109                 else:
   219                     self.VariablesGrid.SetItemText(item, entry.get(colname, ""), col)
   110                     value = entry.get(colname, "")
       
   111                     if colname == "Access":
       
   112                         value = GetAccessValue(value, entry.get("PDOMapping", ""))
       
   113                     self.VariablesGrid.SetItemText(item, value, col)
   220             if entry["PDOMapping"] == "":
   114             if entry["PDOMapping"] == "":
   221                 self.VariablesGrid.SetItemBackgroundColour(item, wx.LIGHT_GREY)
   115                 self.VariablesGrid.SetItemBackgroundColour(item, wx.LIGHT_GREY)
   222             self.VariablesGrid.SetItemPyData(item, entry)
   116             self.VariablesGrid.SetItemPyData(item, entry)
   223             idx = self.GenerateVariablesGridBranch(item, entry["children"], colnames, idx)
   117             idx = self.GenerateVariablesGridBranch(item, entry["children"], colnames, idx)
   224             if not no_more_items:
   118             if not no_more_items:
   261                 dragSource.DoDragDrop()
   155                 dragSource.DoDragDrop()
   262                 return
   156                 return
   263             
   157             
   264         event.Skip()
   158         event.Skip()
   265 
   159 
   266     def OnEthercatNodeEditorResize(self, event):
   160 CIA402NodeEditor = NodeEditor
   267         self.EthercatNodeEditor.GetBestSize()
   161 
   268         xstart, ystart = self.EthercatNodeEditor.GetViewStart()
   162 
   269         window_size = self.EthercatNodeEditor.GetClientSize()
   163 def GetModulesTableColnames():
   270         maxx, maxy = self.EthercatNodeEditor.GetMinSize()
   164     _ = lambda x : x
       
   165     return [_("Name"), _("PDO alignment (bits)")]
       
   166 
       
   167 class LibraryEditorPanel(wx.ScrolledWindow):
       
   168     
       
   169     def __init__(self, parent, module_library, buttons):
       
   170         wx.ScrolledWindow.__init__(self, parent,
       
   171             style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
       
   172         self.Bind(wx.EVT_SIZE, self.OnResize)
       
   173         
       
   174         self.ModuleLibrary = module_library
       
   175     
       
   176         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=4, vgap=5)
       
   177         main_sizer.AddGrowableCol(0)
       
   178         main_sizer.AddGrowableRow(1)
       
   179         main_sizer.AddGrowableRow(3)
       
   180         
       
   181         ESI_files_label = wx.StaticText(self, 
       
   182             label=_("ESI Files:"))
       
   183         main_sizer.AddWindow(ESI_files_label, border=10, 
       
   184             flag=wx.TOP|wx.LEFT|wx.RIGHT)
       
   185         
       
   186         folder_tree_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=1, vgap=0)
       
   187         folder_tree_sizer.AddGrowableCol(0)
       
   188         folder_tree_sizer.AddGrowableRow(0)
       
   189         main_sizer.AddSizer(folder_tree_sizer, border=10, 
       
   190             flag=wx.GROW|wx.LEFT|wx.RIGHT)
       
   191         
       
   192         self.ESIFiles = FolderTree(self, self.GetPath(), editable=False)
       
   193         self.ESIFiles.SetFilter(".xml")
       
   194         self.ESIFiles.SetMinSize(wx.Size(600, 300))
       
   195         folder_tree_sizer.AddWindow(self.ESIFiles, flag=wx.GROW)
       
   196         
       
   197         buttons_sizer = wx.BoxSizer(wx.VERTICAL)
       
   198         folder_tree_sizer.AddSizer(buttons_sizer, 
       
   199             flag=wx.ALIGN_CENTER_VERTICAL)
       
   200         
       
   201         for idx, (name, bitmap, help, callback) in enumerate(buttons):
       
   202             button = wx.lib.buttons.GenBitmapButton(self, 
       
   203                   bitmap=GetBitmap(bitmap), 
       
   204                   size=wx.Size(28, 28), style=wx.NO_BORDER)
       
   205             button.SetToolTipString(help)
       
   206             setattr(self, name, button)
       
   207             if idx > 0:
       
   208                 flag = wx.TOP
       
   209             else:
       
   210                 flag = 0
       
   211             if callback is None:
       
   212                 callback = getattr(self, "On" + name, None)
       
   213             if callback is not None:
       
   214                 self.Bind(wx.EVT_BUTTON, callback, button)
       
   215             buttons_sizer.AddWindow(button, border=10, flag=flag)
       
   216         
       
   217         modules_label = wx.StaticText(self, 
       
   218             label=_("Modules library:"))
       
   219         main_sizer.AddSizer(modules_label, border=10, 
       
   220             flag=wx.LEFT|wx.RIGHT)
       
   221         
       
   222         self.ModulesGrid = wx.gizmos.TreeListCtrl(self,
       
   223               style=wx.TR_DEFAULT_STYLE |
       
   224                     wx.TR_ROW_LINES |
       
   225                     wx.TR_COLUMN_LINES |
       
   226                     wx.TR_HIDE_ROOT |
       
   227                     wx.TR_FULL_ROW_HIGHLIGHT)
       
   228         self.ModulesGrid.SetMinSize(wx.Size(600, 300))
       
   229         self.ModulesGrid.GetMainWindow().Bind(wx.EVT_LEFT_DCLICK,
       
   230             self.OnModulesGridLeftDClick)
       
   231         main_sizer.AddWindow(self.ModulesGrid, border=10, 
       
   232             flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
       
   233         
       
   234         self.SetSizer(main_sizer)
       
   235         
       
   236         for colname, colsize, colalign in zip(GetModulesTableColnames(),
       
   237                                               [400, 150],
       
   238                                               [wx.ALIGN_LEFT, wx.ALIGN_RIGHT]):
       
   239             self.ModulesGrid.AddColumn(_(colname), colsize, colalign)
       
   240         self.ModulesGrid.SetMainColumn(0)
       
   241     
       
   242     def GetPath(self):
       
   243         return self.ModuleLibrary.GetPath()
       
   244     
       
   245     def GetSelectedFilePath(self):
       
   246         return self.ESIFiles.GetPath()
       
   247     
       
   248     def RefreshView(self):
       
   249         self.ESIFiles.RefreshTree()
       
   250         self.RefreshModulesGrid()
       
   251     
       
   252     def RefreshModulesGrid(self):
       
   253         root = self.ModulesGrid.GetRootItem()
       
   254         if not root.IsOk():
       
   255             root = self.ModulesGrid.AddRoot("Modules")
       
   256         self.GenerateModulesGridBranch(root, 
       
   257             self.ModuleLibrary.GetModulesLibrary(), 
       
   258             GetVariablesTableColnames())
       
   259         self.ModulesGrid.Expand(root)
       
   260             
       
   261     def GenerateModulesGridBranch(self, root, modules, colnames):
       
   262         item, root_cookie = self.ModulesGrid.GetFirstChild(root)
       
   263         
       
   264         no_more_items = not item.IsOk()
       
   265         for module in modules:
       
   266             if no_more_items:
       
   267                 item = self.ModulesGrid.AppendItem(root, "")
       
   268             self.ModulesGrid.SetItemText(item, module["name"], 0)
       
   269             if module["infos"] is not None:
       
   270                 self.ModulesGrid.SetItemText(item, str(module["infos"]["alignment"]), 1)
       
   271             else:
       
   272                 self.ModulesGrid.SetItemBackgroundColour(item, wx.LIGHT_GREY)
       
   273             self.ModulesGrid.SetItemPyData(item, module["infos"])
       
   274             self.GenerateModulesGridBranch(item, module["children"], colnames)
       
   275             if not no_more_items:
       
   276                 item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie)
       
   277                 no_more_items = not item.IsOk()
       
   278         
       
   279         if not no_more_items:
       
   280             to_delete = []
       
   281             while item.IsOk():
       
   282                 to_delete.append(item)
       
   283                 item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie)
       
   284             for item in to_delete:
       
   285                 self.ModulesGrid.Delete(item)
       
   286     
       
   287     def OnImportButton(self, event):
       
   288         dialog = wx.FileDialog(self,
       
   289              _("Choose an XML file"), 
       
   290              os.getcwd(), "",  
       
   291              _("XML files (*.xml)|*.xml|All files|*.*"), wx.OPEN)
       
   292         
       
   293         if dialog.ShowModal() == wx.ID_OK:
       
   294             filepath = dialog.GetPath()
       
   295             if self.ModuleLibrary.ImportModuleLibrary(filepath):
       
   296                 wx.CallAfter(self.RefreshView)
       
   297             else:
       
   298                 message = wx.MessageDialog(self, 
       
   299                     _("No such XML file: %s\n") % filepath, 
       
   300                     _("Error"), wx.OK|wx.ICON_ERROR)
       
   301                 message.ShowModal()
       
   302                 message.Destroy()
       
   303         dialog.Destroy()
       
   304         
       
   305         event.Skip()
       
   306     
       
   307     def OnDeleteButton(self, event):
       
   308         filepath = self.GetSelectedFilePath()
       
   309         if os.path.isfile(filepath):
       
   310             folder, filename = os.path.split(filepath)
       
   311             
       
   312             dialog = wx.MessageDialog(self, 
       
   313                   _("Do you really want to delete the file '%s'?") % filename, 
       
   314                   _("Delete File"), wx.YES_NO|wx.ICON_QUESTION)
       
   315             remove = dialog.ShowModal() == wx.ID_YES
       
   316             dialog.Destroy()
       
   317             
       
   318             if remove:
       
   319                 os.remove(filepath)
       
   320                 self.ModuleLibrary.LoadModules()
       
   321                 wx.CallAfter(self.RefreshView)
       
   322         event.Skip()
       
   323     
       
   324     def OnModulesGridLeftDClick(self, event):
       
   325         item, flags, col = self.ModulesGrid.HitTest(event.GetPosition())
       
   326         if item.IsOk():
       
   327             entry_infos = self.ModulesGrid.GetItemPyData(item)
       
   328             if entry_infos is not None and col == 1:
       
   329                 dialog = wx.TextEntryDialog(self, 
       
   330                     _("Set PDO alignment (bits):"),
       
   331                     _("%s PDO alignment") % self.ModulesGrid.GetItemText(item), 
       
   332                     str(entry_infos["alignment"]))
       
   333                 
       
   334                 if dialog.ShowModal() == wx.ID_OK:
       
   335                     try:
       
   336                         self.ModuleLibrary.SetAlignment(
       
   337                             entry_infos["vendor"],
       
   338                             entry_infos["product_code"],
       
   339                             entry_infos["revision_number"],
       
   340                             int(dialog.GetValue()))
       
   341                         wx.CallAfter(self.RefreshModulesGrid)
       
   342                     except ValueError:
       
   343                         message = wx.MessageDialog(self, 
       
   344                             _("Module PDO alignment must be an integer!"), 
       
   345                             _("Error"), wx.OK|wx.ICON_ERROR)
       
   346                         message.ShowModal()
       
   347                         message.Destroy()
       
   348                     
       
   349                 dialog.Destroy()
       
   350         
       
   351         event.Skip()
       
   352     
       
   353     def OnResize(self, event):
       
   354         self.GetBestSize()
       
   355         xstart, ystart = self.GetViewStart()
       
   356         window_size = self.GetClientSize()
       
   357         maxx, maxy = self.GetMinSize()
   271         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
   358         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
   272         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
   359         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
   273         self.EthercatNodeEditor.Scroll(posx, posy)
   360         self.Scroll(posx, posy)
   274         self.EthercatNodeEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
   361         self.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
   275                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
   362                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
   276         event.Skip()
   363         event.Skip()
   277 
   364 
   278 CIA402NodeEditor = NodeEditor
   365 class DatabaseManagementDialog(wx.Dialog):
       
   366     
       
   367     def __init__(self, parent, database):
       
   368         wx.Dialog.__init__(self, parent,
       
   369               size=wx.Size(700, 500), title=_('ESI Files Database management'),
       
   370               style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
       
   371         
       
   372         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
       
   373         main_sizer.AddGrowableCol(0)
       
   374         main_sizer.AddGrowableRow(0)
       
   375         
       
   376         self.DatabaseEditor = LibraryEditorPanel(self, database,
       
   377             [("ImportButton", "ImportESI", _("Import file to ESI files database"), None),
       
   378              ("DeleteButton", "remove_element", _("Remove file from database"), None)])
       
   379         main_sizer.AddWindow(self.DatabaseEditor, border=10,
       
   380             flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
       
   381         
       
   382         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
       
   383         button_sizer.GetAffirmativeButton().SetLabel(_("Add file to project"))
       
   384         button_sizer.GetCancelButton().SetLabel(_("Close"))
       
   385         main_sizer.AddSizer(button_sizer, border=10, 
       
   386               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
       
   387         
       
   388         self.SetSizer(main_sizer)
       
   389         
       
   390         self.DatabaseEditor.RefreshView()
       
   391         
       
   392     def GetValue(self):
       
   393         return self.DatabaseEditor.GetSelectedFilePath()
       
   394 
       
   395 class LibraryEditor(ConfTreeNodeEditor):
       
   396     
       
   397     CONFNODEEDITOR_TABS = [
       
   398         (_("Modules Library"), "_create_ModuleLibraryEditor")]
       
   399     
       
   400     def _create_ModuleLibraryEditor(self, prnt):
       
   401         self.ModuleLibraryEditor = LibraryEditorPanel(prnt,
       
   402             self.Controler.GetModulesLibraryInstance(),
       
   403             [("ImportButton", "ImportESI", _("Import ESI file"), None),
       
   404              ("AddButton", "ImportDatabase", _("Add file from ESI files database"), self.OnAddButton),
       
   405              ("DeleteButton", "remove_element", _("Remove file from library"), None)])
       
   406         
       
   407         return self.ModuleLibraryEditor
       
   408 
       
   409     def __init__(self, parent, controler, window):
       
   410         ConfTreeNodeEditor.__init__(self, parent, controler, window)
       
   411     
       
   412         self.RefreshView()
       
   413     
       
   414     def RefreshView(self):
       
   415         ConfTreeNodeEditor.RefreshView(self)
       
   416         self.ModuleLibraryEditor.RefreshView()
       
   417 
       
   418     def OnAddButton(self, event):
       
   419         dialog = DatabaseManagementDialog(self, 
       
   420             self.Controler.GetModulesDatabaseInstance())
       
   421         
       
   422         if dialog.ShowModal() == wx.ID_OK:
       
   423             module_library = self.Controler.GetModulesLibraryInstance()
       
   424             module_library.ImportModuleLibrary(dialog.GetValue())
       
   425             
       
   426         dialog.Destroy()
       
   427         
       
   428         wx.CallAfter(self.ModuleLibraryEditor.RefreshView)
       
   429         
       
   430         event.Skip()
       
   431