]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - objdictgen/subindextable.py
Bug on new DCF entry boolean value fixed
[CanFestival-3.git] / objdictgen / subindextable.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 #This file is part of CanFestival, a library implementing CanOpen Stack. 
5 #
6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
7 #
8 #See COPYING file for copyrights details.
9 #
10 #This library is free software; you can redistribute it and/or
11 #modify it under the terms of the GNU Lesser General Public
12 #License as published by the Free Software Foundation; either
13 #version 2.1 of the License, or (at your option) any later version.
14 #
15 #This library is distributed in the hope that it will be useful,
16 #but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 #Lesser General Public License for more details.
19 #
20 #You should have received a copy of the GNU Lesser General Public
21 #License along with this library; if not, write to the Free Software
22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
24 import wx
25 import wx.grid
26
27 from types import *
28 from commondialogs import *
29
30 from node import OD_Subindex, OD_MultipleSubindexes, OD_IdenticalSubindexes, OD_IdenticalIndexes
31
32 ColSizes = [75, 250, 150, 125, 100, 60, 250]
33 ColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_CENTER, wx.ALIGN_RIGHT, wx.ALIGN_CENTER, wx.ALIGN_CENTER, wx.ALIGN_LEFT]
34 AccessList = "Read Only,Write Only,Read/Write"
35 RAccessList = "Read Only,Read/Write"
36 BoolList = "True,False"
37 OptionList = "Yes,No"
38
39 DictionaryOrganisation = [
40     {"minIndex" : 0x0001, "maxIndex" : 0x0FFF, "name" : "Data Type Definitions"},
41     {"minIndex" : 0x1000, "maxIndex" : 0x1029, "name" : "Communication Parameters"},
42     {"minIndex" : 0x1200, "maxIndex" : 0x12FF, "name" : "SDO Parameters"},
43     {"minIndex" : 0x1400, "maxIndex" : 0x15FF, "name" : "Receive PDO Parameters"},
44     {"minIndex" : 0x1600, "maxIndex" : 0x17FF, "name" : "Receive PDO Mapping"},
45     {"minIndex" : 0x1800, "maxIndex" : 0x19FF, "name" : "Transmit PDO Parameters"},
46     {"minIndex" : 0x1A00, "maxIndex" : 0x1BFF, "name" : "Transmit PDO Mapping"},
47     {"minIndex" : 0x1C00, "maxIndex" : 0x1FFF, "name" : "Other Communication Parameters"},
48     {"minIndex" : 0x2000, "maxIndex" : 0x5FFF, "name" : "Manufacturer Specific"},
49     {"minIndex" : 0x6000, "maxIndex" : 0x9FFF, "name" : "Standardized Device Profile"},
50     {"minIndex" : 0xA000, "maxIndex" : 0xBFFF, "name" : "Standardized Interface Profile"}]
51
52 SizeConversion = {1 : "X", 8 : "B", 16 : "W", 24 : "D", 32 : "D", 40 : "L", 48 : "L", 56 : "L", 64 : "L"}
53
54 class SubindexTable(wx.grid.PyGridTableBase):
55     
56     """
57     A custom wxGrid Table using user supplied data
58     """
59     def __init__(self, parent, data, editors, colnames):
60         # The base class must be initialized *first*
61         wx.grid.PyGridTableBase.__init__(self)
62         self.data = data
63         self.editors = editors
64         self.CurrentIndex = 0
65         self.colnames = colnames
66         self.Parent = parent
67         self.Editable = True
68         # XXX
69         # we need to store the row length and collength to
70         # see if the table has changed size
71         self._rows = self.GetNumberRows()
72         self._cols = self.GetNumberCols()
73     
74     def Disable(self):
75         self.Editable = False
76         
77     def Enable(self):
78         self.Editable = True
79     
80     def GetNumberCols(self):
81         return len(self.colnames)
82         
83     def GetNumberRows(self):
84         return len(self.data)
85
86     def GetColLabelValue(self, col):
87         if col < len(self.colnames):
88             return self.colnames[col]
89
90     def GetRowLabelValues(self, row):
91         return row
92
93     def GetValue(self, row, col):
94         if row < self.GetNumberRows():
95             return str(self.data[row].get(self.GetColLabelValue(col), ""))
96             
97     def GetEditor(self, row, col):
98         if row < self.GetNumberRows():
99             return self.editors[row].get(self.GetColLabelValue(col), "")
100     
101     def GetValueByName(self, row, colname):
102         return self.data[row].get(colname)
103
104     def SetValue(self, row, col, value):
105         if col < len(self.colnames):
106             self.data[row][self.GetColLabelValue(col)] = value
107         
108     def ResetView(self, grid):
109         """
110         (wx.grid.Grid) -> Reset the grid view.   Call this to
111         update the grid if rows and columns have been added or deleted
112         """
113         grid.BeginBatch()
114         for current, new, delmsg, addmsg in [
115             (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
116             (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
117         ]:
118             if new < current:
119                 msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
120                 grid.ProcessTableMessage(msg)
121             elif new > current:
122                 msg = wx.grid.GridTableMessage(self,addmsg,new-current)
123                 grid.ProcessTableMessage(msg)
124                 self.UpdateValues(grid)
125         grid.EndBatch()
126
127         self._rows = self.GetNumberRows()
128         self._cols = self.GetNumberCols()
129         # update the column rendering scheme
130         self._updateColAttrs(grid)
131
132         # update the scrollbars and the displayed part of the grid
133         grid.AdjustScrollbars()
134         grid.ForceRefresh()
135
136
137     def UpdateValues(self, grid):
138         """Update all displayed values"""
139         # This sends an event to the grid table to update all of the values
140         msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
141         grid.ProcessTableMessage(msg)
142
143     def _updateColAttrs(self, grid):
144         """
145         wx.grid.Grid -> update the column attributes to add the
146         appropriate renderer given the column name.
147
148         Otherwise default to the default renderer.
149         """
150         
151         for col in range(self.GetNumberCols()):
152             attr = wx.grid.GridCellAttr()
153             attr.SetAlignment(ColAlignements[col], wx.ALIGN_CENTRE)
154             grid.SetColAttr(col, attr)
155             grid.SetColSize(col, ColSizes[col])
156         
157         typelist = None
158         maplist = None
159         for row in range(self.GetNumberRows()):
160             editors = self.editors[row]
161             for col in range(self.GetNumberCols()):
162                 editor = None
163                 renderer = None
164                 
165                 colname = self.GetColLabelValue(col)
166                 editortype = editors[colname]
167                 if editortype and self.Editable:
168                     grid.SetReadOnly(row, col, False)
169                     if editortype == "string":
170                         editor = wx.grid.GridCellTextEditor()
171                         renderer = wx.grid.GridCellStringRenderer()
172                         if colname == "value" and "length" in editors:
173                             editor.SetParameters(editors["length"]) 
174                     elif editortype == "number":
175                         editor = wx.grid.GridCellNumberEditor()
176                         renderer = wx.grid.GridCellNumberRenderer()
177                         if colname == "value" and "min" in editors and "max" in editors:
178                             editor.SetParameters("%s,%s"%(editors["min"],editors["max"]))
179                     elif editortype == "real":
180                         editor = wx.grid.GridCellFloatEditor()
181                         renderer = wx.grid.GridCellFloatRenderer()
182                         if colname == "value" and "min" in editors and "max" in editors:
183                             editor.SetParameters("%s,%s"%(editors["min"],editors["max"]))
184                     elif editortype == "bool":
185                         editor = wx.grid.GridCellChoiceEditor()
186                         editor.SetParameters(BoolList)
187                     elif editortype == "access":
188                         editor = wx.grid.GridCellChoiceEditor()
189                         editor.SetParameters(AccessList)
190                     elif editortype == "raccess":
191                         editor = wx.grid.GridCellChoiceEditor()
192                         editor.SetParameters(RAccessList)
193                     elif editortype == "option":
194                         editor = wx.grid.GridCellChoiceEditor()
195                         editor.SetParameters(OptionList)
196                     elif editortype == "type":
197                         editor = wx.grid.GridCellChoiceEditor()
198                         if typelist == None:
199                             typelist = self.Parent.Manager.GetCurrentTypeList()
200                         editor.SetParameters(typelist)
201                     elif editortype == "map":
202                         editor = wx.grid.GridCellChoiceEditor()
203                         if maplist == None:
204                             maplist = self.Parent.Manager.GetCurrentMapList()
205                         editor.SetParameters(maplist)
206                     elif editortype == "time":
207                         editor = wx.grid.GridCellTextEditor()
208                         renderer = wx.grid.GridCellStringRenderer()
209                     elif editortype == "domain":
210                         editor = wx.grid.GridCellTextEditor()
211                         renderer = wx.grid.GridCellStringRenderer()
212                     elif editortype == "dcf":
213                         editor = wx.grid.GridCellTextEditor()
214                         renderer = wx.grid.GridCellStringRenderer()
215                 else:
216                     grid.SetReadOnly(row, col, True)
217                     
218                 grid.SetCellEditor(row, col, editor)
219                 grid.SetCellRenderer(row, col, renderer)
220                 
221                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
222     
223     def SetData(self, data):
224         self.data = data
225         
226     def SetEditors(self, editors):
227         self.editors = editors
228     
229     def GetCurrentIndex(self):
230         return self.CurrentIndex
231     
232     def SetCurrentIndex(self, index):
233         self.CurrentIndex = index
234     
235     def AppendRow(self, row_content):
236         self.data.append(row_content)
237
238     def Empty(self):
239         self.data = []
240         self.editors = []
241
242 [ID_EDITINGPANEL, ID_EDITINGPANELADDBUTTON, ID_EDITINGPANELINDEXCHOICE, 
243  ID_EDITINGPANELINDEXLIST, ID_EDITINGPANELINDEXLISTPANEL, ID_EDITINGPANELPARTLIST, 
244  ID_EDITINGPANELSECONDSPLITTER, ID_EDITINGPANELSUBINDEXGRID,
245  ID_EDITINGPANELSUBINDEXGRIDPANEL, ID_EDITINGPANELCALLBACKCHECK,
246 ] = [wx.NewId() for _init_ctrls in range(10)]
247
248 [ID_EDITINGPANELINDEXLISTMENUITEMS0, ID_EDITINGPANELINDEXLISTMENUITEMS1, 
249  ID_EDITINGPANELINDEXLISTMENUITEMS2, 
250 ] = [wx.NewId() for _init_coll_IndexListMenu_Items in range(3)]
251
252 [ID_EDITINGPANELMENU1ITEMS0, ID_EDITINGPANELMENU1ITEMS1, 
253  ID_EDITINGPANELMENU1ITEMS3, ID_EDITINGPANELMENU1ITEMS4, 
254 ] = [wx.NewId() for _init_coll_SubindexGridMenu_Items in range(4)]
255
256 class EditingPanel(wx.SplitterWindow):
257     def _init_coll_AddToListSizer_Items(self, parent):
258         parent.AddWindow(self.AddButton, 0, border=0, flag=0)
259         parent.AddWindow(self.IndexChoice, 0, border=0, flag=wx.GROW)
260
261     def _init_coll_SubindexGridSizer_Items(self, parent):
262         parent.AddWindow(self.CallbackCheck, 0, border=0, flag=0)
263         parent.AddWindow(self.SubindexGrid, 0, border=0, flag=wx.GROW)
264
265     def _init_coll_IndexListSizer_Items(self, parent):
266         parent.AddWindow(self.IndexList, 0, border=0, flag=wx.GROW)
267         parent.AddSizer(self.AddToListSizer, 0, border=0, flag=wx.GROW)
268
269     def _init_coll_AddToListSizer_Growables(self, parent):
270         parent.AddGrowableCol(1)
271
272     def _init_coll_SubindexGridSizer_Growables(self, parent):
273         parent.AddGrowableCol(0)
274         parent.AddGrowableRow(1)
275
276     def _init_coll_IndexListSizer_Growables(self, parent):
277         parent.AddGrowableCol(0)
278         parent.AddGrowableRow(0)
279
280     def _init_coll_SubindexGridMenu_Items(self, parent):
281         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS0,
282               kind=wx.ITEM_NORMAL, text='Add subindexes')
283         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS1,
284               kind=wx.ITEM_NORMAL, text='Delete subindexes')
285         parent.AppendSeparator()
286         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS3,
287               kind=wx.ITEM_NORMAL, text='Default value')
288         if not self.Editable:
289             parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS4,
290                   kind=wx.ITEM_NORMAL, text='Add to DCF')
291         self.Bind(wx.EVT_MENU, self.OnAddSubindexMenu,
292               id=ID_EDITINGPANELMENU1ITEMS0)
293         self.Bind(wx.EVT_MENU, self.OnDeleteSubindexMenu,
294               id=ID_EDITINGPANELMENU1ITEMS1)
295         self.Bind(wx.EVT_MENU, self.OnDefaultValueSubindexMenu,
296               id=ID_EDITINGPANELMENU1ITEMS3)
297         if not self.Editable:
298             self.Bind(wx.EVT_MENU, self.OnAddToDCFSubindexMenu,
299                   id=ID_EDITINGPANELMENU1ITEMS4)
300
301     def _init_coll_IndexListMenu_Items(self, parent):
302         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS0,
303               kind=wx.ITEM_NORMAL, text='Rename')
304         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS2,
305               kind=wx.ITEM_NORMAL, text='Modify')
306         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS1,
307               kind=wx.ITEM_NORMAL, text='Delete')
308         self.Bind(wx.EVT_MENU, self.OnRenameIndexMenu,
309               id=ID_EDITINGPANELINDEXLISTMENUITEMS0)
310         self.Bind(wx.EVT_MENU, self.OnDeleteIndexMenu,
311               id=ID_EDITINGPANELINDEXLISTMENUITEMS1)
312         self.Bind(wx.EVT_MENU, self.OnModifyIndexMenu,
313               id=ID_EDITINGPANELINDEXLISTMENUITEMS2)
314
315     def _init_utils(self):
316         self.IndexListMenu = wx.Menu(title='')
317         self.SubindexGridMenu = wx.Menu(title='')
318
319         self._init_coll_IndexListMenu_Items(self.IndexListMenu)
320         self._init_coll_SubindexGridMenu_Items(self.SubindexGridMenu)
321
322     def _init_sizers(self):
323         self.IndexListSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
324         self.SubindexGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
325         self.AddToListSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
326
327         self._init_coll_IndexListSizer_Growables(self.IndexListSizer)
328         self._init_coll_IndexListSizer_Items(self.IndexListSizer)
329         self._init_coll_SubindexGridSizer_Growables(self.SubindexGridSizer)
330         self._init_coll_SubindexGridSizer_Items(self.SubindexGridSizer)
331         self._init_coll_AddToListSizer_Growables(self.AddToListSizer)
332         self._init_coll_AddToListSizer_Items(self.AddToListSizer)
333
334         self.SubindexGridPanel.SetSizer(self.SubindexGridSizer)
335         self.IndexListPanel.SetSizer(self.IndexListSizer)
336         
337     def _init_ctrls(self, prnt):
338         wx.SplitterWindow.__init__(self, id=ID_EDITINGPANEL,
339               name='MainSplitter', parent=prnt, point=wx.Point(0, 0),
340               size=wx.Size(-1, -1), style=wx.SP_3D)
341         self._init_utils()
342         self.SetNeedUpdating(True)
343         self.SetMinimumPaneSize(1)
344
345         self.PartList = wx.ListBox(choices=[], id=ID_EDITINGPANELPARTLIST,
346               name='PartList', parent=self, pos=wx.Point(0, 0),
347               size=wx.Size(-1, -1), style=0)
348         self.PartList.Bind(wx.EVT_LISTBOX, self.OnPartListBoxClick,
349               id=ID_EDITINGPANELPARTLIST)
350
351         self.SecondSplitter = wx.SplitterWindow(id=ID_EDITINGPANELSECONDSPLITTER,
352               name='SecondSplitter', parent=self, point=wx.Point(0, 0), 
353               size=wx.Size(-1, -1), style=wx.SP_3D)
354         self.SecondSplitter.SetMinimumPaneSize(1)
355         self.SplitHorizontally(self.PartList, self.SecondSplitter,
356               110)
357
358         self.SubindexGridPanel = wx.Panel(id=ID_EDITINGPANELSUBINDEXGRIDPANEL,
359               name='SubindexGridPanel', parent=self.SecondSplitter, 
360               pos=wx.Point(0, 0), size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
361
362         self.IndexListPanel = wx.Panel(id=ID_EDITINGPANELINDEXLISTPANEL,
363               name='IndexListPanel', parent=self.SecondSplitter, 
364               pos=wx.Point(0, 0), size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
365         self.SecondSplitter.SplitVertically(self.IndexListPanel,
366               self.SubindexGridPanel, 280)
367
368         self.SubindexGrid = wx.grid.Grid(id=ID_EDITINGPANELSUBINDEXGRID,
369               name='SubindexGrid', parent=self.SubindexGridPanel, pos=wx.Point(0,
370               0), size=wx.Size(-1, -1), style=0)
371         self.SubindexGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
372               'Sans'))
373         self.SubindexGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
374               False, 'Sans'))
375         self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
376               self.OnSubindexGridCellChange)
377         self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK,
378               self.OnSubindexGridRightClick)
379         self.SubindexGrid.Bind(wx.grid.EVT_GRID_SELECT_CELL,
380               self.OnSubindexGridSelectCell)
381         self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, 
382               self.OnSubindexGridCellLeftClick)
383         self.SubindexGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, 
384               self.OnSubindexGridEditorShown)
385
386         self.CallbackCheck = wx.CheckBox(id=ID_EDITINGPANELCALLBACKCHECK,
387               label='Have Callbacks', name='CallbackCheck',
388               parent=self.SubindexGridPanel, pos=wx.Point(0, 0), size=wx.Size(152,
389               24), style=0)
390         self.CallbackCheck.Bind(wx.EVT_CHECKBOX, self.OnCallbackCheck,
391               id=ID_EDITINGPANELCALLBACKCHECK)
392
393         self.IndexList = wx.ListBox(choices=[], id=ID_EDITINGPANELINDEXLIST,
394               name='IndexList', parent=self.IndexListPanel, pos=wx.Point(0, 0),
395               size=wx.Size(-1, -1), style=0)
396         self.IndexList.Bind(wx.EVT_LISTBOX, self.OnIndexListClick,
397               id=ID_EDITINGPANELINDEXLIST)
398         self.IndexList.Bind(wx.EVT_RIGHT_UP, self.OnIndexListRightUp)
399
400         self.AddButton = wx.Button(id=ID_EDITINGPANELADDBUTTON, label='Add',
401               name='AddButton', parent=self.IndexListPanel, pos=wx.Point(0, 0),
402               size=wx.Size(50, 30), style=0)
403         self.AddButton.Bind(wx.EVT_BUTTON, self.OnAddButtonClick,
404               id=ID_EDITINGPANELADDBUTTON)
405
406         self.IndexChoice = wx.Choice(choices=[], id=ID_EDITINGPANELINDEXCHOICE,
407               name='IndexChoice', parent=self.IndexListPanel, pos=wx.Point(50,
408               0), size=wx.Size(-1, 30), style=0)
409
410         self._init_sizers()
411
412     def __init__(self, parent, window, manager, editable = True):
413         self.Editable = editable
414         self._init_ctrls(parent)
415         self.ParentWindow = window
416         self.Manager = manager
417         self.ListIndex = []
418         self.ChoiceIndex = []
419         self.FirstCall = False
420         self.Index = None
421         
422         for values in DictionaryOrganisation:
423             text = "   0x%04X-0x%04X      %s"%(values["minIndex"], values["maxIndex"], values["name"])
424             self.PartList.Append(text)
425         self.Table = SubindexTable(self, [], [], ["subindex", "name", "type", "value", "access", "save", "comment"])
426         self.SubindexGrid.SetTable(self.Table)
427         self.SubindexGrid.SetRowLabelSize(0)
428         self.CallbackCheck.Disable()
429         self.Table.ResetView(self.SubindexGrid)
430
431         if not self.Editable:
432             self.AddButton.Disable()
433             self.IndexChoice.Disable()
434             self.CallbackCheck.Disable()
435             self.Table.Disable()
436
437     def GetIndex(self):
438         return self.Index
439     
440     def SetIndex(self, index):
441         self.Index = index
442
443     def GetSelection(self):
444         selected = self.IndexList.GetSelection()
445         if selected != wx.NOT_FOUND:
446             index = self.ListIndex[selected]
447             subIndex = self.SubindexGrid.GetGridCursorRow()
448             return index, subIndex
449         return None
450
451     def OnSubindexGridCellLeftClick(self, event):
452         if not self.ParentWindow.ModeSolo:
453             col = event.GetCol()
454             if not self.Editable and col == 0:
455                 selected = self.IndexList.GetSelection()
456                 if selected != wx.NOT_FOUND:
457                     index = self.ListIndex[selected]
458                     subindex = event.GetRow()
459                     entry_infos = self.Manager.GetEntryInfos(index)
460                     if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0:
461                         subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
462                         typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
463                         if subentry_infos["pdo"] and typeinfos:
464                             bus_id = '.'.join(map(str, self.ParentWindow.GetBusId()))
465                             node_id = self.ParentWindow.GetCurrentNodeId()
466                             size = typeinfos["size"]
467                             data = wx.TextDataObject(str(("%s%s.%d.%d.%d"%(SizeConversion[size], bus_id, node_id, index, subindex), "location")))
468                             dragSource = wx.DropSource(self.SubindexGrid)
469                             dragSource.SetData(data)
470                             dragSource.DoDragDrop()
471         event.Skip()
472
473     def OnAddButtonClick(self, event):
474         if self.Editable:
475             self.SubindexGrid.SetGridCursor(0, 0)
476             selected = self.IndexChoice.GetStringSelection()
477             if selected != "":
478                 if selected == "User Type":
479                     self.ParentWindow.AddUserType()
480                 elif selected == "SDO Server":
481                     self.Manager.AddSDOServerToCurrent()
482                 elif selected == "SDO Client":
483                     self.Manager.AddSDOClientToCurrent()
484                 elif selected == "PDO Receive":
485                     self.Manager.AddPDOReceiveToCurrent()
486                 elif selected == "PDO Transmit":
487                     self.Manager.AddPDOTransmitToCurrent()
488                 elif selected == "Map Variable":
489                     self.ParentWindow.AddMapVariable()
490                 elif selected in [menu for menu, indexes in self.Manager.GetCurrentSpecificMenu()]:
491                     self.Manager.AddSpecificEntryToCurrent(selected)
492                 else:
493                     index = self.ChoiceIndex[self.IndexChoice.GetSelection()]
494                     self.Manager.ManageEntriesOfCurrent([index], [])
495                 self.ParentWindow.RefreshBufferState()
496                 self.RefreshIndexList()
497         event.Skip()
498
499     def OnPartListBoxClick(self, event):
500         self.SubindexGrid.SetGridCursor(0, 0)
501         self.RefreshIndexList()
502         event.Skip()
503
504     def OnIndexListClick(self, event):
505         self.SubindexGrid.SetGridCursor(0, 0)
506         self.RefreshTable()
507         event.Skip()
508
509     def OnSubindexGridSelectCell(self, event):
510         wx.CallAfter(self.ParentWindow.RefreshStatusBar)
511         event.Skip()
512
513 #-------------------------------------------------------------------------------
514 #                             Refresh Functions
515 #-------------------------------------------------------------------------------
516
517     def RefreshIndexList(self):
518         selected = self.IndexList.GetSelection()
519         choice = self.IndexChoice.GetStringSelection()
520         choiceindex = self.IndexChoice.GetSelection()
521         if selected != wx.NOT_FOUND:
522             selectedindex = self.ListIndex[selected]
523         self.IndexList.Clear()
524         self.IndexChoice.Clear()
525         i = self.PartList.GetSelection()
526         if i < len(DictionaryOrganisation):
527             values = DictionaryOrganisation[i]
528             self.ListIndex = []
529             for name, index in self.Manager.GetCurrentValidIndexes(values["minIndex"], values["maxIndex"]):
530                 self.IndexList.Append("0x%04X   %s"%(index, name))
531                 self.ListIndex.append(index)
532             if self.Editable:
533                 self.ChoiceIndex = []
534                 if i == 0:
535                     self.IndexChoice.Append("User Type")
536                     self.IndexChoice.SetStringSelection("User Type")
537                 elif i == 2:
538                     self.IndexChoice.Append("SDO Server")
539                     self.IndexChoice.Append("SDO Client")
540                     if choiceindex != wx.NOT_FOUND and choice == self.IndexChoice.GetString(choiceindex):
541                          self.IndexChoice.SetStringSelection(choice)
542                 elif i in (3, 4):
543                     self.IndexChoice.Append("PDO Receive")
544                     self.IndexChoice.SetStringSelection("PDO Receive")
545                 elif i in (5, 6):
546                     self.IndexChoice.Append("PDO Transmit")
547                     self.IndexChoice.SetStringSelection("PDO Transmit")
548                 elif i == 8:
549                     self.IndexChoice.Append("Map Variable")
550                     self.IndexChoice.SetStringSelection("Map Variable")
551                 else:
552                     for name, index in self.Manager.GetCurrentValidChoices(values["minIndex"], values["maxIndex"]):
553                         if index:
554                             self.IndexChoice.Append("0x%04X   %s"%(index, name))
555                         else:
556                             self.IndexChoice.Append(name)
557                         self.ChoiceIndex.append(index)
558                 if choiceindex != wx.NOT_FOUND and choiceindex < self.IndexChoice.GetCount() and choice == self.IndexChoice.GetString(choiceindex):
559                     self.IndexChoice.SetStringSelection(choice)
560         if self.Editable:
561             self.IndexChoice.Enable(self.IndexChoice.GetCount() != 0)
562             self.AddButton.Enable(self.IndexChoice.GetCount() != 0)
563         if selected == wx.NOT_FOUND or selected >= len(self.ListIndex) or selectedindex != self.ListIndex[selected]:
564             self.Table.Empty()
565             self.CallbackCheck.SetValue(False)
566             self.CallbackCheck.Disable()
567             self.Table.ResetView(self.SubindexGrid)
568             self.ParentWindow.RefreshStatusBar()
569         else:
570             self.IndexList.SetSelection(selected)
571             self.RefreshTable()
572
573     def RefreshTable(self):
574         selected = self.IndexList.GetSelection()
575         if selected != wx.NOT_FOUND:
576             index = self.ListIndex[selected]
577             if index > 0x260 and self.Editable:
578                 self.CallbackCheck.Enable()
579                 self.CallbackCheck.SetValue(self.Manager.HasCurrentEntryCallbacks(index))
580             result = self.Manager.GetCurrentEntryValues(index)
581             if result != None:
582                 self.Table.SetCurrentIndex(index)
583                 data, editors = result
584                 self.Table.SetData(data)
585                 self.Table.SetEditors(editors)
586                 self.Table.ResetView(self.SubindexGrid)
587         self.ParentWindow.RefreshStatusBar()
588
589 #-------------------------------------------------------------------------------
590 #                        Editing Table value function
591 #-------------------------------------------------------------------------------
592
593     def OnSubindexGridEditorShown(self, event):
594         row, col = event.GetRow(), event.GetCol() 
595         if self.Table.GetEditor(row, col) == "dcf":
596             wx.CallAfter(self.ShowDCFEntryDialog, row, col)
597             event.Veto()
598         else:
599             event.Skip()
600
601     def ShowDCFEntryDialog(self, row, col):
602         if self.Editable:
603             selected = self.IndexList.GetSelection()
604             if selected != wx.NOT_FOUND:
605                 index = self.ListIndex[selected]
606                 if self.Manager.IsCurrentEntry(index):
607                     dialog = DCFEntryValuesDialog(self)
608                     dialog.SetValues(self.Table.GetValue(row, col).decode("hex_codec"))
609                     if dialog.ShowModal() == wx.ID_OK:
610                         value = dialog.GetValues()
611                         self.Manager.SetCurrentEntry(index, row, value, "value", "dcf")
612                         self.ParentWindow.RefreshBufferState()
613                         wx.CallAfter(self.RefreshTable)
614
615     def OnSubindexGridCellChange(self, event):
616         if self.Editable:
617             index = self.Table.GetCurrentIndex()
618             subIndex = event.GetRow()
619             col = event.GetCol()
620             name = self.Table.GetColLabelValue(col)
621             value = self.Table.GetValue(subIndex, col)
622             editor = self.Table.GetEditor(subIndex, col)
623             self.Manager.SetCurrentEntry(index, subIndex, value, name, editor)
624             self.ParentWindow.RefreshBufferState()
625             wx.CallAfter(self.RefreshTable)
626         event.Skip()
627
628     def OnCallbackCheck(self, event):
629         if self.Editable:
630             index = self.Table.GetCurrentIndex()
631             self.Manager.SetCurrentEntryCallbacks(index, self.CallbackCheck.GetValue())
632             self.ParentWindow.RefreshBufferState()
633             wx.CallAfter(self.RefreshTable)
634         event.Skip()
635
636 #-------------------------------------------------------------------------------
637 #                          Contextual Menu functions
638 #-------------------------------------------------------------------------------
639
640     def OnIndexListRightUp(self, event):
641         if self.Editable:
642             if not self.FirstCall:
643                 self.FirstCall = True
644                 selected = self.IndexList.GetSelection()
645                 if selected != wx.NOT_FOUND:
646                     index = self.ListIndex[selected]
647                     if index < 0x260:
648                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
649                         self.IndexListMenu.FindItemByPosition(1).Enable(True)
650                         self.PopupMenu(self.IndexListMenu)
651                     elif 0x1000 <= index <= 0x1FFF:
652                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
653                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
654                         self.PopupMenu(self.IndexListMenu)
655                     elif 0x2000 <= index <= 0x5FFF:
656                         self.IndexListMenu.FindItemByPosition(0).Enable(True)
657                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
658                         self.PopupMenu(self.IndexListMenu)
659                     elif index >= 0x6000:
660                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
661                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
662                         self.PopupMenu(self.IndexListMenu)
663             else:
664                 self.FirstCall = False
665         event.Skip()
666
667     def OnSubindexGridRightClick(self, event):
668         self.SubindexGrid.SetGridCursor(event.GetRow(), event.GetCol())
669         if self.Editable:
670             selected = self.IndexList.GetSelection()
671             if selected != wx.NOT_FOUND:
672                 index = self.ListIndex[selected]
673                 if self.Manager.IsCurrentEntry(index):
674                     showpopup = False
675                     infos = self.Manager.GetEntryInfos(index)
676                     if 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_MultipleSubindexes or infos["struct"] & OD_IdenticalSubindexes:
677                         showpopup = True
678                         self.SubindexGridMenu.FindItemByPosition(0).Enable(True)
679                         self.SubindexGridMenu.FindItemByPosition(1).Enable(True)
680                     else:
681                         self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
682                         self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
683                     if self.Table.GetColLabelValue(event.GetCol()) == "value":
684                         showpopup = True
685                         self.SubindexGridMenu.FindItemByPosition(3).Enable(True)
686                     else:
687                         self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
688                     if showpopup:
689                         self.PopupMenu(self.SubindexGridMenu)
690         elif self.Table.GetColLabelValue(event.GetCol()) == "value":
691             selected = self.IndexList.GetSelection()
692             if selected != wx.NOT_FOUND:
693                 index = self.ListIndex[selected]
694                 if self.Manager.IsCurrentEntry(index):
695                     infos = self.Manager.GetEntryInfos(index)
696                     if not infos["struct"] & OD_MultipleSubindexes or event.GetRow() > 0:
697                         self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
698                         self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
699                         self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
700                         self.SubindexGridMenu.FindItemByPosition(4).Enable(True)
701                         self.PopupMenu(self.SubindexGridMenu)
702         event.Skip()
703
704     def OnAddToDCFSubindexMenu(self, event):
705         if not self.Editable:
706             selected = self.IndexList.GetSelection()
707             if selected != wx.NOT_FOUND:
708                 index = self.ListIndex[selected]
709                 subindex = self.SubindexGrid.GetGridCursorRow()
710                 entry_infos = self.Manager.GetEntryInfos(index)
711                 if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0:
712                     subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
713                     typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
714                     if typeinfos:
715                         node_id = self.ParentWindow.GetCurrentNodeId()
716                         value = self.Table.GetValueByName(subindex, "value")
717                         if value == "True":
718                             value = 1
719                         elif value == "False":
720                             value = 0
721                         elif value.isdigit():
722                             value = int(value)
723                         elif value.startswith("0x"):
724                             value = int(value, 16)
725                         else:
726                             value = int(value.encode("hex_codec"), 16)
727                         self.Manager.AddToMasterDCF(node_id, index, subindex, max(1, typeinfos["size"] / 8), value)    
728                         self.ParentWindow.OpenMasterDCFDialog(node_id)
729
730     def OpenDCFDialog(self, node_id):
731         self.PartList.SetSelection(7)
732         self.RefreshIndexList()
733         self.IndexList.SetSelection(self.ListIndex.index(0x1F22))
734         self.RefreshTable()
735         self.SubindexGrid.SetGridCursor(node_id, 3)
736         self.ShowDCFEntryDialog(node_id, 3)
737
738     def OnRenameIndexMenu(self, event):
739         if self.Editable:
740             selected = self.IndexList.GetSelection()
741             if selected != wx.NOT_FOUND:
742                 index = self.ListIndex[selected]
743                 if self.Manager.IsCurrentEntry(index):
744                     infos = self.Manager.GetEntryInfos(index)
745                     dialog = wx.TextEntryDialog(self, "Give a new name for index 0x%04X"%index,
746                                  "Rename an index", infos["name"], wx.OK|wx.CANCEL)
747                     if dialog.ShowModal() == wx.ID_OK:
748                         self.Manager.SetCurrentEntryName(index, dialog.GetValue())
749                         self.ParentWindow.RefreshBufferState()
750                         self.RefreshIndexList()
751                     dialog.Destroy()
752         event.Skip()
753
754     def OnModifyIndexMenu(self, event):
755         if self.Editable:
756             selected = self.IndexList.GetSelection()
757             if selected != wx.NOT_FOUND:
758                 index = self.ListIndex[selected]
759                 if self.Manager.IsCurrentEntry(index) and index < 0x260:
760                     values, valuetype = self.Manager.GetCustomisedTypeValues(index)
761                     dialog = UserTypeDialog(self)
762                     dialog.SetTypeList(self.Manager.GetCustomisableTypes(), values[1])
763                     if valuetype == 0:
764                         dialog.SetValues(min = values[2], max = values[3])
765                     elif valuetype == 1:
766                         dialog.SetValues(length = values[2])
767                     if dialog.ShowModal() == wx.ID_OK:
768                         type, min, max, length = dialog.GetValues()
769                         self.Manager.SetCurrentUserType(index, type, min, max, length)
770                         self.ParentWindow.RefreshBufferState()
771                         self.RefreshIndexList()
772         event.Skip()
773         
774     def OnDeleteIndexMenu(self, event):
775         if self.Editable:
776             selected = self.IndexList.GetSelection()
777             if selected != wx.NOT_FOUND:
778                 index = self.ListIndex[selected]
779                 if self.Manager.IsCurrentEntry(index):
780                     self.Manager.ManageEntriesOfCurrent([],[index])
781                     self.ParentWindow.RefreshBufferState()
782                     self.RefreshIndexList()
783         event.Skip()
784
785     def OnAddSubindexMenu(self, event):
786         if self.Editable:
787             selected = self.IndexList.GetSelection()
788             if selected != wx.NOT_FOUND:
789                 index = self.ListIndex[selected]
790                 if self.Manager.IsCurrentEntry(index):
791                     dialog = wx.TextEntryDialog(self, "Number of subindexes to add:",
792                                  "Add subindexes", "1", wx.OK|wx.CANCEL)
793                     if dialog.ShowModal() == wx.ID_OK:
794                         try:
795                             number = int(dialog.GetValue())
796                             self.Manager.AddSubentriesToCurrent(index, number)
797                             self.ParentWindow.RefreshBufferState()
798                             self.RefreshIndexList()
799                         except:
800                             message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
801                             message.ShowModal()
802                             message.Destroy()
803                     dialog.Destroy()
804         event.Skip()
805
806     def OnDeleteSubindexMenu(self, event):
807         if self.Editable:
808             selected = self.IndexList.GetSelection()
809             if selected != wx.NOT_FOUND:
810                 index = self.ListIndex[selected]
811                 if self.Manager.IsCurrentEntry(index):
812                     dialog = wx.TextEntryDialog(self, "Number of subindexes to delete:",
813                                  "Delete subindexes", "1", wx.OK|wx.CANCEL)
814                     if dialog.ShowModal() == wx.ID_OK:
815                         try:
816                             number = int(dialog.GetValue())
817                             self.Manager.RemoveSubentriesFromCurrent(index, number)
818                             self.ParentWindow.RefreshBufferState()
819                             self.RefreshIndexList()
820                         except:
821                             message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
822                             message.ShowModal()
823                             message.Destroy()
824                     dialog.Destroy()
825         event.Skip()
826
827     def OnDefaultValueSubindexMenu(self, event):
828         if self.Editable:
829             selected = self.IndexList.GetSelection()
830             if selected != wx.NOT_FOUND:
831                 index = self.ListIndex[selected]
832                 if self.Manager.IsCurrentEntry(index):
833                     row = self.SubindexGrid.GetGridCursorRow()
834                     self.Manager.SetCurrentEntryToDefault(index, row)
835                     self.ParentWindow.RefreshBufferState()
836                     self.RefreshIndexList()
837         event.Skip()