|
1 #!/usr/bin/env python |
|
2 # -*- coding: utf-8 -*- |
|
3 |
|
4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor |
|
5 #based on the plcopen standard. |
|
6 # |
|
7 #Copyright (C): Edouard TISSERANT and Laurent BESSARD |
|
8 # |
|
9 #See COPYING file for copyrights details. |
|
10 # |
|
11 #This library is free software; you can redistribute it and/or |
|
12 #modify it under the terms of the GNU Lesser General Public |
|
13 #License as published by the Free Software Foundation; either |
|
14 #version 2.1 of the License, or (at your option) any later version. |
|
15 # |
|
16 #This library is distributed in the hope that it will be useful, |
|
17 #but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
19 #Lesser General Public License for more details. |
|
20 # |
|
21 #You should have received a copy of the GNU Lesser General Public |
|
22 #License along with this library; if not, write to the Free Software |
|
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
24 |
|
25 from wxPython.wx import * |
|
26 import wx |
|
27 |
|
28 from plcopen.structures import * |
|
29 from graphics.GraphicCommons import * |
|
30 from graphics.FBD_Objects import * |
|
31 from Viewer import * |
|
32 |
|
33 class FBD_Viewer(Viewer): |
|
34 |
|
35 def __init__(self, parent, window, controler): |
|
36 Viewer.__init__(self, parent, window, controler) |
|
37 |
|
38 #------------------------------------------------------------------------------- |
|
39 # Mouse event functions |
|
40 #------------------------------------------------------------------------------- |
|
41 |
|
42 def OnViewerLeftDown(self, event): |
|
43 if self.Mode == MODE_SELECTION: |
|
44 pos = event.GetPosition() |
|
45 if event.ControlDown() and self.SelectedElement: |
|
46 element = self.FindElement(pos, True) |
|
47 if element: |
|
48 if isinstance(self.SelectedElement, Graphic_Group): |
|
49 self.SelectedElement.SetSelected(False) |
|
50 self.SelectedElement.SelectElement(element) |
|
51 elif self.SelectedElement: |
|
52 group = Graphic_Group(self) |
|
53 group.SelectElement(self.SelectedElement) |
|
54 group.SelectElement(element) |
|
55 self.SelectedElement = group |
|
56 elements = self.SelectedElement.GetElements() |
|
57 if len(elements) == 0: |
|
58 self.SelectedElement = element |
|
59 elif len(elements) == 1: |
|
60 self.SelectedElement = elements[0] |
|
61 self.SelectedElement.SetSelected(True) |
|
62 else: |
|
63 element = self.FindElement(pos) |
|
64 if self.SelectedElement and self.SelectedElement != element: |
|
65 self.SelectedElement.SetSelected(False) |
|
66 self.SelectedElement = None |
|
67 self.Refresh() |
|
68 if element: |
|
69 self.SelectedElement = element |
|
70 self.SelectedElement.OnLeftDown(event, self.Scaling) |
|
71 self.Refresh() |
|
72 else: |
|
73 self.rubberBand.Reset() |
|
74 self.rubberBand.OnLeftDown(event, self.Scaling) |
|
75 elif self.Mode in [MODE_BLOCK,MODE_VARIABLE,MODE_CONNECTION,MODE_COMMENT]: |
|
76 self.rubberBand.Reset() |
|
77 self.rubberBand.OnLeftDown(event, self.Scaling) |
|
78 elif self.Mode == MODE_WIRE: |
|
79 pos = GetScaledEventPosition(event, self.Scaling) |
|
80 wire = Wire(self, [wxPoint(pos.x, pos.y), EAST], [wxPoint(pos.x, pos.y), WEST]) |
|
81 wire.oldPos = pos |
|
82 wire.Handle = (HANDLE_POINT, 0) |
|
83 wire.ProcessDragging(0, 0) |
|
84 wire.Handle = (HANDLE_POINT, 1) |
|
85 self.Wires.append(wire) |
|
86 self.Elements.append(wire) |
|
87 if self.SelectedElement: |
|
88 self.SelectedElement.SetSelected(False) |
|
89 self.SelectedElement = wire |
|
90 self.Refresh() |
|
91 event.Skip() |
|
92 |
|
93 def OnViewerLeftUp(self, event): |
|
94 if self.rubberBand.IsShown(): |
|
95 if self.Mode == MODE_SELECTION: |
|
96 elements = self.SearchElements(self.rubberBand.GetCurrentExtent()) |
|
97 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
98 if len(elements) > 0: |
|
99 self.SelectedElement = Graphic_Group(self) |
|
100 self.SelectedElement.SetElements(elements) |
|
101 self.SelectedElement.SetSelected(True) |
|
102 self.Refresh() |
|
103 elif self.Mode == MODE_BLOCK: |
|
104 bbox = self.rubberBand.GetCurrentExtent() |
|
105 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
106 wxCallAfter(self.AddNewBlock, bbox) |
|
107 elif self.Mode == MODE_VARIABLE: |
|
108 bbox = self.rubberBand.GetCurrentExtent() |
|
109 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
110 wxCallAfter(self.AddNewVariable, bbox) |
|
111 elif self.Mode == MODE_CONNECTION: |
|
112 bbox = self.rubberBand.GetCurrentExtent() |
|
113 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
114 wxCallAfter(self.AddNewConnection, bbox) |
|
115 elif self.Mode == MODE_COMMENT: |
|
116 bbox = self.rubberBand.GetCurrentExtent() |
|
117 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
118 wxCallAfter(self.AddNewComment, bbox) |
|
119 elif self.Mode == MODE_SELECTION and self.SelectedElement: |
|
120 self.SelectedElement.OnLeftUp(event, self.Scaling) |
|
121 wxCallAfter(self.SetCursor, wxNullCursor) |
|
122 self.ReleaseMouse() |
|
123 self.Refresh() |
|
124 elif self.Mode == MODE_WIRE and self.SelectedElement: |
|
125 self.SelectedElement.ResetPoints() |
|
126 self.SelectedElement.OnMotion(event, self.Scaling) |
|
127 self.SelectedElement.GeneratePoints() |
|
128 self.SelectedElement.RefreshModel() |
|
129 self.SelectedElement.SetSelected(True) |
|
130 self.Refresh() |
|
131 event.Skip() |
|
132 |
|
133 def OnViewerRightUp(self, event): |
|
134 pos = event.GetPosition() |
|
135 element = self.FindElement(pos) |
|
136 if element: |
|
137 if self.SelectedElement and self.SelectedElement != element: |
|
138 self.SelectedElement.SetSelected(False) |
|
139 self.SelectedElement = element |
|
140 self.SelectedElement.SetSelected(True) |
|
141 self.SelectedElement.OnRightUp(event, self.Scaling) |
|
142 wxCallAfter(self.SetCursor, wxNullCursor) |
|
143 self.ReleaseMouse() |
|
144 self.Refresh() |
|
145 event.Skip() |
|
146 |
|
147 def OnViewerLeftDClick(self, event): |
|
148 if self.Mode == MODE_SELECTION and self.SelectedElement: |
|
149 self.SelectedElement.OnLeftDClick(event, self.Scaling) |
|
150 self.Refresh() |
|
151 event.Skip() |
|
152 |
|
153 def OnViewerMotion(self, event): |
|
154 if self.rubberBand.IsShown(): |
|
155 self.rubberBand.OnMotion(event, self.Scaling) |
|
156 elif self.Mode == MODE_SELECTION and self.SelectedElement: |
|
157 self.SelectedElement.OnMotion(event, self.Scaling) |
|
158 self.Refresh() |
|
159 elif self.Mode == MODE_WIRE and self.SelectedElement: |
|
160 self.SelectedElement.ResetPoints() |
|
161 self.SelectedElement.OnMotion(event, self.Scaling) |
|
162 self.SelectedElement.GeneratePoints() |
|
163 self.Refresh() |
|
164 event.Skip() |
|
165 |
|
166 #------------------------------------------------------------------------------- |
|
167 # Keyboard event functions |
|
168 #------------------------------------------------------------------------------- |
|
169 |
|
170 def OnChar(self, event): |
|
171 keycode = event.GetKeyCode() |
|
172 if self.Scaling: |
|
173 scaling = self.Scaling |
|
174 else: |
|
175 scaling = (8, 8) |
|
176 if keycode == WXK_DELETE and self.SelectedElement: |
|
177 self.SelectedElement.Clean() |
|
178 self.SelectedElement.Delete() |
|
179 self.SelectedElement = None |
|
180 elif keycode == WXK_LEFT and self.SelectedElement: |
|
181 self.SelectedElement.Move(-scaling[0], 0) |
|
182 elif keycode == WXK_RIGHT and self.SelectedElement: |
|
183 self.SelectedElement.Move(scaling[0], 0) |
|
184 elif keycode == WXK_UP and self.SelectedElement: |
|
185 self.SelectedElement.Move(0, -scaling[1]) |
|
186 elif keycode == WXK_DOWN and self.SelectedElement: |
|
187 self.SelectedElement.Move(0, scaling[1]) |
|
188 self.Refresh() |
|
189 event.Skip() |
|
190 |
|
191 #------------------------------------------------------------------------------- |
|
192 # Adding element functions |
|
193 #------------------------------------------------------------------------------- |
|
194 |
|
195 def AddNewBlock(self, bbox): |
|
196 dialog = BlockPropertiesDialog(self.Parent) |
|
197 dialog.SetBlockList(self.Controler.GetBlockTypes()) |
|
198 dialog.SetMinBlockSize((bbox.width, bbox.height)) |
|
199 if dialog.ShowModal() == wxID_OK: |
|
200 id = self.GetNewId() |
|
201 values = dialog.GetValues() |
|
202 if "name" in values: |
|
203 block = FBD_Block(self, values["type"], values["name"], id, values["extension"]) |
|
204 else: |
|
205 block = FBD_Block(self, values["type"], "", id, values["extension"]) |
|
206 block.SetPosition(bbox.x, bbox.y) |
|
207 block.SetSize(values["width"], values["height"]) |
|
208 self.Blocks.append(block) |
|
209 self.Elements.append(block) |
|
210 self.Controler.AddCurrentElementEditingBlock(id) |
|
211 self.RefreshBlockModel(block) |
|
212 self.Parent.RefreshProjectTree() |
|
213 self.Refresh() |
|
214 dialog.Destroy() |
|
215 |
|
216 def AddNewVariable(self, bbox): |
|
217 dialog = VariablePropertiesDialog(self.Parent) |
|
218 dialog.SetMinVariableSize((bbox.width, bbox.height)) |
|
219 varlist = [] |
|
220 vars = self.Controler.GetCurrentElementEditingInterfaceVars() |
|
221 if vars: |
|
222 for var in vars: |
|
223 varlist.append((var["Name"], var["Class"], var["Type"])) |
|
224 returntype = self.Controler.GetCurrentElementEditingInterfaceReturnType() |
|
225 if returntype: |
|
226 varlist.append((self.Controler.GetCurrentElementEditingName(), "Output", returntype)) |
|
227 dialog.SetVariables(varlist) |
|
228 if dialog.ShowModal() == wxID_OK: |
|
229 id = self.GetNewId() |
|
230 values = dialog.GetValues() |
|
231 variable = FBD_Variable(self, values["type"], values["name"], values["value_type"], id) |
|
232 variable.SetPosition(bbox.x, bbox.y) |
|
233 variable.SetSize(values["width"], values["height"]) |
|
234 self.Blocks.append(variable) |
|
235 self.Elements.append(variable) |
|
236 self.Controler.AddCurrentElementEditingVariable(id, values["type"]) |
|
237 self.RefreshVariableModel(variable) |
|
238 self.Parent.RefreshProjectTree() |
|
239 self.Refresh() |
|
240 dialog.Destroy() |
|
241 |
|
242 def AddNewConnection(self, bbox): |
|
243 dialog = ConnectionPropertiesDialog(self.Parent) |
|
244 dialog.SetMinConnectionSize((bbox.width, bbox.height)) |
|
245 if dialog.ShowModal() == wxID_OK: |
|
246 id = self.GetNewId() |
|
247 values = dialog.GetValues() |
|
248 connection = FBD_Connection(self, values["type"], values["name"], id) |
|
249 connection.SetPosition(bbox.x, bbox.y) |
|
250 connection.SetSize(values["width"], values["height"]) |
|
251 self.Blocks.append(connection) |
|
252 self.Elements.append(connection) |
|
253 self.Controler.AddCurrentElementEditingConnection(id, values["type"]) |
|
254 self.RefreshConnectionModel(connection) |
|
255 self.Parent.RefreshProjectTree() |
|
256 self.Refresh() |
|
257 dialog.Destroy() |
|
258 |
|
259 def AddNewComment(self, bbox): |
|
260 dialog = wxTextEntryDialog(self.Parent, "Add a new comment", "Please enter comment text", "", wxOK|wxCANCEL|wxTE_MULTILINE) |
|
261 if dialog.ShowModal() == wxID_OK: |
|
262 value = dialog.GetValue() |
|
263 id = self.GetNewId() |
|
264 comment = Comment(self, value, id) |
|
265 comment.SetPosition(bbox.x, bbox.y) |
|
266 min_width, min_height = comment.GetMinSize() |
|
267 comment.SetSize(max(min_width,bbox.width),max(min_height,bbox.height)) |
|
268 self.Elements.append(comment) |
|
269 self.Controler.AddCurrentElementEditingComment(id) |
|
270 self.RefreshCommentModel(comment) |
|
271 self.Refresh() |
|
272 dialog.Destroy() |
|
273 |
|
274 #------------------------------------------------------------------------------- |
|
275 # Delete element functions |
|
276 #------------------------------------------------------------------------------- |
|
277 |
|
278 def DeleteBlock(self, block): |
|
279 wires = [] |
|
280 for output in block.GetConnectors()["outputs"]: |
|
281 wires.extend([wire[0] for wire in output.GetWires()]) |
|
282 block.Clean() |
|
283 self.Blocks.remove(block) |
|
284 self.Elements.remove(block) |
|
285 self.Controler.RemoveCurrentElementEditingInstance(block.GetId()) |
|
286 for wire in wires: |
|
287 wire.RefreshModel() |
|
288 self.Parent.RefreshProjectTree() |
|
289 |
|
290 def DeleteVariable(self, variable): |
|
291 wires = [] |
|
292 if self.SelectedElement.GetType() == INPUT: |
|
293 connector = variable.GetConnector() |
|
294 wires.extend([wire[0] for wire in connector.GetWires()]) |
|
295 variable.Clean() |
|
296 self.Blocks.remove(self.SelectedElement) |
|
297 self.Elements.remove(self.SelectedElement) |
|
298 self.Controler.RemoveCurrentElementEditingInstance(variable.GetId()) |
|
299 for wire in wires: |
|
300 wire.RefreshModel() |
|
301 self.Parent.RefreshProjectTree() |
|
302 |
|
303 def DeleteConnection(self, connection): |
|
304 wires = [] |
|
305 if self.SelectedElement.GetType() == CONTINUATION: |
|
306 connector = connection.GetConnector() |
|
307 wires.extend([wire[0] for wire in connector.GetWires()]) |
|
308 connection.Clean() |
|
309 self.Blocks.remove(self.SelectedElement) |
|
310 self.Elements.remove(self.SelectedElement) |
|
311 self.Controler.RemoveCurrentElementEditingInstance(connection.GetId()) |
|
312 for wire in wires: |
|
313 wire.RefreshModel() |
|
314 self.Parent.RefreshProjectTree() |
|
315 |
|
316 def DeleteComment(self, comment): |
|
317 self.Elements.remove(self.SelectedElement) |
|
318 self.Controler.RemoveCurrentElementEditingInstance(comment.GetId()) |
|
319 |
|
320 def DeleteWire(self, wire): |
|
321 connected = wire.GetConnected() |
|
322 self.SelectedElement.Clean() |
|
323 self.Wires.remove(self.SelectedElement) |
|
324 self.Elements.remove(self.SelectedElement) |
|
325 for connector in connected: |
|
326 connector.RefreshParentBlock() |
|
327 |
|
328 #------------------------------------------------------------------------------- |
|
329 # Create New Block Dialog |
|
330 #------------------------------------------------------------------------------- |
|
331 |
|
332 [wxID_BLOCKPROPERTIESDIALOG, wxID_BLOCKPROPERTIESDIALOGMAINPANEL, |
|
333 wxID_BLOCKPROPERTIESDIALOGNAME, wxID_BLOCKPROPERTIESDIALOGTYPETREE, |
|
334 wxID_BLOCKPROPERTIESDIALOGTYPEDESC, wxID_BLOCKPROPERTIESDIALOGINPUTS, |
|
335 wxID_BLOCKPROPERTIESDIALOGPREVIEW, wxID_BLOCKPROPERTIESDIALOGSTATICTEXT1, |
|
336 wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, wxID_BLOCKPROPERTIESDIALOGSTATICTEXT3, |
|
337 wxID_BLOCKPROPERTIESDIALOGSTATICTEXT4, |
|
338 ] = [wx.NewId() for _init_ctrls in range(11)] |
|
339 |
|
340 class BlockPropertiesDialog(wx.Dialog): |
|
341 def _init_coll_flexGridSizer1_Items(self, parent): |
|
342 # generated method, don't edit |
|
343 |
|
344 parent.AddWindow(self.MainPanel, 0, border=0, flag=0) |
|
345 |
|
346 def _init_sizers(self): |
|
347 # generated method, don't edit |
|
348 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
|
349 |
|
350 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
351 |
|
352 self.SetSizer(self.flexGridSizer1) |
|
353 |
|
354 def _init_ctrls(self, prnt): |
|
355 # generated method, don't edit |
|
356 wx.Dialog.__init__(self, id=wxID_BLOCKPROPERTIESDIALOG, |
|
357 name='BlockPropertiesDialog', parent=prnt, pos=wx.Point(376, 223), |
|
358 size=wx.Size(600, 360), style=wx.DEFAULT_DIALOG_STYLE, |
|
359 title='Block Properties') |
|
360 self.SetClientSize(wx.Size(600, 360)) |
|
361 |
|
362 self.MainPanel = wx.Panel(id=wxID_BLOCKPROPERTIESDIALOGMAINPANEL, |
|
363 name='MainPanel', parent=self, pos=wx.Point(0, 0), |
|
364 size=wx.Size(600, 320), style=wx.TAB_TRAVERSAL) |
|
365 self.MainPanel.SetAutoLayout(True) |
|
366 |
|
367 self.staticbox1 = wx.StaticBox(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT1, |
|
368 label='Type:', name='staticBox1', parent=self.MainPanel, |
|
369 pos=wx.Point(24, 24), size=wx.Size(245, 280), style=0) |
|
370 |
|
371 self.staticText2 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, |
|
372 label='Name:', name='staticText2', parent=self.MainPanel, |
|
373 pos=wx.Point(274, 24), size=wx.Size(70, 17), style=0) |
|
374 |
|
375 self.staticText3 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, |
|
376 label='Inputs:', name='staticText4', parent=self.MainPanel, |
|
377 pos=wx.Point(424, 24), size=wx.Size(70, 17), style=0) |
|
378 |
|
379 self.staticText4 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT4, |
|
380 label='Preview:', name='staticText4', parent=self.MainPanel, |
|
381 pos=wx.Point(274, 80), size=wx.Size(100, 17), style=0) |
|
382 |
|
383 self.TypeTree = wx.TreeCtrl(id=wxID_BLOCKPROPERTIESDIALOGTYPETREE, |
|
384 name='TypeTree', parent=self.MainPanel, pos=wx.Point(34, 44), |
|
385 size=wx.Size(225, 180), style=wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.TR_SINGLE|wx.SUNKEN_BORDER) |
|
386 EVT_TREE_SEL_CHANGED(self, wxID_BLOCKPROPERTIESDIALOGTYPETREE, self.OnTypeTreeItemSelected) |
|
387 |
|
388 self.TypeDesc = wx.TextCtrl(id=wxID_BLOCKPROPERTIESDIALOGTYPEDESC, |
|
389 name='TypeDesc', parent=self.MainPanel, pos=wx.Point(34, 230), |
|
390 size=wx.Size(225, 65), style=wx.TE_READONLY|wx.TE_MULTILINE) |
|
391 |
|
392 self.Name = wx.TextCtrl(id=wxID_BLOCKPROPERTIESDIALOGNAME, value='', |
|
393 name='Name', parent=self.MainPanel, pos=wx.Point(274, 48), |
|
394 size=wx.Size(145, 24), style=0) |
|
395 EVT_TEXT(self, wxID_BLOCKPROPERTIESDIALOGNAME, self.OnNameChanged) |
|
396 |
|
397 self.Inputs = wx.SpinCtrl(id=wxID_BLOCKPROPERTIESDIALOGINPUTS, |
|
398 name='Inputs', parent=self.MainPanel, pos=wx.Point(424, 48), |
|
399 size=wx.Size(145, 24), style=0, min=2, max=20) |
|
400 EVT_SPINCTRL(self, wxID_BLOCKPROPERTIESDIALOGINPUTS, self.OnInputsChanged) |
|
401 |
|
402 self.Preview = wx.Panel(id=wxID_BLOCKPROPERTIESDIALOGPREVIEW, |
|
403 name='Preview', parent=self.MainPanel, pos=wx.Point(274, 104), |
|
404 size=wx.Size(300, 200), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) |
|
405 self.Preview.SetBackgroundColour(wxColour(255,255,255)) |
|
406 |
|
407 self._init_sizers() |
|
408 |
|
409 def __init__(self, parent): |
|
410 self._init_ctrls(parent) |
|
411 self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL) |
|
412 self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) |
|
413 self.Name.SetValue("") |
|
414 self.Name.Enable(False) |
|
415 self.Inputs.Enable(False) |
|
416 self.Block = None |
|
417 self.MinBlockSize = None |
|
418 |
|
419 EVT_PAINT(self, self.OnPaint) |
|
420 EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK) |
|
421 |
|
422 def OnOK(self, event): |
|
423 error = [] |
|
424 selected = self.TypeTree.GetSelection() |
|
425 if not selected.IsOk() or self.TypeTree.GetItemParent(selected) == self.TypeTree.GetRootItem() or selected == self.TypeTree.GetRootItem(): |
|
426 message = wxMessageDialog(self, "Form isn't complete. Valid block type must be selected!", "Error", wxOK|wxICON_ERROR) |
|
427 message.ShowModal() |
|
428 message.Destroy() |
|
429 elif self.Name.IsEnabled() and self.Name.GetValue() == "": |
|
430 message = wxMessageDialog(self, "Form isn't complete. Name must be filled!", "Error", wxOK|wxICON_ERROR) |
|
431 message.ShowModal() |
|
432 message.Destroy() |
|
433 else: |
|
434 self.EndModal(wxID_OK) |
|
435 |
|
436 def SetBlockList(self, blocktypes): |
|
437 root = self.TypeTree.AddRoot("") |
|
438 for category in blocktypes: |
|
439 category_item = self.TypeTree.AppendItem(root, category["name"]) |
|
440 for blocktype in category["list"]: |
|
441 blocktype_item = self.TypeTree.AppendItem(category_item, blocktype["name"]) |
|
442 |
|
443 def SetMinBlockSize(self, size): |
|
444 self.MinBlockSize = size |
|
445 |
|
446 def GetValues(self): |
|
447 values = {} |
|
448 values["type"] = self.TypeTree.GetItemText(self.TypeTree.GetSelection()) |
|
449 if self.Name.GetValue() != "": |
|
450 values["name"] = self.Name.GetValue() |
|
451 values["width"], values["height"] = self.Block.GetSize() |
|
452 values["extension"] = self.Inputs.GetValue() |
|
453 return values |
|
454 |
|
455 def OnTypeTreeItemSelected(self, event): |
|
456 self.Name.SetValue("") |
|
457 selected = event.GetItem() |
|
458 if self.TypeTree.GetItemParent(selected) != self.TypeTree.GetRootItem(): |
|
459 blocktype = GetBlockType(self.TypeTree.GetItemText(selected)) |
|
460 if blocktype: |
|
461 self.Inputs.SetValue(len(blocktype["inputs"])) |
|
462 self.Inputs.Enable(blocktype["extensible"]) |
|
463 self.Name.Enable(blocktype["type"] != "function") |
|
464 self.TypeDesc.SetValue(blocktype["comment"]) |
|
465 wxCallAfter(self.RefreshPreview) |
|
466 else: |
|
467 self.Name.Enable(False) |
|
468 self.Inputs.Enable(False) |
|
469 self.Inputs.SetValue(2) |
|
470 self.TypeDesc.SetValue("") |
|
471 wxCallAfter(self.ErasePreview) |
|
472 else: |
|
473 self.Name.Enable(False) |
|
474 self.Inputs.Enable(False) |
|
475 self.Inputs.SetValue(2) |
|
476 self.TypeDesc.SetValue("") |
|
477 wxCallAfter(self.ErasePreview) |
|
478 event.Skip() |
|
479 |
|
480 def OnNameChanged(self, event): |
|
481 if self.Name.IsEnabled(): |
|
482 self.RefreshPreview() |
|
483 event.Skip() |
|
484 |
|
485 def OnInputsChanged(self, event): |
|
486 if self.Inputs.IsEnabled(): |
|
487 self.RefreshPreview() |
|
488 event.Skip() |
|
489 |
|
490 def ErasePreview(self): |
|
491 dc = wxClientDC(self.Preview) |
|
492 dc.Clear() |
|
493 self.Block = None |
|
494 |
|
495 def RefreshPreview(self): |
|
496 dc = wxClientDC(self.Preview) |
|
497 dc.Clear() |
|
498 blocktype = self.TypeTree.GetItemText(self.TypeTree.GetSelection()) |
|
499 self.Block = FBD_Block(self.Preview, blocktype, self.Name.GetValue(), extension = self.Inputs.GetValue()) |
|
500 width, height = self.MinBlockSize |
|
501 min_width, min_height = self.Block.GetMinSize() |
|
502 width, height = max(min_width, width), max(min_height, height) |
|
503 self.Block.SetSize(width, height) |
|
504 clientsize = self.Preview.GetClientSize() |
|
505 x = (clientsize.width - width) / 2 |
|
506 y = (clientsize.height - height) / 2 |
|
507 self.Block.SetPosition(x, y) |
|
508 self.Block.Draw(dc) |
|
509 |
|
510 def OnPaint(self, event): |
|
511 if self.Block: |
|
512 self.RefreshPreview() |
|
513 else: |
|
514 self.ErasePreview() |
|
515 |
|
516 |
|
517 #------------------------------------------------------------------------------- |
|
518 # Create New Variable Dialog |
|
519 #------------------------------------------------------------------------------- |
|
520 |
|
521 [wxID_VARIABLEPROPERTIESDIALOG, wxID_VARIABLEPROPERTIESDIALOGMAINPANEL, |
|
522 wxID_VARIABLEPROPERTIESDIALOGNAME, wxID_VARIABLEPROPERTIESDIALOGCLASS, |
|
523 wxID_VARIABLEPROPERTIESDIALOGPREVIEW, wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT1, |
|
524 wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT2, wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT3, |
|
525 ] = [wx.NewId() for _init_ctrls in range(8)] |
|
526 |
|
527 class VariablePropertiesDialog(wx.Dialog): |
|
528 def _init_coll_flexGridSizer1_Items(self, parent): |
|
529 # generated method, don't edit |
|
530 |
|
531 parent.AddWindow(self.MainPanel, 0, border=0, flag=0) |
|
532 |
|
533 def _init_sizers(self): |
|
534 # generated method, don't edit |
|
535 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
|
536 |
|
537 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
538 |
|
539 self.SetSizer(self.flexGridSizer1) |
|
540 |
|
541 def _init_ctrls(self, prnt): |
|
542 # generated method, don't edit |
|
543 wx.Dialog.__init__(self, id=wxID_VARIABLEPROPERTIESDIALOG, |
|
544 name='VariablePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), |
|
545 size=wx.Size(400, 320), style=wx.DEFAULT_DIALOG_STYLE, |
|
546 title='Variable Properties') |
|
547 self.SetClientSize(wx.Size(400, 320)) |
|
548 |
|
549 self.MainPanel = wx.Panel(id=wxID_VARIABLEPROPERTIESDIALOGMAINPANEL, |
|
550 name='MainPanel', parent=self, pos=wx.Point(0, 0), |
|
551 size=wx.Size(400, 280), style=wx.TAB_TRAVERSAL) |
|
552 self.MainPanel.SetAutoLayout(True) |
|
553 |
|
554 self.staticText1 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT1, |
|
555 label='Class:', name='staticText1', parent=self.MainPanel, |
|
556 pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) |
|
557 |
|
558 self.staticText2 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT2, |
|
559 label='Name:', name='staticText2', parent=self.MainPanel, |
|
560 pos=wx.Point(204, 24), size=wx.Size(70, 17), style=0) |
|
561 |
|
562 self.staticText3 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT3, |
|
563 label='Preview:', name='staticText3', parent=self.MainPanel, |
|
564 pos=wx.Point(24, 72), size=wx.Size(100, 17), style=0) |
|
565 |
|
566 self.Class = wx.Choice(id=wxID_VARIABLEPROPERTIESDIALOGCLASS, |
|
567 name='Class', parent=self.MainPanel, pos=wx.Point(24, 48), |
|
568 size=wx.Size(145, 24), style=0) |
|
569 EVT_CHOICE(self, wxID_VARIABLEPROPERTIESDIALOGCLASS, self.OnClassChanged) |
|
570 |
|
571 self.Name = wx.Choice(id=wxID_VARIABLEPROPERTIESDIALOGNAME, |
|
572 name='Name', parent=self.MainPanel, pos=wx.Point(204, 48), |
|
573 size=wx.Size(145, 24), style=0) |
|
574 EVT_CHOICE(self, wxID_VARIABLEPROPERTIESDIALOGNAME, self.OnNameChanged) |
|
575 |
|
576 self.Preview = wx.Panel(id=wxID_VARIABLEPROPERTIESDIALOGPREVIEW, |
|
577 name='Preview', parent=self.MainPanel, pos=wx.Point(24, 104), |
|
578 size=wx.Size(350, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) |
|
579 self.Preview.SetBackgroundColour(wxColour(255,255,255)) |
|
580 |
|
581 self._init_sizers() |
|
582 |
|
583 def __init__(self, parent): |
|
584 self._init_ctrls(parent) |
|
585 self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL) |
|
586 self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) |
|
587 self.Variable = None |
|
588 self.VarList = [] |
|
589 self.MinVariableSize = None |
|
590 self.RefreshNameList() |
|
591 |
|
592 for choice in ["Input", "Output", "InOut"]: |
|
593 self.Class.Append(choice) |
|
594 self.Class.SetStringSelection("Input") |
|
595 |
|
596 EVT_PAINT(self, self.OnPaint) |
|
597 |
|
598 def RefreshNameList(self): |
|
599 selected = self.Name.GetStringSelection() |
|
600 self.Name.Clear() |
|
601 for name, var_type, value_type in self.VarList: |
|
602 if var_type in ["Local","Temp","Output","InOut"]: |
|
603 self.Name.Append(name) |
|
604 elif var_type == "Input" and self.Class.GetStringSelection() == "Input": |
|
605 self.Name.Append(name) |
|
606 if self.Name.FindString(selected) != wxNOT_FOUND: |
|
607 self.Name.SetStringSelection(selected) |
|
608 self.Name.Enable(self.Name.GetCount() > 0) |
|
609 |
|
610 def SetMinVariableSize(self, size): |
|
611 self.MinVariableSize = size |
|
612 |
|
613 def SetVariables(self, vars): |
|
614 self.VarList = vars |
|
615 self.RefreshNameList() |
|
616 |
|
617 def GetValues(self): |
|
618 values = {} |
|
619 classtype = self.Class.GetStringSelection() |
|
620 if classtype == "Input": |
|
621 values["type"] = INPUT |
|
622 elif classtype == "Output": |
|
623 values["type"] = OUTPUT |
|
624 elif classtype == "InOut": |
|
625 values["type"] = INOUT |
|
626 values["name"] = self.Name.GetStringSelection() |
|
627 values["value_type"] = "" |
|
628 for var_name, var_type, value_type in self.VarList: |
|
629 if var_name == values["name"]: |
|
630 values["value_type"] = value_type |
|
631 values["width"], values["height"] = self.Variable.GetSize() |
|
632 return values |
|
633 |
|
634 def OnClassChanged(self, event): |
|
635 self.RefreshNameList() |
|
636 self.RefreshPreview() |
|
637 event.Skip() |
|
638 |
|
639 def OnNameChanged(self, event): |
|
640 self.RefreshPreview() |
|
641 event.Skip() |
|
642 |
|
643 def RefreshPreview(self): |
|
644 dc = wxClientDC(self.Preview) |
|
645 dc.Clear() |
|
646 name = self.Name.GetStringSelection() |
|
647 type = "" |
|
648 for var_name, var_type, value_type in self.VarList: |
|
649 if var_name == name: |
|
650 type = value_type |
|
651 classtype = self.Class.GetStringSelection() |
|
652 if classtype == "Input": |
|
653 self.Variable = FBD_Variable(self.Preview, INPUT, name, type) |
|
654 elif classtype == "Output": |
|
655 self.Variable = FBD_Variable(self.Preview, OUTPUT, name, type) |
|
656 elif classtype == "InOut": |
|
657 self.Variable = FBD_Variable(self.Preview, INOUT, name, type) |
|
658 width, height = self.MinVariableSize |
|
659 min_width, min_height = self.Variable.GetMinSize() |
|
660 width, height = max(min_width, width), max(min_height, height) |
|
661 self.Variable.SetSize(width, height) |
|
662 clientsize = self.Preview.GetClientSize() |
|
663 x = (clientsize.width - width) / 2 |
|
664 y = (clientsize.height - height) / 2 |
|
665 self.Variable.SetPosition(x, y) |
|
666 self.Variable.Draw(dc) |
|
667 |
|
668 def OnPaint(self, event): |
|
669 self.RefreshPreview() |
|
670 |
|
671 #------------------------------------------------------------------------------- |
|
672 # Create New Connection Dialog |
|
673 #------------------------------------------------------------------------------- |
|
674 |
|
675 [wxID_CONNECTIONPROPERTIESDIALOG, wxID_CONNECTIONPROPERTIESDIALOGMAINPANEL, |
|
676 wxID_CONNECTIONPROPERTIESDIALOGNAME, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, |
|
677 wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, wxID_CONNECTIONPROPERTIESDIALOGPREVIEW, |
|
678 wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT1, wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT2, |
|
679 wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT3, |
|
680 ] = [wx.NewId() for _init_ctrls in range(9)] |
|
681 |
|
682 class ConnectionPropertiesDialog(wx.Dialog): |
|
683 def _init_coll_flexGridSizer1_Items(self, parent): |
|
684 # generated method, don't edit |
|
685 |
|
686 parent.AddWindow(self.MainPanel, 0, border=0, flag=0) |
|
687 |
|
688 def _init_sizers(self): |
|
689 # generated method, don't edit |
|
690 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
|
691 |
|
692 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
693 |
|
694 self.SetSizer(self.flexGridSizer1) |
|
695 |
|
696 def _init_ctrls(self, prnt): |
|
697 # generated method, don't edit |
|
698 wx.Dialog.__init__(self, id=wxID_CONNECTIONPROPERTIESDIALOG, |
|
699 name='ConnectionPropertiesDialog', parent=prnt, pos=wx.Point(376, 223), |
|
700 size=wx.Size(350, 220), style=wx.DEFAULT_DIALOG_STYLE, |
|
701 title='Connection Properties') |
|
702 self.SetClientSize(wx.Size(350, 220)) |
|
703 |
|
704 self.MainPanel = wx.Panel(id=wxID_CONNECTIONPROPERTIESDIALOGMAINPANEL, |
|
705 name='MainPanel', parent=self, pos=wx.Point(0, 0), |
|
706 size=wx.Size(340, 360), style=wx.TAB_TRAVERSAL) |
|
707 self.MainPanel.SetAutoLayout(True) |
|
708 |
|
709 self.staticText1 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT1, |
|
710 label='Type:', name='staticText1', parent=self.MainPanel, |
|
711 pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) |
|
712 |
|
713 self.staticText2 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT2, |
|
714 label='Name:', name='staticText2', parent=self.MainPanel, |
|
715 pos=wx.Point(24, 104), size=wx.Size(70, 17), style=0) |
|
716 |
|
717 self.staticText3 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT3, |
|
718 label='Preview:', name='staticText3', parent=self.MainPanel, |
|
719 pos=wx.Point(174, 24), size=wx.Size(100, 17), style=0) |
|
720 |
|
721 self.radioButton1 = wx.RadioButton(id=wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, |
|
722 label='Connector', name='radioButton1', parent=self.MainPanel, |
|
723 pos=wx.Point(24, 48), size=wx.Size(114, 24), style=0) |
|
724 EVT_RADIOBUTTON(self, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, self.OnTypeChanged) |
|
725 self.radioButton1.SetValue(True) |
|
726 |
|
727 self.radioButton2 = wx.RadioButton(id=wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, |
|
728 label='Continuation', name='radioButton2', parent=self.MainPanel, |
|
729 pos=wx.Point(24, 72), size=wx.Size(128, 24), style=0) |
|
730 EVT_RADIOBUTTON(self, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, self.OnTypeChanged) |
|
731 self.radioButton2.SetValue(False) |
|
732 |
|
733 self.Name = wx.TextCtrl(id=wxID_CONNECTIONPROPERTIESDIALOGNAME, |
|
734 name='Name', parent=self.MainPanel, pos=wx.Point(24, 130), |
|
735 size=wx.Size(145, 24), style=0) |
|
736 EVT_TEXT(self, wxID_CONNECTIONPROPERTIESDIALOGNAME, self.OnNameChanged) |
|
737 |
|
738 self.Preview = wx.Panel(id=wxID_CONNECTIONPROPERTIESDIALOGPREVIEW, |
|
739 name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48), |
|
740 size=wx.Size(150, 100), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) |
|
741 self.Preview.SetBackgroundColour(wxColour(255,255,255)) |
|
742 |
|
743 self._init_sizers() |
|
744 |
|
745 def __init__(self, parent): |
|
746 self._init_ctrls(parent) |
|
747 self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL) |
|
748 self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) |
|
749 self.Connection = None |
|
750 self.MinConnectionSize = None |
|
751 |
|
752 EVT_PAINT(self, self.OnPaint) |
|
753 |
|
754 def SetMinConnectionSize(self, size): |
|
755 self.MinConnectionSize = size |
|
756 |
|
757 def GetValues(self): |
|
758 values = {} |
|
759 if self.radioButton1.GetValue(): |
|
760 values["type"] = CONNECTOR |
|
761 else: |
|
762 values["type"] = CONTINUATION |
|
763 values["name"] = self.Name.GetValue() |
|
764 values["width"], values["height"] = self.Connection.GetSize() |
|
765 return values |
|
766 |
|
767 def OnTypeChanged(self, event): |
|
768 self.RefreshPreview() |
|
769 event.Skip() |
|
770 |
|
771 def OnNameChanged(self, event): |
|
772 self.RefreshPreview() |
|
773 event.Skip() |
|
774 |
|
775 def RefreshPreview(self): |
|
776 dc = wxClientDC(self.Preview) |
|
777 dc.Clear() |
|
778 if self.radioButton1.GetValue(): |
|
779 self.Connection = FBD_Connector(self.Preview, CONNECTOR, self.Name.GetValue()) |
|
780 else: |
|
781 self.Connection = FBD_Connector(self.Preview, CONTINUATION, self.Name.GetValue()) |
|
782 width, height = self.MinConnectionSize |
|
783 min_width, min_height = self.Connection.GetMinSize() |
|
784 width, height = max(min_width, width), max(min_height, height) |
|
785 self.Connection.SetSize(width, height) |
|
786 clientsize = self.Preview.GetClientSize() |
|
787 x = (clientsize.width - width) / 2 |
|
788 y = (clientsize.height - height) / 2 |
|
789 self.Connection.SetPosition(x, y) |
|
790 self.Connection.Draw(dc) |
|
791 |
|
792 def OnPaint(self, event): |
|
793 self.RefreshPreview() |