]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - objdictgen/subindextable.py
Adding standard default value to index 0x1014
[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                 else:
213                     grid.SetReadOnly(row, col, True)
214                     
215                 grid.SetCellEditor(row, col, editor)
216                 grid.SetCellRenderer(row, col, renderer)
217                 
218                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
219     
220     def SetData(self, data):
221         self.data = data
222         
223     def SetEditors(self, editors):
224         self.editors = editors
225     
226     def GetCurrentIndex(self):
227         return self.CurrentIndex
228     
229     def SetCurrentIndex(self, index):
230         self.CurrentIndex = index
231     
232     def AppendRow(self, row_content):
233         self.data.append(row_content)
234
235     def Empty(self):
236         self.data = []
237         self.editors = []
238
239 [ID_EDITINGPANEL, ID_EDITINGPANELADDBUTTON, ID_EDITINGPANELINDEXCHOICE, 
240  ID_EDITINGPANELINDEXLIST, ID_EDITINGPANELINDEXLISTPANEL, ID_EDITINGPANELPARTLIST, 
241  ID_EDITINGPANELSECONDSPLITTER, ID_EDITINGPANELSUBINDEXGRID,
242  ID_EDITINGPANELSUBINDEXGRIDPANEL, ID_EDITINGPANELCALLBACKCHECK,
243 ] = [wx.NewId() for _init_ctrls in range(10)]
244
245 [ID_EDITINGPANELINDEXLISTMENUITEMS0, ID_EDITINGPANELINDEXLISTMENUITEMS1, 
246  ID_EDITINGPANELINDEXLISTMENUITEMS2, 
247 ] = [wx.NewId() for _init_coll_IndexListMenu_Items in range(3)]
248
249 [ID_EDITINGPANELMENU1ITEMS0, ID_EDITINGPANELMENU1ITEMS1, 
250  ID_EDITINGPANELMENU1ITEMS3, 
251 ] = [wx.NewId() for _init_coll_SubindexGridMenu_Items in range(3)]
252
253 class EditingPanel(wx.SplitterWindow):
254     def _init_coll_AddToListSizer_Items(self, parent):
255         parent.AddWindow(self.AddButton, 0, border=0, flag=0)
256         parent.AddWindow(self.IndexChoice, 0, border=0, flag=wx.GROW)
257
258     def _init_coll_SubindexGridSizer_Items(self, parent):
259         parent.AddWindow(self.CallbackCheck, 0, border=0, flag=0)
260         parent.AddWindow(self.SubindexGrid, 0, border=0, flag=wx.GROW)
261
262     def _init_coll_IndexListSizer_Items(self, parent):
263         parent.AddWindow(self.IndexList, 0, border=0, flag=wx.GROW)
264         parent.AddSizer(self.AddToListSizer, 0, border=0, flag=wx.GROW)
265
266     def _init_coll_AddToListSizer_Growables(self, parent):
267         parent.AddGrowableCol(1)
268
269     def _init_coll_SubindexGridSizer_Growables(self, parent):
270         parent.AddGrowableCol(0)
271         parent.AddGrowableRow(1)
272
273     def _init_coll_IndexListSizer_Growables(self, parent):
274         parent.AddGrowableCol(0)
275         parent.AddGrowableRow(0)
276
277     def _init_coll_SubindexGridMenu_Items(self, parent):
278         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS0,
279               kind=wx.ITEM_NORMAL, text='Add subindexes')
280         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS1,
281               kind=wx.ITEM_NORMAL, text='Delete subindexes')
282         parent.AppendSeparator()
283         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS3,
284               kind=wx.ITEM_NORMAL, text='Default value')
285         self.Bind(wx.EVT_MENU, self.OnAddSubindexMenu,
286               id=ID_EDITINGPANELMENU1ITEMS0)
287         self.Bind(wx.EVT_MENU, self.OnDeleteSubindexMenu,
288               id=ID_EDITINGPANELMENU1ITEMS1)
289         self.Bind(wx.EVT_MENU, self.OnDefaultValueSubindexMenu,
290               id=ID_EDITINGPANELMENU1ITEMS3)
291
292     def _init_coll_IndexListMenu_Items(self, parent):
293         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS0,
294               kind=wx.ITEM_NORMAL, text='Rename')
295         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS2,
296               kind=wx.ITEM_NORMAL, text='Modify')
297         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS1,
298               kind=wx.ITEM_NORMAL, text='Delete')
299         self.Bind(wx.EVT_MENU, self.OnRenameIndexMenu,
300               id=ID_EDITINGPANELINDEXLISTMENUITEMS0)
301         self.Bind(wx.EVT_MENU, self.OnDeleteIndexMenu,
302               id=ID_EDITINGPANELINDEXLISTMENUITEMS1)
303         self.Bind(wx.EVT_MENU, self.OnModifyIndexMenu,
304               id=ID_EDITINGPANELINDEXLISTMENUITEMS2)
305
306     def _init_utils(self):
307         self.IndexListMenu = wx.Menu(title='')
308         self.SubindexGridMenu = wx.Menu(title='')
309
310         self._init_coll_IndexListMenu_Items(self.IndexListMenu)
311         self._init_coll_SubindexGridMenu_Items(self.SubindexGridMenu)
312
313     def _init_sizers(self):
314         self.IndexListSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
315         self.SubindexGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
316         self.AddToListSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
317
318         self._init_coll_IndexListSizer_Growables(self.IndexListSizer)
319         self._init_coll_IndexListSizer_Items(self.IndexListSizer)
320         self._init_coll_SubindexGridSizer_Growables(self.SubindexGridSizer)
321         self._init_coll_SubindexGridSizer_Items(self.SubindexGridSizer)
322         self._init_coll_AddToListSizer_Growables(self.AddToListSizer)
323         self._init_coll_AddToListSizer_Items(self.AddToListSizer)
324
325         self.SubindexGridPanel.SetSizer(self.SubindexGridSizer)
326         self.IndexListPanel.SetSizer(self.IndexListSizer)
327         
328     def _init_ctrls(self, prnt):
329         wx.SplitterWindow.__init__(self, id=ID_EDITINGPANEL,
330               name='MainSplitter', parent=prnt, point=wx.Point(0, 0),
331               size=wx.Size(-1, -1), style=wx.SP_3D)
332         self._init_utils()
333         self.SetNeedUpdating(True)
334         self.SetMinimumPaneSize(1)
335
336         self.PartList = wx.ListBox(choices=[], id=ID_EDITINGPANELPARTLIST,
337               name='PartList', parent=self, pos=wx.Point(0, 0),
338               size=wx.Size(-1, -1), style=0)
339         self.PartList.Bind(wx.EVT_LISTBOX, self.OnPartListBoxClick,
340               id=ID_EDITINGPANELPARTLIST)
341
342         self.SecondSplitter = wx.SplitterWindow(id=ID_EDITINGPANELSECONDSPLITTER,
343               name='SecondSplitter', parent=self, point=wx.Point(0, 0), 
344               size=wx.Size(-1, -1), style=wx.SP_3D)
345         self.SecondSplitter.SetMinimumPaneSize(1)
346         self.SplitHorizontally(self.PartList, self.SecondSplitter,
347               110)
348
349         self.SubindexGridPanel = wx.Panel(id=ID_EDITINGPANELSUBINDEXGRIDPANEL,
350               name='SubindexGridPanel', parent=self.SecondSplitter, 
351               pos=wx.Point(0, 0), size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
352
353         self.IndexListPanel = wx.Panel(id=ID_EDITINGPANELINDEXLISTPANEL,
354               name='IndexListPanel', parent=self.SecondSplitter, 
355               pos=wx.Point(0, 0), size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
356         self.SecondSplitter.SplitVertically(self.IndexListPanel,
357               self.SubindexGridPanel, 280)
358
359         self.SubindexGrid = wx.grid.Grid(id=ID_EDITINGPANELSUBINDEXGRID,
360               name='SubindexGrid', parent=self.SubindexGridPanel, pos=wx.Point(0,
361               0), size=wx.Size(-1, -1), style=0)
362         self.SubindexGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
363               'Sans'))
364         self.SubindexGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
365               False, 'Sans'))
366         self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
367               self.OnSubindexGridCellChange)
368         self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK,
369               self.OnSubindexGridRightClick)
370         self.SubindexGrid.Bind(wx.grid.EVT_GRID_SELECT_CELL,
371               self.OnSubindexGridSelectCell)
372         self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnSubindexGridCellLeftClick)
373
374         self.CallbackCheck = wx.CheckBox(id=ID_EDITINGPANELCALLBACKCHECK,
375               label='Have Callbacks', name='CallbackCheck',
376               parent=self.SubindexGridPanel, pos=wx.Point(0, 0), size=wx.Size(152,
377               24), style=0)
378         self.CallbackCheck.Bind(wx.EVT_CHECKBOX, self.OnCallbackCheck,
379               id=ID_EDITINGPANELCALLBACKCHECK)
380
381         self.IndexList = wx.ListBox(choices=[], id=ID_EDITINGPANELINDEXLIST,
382               name='IndexList', parent=self.IndexListPanel, pos=wx.Point(0, 0),
383               size=wx.Size(-1, -1), style=0)
384         self.IndexList.Bind(wx.EVT_LISTBOX, self.OnIndexListClick,
385               id=ID_EDITINGPANELINDEXLIST)
386         self.IndexList.Bind(wx.EVT_RIGHT_UP, self.OnIndexListRightUp)
387
388         self.AddButton = wx.Button(id=ID_EDITINGPANELADDBUTTON, label='Add',
389               name='AddButton', parent=self.IndexListPanel, pos=wx.Point(0, 0),
390               size=wx.Size(50, 30), style=0)
391         self.AddButton.Bind(wx.EVT_BUTTON, self.OnAddButtonClick,
392               id=ID_EDITINGPANELADDBUTTON)
393
394         self.IndexChoice = wx.Choice(choices=[], id=ID_EDITINGPANELINDEXCHOICE,
395               name='IndexChoice', parent=self.IndexListPanel, pos=wx.Point(50,
396               0), size=wx.Size(-1, 30), style=0)
397
398         self._init_sizers()
399
400     def __init__(self, parent, window, manager, editable = True):
401         self._init_ctrls(parent)
402         self.ParentWindow = window
403         self.Manager = manager
404         self.ListIndex = []
405         self.ChoiceIndex = []
406         self.FirstCall = False
407         self.Editable = editable
408         self.Index = None
409         
410         for values in DictionaryOrganisation:
411             text = "   0x%04X-0x%04X      %s"%(values["minIndex"], values["maxIndex"], values["name"])
412             self.PartList.Append(text)
413         self.Table = SubindexTable(self, [], [], ["subindex", "name", "type", "value", "access", "save", "comment"])
414         self.SubindexGrid.SetTable(self.Table)
415         self.SubindexGrid.SetRowLabelSize(0)
416         self.CallbackCheck.Disable()
417         self.Table.ResetView(self.SubindexGrid)
418
419         if not self.Editable:
420             self.AddButton.Disable()
421             self.IndexChoice.Disable()
422             self.CallbackCheck.Disable()
423             self.Table.Disable()
424
425     def GetIndex(self):
426         return self.Index
427     
428     def SetIndex(self, index):
429         self.Index = index
430
431     def GetSelection(self):
432         selected = self.IndexList.GetSelection()
433         if selected != wx.NOT_FOUND:
434             index = self.ListIndex[selected]
435             subIndex = self.SubindexGrid.GetGridCursorRow()
436             return index, subIndex
437         return None
438
439     def OnSubindexGridCellLeftClick(self, event):
440         wx.CallAfter(self.BeginDrag)
441         event.Skip()
442
443     def OnAddButtonClick(self, event):
444         if self.Editable:
445             self.SubindexGrid.SetGridCursor(0, 0)
446             selected = self.IndexChoice.GetStringSelection()
447             if selected != "":
448                 if selected == "User Type":
449                     self.ParentWindow.AddUserType()
450                 elif selected == "SDO Server":
451                     self.Manager.AddSDOServerToCurrent()
452                 elif selected == "SDO Client":
453                     self.Manager.AddSDOClientToCurrent()
454                 elif selected == "PDO Receive":
455                     self.Manager.AddPDOReceiveToCurrent()
456                 elif selected == "PDO Transmit":
457                     self.Manager.AddPDOTransmitToCurrent()
458                 elif selected == "Map Variable":
459                     self.ParentWindow.AddMapVariable()
460                 elif selected in [menu for menu, indexes in self.Manager.GetCurrentSpecificMenu()]:
461                     self.Manager.AddSpecificEntryToCurrent(selected)
462                 else:
463                     index = self.ChoiceIndex[self.IndexChoice.GetSelection()]
464                     self.Manager.ManageEntriesOfCurrent([index], [])
465                 self.ParentWindow.RefreshBufferState()
466                 self.RefreshIndexList()
467         event.Skip()
468
469     def OnPartListBoxClick(self, event):
470         self.SubindexGrid.SetGridCursor(0, 0)
471         self.RefreshIndexList()
472         event.Skip()
473
474     def OnIndexListClick(self, event):
475         self.SubindexGrid.SetGridCursor(0, 0)
476         self.RefreshTable()
477         event.Skip()
478
479     def OnSubindexGridSelectCell(self, event):
480         wx.CallAfter(self.BeginDrag)
481         wx.CallAfter(self.ParentWindow.RefreshStatusBar)
482         event.Skip()
483
484     def BeginDrag(self):
485         if not self.ParentWindow.ModeSolo:
486             row = self.SubindexGrid.GetGridCursorRow()
487             col = self.SubindexGrid.GetGridCursorCol()
488             if not self.Editable and col == 0:
489                 selected = self.IndexList.GetSelection()
490                 if selected != wx.NOT_FOUND:
491                     index = self.ListIndex[selected]
492                     subindex = self.SubindexGrid.GetGridCursorRow()
493                     entry_infos = self.Manager.GetEntryInfos(index)
494                     if not entry_infos["struct"] & OD_MultipleSubindexes or row != 0:
495                         subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
496                         typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
497                         if subentry_infos["pdo"] and typeinfos:
498                             bus_id = '.'.join(map(str,self.ParentWindow.GetBusId()))
499                             node_id = self.ParentWindow.GetCurrentNodeId()
500                             size = typeinfos["size"]
501                             data = wx.TextDataObject(str(("%s%s.%d.%d.%d"%(SizeConversion[size], bus_id, node_id, index, subindex), "location")))
502                             dragSource = wx.DropSource(self.SubindexGrid)
503                             dragSource.SetData(data)
504                             dragSource.DoDragDrop()
505
506 #-------------------------------------------------------------------------------
507 #                             Refresh Functions
508 #-------------------------------------------------------------------------------
509
510     def RefreshIndexList(self):
511         selected = self.IndexList.GetSelection()
512         choice = self.IndexChoice.GetStringSelection()
513         choiceindex = self.IndexChoice.GetSelection()
514         if selected != wx.NOT_FOUND:
515             selectedindex = self.ListIndex[selected]
516         self.IndexList.Clear()
517         self.IndexChoice.Clear()
518         i = self.PartList.GetSelection()
519         if i < len(DictionaryOrganisation):
520             values = DictionaryOrganisation[i]
521             self.ListIndex = []
522             for name, index in self.Manager.GetCurrentValidIndexes(values["minIndex"], values["maxIndex"]):
523                 self.IndexList.Append("0x%04X   %s"%(index, name))
524                 self.ListIndex.append(index)
525             if self.Editable:
526                 self.ChoiceIndex = []
527                 if i == 0:
528                     self.IndexChoice.Append("User Type")
529                     self.IndexChoice.SetStringSelection("User Type")
530                 elif i == 2:
531                     self.IndexChoice.Append("SDO Server")
532                     self.IndexChoice.Append("SDO Client")
533                     if choiceindex != wx.NOT_FOUND and choice == self.IndexChoice.GetString(choiceindex):
534                          self.IndexChoice.SetStringSelection(choice)
535                 elif i in (3, 4):
536                     self.IndexChoice.Append("PDO Receive")
537                     self.IndexChoice.SetStringSelection("PDO Receive")
538                 elif i in (5, 6):
539                     self.IndexChoice.Append("PDO Transmit")
540                     self.IndexChoice.SetStringSelection("PDO Transmit")
541                 elif i == 8:
542                     self.IndexChoice.Append("Map Variable")
543                     self.IndexChoice.SetStringSelection("Map Variable")
544                 else:
545                     for name, index in self.Manager.GetCurrentValidChoices(values["minIndex"], values["maxIndex"]):
546                         if index:
547                             self.IndexChoice.Append("0x%04X   %s"%(index, name))
548                         else:
549                             self.IndexChoice.Append(name)
550                         self.ChoiceIndex.append(index)
551                 if choiceindex != wx.NOT_FOUND and choiceindex < self.IndexChoice.GetCount() and choice == self.IndexChoice.GetString(choiceindex):
552                     self.IndexChoice.SetStringSelection(choice)
553         if self.Editable:
554             self.IndexChoice.Enable(self.IndexChoice.GetCount() != 0)
555             self.AddButton.Enable(self.IndexChoice.GetCount() != 0)
556         if selected == wx.NOT_FOUND or selected >= len(self.ListIndex) or selectedindex != self.ListIndex[selected]:
557             self.Table.Empty()
558             self.CallbackCheck.SetValue(False)
559             self.CallbackCheck.Disable()
560             self.Table.ResetView(self.SubindexGrid)
561             self.ParentWindow.RefreshStatusBar()
562         else:
563             self.IndexList.SetSelection(selected)
564             self.RefreshTable()
565
566     def RefreshTable(self):
567         selected = self.IndexList.GetSelection()
568         if selected != wx.NOT_FOUND:
569             index = self.ListIndex[selected]
570             if index > 0x260 and self.Editable:
571                 self.CallbackCheck.Enable()
572                 self.CallbackCheck.SetValue(self.Manager.HasCurrentEntryCallbacks(index))
573             result = self.Manager.GetCurrentEntryValues(index)
574             if result != None:
575                 self.Table.SetCurrentIndex(index)
576                 data, editors = result
577                 self.Table.SetData(data)
578                 self.Table.SetEditors(editors)
579                 self.Table.ResetView(self.SubindexGrid)
580         self.ParentWindow.RefreshStatusBar()
581
582 #-------------------------------------------------------------------------------
583 #                        Editing Table value function
584 #-------------------------------------------------------------------------------
585
586     def OnSubindexGridCellChange(self, event):
587         if self.Editable:
588             index = self.Table.GetCurrentIndex()
589             subIndex = event.GetRow()
590             col = event.GetCol()
591             name = self.Table.GetColLabelValue(col)
592             value = self.Table.GetValue(subIndex, col)
593             editor = self.Table.GetEditor(subIndex, col)
594             self.Manager.SetCurrentEntry(index, subIndex, value, name, editor)
595             self.ParentWindow.RefreshBufferState()
596             wx.CallAfter(self.RefreshTable)
597         event.Skip()
598
599     def OnCallbackCheck(self, event):
600         if self.Editable:
601             index = self.Table.GetCurrentIndex()
602             self.Manager.SetCurrentEntryCallbacks(index, self.CallbackCheck.GetValue())
603             self.ParentWindow.RefreshBufferState()
604             wx.CallAfter(self.RefreshTable)
605         event.Skip()
606
607 #-------------------------------------------------------------------------------
608 #                          Contextual Menu functions
609 #-------------------------------------------------------------------------------
610
611     def OnIndexListRightUp(self, event):
612         if self.Editable:
613             if not self.FirstCall:
614                 self.FirstCall = True
615                 selected = self.IndexList.GetSelection()
616                 if selected != wx.NOT_FOUND:
617                     index = self.ListIndex[selected]
618                     if index < 0x260:
619                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
620                         self.IndexListMenu.FindItemByPosition(1).Enable(True)
621                         self.PopupMenu(self.IndexListMenu)
622                     elif 0x1000 <= index <= 0x1FFF:
623                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
624                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
625                         self.PopupMenu(self.IndexListMenu)
626                     elif 0x2000 <= index <= 0x5FFF:
627                         self.IndexListMenu.FindItemByPosition(0).Enable(True)
628                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
629                         self.PopupMenu(self.IndexListMenu)
630                     elif index >= 0x6000:
631                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
632                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
633                         self.PopupMenu(self.IndexListMenu)
634             else:
635                 self.FirstCall = False
636         event.Skip()
637
638     def OnSubindexGridRightClick(self, event):
639         self.SubindexGrid.SetGridCursor(event.GetRow(), event.GetCol())
640         if self.Editable:
641             selected = self.IndexList.GetSelection()
642             if selected != wx.NOT_FOUND:
643                 index = self.ListIndex[selected]
644                 if self.Manager.IsCurrentEntry(index):
645                     showpopup = False
646                     infos = self.Manager.GetEntryInfos(index)
647                     if 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_MultipleSubindexes or infos["struct"] & OD_IdenticalSubindexes:
648                         showpopup = True
649                         self.SubindexGridMenu.FindItemByPosition(0).Enable(True)
650                         self.SubindexGridMenu.FindItemByPosition(1).Enable(True)
651                     else:
652                         self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
653                         self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
654                     if self.Table.GetColLabelValue(event.GetCol()) == "value":
655                         showpopup = True
656                         self.SubindexGridMenu.FindItemByPosition(3).Enable(True)
657                     else:
658                         self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
659                     if showpopup:
660                         self.PopupMenu(self.SubindexGridMenu)
661         event.Skip()
662
663     def OnRenameIndexMenu(self, event):
664         if self.Editable:
665             selected = self.IndexList.GetSelection()
666             if selected != wx.NOT_FOUND:
667                 index = self.ListIndex[selected]
668                 if self.Manager.IsCurrentEntry(index):
669                     infos = self.Manager.GetEntryInfos(index)
670                     dialog = wx.TextEntryDialog(self, "Give a new name for index 0x%04X"%index,
671                                  "Rename an index", infos["name"], wx.OK|wx.CANCEL)
672                     if dialog.ShowModal() == wx.ID_OK:
673                         self.Manager.SetCurrentEntryName(index, dialog.GetValue())
674                         self.ParentWindow.RefreshBufferState()
675                         self.RefreshIndexList()
676                     dialog.Destroy()
677         event.Skip()
678
679     def OnModifyIndexMenu(self, event):
680         if self.Editable:
681             selected = self.IndexList.GetSelection()
682             if selected != wx.NOT_FOUND:
683                 index = self.ListIndex[selected]
684                 if self.Manager.IsCurrentEntry(index) and index < 0x260:
685                     values, valuetype = self.Manager.GetCustomisedTypeValues(index)
686                     dialog = UserTypeDialog(self)
687                     dialog.SetTypeList(self.Manager.GetCustomisableTypes(), values[1])
688                     if valuetype == 0:
689                         dialog.SetValues(min = values[2], max = values[3])
690                     elif valuetype == 1:
691                         dialog.SetValues(length = values[2])
692                     if dialog.ShowModal() == wx.ID_OK:
693                         type, min, max, length = dialog.GetValues()
694                         self.Manager.SetCurrentUserType(index, type, min, max, length)
695                         self.ParentWindow.RefreshBufferState()
696                         self.RefreshIndexList()
697         event.Skip()
698         
699     def OnDeleteIndexMenu(self, event):
700         if self.Editable:
701             selected = self.IndexList.GetSelection()
702             if selected != wx.NOT_FOUND:
703                 index = self.ListIndex[selected]
704                 if self.Manager.IsCurrentEntry(index):
705                     self.Manager.ManageEntriesOfCurrent([],[index])
706                     self.ParentWindow.RefreshBufferState()
707                     self.RefreshIndexList()
708         event.Skip()
709
710     def OnAddSubindexMenu(self, event):
711         if self.Editable:
712             selected = self.IndexList.GetSelection()
713             if selected != wx.NOT_FOUND:
714                 index = self.ListIndex[selected]
715                 if self.Manager.IsCurrentEntry(index):
716                     dialog = wx.TextEntryDialog(self, "Number of subindexes to add:",
717                                  "Add subindexes", "1", wx.OK|wx.CANCEL)
718                     if dialog.ShowModal() == wx.ID_OK:
719                         try:
720                             number = int(dialog.GetValue())
721                             self.Manager.AddSubentriesToCurrent(index, number)
722                             self.ParentWindow.RefreshBufferState()
723                             self.RefreshIndexList()
724                         except:
725                             message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
726                             message.ShowModal()
727                             message.Destroy()
728                     dialog.Destroy()
729         event.Skip()
730
731     def OnDeleteSubindexMenu(self, event):
732         if self.Editable:
733             selected = self.IndexList.GetSelection()
734             if selected != wx.NOT_FOUND:
735                 index = self.ListIndex[selected]
736                 if self.Manager.IsCurrentEntry(index):
737                     dialog = wx.TextEntryDialog(self, "Number of subindexes to delete:",
738                                  "Delete subindexes", "1", wx.OK|wx.CANCEL)
739                     if dialog.ShowModal() == wx.ID_OK:
740                         try:
741                             number = int(dialog.GetValue())
742                             self.Manager.RemoveSubentriesFromCurrent(index, number)
743                             self.ParentWindow.RefreshBufferState()
744                             self.RefreshIndexList()
745                         except:
746                             message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
747                             message.ShowModal()
748                             message.Destroy()
749                     dialog.Destroy()
750         event.Skip()
751
752     def OnDefaultValueSubindexMenu(self, event):
753         if self.Editable:
754             selected = self.IndexList.GetSelection()
755             if selected != wx.NOT_FOUND:
756                 index = self.ListIndex[selected]
757                 if self.Manager.IsCurrentEntry(index):
758                     row = self.SubindexGrid.GetGridCursorRow()
759                     self.Manager.SetCurrentEntryToDefault(index, row)
760                     self.ParentWindow.RefreshBufferState()
761                     self.RefreshIndexList()
762         event.Skip()