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 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 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 connector = self.FindBlockConnector(pos) |
|
81 if connector: |
|
82 if (connector.GetDirection() == EAST): |
|
83 wire = Wire(self, [wxPoint(pos.x, pos.y), EAST], [wxPoint(pos.x, pos.y), WEST]) |
|
84 else: |
|
85 wire = Wire(self, [wxPoint(pos.x, pos.y), WEST], [wxPoint(pos.x, pos.y), EAST]) |
|
86 wire.oldPos = pos |
|
87 wire.Handle = (HANDLE_POINT, 0) |
|
88 wire.ProcessDragging(0, 0) |
|
89 wire.Handle = (HANDLE_POINT, 1) |
|
90 self.Wires.append(wire) |
|
91 self.Elements.append(wire) |
|
92 if self.SelectedElement: |
|
93 self.SelectedElement.SetSelected(False) |
|
94 self.SelectedElement = wire |
|
95 elif self.SelectedElement: |
|
96 self.SelectedElement.SetSelected(False) |
|
97 self.SelectedElement = None |
|
98 self.Refresh() |
|
99 event.Skip() |
|
100 |
|
101 def OnViewerLeftUp(self, event): |
|
102 if self.rubberBand.IsShown(): |
|
103 if self.Mode == MODE_SELECTION: |
|
104 elements = self.SearchElements(self.rubberBand.GetCurrentExtent()) |
|
105 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
106 if len(elements) > 0: |
|
107 self.SelectedElement = Graphic_Group(self) |
|
108 self.SelectedElement.SetElements(elements) |
|
109 self.SelectedElement.SetSelected(True) |
|
110 self.Refresh() |
|
111 elif self.Mode == MODE_BLOCK: |
|
112 bbox = self.rubberBand.GetCurrentExtent() |
|
113 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
114 wxCallAfter(self.AddNewBlock, bbox) |
|
115 elif self.Mode == MODE_VARIABLE: |
|
116 bbox = self.rubberBand.GetCurrentExtent() |
|
117 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
118 wxCallAfter(self.AddNewVariable, bbox) |
|
119 elif self.Mode == MODE_CONNECTION: |
|
120 bbox = self.rubberBand.GetCurrentExtent() |
|
121 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
122 wxCallAfter(self.AddNewConnection, bbox) |
|
123 elif self.Mode == MODE_COMMENT: |
|
124 bbox = self.rubberBand.GetCurrentExtent() |
|
125 self.rubberBand.OnLeftUp(event, self.Scaling) |
|
126 wxCallAfter(self.AddNewComment, bbox) |
|
127 elif self.Mode == MODE_SELECTION and self.SelectedElement: |
|
128 self.SelectedElement.OnLeftUp(event, self.Scaling) |
|
129 wxCallAfter(self.SetCursor, wxNullCursor) |
|
130 self.ReleaseMouse() |
|
131 self.Refresh() |
|
132 elif self.Mode == MODE_WIRE and self.SelectedElement: |
|
133 pos = GetScaledEventPosition(event, self.Scaling) |
|
134 connector = self.FindBlockConnector(pos, False) |
|
135 if connector and connector != self.SelectedElement.StartConnected: |
|
136 self.SelectedElement.ResetPoints() |
|
137 self.SelectedElement.OnMotion(event, self.Scaling) |
|
138 self.SelectedElement.GeneratePoints() |
|
139 self.SelectedElement.RefreshModel() |
|
140 self.SelectedElement.SetSelected(True) |
|
141 else: |
|
142 self.SelectedElement.Delete() |
|
143 self.SelectedElement = None |
|
144 self.Refresh() |
|
145 if not self.SavedMode: |
|
146 wxCallAfter(self.Parent.ResetCurrentMode) |
|
147 event.Skip() |
|
148 |
|
149 def OnViewerRightUp(self, event): |
|
150 pos = event.GetPosition() |
|
151 element = self.FindElement(pos) |
|
152 if element: |
|
153 if self.SelectedElement and self.SelectedElement != element: |
|
154 self.SelectedElement.SetSelected(False) |
|
155 self.SelectedElement = element |
|
156 self.SelectedElement.SetSelected(True) |
|
157 self.SelectedElement.OnRightUp(event, self.Scaling) |
|
158 wxCallAfter(self.SetCursor, wxNullCursor) |
|
159 self.ReleaseMouse() |
|
160 self.Refresh() |
|
161 event.Skip() |
|
162 |
|
163 def OnViewerLeftDClick(self, event): |
|
164 if self.Mode == MODE_SELECTION and self.SelectedElement: |
|
165 self.SelectedElement.OnLeftDClick(event, self.Scaling) |
|
166 self.Refresh() |
|
167 event.Skip() |
|
168 |
|
169 def OnViewerMotion(self, event): |
|
170 if self.rubberBand.IsShown(): |
|
171 self.rubberBand.OnMotion(event, self.Scaling) |
|
172 elif self.Mode == MODE_SELECTION and self.SelectedElement: |
|
173 self.SelectedElement.OnMotion(event, self.Scaling) |
|
174 self.Refresh() |
|
175 elif self.Mode == MODE_WIRE and self.SelectedElement: |
|
176 pos = GetScaledEventPosition(event, self.Scaling) |
|
177 connector = self.FindBlockConnector(pos, False) |
|
178 if not connector or self.SelectedElement.EndConnected == None: |
|
179 self.SelectedElement.ResetPoints() |
|
180 self.SelectedElement.OnMotion(event, self.Scaling) |
|
181 self.SelectedElement.GeneratePoints() |
|
182 self.Refresh() |
|
183 event.Skip() |
|
184 |
|
185 #------------------------------------------------------------------------------- |
|
186 # Keyboard event functions |
|
187 #------------------------------------------------------------------------------- |
|
188 |
|
189 def OnChar(self, event): |
|
190 keycode = event.GetKeyCode() |
|
191 if self.Scaling: |
|
192 scaling = self.Scaling |
|
193 else: |
|
194 scaling = (8, 8) |
|
195 if keycode == WXK_DELETE and self.SelectedElement: |
|
196 self.SelectedElement.Clean() |
|
197 self.SelectedElement.Delete() |
|
198 self.SelectedElement = None |
|
199 elif keycode == WXK_LEFT and self.SelectedElement: |
|
200 self.SelectedElement.Move(-scaling[0], 0) |
|
201 elif keycode == WXK_RIGHT and self.SelectedElement: |
|
202 self.SelectedElement.Move(scaling[0], 0) |
|
203 elif keycode == WXK_UP and self.SelectedElement: |
|
204 self.SelectedElement.Move(0, -scaling[1]) |
|
205 elif keycode == WXK_DOWN and self.SelectedElement: |
|
206 self.SelectedElement.Move(0, scaling[1]) |
|
207 self.Refresh() |
|
208 event.Skip() |
|
209 |
|
210 #------------------------------------------------------------------------------- |
|
211 # Adding element functions |
|
212 #------------------------------------------------------------------------------- |
|
213 |
|
214 def AddNewBlock(self, bbox): |
|
215 dialog = BlockPropertiesDialog(self.Parent) |
|
216 dialog.SetBlockList(self.Controler.GetBlockTypes()) |
|
217 dialog.SetMinBlockSize((bbox.width, bbox.height)) |
|
218 if dialog.ShowModal() == wxID_OK: |
|
219 id = self.GetNewId() |
|
220 values = dialog.GetValues() |
|
221 if "name" in values: |
|
222 block = FBD_Block(self, values["type"], values["name"], id, values["extension"]) |
|
223 else: |
|
224 block = FBD_Block(self, values["type"], "", id, values["extension"]) |
|
225 block.SetPosition(bbox.x, bbox.y) |
|
226 block.SetSize(values["width"], values["height"]) |
|
227 self.Blocks.append(block) |
|
228 self.Elements.append(block) |
|
229 self.Controler.AddCurrentElementEditingBlock(id) |
|
230 self.RefreshBlockModel(block) |
|
231 self.Refresh() |
|
232 dialog.Destroy() |
|
233 |
|
234 def AddNewVariable(self, bbox): |
|
235 dialog = VariablePropertiesDialog(self.Parent) |
|
236 dialog.SetMinVariableSize((bbox.width, bbox.height)) |
|
237 varlist = [] |
|
238 vars = self.Controler.GetCurrentElementEditingInterfaceVars() |
|
239 if vars: |
|
240 for var in vars: |
|
241 varlist.append((var["Name"], var["Class"], var["Type"])) |
|
242 returntype = self.Controler.GetCurrentElementEditingInterfaceReturnType() |
|
243 if returntype: |
|
244 varlist.append((self.Controler.GetCurrentElementEditingName(), "Output", returntype)) |
|
245 dialog.SetVariables(varlist) |
|
246 if dialog.ShowModal() == wxID_OK: |
|
247 id = self.GetNewId() |
|
248 values = dialog.GetValues() |
|
249 variable = FBD_Variable(self, values["type"], values["name"], values["value_type"], id) |
|
250 variable.SetPosition(bbox.x, bbox.y) |
|
251 variable.SetSize(values["width"], values["height"]) |
|
252 self.Blocks.append(variable) |
|
253 self.Elements.append(variable) |
|
254 self.Controler.AddCurrentElementEditingVariable(id, values["type"]) |
|
255 self.RefreshVariableModel(variable) |
|
256 self.Refresh() |
|
257 dialog.Destroy() |
|
258 |
|
259 def AddNewConnection(self, bbox): |
|
260 dialog = ConnectionPropertiesDialog(self.Parent) |
|
261 dialog.SetMinConnectionSize((bbox.width, bbox.height)) |
|
262 if dialog.ShowModal() == wxID_OK: |
|
263 id = self.GetNewId() |
|
264 values = dialog.GetValues() |
|
265 connection = FBD_Connection(self, values["type"], values["name"], id) |
|
266 connection.SetPosition(bbox.x, bbox.y) |
|
267 connection.SetSize(values["width"], values["height"]) |
|
268 self.Blocks.append(connection) |
|
269 self.Elements.append(connection) |
|
270 self.Controler.AddCurrentElementEditingConnection(id, values["type"]) |
|
271 self.RefreshConnectionModel(connection) |
|
272 self.Refresh() |
|
273 dialog.Destroy() |
|
274 |
|
275 def AddNewComment(self, bbox): |
|
276 dialog = wxTextEntryDialog(self.Parent, "Add a new comment", "Please enter comment text", "", wxOK|wxCANCEL|wxTE_MULTILINE) |
|
277 if dialog.ShowModal() == wxID_OK: |
|
278 value = dialog.GetValue() |
|
279 id = self.GetNewId() |
|
280 comment = Comment(self, value, id) |
|
281 comment.SetPosition(bbox.x, bbox.y) |
|
282 min_width, min_height = comment.GetMinSize() |
|
283 comment.SetSize(max(min_width,bbox.width),max(min_height,bbox.height)) |
|
284 self.Elements.append(comment) |
|
285 self.Controler.AddCurrentElementEditingComment(id) |
|
286 self.RefreshCommentModel(comment) |
|
287 self.Refresh() |
|
288 dialog.Destroy() |
|
289 |
|
290 #------------------------------------------------------------------------------- |
|
291 # Delete element functions |
|
292 #------------------------------------------------------------------------------- |
|
293 |
|
294 def DeleteBlock(self, block): |
|
295 wires = [] |
|
296 for output in block.GetConnectors()["outputs"]: |
|
297 wires.extend([wire[0] for wire in output.GetWires()]) |
|
298 block.Clean() |
|
299 self.Blocks.remove(block) |
|
300 self.Elements.remove(block) |
|
301 self.Controler.RemoveCurrentElementEditingInstance(block.GetId()) |
|
302 for wire in wires: |
|
303 wire.RefreshModel() |
|
304 |
|
305 def DeleteVariable(self, variable): |
|
306 wires = [] |
|
307 if variable.GetType() == INPUT: |
|
308 connector = variable.GetConnector() |
|
309 wires.extend([wire[0] for wire in connector.GetWires()]) |
|
310 variable.Clean() |
|
311 self.Blocks.remove(variable) |
|
312 self.Elements.remove(variable) |
|
313 self.Controler.RemoveCurrentElementEditingInstance(variable.GetId()) |
|
314 for wire in wires: |
|
315 wire.RefreshModel() |
|
316 |
|
317 def DeleteConnection(self, connection): |
|
318 wires = [] |
|
319 if connection.GetType() == CONTINUATION: |
|
320 connector = connection.GetConnector() |
|
321 wires.extend([wire[0] for wire in connector.GetWires()]) |
|
322 connection.Clean() |
|
323 self.Blocks.remove(connection) |
|
324 self.Elements.remove(connection) |
|
325 self.Controler.RemoveCurrentElementEditingInstance(connection.GetId()) |
|
326 for wire in wires: |
|
327 wire.RefreshModel() |
|
328 |
|
329 def DeleteComment(self, comment): |
|
330 self.Elements.remove(comment) |
|
331 self.Controler.RemoveCurrentElementEditingInstance(comment.GetId()) |
|
332 |
|
333 def DeleteWire(self, wire): |
|
334 connected = wire.GetConnected() |
|
335 wire.Clean() |
|
336 self.Wires.remove(wire) |
|
337 self.Elements.remove(wire) |
|
338 for connector in connected: |
|
339 connector.RefreshParentBlock() |
|
340 |
|
341 #------------------------------------------------------------------------------- |
|
342 # Edit element content functions |
|
343 #------------------------------------------------------------------------------- |
|
344 |
|
345 def EditBlockContent(self, block): |
|
346 dialog = BlockPropertiesDialog(self.Parent) |
|
347 dialog.SetBlockList(self.Controler.GetBlockTypes()) |
|
348 dialog.SetMinBlockSize(block.GetSize()) |
|
349 values = {"name" : block.GetName(), "type" : block.GetType()} |
|
350 values["extension"] = block.GetExtension() |
|
351 dialog.SetValues(values) |
|
352 if dialog.ShowModal() == wxID_OK: |
|
353 values = dialog.GetValues() |
|
354 if "name" in values: |
|
355 block.SetName(values["name"]) |
|
356 block.SetExtension(values["extension"]) |
|
357 block.SetSize(values["width"], values["height"]) |
|
358 block.SetType(values["type"]) |
|
359 self.RefreshBlockModel(block) |
|
360 self.Refresh() |
|
361 dialog.Destroy() |
|
362 |
|
363 def EditVariableContent(self, variable): |
|
364 dialog = VariablePropertiesDialog(self.Parent) |
|
365 dialog.SetMinVariableSize(variable.GetSize()) |
|
366 varlist = [] |
|
367 vars = self.Controler.GetCurrentElementEditingInterfaceVars() |
|
368 if vars: |
|
369 for var in vars: |
|
370 varlist.append((var["Name"], var["Class"], var["Type"])) |
|
371 returntype = self.Controler.GetCurrentElementEditingInterfaceReturnType() |
|
372 if returntype: |
|
373 varlist.append((self.Controler.GetCurrentElementEditingName(), "Output", returntype)) |
|
374 dialog.SetVariables(varlist) |
|
375 values = {"name" : variable.GetName(), "type" : variable.GetType()} |
|
376 dialog.SetValues(values) |
|
377 if dialog.ShowModal() == wxID_OK: |
|
378 old_type = variable.GetType() |
|
379 values = dialog.GetValues() |
|
380 variable.SetName(values["name"]) |
|
381 variable.SetType(values["type"], values["value_type"]) |
|
382 variable.SetSize(values["width"], values["height"]) |
|
383 if old_type != values["type"]: |
|
384 id = variable.GetId() |
|
385 self.Controler.RemoveCurrentElementEditingInstance(id) |
|
386 self.Controler.AddCurrentElementEditingVariable(id, values["type"]) |
|
387 self.RefreshVariableModel(variable) |
|
388 self.Refresh() |
|
389 dialog.Destroy() |
|
390 |
|
391 #------------------------------------------------------------------------------- |
|
392 # Create New Block Dialog |
|
393 #------------------------------------------------------------------------------- |
|
394 |
|
395 [wxID_BLOCKPROPERTIESDIALOG, wxID_BLOCKPROPERTIESDIALOGMAINPANEL, |
|
396 wxID_BLOCKPROPERTIESDIALOGNAME, wxID_BLOCKPROPERTIESDIALOGTYPETREE, |
|
397 wxID_BLOCKPROPERTIESDIALOGTYPEDESC, wxID_BLOCKPROPERTIESDIALOGINPUTS, |
|
398 wxID_BLOCKPROPERTIESDIALOGPREVIEW, wxID_BLOCKPROPERTIESDIALOGSTATICTEXT1, |
|
399 wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, wxID_BLOCKPROPERTIESDIALOGSTATICTEXT3, |
|
400 wxID_BLOCKPROPERTIESDIALOGSTATICTEXT4, |
|
401 ] = [wx.NewId() for _init_ctrls in range(11)] |
|
402 |
|
403 [CATEGORY, BLOCK] = range(2) |
|
404 |
|
405 class BlockPropertiesDialog(wx.Dialog): |
|
406 def _init_coll_flexGridSizer1_Items(self, parent): |
|
407 # generated method, don't edit |
|
408 |
|
409 parent.AddWindow(self.MainPanel, 0, border=0, flag=0) |
|
410 |
|
411 def _init_sizers(self): |
|
412 # generated method, don't edit |
|
413 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
|
414 |
|
415 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
416 |
|
417 self.SetSizer(self.flexGridSizer1) |
|
418 |
|
419 def _init_ctrls(self, prnt): |
|
420 # generated method, don't edit |
|
421 wx.Dialog.__init__(self, id=wxID_BLOCKPROPERTIESDIALOG, |
|
422 name='BlockPropertiesDialog', parent=prnt, pos=wx.Point(376, 223), |
|
423 size=wx.Size(600, 360), style=wx.DEFAULT_DIALOG_STYLE, |
|
424 title='Block Properties') |
|
425 self.SetClientSize(wx.Size(600, 360)) |
|
426 |
|
427 self.MainPanel = wx.Panel(id=wxID_BLOCKPROPERTIESDIALOGMAINPANEL, |
|
428 name='MainPanel', parent=self, pos=wx.Point(0, 0), |
|
429 size=wx.Size(600, 320), style=wx.TAB_TRAVERSAL) |
|
430 self.MainPanel.SetAutoLayout(True) |
|
431 |
|
432 self.staticbox1 = wx.StaticBox(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT1, |
|
433 label='Type:', name='staticBox1', parent=self.MainPanel, |
|
434 pos=wx.Point(24, 24), size=wx.Size(245, 280), style=0) |
|
435 |
|
436 self.staticText2 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, |
|
437 label='Name:', name='staticText2', parent=self.MainPanel, |
|
438 pos=wx.Point(274, 24), size=wx.Size(70, 17), style=0) |
|
439 |
|
440 self.staticText3 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, |
|
441 label='Inputs:', name='staticText4', parent=self.MainPanel, |
|
442 pos=wx.Point(424, 24), size=wx.Size(70, 17), style=0) |
|
443 |
|
444 self.staticText4 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT4, |
|
445 label='Preview:', name='staticText4', parent=self.MainPanel, |
|
446 pos=wx.Point(274, 80), size=wx.Size(100, 17), style=0) |
|
447 |
|
448 self.TypeTree = wx.TreeCtrl(id=wxID_BLOCKPROPERTIESDIALOGTYPETREE, |
|
449 name='TypeTree', parent=self.MainPanel, pos=wx.Point(34, 44), |
|
450 size=wx.Size(225, 180), style=wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.TR_SINGLE|wx.SUNKEN_BORDER) |
|
451 EVT_TREE_SEL_CHANGED(self, wxID_BLOCKPROPERTIESDIALOGTYPETREE, self.OnTypeTreeItemSelected) |
|
452 |
|
453 self.TypeDesc = wx.TextCtrl(id=wxID_BLOCKPROPERTIESDIALOGTYPEDESC, |
|
454 name='TypeDesc', parent=self.MainPanel, pos=wx.Point(34, 230), |
|
455 size=wx.Size(225, 65), style=wx.TE_READONLY|wx.TE_MULTILINE) |
|
456 |
|
457 self.Name = wx.TextCtrl(id=wxID_BLOCKPROPERTIESDIALOGNAME, value='', |
|
458 name='Name', parent=self.MainPanel, pos=wx.Point(274, 48), |
|
459 size=wx.Size(145, 24), style=0) |
|
460 EVT_TEXT(self, wxID_BLOCKPROPERTIESDIALOGNAME, self.OnNameChanged) |
|
461 |
|
462 self.Inputs = wx.SpinCtrl(id=wxID_BLOCKPROPERTIESDIALOGINPUTS, |
|
463 name='Inputs', parent=self.MainPanel, pos=wx.Point(424, 48), |
|
464 size=wx.Size(145, 24), style=0, min=2, max=20) |
|
465 EVT_SPINCTRL(self, wxID_BLOCKPROPERTIESDIALOGINPUTS, self.OnInputsChanged) |
|
466 |
|
467 self.Preview = wx.Panel(id=wxID_BLOCKPROPERTIESDIALOGPREVIEW, |
|
468 name='Preview', parent=self.MainPanel, pos=wx.Point(274, 104), |
|
469 size=wx.Size(300, 200), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) |
|
470 self.Preview.SetBackgroundColour(wxColour(255,255,255)) |
|
471 |
|
472 self._init_sizers() |
|
473 |
|
474 def __init__(self, parent): |
|
475 self._init_ctrls(parent) |
|
476 self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) |
|
477 self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) |
|
478 self.Name.SetValue("") |
|
479 self.Name.Enable(False) |
|
480 self.Inputs.Enable(False) |
|
481 self.Block = None |
|
482 self.MinBlockSize = None |
|
483 |
|
484 EVT_PAINT(self, self.OnPaint) |
|
485 EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK) |
|
486 |
|
487 def FindTreeItem(self, root, name): |
|
488 if root.IsOk(): |
|
489 if self.TypeTree.GetItemText(root) == name: |
|
490 return root |
|
491 else: |
|
492 item, root_cookie = self.TypeTree.GetFirstChild(root) |
|
493 while item.IsOk(): |
|
494 result = self.FindTreeItem(item, name) |
|
495 if result: |
|
496 return result |
|
497 item, root_cookie = self.TypeTree.GetNextChild(root, root_cookie) |
|
498 return None |
|
499 |
|
500 def OnOK(self, event): |
|
501 error = [] |
|
502 selected = self.TypeTree.GetSelection() |
|
503 if not selected.IsOk() or self.TypeTree.GetItemParent(selected) == self.TypeTree.GetRootItem() or selected == self.TypeTree.GetRootItem(): |
|
504 message = wxMessageDialog(self, "Form isn't complete. Valid block type must be selected!", "Error", wxOK|wxICON_ERROR) |
|
505 message.ShowModal() |
|
506 message.Destroy() |
|
507 elif self.Name.IsEnabled() and self.Name.GetValue() == "": |
|
508 message = wxMessageDialog(self, "Form isn't complete. Name must be filled!", "Error", wxOK|wxICON_ERROR) |
|
509 message.ShowModal() |
|
510 message.Destroy() |
|
511 else: |
|
512 self.EndModal(wxID_OK) |
|
513 |
|
514 def SetBlockList(self, blocktypes): |
|
515 root = self.TypeTree.AddRoot("") |
|
516 self.TypeTree.SetPyData(root, CATEGORY) |
|
517 for category in blocktypes: |
|
518 category_item = self.TypeTree.AppendItem(root, category["name"]) |
|
519 self.TypeTree.SetPyData(category_item, CATEGORY) |
|
520 for blocktype in category["list"]: |
|
521 blocktype_item = self.TypeTree.AppendItem(category_item, blocktype["name"]) |
|
522 self.TypeTree.SetPyData(blocktype_item, BLOCK) |
|
523 |
|
524 def SetMinBlockSize(self, size): |
|
525 self.MinBlockSize = size |
|
526 |
|
527 def SetValues(self, values): |
|
528 for name, value in values.items(): |
|
529 if name == "type": |
|
530 item = self.FindTreeItem(self.TypeTree.GetRootItem(), value) |
|
531 if item: |
|
532 self.TypeTree.SelectItem(item) |
|
533 elif name == "name": |
|
534 self.Name.SetValue(value) |
|
535 elif name == "extension": |
|
536 self.Inputs.SetValue(value) |
|
537 self.RefreshPreview() |
|
538 |
|
539 def GetValues(self): |
|
540 values = {} |
|
541 values["type"] = self.TypeTree.GetItemText(self.TypeTree.GetSelection()) |
|
542 if self.Name.GetValue() != "": |
|
543 values["name"] = self.Name.GetValue() |
|
544 values["width"], values["height"] = self.Block.GetSize() |
|
545 values["extension"] = self.Inputs.GetValue() |
|
546 return values |
|
547 |
|
548 def OnTypeTreeItemSelected(self, event): |
|
549 self.Name.SetValue("") |
|
550 selected = event.GetItem() |
|
551 if self.TypeTree.GetPyData(selected) != CATEGORY: |
|
552 blocktype = GetBlockType(self.TypeTree.GetItemText(selected)) |
|
553 if blocktype: |
|
554 self.Inputs.SetValue(len(blocktype["inputs"])) |
|
555 self.Inputs.Enable(blocktype["extensible"]) |
|
556 self.Name.Enable(blocktype["type"] != "function") |
|
557 self.TypeDesc.SetValue(blocktype["comment"]) |
|
558 wxCallAfter(self.RefreshPreview) |
|
559 else: |
|
560 self.Name.Enable(False) |
|
561 self.Inputs.Enable(False) |
|
562 self.Inputs.SetValue(2) |
|
563 self.TypeDesc.SetValue("") |
|
564 wxCallAfter(self.ErasePreview) |
|
565 else: |
|
566 self.Name.Enable(False) |
|
567 self.Inputs.Enable(False) |
|
568 self.Inputs.SetValue(2) |
|
569 self.TypeDesc.SetValue("") |
|
570 wxCallAfter(self.ErasePreview) |
|
571 event.Skip() |
|
572 |
|
573 def OnNameChanged(self, event): |
|
574 if self.Name.IsEnabled(): |
|
575 self.RefreshPreview() |
|
576 event.Skip() |
|
577 |
|
578 def OnInputsChanged(self, event): |
|
579 if self.Inputs.IsEnabled(): |
|
580 self.RefreshPreview() |
|
581 event.Skip() |
|
582 |
|
583 def ErasePreview(self): |
|
584 dc = wxClientDC(self.Preview) |
|
585 dc.Clear() |
|
586 self.Block = None |
|
587 |
|
588 def RefreshPreview(self): |
|
589 dc = wxClientDC(self.Preview) |
|
590 dc.Clear() |
|
591 item = self.TypeTree.GetSelection() |
|
592 if self.TypeTree.GetPyData(item) == CATEGORY: |
|
593 self.Block = None |
|
594 else: |
|
595 blocktype = self.TypeTree.GetItemText(item) |
|
596 if blocktype: |
|
597 self.Block = FBD_Block(self.Preview, blocktype, self.Name.GetValue(), extension = self.Inputs.GetValue()) |
|
598 width, height = self.MinBlockSize |
|
599 min_width, min_height = self.Block.GetMinSize() |
|
600 width, height = max(min_width, width), max(min_height, height) |
|
601 self.Block.SetSize(width, height) |
|
602 clientsize = self.Preview.GetClientSize() |
|
603 x = (clientsize.width - width) / 2 |
|
604 y = (clientsize.height - height) / 2 |
|
605 self.Block.SetPosition(x, y) |
|
606 self.Block.Draw(dc) |
|
607 else: |
|
608 self.Block = None |
|
609 |
|
610 def OnPaint(self, event): |
|
611 if self.Block: |
|
612 self.RefreshPreview() |
|
613 |
|
614 |
|
615 #------------------------------------------------------------------------------- |
|
616 # Create New Variable Dialog |
|
617 #------------------------------------------------------------------------------- |
|
618 |
|
619 [wxID_VARIABLEPROPERTIESDIALOG, wxID_VARIABLEPROPERTIESDIALOGMAINPANEL, |
|
620 wxID_VARIABLEPROPERTIESDIALOGNAME, wxID_VARIABLEPROPERTIESDIALOGCLASS, |
|
621 wxID_VARIABLEPROPERTIESDIALOGPREVIEW, wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT1, |
|
622 wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT2, wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT3, |
|
623 ] = [wx.NewId() for _init_ctrls in range(8)] |
|
624 |
|
625 class VariablePropertiesDialog(wx.Dialog): |
|
626 def _init_coll_flexGridSizer1_Items(self, parent): |
|
627 # generated method, don't edit |
|
628 |
|
629 parent.AddWindow(self.MainPanel, 0, border=0, flag=0) |
|
630 |
|
631 def _init_sizers(self): |
|
632 # generated method, don't edit |
|
633 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
|
634 |
|
635 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
636 |
|
637 self.SetSizer(self.flexGridSizer1) |
|
638 |
|
639 def _init_ctrls(self, prnt): |
|
640 # generated method, don't edit |
|
641 wx.Dialog.__init__(self, id=wxID_VARIABLEPROPERTIESDIALOG, |
|
642 name='VariablePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), |
|
643 size=wx.Size(400, 320), style=wx.DEFAULT_DIALOG_STYLE, |
|
644 title='Variable Properties') |
|
645 self.SetClientSize(wx.Size(400, 320)) |
|
646 |
|
647 self.MainPanel = wx.Panel(id=wxID_VARIABLEPROPERTIESDIALOGMAINPANEL, |
|
648 name='MainPanel', parent=self, pos=wx.Point(0, 0), |
|
649 size=wx.Size(400, 280), style=wx.TAB_TRAVERSAL) |
|
650 self.MainPanel.SetAutoLayout(True) |
|
651 |
|
652 self.staticText1 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT1, |
|
653 label='Class:', name='staticText1', parent=self.MainPanel, |
|
654 pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) |
|
655 |
|
656 self.staticText2 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT2, |
|
657 label='Name:', name='staticText2', parent=self.MainPanel, |
|
658 pos=wx.Point(204, 24), size=wx.Size(70, 17), style=0) |
|
659 |
|
660 self.staticText3 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT3, |
|
661 label='Preview:', name='staticText3', parent=self.MainPanel, |
|
662 pos=wx.Point(24, 78), size=wx.Size(100, 17), style=0) |
|
663 |
|
664 self.Class = wx.Choice(id=wxID_VARIABLEPROPERTIESDIALOGCLASS, |
|
665 name='Class', parent=self.MainPanel, pos=wx.Point(24, 48), |
|
666 size=wx.Size(145, 24), style=0) |
|
667 EVT_CHOICE(self, wxID_VARIABLEPROPERTIESDIALOGCLASS, self.OnClassChanged) |
|
668 |
|
669 self.Name = wx.Choice(id=wxID_VARIABLEPROPERTIESDIALOGNAME, |
|
670 name='Name', parent=self.MainPanel, pos=wx.Point(204, 48), |
|
671 size=wx.Size(145, 24), style=0) |
|
672 EVT_CHOICE(self, wxID_VARIABLEPROPERTIESDIALOGNAME, self.OnNameChanged) |
|
673 |
|
674 self.Preview = wx.Panel(id=wxID_VARIABLEPROPERTIESDIALOGPREVIEW, |
|
675 name='Preview', parent=self.MainPanel, pos=wx.Point(24, 104), |
|
676 size=wx.Size(350, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) |
|
677 self.Preview.SetBackgroundColour(wxColour(255,255,255)) |
|
678 |
|
679 self._init_sizers() |
|
680 |
|
681 def __init__(self, parent): |
|
682 self._init_ctrls(parent) |
|
683 self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) |
|
684 self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) |
|
685 self.Variable = None |
|
686 self.VarList = [] |
|
687 self.MinVariableSize = None |
|
688 self.RefreshNameList() |
|
689 |
|
690 for choice in ["Input", "Output", "InOut"]: |
|
691 self.Class.Append(choice) |
|
692 self.Class.SetStringSelection("Input") |
|
693 |
|
694 EVT_PAINT(self, self.OnPaint) |
|
695 |
|
696 def RefreshNameList(self): |
|
697 selected = self.Name.GetStringSelection() |
|
698 self.Name.Clear() |
|
699 for name, var_type, value_type in self.VarList: |
|
700 if var_type in ["Local","Temp","Output","InOut"]: |
|
701 self.Name.Append(name) |
|
702 elif var_type == "Input" and self.Class.GetStringSelection() == "Input": |
|
703 self.Name.Append(name) |
|
704 if self.Name.FindString(selected) != wxNOT_FOUND: |
|
705 self.Name.SetStringSelection(selected) |
|
706 self.Name.Enable(self.Name.GetCount() > 0) |
|
707 |
|
708 def SetMinVariableSize(self, size): |
|
709 self.MinVariableSize = size |
|
710 |
|
711 def SetVariables(self, vars): |
|
712 self.VarList = vars |
|
713 self.RefreshNameList() |
|
714 |
|
715 def SetValues(self, values): |
|
716 for name, value in values.items(): |
|
717 if name == "type": |
|
718 if value == INPUT: |
|
719 self.Class.SetStringSelection("Input") |
|
720 if value == OUTPUT: |
|
721 self.Class.SetStringSelection("Output") |
|
722 if value == INOUT: |
|
723 self.Class.SetStringSelection("InOut") |
|
724 elif name == "name": |
|
725 self.Name.SetStringSelection(value) |
|
726 self.RefreshPreview() |
|
727 |
|
728 def GetValues(self): |
|
729 values = {} |
|
730 classtype = self.Class.GetStringSelection() |
|
731 if classtype == "Input": |
|
732 values["type"] = INPUT |
|
733 elif classtype == "Output": |
|
734 values["type"] = OUTPUT |
|
735 elif classtype == "InOut": |
|
736 values["type"] = INOUT |
|
737 values["name"] = self.Name.GetStringSelection() |
|
738 values["value_type"] = "" |
|
739 for var_name, var_type, value_type in self.VarList: |
|
740 if var_name == values["name"]: |
|
741 values["value_type"] = value_type |
|
742 values["width"], values["height"] = self.Variable.GetSize() |
|
743 return values |
|
744 |
|
745 def OnClassChanged(self, event): |
|
746 self.RefreshNameList() |
|
747 self.RefreshPreview() |
|
748 event.Skip() |
|
749 |
|
750 def OnNameChanged(self, event): |
|
751 self.RefreshPreview() |
|
752 event.Skip() |
|
753 |
|
754 def RefreshPreview(self): |
|
755 dc = wxClientDC(self.Preview) |
|
756 dc.Clear() |
|
757 name = self.Name.GetStringSelection() |
|
758 type = "" |
|
759 for var_name, var_type, value_type in self.VarList: |
|
760 if var_name == name: |
|
761 type = value_type |
|
762 classtype = self.Class.GetStringSelection() |
|
763 if classtype == "Input": |
|
764 self.Variable = FBD_Variable(self.Preview, INPUT, name, type) |
|
765 elif classtype == "Output": |
|
766 self.Variable = FBD_Variable(self.Preview, OUTPUT, name, type) |
|
767 elif classtype == "InOut": |
|
768 self.Variable = FBD_Variable(self.Preview, INOUT, name, type) |
|
769 width, height = self.MinVariableSize |
|
770 min_width, min_height = self.Variable.GetMinSize() |
|
771 width, height = max(min_width, width), max(min_height, height) |
|
772 self.Variable.SetSize(width, height) |
|
773 clientsize = self.Preview.GetClientSize() |
|
774 x = (clientsize.width - width) / 2 |
|
775 y = (clientsize.height - height) / 2 |
|
776 self.Variable.SetPosition(x, y) |
|
777 self.Variable.Draw(dc) |
|
778 |
|
779 def OnPaint(self, event): |
|
780 self.RefreshPreview() |
|
781 |
|
782 #------------------------------------------------------------------------------- |
|
783 # Create New Connection Dialog |
|
784 #------------------------------------------------------------------------------- |
|
785 |
|
786 [wxID_CONNECTIONPROPERTIESDIALOG, wxID_CONNECTIONPROPERTIESDIALOGMAINPANEL, |
|
787 wxID_CONNECTIONPROPERTIESDIALOGNAME, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, |
|
788 wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, wxID_CONNECTIONPROPERTIESDIALOGPREVIEW, |
|
789 wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT1, wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT2, |
|
790 wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT3, |
|
791 ] = [wx.NewId() for _init_ctrls in range(9)] |
|
792 |
|
793 class ConnectionPropertiesDialog(wx.Dialog): |
|
794 def _init_coll_flexGridSizer1_Items(self, parent): |
|
795 # generated method, don't edit |
|
796 |
|
797 parent.AddWindow(self.MainPanel, 0, border=0, flag=0) |
|
798 |
|
799 def _init_sizers(self): |
|
800 # generated method, don't edit |
|
801 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
|
802 |
|
803 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
804 |
|
805 self.SetSizer(self.flexGridSizer1) |
|
806 |
|
807 def _init_ctrls(self, prnt): |
|
808 # generated method, don't edit |
|
809 wx.Dialog.__init__(self, id=wxID_CONNECTIONPROPERTIESDIALOG, |
|
810 name='ConnectionPropertiesDialog', parent=prnt, pos=wx.Point(376, 223), |
|
811 size=wx.Size(350, 220), style=wx.DEFAULT_DIALOG_STYLE, |
|
812 title='Connection Properties') |
|
813 self.SetClientSize(wx.Size(350, 220)) |
|
814 |
|
815 self.MainPanel = wx.Panel(id=wxID_CONNECTIONPROPERTIESDIALOGMAINPANEL, |
|
816 name='MainPanel', parent=self, pos=wx.Point(0, 0), |
|
817 size=wx.Size(340, 360), style=wx.TAB_TRAVERSAL) |
|
818 self.MainPanel.SetAutoLayout(True) |
|
819 |
|
820 self.staticText1 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT1, |
|
821 label='Type:', name='staticText1', parent=self.MainPanel, |
|
822 pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) |
|
823 |
|
824 self.staticText2 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT2, |
|
825 label='Name:', name='staticText2', parent=self.MainPanel, |
|
826 pos=wx.Point(24, 104), size=wx.Size(70, 17), style=0) |
|
827 |
|
828 self.staticText3 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT3, |
|
829 label='Preview:', name='staticText3', parent=self.MainPanel, |
|
830 pos=wx.Point(174, 24), size=wx.Size(100, 17), style=0) |
|
831 |
|
832 self.radioButton1 = wx.RadioButton(id=wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, |
|
833 label='Connector', name='radioButton1', parent=self.MainPanel, |
|
834 pos=wx.Point(24, 48), size=wx.Size(114, 24), style=0) |
|
835 EVT_RADIOBUTTON(self, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, self.OnTypeChanged) |
|
836 self.radioButton1.SetValue(True) |
|
837 |
|
838 self.radioButton2 = wx.RadioButton(id=wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, |
|
839 label='Continuation', name='radioButton2', parent=self.MainPanel, |
|
840 pos=wx.Point(24, 72), size=wx.Size(128, 24), style=0) |
|
841 EVT_RADIOBUTTON(self, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, self.OnTypeChanged) |
|
842 self.radioButton2.SetValue(False) |
|
843 |
|
844 self.Name = wx.TextCtrl(id=wxID_CONNECTIONPROPERTIESDIALOGNAME, |
|
845 name='Name', parent=self.MainPanel, pos=wx.Point(24, 130), |
|
846 size=wx.Size(145, 24), style=0) |
|
847 EVT_TEXT(self, wxID_CONNECTIONPROPERTIESDIALOGNAME, self.OnNameChanged) |
|
848 |
|
849 self.Preview = wx.Panel(id=wxID_CONNECTIONPROPERTIESDIALOGPREVIEW, |
|
850 name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48), |
|
851 size=wx.Size(150, 100), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) |
|
852 self.Preview.SetBackgroundColour(wxColour(255,255,255)) |
|
853 |
|
854 self._init_sizers() |
|
855 |
|
856 def __init__(self, parent): |
|
857 self._init_ctrls(parent) |
|
858 self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) |
|
859 self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) |
|
860 self.Connection = None |
|
861 self.MinConnectionSize = None |
|
862 |
|
863 EVT_PAINT(self, self.OnPaint) |
|
864 |
|
865 def SetMinConnectionSize(self, size): |
|
866 self.MinConnectionSize = size |
|
867 |
|
868 def GetValues(self): |
|
869 values = {} |
|
870 if self.radioButton1.GetValue(): |
|
871 values["type"] = CONNECTOR |
|
872 else: |
|
873 values["type"] = CONTINUATION |
|
874 values["name"] = self.Name.GetValue() |
|
875 values["width"], values["height"] = self.Connection.GetSize() |
|
876 return values |
|
877 |
|
878 def OnTypeChanged(self, event): |
|
879 self.RefreshPreview() |
|
880 event.Skip() |
|
881 |
|
882 def OnNameChanged(self, event): |
|
883 self.RefreshPreview() |
|
884 event.Skip() |
|
885 |
|
886 def RefreshPreview(self): |
|
887 dc = wxClientDC(self.Preview) |
|
888 dc.Clear() |
|
889 if self.radioButton1.GetValue(): |
|
890 self.Connection = FBD_Connector(self.Preview, CONNECTOR, self.Name.GetValue()) |
|
891 else: |
|
892 self.Connection = FBD_Connector(self.Preview, CONTINUATION, self.Name.GetValue()) |
|
893 width, height = self.MinConnectionSize |
|
894 min_width, min_height = self.Connection.GetMinSize() |
|
895 width, height = max(min_width, width), max(min_height, height) |
|
896 self.Connection.SetSize(width, height) |
|
897 clientsize = self.Preview.GetClientSize() |
|
898 x = (clientsize.width - width) / 2 |
|
899 y = (clientsize.height - height) / 2 |
|
900 self.Connection.SetPosition(x, y) |
|
901 self.Connection.Draw(dc) |
|
902 |
|
903 def OnPaint(self, event): |
|
904 self.RefreshPreview() |
|
905 |
|