2 # -*- coding: utf-8 -*-
4 #This file is part of CanFestival, a library implementing CanOpen Stack.
6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
8 #See COPYING file for copyrights details.
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.
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.
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
28 from commondialogs import *
30 from node import OD_Subindex, OD_MultipleSubindexes, OD_IdenticalSubindexes, OD_IdenticalIndexes
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"
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"}]
52 SizeConversion = {1 : "X", 8 : "B", 16 : "W", 24 : "D", 32 : "D", 40 : "L", 48 : "L", 56 : "L", 64 : "L"}
54 class SubindexTable(wx.grid.PyGridTableBase):
57 A custom wxGrid Table using user supplied data
59 def __init__(self, parent, data, editors, colnames):
60 # The base class must be initialized *first*
61 wx.grid.PyGridTableBase.__init__(self)
63 self.editors = editors
65 self.colnames = colnames
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()
80 def GetNumberCols(self):
81 return len(self.colnames)
83 def GetNumberRows(self):
86 def GetColLabelValue(self, col):
87 if col < len(self.colnames):
88 return self.colnames[col]
90 def GetRowLabelValues(self, row):
93 def GetValue(self, row, col):
94 if row < self.GetNumberRows():
95 return str(self.data[row].get(self.GetColLabelValue(col), ""))
97 def GetEditor(self, row, col):
98 if row < self.GetNumberRows():
99 return self.editors[row].get(self.GetColLabelValue(col), "")
101 def GetValueByName(self, row, colname):
102 return self.data[row].get(colname)
104 def SetValue(self, row, col, value):
105 if col < len(self.colnames):
106 self.data[row][self.GetColLabelValue(col)] = value
108 def ResetView(self, grid):
110 (wx.grid.Grid) -> Reset the grid view. Call this to
111 update the grid if rows and columns have been added or deleted
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),
119 msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
120 grid.ProcessTableMessage(msg)
122 msg = wx.grid.GridTableMessage(self,addmsg,new-current)
123 grid.ProcessTableMessage(msg)
124 self.UpdateValues(grid)
127 self._rows = self.GetNumberRows()
128 self._cols = self.GetNumberCols()
129 # update the column rendering scheme
130 self._updateColAttrs(grid)
132 # update the scrollbars and the displayed part of the grid
133 grid.AdjustScrollbars()
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)
143 def _updateColAttrs(self, grid):
145 wx.grid.Grid -> update the column attributes to add the
146 appropriate renderer given the column name.
148 Otherwise default to the default renderer.
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])
159 for row in range(self.GetNumberRows()):
160 editors = self.editors[row]
161 for col in range(self.GetNumberCols()):
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 == "float":
180 editor = wx.grid.GridCellTextEditor()
181 renderer = wx.grid.GridCellStringRenderer()
182 elif editortype == "bool":
183 editor = wx.grid.GridCellChoiceEditor()
184 editor.SetParameters(BoolList)
185 elif editortype == "access":
186 editor = wx.grid.GridCellChoiceEditor()
187 editor.SetParameters(AccessList)
188 elif editortype == "raccess":
189 editor = wx.grid.GridCellChoiceEditor()
190 editor.SetParameters(RAccessList)
191 elif editortype == "option":
192 editor = wx.grid.GridCellChoiceEditor()
193 editor.SetParameters(OptionList)
194 elif editortype == "type":
195 editor = wx.grid.GridCellChoiceEditor()
197 typelist = self.Parent.Manager.GetCurrentTypeList()
198 editor.SetParameters(typelist)
199 elif editortype == "map":
200 editor = wx.grid.GridCellChoiceEditor()
202 maplist = self.Parent.Manager.GetCurrentMapList()
203 editor.SetParameters(maplist)
204 elif editortype == "time":
205 editor = wx.grid.GridCellTextEditor()
206 renderer = wx.grid.GridCellStringRenderer()
207 elif editortype == "domain":
208 editor = wx.grid.GridCellTextEditor()
209 renderer = wx.grid.GridCellStringRenderer()
210 elif editortype == "dcf":
211 editor = wx.grid.GridCellTextEditor()
212 renderer = wx.grid.GridCellStringRenderer()
214 grid.SetReadOnly(row, col, True)
216 grid.SetCellEditor(row, col, editor)
217 grid.SetCellRenderer(row, col, renderer)
219 grid.SetCellBackgroundColour(row, col, wx.WHITE)
221 def SetData(self, data):
224 def SetEditors(self, editors):
225 self.editors = editors
227 def GetCurrentIndex(self):
228 return self.CurrentIndex
230 def SetCurrentIndex(self, index):
231 self.CurrentIndex = index
233 def AppendRow(self, row_content):
234 self.data.append(row_content)
240 [ID_EDITINGPANEL, ID_EDITINGPANELADDBUTTON, ID_EDITINGPANELINDEXCHOICE,
241 ID_EDITINGPANELINDEXLIST, ID_EDITINGPANELINDEXLISTPANEL, ID_EDITINGPANELPARTLIST,
242 ID_EDITINGPANELSECONDSPLITTER, ID_EDITINGPANELSUBINDEXGRID,
243 ID_EDITINGPANELSUBINDEXGRIDPANEL, ID_EDITINGPANELCALLBACKCHECK,
244 ] = [wx.NewId() for _init_ctrls in range(10)]
246 [ID_EDITINGPANELINDEXLISTMENUITEMS0, ID_EDITINGPANELINDEXLISTMENUITEMS1,
247 ID_EDITINGPANELINDEXLISTMENUITEMS2,
248 ] = [wx.NewId() for _init_coll_IndexListMenu_Items in range(3)]
250 [ID_EDITINGPANELMENU1ITEMS0, ID_EDITINGPANELMENU1ITEMS1,
251 ID_EDITINGPANELMENU1ITEMS3, ID_EDITINGPANELMENU1ITEMS4,
252 ] = [wx.NewId() for _init_coll_SubindexGridMenu_Items in range(4)]
254 class EditingPanel(wx.SplitterWindow):
255 def _init_coll_AddToListSizer_Items(self, parent):
256 parent.AddWindow(self.AddButton, 0, border=0, flag=0)
257 parent.AddWindow(self.IndexChoice, 0, border=0, flag=wx.GROW)
259 def _init_coll_SubindexGridSizer_Items(self, parent):
260 parent.AddWindow(self.CallbackCheck, 0, border=0, flag=0)
261 parent.AddWindow(self.SubindexGrid, 0, border=0, flag=wx.GROW)
263 def _init_coll_IndexListSizer_Items(self, parent):
264 parent.AddWindow(self.IndexList, 0, border=0, flag=wx.GROW)
265 parent.AddSizer(self.AddToListSizer, 0, border=0, flag=wx.GROW)
267 def _init_coll_AddToListSizer_Growables(self, parent):
268 parent.AddGrowableCol(1)
270 def _init_coll_SubindexGridSizer_Growables(self, parent):
271 parent.AddGrowableCol(0)
272 parent.AddGrowableRow(1)
274 def _init_coll_IndexListSizer_Growables(self, parent):
275 parent.AddGrowableCol(0)
276 parent.AddGrowableRow(0)
278 def _init_coll_SubindexGridMenu_Items(self, parent):
279 parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS0,
280 kind=wx.ITEM_NORMAL, text='Add subindexes')
281 parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS1,
282 kind=wx.ITEM_NORMAL, text='Delete subindexes')
283 parent.AppendSeparator()
284 parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS3,
285 kind=wx.ITEM_NORMAL, text='Default value')
286 if not self.Editable:
287 parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS4,
288 kind=wx.ITEM_NORMAL, text='Add to DCF')
289 self.Bind(wx.EVT_MENU, self.OnAddSubindexMenu,
290 id=ID_EDITINGPANELMENU1ITEMS0)
291 self.Bind(wx.EVT_MENU, self.OnDeleteSubindexMenu,
292 id=ID_EDITINGPANELMENU1ITEMS1)
293 self.Bind(wx.EVT_MENU, self.OnDefaultValueSubindexMenu,
294 id=ID_EDITINGPANELMENU1ITEMS3)
295 if not self.Editable:
296 self.Bind(wx.EVT_MENU, self.OnAddToDCFSubindexMenu,
297 id=ID_EDITINGPANELMENU1ITEMS4)
299 def _init_coll_IndexListMenu_Items(self, parent):
300 parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS0,
301 kind=wx.ITEM_NORMAL, text='Rename')
302 parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS2,
303 kind=wx.ITEM_NORMAL, text='Modify')
304 parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS1,
305 kind=wx.ITEM_NORMAL, text='Delete')
306 self.Bind(wx.EVT_MENU, self.OnRenameIndexMenu,
307 id=ID_EDITINGPANELINDEXLISTMENUITEMS0)
308 self.Bind(wx.EVT_MENU, self.OnDeleteIndexMenu,
309 id=ID_EDITINGPANELINDEXLISTMENUITEMS1)
310 self.Bind(wx.EVT_MENU, self.OnModifyIndexMenu,
311 id=ID_EDITINGPANELINDEXLISTMENUITEMS2)
313 def _init_utils(self):
314 self.IndexListMenu = wx.Menu(title='')
315 self.SubindexGridMenu = wx.Menu(title='')
317 self._init_coll_IndexListMenu_Items(self.IndexListMenu)
318 self._init_coll_SubindexGridMenu_Items(self.SubindexGridMenu)
320 def _init_sizers(self):
321 self.IndexListSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
322 self.SubindexGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
323 self.AddToListSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
325 self._init_coll_IndexListSizer_Growables(self.IndexListSizer)
326 self._init_coll_IndexListSizer_Items(self.IndexListSizer)
327 self._init_coll_SubindexGridSizer_Growables(self.SubindexGridSizer)
328 self._init_coll_SubindexGridSizer_Items(self.SubindexGridSizer)
329 self._init_coll_AddToListSizer_Growables(self.AddToListSizer)
330 self._init_coll_AddToListSizer_Items(self.AddToListSizer)
332 self.SubindexGridPanel.SetSizer(self.SubindexGridSizer)
333 self.IndexListPanel.SetSizer(self.IndexListSizer)
335 def _init_ctrls(self, prnt):
336 wx.SplitterWindow.__init__(self, id=ID_EDITINGPANEL,
337 name='MainSplitter', parent=prnt, point=wx.Point(0, 0),
338 size=wx.Size(-1, -1), style=wx.SP_3D)
340 self.SetNeedUpdating(True)
341 self.SetMinimumPaneSize(1)
343 self.PartList = wx.ListBox(choices=[], id=ID_EDITINGPANELPARTLIST,
344 name='PartList', parent=self, pos=wx.Point(0, 0),
345 size=wx.Size(-1, -1), style=0)
346 self.PartList.Bind(wx.EVT_LISTBOX, self.OnPartListBoxClick,
347 id=ID_EDITINGPANELPARTLIST)
349 self.SecondSplitter = wx.SplitterWindow(id=ID_EDITINGPANELSECONDSPLITTER,
350 name='SecondSplitter', parent=self, point=wx.Point(0, 0),
351 size=wx.Size(-1, -1), style=wx.SP_3D)
352 self.SecondSplitter.SetMinimumPaneSize(1)
353 self.SplitHorizontally(self.PartList, self.SecondSplitter,
356 self.SubindexGridPanel = wx.Panel(id=ID_EDITINGPANELSUBINDEXGRIDPANEL,
357 name='SubindexGridPanel', parent=self.SecondSplitter,
358 pos=wx.Point(0, 0), size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
360 self.IndexListPanel = wx.Panel(id=ID_EDITINGPANELINDEXLISTPANEL,
361 name='IndexListPanel', parent=self.SecondSplitter,
362 pos=wx.Point(0, 0), size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
363 self.SecondSplitter.SplitVertically(self.IndexListPanel,
364 self.SubindexGridPanel, 280)
366 self.SubindexGrid = wx.grid.Grid(id=ID_EDITINGPANELSUBINDEXGRID,
367 name='SubindexGrid', parent=self.SubindexGridPanel, pos=wx.Point(0,
368 0), size=wx.Size(-1, -1), style=0)
369 self.SubindexGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
371 self.SubindexGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
373 self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
374 self.OnSubindexGridCellChange)
375 self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK,
376 self.OnSubindexGridRightClick)
377 self.SubindexGrid.Bind(wx.grid.EVT_GRID_SELECT_CELL,
378 self.OnSubindexGridSelectCell)
379 self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK,
380 self.OnSubindexGridCellLeftClick)
381 self.SubindexGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN,
382 self.OnSubindexGridEditorShown)
384 self.CallbackCheck = wx.CheckBox(id=ID_EDITINGPANELCALLBACKCHECK,
385 label='Have Callbacks', name='CallbackCheck',
386 parent=self.SubindexGridPanel, pos=wx.Point(0, 0), size=wx.Size(152,
388 self.CallbackCheck.Bind(wx.EVT_CHECKBOX, self.OnCallbackCheck,
389 id=ID_EDITINGPANELCALLBACKCHECK)
391 self.IndexList = wx.ListBox(choices=[], id=ID_EDITINGPANELINDEXLIST,
392 name='IndexList', parent=self.IndexListPanel, pos=wx.Point(0, 0),
393 size=wx.Size(-1, -1), style=0)
394 self.IndexList.Bind(wx.EVT_LISTBOX, self.OnIndexListClick,
395 id=ID_EDITINGPANELINDEXLIST)
396 self.IndexList.Bind(wx.EVT_RIGHT_UP, self.OnIndexListRightUp)
398 self.AddButton = wx.Button(id=ID_EDITINGPANELADDBUTTON, label='Add',
399 name='AddButton', parent=self.IndexListPanel, pos=wx.Point(0, 0),
400 size=wx.Size(50, 30), style=0)
401 self.AddButton.Bind(wx.EVT_BUTTON, self.OnAddButtonClick,
402 id=ID_EDITINGPANELADDBUTTON)
404 self.IndexChoice = wx.Choice(choices=[], id=ID_EDITINGPANELINDEXCHOICE,
405 name='IndexChoice', parent=self.IndexListPanel, pos=wx.Point(50,
406 0), size=wx.Size(-1, 30), style=0)
410 def __init__(self, parent, window, manager, editable = True):
411 self.Editable = editable
412 self._init_ctrls(parent)
413 self.ParentWindow = window
414 self.Manager = manager
416 self.ChoiceIndex = []
417 self.FirstCall = False
420 for values in DictionaryOrganisation:
421 text = " 0x%04X-0x%04X %s"%(values["minIndex"], values["maxIndex"], values["name"])
422 self.PartList.Append(text)
423 self.Table = SubindexTable(self, [], [], ["subindex", "name", "type", "value", "access", "save", "comment"])
424 self.SubindexGrid.SetTable(self.Table)
425 self.SubindexGrid.SetRowLabelSize(0)
426 self.CallbackCheck.Disable()
427 self.Table.ResetView(self.SubindexGrid)
429 if not self.Editable:
430 self.AddButton.Disable()
431 self.IndexChoice.Disable()
432 self.CallbackCheck.Disable()
438 def SetIndex(self, index):
441 def GetSelection(self):
442 selected = self.IndexList.GetSelection()
443 if selected != wx.NOT_FOUND:
444 index = self.ListIndex[selected]
445 subIndex = self.SubindexGrid.GetGridCursorRow()
446 return index, subIndex
449 def OnSubindexGridCellLeftClick(self, event):
450 if not self.ParentWindow.ModeSolo:
452 if self.Editable and col == 0:
453 selected = self.IndexList.GetSelection()
454 if selected != wx.NOT_FOUND:
455 index = self.ListIndex[selected]
456 subindex = event.GetRow()
457 entry_infos = self.Manager.GetEntryInfos(index)
458 if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0:
459 subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
460 typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
462 bus_id = '.'.join(map(str, self.ParentWindow.GetBusId()))
463 size = typeinfos["size"]
464 data = wx.TextDataObject(str(("%s%s.%d.%d"%(SizeConversion[size], bus_id, index, subindex), "location")))
465 dragSource = wx.DropSource(self.SubindexGrid)
466 dragSource.SetData(data)
467 dragSource.DoDragDrop()
469 selected = self.IndexList.GetSelection()
470 if selected != wx.NOT_FOUND:
471 index = self.ListIndex[selected]
472 subindex = event.GetRow()
473 entry_infos = self.Manager.GetEntryInfos(index)
474 if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0:
475 subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
476 typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
477 if subentry_infos["pdo"] and typeinfos:
478 bus_id = '.'.join(map(str, self.ParentWindow.GetBusId()))
479 node_id = self.ParentWindow.GetCurrentNodeId()
480 size = typeinfos["size"]
481 data = wx.TextDataObject(str(("%s%s.%d.%d.%d"%(SizeConversion[size], bus_id, node_id, index, subindex), "location")))
482 dragSource = wx.DropSource(self.SubindexGrid)
483 dragSource.SetData(data)
484 dragSource.DoDragDrop()
487 def OnAddButtonClick(self, event):
489 self.SubindexGrid.SetGridCursor(0, 0)
490 selected = self.IndexChoice.GetStringSelection()
492 if selected == "User Type":
493 self.ParentWindow.AddUserType()
494 elif selected == "SDO Server":
495 self.Manager.AddSDOServerToCurrent()
496 elif selected == "SDO Client":
497 self.Manager.AddSDOClientToCurrent()
498 elif selected == "PDO Receive":
499 self.Manager.AddPDOReceiveToCurrent()
500 elif selected == "PDO Transmit":
501 self.Manager.AddPDOTransmitToCurrent()
502 elif selected == "Map Variable":
503 self.ParentWindow.AddMapVariable()
504 elif selected in [menu for menu, indexes in self.Manager.GetCurrentSpecificMenu()]:
505 self.Manager.AddSpecificEntryToCurrent(selected)
507 index = self.ChoiceIndex[self.IndexChoice.GetSelection()]
508 self.Manager.ManageEntriesOfCurrent([index], [])
509 self.ParentWindow.RefreshBufferState()
510 self.RefreshIndexList()
513 def OnPartListBoxClick(self, event):
514 if not self.ParentWindow.IsClosing():
515 self.SubindexGrid.SetGridCursor(0, 0)
516 self.RefreshIndexList()
519 def OnIndexListClick(self, event):
520 if not self.ParentWindow.IsClosing():
521 self.SubindexGrid.SetGridCursor(0, 0)
525 def OnSubindexGridSelectCell(self, event):
526 if not self.ParentWindow.IsClosing():
527 wx.CallAfter(self.ParentWindow.RefreshStatusBar)
530 #-------------------------------------------------------------------------------
532 #-------------------------------------------------------------------------------
534 def RefreshIndexList(self):
535 selected = self.IndexList.GetSelection()
536 choice = self.IndexChoice.GetStringSelection()
537 choiceindex = self.IndexChoice.GetSelection()
538 if selected != wx.NOT_FOUND:
539 selectedindex = self.ListIndex[selected]
540 self.IndexList.Clear()
541 self.IndexChoice.Clear()
542 i = self.PartList.GetSelection()
543 if i < len(DictionaryOrganisation):
544 values = DictionaryOrganisation[i]
546 for name, index in self.Manager.GetCurrentValidIndexes(values["minIndex"], values["maxIndex"]):
547 self.IndexList.Append("0x%04X %s"%(index, name))
548 self.ListIndex.append(index)
550 self.ChoiceIndex = []
552 self.IndexChoice.Append("User Type")
553 self.IndexChoice.SetStringSelection("User Type")
555 self.IndexChoice.Append("SDO Server")
556 self.IndexChoice.Append("SDO Client")
557 if choiceindex != wx.NOT_FOUND and choice == self.IndexChoice.GetString(choiceindex):
558 self.IndexChoice.SetStringSelection(choice)
560 self.IndexChoice.Append("PDO Receive")
561 self.IndexChoice.SetStringSelection("PDO Receive")
563 self.IndexChoice.Append("PDO Transmit")
564 self.IndexChoice.SetStringSelection("PDO Transmit")
566 self.IndexChoice.Append("Map Variable")
567 self.IndexChoice.SetStringSelection("Map Variable")
569 for name, index in self.Manager.GetCurrentValidChoices(values["minIndex"], values["maxIndex"]):
571 self.IndexChoice.Append("0x%04X %s"%(index, name))
573 self.IndexChoice.Append(name)
574 self.ChoiceIndex.append(index)
575 if choiceindex != wx.NOT_FOUND and choiceindex < self.IndexChoice.GetCount() and choice == self.IndexChoice.GetString(choiceindex):
576 self.IndexChoice.SetStringSelection(choice)
578 self.IndexChoice.Enable(self.IndexChoice.GetCount() != 0)
579 self.AddButton.Enable(self.IndexChoice.GetCount() != 0)
580 if selected == wx.NOT_FOUND or selected >= len(self.ListIndex) or selectedindex != self.ListIndex[selected]:
582 self.CallbackCheck.SetValue(False)
583 self.CallbackCheck.Disable()
584 self.Table.ResetView(self.SubindexGrid)
585 self.ParentWindow.RefreshStatusBar()
587 self.IndexList.SetSelection(selected)
590 def RefreshTable(self):
591 selected = self.IndexList.GetSelection()
592 if selected != wx.NOT_FOUND:
593 index = self.ListIndex[selected]
594 if index > 0x260 and self.Editable:
595 self.CallbackCheck.Enable()
596 self.CallbackCheck.SetValue(self.Manager.HasCurrentEntryCallbacks(index))
597 result = self.Manager.GetCurrentEntryValues(index)
599 self.Table.SetCurrentIndex(index)
600 data, editors = result
601 self.Table.SetData(data)
602 self.Table.SetEditors(editors)
603 self.Table.ResetView(self.SubindexGrid)
604 self.ParentWindow.RefreshStatusBar()
606 #-------------------------------------------------------------------------------
607 # Editing Table value function
608 #-------------------------------------------------------------------------------
610 def OnSubindexGridEditorShown(self, event):
611 row, col = event.GetRow(), event.GetCol()
612 if self.Table.GetEditor(row, col) == "dcf":
613 wx.CallAfter(self.ShowDCFEntryDialog, row, col)
618 def ShowDCFEntryDialog(self, row, col):
620 selected = self.IndexList.GetSelection()
621 if selected != wx.NOT_FOUND:
622 index = self.ListIndex[selected]
623 if self.Manager.IsCurrentEntry(index):
624 dialog = DCFEntryValuesDialog(self)
625 dialog.SetValues(self.Table.GetValue(row, col).decode("hex_codec"))
626 if dialog.ShowModal() == wx.ID_OK:
627 value = dialog.GetValues()
628 self.Manager.SetCurrentEntry(index, row, value, "value", "dcf")
629 self.ParentWindow.RefreshBufferState()
630 wx.CallAfter(self.RefreshTable)
632 def OnSubindexGridCellChange(self, event):
634 index = self.Table.GetCurrentIndex()
635 subIndex = event.GetRow()
637 name = self.Table.GetColLabelValue(col)
638 value = self.Table.GetValue(subIndex, col)
639 editor = self.Table.GetEditor(subIndex, col)
640 self.Manager.SetCurrentEntry(index, subIndex, value, name, editor)
641 self.ParentWindow.RefreshBufferState()
642 wx.CallAfter(self.RefreshTable)
645 def OnCallbackCheck(self, event):
647 index = self.Table.GetCurrentIndex()
648 self.Manager.SetCurrentEntryCallbacks(index, self.CallbackCheck.GetValue())
649 self.ParentWindow.RefreshBufferState()
650 wx.CallAfter(self.RefreshTable)
653 #-------------------------------------------------------------------------------
654 # Contextual Menu functions
655 #-------------------------------------------------------------------------------
657 def OnIndexListRightUp(self, event):
659 if not self.FirstCall:
660 self.FirstCall = True
661 selected = self.IndexList.GetSelection()
662 if selected != wx.NOT_FOUND:
663 index = self.ListIndex[selected]
665 self.IndexListMenu.FindItemByPosition(0).Enable(False)
666 self.IndexListMenu.FindItemByPosition(1).Enable(True)
667 self.PopupMenu(self.IndexListMenu)
668 elif 0x1000 <= index <= 0x1FFF:
669 self.IndexListMenu.FindItemByPosition(0).Enable(False)
670 self.IndexListMenu.FindItemByPosition(1).Enable(False)
671 self.PopupMenu(self.IndexListMenu)
672 elif 0x2000 <= index <= 0x5FFF:
673 self.IndexListMenu.FindItemByPosition(0).Enable(True)
674 self.IndexListMenu.FindItemByPosition(1).Enable(False)
675 self.PopupMenu(self.IndexListMenu)
676 elif index >= 0x6000:
677 self.IndexListMenu.FindItemByPosition(0).Enable(False)
678 self.IndexListMenu.FindItemByPosition(1).Enable(False)
679 self.PopupMenu(self.IndexListMenu)
681 self.FirstCall = False
684 def OnSubindexGridRightClick(self, event):
685 self.SubindexGrid.SetGridCursor(event.GetRow(), event.GetCol())
687 selected = self.IndexList.GetSelection()
688 if selected != wx.NOT_FOUND:
689 index = self.ListIndex[selected]
690 if self.Manager.IsCurrentEntry(index):
692 infos = self.Manager.GetEntryInfos(index)
693 if 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_MultipleSubindexes or infos["struct"] & OD_IdenticalSubindexes:
695 self.SubindexGridMenu.FindItemByPosition(0).Enable(True)
696 self.SubindexGridMenu.FindItemByPosition(1).Enable(True)
698 self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
699 self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
700 if self.Table.GetColLabelValue(event.GetCol()) == "value":
702 self.SubindexGridMenu.FindItemByPosition(3).Enable(True)
704 self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
706 self.PopupMenu(self.SubindexGridMenu)
707 elif self.Table.GetColLabelValue(event.GetCol()) == "value":
708 selected = self.IndexList.GetSelection()
709 if selected != wx.NOT_FOUND:
710 index = self.ListIndex[selected]
711 if self.Manager.IsCurrentEntry(index):
712 infos = self.Manager.GetEntryInfos(index)
713 if not infos["struct"] & OD_MultipleSubindexes or event.GetRow() > 0:
714 self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
715 self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
716 self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
717 self.SubindexGridMenu.FindItemByPosition(4).Enable(True)
718 self.PopupMenu(self.SubindexGridMenu)
721 def OnAddToDCFSubindexMenu(self, event):
722 if not self.Editable:
723 selected = self.IndexList.GetSelection()
724 if selected != wx.NOT_FOUND:
725 index = self.ListIndex[selected]
726 subindex = self.SubindexGrid.GetGridCursorRow()
727 entry_infos = self.Manager.GetEntryInfos(index)
728 if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0:
729 subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
730 typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
732 node_id = self.ParentWindow.GetCurrentNodeId()
733 value = self.Table.GetValueByName(subindex, "value")
736 elif value == "False":
738 elif value.isdigit():
740 elif value.startswith("0x"):
741 value = int(value, 16)
743 value = int(value.encode("hex_codec"), 16)
744 self.Manager.AddToMasterDCF(node_id, index, subindex, max(1, typeinfos["size"] / 8), value)
745 self.ParentWindow.OpenMasterDCFDialog(node_id)
747 def OpenDCFDialog(self, node_id):
748 self.PartList.SetSelection(7)
749 self.RefreshIndexList()
750 self.IndexList.SetSelection(self.ListIndex.index(0x1F22))
752 self.SubindexGrid.SetGridCursor(node_id, 3)
753 self.ShowDCFEntryDialog(node_id, 3)
755 def OnRenameIndexMenu(self, event):
757 selected = self.IndexList.GetSelection()
758 if selected != wx.NOT_FOUND:
759 index = self.ListIndex[selected]
760 if self.Manager.IsCurrentEntry(index):
761 infos = self.Manager.GetEntryInfos(index)
762 dialog = wx.TextEntryDialog(self, "Give a new name for index 0x%04X"%index,
763 "Rename an index", infos["name"], wx.OK|wx.CANCEL)
764 if dialog.ShowModal() == wx.ID_OK:
765 self.Manager.SetCurrentEntryName(index, dialog.GetValue())
766 self.ParentWindow.RefreshBufferState()
767 self.RefreshIndexList()
771 def OnModifyIndexMenu(self, event):
773 selected = self.IndexList.GetSelection()
774 if selected != wx.NOT_FOUND:
775 index = self.ListIndex[selected]
776 if self.Manager.IsCurrentEntry(index) and index < 0x260:
777 values, valuetype = self.Manager.GetCustomisedTypeValues(index)
778 dialog = UserTypeDialog(self)
779 dialog.SetTypeList(self.Manager.GetCustomisableTypes(), values[1])
781 dialog.SetValues(min = values[2], max = values[3])
783 dialog.SetValues(length = values[2])
784 if dialog.ShowModal() == wx.ID_OK:
785 type, min, max, length = dialog.GetValues()
786 self.Manager.SetCurrentUserType(index, type, min, max, length)
787 self.ParentWindow.RefreshBufferState()
788 self.RefreshIndexList()
791 def OnDeleteIndexMenu(self, event):
793 selected = self.IndexList.GetSelection()
794 if selected != wx.NOT_FOUND:
795 index = self.ListIndex[selected]
796 if self.Manager.IsCurrentEntry(index):
797 self.Manager.ManageEntriesOfCurrent([],[index])
798 self.ParentWindow.RefreshBufferState()
799 self.RefreshIndexList()
802 def OnAddSubindexMenu(self, event):
804 selected = self.IndexList.GetSelection()
805 if selected != wx.NOT_FOUND:
806 index = self.ListIndex[selected]
807 if self.Manager.IsCurrentEntry(index):
808 dialog = wx.TextEntryDialog(self, "Number of subindexes to add:",
809 "Add subindexes", "1", wx.OK|wx.CANCEL)
810 if dialog.ShowModal() == wx.ID_OK:
812 number = int(dialog.GetValue())
813 self.Manager.AddSubentriesToCurrent(index, number)
814 self.ParentWindow.RefreshBufferState()
815 self.RefreshIndexList()
817 message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
823 def OnDeleteSubindexMenu(self, event):
825 selected = self.IndexList.GetSelection()
826 if selected != wx.NOT_FOUND:
827 index = self.ListIndex[selected]
828 if self.Manager.IsCurrentEntry(index):
829 dialog = wx.TextEntryDialog(self, "Number of subindexes to delete:",
830 "Delete subindexes", "1", wx.OK|wx.CANCEL)
831 if dialog.ShowModal() == wx.ID_OK:
833 number = int(dialog.GetValue())
834 self.Manager.RemoveSubentriesFromCurrent(index, number)
835 self.ParentWindow.RefreshBufferState()
836 self.RefreshIndexList()
838 message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
844 def OnDefaultValueSubindexMenu(self, event):
846 selected = self.IndexList.GetSelection()
847 if selected != wx.NOT_FOUND:
848 index = self.ListIndex[selected]
849 if self.Manager.IsCurrentEntry(index):
850 row = self.SubindexGrid.GetGridCursorRow()
851 self.Manager.SetCurrentEntryToDefault(index, row)
852 self.ParentWindow.RefreshBufferState()
853 self.RefreshIndexList()