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