editors/Viewer.py
changeset 1911 c1298e7ffe3a
parent 1619 163d3a883575
child 1644 976ce8c6195d
equal deleted inserted replaced
1910:a375e31bf312 1911:c1298e7ffe3a
     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
    41 SCROLLBAR_UNIT = 10
    41 SCROLLBAR_UNIT = 10
    42 WINDOW_BORDER = 10
    42 WINDOW_BORDER = 10
    43 SCROLL_ZONE = 10
    43 SCROLL_ZONE = 10
    44 
    44 
    45 CURSORS = None
    45 CURSORS = None
       
    46 SFC_Objects = (SFC_Step, SFC_ActionBlock, SFC_Transition, SFC_Divergence, SFC_Jump)
    46 
    47 
    47 def ResetCursors():
    48 def ResetCursors():
    48     global CURSORS
    49     global CURSORS
    49     if CURSORS == None:
    50     if CURSORS == None:
    50         CURSORS = [wx.NullCursor,
    51         CURSORS = [wx.NullCursor,
   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: