1 #!/usr/bin/env python |
1 #!/usr/bin/env python |
2 # -*- coding: utf-8 -*- |
2 # -*- coding: utf-8 -*- |
3 |
3 |
4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor |
4 # This file is part of Beremiz, a Integrated Development Environment for |
5 #based on the plcopen standard. |
5 # programming IEC 61131-3 automates supporting plcopen standard and CanFestival. |
6 # |
6 # |
7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
7 # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
8 # |
8 # |
9 #See COPYING file for copyrights details. |
9 # See COPYING file for copyrights details. |
10 # |
10 # |
11 #This library is free software; you can redistribute it and/or |
11 # This program is free software; you can redistribute it and/or |
12 #modify it under the terms of the GNU General Public |
12 # modify it under the terms of the GNU General Public License |
13 #License as published by the Free Software Foundation; either |
13 # as published by the Free Software Foundation; either version 2 |
14 #version 2.1 of the License, or (at your option) any later version. |
14 # of the License, or (at your option) any later version. |
15 # |
15 # |
16 #This library is distributed in the hope that it will be useful, |
16 # This program is distributed in the hope that it will be useful, |
17 #but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 #General Public License for more details. |
19 # GNU General Public License for more details. |
20 # |
20 # |
21 #You should have received a copy of the GNU General Public |
21 # You should have received a copy of the GNU General Public License |
22 #License along with this library; if not, write to the Free Software |
22 # along with this program; if not, write to the Free Software |
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
24 |
24 |
25 import re |
25 import re |
26 import math |
26 import math |
27 from time import time as gettime |
27 from time import time as gettime |
28 from types import TupleType |
28 from types import TupleType |
143 def transitionCreationFunction(viewer, id, specific_values): |
144 def transitionCreationFunction(viewer, id, specific_values): |
144 transition = SFC_Transition(viewer, specific_values.condition_type, |
145 transition = SFC_Transition(viewer, specific_values.condition_type, |
145 specific_values.condition, |
146 specific_values.condition, |
146 specific_values.priority, id) |
147 specific_values.priority, id) |
147 return transition |
148 return transition |
|
149 |
|
150 divergence_types = [SELECTION_DIVERGENCE, |
|
151 SELECTION_CONVERGENCE, SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE] |
148 |
152 |
149 def GetDivergenceCreationFunction(divergence_type): |
153 def GetDivergenceCreationFunction(divergence_type): |
150 def divergenceCreationFunction(viewer, id, specific_values): |
154 def divergenceCreationFunction(viewer, id, specific_values): |
151 return SFC_Divergence(viewer, divergence_type, |
155 return SFC_Divergence(viewer, divergence_type, |
152 specific_values.connectors, id) |
156 specific_values.connectors, id) |
241 if pou_name == values[0]: |
245 if pou_name == values[0]: |
242 message = _("\"%s\" can't use itself!")%pou_name |
246 message = _("\"%s\" can't use itself!")%pou_name |
243 elif pou_type == "function" and values[1] != "function": |
247 elif pou_type == "function" and values[1] != "function": |
244 message = _("Function Blocks can't be used in Functions!") |
248 message = _("Function Blocks can't be used in Functions!") |
245 elif self.ParentWindow.Controler.PouIsUsedBy(pou_name, values[0], self.ParentWindow.Debug): |
249 elif self.ParentWindow.Controler.PouIsUsedBy(pou_name, values[0], self.ParentWindow.Debug): |
246 message = _("\"%s\" is already used by \"%s\"!")%(pou_name, values[0]) |
250 message = _("\"{a1}\" is already used by \"{a2}\"!").format(a1 = pou_name, a2 = values[0]) |
247 else: |
251 else: |
248 blockname = values[2] |
252 blockname = values[2] |
249 if len(values) > 3: |
253 if len(values) > 3: |
250 blockinputs = values[3] |
254 blockinputs = values[3] |
251 else: |
255 else: |
280 if pou_type == "program": |
284 if pou_type == "program": |
281 location = values[0] |
285 location = values[0] |
282 if not location.startswith("%"): |
286 if not location.startswith("%"): |
283 dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow, |
287 dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow, |
284 _("Select a variable class:"), _("Variable class"), |
288 _("Select a variable class:"), _("Variable class"), |
285 ["Input", "Output", "Memory"], |
289 [_("Input"), _("Output"), _("Memory")], |
286 wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL) |
290 wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL) |
287 if dialog.ShowModal() == wx.ID_OK: |
291 if dialog.ShowModal() == wx.ID_OK: |
288 selected = dialog.GetSelection() |
292 selected = dialog.GetSelection() |
289 else: |
293 else: |
290 selected = None |
294 selected = None |
299 location = "%M" + location |
303 location = "%M" + location |
300 var_name = values[3] |
304 var_name = values[3] |
301 dlg = wx.TextEntryDialog( |
305 dlg = wx.TextEntryDialog( |
302 self.ParentWindow.ParentWindow, |
306 self.ParentWindow.ParentWindow, |
303 _("Confirm or change variable name"), |
307 _("Confirm or change variable name"), |
304 'Variable Drop', var_name) |
308 _('Variable Drop'), var_name) |
305 dlg.SetValue(var_name) |
309 dlg.SetValue(var_name) |
306 var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None |
310 var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None |
307 dlg.Destroy() |
311 dlg.Destroy() |
308 if var_name is None: |
312 if var_name is None: |
309 return |
313 return |
329 initval = values[0] |
333 initval = values[0] |
330 var_name = values[3] |
334 var_name = values[3] |
331 dlg = wx.TextEntryDialog( |
335 dlg = wx.TextEntryDialog( |
332 self.ParentWindow.ParentWindow, |
336 self.ParentWindow.ParentWindow, |
333 _("Confirm or change variable name"), |
337 _("Confirm or change variable name"), |
334 'Variable Drop', var_name) |
338 _('Variable Drop'), var_name) |
335 dlg.SetValue(var_name) |
339 dlg.SetValue(var_name) |
336 var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None |
340 var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None |
337 dlg.Destroy() |
341 dlg.Destroy() |
338 if var_name is None: |
342 if var_name is None: |
339 return |
343 return |
351 elif values[1] == "Global": |
355 elif values[1] == "Global": |
352 var_name = values[0] |
356 var_name = values[0] |
353 dlg = wx.TextEntryDialog( |
357 dlg = wx.TextEntryDialog( |
354 self.ParentWindow.ParentWindow, |
358 self.ParentWindow.ParentWindow, |
355 _("Confirm or change variable name"), |
359 _("Confirm or change variable name"), |
356 'Variable Drop', var_name) |
360 _('Variable Drop'), var_name) |
357 dlg.SetValue(var_name) |
361 dlg.SetValue(var_name) |
358 var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None |
362 var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None |
359 dlg.Destroy() |
363 dlg.Destroy() |
360 if var_name is None: |
364 if var_name is None: |
361 return |
365 return |
571 |
575 |
572 else: |
576 else: |
573 [ID_CLEAR_EXEC_ORDER, ID_RESET_EXEC_ORDER] = [wx.NewId() for i in xrange(2)] |
577 [ID_CLEAR_EXEC_ORDER, ID_RESET_EXEC_ORDER] = [wx.NewId() for i in xrange(2)] |
574 |
578 |
575 # Create menu items |
579 # Create menu items |
576 self.AddMenuItems(menu, [ |
580 if self.CurrentLanguage == 'FBD': |
577 (ID_CLEAR_EXEC_ORDER, wx.ITEM_NORMAL, _(u'Clear Execution Order'), '', self.OnClearExecutionOrderMenu), |
581 self.AddMenuItems(menu, [ |
578 (ID_RESET_EXEC_ORDER, wx.ITEM_NORMAL, _(u'Reset Execution Order'), '', self.OnResetExecutionOrderMenu)]) |
582 (ID_CLEAR_EXEC_ORDER, wx.ITEM_NORMAL, _(u'Clear Execution Order'), '', self.OnClearExecutionOrderMenu), |
579 |
583 (ID_RESET_EXEC_ORDER, wx.ITEM_NORMAL, _(u'Reset Execution Order'), '', self.OnResetExecutionOrderMenu)]) |
580 menu.AppendSeparator() |
584 menu.AppendSeparator() |
581 |
585 |
582 add_menu = wx.Menu(title='') |
586 add_menu = wx.Menu(title='') |
583 self.AddAddMenuItems(add_menu) |
587 self.AddAddMenuItems(add_menu) |
584 menu.AppendMenu(-1, _(u'Add'), add_menu) |
588 menu.AppendMenu(-1, _(u'Add'), add_menu) |
585 |
589 |
598 menu.Enable(ID_PASTE, self.ParentWindow.GetCopyBuffer() is not None) |
602 menu.Enable(ID_PASTE, self.ParentWindow.GetCopyBuffer() is not None) |
599 |
603 |
600 def _init_Editor(self, prnt): |
604 def _init_Editor(self, prnt): |
601 self.Editor = wx.ScrolledWindow(prnt, name="Viewer", |
605 self.Editor = wx.ScrolledWindow(prnt, name="Viewer", |
602 pos=wx.Point(0, 0), size=wx.Size(0, 0), |
606 pos=wx.Point(0, 0), size=wx.Size(0, 0), |
603 style=wx.HSCROLL | wx.VSCROLL | wx.ALWAYS_SHOW_SB) |
607 style=wx.HSCROLL | wx.VSCROLL) |
604 self.Editor.ParentWindow = self |
608 self.Editor.ParentWindow = self |
605 |
609 |
606 # Create a new Viewer |
610 # Create a new Viewer |
607 def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""): |
611 def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""): |
608 self.VARIABLE_PANEL_TYPE = controler.GetPouType(tagname.split("::")[1]) |
612 self.VARIABLE_PANEL_TYPE = controler.GetPouType(tagname.split("::")[1]) |
755 self.Editor.Freeze() |
759 self.Editor.Freeze() |
756 if mouse_event is None: |
760 if mouse_event is None: |
757 client_size = self.Editor.GetClientSize() |
761 client_size = self.Editor.GetClientSize() |
758 mouse_pos = wx.Point(client_size[0] / 2, client_size[1] / 2) |
762 mouse_pos = wx.Point(client_size[0] / 2, client_size[1] / 2) |
759 mouse_event = wx.MouseEvent(wx.EVT_MOUSEWHEEL.typeId) |
763 mouse_event = wx.MouseEvent(wx.EVT_MOUSEWHEEL.typeId) |
760 mouse_event.m_x = mouse_pos.x |
764 mouse_event.x = mouse_pos.x |
761 mouse_event.m_y = mouse_pos.y |
765 mouse_event.y = mouse_pos.y |
762 else: |
766 else: |
763 mouse_pos = mouse_event.GetPosition() |
767 mouse_pos = mouse_event.GetPosition() |
764 pos = mouse_event.GetLogicalPosition(dc) |
768 pos = mouse_event.GetLogicalPosition(dc) |
765 xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL) |
769 xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL) |
766 ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL) |
770 ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL) |
881 wires.sort(lambda x, y: cmp(self.Wires[x], self.Wires[y])) |
885 wires.sort(lambda x, y: cmp(self.Wires[x], self.Wires[y])) |
882 if sort_comments: |
886 if sort_comments: |
883 comments.sort(lambda x, y: cmp(x.GetId(), y.GetId())) |
887 comments.sort(lambda x, y: cmp(x.GetId(), y.GetId())) |
884 return blocks + wires + comments |
888 return blocks + wires + comments |
885 |
889 |
|
890 def GetContinuationByName(self, name): |
|
891 blocks = [] |
|
892 for block in self.Blocks.itervalues(): |
|
893 if isinstance(block, FBD_Connector) and\ |
|
894 block.GetType() == CONTINUATION and\ |
|
895 block.GetName() == name: |
|
896 blocks.append(block) |
|
897 return blocks |
|
898 |
886 def GetConnectorByName(self, name): |
899 def GetConnectorByName(self, name): |
887 for block in self.Blocks.itervalues(): |
900 for block in self.Blocks.itervalues(): |
888 if isinstance(block, FBD_Connector) and\ |
901 if isinstance(block, FBD_Connector) and\ |
889 block.GetType() == CONNECTOR and\ |
902 block.GetType() == CONNECTOR and\ |
890 block.GetName() == name: |
903 block.GetName() == name: |
1460 if element.HitTest(pos, connectors) or element.TestHandle(event) != (0, 0): |
1473 if element.HitTest(pos, connectors) or element.TestHandle(event) != (0, 0): |
1461 return element |
1474 return element |
1462 return None |
1475 return None |
1463 |
1476 |
1464 def FindBlockConnector(self, pos, direction = None, exclude = None): |
1477 def FindBlockConnector(self, pos, direction = None, exclude = None): |
|
1478 result, error = self.FindBlockConnectorWithError(pos, direction, exclude) |
|
1479 return result |
|
1480 |
|
1481 def FindBlockConnectorWithError(self, pos, direction = None, exclude = None): |
|
1482 error = False |
|
1483 startblock = None |
1465 for block in self.Blocks.itervalues(): |
1484 for block in self.Blocks.itervalues(): |
1466 result = block.TestConnector(pos, direction, exclude) |
1485 connector = block.TestConnector(pos, direction, exclude) |
1467 if result: |
1486 if connector: |
1468 return result |
1487 if self.IsWire(self.SelectedElement): |
1469 return None |
1488 startblock = self.SelectedElement.StartConnected.GetParentBlock() |
1470 |
1489 avail, error = connector.ConnectionAvailable(direction, exclude) |
|
1490 if not avail or not self.BlockCompatibility(startblock, block, direction): |
|
1491 connector = None |
|
1492 error = True |
|
1493 return connector, error |
|
1494 return None, error |
|
1495 |
1471 def FindElementById(self, id): |
1496 def FindElementById(self, id): |
1472 block = self.Blocks.get(id, None) |
1497 block = self.Blocks.get(id, None) |
1473 if block is not None: |
1498 if block is not None: |
1474 return block |
1499 return block |
1475 comment = self.Comments.get(id, None) |
1500 comment = self.Comments.get(id, None) |
2046 self.SelectedElement.RefreshModel() |
2071 self.SelectedElement.RefreshModel() |
2047 self.SelectedElement.SetSelected(True) |
2072 self.SelectedElement.SetSelected(True) |
2048 self.SelectedElement.HighlightPoint(pos) |
2073 self.SelectedElement.HighlightPoint(pos) |
2049 self.RefreshBuffer() |
2074 self.RefreshBuffer() |
2050 elif connector is None or self.SelectedElement.GetDragging(): |
2075 elif connector is None or self.SelectedElement.GetDragging(): |
2051 start_connector = self.SelectedElement.GetStartConnected() |
2076 items = self.GetPopupMenuItems() |
2052 start_direction = start_connector.GetDirection() |
|
2053 |
|
2054 items = [] |
|
2055 |
|
2056 if self.CurrentLanguage == "SFC" and start_direction == SOUTH: |
|
2057 items.extend([ |
|
2058 (_(u'Initial Step'), self.GetAddToWireMenuCallBack(self.AddNewStep, True)), |
|
2059 (_(u'Step'), self.GetAddToWireMenuCallBack(self.AddNewStep, False)), |
|
2060 (_(u'Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, False)), |
|
2061 (_(u'Divergence'), self.GetAddToWireMenuCallBack(self.AddNewDivergence)), |
|
2062 (_(u'Jump'), self.GetAddToWireMenuCallBack(self.AddNewJump)), |
|
2063 ]) |
|
2064 |
|
2065 elif start_direction == EAST: |
|
2066 |
|
2067 if isinstance(start_connector.GetParentBlock(), SFC_Step): |
|
2068 items.append( |
|
2069 (_(u'Action Block'), self.GetAddToWireMenuCallBack(self.AddNewActionBlock)) |
|
2070 ) |
|
2071 else: |
|
2072 items.extend([ |
|
2073 (_(u'Block'), self.GetAddToWireMenuCallBack(self.AddNewBlock)), |
|
2074 (_(u'Variable'), self.GetAddToWireMenuCallBack(self.AddNewVariable, True)), |
|
2075 (_(u'Connection'), self.GetAddToWireMenuCallBack(self.AddNewConnection)), |
|
2076 ]) |
|
2077 |
|
2078 if self.CurrentLanguage != "FBD": |
|
2079 items.append( |
|
2080 (_(u'Contact'), self.GetAddToWireMenuCallBack(self.AddNewContact)) |
|
2081 ) |
|
2082 if self.CurrentLanguage == "LD": |
|
2083 items.extend([ |
|
2084 (_(u'Coil'), self.GetAddToWireMenuCallBack(self.AddNewCoil)), |
|
2085 (_(u'Power Rail'), self.GetAddToWireMenuCallBack(self.AddNewPowerRail)), |
|
2086 ]) |
|
2087 if self.CurrentLanguage == "SFC": |
|
2088 items.append( |
|
2089 (_(u'Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, True)) |
|
2090 ) |
|
2091 |
|
2092 if len(items) > 0: |
2077 if len(items) > 0: |
2093 if self.Editor.HasCapture(): |
2078 if self.Editor.HasCapture(): |
2094 self.Editor.ReleaseMouse() |
2079 self.Editor.ReleaseMouse() |
2095 |
2080 |
2096 # Popup contextual menu |
2081 # Popup contextual menu |
2271 self.HighlightedElement = highlighted |
2256 self.HighlightedElement = highlighted |
2272 if self.rubberBand.IsShown(): |
2257 if self.rubberBand.IsShown(): |
2273 self.rubberBand.OnMotion(event, dc, self.Scaling) |
2258 self.rubberBand.OnMotion(event, dc, self.Scaling) |
2274 elif not self.Debug and self.Mode == MODE_SELECTION and self.SelectedElement is not None: |
2259 elif not self.Debug and self.Mode == MODE_SELECTION and self.SelectedElement is not None: |
2275 if self.DrawingWire: |
2260 if self.DrawingWire: |
2276 connector = self.FindBlockConnector(pos, self.SelectedElement.GetConnectionDirection(), self.SelectedElement.EndConnected) |
2261 connector, errorHighlight = self.FindBlockConnectorWithError(pos, self.SelectedElement.GetConnectionDirection(), self.SelectedElement.EndConnected) |
|
2262 self.SelectedElement.ErrHighlight = errorHighlight; |
2277 if not connector or self.SelectedElement.EndConnected == None: |
2263 if not connector or self.SelectedElement.EndConnected == None: |
2278 self.SelectedElement.ResetPoints() |
2264 self.SelectedElement.ResetPoints() |
2279 movex, movey = self.SelectedElement.OnMotion(event, dc, self.Scaling) |
2265 movex, movey = self.SelectedElement.OnMotion(event, dc, self.Scaling) |
2280 self.SelectedElement.GeneratePoints() |
2266 self.SelectedElement.GeneratePoints() |
2281 if movex != 0 or movey != 0: |
2267 if movex != 0 or movey != 0: |
2337 move_window.y = 1 |
2323 move_window.y = 1 |
2338 if move_window.x != 0 or move_window.y != 0: |
2324 if move_window.x != 0 or move_window.y != 0: |
2339 self.RefreshVisibleElements(xp = xstart + move_window.x, yp = ystart + move_window.y) |
2325 self.RefreshVisibleElements(xp = xstart + move_window.x, yp = ystart + move_window.y) |
2340 self.Scroll(xstart + move_window.x, ystart + move_window.y) |
2326 self.Scroll(xstart + move_window.x, ystart + move_window.y) |
2341 self.RefreshScrollBars(move_window.x, move_window.y) |
2327 self.RefreshScrollBars(move_window.x, move_window.y) |
|
2328 |
|
2329 def BlockCompatibility(self, startblock=None, endblock=None, direction = None): |
|
2330 return True |
|
2331 |
|
2332 def GetPopupMenuItems(self): |
|
2333 start_connector = self.SelectedElement.GetStartConnected() |
|
2334 start_direction = start_connector.GetDirection() |
|
2335 startblock = start_connector.GetParentBlock() |
|
2336 items = [] |
|
2337 if isinstance(startblock, SFC_Objects): |
|
2338 startblockname = self.GetBlockName(startblock) |
|
2339 poss_div_types = [] |
|
2340 |
|
2341 SFC_WireMenu_Buttons = { |
|
2342 'SFC_Step': (_(u'Step'), self.GetAddToWireMenuCallBack(self.AddNewStep, False)), |
|
2343 'SFC_Jump': (_(u'Jump'), self.GetAddToWireMenuCallBack(self.AddNewJump)), |
|
2344 'SFC_Transition': (_(u'Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, False)), |
|
2345 'SFC_ActionBlock': (_(u'Action Block'), self.GetAddToWireMenuCallBack(self.AddNewActionBlock))} |
|
2346 |
|
2347 for endblock in self.SFC_StandardRules.get(startblockname): |
|
2348 if start_direction in endblock: |
|
2349 if endblock[0] in divergence_types: |
|
2350 poss_div_types.append(endblock[0]) |
|
2351 else: |
|
2352 items.append(SFC_WireMenu_Buttons[endblock[0]]) |
|
2353 if len(poss_div_types) > 0: |
|
2354 items.append((_(u'Divergence'), self.GetAddToWireMenuCallBack(self.AddNewDivergence, |
|
2355 poss_div_types))) |
|
2356 elif start_direction == EAST: |
|
2357 items.extend([ |
|
2358 (_(u'Block'), self.GetAddToWireMenuCallBack(self.AddNewBlock)), |
|
2359 (_(u'Connection'), self.GetAddToWireMenuCallBack(self.AddNewConnection))]) |
|
2360 |
|
2361 if self.CurrentLanguage != "FBD": |
|
2362 items.append((_(u'Contact'), self.GetAddToWireMenuCallBack(self.AddNewContact))) |
|
2363 |
|
2364 if self.CurrentLanguage == "LD": |
|
2365 items.extend([ |
|
2366 (_(u'Coil'), self.GetAddToWireMenuCallBack(self.AddNewCoil)), |
|
2367 (_(u'Power Rail'), self.GetAddToWireMenuCallBack(self.AddNewPowerRail))]) |
|
2368 |
|
2369 if self.CurrentLanguage == "SFC": |
|
2370 items.append( |
|
2371 (_(u'Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, True))) |
|
2372 else: |
|
2373 items.append( |
|
2374 (_(u'Variable'), self.GetAddToWireMenuCallBack(self.AddNewVariable, True))) |
|
2375 return items |
2342 |
2376 |
2343 #------------------------------------------------------------------------------- |
2377 #------------------------------------------------------------------------------- |
2344 # Keyboard event functions |
2378 # Keyboard event functions |
2345 #------------------------------------------------------------------------------- |
2379 #------------------------------------------------------------------------------- |
2346 |
2380 |
2396 self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False) |
2430 self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False) |
2397 elif not self.Debug and keycode == wx.WXK_SPACE and self.SelectedElement is not None and self.SelectedElement.Dragging: |
2431 elif not self.Debug and keycode == wx.WXK_SPACE and self.SelectedElement is not None and self.SelectedElement.Dragging: |
2398 if self.IsBlock(self.SelectedElement) or self.IsComment(self.SelectedElement): |
2432 if self.IsBlock(self.SelectedElement) or self.IsComment(self.SelectedElement): |
2399 block = self.CopyBlock(self.SelectedElement, wx.Point(*self.SelectedElement.GetPosition())) |
2433 block = self.CopyBlock(self.SelectedElement, wx.Point(*self.SelectedElement.GetPosition())) |
2400 event = wx.MouseEvent() |
2434 event = wx.MouseEvent() |
2401 event.m_x, event.m_y = self.Editor.ScreenToClient(wx.GetMousePosition()) |
2435 event.x, event.y = self.Editor.ScreenToClient(wx.GetMousePosition()) |
2402 dc = self.GetLogicalDC() |
2436 dc = self.GetLogicalDC() |
2403 self.SelectedElement.OnLeftUp(event, dc, self.Scaling) |
2437 self.SelectedElement.OnLeftUp(event, dc, self.Scaling) |
2404 self.SelectedElement.SetSelected(False) |
2438 self.SelectedElement.SetSelected(False) |
2405 block.OnLeftDown(event, dc, self.Scaling) |
2439 block.OnLeftDown(event, dc, self.Scaling) |
2406 self.SelectedElement = block |
2440 self.SelectedElement = block |
2605 if wire is not None: |
2639 if wire is not None: |
2606 values = { |
2640 values = { |
2607 "name": self.Controler.GenerateNewName( |
2641 "name": self.Controler.GenerateNewName( |
2608 self.TagName, None, "Step%d", 0), |
2642 self.TagName, None, "Step%d", 0), |
2609 "input": True, |
2643 "input": True, |
2610 "output": False, |
2644 "output": True, |
2611 "action":False} |
2645 "action":False} |
2612 else: |
2646 else: |
2613 dialog = SFCStepDialog(self.ParentWindow, self.Controler, self.TagName, initial) |
2647 dialog = SFCStepDialog(self.ParentWindow, self.Controler, self.TagName, initial) |
2614 dialog.SetPreviewFont(self.GetFont()) |
2648 dialog.SetPreviewFont(self.GetFont()) |
2615 dialog.SetMinElementSize((bbox.width, bbox.height)) |
2649 dialog.SetMinElementSize((bbox.width, bbox.height)) |
2649 connector = transition.GetConditionConnector() |
2683 connector = transition.GetConditionConnector() |
2650 else: |
2684 else: |
2651 connector = transition.GetConnectors()["inputs"][0] |
2685 connector = transition.GetConnectors()["inputs"][0] |
2652 self.AddNewElement(transition, bbox, wire, connector) |
2686 self.AddNewElement(transition, bbox, wire, connector) |
2653 |
2687 |
2654 def AddNewDivergence(self, bbox, wire=None): |
2688 def AddNewDivergence(self, bbox, poss_div_types = None, wire=None): |
2655 dialog = SFCDivergenceDialog(self.ParentWindow, self.Controler, self.TagName) |
2689 dialog = SFCDivergenceDialog(self.ParentWindow, self.Controler, self.TagName, poss_div_types) |
2656 dialog.SetPreviewFont(self.GetFont()) |
2690 dialog.SetPreviewFont(self.GetFont()) |
2657 dialog.SetMinElementSize((bbox.width, bbox.height)) |
2691 dialog.SetMinElementSize((bbox.width, bbox.height)) |
2658 if dialog.ShowModal() == wx.ID_OK: |
2692 if dialog.ShowModal() == wx.ID_OK: |
2659 id = self.GetNewId() |
2693 id = self.GetNewId() |
2660 values = dialog.GetValues() |
2694 values = dialog.GetValues() |
2866 "output": len(connectors["outputs"]) > 0, |
2900 "output": len(connectors["outputs"]) > 0, |
2867 "action": step.GetActionConnector() != None}) |
2901 "action": step.GetActionConnector() != None}) |
2868 if dialog.ShowModal() == wx.ID_OK: |
2902 if dialog.ShowModal() == wx.ID_OK: |
2869 values = dialog.GetValues() |
2903 values = dialog.GetValues() |
2870 rect = step.GetRedrawRect(1, 1) |
2904 rect = step.GetRedrawRect(1, 1) |
2871 step.SetName(values["name"]) |
2905 |
|
2906 new_name = values["name"] |
|
2907 if self.GetDrawingMode() == DRIVENDRAWING_MODE: |
|
2908 old_name = step.GetName().upper() |
|
2909 if new_name.upper() != old_name: |
|
2910 for block in self.Blocks.itervalues(): |
|
2911 if isinstance(block, SFC_Jump): |
|
2912 if old_name == block.GetTarget().upper(): |
|
2913 block.SetTarget(new_name) |
|
2914 block.RefreshModel() |
|
2915 rect = rect.Union(block.GetRedrawRect()) |
|
2916 block.Refresh(rect) |
|
2917 step.SetName(new_name) |
|
2918 |
2872 if values["input"]: |
2919 if values["input"]: |
2873 step.AddInput() |
2920 step.AddInput() |
2874 else: |
2921 else: |
2875 step.RemoveInput() |
2922 step.RemoveInput() |
2876 if values["output"]: |
2923 if values["output"]: |
2913 if isinstance(block, SFC_Step): |
2960 if isinstance(block, SFC_Step): |
2914 choices.append(block.GetName()) |
2961 choices.append(block.GetName()) |
2915 dialog = wx.SingleChoiceDialog(self.ParentWindow, |
2962 dialog = wx.SingleChoiceDialog(self.ParentWindow, |
2916 _("Edit jump target"), _("Please choose a target"), |
2963 _("Edit jump target"), _("Please choose a target"), |
2917 choices, wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL) |
2964 choices, wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL) |
2918 dialog.SetSelection(choices.index(jump.GetTarget())) |
2965 try: |
|
2966 indx = choices.index(jump.GetTarget()) |
|
2967 dialog.SetSelection(indx) |
|
2968 except ValueError: |
|
2969 pass |
|
2970 |
2919 if dialog.ShowModal() == wx.ID_OK: |
2971 if dialog.ShowModal() == wx.ID_OK: |
2920 value = dialog.GetStringSelection() |
2972 value = dialog.GetStringSelection() |
2921 rect = jump.GetRedrawRect(1, 1) |
2973 rect = jump.GetRedrawRect(1, 1) |
2922 jump.SetTarget(value) |
2974 jump.SetTarget(value) |
2923 rect = rect.Union(jump.GetRedrawRect()) |
2975 rect = rect.Union(jump.GetRedrawRect()) |
3214 if action_connector is not None: |
3266 if action_connector is not None: |
3215 for element in action_connector.GetConnectedBlocks(): |
3267 for element in action_connector.GetConnectedBlocks(): |
3216 if element not in elements: |
3268 if element not in elements: |
3217 elements.append(element) |
3269 elements.append(element) |
3218 step.Clean() |
3270 step.Clean() |
|
3271 |
|
3272 if self.GetDrawingMode() == DRIVENDRAWING_MODE: |
|
3273 name = step.GetName().upper() |
|
3274 remove_jumps = [] |
|
3275 for block in self.Blocks.itervalues(): |
|
3276 if isinstance(block, SFC_Jump): |
|
3277 if name == block.GetTarget().upper(): |
|
3278 remove_jumps.append(block) |
|
3279 for jump in remove_jumps: |
|
3280 self.DeleteJump(jump) |
|
3281 |
3219 self.RemoveBlock(step) |
3282 self.RemoveBlock(step) |
3220 self.Controler.RemoveEditedElementInstance(self.TagName, step.GetId()) |
3283 self.Controler.RemoveEditedElementInstance(self.TagName, step.GetId()) |
3221 for element in elements: |
3284 for element in elements: |
3222 element.RefreshModel() |
3285 element.RefreshModel() |
3223 |
3286 |
3397 def Find(self, direction, search_params): |
3460 def Find(self, direction, search_params): |
3398 if self.SearchParams != search_params: |
3461 if self.SearchParams != search_params: |
3399 self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT) |
3462 self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT) |
3400 |
3463 |
3401 self.SearchParams = search_params |
3464 self.SearchParams = search_params |
3402 criteria = { |
|
3403 "raw_pattern": search_params["find_pattern"], |
|
3404 "pattern": re.compile(search_params["find_pattern"]), |
|
3405 "case_sensitive": search_params["case_sensitive"], |
|
3406 "regular_expression": search_params["regular_expression"], |
|
3407 "filter": "all"} |
|
3408 |
|
3409 self.SearchResults = [] |
3465 self.SearchResults = [] |
3410 blocks = [] |
3466 blocks = [] |
3411 for infos, start, end, text in self.Controler.SearchInPou(self.TagName, criteria, self.Debug): |
3467 for infos, start, end, text in self.Controler.SearchInPou(self.TagName, search_params, self.Debug): |
3412 if infos[1] in ["var_local", "var_input", "var_output", "var_inout"]: |
3468 if (infos[0] == self.TagName or self.TagName.split("::")[0] in ['A', 'T']) and infos[1] is not 'name': |
3413 self.SearchResults.append((infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)) |
3469 if infos[1] in ["var_local", "var_input", "var_output", "var_inout"]: |
3414 else: |
3470 self.SearchResults.append((infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)) |
3415 block = self.Blocks.get(infos[2]) |
3471 else: |
3416 if block is not None: |
3472 block = self.Blocks.get(infos[2]) |
3417 blocks.append((block, (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT))) |
3473 if block is not None: |
|
3474 blocks.append((block, (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT))) |
3418 blocks.sort(sort_blocks) |
3475 blocks.sort(sort_blocks) |
3419 self.SearchResults.extend([infos for block, infos in blocks]) |
3476 self.SearchResults.extend([infos for block, infos in blocks]) |
3420 self.CurrentFindHighlight = None |
3477 self.CurrentFindHighlight = None |
3421 |
3478 |
3422 if len(self.SearchResults) > 0: |
3479 if len(self.SearchResults) > 0: |