editors/Viewer.py
branch1.1 Korean release
changeset 968 eee7625de1f7
parent 940 0c68d1af821d
child 980 c7ba67d01d65
equal deleted inserted replaced
808:6e205c1f05a0 968:eee7625de1f7
       
     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) 2007: 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 #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 import re
       
    26 import math
       
    27 import time
       
    28 from types import TupleType
       
    29 from threading import Lock
       
    30 
       
    31 import wx
       
    32 
       
    33 from plcopen.structures import *
       
    34 from PLCControler import ITEM_VAR_LOCAL, ITEM_POU, ITEM_PROGRAM, ITEM_FUNCTIONBLOCK
       
    35 
       
    36 from dialogs import *
       
    37 from graphics import *
       
    38 from EditorPanel import EditorPanel
       
    39 
       
    40 SCROLLBAR_UNIT = 10
       
    41 WINDOW_BORDER = 10
       
    42 SCROLL_ZONE = 10
       
    43 
       
    44 CURSORS = None
       
    45 
       
    46 def ResetCursors():
       
    47     global CURSORS
       
    48     if CURSORS == None:
       
    49         CURSORS = [wx.NullCursor, 
       
    50                    wx.StockCursor(wx.CURSOR_HAND),
       
    51                    wx.StockCursor(wx.CURSOR_SIZENWSE),
       
    52                    wx.StockCursor(wx.CURSOR_SIZENESW),
       
    53                    wx.StockCursor(wx.CURSOR_SIZEWE),
       
    54                    wx.StockCursor(wx.CURSOR_SIZENS)]
       
    55 
       
    56 def AppendMenu(parent, help, id, kind, text):
       
    57     if wx.VERSION >= (2, 6, 0):
       
    58         parent.Append(help=help, id=id, kind=kind, text=text)
       
    59     else:
       
    60         parent.Append(helpString=help, id=id, kind=kind, item=text)
       
    61 
       
    62 if wx.Platform == '__WXMSW__':
       
    63     faces = { 'times': 'Times New Roman',
       
    64               'mono' : 'Courier New',
       
    65               'helv' : 'Arial',
       
    66               'other': 'Comic Sans MS',
       
    67               'size' : 10,
       
    68              }
       
    69 else:
       
    70     faces = { 'times': 'Times',
       
    71               'mono' : 'Courier',
       
    72               'helv' : 'Helvetica',
       
    73               'other': 'new century schoolbook',
       
    74               'size' : 12,
       
    75              }
       
    76 
       
    77 ZOOM_FACTORS = [math.sqrt(2) ** x for x in xrange(-6, 7)]
       
    78 
       
    79 def GetVariableCreationFunction(variable_type):
       
    80     def variableCreationFunction(viewer, id, specific_values):
       
    81         return FBD_Variable(viewer, variable_type, 
       
    82                                     specific_values["name"], 
       
    83                                     specific_values["value_type"], 
       
    84                                     id,
       
    85                                     specific_values["executionOrder"])
       
    86     return variableCreationFunction
       
    87 
       
    88 def GetConnectorCreationFunction(connector_type):
       
    89     def connectorCreationFunction(viewer, id, specific_values):
       
    90         return FBD_Connector(viewer, connector_type, 
       
    91                                      specific_values["name"], id)
       
    92     return connectorCreationFunction
       
    93 
       
    94 def commentCreationFunction(viewer, id, specific_values):
       
    95     return Comment(viewer, specific_values["content"], id)
       
    96 
       
    97 def GetPowerRailCreationFunction(powerrail_type):
       
    98     def powerRailCreationFunction(viewer, id, specific_values):
       
    99         return LD_PowerRail(viewer, powerrail_type, id, 
       
   100                                     specific_values["connectors"])
       
   101     return powerRailCreationFunction
       
   102 
       
   103 CONTACT_TYPES = {(True, "none"): CONTACT_REVERSE,
       
   104                  (False, "rising"): CONTACT_RISING,
       
   105                  (False, "falling"): CONTACT_FALLING}
       
   106 
       
   107 def contactCreationFunction(viewer, id, specific_values):
       
   108     contact_type = CONTACT_TYPES.get((specific_values.get("negated", False), 
       
   109                                       specific_values.get("edge", "none")),
       
   110                                      CONTACT_NORMAL)
       
   111     return LD_Contact(viewer, contact_type, specific_values["name"], id)
       
   112 
       
   113 COIL_TYPES = {(True, "none", "none"): COIL_REVERSE,
       
   114               (False, "none", "set"): COIL_SET,
       
   115               (False, "none", "reset"): COIL_RESET,
       
   116               (False, "rising", "none"): COIL_RISING,
       
   117               (False, "falling", "none"): COIL_FALLING}
       
   118 
       
   119 def coilCreationFunction(viewer, id, specific_values):
       
   120     coil_type = COIL_TYPES.get((specific_values.get("negated", False), 
       
   121                                 specific_values.get("edge", "none"),
       
   122                                 specific_values.get("storage", "none")),
       
   123                                COIL_NORMAL)
       
   124     return LD_Coil(viewer, coil_type, specific_values["name"], id)
       
   125 
       
   126 def stepCreationFunction(viewer, id, specific_values):
       
   127     step = SFC_Step(viewer, specific_values["name"], 
       
   128                             specific_values.get("initial", False), id)
       
   129     if specific_values.get("action", None):
       
   130         step.AddAction()
       
   131         connector = step.GetActionConnector()
       
   132         connector.SetPosition(wx.Point(*specific_values["action"]["position"]))
       
   133     return step
       
   134 
       
   135 def transitionCreationFunction(viewer, id, specific_values):
       
   136     transition = SFC_Transition(viewer, specific_values["condition_type"], 
       
   137                                         specific_values.get("condition", None), 
       
   138                                         specific_values["priority"], id)
       
   139     return transition
       
   140 
       
   141 def GetDivergenceCreationFunction(divergence_type):
       
   142     def divergenceCreationFunction(viewer, id, specific_values):
       
   143         return SFC_Divergence(viewer, divergence_type, 
       
   144                                       specific_values["connectors"], id)
       
   145     return divergenceCreationFunction
       
   146 
       
   147 def jumpCreationFunction(viewer, id, specific_values):
       
   148     return SFC_Jump(viewer, specific_values["target"], id)
       
   149 
       
   150 def actionBlockCreationFunction(viewer, id, specific_values):
       
   151     return SFC_ActionBlock(viewer, specific_values["actions"], id)
       
   152 
       
   153 ElementCreationFunctions = {
       
   154     "input": GetVariableCreationFunction(INPUT),
       
   155     "output": GetVariableCreationFunction(OUTPUT),
       
   156     "inout": GetVariableCreationFunction(INOUT),
       
   157     "connector": GetConnectorCreationFunction(CONNECTOR),
       
   158     "continuation": GetConnectorCreationFunction(CONTINUATION),
       
   159     "comment": commentCreationFunction,
       
   160     "leftPowerRail": GetPowerRailCreationFunction(LEFTRAIL),
       
   161     "rightPowerRail": GetPowerRailCreationFunction(RIGHTRAIL),
       
   162     "contact": contactCreationFunction,
       
   163     "coil": coilCreationFunction,
       
   164     "step": stepCreationFunction, 
       
   165     "transition": transitionCreationFunction,
       
   166     "selectionDivergence": GetDivergenceCreationFunction(SELECTION_DIVERGENCE), 
       
   167     "selectionConvergence": GetDivergenceCreationFunction(SELECTION_CONVERGENCE), 
       
   168     "simultaneousDivergence": GetDivergenceCreationFunction(SIMULTANEOUS_DIVERGENCE), 
       
   169     "simultaneousConvergence": GetDivergenceCreationFunction(SIMULTANEOUS_CONVERGENCE), 
       
   170     "jump": jumpCreationFunction,
       
   171     "actionBlock": actionBlockCreationFunction,
       
   172 }
       
   173 
       
   174 def sort_blocks(block_infos1, block_infos2):
       
   175     x1, y1 = block_infos1[0].GetPosition()
       
   176     x2, y2 = block_infos2[0].GetPosition()
       
   177     if y1 == y2:
       
   178         return cmp(x1, x2)
       
   179     else:
       
   180         return cmp(y1, y2)
       
   181 
       
   182 #-------------------------------------------------------------------------------
       
   183 #                       Graphic elements Viewer base class
       
   184 #-------------------------------------------------------------------------------
       
   185 
       
   186 # ID Constants for alignment menu items
       
   187 [ID_VIEWERALIGNMENTMENUITEMS0, ID_VIEWERALIGNMENTMENUITEMS1,
       
   188  ID_VIEWERALIGNMENTMENUITEMS2, ID_VIEWERALIGNMENTMENUITEMS4,
       
   189  ID_VIEWERALIGNMENTMENUITEMS5, ID_VIEWERALIGNMENTMENUITEMS6,
       
   190 ] = [wx.NewId() for _init_coll_AlignmentMenu_Items in range(6)]
       
   191 
       
   192 # ID Constants for contextual menu items
       
   193 [ID_VIEWERCONTEXTUALMENUITEMS0, ID_VIEWERCONTEXTUALMENUITEMS1,
       
   194  ID_VIEWERCONTEXTUALMENUITEMS2, ID_VIEWERCONTEXTUALMENUITEMS3,
       
   195  ID_VIEWERCONTEXTUALMENUITEMS5, ID_VIEWERCONTEXTUALMENUITEMS6,
       
   196  ID_VIEWERCONTEXTUALMENUITEMS8, ID_VIEWERCONTEXTUALMENUITEMS9,
       
   197  ID_VIEWERCONTEXTUALMENUITEMS11, ID_VIEWERCONTEXTUALMENUITEMS12,
       
   198  ID_VIEWERCONTEXTUALMENUITEMS14, ID_VIEWERCONTEXTUALMENUITEMS16,
       
   199  ID_VIEWERCONTEXTUALMENUITEMS17,
       
   200 ] = [wx.NewId() for _init_coll_ContextualMenu_Items in range(13)]
       
   201 
       
   202 
       
   203 class ViewerDropTarget(wx.TextDropTarget):
       
   204     
       
   205     def __init__(self, parent):
       
   206         wx.TextDropTarget.__init__(self)
       
   207         self.ParentWindow = parent
       
   208     
       
   209     def OnDropText(self, x, y, data):
       
   210         self.ParentWindow.Select()
       
   211         tagname = self.ParentWindow.GetTagName()
       
   212         pou_name, pou_type = self.ParentWindow.Controler.GetEditedElementType(tagname, self.ParentWindow.Debug)
       
   213         x, y = self.ParentWindow.CalcUnscrolledPosition(x, y)
       
   214         x = int(x / self.ParentWindow.ViewScale[0])
       
   215         y = int(y / self.ParentWindow.ViewScale[1])
       
   216         scaling = self.ParentWindow.Scaling
       
   217         message = None
       
   218         try:
       
   219             values = eval(data)
       
   220         except:
       
   221             message = _("Invalid value \"%s\" for viewer block")%data
       
   222             values = None
       
   223         if not isinstance(values, TupleType):
       
   224             message = _("Invalid value \"%s\" for viewer block")%data
       
   225             values = None
       
   226         if values is not None:
       
   227             if values[1] == "debug":
       
   228                 pass
       
   229             elif values[1] == "program":
       
   230                 message = _("Programs can't be used by other POUs!")
       
   231             elif values[1] in ["function", "functionBlock"]:
       
   232                 words = tagname.split("::")
       
   233                 if pou_name == values[0]:
       
   234                     message = _("\"%s\" can't use itself!")%pou_name
       
   235                 elif pou_type == "function" and values[1] != "function":
       
   236                     message = _("Function Blocks can't be used in Functions!")
       
   237                 elif self.ParentWindow.Controler.PouIsUsedBy(pou_name, values[0], self.ParentWindow.Debug):
       
   238                     message = _("\"%s\" is already used by \"%s\"!")%(pou_name, values[0])
       
   239                 else:
       
   240                     blockname = values[2]
       
   241                     if len(values) > 3:
       
   242                         blockinputs = values[3]
       
   243                     else:
       
   244                         blockinputs = None
       
   245                     if values[1] != "function" and blockname == "":
       
   246                         blockname = self.ParentWindow.GenerateNewName(blocktype=values[0])
       
   247                     if blockname.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
       
   248                         message = _("\"%s\" pou already exists!")%blockname
       
   249                     elif blockname.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
       
   250                         message = _("\"%s\" element for this pou already exists!")%blockname
       
   251                     else:
       
   252                         id = self.ParentWindow.GetNewId()
       
   253                         block = FBD_Block(self.ParentWindow, values[0], blockname, id, inputs = blockinputs)
       
   254                         width, height = block.GetMinSize()
       
   255                         if scaling is not None:
       
   256                             x = round(float(x) / float(scaling[0])) * scaling[0]
       
   257                             y = round(float(y) / float(scaling[1])) * scaling[1]
       
   258                             width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
       
   259                             height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
       
   260                         block.SetPosition(x, y)
       
   261                         block.SetSize(width, height)
       
   262                         self.ParentWindow.AddBlock(block)
       
   263                         self.ParentWindow.Controler.AddEditedElementBlock(tagname, id, values[0], blockname)
       
   264                         self.ParentWindow.RefreshBlockModel(block)
       
   265                         self.ParentWindow.RefreshBuffer()
       
   266                         self.ParentWindow.RefreshScrollBars()
       
   267                         self.ParentWindow.RefreshVisibleElements()
       
   268                         self.ParentWindow.RefreshVariablePanel()
       
   269                         self.ParentWindow.Refresh(False)
       
   270             elif values[1] == "location":
       
   271                 if pou_type == "program":
       
   272                     location = values[0]
       
   273                     if not location.startswith("%"):
       
   274                         dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow, 
       
   275                               _("Select a variable class:"), _("Variable class"), 
       
   276                               ["Input", "Output", "Memory"], 
       
   277                               wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
       
   278                         if dialog.ShowModal() == wx.ID_OK:
       
   279                             selected = dialog.GetSelection()
       
   280                         else:
       
   281                             selected = None
       
   282                         dialog.Destroy()
       
   283                         if selected is None:
       
   284                             return
       
   285                         if selected == 0:
       
   286                             location = "%I" + location
       
   287                         elif selected == 1:
       
   288                             location = "%Q" + location
       
   289                         else:
       
   290                             location = "%M" + location
       
   291                     var_name = values[3]
       
   292                     if var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
       
   293                         message = _("\"%s\" pou already exists!")%var_name
       
   294                     else:
       
   295                         if location[1] == "Q":
       
   296                             var_class = OUTPUT
       
   297                         else:
       
   298                             var_class = INPUT
       
   299                         if values[2] is not None:
       
   300                             var_type = values[2]
       
   301                         else:
       
   302                             var_type = LOCATIONDATATYPES.get(location[2], ["BOOL"])[0]
       
   303                         if not var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
       
   304                             self.ParentWindow.Controler.AddEditedElementPouVar(tagname, var_type, var_name, location, values[4])
       
   305                             self.ParentWindow.RefreshVariablePanel()
       
   306                             self.ParentWindow.ParentWindow.RefreshPouInstanceVariablesPanel()
       
   307                         self.ParentWindow.AddVariableBlock(x, y, scaling, var_class, var_name, var_type)
       
   308             elif values[1] == "Global":
       
   309                 var_name = values[0]
       
   310                 if var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
       
   311                     message = _("\"%s\" pou already exists!")%var_name
       
   312                 else:
       
   313                     if not var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
       
   314                         self.ParentWindow.Controler.AddEditedElementPouExternalVar(tagname, values[2], var_name)
       
   315                         self.ParentWindow.RefreshVariablePanel()
       
   316                     self.ParentWindow.AddVariableBlock(x, y, scaling, INPUT, var_name, values[2])
       
   317             elif values[1] == "Constant":
       
   318                 self.ParentWindow.AddVariableBlock(x, y, scaling, INPUT, values[0], None)
       
   319             elif values[3] == tagname:
       
   320                 if values[1] == "Output":
       
   321                     var_class = OUTPUT
       
   322                 elif values[1] == "InOut":
       
   323                     var_class = INPUT
       
   324                 else:
       
   325                     var_class = INPUT
       
   326                 tree = dict([(var["Name"], var["Tree"]) for var in self.ParentWindow.Controler.GetEditedElementInterfaceVars(tagname, self.ParentWindow.Debug)]).get(values[0], None)
       
   327                 if tree is not None:
       
   328                     if len(tree[0]) > 0:
       
   329                         menu = wx.Menu(title='')
       
   330                         self.GenerateTreeMenu(x, y, scaling, menu, "", var_class, [(values[0], values[2], tree)])
       
   331                         self.ParentWindow.PopupMenuXY(menu)
       
   332                     else:
       
   333                         self.ParentWindow.AddVariableBlock(x, y, scaling, var_class, values[0], values[2])
       
   334                 else:
       
   335                     message = _("Unknown variable \"%s\" for this POU!") % values[0]
       
   336             else:
       
   337                 message = _("Variable don't belong to this POU!")
       
   338         if message is not None:
       
   339             wx.CallAfter(self.ShowMessage, message)
       
   340 
       
   341     def GenerateTreeMenu(self, x, y, scaling, menu, base_path, var_class, tree):
       
   342         for child_name, child_type, (child_tree, child_dimensions) in tree:
       
   343             if base_path:
       
   344                 child_path = "%s.%s" % (base_path, child_name)
       
   345             else:
       
   346                 child_path = child_name
       
   347             if len(child_dimensions) > 0:
       
   348                 child_path += "[%s]" % ",".join([str(dimension[0]) for dimension in child_dimensions])
       
   349                 child_name += "[]"
       
   350             new_id = wx.NewId()
       
   351             AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=child_name)
       
   352             self.ParentWindow.Bind(wx.EVT_MENU, self.GetAddVariableBlockFunction(x, y, scaling, var_class, child_path, child_type), id=new_id)
       
   353             if len(child_tree) > 0:
       
   354                 new_id = wx.NewId()
       
   355                 child_menu = wx.Menu(title='')
       
   356                 self.GenerateTreeMenu(x, y, scaling, child_menu, child_path, var_class, child_tree)
       
   357                 menu.AppendMenu(new_id, "%s." % child_name, child_menu)
       
   358             
       
   359     def GetAddVariableBlockFunction(self, x, y, scaling, var_class, var_name, var_type):
       
   360         def AddVariableFunction(event):
       
   361             self.ParentWindow.AddVariableBlock(x, y, scaling, var_class, var_name, var_type)
       
   362         return AddVariableFunction
       
   363     
       
   364     def ShowMessage(self, message):
       
   365         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
       
   366         message.ShowModal()
       
   367         message.Destroy()
       
   368 
       
   369 """
       
   370 Class that implements a Viewer based on a wx.ScrolledWindow for drawing and 
       
   371 manipulating graphic elements
       
   372 """
       
   373 
       
   374 class Viewer(EditorPanel, DebugViewer, DebugDataConsumer):
       
   375     
       
   376     if wx.VERSION < (2, 6, 0):
       
   377         def Bind(self, event, function, id = None):
       
   378             if id is not None:
       
   379                 event(self, id, function)
       
   380             else:
       
   381                 event(self, function)
       
   382     
       
   383     # Add list of menu items to the given menu
       
   384     def AddMenuItems(self, menu, items):
       
   385         for item in items:
       
   386             if item is None:
       
   387                 menu.AppendSeparator()
       
   388             else:
       
   389                 id, kind, text, help, callback = item
       
   390                 AppendMenu(menu, help=help, id=id, kind=kind, text=text)
       
   391                 # Link menu event to corresponding called functions
       
   392                 self.Bind(wx.EVT_MENU, callback, id=id)
       
   393     
       
   394     # Add Block Pin Menu items to the given menu
       
   395     def AddBlockPinMenuItems(self, menu, connector):
       
   396         [ID_NO_MODIFIER, ID_NEGATED, ID_RISING_EDGE, 
       
   397          ID_FALLING_EDGE] = [wx.NewId() for i in xrange(4)]
       
   398         
       
   399         # Create menu items
       
   400         self.AddMenuItems(menu, [
       
   401             (ID_NO_MODIFIER, wx.ITEM_RADIO, _(u'No Modifier'), '', self.OnNoModifierMenu),
       
   402             (ID_NEGATED, wx.ITEM_RADIO, _(u'Negated'), '', self.OnNegatedMenu),
       
   403             (ID_RISING_EDGE, wx.ITEM_RADIO, _(u'Rising Edge'), '', self.OnRisingEdgeMenu),
       
   404             (ID_FALLING_EDGE, wx.ITEM_RADIO, _(u'Falling Edge'), '', self.OnFallingEdgeMenu)])
       
   405         
       
   406         type = self.Controler.GetEditedElementType(self.TagName, self.Debug)
       
   407         menu.Enable(ID_RISING_EDGE, type != "function")
       
   408         menu.Enable(ID_FALLING_EDGE, type != "function")
       
   409         
       
   410         if connector.IsNegated():
       
   411             menu.Check(ID_NEGATED, True)
       
   412         elif connector.GetEdge() == "rising":
       
   413             menu.Check(ID_RISING_EDGE, True)
       
   414         elif connector.GetEdge() == "falling":
       
   415             menu.Check(ID_FALLING_EDGE, True)
       
   416         else:
       
   417             menu.Check(ID_NO_MODIFIER, True)
       
   418         
       
   419     # Add Alignment Menu items to the given menu
       
   420     def AddAlignmentMenuItems(self, menu):
       
   421         [ID_ALIGN_LEFT, ID_ALIGN_CENTER, ID_ALIGN_RIGHT,
       
   422          ID_ALIGN_TOP, ID_ALIGN_MIDDLE, ID_ALIGN_BOTTOM,
       
   423         ] = [wx.NewId() for i in xrange(6)]
       
   424         
       
   425         # Create menu items
       
   426         self.AddMenuItems(menu, [
       
   427             (ID_ALIGN_LEFT, wx.ITEM_NORMAL, _(u'Left'), '', self.OnAlignLeftMenu),
       
   428             (ID_ALIGN_CENTER, wx.ITEM_NORMAL, _(u'Center'), '', self.OnAlignCenterMenu), 
       
   429             (ID_ALIGN_RIGHT, wx.ITEM_NORMAL, _(u'Right'), '', self.OnAlignRightMenu),
       
   430             None,
       
   431             (ID_ALIGN_TOP, wx.ITEM_NORMAL, _(u'Top'), '', self.OnAlignTopMenu), 
       
   432             (ID_ALIGN_MIDDLE, wx.ITEM_NORMAL, _(u'Middle'), '', self.OnAlignMiddleMenu),
       
   433             (ID_ALIGN_BOTTOM, wx.ITEM_NORMAL, _(u'Bottom'), '', self.OnAlignBottomMenu)])
       
   434     
       
   435     # Add Wire Menu items to the given menu
       
   436     def AddWireMenuItems(self, menu, delete=False):
       
   437         [ID_ADD_SEGMENT, ID_DELETE_SEGMENT] = [wx.NewId() for i in xrange(2)]
       
   438         
       
   439         # Create menu items
       
   440         self.AddMenuItems(menu, [
       
   441             (ID_ADD_SEGMENT, wx.ITEM_NORMAL, _(u'Add Wire Segment'), '', self.OnAddSegmentMenu),
       
   442             (ID_DELETE_SEGMENT, wx.ITEM_NORMAL, _(u'Delete Wire Segment'), '', self.OnDeleteSegmentMenu)])
       
   443     
       
   444         menu.Enable(ID_DELETE_SEGMENT, delete)
       
   445     
       
   446     # Add Divergence Menu items to the given menu
       
   447     def AddDivergenceMenuItems(self, menu, delete=False):
       
   448         [ID_ADD_BRANCH, ID_DELETE_BRANCH] = [wx.NewId() for i in xrange(2)]
       
   449         
       
   450         # Create menu items
       
   451         self.AddMenuItems(menu, [
       
   452             (ID_ADD_BRANCH, wx.ITEM_NORMAL, _(u'Add Divergence Branch'), '', self.OnAddBranchMenu),
       
   453             (ID_DELETE_BRANCH, wx.ITEM_NORMAL, _(u'Delete Divergence Branch'), '', self.OnDeleteBranchMenu)])
       
   454         
       
   455         menu.Enable(ID_DELETE_BRANCH, delete)
       
   456     
       
   457     # Add Add Menu items to the given menu
       
   458     def AddAddMenuItems(self, menu):
       
   459         [ID_ADD_BLOCK, ID_ADD_VARIABLE, ID_ADD_CONNECTION,
       
   460          ID_ADD_COMMENT] = [wx.NewId() for i in xrange(4)]
       
   461         
       
   462         # Create menu items
       
   463         self.AddMenuItems(menu, [
       
   464             (ID_ADD_BLOCK, wx.ITEM_NORMAL, _(u'Block'), '', self.GetAddMenuCallBack(self.AddNewBlock)),
       
   465             (ID_ADD_VARIABLE, wx.ITEM_NORMAL, _(u'Variable'), '', self.GetAddMenuCallBack(self.AddNewVariable)),
       
   466             (ID_ADD_CONNECTION, wx.ITEM_NORMAL, _(u'Connection'), '', self.GetAddMenuCallBack(self.AddNewConnection)),
       
   467             None])
       
   468         
       
   469         if self.CurrentLanguage != "FBD":
       
   470             [ID_ADD_POWER_RAIL, ID_ADD_CONTACT, ID_ADD_COIL,
       
   471             ] = [wx.NewId() for i in xrange(3)]
       
   472             
       
   473             # Create menu items
       
   474             self.AddMenuItems(menu, [
       
   475                 (ID_ADD_POWER_RAIL, wx.ITEM_NORMAL, _(u'Power Rail'), '', self.GetAddMenuCallBack(self.AddNewPowerRail)),
       
   476                 (ID_ADD_CONTACT, wx.ITEM_NORMAL, _(u'Contact'), '', self.GetAddMenuCallBack(self.AddNewContact))])
       
   477                 
       
   478             if self.CurrentLanguage != "SFC":
       
   479                 self.AddMenuItems(menu, [
       
   480                      (ID_ADD_COIL, wx.ITEM_NORMAL, _(u'Coil'), '', self.GetAddMenuCallBack(self.AddNewCoil))])
       
   481             
       
   482             menu.AppendSeparator()
       
   483         
       
   484         if self.CurrentLanguage == "SFC":
       
   485             [ID_ADD_INITIAL_STEP, ID_ADD_STEP, ID_ADD_TRANSITION, 
       
   486              ID_ADD_ACTION_BLOCK, ID_ADD_DIVERGENCE, ID_ADD_JUMP,
       
   487             ] = [wx.NewId() for i in xrange(6)]
       
   488             
       
   489             # Create menu items
       
   490             self.AddMenuItems(menu, [
       
   491                 (ID_ADD_INITIAL_STEP, wx.ITEM_NORMAL, _(u'Initial Step'), '', self.GetAddMenuCallBack(self.AddNewStep, True)),
       
   492                 (ID_ADD_STEP, wx.ITEM_NORMAL, _(u'Step'), '', self.GetAddMenuCallBack(self.AddNewStep)),
       
   493                 (ID_ADD_TRANSITION, wx.ITEM_NORMAL, _(u'Transition'), '', self.GetAddMenuCallBack(self.AddNewTransition)),
       
   494                 (ID_ADD_ACTION_BLOCK, wx.ITEM_NORMAL, _(u'Action Block'), '', self.GetAddMenuCallBack(self.AddNewActionBlock)),
       
   495                 (ID_ADD_DIVERGENCE, wx.ITEM_NORMAL, _(u'Divergence'), '', self.GetAddMenuCallBack(self.AddNewDivergence)),
       
   496                 (ID_ADD_JUMP, wx.ITEM_NORMAL, _(u'Jump'), '', self.GetAddMenuCallBack(self.AddNewJump)),
       
   497                 None])
       
   498         
       
   499         self.AddMenuItems(menu, [
       
   500              (ID_ADD_COMMENT, wx.ITEM_NORMAL, _(u'Comment'), '', self.GetAddMenuCallBack(self.AddNewComment))])
       
   501         
       
   502     # Add Default Menu items to the given menu
       
   503     def AddDefaultMenuItems(self, menu, edit=False, block=False):
       
   504         if block:
       
   505             [ID_EDIT_BLOCK, ID_DELETE, ID_ADJUST_BLOCK_SIZE] = [wx.NewId() for i in xrange(3)]
       
   506         
       
   507             # Create menu items
       
   508             self.AddMenuItems(menu, [
       
   509                  (ID_EDIT_BLOCK, wx.ITEM_NORMAL, _(u'Edit Block'), '', self.OnEditBlockMenu),
       
   510                  (ID_ADJUST_BLOCK_SIZE, wx.ITEM_NORMAL, _(u'Adjust Block Size'), '', self.OnAdjustBlockSizeMenu),
       
   511                  (ID_DELETE, wx.ITEM_NORMAL, _(u'Delete'), '', self.OnDeleteMenu)])
       
   512         
       
   513             menu.Enable(ID_EDIT_BLOCK, edit)
       
   514         
       
   515         else:
       
   516             [ID_CLEAR_EXEC_ORDER, ID_RESET_EXEC_ORDER] = [wx.NewId() for i in xrange(2)]
       
   517         
       
   518             # Create menu items
       
   519             self.AddMenuItems(menu, [
       
   520                  (ID_CLEAR_EXEC_ORDER, wx.ITEM_NORMAL, _(u'Clear Execution Order'), '', self.OnClearExecutionOrderMenu),
       
   521                  (ID_RESET_EXEC_ORDER, wx.ITEM_NORMAL, _(u'Reset Execution Order'), '', self.OnResetExecutionOrderMenu)])
       
   522             
       
   523             menu.AppendSeparator()
       
   524             
       
   525             add_menu = wx.Menu(title='')
       
   526             self.AddAddMenuItems(add_menu)
       
   527             menu.AppendMenu(-1, _(u'Add'), add_menu)
       
   528         
       
   529         menu.AppendSeparator()
       
   530         
       
   531         [ID_CUT, ID_COPY, ID_PASTE] = [wx.NewId() for i in xrange(3)]
       
   532         
       
   533         # Create menu items
       
   534         self.AddMenuItems(menu, [
       
   535              (ID_CUT, wx.ITEM_NORMAL, _(u'Cut'), '', self.GetClipboardCallBack(self.Cut)),
       
   536              (ID_COPY, wx.ITEM_NORMAL, _(u'Copy'), '', self.GetClipboardCallBack(self.Copy)),
       
   537              (ID_PASTE, wx.ITEM_NORMAL, _(u'Paste'), '', self.GetAddMenuCallBack(self.Paste))])
       
   538         
       
   539         menu.Enable(ID_CUT, block)
       
   540         menu.Enable(ID_COPY, block)
       
   541         menu.Enable(ID_PASTE, self.ParentWindow.GetCopyBuffer() is not None)
       
   542         
       
   543     def _init_Editor(self, prnt):
       
   544         self.Editor = wx.ScrolledWindow(prnt, name="Viewer", 
       
   545             pos=wx.Point(0, 0), size=wx.Size(0, 0), 
       
   546             style=wx.HSCROLL | wx.VSCROLL | wx.ALWAYS_SHOW_SB)
       
   547         self.Editor.ParentWindow = self
       
   548     
       
   549     # Create a new Viewer
       
   550     def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""):
       
   551         self.VARIABLE_PANEL_TYPE = controler.GetPouType(tagname.split("::")[1])
       
   552         
       
   553         EditorPanel.__init__(self, parent, tagname, window, controler, debug)
       
   554         DebugViewer.__init__(self, controler, debug)
       
   555         DebugDataConsumer.__init__(self)
       
   556         
       
   557         # Adding a rubberband to Viewer
       
   558         self.rubberBand = RubberBand(viewer=self)
       
   559         self.Editor.SetBackgroundColour(wx.Colour(255,255,255))
       
   560         self.Editor.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
       
   561         self.ResetView()
       
   562         self.Scaling = None
       
   563         self.DrawGrid = True
       
   564         self.GridBrush = wx.TRANSPARENT_BRUSH
       
   565         self.PageSize = None
       
   566         self.PagePen = wx.TRANSPARENT_PEN
       
   567         self.DrawingWire = False
       
   568         self.current_id = 0
       
   569         self.TagName = tagname
       
   570         self.Highlights = []
       
   571         self.SearchParams = None
       
   572         self.SearchResults = None
       
   573         self.CurrentFindHighlight = None
       
   574         self.InstancePath = instancepath
       
   575         self.StartMousePos = None
       
   576         self.StartScreenPos = None
       
   577         self.Buffering = False
       
   578         
       
   579         # Initialize Cursors
       
   580         ResetCursors()
       
   581         self.CurrentCursor = 0
       
   582         
       
   583         # Initialize Block, Wire and Comment numbers
       
   584         self.wire_id = 0
       
   585         
       
   586         # Initialize Viewer mode to Selection mode
       
   587         self.Mode = MODE_SELECTION
       
   588         self.SavedMode = False
       
   589         self.CurrentLanguage = "FBD"
       
   590         
       
   591         if not self.Debug:
       
   592             self.Editor.SetDropTarget(ViewerDropTarget(self))
       
   593         
       
   594         self.ElementRefreshList = []
       
   595         self.ElementRefreshList_lock = Lock()
       
   596         
       
   597         dc = wx.ClientDC(self.Editor)
       
   598         font = wx.Font(faces["size"], wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["mono"])
       
   599         dc.SetFont(font)
       
   600         width, height = dc.GetTextExtent("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
       
   601         while width > 260:
       
   602             faces["size"] -= 1
       
   603             font = wx.Font(faces["size"], wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["mono"])
       
   604             dc.SetFont(font)
       
   605             width, height = dc.GetTextExtent("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
       
   606         self.SetFont(font)
       
   607         self.MiniTextDC = wx.MemoryDC()
       
   608         self.MiniTextDC.SetFont(wx.Font(faces["size"] * 0.75, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]))
       
   609         
       
   610         self.CurrentScale = None
       
   611         self.SetScale(len(ZOOM_FACTORS) / 2, False)
       
   612         
       
   613         self.RefreshHighlightsTimer = wx.Timer(self, -1)
       
   614         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
       
   615         
       
   616         self.ResetView()
       
   617         
       
   618         # Link Viewer event to corresponding methods
       
   619         self.Editor.Bind(wx.EVT_PAINT, self.OnPaint)
       
   620         self.Editor.Bind(wx.EVT_LEFT_DOWN, self.OnViewerLeftDown)
       
   621         self.Editor.Bind(wx.EVT_LEFT_UP, self.OnViewerLeftUp)
       
   622         self.Editor.Bind(wx.EVT_LEFT_DCLICK, self.OnViewerLeftDClick)
       
   623         self.Editor.Bind(wx.EVT_RIGHT_DOWN, self.OnViewerRightDown)
       
   624         self.Editor.Bind(wx.EVT_RIGHT_UP, self.OnViewerRightUp)
       
   625         self.Editor.Bind(wx.EVT_MIDDLE_DOWN, self.OnViewerMiddleDown)
       
   626         self.Editor.Bind(wx.EVT_MIDDLE_UP, self.OnViewerMiddleUp)
       
   627         self.Editor.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveViewer)
       
   628         self.Editor.Bind(wx.EVT_MOTION, self.OnViewerMotion)
       
   629         self.Editor.Bind(wx.EVT_CHAR, self.OnChar)
       
   630         self.Editor.Bind(wx.EVT_SCROLLWIN, self.OnScrollWindow)
       
   631         self.Editor.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.OnScrollStop)
       
   632         self.Editor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheelWindow)
       
   633         self.Editor.Bind(wx.EVT_SIZE, self.OnMoveWindow)
       
   634         self.Editor.Bind(wx.EVT_MOUSE_EVENTS, self.OnViewerMouseEvent)
       
   635     
       
   636     # Destructor
       
   637     def __del__(self):
       
   638         DebugViewer.__del__(self)
       
   639         self.Flush()
       
   640         self.ResetView()
       
   641         self.RefreshHighlightsTimer.Stop()
       
   642     
       
   643     def SetCurrentCursor(self, cursor):
       
   644         if self.Mode != MODE_MOTION:
       
   645             global CURSORS
       
   646             if self.CurrentCursor != cursor:
       
   647                 self.CurrentCursor = cursor
       
   648                 self.Editor.SetCursor(CURSORS[cursor])
       
   649     
       
   650     def GetScrolledRect(self, rect):
       
   651         rect.x, rect.y = self.Editor.CalcScrolledPosition(int(rect.x * self.ViewScale[0]), 
       
   652                                                    int(rect.y * self.ViewScale[1]))
       
   653         rect.width = int(rect.width * self.ViewScale[0]) + 2
       
   654         rect.height = int(rect.height * self.ViewScale[1]) + 2
       
   655         return rect
       
   656     
       
   657     def GetTitle(self):
       
   658         if self.Debug:
       
   659             if len(self.InstancePath) > 15:
       
   660                 return "..." + self.InstancePath[-12:]
       
   661             return self.InstancePath
       
   662         return EditorPanel.GetTitle(self)
       
   663     
       
   664     def GetScaling(self):
       
   665         return self.Scaling
       
   666     
       
   667     def GetInstancePath(self, variable_base=False):
       
   668         if variable_base:
       
   669             words = self.TagName.split("::")
       
   670             if words[0] in ["A", "T"]:
       
   671                 return ".".join(self.InstancePath.split(".")[:-1])
       
   672         return self.InstancePath
       
   673     
       
   674     def IsViewing(self, tagname):
       
   675         if self.Debug:
       
   676             return self.InstancePath == tagname
       
   677         return EditorPanel.IsViewing(self, tagname)
       
   678     
       
   679     # Returns a new id
       
   680     def GetNewId(self):
       
   681         self.current_id += 1
       
   682         return self.current_id
       
   683         
       
   684     def SetScale(self, scale_number, refresh=True, mouse_event=None):
       
   685         new_scale = max(0, min(scale_number, len(ZOOM_FACTORS) - 1))
       
   686         if self.CurrentScale != new_scale:
       
   687             if refresh:
       
   688                 dc = self.GetLogicalDC()
       
   689             self.CurrentScale = new_scale
       
   690             self.ViewScale = (ZOOM_FACTORS[self.CurrentScale], ZOOM_FACTORS[self.CurrentScale])
       
   691             if refresh:
       
   692                 self.Editor.Freeze()
       
   693                 if mouse_event is None:
       
   694                     client_size = self.Editor.GetClientSize()
       
   695                     mouse_pos = wx.Point(client_size[0] / 2, client_size[1] / 2)
       
   696                     mouse_event = wx.MouseEvent(wx.EVT_MOUSEWHEEL.typeId)
       
   697                     mouse_event.m_x = mouse_pos.x
       
   698                     mouse_event.m_y = mouse_pos.y
       
   699                 else:
       
   700                     mouse_pos = mouse_event.GetPosition()
       
   701                 pos = mouse_event.GetLogicalPosition(dc)
       
   702                 xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
       
   703                 ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
       
   704                 scrollx = max(0, round(pos.x * self.ViewScale[0] - mouse_pos.x) / SCROLLBAR_UNIT)
       
   705                 scrolly = max(0, round(pos.y * self.ViewScale[1] - mouse_pos.y) / SCROLLBAR_UNIT)
       
   706                 if scrollx > xmax or scrolly > ymax:
       
   707                     self.RefreshScrollBars(max(0, scrollx - xmax), max(0, scrolly - ymax))
       
   708                     self.Scroll(scrollx, scrolly)
       
   709                 else:
       
   710                     self.Scroll(scrollx, scrolly)
       
   711                     self.RefreshScrollBars()
       
   712                 self.RefreshScaling(refresh)
       
   713                 self.Editor.Thaw()
       
   714     
       
   715     def GetScale(self):
       
   716         return self.CurrentScale
       
   717 
       
   718     def GetViewScale(self):
       
   719         return self.ViewScale
       
   720 
       
   721     def GetState(self):
       
   722         return {"position": self.Editor.GetViewStart(),
       
   723                 "zoom": self.CurrentScale}
       
   724 
       
   725     def SetState(self, state):
       
   726         if self:
       
   727             if state.has_key("zoom"):
       
   728                 self.SetScale(state["zoom"])
       
   729             if state.has_key("position"):
       
   730                 self.Scroll(*state["position"])
       
   731             self.RefreshVisibleElements()
       
   732         
       
   733     def GetLogicalDC(self, buffered=False):
       
   734         if buffered:
       
   735             bitmap = wx.EmptyBitmap(*self.Editor.GetClientSize())
       
   736             dc = wx.MemoryDC(bitmap)
       
   737         else:
       
   738             dc = wx.ClientDC(self.Editor)
       
   739         dc.SetFont(self.GetFont())
       
   740         if wx.VERSION >= (2, 6, 0):
       
   741             self.Editor.DoPrepareDC(dc)
       
   742         else:
       
   743             self.Editor.PrepareDC(dc)
       
   744         dc.SetUserScale(self.ViewScale[0], self.ViewScale[1])
       
   745         return dc
       
   746     
       
   747     def RefreshRect(self, rect, eraseBackground=True):
       
   748         self.Editor.RefreshRect(rect, eraseBackground)
       
   749     
       
   750     def Scroll(self, x, y):
       
   751         self.Editor.Scroll(x, y)
       
   752     
       
   753     def GetScrollPos(self, orientation):
       
   754         return self.Editor.GetScrollPos(orientation)
       
   755     
       
   756     def GetScrollRange(self, orientation):
       
   757         return self.Editor.GetScrollRange(orientation)
       
   758     
       
   759     def GetScrollThumb(self, orientation):
       
   760         return self.Editor.GetScrollThumb(orientation)
       
   761     
       
   762     def CalcUnscrolledPosition(self, x, y):
       
   763         return self.Editor.CalcUnscrolledPosition(x, y)
       
   764     
       
   765     def GetViewStart(self):
       
   766         return self.Editor.GetViewStart()
       
   767     
       
   768     def GetTextExtent(self, text):
       
   769         return self.Editor.GetTextExtent(text)
       
   770     
       
   771     def GetFont(self):
       
   772         return self.Editor.GetFont()
       
   773     
       
   774     def GetMiniTextExtent(self, text):
       
   775         return self.MiniTextDC.GetTextExtent(text)
       
   776     
       
   777     def GetMiniFont(self):
       
   778         return self.MiniTextDC.GetFont()
       
   779     
       
   780 #-------------------------------------------------------------------------------
       
   781 #                         Element management functions
       
   782 #-------------------------------------------------------------------------------
       
   783 
       
   784     def AddBlock(self, block):
       
   785         self.Blocks[block.GetId()] = block
       
   786         
       
   787     def AddWire(self, wire):
       
   788         self.wire_id += 1
       
   789         self.Wires[wire] = self.wire_id
       
   790         
       
   791     def AddComment(self, comment):
       
   792         self.Comments[comment.GetId()] = comment
       
   793 
       
   794     def IsBlock(self, block):
       
   795         if block is not None:
       
   796             return self.Blocks.get(block.GetId(), False)
       
   797         return False
       
   798         
       
   799     def IsWire(self, wire):
       
   800         return self.Wires.get(wire, False)
       
   801         
       
   802     def IsComment(self, comment):
       
   803         if comment is not None:
       
   804             return self.Comments.get(comment.GetId(), False)
       
   805         return False
       
   806 
       
   807     def RemoveBlock(self, block):
       
   808         self.Blocks.pop(block.GetId())
       
   809         
       
   810     def RemoveWire(self, wire):
       
   811         self.Wires.pop(wire)
       
   812         
       
   813     def RemoveComment(self, comment):
       
   814         self.Comments.pop(comment.GetId())
       
   815 
       
   816     def GetElements(self, sort_blocks=False, sort_wires=False, sort_comments=False):
       
   817         blocks = self.Blocks.values()
       
   818         wires = self.Wires.keys()
       
   819         comments = self.Comments.values()
       
   820         if sort_blocks:
       
   821             blocks.sort(lambda x, y: cmp(x.GetId(), y.GetId()))
       
   822         if sort_wires:
       
   823             wires.sort(lambda x, y: cmp(self.Wires[x], self.Wires[y]))
       
   824         if sort_comments:
       
   825             comments.sort(lambda x, y: cmp(x.GetId(), y.GetId()))
       
   826         return blocks + wires + comments
       
   827 
       
   828     def GetConnectorByName(self, name):
       
   829         for block in self.Blocks.itervalues():
       
   830             if isinstance(block, FBD_Connector) and\
       
   831                block.GetType() == CONNECTOR and\
       
   832                block.GetName() == name:
       
   833                 return block
       
   834         return None
       
   835     
       
   836     def RefreshVisibleElements(self, xp = None, yp = None):
       
   837         x, y = self.Editor.CalcUnscrolledPosition(0, 0)
       
   838         if xp is not None:
       
   839             x = xp * self.Editor.GetScrollPixelsPerUnit()[0]
       
   840         if yp is not None:
       
   841             y = yp * self.Editor.GetScrollPixelsPerUnit()[1]
       
   842         width, height = self.Editor.GetClientSize()
       
   843         screen = wx.Rect(int(x / self.ViewScale[0]), int(y / self.ViewScale[1]),
       
   844                          int(width / self.ViewScale[0]), int(height / self.ViewScale[1]))
       
   845         for comment in self.Comments.itervalues():
       
   846             comment.TestVisible(screen)
       
   847         for wire in self.Wires.iterkeys():
       
   848             wire.TestVisible(screen)
       
   849         for block in self.Blocks.itervalues():
       
   850             block.TestVisible(screen)
       
   851     
       
   852     def GetElementIECPath(self, element):
       
   853         iec_path = None
       
   854         instance_path = self.GetInstancePath(True)
       
   855         if isinstance(element, Wire) and element.EndConnected is not None:
       
   856             block = element.EndConnected.GetParentBlock()
       
   857             if isinstance(block, FBD_Block):
       
   858                 blockname = block.GetName()
       
   859                 connectorname = element.EndConnected.GetName()
       
   860                 if blockname != "":
       
   861                     iec_path = "%s.%s.%s"%(instance_path, blockname, connectorname)
       
   862                 else:
       
   863                     if connectorname == "":
       
   864                         iec_path = "%s.%s%d"%(instance_path, block.GetType(), block.GetId())
       
   865                     else:
       
   866                         iec_path = "%s.%s%d_%s"%(instance_path, block.GetType(), block.GetId(), connectorname)
       
   867             elif isinstance(block, FBD_Variable):
       
   868                 iec_path = "%s.%s"%(instance_path, block.GetName())
       
   869             elif isinstance(block, FBD_Connector):
       
   870                 connection = self.GetConnectorByName(block.GetName())
       
   871                 if connection is not None:
       
   872                     connector = connection.GetConnector()
       
   873                     if len(connector.Wires) == 1:
       
   874                         iec_path = self.GetElementIECPath(connector.Wires[0][0])
       
   875         elif isinstance(element, LD_Contact):
       
   876             iec_path = "%s.%s"%(instance_path, element.GetName())
       
   877         elif isinstance(element, SFC_Step):
       
   878             iec_path = "%s.%s.X"%(instance_path, element.GetName())
       
   879         elif isinstance(element, SFC_Transition):
       
   880             connectors = element.GetConnectors()
       
   881             previous_steps = self.GetPreviousSteps(connectors["inputs"])
       
   882             next_steps = self.GetNextSteps(connectors["outputs"])
       
   883             iec_path = "%s.%s->%s"%(instance_path, ",".join(previous_steps), ",".join(next_steps))
       
   884         return iec_path
       
   885        
       
   886 #-------------------------------------------------------------------------------
       
   887 #                              Reset functions
       
   888 #-------------------------------------------------------------------------------
       
   889 
       
   890     # Resets Viewer lists
       
   891     def ResetView(self):
       
   892         self.Blocks = {}
       
   893         self.Wires = {}
       
   894         self.Comments = {}
       
   895         self.Subscribed = {}
       
   896         self.SelectedElement = None
       
   897         self.HighlightedElement = None
       
   898         self.ToolTipElement = None
       
   899     
       
   900     def Flush(self):
       
   901         self.DeleteDataConsumers()
       
   902         for block in self.Blocks.itervalues():
       
   903             block.Flush()
       
   904     
       
   905     # Remove all elements
       
   906     def CleanView(self):
       
   907         for block in self.Blocks.itervalues():
       
   908             block.Clean()
       
   909         self.ResetView()
       
   910     
       
   911     # Changes Viewer mode
       
   912     def SetMode(self, mode):
       
   913         if self.Mode != mode or mode == MODE_SELECTION:    
       
   914             if self.Mode == MODE_MOTION:
       
   915                 wx.CallAfter(self.Editor.SetCursor, wx.NullCursor)
       
   916             self.Mode = mode
       
   917             self.SavedMode = False
       
   918         else:
       
   919             self.SavedMode = True
       
   920         # Reset selection
       
   921         if self.Mode != MODE_SELECTION and self.SelectedElement:
       
   922             self.SelectedElement.SetSelected(False)
       
   923             self.SelectedElement = None
       
   924         if self.Mode == MODE_MOTION:
       
   925             wx.CallAfter(self.Editor.SetCursor, wx.StockCursor(wx.CURSOR_HAND))
       
   926             self.SavedMode = True
       
   927         
       
   928     # Return current drawing mode
       
   929     def GetDrawingMode(self):
       
   930         return self.ParentWindow.GetDrawingMode()
       
   931     
       
   932     # Buffer the last model state
       
   933     def RefreshBuffer(self):
       
   934         self.Controler.BufferProject()
       
   935         if self.ParentWindow:
       
   936             self.ParentWindow.RefreshTitle()
       
   937             self.ParentWindow.RefreshFileMenu()
       
   938             self.ParentWindow.RefreshEditMenu()
       
   939     
       
   940     def StartBuffering(self):
       
   941         if not self.Buffering:
       
   942             self.Buffering = True
       
   943             self.Controler.StartBuffering()
       
   944             if self.ParentWindow:
       
   945                 self.ParentWindow.RefreshTitle()
       
   946                 self.ParentWindow.RefreshFileMenu()
       
   947                 self.ParentWindow.RefreshEditMenu()
       
   948     
       
   949     def ResetBuffer(self):
       
   950         if self.Buffering:
       
   951             self.Controler.EndBuffering()
       
   952             self.Buffering = False
       
   953     
       
   954     def GetBufferState(self):
       
   955         if not self.Debug:
       
   956             return self.Controler.GetBufferState()
       
   957         return False, False
       
   958     
       
   959     def Undo(self):
       
   960         if not self.Debug:
       
   961             self.Controler.LoadPrevious()
       
   962             self.ParentWindow.CloseTabsWithoutModel()
       
   963             
       
   964     def Redo(self):
       
   965         if not self.Debug:
       
   966             self.Controler.LoadNext()
       
   967             self.ParentWindow.CloseTabsWithoutModel()
       
   968         
       
   969     def HasNoModel(self):
       
   970         if not self.Debug:
       
   971             return self.Controler.GetEditedElement(self.TagName) is None
       
   972         return False
       
   973     
       
   974     # Refresh the current scaling
       
   975     def RefreshScaling(self, refresh=True):
       
   976         properties = self.Controler.GetProjectProperties(self.Debug)
       
   977         scaling = properties["scaling"][self.CurrentLanguage]
       
   978         if scaling[0] != 0 and scaling[1] != 0:
       
   979             self.Scaling = scaling
       
   980             if self.DrawGrid:
       
   981                 width = max(2, int(scaling[0] * self.ViewScale[0]))
       
   982                 height = max(2, int(scaling[1] * self.ViewScale[1]))
       
   983                 bitmap = wx.EmptyBitmap(width, height)
       
   984                 dc = wx.MemoryDC(bitmap)
       
   985                 dc.SetBackground(wx.Brush(self.Editor.GetBackgroundColour()))
       
   986                 dc.Clear()
       
   987                 dc.SetPen(MiterPen(wx.Colour(180, 180, 180)))
       
   988                 dc.DrawPoint(0, 0)
       
   989                 self.GridBrush = wx.BrushFromBitmap(bitmap)
       
   990             else:
       
   991                 self.GridBrush = wx.TRANSPARENT_BRUSH
       
   992         else:
       
   993             self.Scaling = None
       
   994             self.GridBrush = wx.TRANSPARENT_BRUSH
       
   995         page_size = properties["pageSize"]
       
   996         if page_size != (0, 0):
       
   997             self.PageSize = map(int, page_size)
       
   998             self.PagePen = MiterPen(wx.Colour(180, 180, 180))
       
   999         else:
       
  1000             self.PageSize = None
       
  1001             self.PagePen = wx.TRANSPARENT_PEN
       
  1002         if refresh:
       
  1003             self.RefreshVisibleElements()
       
  1004             self.Refresh(False)
       
  1005         
       
  1006         
       
  1007 #-------------------------------------------------------------------------------
       
  1008 #                          Refresh functions
       
  1009 #-------------------------------------------------------------------------------
       
  1010     
       
  1011     VALUE_TRANSLATION = {True: _("Active"), False: _("Inactive")}
       
  1012 
       
  1013     def SetValue(self, value):
       
  1014         if self.Value != value:
       
  1015             self.Value = value
       
  1016             
       
  1017             xstart, ystart = self.GetViewStart()
       
  1018             window_size = self.Editor.GetClientSize()
       
  1019             refresh_rect = self.GetRedrawRect()
       
  1020             if (xstart * SCROLLBAR_UNIT <= refresh_rect.x + refresh_rect.width and 
       
  1021                 xstart * SCROLLBAR_UNIT + window_size[0] >= refresh_rect.x and
       
  1022                 ystart * SCROLLBAR_UNIT <= refresh_rect.y + refresh_rect.height and 
       
  1023                 ystart * SCROLLBAR_UNIT + window_size[1] >= refresh_rect.y):
       
  1024                 self.ElementNeedRefresh(self)
       
  1025     
       
  1026     def GetRedrawRect(self):
       
  1027         dc = self.GetLogicalDC()
       
  1028         ipw, iph = dc.GetTextExtent(_("Debug: %s") % self.InstancePath)
       
  1029         vw, vh = 0, 0
       
  1030         for value in self.VALUE_TRANSLATION.itervalues():
       
  1031             w, h = dc.GetTextExtent("(%s)" % value)
       
  1032             vw = max(vw, w)
       
  1033             vh = max(vh, h)
       
  1034         return wx.Rect(ipw + 4, 2, vw, vh)
       
  1035     
       
  1036     def ElementNeedRefresh(self, element):
       
  1037         self.ElementRefreshList_lock.acquire()
       
  1038         self.ElementRefreshList.append(element)
       
  1039         self.ElementRefreshList_lock.release()
       
  1040         
       
  1041     def RefreshNewData(self):
       
  1042         refresh_rect = None
       
  1043         self.ElementRefreshList_lock.acquire()
       
  1044         for element in self.ElementRefreshList:
       
  1045             if refresh_rect is None:
       
  1046                 refresh_rect = element.GetRedrawRect()
       
  1047             else:
       
  1048                 refresh_rect.Union(element.GetRedrawRect())
       
  1049         self.ElementRefreshList = []
       
  1050         self.ElementRefreshList_lock.release()
       
  1051         
       
  1052         if refresh_rect is not None:
       
  1053             self.RefreshRect(self.GetScrolledRect(refresh_rect), False)
       
  1054         else:
       
  1055             DebugViewer.RefreshNewData(self)
       
  1056         
       
  1057     # Refresh Viewer elements
       
  1058     def RefreshView(self, variablepanel=True, selection=None):
       
  1059         EditorPanel.RefreshView(self, variablepanel)
       
  1060         
       
  1061         if self.TagName.split("::")[0] == "A":
       
  1062             self.AddDataConsumer("%s.Q" % self.InstancePath.upper(), self)
       
  1063         
       
  1064         if self.ToolTipElement is not None:
       
  1065             self.ToolTipElement.ClearToolTip()
       
  1066             self.ToolTipElement = None
       
  1067         
       
  1068         self.Inhibit(True)
       
  1069         self.current_id = 0
       
  1070         # Start by reseting Viewer
       
  1071         self.Flush()
       
  1072         self.ResetView()
       
  1073         self.ResetBuffer()
       
  1074         instance = {}
       
  1075         # List of ids of already loaded blocks
       
  1076         ids = []
       
  1077         # Load Blocks until they are all loaded
       
  1078         while instance is not None:
       
  1079             instance = self.Controler.GetEditedElementInstanceInfos(self.TagName, exclude = ids, debug = self.Debug)
       
  1080             if instance is not None:
       
  1081                 self.loadInstance(instance, ids, selection)
       
  1082         self.RefreshScrollBars()
       
  1083         
       
  1084         for wire in self.Wires:
       
  1085             if not wire.IsConnectedCompatible():
       
  1086                 wire.SetValid(False)
       
  1087             if self.Debug:
       
  1088                 iec_path = self.GetElementIECPath(wire)
       
  1089                 if iec_path is None:
       
  1090                     block = wire.EndConnected.GetParentBlock()
       
  1091                     if isinstance(block, LD_PowerRail):
       
  1092                         wire.SetValue(True)
       
  1093                 elif self.AddDataConsumer(iec_path.upper(), wire) is None:
       
  1094                     wire.SetValue("undefined")
       
  1095 
       
  1096         if self.Debug:
       
  1097             for block in self.Blocks.itervalues():
       
  1098                 block.SpreadCurrent()
       
  1099                 iec_path = self.GetElementIECPath(block)
       
  1100                 if iec_path is not None:
       
  1101                     self.AddDataConsumer(iec_path.upper(), block)
       
  1102 
       
  1103         self.Inhibit(False)
       
  1104         self.RefreshVisibleElements()
       
  1105         self.ShowHighlights()
       
  1106         self.Refresh(False)
       
  1107     
       
  1108     def GetPreviousSteps(self, connectors):
       
  1109         steps = []
       
  1110         for connector in connectors:
       
  1111             for wire, handle in connector.GetWires():
       
  1112                 previous = wire.GetOtherConnected(connector).GetParentBlock()
       
  1113                 if isinstance(previous, SFC_Step):
       
  1114                     steps.append(previous.GetName())
       
  1115                 elif isinstance(previous, SFC_Divergence) and previous.GetType() in [SIMULTANEOUS_CONVERGENCE, SELECTION_DIVERGENCE]:
       
  1116                     connectors = previous.GetConnectors()
       
  1117                     steps.extend(self.GetPreviousSteps(connectors["inputs"]))
       
  1118         return steps
       
  1119     
       
  1120     def GetNextSteps(self, connectors):
       
  1121         steps = []
       
  1122         for connector in connectors:
       
  1123             for wire, handle in connector.GetWires():
       
  1124                 next = wire.GetOtherConnected(connector).GetParentBlock()
       
  1125                 if isinstance(next, SFC_Step):
       
  1126                     steps.append(next.GetName())
       
  1127                 elif isinstance(next, SFC_Jump):
       
  1128                     steps.append(next.GetTarget())
       
  1129                 elif isinstance(next, SFC_Divergence) and next.GetType() in [SIMULTANEOUS_DIVERGENCE, SELECTION_CONVERGENCE]:
       
  1130                     connectors = next.GetConnectors()
       
  1131                     steps.extend(self.GetNextSteps(connectors["outputs"]))
       
  1132         return steps
       
  1133     
       
  1134     def GetMaxSize(self):
       
  1135         maxx = maxy = 0
       
  1136         for element in self.GetElements():
       
  1137             bbox = element.GetBoundingBox()
       
  1138             maxx = max(maxx, bbox.x + bbox.width)
       
  1139             maxy = max(maxy, bbox.y + bbox.height)
       
  1140         return maxx, maxy
       
  1141     
       
  1142     def RefreshScrollBars(self, width_incr=0, height_incr=0):
       
  1143         xstart, ystart = self.GetViewStart()
       
  1144         window_size = self.Editor.GetClientSize()
       
  1145         maxx, maxy = self.GetMaxSize()
       
  1146         maxx = max(maxx + WINDOW_BORDER, (xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[0])
       
  1147         maxy = max(maxy + WINDOW_BORDER, (ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[1])
       
  1148         if self.rubberBand.IsShown():
       
  1149             extent = self.rubberBand.GetCurrentExtent()
       
  1150             maxx = max(maxx, extent.x + extent.width)
       
  1151             maxy = max(maxy, extent.y + extent.height)
       
  1152         maxx = int(maxx * self.ViewScale[0])
       
  1153         maxy = int(maxy * self.ViewScale[1])
       
  1154         self.Editor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
       
  1155             round(maxx / SCROLLBAR_UNIT) + width_incr, round(maxy / SCROLLBAR_UNIT) + height_incr, 
       
  1156             xstart, ystart, True)
       
  1157     
       
  1158     def EnsureVisible(self, block):
       
  1159         xstart, ystart = self.GetViewStart()
       
  1160         window_size = self.Editor.GetClientSize()
       
  1161         block_bbx = block.GetBoundingBox()
       
  1162         
       
  1163         screen_minx, screen_miny = xstart * SCROLLBAR_UNIT, ystart * SCROLLBAR_UNIT
       
  1164         screen_maxx, screen_maxy = screen_minx + window_size[0], screen_miny + window_size[1]
       
  1165         block_minx = int(block_bbx.x * self.ViewScale[0]) 
       
  1166         block_miny = int(block_bbx.y * self.ViewScale[1])
       
  1167         block_maxx = int(round((block_bbx.x + block_bbx.width) * self.ViewScale[0]))
       
  1168         block_maxy = int(round((block_bbx.y + block_bbx.height) * self.ViewScale[1]))
       
  1169         
       
  1170         xpos, ypos = xstart, ystart
       
  1171         if block_minx < screen_minx and block_maxx < screen_maxx:
       
  1172             xpos -= (screen_minx - block_minx) / SCROLLBAR_UNIT + 1
       
  1173         elif block_maxx > screen_maxx and block_minx > screen_minx:
       
  1174             xpos += (block_maxx - screen_maxx) / SCROLLBAR_UNIT + 1
       
  1175         if block_miny < screen_miny and block_maxy < screen_maxy:
       
  1176             ypos -= (screen_miny - block_miny) / SCROLLBAR_UNIT + 1
       
  1177         elif block_maxy > screen_maxy and block_miny > screen_miny:
       
  1178             ypos += (block_maxy - screen_maxy) / SCROLLBAR_UNIT + 1
       
  1179         self.Scroll(xpos, ypos)
       
  1180     
       
  1181     def SelectInGroup(self, element):
       
  1182         element.SetSelected(True)
       
  1183         if self.SelectedElement is None:
       
  1184             self.SelectedElement = element
       
  1185         elif isinstance(self.SelectedElement, Graphic_Group):
       
  1186             self.SelectedElement.SelectElement(element)
       
  1187         else:
       
  1188             group = Graphic_Group(self)
       
  1189             group.SelectElement(self.SelectedElement)
       
  1190             group.SelectElement(element)
       
  1191             self.SelectedElement = group
       
  1192         
       
  1193     # Load instance from given informations
       
  1194     def loadInstance(self, instance, ids, selection):
       
  1195         ids.append(instance["id"])
       
  1196         self.current_id = max(self.current_id, instance["id"])
       
  1197         creation_function = ElementCreationFunctions.get(instance["type"], None)
       
  1198         connectors = {"inputs" : [], "outputs" : []}
       
  1199         specific_values = instance["specific_values"]
       
  1200         if creation_function is not None:
       
  1201             element = creation_function(self, instance["id"], specific_values)
       
  1202             if isinstance(element, SFC_Step):
       
  1203                 if len(instance["inputs"]) > 0:
       
  1204                     element.AddInput()
       
  1205                 else:
       
  1206                     element.RemoveInput()
       
  1207                 if len(instance["outputs"]) > 0:
       
  1208                     element.AddOutput()
       
  1209             if isinstance(element, SFC_Transition) and specific_values["condition_type"] == "connection":
       
  1210                 connector = element.GetConditionConnector()
       
  1211                 self.CreateWires(connector, instance["id"], specific_values["connection"]["links"], ids, selection)
       
  1212         else:
       
  1213             executionControl = False
       
  1214             for input in instance["inputs"]:
       
  1215                 if input["negated"]:
       
  1216                     connectors["inputs"].append((input["name"], None, "negated"))
       
  1217                 elif input["edge"]:
       
  1218                     connectors["inputs"].append((input["name"], None, input["edge"]))
       
  1219                 else:
       
  1220                     connectors["inputs"].append((input["name"], None, "none"))
       
  1221             for output in instance["outputs"]:
       
  1222                 if output["negated"]:
       
  1223                     connectors["outputs"].append((output["name"], None, "negated"))
       
  1224                 elif output["edge"]:
       
  1225                     connectors["outputs"].append((output["name"], None, output["edge"]))
       
  1226                 else:
       
  1227                     connectors["outputs"].append((output["name"], None, "none"))
       
  1228             if len(connectors["inputs"]) > 0 and connectors["inputs"][0][0] == "EN":
       
  1229                 connectors["inputs"].pop(0)
       
  1230                 executionControl = True
       
  1231             if len(connectors["outputs"]) > 0 and connectors["outputs"][0][0] == "ENO":
       
  1232                 connectors["outputs"].pop(0)
       
  1233                 executionControl = True
       
  1234             if specific_values["name"] is None:
       
  1235                 specific_values["name"] = ""
       
  1236             element = FBD_Block(self, instance["type"], specific_values["name"], 
       
  1237                       instance["id"], len(connectors["inputs"]), 
       
  1238                       connectors=connectors, executionControl=executionControl, 
       
  1239                       executionOrder=specific_values["executionOrder"])
       
  1240         if isinstance(element, Comment):
       
  1241             self.AddComment(element)
       
  1242         else:
       
  1243             self.AddBlock(element)
       
  1244             connectors = element.GetConnectors()
       
  1245         element.SetPosition(instance["x"], instance["y"])
       
  1246         element.SetSize(instance["width"], instance["height"])
       
  1247         for i, output_connector in enumerate(instance["outputs"]):
       
  1248             if i < len(connectors["outputs"]):
       
  1249                 connector = connectors["outputs"][i]
       
  1250                 if output_connector.get("negated", False):
       
  1251                     connector.SetNegated(True)
       
  1252                 if output_connector.get("edge", "none") != "none":
       
  1253                     connector.SetEdge(output_connector["edge"])
       
  1254                 connector.SetPosition(wx.Point(*output_connector["position"]))
       
  1255         for i, input_connector in enumerate(instance["inputs"]):
       
  1256             if i < len(connectors["inputs"]):
       
  1257                 connector = connectors["inputs"][i]
       
  1258                 connector.SetPosition(wx.Point(*input_connector["position"]))
       
  1259                 if input_connector.get("negated", False):
       
  1260                     connector.SetNegated(True)
       
  1261                 if input_connector.get("edge", "none") != "none":
       
  1262                     connector.SetEdge(input_connector["edge"])
       
  1263                 self.CreateWires(connector, instance["id"], input_connector["links"], ids, selection)
       
  1264         if selection is not None and selection[0].get(instance["id"], False):
       
  1265             self.SelectInGroup(element)
       
  1266 
       
  1267     def CreateWires(self, start_connector, id, links, ids, selection=None):
       
  1268         for link in links:
       
  1269             refLocalId = link["refLocalId"]
       
  1270             if refLocalId is not None:
       
  1271                 if refLocalId not in ids:
       
  1272                     new_instance = self.Controler.GetEditedElementInstanceInfos(self.TagName, refLocalId, debug = self.Debug)
       
  1273                     if new_instance is not None:
       
  1274                         self.loadInstance(new_instance, ids, selection)
       
  1275                 connected = self.FindElementById(refLocalId)
       
  1276                 if connected is not None:
       
  1277                     points = link["points"]
       
  1278                     end_connector = connected.GetConnector(wx.Point(points[-1][0], points[-1][1]), link["formalParameter"])
       
  1279                     if end_connector is not None:
       
  1280                         wire = Wire(self)
       
  1281                         wire.SetPoints(points)
       
  1282                         start_connector.Connect((wire, 0), False)
       
  1283                         end_connector.Connect((wire, -1), False)
       
  1284                         wire.ConnectStartPoint(None, start_connector)
       
  1285                         wire.ConnectEndPoint(None, end_connector)
       
  1286                         self.AddWire(wire)
       
  1287                         if selection is not None and (\
       
  1288                            selection[1].get((id, refLocalId), False) or \
       
  1289                            selection[1].get((refLocalId, id), False)):
       
  1290                             self.SelectInGroup(wire)
       
  1291 
       
  1292     def IsOfType(self, type, reference):
       
  1293         return self.Controler.IsOfType(type, reference, self.Debug)
       
  1294     
       
  1295     def IsEndType(self, type):
       
  1296         return self.Controler.IsEndType(type)
       
  1297 
       
  1298     def GetBlockType(self, type, inputs = None):
       
  1299         return self.Controler.GetBlockType(type, inputs, self.Debug)
       
  1300 
       
  1301 #-------------------------------------------------------------------------------
       
  1302 #                          Search Element functions
       
  1303 #-------------------------------------------------------------------------------
       
  1304 
       
  1305     def FindBlock(self, event):
       
  1306         dc = self.GetLogicalDC()
       
  1307         pos = event.GetLogicalPosition(dc)
       
  1308         for block in self.Blocks.itervalues():
       
  1309             if block.HitTest(pos) or block.TestHandle(event) != (0, 0):
       
  1310                 return block
       
  1311         return None
       
  1312     
       
  1313     def FindWire(self, event):
       
  1314         dc = self.GetLogicalDC()
       
  1315         pos = event.GetLogicalPosition(dc)
       
  1316         for wire in self.Wires:
       
  1317             if wire.HitTest(pos) or wire.TestHandle(event) != (0, 0):
       
  1318                 return wire
       
  1319         return None
       
  1320     
       
  1321     def FindElement(self, event, exclude_group = False, connectors = True):
       
  1322         dc = self.GetLogicalDC()
       
  1323         pos = event.GetLogicalPosition(dc)
       
  1324         if self.SelectedElement and not (exclude_group and isinstance(self.SelectedElement, Graphic_Group)):
       
  1325             if self.SelectedElement.HitTest(pos, connectors) or self.SelectedElement.TestHandle(event) != (0, 0):
       
  1326                 return self.SelectedElement
       
  1327         for element in self.GetElements():
       
  1328             if element.HitTest(pos, connectors) or element.TestHandle(event) != (0, 0):
       
  1329                 return element
       
  1330         return None
       
  1331     
       
  1332     def FindBlockConnector(self, pos, direction = None, exclude = None):
       
  1333         for block in self.Blocks.itervalues():
       
  1334             result = block.TestConnector(pos, direction, exclude)
       
  1335             if result:
       
  1336                 return result
       
  1337         return None
       
  1338     
       
  1339     def FindElementById(self, id):
       
  1340         block = self.Blocks.get(id, None)
       
  1341         if block is not None:
       
  1342             return block
       
  1343         comment = self.Comments.get(id, None)
       
  1344         if comment is not None:
       
  1345             return comment
       
  1346         return None
       
  1347     
       
  1348     def SearchElements(self, bbox):
       
  1349         elements = []
       
  1350         for element in self.GetElements():
       
  1351             if element.IsInSelection(bbox):
       
  1352                 elements.append(element)
       
  1353         return elements
       
  1354 
       
  1355     def SelectAll(self):
       
  1356         if self.SelectedElement is not None:
       
  1357             self.SelectedElement.SetSelected(False)
       
  1358         self.SelectedElement = Graphic_Group(self)
       
  1359         for element in self.GetElements():
       
  1360             self.SelectedElement.SelectElement(element)
       
  1361         self.SelectedElement.SetSelected(True)
       
  1362     
       
  1363 #-------------------------------------------------------------------------------
       
  1364 #                           Popup menu functions
       
  1365 #-------------------------------------------------------------------------------
       
  1366 
       
  1367     def GetForceVariableMenuFunction(self, iec_path, element):
       
  1368         iec_type = self.GetDataType(iec_path)
       
  1369         def ForceVariableFunction(event):
       
  1370             if iec_type is not None:
       
  1371                 dialog = ForceVariableDialog(self.ParentWindow, iec_type, str(element.GetValue()))
       
  1372                 if dialog.ShowModal() == wx.ID_OK:
       
  1373                     self.ParentWindow.AddDebugVariable(iec_path)
       
  1374                     self.ForceDataValue(iec_path, dialog.GetValue())
       
  1375         return ForceVariableFunction
       
  1376 
       
  1377     def GetReleaseVariableMenuFunction(self, iec_path):
       
  1378         def ReleaseVariableFunction(event):
       
  1379             self.ReleaseDataValue(iec_path)
       
  1380         return ReleaseVariableFunction
       
  1381 
       
  1382     def GetChangeVariableTypeMenuFunction(self, type):
       
  1383         def ChangeVariableTypeMenu(event):
       
  1384             self.ChangeVariableType(self.SelectedElement, type)
       
  1385         return ChangeVariableTypeMenu
       
  1386 
       
  1387     def GetChangeConnectionTypeMenuFunction(self, type):
       
  1388         def ChangeConnectionTypeMenu(event):
       
  1389             self.ChangeConnectionType(self.SelectedElement, type)
       
  1390         return ChangeConnectionTypeMenu
       
  1391 
       
  1392     def PopupForceMenu(self):
       
  1393         iec_path = self.GetElementIECPath(self.SelectedElement)
       
  1394         if iec_path is not None:
       
  1395             menu = wx.Menu(title='')
       
  1396             new_id = wx.NewId()
       
  1397             AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Force value"))
       
  1398             self.Bind(wx.EVT_MENU, self.GetForceVariableMenuFunction(iec_path.upper(), self.SelectedElement), id=new_id)
       
  1399             new_id = wx.NewId()
       
  1400             AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Release value"))
       
  1401             self.Bind(wx.EVT_MENU, self.GetReleaseVariableMenuFunction(iec_path.upper()), id=new_id)
       
  1402             if self.SelectedElement.IsForced():
       
  1403                 menu.Enable(new_id, True)
       
  1404             else:
       
  1405                 menu.Enable(new_id, False)
       
  1406             self.Editor.PopupMenu(menu)
       
  1407             menu.Destroy()
       
  1408 
       
  1409     def PopupBlockMenu(self, connector = None):
       
  1410         menu = wx.Menu(title='')
       
  1411         if connector is not None and connector.IsCompatible("BOOL"):
       
  1412             self.AddBlockPinMenuItems(menu, connector)
       
  1413         else:
       
  1414             edit = self.SelectedElement.GetType() in self.Controler.GetProjectPouNames(self.Debug)
       
  1415             self.AddDefaultMenuItems(menu, block=True, edit=edit)
       
  1416         self.Editor.PopupMenu(menu)
       
  1417         menu.Destroy()
       
  1418     
       
  1419     def PopupVariableMenu(self):
       
  1420         menu = wx.Menu(title='')
       
  1421         variable_type = self.SelectedElement.GetType()
       
  1422         for type_label, type in [(_("Input"), INPUT),
       
  1423                                  (_("Output"), OUTPUT),
       
  1424                                  (_("InOut"), INOUT)]:
       
  1425             new_id = wx.NewId()
       
  1426             AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_RADIO, text=type_label)
       
  1427             self.Bind(wx.EVT_MENU, self.GetChangeVariableTypeMenuFunction(type), id=new_id)
       
  1428             if type == variable_type:
       
  1429                 menu.Check(new_id, True)
       
  1430         menu.AppendSeparator()
       
  1431         self.AddDefaultMenuItems(menu, block=True)
       
  1432         self.Editor.PopupMenu(menu)
       
  1433         menu.Destroy()
       
  1434     
       
  1435     def PopupConnectionMenu(self):
       
  1436         menu = wx.Menu(title='')
       
  1437         connection_type = self.SelectedElement.GetType()
       
  1438         for type_label, type in [(_("Connector"), CONNECTOR),
       
  1439                                  (_("Continuation"), CONTINUATION)]:
       
  1440             new_id = wx.NewId()
       
  1441             AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_RADIO, text=type_label)
       
  1442             self.Bind(wx.EVT_MENU, self.GetChangeConnectionTypeMenuFunction(type), id=new_id)
       
  1443             if type == connection_type:
       
  1444                 menu.Check(new_id, True)
       
  1445         menu.AppendSeparator()
       
  1446         self.AddDefaultMenuItems(menu, block=True)
       
  1447         self.Editor.PopupMenu(menu)
       
  1448         menu.Destroy()
       
  1449     
       
  1450     def PopupWireMenu(self, delete=True):
       
  1451         menu = wx.Menu(title='')
       
  1452         self.AddWireMenuItems(menu, delete)
       
  1453         menu.AppendSeparator()
       
  1454         self.AddDefaultMenuItems(menu, block=True)
       
  1455         self.Editor.PopupMenu(menu)
       
  1456         menu.Destroy()
       
  1457         
       
  1458     def PopupDivergenceMenu(self, connector):
       
  1459         menu = wx.Menu(title='')
       
  1460         self.AddDivergenceMenuItems(menu, connector)
       
  1461         menu.AppendSeparator()
       
  1462         self.AddDefaultMenuItems(menu, block=True)
       
  1463         self.Editor.PopupMenu(menu)
       
  1464         menu.Destroy()
       
  1465     
       
  1466     def PopupGroupMenu(self):
       
  1467         menu = wx.Menu(title='')
       
  1468         align_menu = wx.Menu(title='')
       
  1469         self.AddAlignmentMenuItems(align_menu)
       
  1470         menu.AppendMenu(-1, _(u'Alignment'), align_menu)
       
  1471         menu.AppendSeparator()
       
  1472         self.AddDefaultMenuItems(menu, block=True)
       
  1473         self.Editor.PopupMenu(menu)
       
  1474         menu.Destroy()
       
  1475         
       
  1476     def PopupDefaultMenu(self, block=True):
       
  1477         menu = wx.Menu(title='')
       
  1478         self.AddDefaultMenuItems(menu, block=block)
       
  1479         self.Editor.PopupMenu(menu)
       
  1480         menu.Destroy()
       
  1481 
       
  1482 #-------------------------------------------------------------------------------
       
  1483 #                            Menu items functions
       
  1484 #-------------------------------------------------------------------------------
       
  1485 
       
  1486     def OnAlignLeftMenu(self, event):
       
  1487         if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
       
  1488             self.SelectedElement.AlignElements(ALIGN_LEFT, None)
       
  1489             self.RefreshBuffer()
       
  1490             self.Refresh(False)
       
  1491     
       
  1492     def OnAlignCenterMenu(self, event):
       
  1493         if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
       
  1494             self.SelectedElement.AlignElements(ALIGN_CENTER, None)
       
  1495             self.RefreshBuffer()
       
  1496             self.Refresh(False)
       
  1497     
       
  1498     def OnAlignRightMenu(self, event):
       
  1499         if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
       
  1500             self.SelectedElement.AlignElements(ALIGN_RIGHT, None)
       
  1501             self.RefreshBuffer()
       
  1502             self.Refresh(False)
       
  1503     
       
  1504     def OnAlignTopMenu(self, event):
       
  1505         if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
       
  1506             self.SelectedElement.AlignElements(None, ALIGN_TOP)
       
  1507             self.RefreshBuffer()
       
  1508             self.Refresh(False)
       
  1509     
       
  1510     def OnAlignMiddleMenu(self, event):
       
  1511         if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
       
  1512             self.SelectedElement.AlignElements(None, ALIGN_MIDDLE)
       
  1513             self.RefreshBuffer()
       
  1514             self.Refresh(False)
       
  1515     
       
  1516     def OnAlignBottomMenu(self, event):
       
  1517         if self.SelectedElement is not None and isinstance(self.SelectedElement, Graphic_Group):
       
  1518             self.SelectedElement.AlignElements(None, ALIGN_BOTTOM)
       
  1519             self.RefreshBuffer()
       
  1520             self.Refresh(False)
       
  1521         
       
  1522     def OnNoModifierMenu(self, event):
       
  1523         if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
       
  1524             self.SelectedElement.SetConnectorNegated(False)
       
  1525             self.SelectedElement.Refresh()
       
  1526             self.RefreshBuffer()
       
  1527     
       
  1528     def OnNegatedMenu(self, event):
       
  1529         if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
       
  1530             self.SelectedElement.SetConnectorNegated(True)
       
  1531             self.SelectedElement.Refresh()
       
  1532             self.RefreshBuffer()
       
  1533 
       
  1534     def OnRisingEdgeMenu(self, event):
       
  1535         if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
       
  1536             self.SelectedElement.SetConnectorEdge("rising")
       
  1537             self.SelectedElement.Refresh()
       
  1538             self.RefreshBuffer()
       
  1539 
       
  1540     def OnFallingEdgeMenu(self, event):
       
  1541         if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
       
  1542             self.SelectedElement.SetConnectorEdge("falling")
       
  1543             self.SelectedElement.Refresh()
       
  1544             self.RefreshBuffer()
       
  1545 
       
  1546     def OnAddSegmentMenu(self, event):
       
  1547         if self.SelectedElement is not None and self.IsWire(self.SelectedElement):
       
  1548             self.SelectedElement.AddSegment()
       
  1549             self.SelectedElement.Refresh()
       
  1550 
       
  1551     def OnDeleteSegmentMenu(self, event):
       
  1552         if self.SelectedElement is not None and self.IsWire(self.SelectedElement):
       
  1553             self.SelectedElement.DeleteSegment()
       
  1554             self.SelectedElement.Refresh()
       
  1555 
       
  1556     def OnAddBranchMenu(self, event):
       
  1557         if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
       
  1558             self.AddDivergenceBranch(self.SelectedElement)
       
  1559 
       
  1560     def OnDeleteBranchMenu(self, event):
       
  1561         if self.SelectedElement is not None and self.IsBlock(self.SelectedElement):
       
  1562             self.RemoveDivergenceBranch(self.SelectedElement)
       
  1563 
       
  1564     def OnEditBlockMenu(self, event):
       
  1565         if self.SelectedElement is not None:
       
  1566             self.ParentWindow.EditProjectElement(ITEM_POU, "P::%s"%self.SelectedElement.GetType())
       
  1567 
       
  1568     def OnAdjustBlockSizeMenu(self, event):
       
  1569         if self.SelectedElement is not None:
       
  1570             movex, movey = self.SelectedElement.SetBestSize(self.Scaling)
       
  1571             self.SelectedElement.RefreshModel(True)
       
  1572             self.RefreshBuffer()
       
  1573             self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False)
       
  1574 
       
  1575     def OnDeleteMenu(self, event):
       
  1576         if self.SelectedElement is not None:
       
  1577             self.SelectedElement.Delete()
       
  1578             self.SelectedElement = None
       
  1579             self.RefreshBuffer()
       
  1580             self.Refresh(False)
       
  1581 
       
  1582     def OnClearExecutionOrderMenu(self, event):
       
  1583         self.Controler.ClearEditedElementExecutionOrder(self.TagName)
       
  1584         self.RefreshBuffer()
       
  1585         self.RefreshView()
       
  1586         
       
  1587     def OnResetExecutionOrderMenu(self, event):
       
  1588         self.Controler.ResetEditedElementExecutionOrder(self.TagName)
       
  1589         self.RefreshBuffer()
       
  1590         self.RefreshView()
       
  1591 
       
  1592     def GetAddMenuCallBack(self, func, *args):
       
  1593         def AddMenuCallBack(event):
       
  1594             wx.CallAfter(func, self.rubberBand.GetCurrentExtent(), *args)
       
  1595         return AddMenuCallBack
       
  1596 
       
  1597     def GetClipboardCallBack(self, func):
       
  1598         def ClipboardCallback(event):
       
  1599             wx.CallAfter(func)
       
  1600         return ClipboardCallback
       
  1601 
       
  1602 #-------------------------------------------------------------------------------
       
  1603 #                          Mouse event functions
       
  1604 #-------------------------------------------------------------------------------
       
  1605 
       
  1606     def OnViewerMouseEvent(self, event):
       
  1607         if not event.Entering():
       
  1608             self.ResetBuffer()
       
  1609             element = None
       
  1610             if not event.Leaving() and not event.LeftUp() and not event.LeftDClick():
       
  1611                 element = self.FindElement(event, True, False)
       
  1612             if self.ToolTipElement is not None:
       
  1613                 self.ToolTipElement.ClearToolTip()
       
  1614             self.ToolTipElement = element
       
  1615             if self.ToolTipElement is not None:
       
  1616                 tooltip_pos = self.Editor.ClientToScreen(event.GetPosition())
       
  1617                 tooltip_pos.x += 10
       
  1618                 tooltip_pos.y += 10
       
  1619                 self.ToolTipElement.CreateToolTip(tooltip_pos)
       
  1620         event.Skip()
       
  1621     
       
  1622     def OnViewerLeftDown(self, event):
       
  1623         self.Editor.CaptureMouse()
       
  1624         if self.Mode == MODE_SELECTION:
       
  1625             dc = self.GetLogicalDC()
       
  1626             pos = event.GetLogicalPosition(dc)
       
  1627             if event.ShiftDown() and not event.ControlDown() and self.SelectedElement is not None:
       
  1628                 element = self.FindElement(event, True)
       
  1629                 if element is not None:
       
  1630                     if isinstance(self.SelectedElement, Graphic_Group):
       
  1631                         self.SelectedElement.SetSelected(False)
       
  1632                         self.SelectedElement.SelectElement(element)
       
  1633                     elif self.SelectedElement is not None:
       
  1634                         group = Graphic_Group(self)
       
  1635                         group.SelectElement(self.SelectedElement)
       
  1636                         group.SelectElement(element)
       
  1637                         self.SelectedElement = group
       
  1638                     elements = self.SelectedElement.GetElements()
       
  1639                     if len(elements) == 0:
       
  1640                         self.SelectedElement = element
       
  1641                     elif len(elements) == 1:
       
  1642                         self.SelectedElement = elements[0]
       
  1643                     self.SelectedElement.SetSelected(True)
       
  1644                 else:
       
  1645                     self.rubberBand.Reset()
       
  1646                     self.rubberBand.OnLeftDown(event, dc, self.Scaling)
       
  1647             else:
       
  1648                 element = self.FindElement(event)
       
  1649                 if not self.Debug and (element is None or element.TestHandle(event) == (0, 0)):
       
  1650                     connector = self.FindBlockConnector(pos)
       
  1651                 else:
       
  1652                     connector = None
       
  1653                 if not self.Debug and self.DrawingWire:
       
  1654                     self.DrawingWire = False
       
  1655                     if self.SelectedElement is not None:
       
  1656                         if element is None or element.TestHandle(event) == (0, 0):
       
  1657                             connector = self.FindBlockConnector(pos, self.SelectedElement.GetConnectionDirection())
       
  1658                         if connector is not None:
       
  1659                             event.Dragging = lambda : True
       
  1660                             self.SelectedElement.OnMotion(event, dc, self.Scaling)
       
  1661                         if self.SelectedElement.EndConnected is not None:
       
  1662                             self.SelectedElement.ResetPoints()
       
  1663                             self.SelectedElement.GeneratePoints()
       
  1664                             self.SelectedElement.RefreshModel()
       
  1665                             self.SelectedElement.SetSelected(True)
       
  1666                             element = self.SelectedElement
       
  1667                             self.RefreshBuffer()
       
  1668                         else:
       
  1669                             rect = self.SelectedElement.GetRedrawRect()
       
  1670                             self.SelectedElement.Delete()
       
  1671                             self.SelectedElement = None
       
  1672                             element = None
       
  1673                             self.RefreshRect(self.GetScrolledRect(rect), False)
       
  1674                 elif not self.Debug and connector is not None and not event.ControlDown():
       
  1675                     self.DrawingWire = True
       
  1676                     scaled_pos = GetScaledEventPosition(event, dc, self.Scaling)
       
  1677                     if (connector.GetDirection() == EAST):
       
  1678                         wire = Wire(self, [wx.Point(pos.x, pos.y), EAST], [wx.Point(scaled_pos.x, scaled_pos.y), WEST])
       
  1679                     else:
       
  1680                         wire = Wire(self, [wx.Point(pos.x, pos.y), WEST], [wx.Point(scaled_pos.x, scaled_pos.y), EAST])
       
  1681                     wire.oldPos = scaled_pos
       
  1682                     wire.Handle = (HANDLE_POINT, 0)
       
  1683                     wire.ProcessDragging(0, 0, event, None)
       
  1684                     wire.Handle = (HANDLE_POINT, 1)
       
  1685                     self.AddWire(wire)
       
  1686                     if self.SelectedElement is not None:
       
  1687                         self.SelectedElement.SetSelected(False)
       
  1688                     self.SelectedElement = wire
       
  1689                     if self.HighlightedElement is not None:
       
  1690                         self.HighlightedElement.SetHighlighted(False)
       
  1691                     self.HighlightedElement = wire
       
  1692                     self.RefreshVisibleElements()
       
  1693                     self.SelectedElement.SetHighlighted(True)
       
  1694                 else:
       
  1695                     if self.SelectedElement is not None and self.SelectedElement != element:
       
  1696                         self.SelectedElement.SetSelected(False)
       
  1697                         self.SelectedElement = None
       
  1698                     if element is not None:
       
  1699                         self.SelectedElement = element
       
  1700                         if self.Debug:
       
  1701                             self.StartMousePos = event.GetPosition()
       
  1702                             Graphic_Element.OnLeftDown(self.SelectedElement, event, dc, self.Scaling)
       
  1703                         else:
       
  1704                             self.SelectedElement.OnLeftDown(event, dc, self.Scaling)
       
  1705                         self.SelectedElement.Refresh()
       
  1706                     else:
       
  1707                         self.rubberBand.Reset()
       
  1708                         self.rubberBand.OnLeftDown(event, dc, self.Scaling)
       
  1709         elif self.Mode in [MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT, 
       
  1710                            MODE_CONTACT, MODE_COIL, MODE_POWERRAIL, MODE_INITIALSTEP, 
       
  1711                            MODE_STEP, MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION]:
       
  1712             self.rubberBand.Reset()
       
  1713             self.rubberBand.OnLeftDown(event, self.GetLogicalDC(), self.Scaling)
       
  1714         elif self.Mode == MODE_MOTION:
       
  1715             self.StartMousePos = event.GetPosition()
       
  1716             self.StartScreenPos = self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)
       
  1717         event.Skip()
       
  1718 
       
  1719     def OnViewerLeftUp(self, event):
       
  1720         self.StartMousePos = None
       
  1721         if self.rubberBand.IsShown():
       
  1722             if self.Mode == MODE_SELECTION:
       
  1723                 new_elements = self.SearchElements(self.rubberBand.GetCurrentExtent())
       
  1724                 self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling)
       
  1725                 if event.ShiftDown() and self.SelectedElement is not None:
       
  1726                     if isinstance(self.SelectedElement, Graphic_Group):
       
  1727                         elements = self.SelectedElement.GetElements()
       
  1728                     else:
       
  1729                         elements = [self.SelectedElement]
       
  1730                     for element in elements:
       
  1731                         if element not in new_elements:
       
  1732                             new_elements.append(element)
       
  1733                 if len(new_elements) == 1:
       
  1734                     self.SelectedElement = new_elements[0]
       
  1735                     self.SelectedElement.SetSelected(True)
       
  1736                 elif len(new_elements) > 1:
       
  1737                     self.SelectedElement = Graphic_Group(self)
       
  1738                     self.SelectedElement.SetElements(new_elements)
       
  1739                     self.SelectedElement.SetSelected(True)
       
  1740             else:
       
  1741                 bbox = self.rubberBand.GetCurrentExtent()
       
  1742                 self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling)                
       
  1743                 if self.Mode == MODE_BLOCK:
       
  1744                     wx.CallAfter(self.AddNewBlock, bbox)
       
  1745                 elif self.Mode == MODE_VARIABLE:
       
  1746                     wx.CallAfter(self.AddNewVariable, bbox)
       
  1747                 elif self.Mode == MODE_CONNECTION:
       
  1748                     wx.CallAfter(self.AddNewConnection, bbox)
       
  1749                 elif self.Mode == MODE_COMMENT:
       
  1750                     wx.CallAfter(self.AddNewComment, bbox)
       
  1751                 elif self.Mode == MODE_CONTACT:
       
  1752                     wx.CallAfter(self.AddNewContact, bbox)
       
  1753                 elif self.Mode == MODE_COIL:
       
  1754                     wx.CallAfter(self.AddNewCoil, bbox)
       
  1755                 elif self.Mode == MODE_POWERRAIL:
       
  1756                     wx.CallAfter(self.AddNewPowerRail, bbox)
       
  1757                 elif self.Mode == MODE_INITIALSTEP:
       
  1758                     wx.CallAfter(self.AddNewStep, bbox, True)
       
  1759                 elif self.Mode == MODE_STEP:
       
  1760                     wx.CallAfter(self.AddNewStep, bbox, False)
       
  1761                 elif self.Mode == MODE_TRANSITION:
       
  1762                     wx.CallAfter(self.AddNewTransition, bbox)
       
  1763                 elif self.Mode == MODE_DIVERGENCE:
       
  1764                     wx.CallAfter(self.AddNewDivergence, bbox)
       
  1765                 elif self.Mode == MODE_JUMP:
       
  1766                     wx.CallAfter(self.AddNewJump, bbox)
       
  1767                 elif self.Mode == MODE_ACTION:
       
  1768                     wx.CallAfter(self.AddNewActionBlock, bbox)
       
  1769         elif self.Mode == MODE_SELECTION and self.SelectedElement is not None:
       
  1770             dc = self.GetLogicalDC()
       
  1771             if not self.Debug and self.DrawingWire:
       
  1772                 pos = event.GetLogicalPosition(dc)
       
  1773                 connector = self.FindBlockConnector(pos, self.SelectedElement.GetConnectionDirection())
       
  1774                 if self.SelectedElement.EndConnected is not None:
       
  1775                     self.DrawingWire = False
       
  1776                     self.SelectedElement.StartConnected.HighlightParentBlock(False)
       
  1777                     self.SelectedElement.EndConnected.HighlightParentBlock(False)
       
  1778                     self.SelectedElement.ResetPoints()
       
  1779                     self.SelectedElement.OnMotion(event, dc, self.Scaling)
       
  1780                     self.SelectedElement.GeneratePoints()
       
  1781                     self.SelectedElement.RefreshModel()
       
  1782                     self.SelectedElement.SetSelected(True)
       
  1783                     self.SelectedElement.HighlightPoint(pos)
       
  1784                     self.RefreshBuffer()
       
  1785                 elif connector is None or self.SelectedElement.GetDragging():
       
  1786                     self.DrawingWire = False
       
  1787                     rect = self.SelectedElement.GetRedrawRect()
       
  1788                     wire = self.SelectedElement
       
  1789                     self.SelectedElement = self.SelectedElement.StartConnected.GetParentBlock()
       
  1790                     self.SelectedElement.SetSelected(True)
       
  1791                     rect.Union(self.SelectedElement.GetRedrawRect())
       
  1792                     wire.Delete()
       
  1793                     self.RefreshRect(self.GetScrolledRect(rect), False)
       
  1794             else:
       
  1795                 if self.Debug:
       
  1796                     Graphic_Element.OnLeftUp(self.SelectedElement, event, dc, self.Scaling)
       
  1797                 else:
       
  1798                     self.SelectedElement.OnLeftUp(event, dc, self.Scaling)
       
  1799                 wx.CallAfter(self.SetCurrentCursor, 0)
       
  1800         elif self.Mode == MODE_MOTION:
       
  1801             self.StartMousePos = None
       
  1802             self.StartScreenPos = None
       
  1803         if self.Mode != MODE_SELECTION and not self.SavedMode:
       
  1804             wx.CallAfter(self.ParentWindow.ResetCurrentMode)
       
  1805         if self.Editor.HasCapture():
       
  1806             self.Editor.ReleaseMouse()
       
  1807         event.Skip()
       
  1808     
       
  1809     def OnViewerMiddleDown(self, event):
       
  1810         self.Editor.CaptureMouse()
       
  1811         self.StartMousePos = event.GetPosition()
       
  1812         self.StartScreenPos = self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)
       
  1813         event.Skip()
       
  1814         
       
  1815     def OnViewerMiddleUp(self, event):
       
  1816         self.StartMousePos = None
       
  1817         self.StartScreenPos = None
       
  1818         if self.Editor.HasCapture():
       
  1819             self.Editor.ReleaseMouse()
       
  1820         event.Skip()
       
  1821     
       
  1822     def OnViewerRightDown(self, event):
       
  1823         self.Editor.CaptureMouse()
       
  1824         if self.Mode == MODE_SELECTION:
       
  1825             element = self.FindElement(event)
       
  1826             if self.SelectedElement is not None and self.SelectedElement != element:
       
  1827                 self.SelectedElement.SetSelected(False)
       
  1828                 self.SelectedElement = None
       
  1829             if element is not None:
       
  1830                 self.SelectedElement = element
       
  1831                 if self.Debug:
       
  1832                     Graphic_Element.OnRightDown(self.SelectedElement, event, self.GetLogicalDC(), self.Scaling)
       
  1833                 else:
       
  1834                     self.SelectedElement.OnRightDown(event, self.GetLogicalDC(), self.Scaling)
       
  1835                 self.SelectedElement.Refresh()
       
  1836         event.Skip()
       
  1837     
       
  1838     def OnViewerRightUp(self, event):
       
  1839         dc = self.GetLogicalDC()
       
  1840         self.rubberBand.Reset()
       
  1841         self.rubberBand.OnLeftDown(event, dc, self.Scaling)
       
  1842         self.rubberBand.OnLeftUp(event, dc, self.Scaling)
       
  1843         if self.SelectedElement is not None:
       
  1844             if self.Debug:
       
  1845                 Graphic_Element.OnRightUp(self.SelectedElement, event, self.GetLogicalDC(), self.Scaling)
       
  1846             else:
       
  1847                 self.SelectedElement.OnRightUp(event, self.GetLogicalDC(), self.Scaling)
       
  1848             wx.CallAfter(self.SetCurrentCursor, 0)
       
  1849         elif not self.Debug:
       
  1850             self.PopupDefaultMenu(False)
       
  1851         if self.Editor.HasCapture():
       
  1852             self.Editor.ReleaseMouse()
       
  1853         event.Skip()
       
  1854     
       
  1855     def OnViewerLeftDClick(self, event):
       
  1856         element = self.FindElement(event, connectors=False)
       
  1857         if self.Mode == MODE_SELECTION and element is not None:
       
  1858             if self.SelectedElement is not None and self.SelectedElement != element:
       
  1859                 self.SelectedElement.SetSelected(False)
       
  1860             if self.HighlightedElement is not None and self.HighlightedElement != element:
       
  1861                 self.HighlightedElement.SetHighlighted(False)
       
  1862                     
       
  1863             self.SelectedElement = element
       
  1864             self.HighlightedElement = element
       
  1865             self.SelectedElement.SetHighlighted(True)
       
  1866             
       
  1867             if self.Debug:
       
  1868                 if isinstance(self.SelectedElement, FBD_Block):
       
  1869                     instance_type = self.SelectedElement.GetType()
       
  1870                     pou_type = {
       
  1871                         "program": ITEM_PROGRAM,
       
  1872                         "functionBlock": ITEM_FUNCTIONBLOCK,
       
  1873                     }.get(self.Controler.GetPouType(instance_type))
       
  1874                     if pou_type is not None and instance_type in self.Controler.GetProjectPouNames(self.Debug):
       
  1875                         self.ParentWindow.OpenDebugViewer(pou_type, 
       
  1876                             "%s.%s"%(self.GetInstancePath(True), self.SelectedElement.GetName()),
       
  1877                             self.Controler.ComputePouName(instance_type))
       
  1878                 else:
       
  1879                     iec_path = self.GetElementIECPath(self.SelectedElement)
       
  1880                     if iec_path is not None:
       
  1881                         if isinstance(self.SelectedElement, Wire):
       
  1882                             if self.SelectedElement.EndConnected is not None:
       
  1883                                 self.ParentWindow.OpenDebugViewer(ITEM_VAR_LOCAL, iec_path, 
       
  1884                                         self.SelectedElement.EndConnected.GetType())
       
  1885                         else:
       
  1886                             self.ParentWindow.OpenDebugViewer(ITEM_VAR_LOCAL, iec_path, "BOOL")
       
  1887             elif event.ControlDown() and not event.ShiftDown():
       
  1888                 if not isinstance(self.SelectedElement, Graphic_Group):
       
  1889                     if isinstance(self.SelectedElement, FBD_Block):
       
  1890                         instance_type = self.SelectedElement.GetType()
       
  1891                     else:
       
  1892                         instance_type = None
       
  1893                     if instance_type in self.Controler.GetProjectPouNames(self.Debug):
       
  1894                         self.ParentWindow.EditProjectElement(ITEM_POU, 
       
  1895                                 self.Controler.ComputePouName(instance_type))
       
  1896                     else:
       
  1897                         self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling)
       
  1898             elif event.ControlDown() and event.ShiftDown():
       
  1899                 movex, movey = self.SelectedElement.SetBestSize(self.Scaling)
       
  1900                 self.SelectedElement.RefreshModel()
       
  1901                 self.RefreshBuffer()
       
  1902                 self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False)
       
  1903             else:
       
  1904                 self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling)
       
  1905         event.Skip()
       
  1906     
       
  1907     def OnViewerMotion(self, event):
       
  1908         if self.Editor.HasCapture() and not event.Dragging():
       
  1909             return
       
  1910         refresh = False
       
  1911         dc = self.GetLogicalDC()
       
  1912         pos = GetScaledEventPosition(event, dc, self.Scaling)
       
  1913         if event.MiddleIsDown() or self.Mode == MODE_MOTION:
       
  1914             if self.StartMousePos is not None and self.StartScreenPos is not None:
       
  1915                 new_pos = event.GetPosition()
       
  1916                 xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
       
  1917                 ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
       
  1918                 scrollx = max(0, self.StartScreenPos[0] - (new_pos[0] - self.StartMousePos[0]) / SCROLLBAR_UNIT)
       
  1919                 scrolly = max(0, self.StartScreenPos[1] - (new_pos[1] - self.StartMousePos[1]) / SCROLLBAR_UNIT)
       
  1920                 if scrollx > xmax or scrolly > ymax:
       
  1921                     self.RefreshScrollBars(max(0, scrollx - xmax), max(0, scrolly - ymax))
       
  1922                     self.Scroll(scrollx, scrolly)
       
  1923                 else:
       
  1924                     self.Scroll(scrollx, scrolly)
       
  1925                     self.RefreshScrollBars()
       
  1926                 self.RefreshVisibleElements()
       
  1927         else:
       
  1928             if not event.Dragging():
       
  1929                 highlighted = self.FindElement(event, connectors=False) 
       
  1930                 if self.HighlightedElement is not None and self.HighlightedElement != highlighted:
       
  1931                     self.HighlightedElement.SetHighlighted(False)
       
  1932                     self.HighlightedElement = None
       
  1933                 if highlighted is not None:
       
  1934                     if isinstance(highlighted, (Wire, Graphic_Group)):
       
  1935                         highlighted.HighlightPoint(pos)
       
  1936                     if self.HighlightedElement != highlighted:
       
  1937                         highlighted.SetHighlighted(True)
       
  1938                 self.HighlightedElement = highlighted
       
  1939             if self.rubberBand.IsShown():
       
  1940                 self.rubberBand.OnMotion(event, dc, self.Scaling)
       
  1941             elif not self.Debug and self.Mode == MODE_SELECTION and self.SelectedElement is not None:
       
  1942                 if self.DrawingWire:
       
  1943                     connector = self.FindBlockConnector(pos, self.SelectedElement.GetConnectionDirection(), self.SelectedElement.EndConnected)
       
  1944                     if not connector or self.SelectedElement.EndConnected == None:
       
  1945                         self.SelectedElement.ResetPoints()
       
  1946                         movex, movey = self.SelectedElement.OnMotion(event, dc, self.Scaling)
       
  1947                         self.SelectedElement.GeneratePoints()
       
  1948                         if movex != 0 or movey != 0:
       
  1949                             self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False)
       
  1950                     else:
       
  1951                         self.SelectedElement.HighlightPoint(pos)
       
  1952                 else:
       
  1953                     movex, movey = self.SelectedElement.OnMotion(event, dc, self.Scaling)
       
  1954                     if movex != 0 or movey != 0:
       
  1955                         self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False)
       
  1956             elif self.Debug and self.StartMousePos is not None and event.Dragging():
       
  1957                 pos = event.GetPosition()
       
  1958                 if abs(self.StartMousePos.x - pos.x) > 5 or abs(self.StartMousePos.y - pos.y) > 5:
       
  1959                     iec_path = self.GetElementIECPath(self.SelectedElement)
       
  1960                     if iec_path is not None:
       
  1961                         self.StartMousePos = None
       
  1962                         if self.HighlightedElement is not None:
       
  1963                             self.HighlightedElement.SetHighlighted(False)
       
  1964                             self.HighlightedElement = None
       
  1965                         data = wx.TextDataObject(str((iec_path, "debug")))
       
  1966                         dragSource = wx.DropSource(self.Editor)
       
  1967                         dragSource.SetData(data)
       
  1968                         dragSource.DoDragDrop()
       
  1969                         if self.Editor.HasCapture():
       
  1970                             self.Editor.ReleaseMouse()
       
  1971                         wx.CallAfter(self.SetCurrentCursor, 0)
       
  1972             self.UpdateScrollPos(event)
       
  1973         event.Skip()
       
  1974 
       
  1975     def OnLeaveViewer(self, event):
       
  1976         if self.StartScreenPos is None:
       
  1977             self.StartMousePos = None
       
  1978         if self.SelectedElement is not None and self.SelectedElement.GetDragging():
       
  1979             event.Skip()
       
  1980         elif self.HighlightedElement is not None:
       
  1981             self.HighlightedElement.SetHighlighted(False)
       
  1982             self.HighlightedElement = None
       
  1983         event.Skip()
       
  1984 
       
  1985     def UpdateScrollPos(self, event):
       
  1986         if (event.Dragging() and self.SelectedElement is not None) or self.rubberBand.IsShown():
       
  1987             position = event.GetPosition()
       
  1988             move_window = wx.Point()
       
  1989             window_size = self.Editor.GetClientSize()
       
  1990             xstart, ystart = self.GetViewStart()
       
  1991             if position.x < SCROLL_ZONE and xstart > 0:
       
  1992                 move_window.x = -1
       
  1993             elif position.x > window_size[0] - SCROLL_ZONE:
       
  1994                 move_window.x = 1
       
  1995             if position.y < SCROLL_ZONE and ystart > 0:
       
  1996                 move_window.y = -1
       
  1997             elif position.y > window_size[1] - SCROLL_ZONE:
       
  1998                 move_window.y = 1
       
  1999             if move_window.x != 0 or move_window.y != 0:
       
  2000                 self.RefreshVisibleElements(xp = xstart + move_window.x, yp = ystart + move_window.y)
       
  2001                 self.Scroll(xstart + move_window.x, ystart + move_window.y)
       
  2002                 self.RefreshScrollBars(move_window.x, move_window.y)
       
  2003 
       
  2004 #-------------------------------------------------------------------------------
       
  2005 #                          Keyboard event functions
       
  2006 #-------------------------------------------------------------------------------
       
  2007 
       
  2008     ARROW_KEY_MOVE = {
       
  2009         wx.WXK_LEFT: (-1, 0),
       
  2010         wx.WXK_RIGHT: (1, 0),
       
  2011         wx.WXK_UP: (0, -1),
       
  2012         wx.WXK_DOWN: (0, 1),
       
  2013     }
       
  2014 
       
  2015     def OnChar(self, event):
       
  2016         xpos, ypos = self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)
       
  2017         xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
       
  2018         ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
       
  2019         keycode = event.GetKeyCode()
       
  2020         if self.Scaling is not None:
       
  2021             scaling = self.Scaling
       
  2022         else:
       
  2023             scaling = (8, 8)
       
  2024         if not self.Debug and keycode == wx.WXK_DELETE and self.SelectedElement is not None:
       
  2025             rect = self.SelectedElement.GetRedrawRect(1, 1)
       
  2026             self.SelectedElement.Delete()
       
  2027             self.SelectedElement = None
       
  2028             self.RefreshBuffer()
       
  2029             self.RefreshScrollBars()
       
  2030             wx.CallAfter(self.SetCurrentCursor, 0)
       
  2031             self.RefreshRect(self.GetScrolledRect(rect), False)
       
  2032         elif not self.Debug and keycode == wx.WXK_RETURN and self.SelectedElement is not None:
       
  2033             self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling)
       
  2034         elif self.ARROW_KEY_MOVE.has_key(keycode):
       
  2035             move = self.ARROW_KEY_MOVE[keycode]
       
  2036             if event.ControlDown() and event.ShiftDown():
       
  2037                 self.Scroll({-1: 0, 0: xpos, 1: xmax}[move[0]],
       
  2038                             {-1: 0, 0: ypos, 1: ymax}[move[1]])
       
  2039                 self.RefreshVisibleElements()
       
  2040             elif event.ControlDown():
       
  2041                 self.Scroll(xpos + move[0], ypos + move[1])
       
  2042                 self.RefreshScrollBars()
       
  2043                 self.RefreshVisibleElements()
       
  2044             elif not self.Debug and self.SelectedElement is not None:
       
  2045                 movex, movey = move
       
  2046                 if not event.AltDown() or event.ShiftDown():
       
  2047                     movex *= scaling[0]
       
  2048                     movey *= scaling[1] 
       
  2049                     if event.ShiftDown() and not event.AltDown():
       
  2050                         movex *= 10
       
  2051                         movey *= 10
       
  2052                 self.SelectedElement.Move(movex, movey)
       
  2053                 self.StartBuffering()
       
  2054                 self.SelectedElement.RefreshModel()
       
  2055                 self.RefreshScrollBars()
       
  2056                 self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False)
       
  2057         elif not self.Debug and keycode == wx.WXK_SPACE and self.SelectedElement is not None and self.SelectedElement.Dragging:
       
  2058             if self.IsBlock(self.SelectedElement) or self.IsComment(self.SelectedElement):
       
  2059                 block = self.CopyBlock(self.SelectedElement, wx.Point(*self.SelectedElement.GetPosition()))
       
  2060                 event = wx.MouseEvent()
       
  2061                 event.m_x, event.m_y = self.Editor.ScreenToClient(wx.GetMousePosition())
       
  2062                 dc = self.GetLogicalDC()
       
  2063                 self.SelectedElement.OnLeftUp(event, dc, self.Scaling)
       
  2064                 self.SelectedElement.SetSelected(False)
       
  2065                 block.OnLeftDown(event, dc, self.Scaling)
       
  2066                 self.SelectedElement = block
       
  2067                 self.SelectedElement.SetSelected(True)
       
  2068                 self.RefreshVariablePanel()
       
  2069                 self.RefreshVisibleElements()
       
  2070             else:
       
  2071                 event.Skip()
       
  2072         elif keycode == ord("+"):
       
  2073             self.SetScale(self.CurrentScale + 1)
       
  2074             self.ParentWindow.RefreshDisplayMenu()
       
  2075         elif keycode == ord("-"):
       
  2076             self.SetScale(self.CurrentScale - 1)
       
  2077             self.ParentWindow.RefreshDisplayMenu()
       
  2078         else:
       
  2079             event.Skip()
       
  2080 
       
  2081 #-------------------------------------------------------------------------------
       
  2082 #                  Model adding functions from Drop Target
       
  2083 #-------------------------------------------------------------------------------
       
  2084 
       
  2085     def AddVariableBlock(self, x, y, scaling, var_class, var_name, var_type):
       
  2086         id = self.GetNewId()
       
  2087         variable = FBD_Variable(self, var_class, var_name, var_type, id)
       
  2088         width, height = variable.GetMinSize()
       
  2089         if scaling is not None:
       
  2090             x = round(float(x) / float(scaling[0])) * scaling[0]
       
  2091             y = round(float(y) / float(scaling[1])) * scaling[1]
       
  2092             width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
       
  2093             height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
       
  2094         variable.SetPosition(x, y)
       
  2095         variable.SetSize(width, height)
       
  2096         self.AddBlock(variable)
       
  2097         self.Controler.AddEditedElementVariable(self.GetTagName(), id, var_class)
       
  2098         self.RefreshVariableModel(variable)
       
  2099         self.RefreshBuffer()
       
  2100         self.RefreshScrollBars()
       
  2101         self.RefreshVisibleElements()
       
  2102         self.Refresh(False)
       
  2103 
       
  2104 #-------------------------------------------------------------------------------
       
  2105 #                          Model adding functions
       
  2106 #-------------------------------------------------------------------------------
       
  2107 
       
  2108     def GetScaledSize(self, width, height):
       
  2109         if self.Scaling is not None:
       
  2110             width = round(float(width) / float(self.Scaling[0]) + 0.4) * self.Scaling[0]
       
  2111             height = round(float(height) / float(self.Scaling[1]) + 0.4) * self.Scaling[1]
       
  2112         return width, height
       
  2113     
       
  2114     def AddNewBlock(self, bbox):
       
  2115         dialog = FBDBlockDialog(self.ParentWindow, self.Controler)
       
  2116         dialog.SetPreviewFont(self.GetFont())
       
  2117         dialog.SetBlockList(self.Controler.GetBlockTypes(self.TagName, self.Debug))
       
  2118         dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
       
  2119         dialog.SetPouElementNames(self.Controler.GetEditedElementVariables(self.TagName, self.Debug))
       
  2120         dialog.SetMinBlockSize((bbox.width, bbox.height))
       
  2121         if dialog.ShowModal() == wx.ID_OK:
       
  2122             id = self.GetNewId()
       
  2123             values = dialog.GetValues()
       
  2124             values.setdefault("name", "")
       
  2125             block = FBD_Block(self, values["type"], values["name"], id, 
       
  2126                     values["extension"], values["inputs"], 
       
  2127                     executionControl = values["executionControl"],
       
  2128                     executionOrder = values["executionOrder"])
       
  2129             block.SetPosition(bbox.x, bbox.y)
       
  2130             block.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2131             self.AddBlock(block)
       
  2132             self.Controler.AddEditedElementBlock(self.TagName, id, values["type"], values.get("name", None))
       
  2133             self.RefreshBlockModel(block)
       
  2134             self.RefreshBuffer()
       
  2135             self.RefreshScrollBars()
       
  2136             self.RefreshVisibleElements()
       
  2137             self.RefreshVariablePanel()
       
  2138             self.ParentWindow.RefreshPouInstanceVariablesPanel()
       
  2139             block.Refresh()
       
  2140         dialog.Destroy()
       
  2141     
       
  2142     def AddNewVariable(self, bbox):
       
  2143         words = self.TagName.split("::")
       
  2144         if words[0] == "T":
       
  2145             dialog = FBDVariableDialog(self.ParentWindow, self.Controler, words[2])
       
  2146         else:
       
  2147             dialog = FBDVariableDialog(self.ParentWindow, self.Controler)
       
  2148         dialog.SetPreviewFont(self.GetFont())
       
  2149         dialog.SetMinVariableSize((bbox.width, bbox.height))
       
  2150         varlist = []
       
  2151         vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
       
  2152         if vars:
       
  2153             for var in vars:
       
  2154                 if var["Edit"]:
       
  2155                     varlist.append((var["Name"], var["Class"], var["Type"]))
       
  2156         returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
       
  2157         if returntype:
       
  2158             varlist.append((self.Controler.GetEditedElementName(self.TagName), "Output", returntype))
       
  2159         dialog.SetVariables(varlist)
       
  2160         if dialog.ShowModal() == wx.ID_OK:
       
  2161             id = self.GetNewId()
       
  2162             values = dialog.GetValues()
       
  2163             variable = FBD_Variable(self, values["type"], values["name"], values["value_type"], id)
       
  2164             variable.SetPosition(bbox.x, bbox.y)
       
  2165             variable.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2166             self.AddBlock(variable)
       
  2167             self.Controler.AddEditedElementVariable(self.TagName, id, values["type"])
       
  2168             self.RefreshVariableModel(variable)
       
  2169             self.RefreshBuffer()
       
  2170             self.RefreshScrollBars()
       
  2171             self.RefreshVisibleElements()
       
  2172             variable.Refresh()
       
  2173         dialog.Destroy()
       
  2174 
       
  2175     def AddNewConnection(self, bbox):
       
  2176         dialog = ConnectionDialog(self.ParentWindow, self.Controler)
       
  2177         dialog.SetPreviewFont(self.GetFont())
       
  2178         dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
       
  2179         dialog.SetPouElementNames(self.Controler.GetEditedElementVariables(self.TagName, self.Debug))
       
  2180         dialog.SetMinConnectionSize((bbox.width, bbox.height))
       
  2181         if dialog.ShowModal() == wx.ID_OK:
       
  2182             id = self.GetNewId()
       
  2183             values = dialog.GetValues()
       
  2184             connection = FBD_Connector(self, values["type"], values["name"], id)
       
  2185             connection.SetPosition(bbox.x, bbox.y)
       
  2186             connection.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2187             self.AddBlock(connection)
       
  2188             self.Controler.AddEditedElementConnection(self.TagName, id, values["type"])
       
  2189             self.RefreshConnectionModel(connection)
       
  2190             self.RefreshBuffer()
       
  2191             self.RefreshScrollBars()
       
  2192             self.RefreshVisibleElements()
       
  2193             connection.Refresh()
       
  2194         dialog.Destroy()
       
  2195 
       
  2196     def AddNewComment(self, bbox):
       
  2197         if wx.VERSION >= (2, 5, 0):
       
  2198             dialog = wx.TextEntryDialog(self.ParentWindow, _("Edit comment"), _("Please enter comment text"), "", wx.OK|wx.CANCEL|wx.TE_MULTILINE)
       
  2199         else:
       
  2200             dialog = wx.TextEntryDialog(self.ParentWindow, _("Edit comment"), _("Please enter comment text"), "", wx.OK|wx.CANCEL)
       
  2201         dialog.SetClientSize(wx.Size(400, 200))
       
  2202         if dialog.ShowModal() == wx.ID_OK:
       
  2203             value = dialog.GetValue()
       
  2204             id = self.GetNewId()
       
  2205             comment = Comment(self, value, id)
       
  2206             comment.SetPosition(bbox.x, bbox.y)
       
  2207             min_width, min_height = comment.GetMinSize()
       
  2208             comment.SetSize(*self.GetScaledSize(max(min_width,bbox.width),max(min_height,bbox.height)))
       
  2209             self.AddComment(comment)
       
  2210             self.Controler.AddEditedElementComment(self.TagName, id)
       
  2211             self.RefreshCommentModel(comment)
       
  2212             self.RefreshBuffer()
       
  2213             self.RefreshScrollBars()
       
  2214             self.RefreshVisibleElements()
       
  2215             comment.Refresh()
       
  2216         dialog.Destroy()
       
  2217 
       
  2218     def AddNewContact(self, bbox):
       
  2219         dialog = LDElementDialog(self.ParentWindow, self.Controler, "contact")
       
  2220         dialog.SetPreviewFont(self.GetFont())
       
  2221         varlist = []
       
  2222         vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
       
  2223         if vars:
       
  2224             for var in vars:
       
  2225                 if var["Type"] == "BOOL":
       
  2226                     varlist.append(var["Name"])
       
  2227         dialog.SetVariables(varlist)
       
  2228         dialog.SetValues({"name":"","type":CONTACT_NORMAL})
       
  2229         dialog.SetElementSize((bbox.width, bbox.height))
       
  2230         if dialog.ShowModal() == wx.ID_OK:
       
  2231             id = self.GetNewId()
       
  2232             values = dialog.GetValues()
       
  2233             contact = LD_Contact(self, values["type"], values["name"], id)
       
  2234             contact.SetPosition(bbox.x, bbox.y)
       
  2235             contact.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2236             self.AddBlock(contact)
       
  2237             self.Controler.AddEditedElementContact(self.TagName, id)
       
  2238             self.RefreshContactModel(contact)
       
  2239             self.RefreshBuffer()
       
  2240             self.RefreshScrollBars()
       
  2241             self.RefreshVisibleElements()
       
  2242             contact.Refresh()
       
  2243         dialog.Destroy()
       
  2244 
       
  2245     def AddNewCoil(self, bbox):
       
  2246         dialog = LDElementDialog(self.ParentWindow, self.Controler, "coil")
       
  2247         dialog.SetPreviewFont(self.GetFont())
       
  2248         varlist = []
       
  2249         vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
       
  2250         if vars:
       
  2251             for var in vars:
       
  2252                 if var["Class"] != "Input" and var["Type"] == "BOOL":
       
  2253                     varlist.append(var["Name"])
       
  2254         returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
       
  2255         if returntype == "BOOL":
       
  2256             varlist.append(self.Controler.GetEditedElementName(self.TagName))
       
  2257         dialog.SetVariables(varlist)
       
  2258         dialog.SetValues({"name":"","type":COIL_NORMAL})
       
  2259         dialog.SetElementSize((bbox.width, bbox.height))
       
  2260         if dialog.ShowModal() == wx.ID_OK:
       
  2261             id = self.GetNewId()
       
  2262             values = dialog.GetValues()
       
  2263             coil = LD_Coil(self, values["type"], values["name"], id)
       
  2264             coil.SetPosition(bbox.x, bbox.y)
       
  2265             coil.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2266             self.AddBlock(coil)
       
  2267             self.Controler.AddEditedElementCoil(self.TagName, id)
       
  2268             self.RefreshCoilModel(coil)
       
  2269             self.RefreshBuffer()
       
  2270             self.RefreshScrollBars()
       
  2271             self.RefreshVisibleElements()
       
  2272             coil.Refresh()
       
  2273         dialog.Destroy()
       
  2274 
       
  2275     def AddNewPowerRail(self, bbox):
       
  2276         dialog = LDPowerRailDialog(self.ParentWindow, self.Controler)
       
  2277         dialog.SetPreviewFont(self.GetFont())
       
  2278         dialog.SetMinSize((bbox.width, bbox.height))
       
  2279         if dialog.ShowModal() == wx.ID_OK:
       
  2280             id = self.GetNewId()
       
  2281             values = dialog.GetValues()
       
  2282             powerrail = LD_PowerRail(self, values["type"], id, values["number"])
       
  2283             powerrail.SetPosition(bbox.x, bbox.y)
       
  2284             powerrail.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2285             self.AddBlock(powerrail)
       
  2286             self.Controler.AddEditedElementPowerRail(self.TagName, id, values["type"])
       
  2287             self.RefreshPowerRailModel(powerrail)
       
  2288             self.RefreshBuffer()
       
  2289             self.RefreshScrollBars()
       
  2290             self.RefreshVisibleElements()
       
  2291             powerrail.Refresh()
       
  2292         dialog.Destroy()
       
  2293 
       
  2294     def AddNewStep(self, bbox, initial = False):
       
  2295         dialog = SFCStepDialog(self.ParentWindow, self.Controler, initial)
       
  2296         dialog.SetPreviewFont(self.GetFont())
       
  2297         dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
       
  2298         dialog.SetVariables(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
       
  2299         dialog.SetStepNames([block.GetName() for block in self.Blocks.itervalues() if isinstance(block, SFC_Step)])
       
  2300         dialog.SetMinStepSize((bbox.width, bbox.height))
       
  2301         if dialog.ShowModal() == wx.ID_OK:
       
  2302             id = self.GetNewId()
       
  2303             values = dialog.GetValues()
       
  2304             step = SFC_Step(self, values["name"], initial, id)
       
  2305             if values["input"]:
       
  2306                 step.AddInput()
       
  2307             else:
       
  2308                 step.RemoveInput()
       
  2309             if values["output"]:
       
  2310                 step.AddOutput()
       
  2311             else:
       
  2312                 step.RemoveOutput()
       
  2313             if values["action"]:
       
  2314                 step.AddAction()    
       
  2315             else:
       
  2316                 step.RemoveAction()
       
  2317             step.SetPosition(bbox.x, bbox.y)
       
  2318             min_width, min_height = step.GetMinSize()
       
  2319             step.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
       
  2320             self.AddBlock(step)
       
  2321             self.Controler.AddEditedElementStep(self.TagName, id)
       
  2322             self.RefreshStepModel(step)
       
  2323             self.RefreshBuffer()
       
  2324             self.RefreshScrollBars()
       
  2325             self.RefreshVisibleElements()
       
  2326             step.Refresh()
       
  2327         dialog.Destroy()
       
  2328 
       
  2329     def AddNewTransition(self, bbox):
       
  2330         dialog = SFCTransitionDialog(self.ParentWindow, self.Controler, self.GetDrawingMode() == FREEDRAWING_MODE)
       
  2331         dialog.SetPreviewFont(self.GetFont())
       
  2332         dialog.SetTransitions(self.Controler.GetEditedElementTransitions(self.TagName, self.Debug))
       
  2333         if dialog.ShowModal() == wx.ID_OK:
       
  2334             id = self.GetNewId()
       
  2335             values = dialog.GetValues()
       
  2336             transition = SFC_Transition(self, values["type"], values["value"], values["priority"], id)
       
  2337             transition.SetPosition(bbox.x, bbox.y)
       
  2338             min_width, min_height = transition.GetMinSize()
       
  2339             transition.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
       
  2340             self.AddBlock(transition)
       
  2341             self.Controler.AddEditedElementTransition(self.TagName, id)
       
  2342             self.RefreshTransitionModel(transition)
       
  2343             self.RefreshBuffer()
       
  2344             self.RefreshScrollBars()
       
  2345             self.RefreshVisibleElements()
       
  2346             transition.Refresh()
       
  2347         dialog.Destroy()
       
  2348 
       
  2349     def AddNewDivergence(self, bbox):
       
  2350         dialog = SFCDivergenceDialog(self.ParentWindow, self.Controler)
       
  2351         dialog.SetPreviewFont(self.GetFont())
       
  2352         dialog.SetMinSize((bbox.width, bbox.height))
       
  2353         if dialog.ShowModal() == wx.ID_OK:
       
  2354             id = self.GetNewId()
       
  2355             values = dialog.GetValues()
       
  2356             divergence = SFC_Divergence(self, values["type"], values["number"], id)
       
  2357             divergence.SetPosition(bbox.x, bbox.y)
       
  2358             min_width, min_height = divergence.GetMinSize(True)
       
  2359             divergence.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
       
  2360             self.AddBlock(divergence)
       
  2361             self.Controler.AddEditedElementDivergence(self.TagName, id, values["type"])
       
  2362             self.RefreshDivergenceModel(divergence)
       
  2363             self.RefreshBuffer()
       
  2364             self.RefreshScrollBars()
       
  2365             self.RefreshVisibleElements()
       
  2366             divergence.Refresh()
       
  2367         dialog.Destroy()
       
  2368 
       
  2369     def AddNewJump(self, bbox):
       
  2370         choices = []
       
  2371         for block in self.Blocks.itervalues():
       
  2372             if isinstance(block, SFC_Step):
       
  2373                 choices.append(block.GetName())
       
  2374         dialog = wx.SingleChoiceDialog(self.ParentWindow, 
       
  2375               _("Add a new jump"), _("Please choose a target"), 
       
  2376               choices, wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
       
  2377         if dialog.ShowModal() == wx.ID_OK:
       
  2378             id = self.GetNewId()
       
  2379             value = dialog.GetStringSelection()
       
  2380             jump = SFC_Jump(self, value, id)
       
  2381             jump.SetPosition(bbox.x, bbox.y)
       
  2382             min_width, min_height = jump.GetMinSize()
       
  2383             jump.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
       
  2384             self.AddBlock(jump)
       
  2385             self.Controler.AddEditedElementJump(self.TagName, id)
       
  2386             self.RefreshJumpModel(jump)
       
  2387             self.RefreshBuffer()
       
  2388             self.RefreshScrollBars()
       
  2389             self.RefreshVisibleElements()
       
  2390             jump.Refresh()
       
  2391         dialog.Destroy()
       
  2392 
       
  2393     def AddNewActionBlock(self, bbox):
       
  2394         dialog = ActionBlockDialog(self.ParentWindow)
       
  2395         dialog.SetQualifierList(self.Controler.GetQualifierTypes())
       
  2396         dialog.SetActionList(self.Controler.GetEditedElementActions(self.TagName, self.Debug))
       
  2397         dialog.SetVariableList(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
       
  2398         if dialog.ShowModal() == wx.ID_OK:
       
  2399             actions = dialog.GetValues()
       
  2400             id = self.GetNewId()
       
  2401             actionblock = SFC_ActionBlock(self, actions, id)
       
  2402             actionblock.SetPosition(bbox.x, bbox.y)
       
  2403             min_width, min_height = actionblock.GetMinSize()
       
  2404             actionblock.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
       
  2405             self.AddBlock(actionblock)
       
  2406             self.Controler.AddEditedElementActionBlock(self.TagName, id)
       
  2407             self.RefreshActionBlockModel(actionblock)
       
  2408             self.RefreshBuffer()
       
  2409             self.RefreshScrollBars()
       
  2410             self.RefreshVisibleElements()
       
  2411             actionblock.Refresh()
       
  2412         dialog.Destroy()
       
  2413 
       
  2414 #-------------------------------------------------------------------------------
       
  2415 #                          Edit element content functions
       
  2416 #-------------------------------------------------------------------------------
       
  2417 
       
  2418     def EditBlockContent(self, block):
       
  2419         dialog = FBDBlockDialog(self.ParentWindow, self.Controler)
       
  2420         dialog.SetPreviewFont(self.GetFont())
       
  2421         dialog.SetBlockList(self.Controler.GetBlockTypes(self.TagName, self.Debug))
       
  2422         dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
       
  2423         variable_names = self.Controler.GetEditedElementVariables(self.TagName, self.Debug)
       
  2424         if block.GetName() != "":
       
  2425             variable_names.remove(block.GetName())
       
  2426         dialog.SetPouElementNames(variable_names)
       
  2427         dialog.SetMinBlockSize(block.GetSize())
       
  2428         old_values = {"name" : block.GetName(), 
       
  2429                       "type" : block.GetType(), 
       
  2430                       "extension" : block.GetExtension(), 
       
  2431                       "inputs" : block.GetInputTypes(), 
       
  2432                       "executionControl" : block.GetExecutionControl(), 
       
  2433                       "executionOrder" : block.GetExecutionOrder()}
       
  2434         dialog.SetValues(old_values)
       
  2435         if dialog.ShowModal() == wx.ID_OK:
       
  2436             new_values = dialog.GetValues()
       
  2437             rect = block.GetRedrawRect(1, 1)
       
  2438             if "name" in new_values:
       
  2439                 block.SetName(new_values["name"])
       
  2440             else:
       
  2441                 block.SetName("")
       
  2442             block.SetSize(*self.GetScaledSize(new_values["width"], new_values["height"]))
       
  2443             block.SetType(new_values["type"], new_values["extension"], executionControl = new_values["executionControl"])
       
  2444             block.SetExecutionOrder(new_values["executionOrder"])
       
  2445             rect = rect.Union(block.GetRedrawRect())
       
  2446             self.RefreshBlockModel(block)
       
  2447             self.RefreshBuffer()
       
  2448             if old_values["executionOrder"] != new_values["executionOrder"]:
       
  2449                 self.RefreshView(selection=({block.GetId(): True}, {}))
       
  2450             else:
       
  2451                 self.RefreshScrollBars()
       
  2452                 self.RefreshVisibleElements()
       
  2453                 block.Refresh(rect)
       
  2454             self.RefreshVariablePanel()
       
  2455             self.ParentWindow.RefreshPouInstanceVariablesPanel()
       
  2456         dialog.Destroy()
       
  2457 
       
  2458     def EditVariableContent(self, variable):
       
  2459         words = self.TagName.split("::")
       
  2460         if words[0] == "T":
       
  2461             dialog = FBDVariableDialog(self.ParentWindow, self.Controler, words[2])
       
  2462         else:
       
  2463             dialog = FBDVariableDialog(self.ParentWindow, self.Controler)
       
  2464         dialog.SetPreviewFont(self.GetFont())
       
  2465         dialog.SetMinVariableSize(variable.GetSize())
       
  2466         varlist = []
       
  2467         vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
       
  2468         if vars:
       
  2469             for var in vars:
       
  2470                 if var["Edit"]:
       
  2471                     varlist.append((var["Name"], var["Class"], var["Type"]))
       
  2472         returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
       
  2473         if returntype:
       
  2474             varlist.append((self.Controler.GetEditedElementName(self.TagName), "Output", returntype))
       
  2475         dialog.SetVariables(varlist)
       
  2476         old_values = {"name" : variable.GetName(), "type" : variable.GetType(), 
       
  2477             "executionOrder" : variable.GetExecutionOrder()}
       
  2478         dialog.SetValues(old_values)
       
  2479         if dialog.ShowModal() == wx.ID_OK:
       
  2480             new_values = dialog.GetValues()
       
  2481             rect = variable.GetRedrawRect(1, 1)
       
  2482             variable.SetName(new_values["name"])
       
  2483             variable.SetType(new_values["type"], new_values["value_type"])
       
  2484             variable.SetSize(*self.GetScaledSize(new_values["width"], new_values["height"]))
       
  2485             variable.SetExecutionOrder(new_values["executionOrder"])
       
  2486             rect = rect.Union(variable.GetRedrawRect())
       
  2487             if old_values["type"] != new_values["type"]:
       
  2488                 id = variable.GetId()
       
  2489                 self.Controler.RemoveEditedElementInstance(self.TagName, id)
       
  2490                 self.Controler.AddEditedElementVariable(self.TagName, id, new_values["type"])
       
  2491             self.RefreshVariableModel(variable)
       
  2492             self.RefreshBuffer()
       
  2493             if old_values["executionOrder"] != new_values["executionOrder"]:
       
  2494                 self.RefreshView(selection=({variable.GetId(): True}, {}))
       
  2495             else:
       
  2496                 self.RefreshVisibleElements()
       
  2497                 self.RefreshScrollBars()
       
  2498                 variable.Refresh(rect)
       
  2499         dialog.Destroy()
       
  2500 
       
  2501     def EditConnectionContent(self, connection):
       
  2502         dialog = ConnectionDialog(self.ParentWindow, self.Controler, True)
       
  2503         dialog.SetPreviewFont(self.GetFont())
       
  2504         dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
       
  2505         dialog.SetPouElementNames(self.Controler.GetEditedElementVariables(self.TagName, self.Debug))
       
  2506         dialog.SetMinConnectionSize(connection.GetSize())
       
  2507         values = {"name" : connection.GetName(), "type" : connection.GetType()}
       
  2508         dialog.SetValues(values)
       
  2509         result = dialog.ShowModal()
       
  2510         dialog.Destroy()
       
  2511         if result in [wx.ID_OK, wx.ID_YESTOALL]:
       
  2512             old_type = connection.GetType()
       
  2513             old_name = connection.GetName()
       
  2514             values = dialog.GetValues()
       
  2515             rect = connection.GetRedrawRect(1, 1)
       
  2516             connection.SetName(values["name"])
       
  2517             connection.SetType(values["type"])
       
  2518             connection.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2519             rect = rect.Union(connection.GetRedrawRect())
       
  2520             if old_type != values["type"]:
       
  2521                 id = connection.GetId()
       
  2522                 self.Controler.RemoveEditedElementInstance(self.TagName, id)
       
  2523                 self.Controler.AddEditedElementConnection(self.TagName, id, values["type"])
       
  2524             self.RefreshConnectionModel(connection)
       
  2525             if old_name != values["name"] and result == wx.ID_YESTOALL:
       
  2526                 self.Controler.UpdateEditedElementUsedVariable(self.TagName, old_name, values["name"])
       
  2527                 self.RefreshBuffer()
       
  2528                 self.RefreshView(selection=({connection.GetId(): True}, {}))
       
  2529             else:
       
  2530                 self.RefreshBuffer()
       
  2531                 self.RefreshScrollBars()
       
  2532                 self.RefreshVisibleElements()
       
  2533                 connection.Refresh(rect)
       
  2534         
       
  2535     def EditContactContent(self, contact):
       
  2536         dialog = LDElementDialog(self.ParentWindow, self.Controler, "contact")
       
  2537         dialog.SetPreviewFont(self.GetFont())
       
  2538         varlist = []
       
  2539         vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
       
  2540         if vars:
       
  2541             for var in vars:
       
  2542                 if var["Type"] == "BOOL":
       
  2543                     varlist.append(var["Name"])
       
  2544         dialog.SetVariables(varlist)
       
  2545         values = {"name" : contact.GetName(), "type" : contact.GetType()}
       
  2546         dialog.SetValues(values)
       
  2547         dialog.SetElementSize(contact.GetSize())
       
  2548         if dialog.ShowModal() == wx.ID_OK:
       
  2549             values = dialog.GetValues()
       
  2550             rect = contact.GetRedrawRect(1, 1)
       
  2551             contact.SetName(values["name"])
       
  2552             contact.SetType(values["type"])
       
  2553             contact.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2554             rect = rect.Union(contact.GetRedrawRect())
       
  2555             self.RefreshContactModel(contact)
       
  2556             self.RefreshBuffer()
       
  2557             self.RefreshScrollBars()
       
  2558             self.RefreshVisibleElements()
       
  2559             contact.Refresh(rect)
       
  2560         dialog.Destroy()
       
  2561 
       
  2562     def EditCoilContent(self, coil):
       
  2563         dialog = LDElementDialog(self.ParentWindow, self.Controler, "coil")
       
  2564         dialog.SetPreviewFont(self.GetFont())
       
  2565         varlist = []
       
  2566         vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
       
  2567         if vars:
       
  2568             for var in vars:
       
  2569                 if var["Class"] != "Input" and var["Type"] == "BOOL":
       
  2570                     varlist.append(var["Name"])
       
  2571         returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
       
  2572         if returntype == "BOOL":
       
  2573             varlist.append(self.Controler.GetEditedElementName(self.TagName))
       
  2574         dialog.SetVariables(varlist)
       
  2575         values = {"name" : coil.GetName(), "type" : coil.GetType()}
       
  2576         dialog.SetValues(values)
       
  2577         dialog.SetElementSize(coil.GetSize())
       
  2578         if dialog.ShowModal() == wx.ID_OK:
       
  2579             values = dialog.GetValues()
       
  2580             rect = coil.GetRedrawRect(1, 1)
       
  2581             coil.SetName(values["name"])
       
  2582             coil.SetType(values["type"])
       
  2583             coil.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2584             rect = rect.Union(coil.GetRedrawRect())
       
  2585             self.RefreshCoilModel(coil)
       
  2586             self.RefreshBuffer()
       
  2587             self.RefreshScrollBars()
       
  2588             self.RefreshVisibleElements()
       
  2589             coil.Refresh(rect)
       
  2590         dialog.Destroy()
       
  2591 
       
  2592     def EditPowerRailContent(self, powerrail):
       
  2593         connectors = powerrail.GetConnectors()
       
  2594         type = powerrail.GetType()
       
  2595         if type == LEFTRAIL:
       
  2596             pin_number = len(connectors["outputs"])
       
  2597         else:
       
  2598             pin_number = len(connectors["inputs"])
       
  2599         dialog = LDPowerRailDialog(self.ParentWindow, self.Controler, type, pin_number)
       
  2600         dialog.SetPreviewFont(self.GetFont())
       
  2601         dialog.SetMinSize(powerrail.GetSize())
       
  2602         if dialog.ShowModal() == wx.ID_OK:
       
  2603             old_type = powerrail.GetType()
       
  2604             values = dialog.GetValues()
       
  2605             rect = powerrail.GetRedrawRect(1, 1)
       
  2606             powerrail.SetType(values["type"], values["number"])
       
  2607             powerrail.SetSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2608             rect = rect.Union(powerrail.GetRedrawRect())
       
  2609             if old_type != values["type"]:
       
  2610                 id = powerrail.GetId()
       
  2611                 self.Controler.RemoveEditedElementInstance(self.TagName, id)
       
  2612                 self.Controler.AddEditedElementPowerRail(self.TagName, id, values["type"])
       
  2613             self.RefreshPowerRailModel(powerrail)
       
  2614             self.RefreshBuffer()
       
  2615             self.RefreshScrollBars()
       
  2616             self.RefreshVisibleElements()
       
  2617             powerrail.Refresh(rect)
       
  2618         dialog.Destroy()
       
  2619 
       
  2620     def EditStepContent(self, step):
       
  2621         dialog = SFCStepDialog(self.ParentWindow, self.Controler, step.GetInitial())
       
  2622         dialog.SetPreviewFont(self.GetFont())
       
  2623         dialog.SetPouNames(self.Controler.GetProjectPouNames(self.Debug))
       
  2624         dialog.SetVariables(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
       
  2625         dialog.SetStepNames([block.GetName() for block in self.Blocks.itervalues() if isinstance(block, SFC_Step) and block.GetName() != step.GetName()])
       
  2626         dialog.SetMinStepSize(step.GetSize())
       
  2627         values = {"name" : step.GetName()}
       
  2628         connectors = step.GetConnectors()
       
  2629         values["input"] = len(connectors["inputs"]) > 0
       
  2630         values["output"] = len(connectors["outputs"]) > 0
       
  2631         values["action"] = step.GetActionConnector() != None
       
  2632         dialog.SetValues(values)
       
  2633         if dialog.ShowModal() == wx.ID_OK:
       
  2634             values = dialog.GetValues()
       
  2635             rect = step.GetRedrawRect(1, 1)
       
  2636             step.SetName(values["name"])
       
  2637             if values["input"]:
       
  2638                 step.AddInput()
       
  2639             else:
       
  2640                 step.RemoveInput()
       
  2641             if values["output"]:
       
  2642                 step.AddOutput()
       
  2643             else:
       
  2644                 step.RemoveOutput()
       
  2645             if values["action"]:
       
  2646                 step.AddAction()    
       
  2647             else:
       
  2648                 step.RemoveAction()
       
  2649             step.UpdateSize(*self.GetScaledSize(values["width"], values["height"]))
       
  2650             rect = rect.Union(step.GetRedrawRect())
       
  2651             self.RefreshStepModel(step)
       
  2652             self.RefreshBuffer()
       
  2653             self.RefreshScrollBars()
       
  2654             self.RefreshVisibleElements()
       
  2655             step.Refresh(rect)
       
  2656         
       
  2657     def EditTransitionContent(self, transition):
       
  2658         dialog = SFCTransitionDialog(self.ParentWindow, self.Controler, self.GetDrawingMode() == FREEDRAWING_MODE)
       
  2659         dialog.SetPreviewFont(self.GetFont())
       
  2660         dialog.SetTransitions(self.Controler.GetEditedElementTransitions(self.TagName, self.Debug))
       
  2661         dialog.SetValues({"type":transition.GetType(),"value":transition.GetCondition(), "priority":transition.GetPriority()})
       
  2662         dialog.SetElementSize(transition.GetSize())
       
  2663         if dialog.ShowModal() == wx.ID_OK:
       
  2664             values = dialog.GetValues()
       
  2665             rect = transition.GetRedrawRect(1, 1)
       
  2666             transition.SetType(values["type"],values["value"])
       
  2667             transition.SetPriority(values["priority"])
       
  2668             rect = rect.Union(transition.GetRedrawRect())
       
  2669             self.RefreshTransitionModel(transition)
       
  2670             self.RefreshBuffer()
       
  2671             self.RefreshScrollBars()
       
  2672             self.RefreshVisibleElements()
       
  2673             transition.Refresh(rect)
       
  2674         dialog.Destroy()
       
  2675 
       
  2676     def EditJumpContent(self, jump):
       
  2677         choices = []
       
  2678         for block in self.Blocks.itervalues():
       
  2679             if isinstance(block, SFC_Step):
       
  2680                 choices.append(block.GetName())
       
  2681         dialog = wx.SingleChoiceDialog(self.ParentWindow, 
       
  2682               _("Edit jump target"), _("Please choose a target"), 
       
  2683               choices, wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
       
  2684         dialog.SetSelection(choices.index(jump.GetTarget()))
       
  2685         if dialog.ShowModal() == wx.ID_OK:
       
  2686             value = dialog.GetStringSelection()
       
  2687             rect = jump.GetRedrawRect(1, 1)
       
  2688             jump.SetTarget(value)
       
  2689             rect = rect.Union(jump.GetRedrawRect())
       
  2690             self.RefreshJumpModel(jump)
       
  2691             self.RefreshBuffer()
       
  2692             self.RefreshScrollBars()
       
  2693             self.RefreshVisibleElements()
       
  2694             jump.Refresh(rect)
       
  2695         dialog.Destroy()
       
  2696 
       
  2697     def EditActionBlockContent(self, actionblock):
       
  2698         dialog = ActionBlockDialog(self.ParentWindow)
       
  2699         dialog.SetQualifierList(self.Controler.GetQualifierTypes())
       
  2700         dialog.SetActionList(self.Controler.GetEditedElementActions(self.TagName, self.Debug))
       
  2701         dialog.SetVariableList(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
       
  2702         dialog.SetValues(actionblock.GetActions())
       
  2703         if dialog.ShowModal() == wx.ID_OK:
       
  2704             actions = dialog.GetValues()
       
  2705             rect = actionblock.GetRedrawRect(1, 1)
       
  2706             actionblock.SetActions(actions)
       
  2707             actionblock.SetSize(*self.GetScaledSize(*actionblock.GetSize()))
       
  2708             rect = rect.Union(actionblock.GetRedrawRect())
       
  2709             self.RefreshActionBlockModel(actionblock)
       
  2710             self.RefreshBuffer()
       
  2711             self.RefreshScrollBars()
       
  2712             self.RefreshVisibleElements()
       
  2713             actionblock.Refresh(rect)
       
  2714         dialog.Destroy()
       
  2715 
       
  2716     def EditCommentContent(self, comment):
       
  2717         if wx.VERSION >= (2, 5, 0):
       
  2718             dialog = wx.TextEntryDialog(self.ParentWindow, _("Edit comment"), _("Please enter comment text"), comment.GetContent(), wx.OK|wx.CANCEL|wx.TE_MULTILINE)
       
  2719         else:
       
  2720             dialog = wx.TextEntryDialog(self.ParentWindow, _("Edit comment"), _("Please enter comment text"), comment.GetContent(), wx.OK|wx.CANCEL)
       
  2721         dialog.SetClientSize(wx.Size(400, 200))
       
  2722         if dialog.ShowModal() == wx.ID_OK:
       
  2723             value = dialog.GetValue()
       
  2724             rect = comment.GetRedrawRect(1, 1)
       
  2725             comment.SetContent(value)
       
  2726             comment.SetSize(*self.GetScaledSize(*comment.GetSize()))
       
  2727             rect = rect.Union(comment.GetRedrawRect())
       
  2728             self.RefreshCommentModel(comment)
       
  2729             self.RefreshBuffer()
       
  2730             self.RefreshScrollBars()
       
  2731             self.RefreshVisibleElements()
       
  2732             comment.Refresh(rect)
       
  2733         dialog.Destroy()
       
  2734 
       
  2735 #-------------------------------------------------------------------------------
       
  2736 #                          Model update functions
       
  2737 #-------------------------------------------------------------------------------
       
  2738 
       
  2739     def RefreshBlockModel(self, block):
       
  2740         blockid = block.GetId()
       
  2741         infos = {}
       
  2742         infos["type"] = block.GetType()
       
  2743         infos["name"] = block.GetName()
       
  2744         if self.CurrentLanguage == "FBD":
       
  2745             infos["executionOrder"] = block.GetExecutionOrder()
       
  2746         infos["x"], infos["y"] = block.GetPosition()
       
  2747         infos["width"], infos["height"] = block.GetSize()
       
  2748         infos["connectors"] = block.GetConnectors()
       
  2749         self.Controler.SetEditedElementBlockInfos(self.TagName, blockid, infos)
       
  2750     
       
  2751     def ChangeVariableType(self, variable, new_type):
       
  2752         old_type = variable.GetType()
       
  2753         rect = variable.GetRedrawRect(1, 1)
       
  2754         if old_type != new_type:
       
  2755             variable.SetType(new_type, variable.GetValueType())
       
  2756             id = variable.GetId()
       
  2757             self.Controler.RemoveEditedElementInstance(self.TagName, id)
       
  2758             self.Controler.AddEditedElementVariable(self.TagName, id, new_type)
       
  2759             self.RefreshVariableModel(variable)
       
  2760             self.RefreshBuffer()
       
  2761             self.RefreshVisibleElements()
       
  2762             self.RefreshScrollBars()
       
  2763             variable.Refresh(rect.Union(variable.GetRedrawRect()))
       
  2764     
       
  2765     def RefreshVariableModel(self, variable):
       
  2766         variableid = variable.GetId()
       
  2767         infos = {}
       
  2768         infos["name"] = variable.GetName()
       
  2769         if self.CurrentLanguage == "FBD":
       
  2770             infos["executionOrder"] = variable.GetExecutionOrder()
       
  2771         infos["x"], infos["y"] = variable.GetPosition()
       
  2772         infos["width"], infos["height"] = variable.GetSize()
       
  2773         infos["connectors"] = variable.GetConnectors()
       
  2774         self.Controler.SetEditedElementVariableInfos(self.TagName, variableid, infos)
       
  2775 
       
  2776     def ChangeConnectionType(self, connection, new_type):
       
  2777         old_type = connection.GetType()
       
  2778         rect = connection.GetRedrawRect(1, 1)
       
  2779         if old_type != new_type:
       
  2780             connection.SetType(new_type)
       
  2781             id = connection.GetId()
       
  2782             self.Controler.RemoveEditedElementInstance(self.TagName, id)
       
  2783             self.Controler.AddEditedElementConnection(self.TagName, id, new_type)
       
  2784             self.RefreshConnectionModel(connection)
       
  2785             self.RefreshBuffer()
       
  2786             self.RefreshScrollBars()
       
  2787             self.RefreshVisibleElements()
       
  2788             connection.Refresh(rect.Union(connection.GetRedrawRect()))
       
  2789 
       
  2790     def RefreshConnectionModel(self, connection):
       
  2791         connectionid = connection.GetId()
       
  2792         infos = {}
       
  2793         infos["name"] = connection.GetName()
       
  2794         infos["x"], infos["y"] = connection.GetPosition()
       
  2795         infos["width"], infos["height"] = connection.GetSize()
       
  2796         infos["connector"] = connection.GetConnector()
       
  2797         self.Controler.SetEditedElementConnectionInfos(self.TagName, connectionid, infos)
       
  2798 
       
  2799     def RefreshCommentModel(self, comment):
       
  2800         commentid = comment.GetId()
       
  2801         infos = {}
       
  2802         infos["content"] = comment.GetContent()
       
  2803         infos["x"], infos["y"] = comment.GetPosition()
       
  2804         infos["width"], infos["height"] = comment.GetSize()
       
  2805         self.Controler.SetEditedElementCommentInfos(self.TagName, commentid, infos)
       
  2806 
       
  2807     def RefreshPowerRailModel(self, powerrail):
       
  2808         powerrailid = powerrail.GetId()
       
  2809         infos = {}
       
  2810         infos["x"], infos["y"] = powerrail.GetPosition()
       
  2811         infos["width"], infos["height"] = powerrail.GetSize()
       
  2812         infos["connectors"] = powerrail.GetConnectors()
       
  2813         self.Controler.SetEditedElementPowerRailInfos(self.TagName, powerrailid, infos)
       
  2814 
       
  2815     def RefreshContactModel(self, contact):
       
  2816         contactid = contact.GetId()
       
  2817         infos = {}
       
  2818         infos["name"] = contact.GetName()
       
  2819         infos["type"] = contact.GetType()
       
  2820         infos["x"], infos["y"] = contact.GetPosition()
       
  2821         infos["width"], infos["height"] = contact.GetSize()
       
  2822         infos["connectors"] = contact.GetConnectors()
       
  2823         self.Controler.SetEditedElementContactInfos(self.TagName, contactid, infos)
       
  2824 
       
  2825     def RefreshCoilModel(self, coil):
       
  2826         coilid = coil.GetId()
       
  2827         infos = {}
       
  2828         infos["name"] = coil.GetName()
       
  2829         infos["type"] = coil.GetType()
       
  2830         infos["x"], infos["y"] = coil.GetPosition()
       
  2831         infos["width"], infos["height"] = coil.GetSize()
       
  2832         infos["connectors"] = coil.GetConnectors()
       
  2833         self.Controler.SetEditedElementCoilInfos(self.TagName, coilid, infos)
       
  2834 
       
  2835     def RefreshStepModel(self, step):
       
  2836         stepid = step.GetId()
       
  2837         infos = {}
       
  2838         infos["name"] = step.GetName()
       
  2839         infos["initial"] = step.GetInitial()
       
  2840         infos["x"], infos["y"] = step.GetPosition()
       
  2841         infos["width"], infos["height"] = step.GetSize()
       
  2842         infos["connectors"] = step.GetConnectors()
       
  2843         infos["action"] = step.GetActionConnector()
       
  2844         self.Controler.SetEditedElementStepInfos(self.TagName, stepid, infos)
       
  2845 
       
  2846     def RefreshTransitionModel(self, transition):
       
  2847         transitionid = transition.GetId()
       
  2848         infos = {}
       
  2849         infos["type"] = transition.GetType()
       
  2850         infos["priority"] = transition.GetPriority()
       
  2851         infos["condition"] = transition.GetCondition()
       
  2852         infos["x"], infos["y"] = transition.GetPosition()
       
  2853         infos["width"], infos["height"] = transition.GetSize()
       
  2854         infos["connectors"] = transition.GetConnectors()
       
  2855         infos["connection"] = transition.GetConditionConnector()
       
  2856         self.Controler.SetEditedElementTransitionInfos(self.TagName, transitionid, infos)
       
  2857 
       
  2858     def RefreshDivergenceModel(self, divergence):
       
  2859         divergenceid = divergence.GetId()
       
  2860         infos = {}
       
  2861         infos["x"], infos["y"] = divergence.GetPosition()
       
  2862         infos["width"], infos["height"] = divergence.GetSize()
       
  2863         infos["connectors"] = divergence.GetConnectors()
       
  2864         self.Controler.SetEditedElementDivergenceInfos(self.TagName, divergenceid, infos)
       
  2865 
       
  2866     def RefreshJumpModel(self, jump):
       
  2867         jumpid = jump.GetId()
       
  2868         infos = {}
       
  2869         infos["target"] = jump.GetTarget()
       
  2870         infos["x"], infos["y"] = jump.GetPosition()
       
  2871         infos["width"], infos["height"] = jump.GetSize()
       
  2872         infos["connector"] = jump.GetConnector()
       
  2873         self.Controler.SetEditedElementJumpInfos(self.TagName, jumpid, infos)
       
  2874 
       
  2875     def RefreshActionBlockModel(self, actionblock):
       
  2876         actionblockid = actionblock.GetId()
       
  2877         infos = {}
       
  2878         infos["actions"] = actionblock.GetActions()
       
  2879         infos["x"], infos["y"] = actionblock.GetPosition()
       
  2880         infos["width"], infos["height"] = actionblock.GetSize()
       
  2881         infos["connector"] = actionblock.GetConnector()
       
  2882         self.Controler.SetEditedElementActionBlockInfos(self.TagName, actionblockid, infos)
       
  2883 
       
  2884 
       
  2885 #-------------------------------------------------------------------------------
       
  2886 #                          Model delete functions
       
  2887 #-------------------------------------------------------------------------------
       
  2888 
       
  2889 
       
  2890     def DeleteBlock(self, block):
       
  2891         elements = []
       
  2892         for output in block.GetConnectors()["outputs"]:
       
  2893             for element in output.GetConnectedBlocks():
       
  2894                 if element not in elements:
       
  2895                     elements.append(element)
       
  2896         block.Clean()
       
  2897         self.RemoveBlock(block)
       
  2898         self.Controler.RemoveEditedElementInstance(self.TagName, block.GetId())
       
  2899         for element in elements:
       
  2900             element.RefreshModel()
       
  2901         wx.CallAfter(self.RefreshVariablePanel)
       
  2902         wx.CallAfter(self.ParentWindow.RefreshPouInstanceVariablesPanel)
       
  2903         
       
  2904     def DeleteVariable(self, variable):
       
  2905         connectors = variable.GetConnectors()
       
  2906         if len(connectors["outputs"]) > 0:
       
  2907             elements = connectors["outputs"][0].GetConnectedBlocks()
       
  2908         else:
       
  2909             elements = []
       
  2910         variable.Clean()
       
  2911         self.RemoveBlock(variable)
       
  2912         self.Controler.RemoveEditedElementInstance(self.TagName, variable.GetId())
       
  2913         for element in elements:
       
  2914             element.RefreshModel()
       
  2915 
       
  2916     def DeleteConnection(self, connection):
       
  2917         if connection.GetType() == CONTINUATION:
       
  2918             elements = connection.GetConnector().GetConnectedBlocks()
       
  2919         else:
       
  2920             elements = []
       
  2921         connection.Clean()
       
  2922         self.RemoveBlock(connection)
       
  2923         self.Controler.RemoveEditedElementInstance(self.TagName, connection.GetId())
       
  2924         for element in elements:
       
  2925             element.RefreshModel()
       
  2926 
       
  2927     def DeleteComment(self, comment):
       
  2928         self.RemoveComment(comment)
       
  2929         self.Controler.RemoveEditedElementInstance(self.TagName, comment.GetId())
       
  2930 
       
  2931     def DeleteWire(self, wire):
       
  2932         if wire in self.Wires:
       
  2933             connected = wire.GetConnected()
       
  2934             wire.Clean()
       
  2935             self.RemoveWire(wire)
       
  2936             for connector in connected:
       
  2937                 connector.RefreshParentBlock()
       
  2938 
       
  2939     def DeleteContact(self, contact):
       
  2940         connectors = contact.GetConnectors()
       
  2941         elements = connectors["outputs"][0].GetConnectedBlocks()
       
  2942         contact.Clean()
       
  2943         self.RemoveBlock(contact)
       
  2944         self.Controler.RemoveEditedElementInstance(self.TagName, contact.GetId())
       
  2945         for element in elements:
       
  2946             element.RefreshModel()
       
  2947 
       
  2948     def DeleteCoil(self, coil):
       
  2949         connectors = coil.GetConnectors()
       
  2950         elements = connectors["outputs"][0].GetConnectedBlocks()
       
  2951         coil.Clean()
       
  2952         self.RemoveBlock(coil)
       
  2953         self.Controler.RemoveEditedElementInstance(self.TagName, coil.GetId())
       
  2954         for element in elements:
       
  2955             element.RefreshModel()
       
  2956 
       
  2957     def DeletePowerRail(self, powerrail):
       
  2958         elements = []
       
  2959         if powerrail.GetType() == LEFTRAIL:
       
  2960             connectors = powerrail.GetConnectors()
       
  2961             for connector in connectors["outputs"]:
       
  2962                 for element in connector.GetConnectedBlocks():
       
  2963                     if element not in elements:
       
  2964                         elements.append(element)
       
  2965         powerrail.Clean()
       
  2966         self.RemoveBlock(powerrail)
       
  2967         self.Controler.RemoveEditedElementInstance(self.TagName, powerrail.GetId())
       
  2968         for element in elements:
       
  2969             element.RefreshModel()
       
  2970 
       
  2971     def DeleteStep(self, step):
       
  2972         elements = []
       
  2973         connectors = step.GetConnectors()
       
  2974         action_connector = step.GetActionConnector()
       
  2975         if len(connectors["outputs"]) > 0:
       
  2976             for element in connectors["outputs"][0].GetConnectedBlocks():
       
  2977                 if element not in elements:
       
  2978                     elements.append(element)
       
  2979         if action_connector is not None:
       
  2980             for element in action_connector.GetConnectedBlocks():
       
  2981                 if element not in elements:
       
  2982                     elements.append(element)
       
  2983         step.Clean()
       
  2984         self.RemoveBlock(step)
       
  2985         self.Controler.RemoveEditedElementInstance(self.TagName, step.GetId())
       
  2986         for element in elements:
       
  2987             element.RefreshModel()
       
  2988             
       
  2989     def DeleteTransition(self, transition):
       
  2990         elements = []
       
  2991         connectors = transition.GetConnectors()
       
  2992         for element in connectors["outputs"][0].GetConnectedBlocks():
       
  2993             if element not in elements:
       
  2994                 elements.append(element)
       
  2995         transition.Clean()
       
  2996         self.RemoveBlock(transition)
       
  2997         self.Controler.RemoveEditedElementInstance(self.TagName, transition.GetId())
       
  2998         for element in elements:
       
  2999             element.RefreshModel()
       
  3000 
       
  3001     def DeleteDivergence(self, divergence):
       
  3002         elements = []
       
  3003         connectors = divergence.GetConnectors()
       
  3004         for output in connectors["outputs"]:
       
  3005             for element in output.GetConnectedBlocks():
       
  3006                 if element not in elements:
       
  3007                     elements.append(element)
       
  3008         divergence.Clean()
       
  3009         self.RemoveBlock(divergence)
       
  3010         self.Controler.RemoveEditedElementInstance(self.TagName, divergence.GetId())
       
  3011         for element in elements:
       
  3012             element.RefreshModel()
       
  3013     
       
  3014     def DeleteJump(self, jump):
       
  3015         jump.Clean()
       
  3016         self.RemoveBlock(jump)
       
  3017         self.Controler.RemoveEditedElementInstance(self.TagName, jump.GetId())
       
  3018     
       
  3019     def DeleteActionBlock(self, actionblock):
       
  3020         actionblock.Clean()
       
  3021         self.RemoveBlock(actionblock)
       
  3022         self.Controler.RemoveEditedElementInstance(self.TagName, actionblock.GetId())
       
  3023 
       
  3024 
       
  3025 #-------------------------------------------------------------------------------
       
  3026 #                            Editing functions
       
  3027 #-------------------------------------------------------------------------------
       
  3028     
       
  3029     def Cut(self):
       
  3030         if not self.Debug and (self.IsBlock(self.SelectedElement) or self.IsComment(self.SelectedElement) or isinstance(self.SelectedElement, Graphic_Group)):
       
  3031             blocks, wires = self.SelectedElement.GetDefinition()
       
  3032             text = self.Controler.GetEditedElementInstancesCopy(self.TagName, blocks, wires, self.Debug)
       
  3033             self.ParentWindow.SetCopyBuffer(text)
       
  3034             rect = self.SelectedElement.GetRedrawRect(1, 1)
       
  3035             self.SelectedElement.Delete()
       
  3036             self.SelectedElement = None
       
  3037             self.RefreshBuffer()
       
  3038             self.RefreshScrollBars()
       
  3039             self.RefreshVariablePanel()
       
  3040             self.ParentWindow.RefreshPouInstanceVariablesPanel()
       
  3041             self.RefreshRect(self.GetScrolledRect(rect), False)
       
  3042         
       
  3043     def Copy(self):
       
  3044         if not self.Debug and (self.IsBlock(self.SelectedElement) or self.IsComment(self.SelectedElement) or isinstance(self.SelectedElement, Graphic_Group)):
       
  3045             blocks, wires = self.SelectedElement.GetDefinition()
       
  3046             text = self.Controler.GetEditedElementInstancesCopy(self.TagName, blocks, wires, self.Debug)
       
  3047             self.ParentWindow.SetCopyBuffer(text)
       
  3048             
       
  3049     def Paste(self, bbx=None):
       
  3050         if not self.Debug:
       
  3051             element = self.ParentWindow.GetCopyBuffer()
       
  3052             if bbx is None:
       
  3053                 mouse_pos = self.Editor.ScreenToClient(wx.GetMousePosition())
       
  3054                 middle = wx.Rect(0, 0, *self.Editor.GetClientSize()).InsideXY(mouse_pos.x, mouse_pos.y)
       
  3055                 if middle:
       
  3056                     x, y = self.CalcUnscrolledPosition(mouse_pos.x, mouse_pos.y)
       
  3057                 else:
       
  3058                     x, y = self.CalcUnscrolledPosition(0, 0)
       
  3059                 new_pos = [int(x / self.ViewScale[0]), int(y / self.ViewScale[1])]
       
  3060             else:
       
  3061                 middle = True
       
  3062                 new_pos = [bbx.x, bbx.y]
       
  3063             result = self.Controler.PasteEditedElementInstances(self.TagName, element, new_pos, middle, self.Debug)
       
  3064             if not isinstance(result, (StringType, UnicodeType)):
       
  3065                 self.RefreshBuffer()
       
  3066                 self.RefreshView(selection=result)
       
  3067                 self.RefreshVariablePanel()
       
  3068                 self.ParentWindow.RefreshPouInstanceVariablesPanel()
       
  3069             else:
       
  3070                 message = wx.MessageDialog(self.Editor, result, "Error", wx.OK|wx.ICON_ERROR)
       
  3071                 message.ShowModal()
       
  3072                 message.Destroy()
       
  3073 
       
  3074     def CanAddElement(self, block):
       
  3075         if isinstance(block, Graphic_Group):
       
  3076             return block.CanAddBlocks(self)
       
  3077         elif self.CurrentLanguage == "SFC":
       
  3078             return True
       
  3079         elif self.CurrentLanguage == "LD" and not isinstance(block, (SFC_Step, SFC_Transition, SFC_Divergence, SFC_Jump, SFC_ActionBlock)):
       
  3080             return True
       
  3081         elif self.CurrentLanguage == "FBD" and isinstance(block, (FBD_Block, FBD_Variable, FBD_Connector, Comment)):
       
  3082             return True
       
  3083         return False
       
  3084 
       
  3085     def GenerateNewName(self, element=None, blocktype=None, exclude={}):
       
  3086         if element is not None and isinstance(element, SFC_Step):
       
  3087             format = "Step%d"
       
  3088         else:
       
  3089             if element is not None:
       
  3090                 blocktype = element.GetType()
       
  3091             if blocktype is None:
       
  3092                 blocktype = "Block"
       
  3093             format = "%s%%d" % blocktype
       
  3094         return self.Controler.GenerateNewName(self.TagName, None, format, exclude, self.Debug)
       
  3095 
       
  3096     def IsNamedElement(self, element):
       
  3097         return isinstance(element, FBD_Block) and element.GetName() != "" or isinstance(element, SFC_Step)
       
  3098 
       
  3099     def CopyBlock(self, element, pos):
       
  3100         if isinstance(element, Graphic_Group):
       
  3101             block = element.Clone(self, pos=pos)
       
  3102         else:
       
  3103             new_id = self.GetNewId()
       
  3104             if self.IsNamedElement(element):
       
  3105                 name = self.GenerateNewName(element)
       
  3106                 block = element.Clone(self, new_id, name, pos)
       
  3107             else:
       
  3108                 name = None
       
  3109                 block = element.Clone(self, new_id, pos=pos)
       
  3110             self.AddBlockInModel(block)
       
  3111         return block
       
  3112     
       
  3113     def AddBlockInModel(self, block):
       
  3114         if isinstance(block, Comment):
       
  3115             self.AddComment(block)
       
  3116             self.Controler.AddEditedElementComment(self.TagName, block.GetId())
       
  3117             self.RefreshCommentModel(block)
       
  3118         else:
       
  3119             self.AddBlock(block)
       
  3120             if isinstance(block, FBD_Block):
       
  3121                 self.Controler.AddEditedElementBlock(self.TagName, block.GetId(), block.GetType(), block.GetName())
       
  3122                 self.RefreshBlockModel(block)
       
  3123             elif isinstance(block, FBD_Variable):
       
  3124                 self.Controler.AddEditedElementVariable(self.TagName, block.GetId(), block.GetType())
       
  3125                 self.RefreshVariableModel(block)
       
  3126             elif isinstance(block, FBD_Connector):
       
  3127                 self.Controler.AddEditedElementConnection(self.TagName, block.GetId(), block.GetType())
       
  3128                 self.RefreshConnectionModel(block)
       
  3129             elif isinstance(block, LD_Contact):
       
  3130                 self.Controler.AddEditedElementContact(self.TagName, block.GetId())
       
  3131                 self.RefreshContactModel(block)
       
  3132             elif isinstance(block, LD_Coil):
       
  3133                 self.Controler.AddEditedElementCoil(self.TagName, block.GetId())
       
  3134                 self.RefreshCoilModel(block)
       
  3135             elif isinstance(block, LD_PowerRail):
       
  3136                 self.Controler.AddEditedElementPowerRail(self.TagName, block.GetId(), block.GetType())
       
  3137                 self.RefreshPowerRailModel(block)
       
  3138             elif isinstance(block, SFC_Step):
       
  3139                 self.Controler.AddEditedElementStep(self.TagName, block.GetId())
       
  3140                 self.RefreshStepModel(block)    
       
  3141             elif isinstance(block, SFC_Transition):
       
  3142                 self.Controler.AddEditedElementTransition(self.TagName, block.GetId())
       
  3143                 self.RefreshTransitionModel(block)       
       
  3144             elif isinstance(block, SFC_Divergence):
       
  3145                 self.Controler.AddEditedElementDivergence(self.TagName, block.GetId(), block.GetType())
       
  3146                 self.RefreshDivergenceModel(block)
       
  3147             elif isinstance(block, SFC_Jump):
       
  3148                 self.Controler.AddEditedElementJump(self.TagName, block.GetId())
       
  3149                 self.RefreshJumpModel(block)       
       
  3150             elif isinstance(block, SFC_ActionBlock):
       
  3151                 self.Controler.AddEditedElementActionBlock(self.TagName, block.GetId())
       
  3152                 self.RefreshActionBlockModel(block)
       
  3153 
       
  3154 #-------------------------------------------------------------------------------
       
  3155 #                         Find and Replace functions
       
  3156 #-------------------------------------------------------------------------------
       
  3157 
       
  3158     def Find(self, direction, search_params):
       
  3159         if self.SearchParams != search_params:
       
  3160             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
       
  3161             
       
  3162             self.SearchParams = search_params
       
  3163             criteria = {
       
  3164                 "raw_pattern": search_params["find_pattern"], 
       
  3165                 "pattern": re.compile(search_params["find_pattern"]),
       
  3166                 "case_sensitive": search_params["case_sensitive"],
       
  3167                 "regular_expression": search_params["regular_expression"],
       
  3168                 "filter": "all"}
       
  3169             
       
  3170             self.SearchResults = []
       
  3171             blocks = []
       
  3172             for infos, start, end, text in self.Controler.SearchInPou(self.TagName, criteria, self.Debug):
       
  3173                 if infos[1] in ["var_local", "var_input", "var_output", "var_inout"]:
       
  3174                     self.SearchResults.append((infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT))
       
  3175                 else:
       
  3176                     block = self.Blocks.get(infos[2])
       
  3177                     if block is not None:
       
  3178                         blocks.append((block, (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)))
       
  3179             blocks.sort(sort_blocks)
       
  3180             self.SearchResults.extend([infos for block, infos in blocks])
       
  3181         
       
  3182         if len(self.SearchResults) > 0:
       
  3183             if self.CurrentFindHighlight is not None:
       
  3184                 old_idx = self.SearchResults.index(self.CurrentFindHighlight)
       
  3185                 if self.SearchParams["wrap"]:
       
  3186                     idx = (old_idx + direction) % len(self.SearchResults)
       
  3187                 else:
       
  3188                     idx = max(0, min(old_idx + direction, len(self.SearchResults) - 1))
       
  3189                 if idx != old_idx:
       
  3190                     self.RemoveHighlight(*self.CurrentFindHighlight)
       
  3191                     self.CurrentFindHighlight = self.SearchResults[idx]
       
  3192                     self.AddHighlight(*self.CurrentFindHighlight)
       
  3193             else:
       
  3194                 self.CurrentFindHighlight = self.SearchResults[0]
       
  3195                 self.AddHighlight(*self.CurrentFindHighlight)
       
  3196             
       
  3197         else:
       
  3198             if self.CurrentFindHighlight is not None:
       
  3199                 self.RemoveHighlight(*self.CurrentFindHighlight)
       
  3200             self.CurrentFindHighlight = None
       
  3201         
       
  3202 #-------------------------------------------------------------------------------
       
  3203 #                        Highlights showing functions
       
  3204 #-------------------------------------------------------------------------------
       
  3205 
       
  3206     def OnRefreshHighlightsTimer(self, event):
       
  3207         self.RefreshView()
       
  3208         event.Skip()
       
  3209 
       
  3210     def ClearHighlights(self, highlight_type=None):
       
  3211         EditorPanel.ClearHighlights(self, highlight_type)
       
  3212         
       
  3213         if highlight_type is None:
       
  3214             self.Highlights = []
       
  3215         else:
       
  3216             self.Highlights = [(infos, start, end, highlight) for (infos, start, end, highlight) in self.Highlights if highlight != highlight_type]
       
  3217         self.RefreshView()
       
  3218 
       
  3219     def AddHighlight(self, infos, start, end, highlight_type):
       
  3220         EditorPanel.AddHighlight(self, infos, start, end, highlight_type)
       
  3221         
       
  3222         self.Highlights.append((infos, start, end, highlight_type))
       
  3223         if infos[0] not in ["var_local", "var_input", "var_output", "var_inout"]:
       
  3224             block = self.Blocks.get(infos[1])
       
  3225             if block is not None:
       
  3226                 self.EnsureVisible(block)
       
  3227             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
       
  3228     
       
  3229     def RemoveHighlight(self, infos, start, end, highlight_type):
       
  3230         EditorPanel.RemoveHighlight(self, infos, start, end, highlight_type)
       
  3231         
       
  3232         if (infos, start, end, highlight_type) in self.Highlights:
       
  3233             self.Highlights.remove((infos, start, end, highlight_type))
       
  3234             self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
       
  3235     
       
  3236     def ShowHighlights(self):
       
  3237         for infos, start, end, highlight_type in self.Highlights:
       
  3238             if infos[0] in ["comment", "io_variable", "block", "connector", "coil", "contact", "step", "transition", "jump", "action_block"]:
       
  3239                 block = self.FindElementById(infos[1])
       
  3240                 if block is not None:
       
  3241                     block.AddHighlight(infos[2:], start, end, highlight_type)
       
  3242         
       
  3243 #-------------------------------------------------------------------------------
       
  3244 #                            Drawing functions
       
  3245 #-------------------------------------------------------------------------------
       
  3246 
       
  3247     def OnScrollWindow(self, event):
       
  3248         if self.Editor.HasCapture() and self.StartMousePos:
       
  3249             return
       
  3250         if wx.Platform == '__WXMSW__':
       
  3251             wx.CallAfter(self.RefreshVisibleElements)
       
  3252         elif event.GetOrientation() == wx.HORIZONTAL:
       
  3253             self.RefreshVisibleElements(xp = event.GetPosition())
       
  3254         else:
       
  3255             self.RefreshVisibleElements(yp = event.GetPosition())
       
  3256         event.Skip()
       
  3257 
       
  3258     def OnScrollStop(self, event):
       
  3259         self.RefreshScrollBars()
       
  3260         event.Skip()
       
  3261 
       
  3262     def OnMouseWheelWindow(self, event):
       
  3263         if self.StartMousePos is None or self.StartScreenPos is None:
       
  3264             rotation = event.GetWheelRotation() / event.GetWheelDelta()
       
  3265             if event.ShiftDown():
       
  3266                 x, y = self.GetViewStart()
       
  3267                 xp = max(0, min(x - rotation * 3, self.Editor.GetVirtualSize()[0] / self.Editor.GetScrollPixelsPerUnit()[0]))
       
  3268                 self.RefreshVisibleElements(xp = xp)
       
  3269                 self.Scroll(xp, y)
       
  3270             elif event.ControlDown():
       
  3271                 dc = self.GetLogicalDC()
       
  3272                 self.SetScale(self.CurrentScale + rotation, mouse_event = event)
       
  3273                 self.ParentWindow.RefreshDisplayMenu()
       
  3274             else:
       
  3275                 x, y = self.GetViewStart()
       
  3276                 yp = max(0, min(y - rotation * 3, self.Editor.GetVirtualSize()[1] / self.Editor.GetScrollPixelsPerUnit()[1]))
       
  3277                 self.RefreshVisibleElements(yp = yp)
       
  3278                 self.Scroll(x, yp)
       
  3279         
       
  3280     def OnMoveWindow(self, event):
       
  3281         self.RefreshScrollBars()
       
  3282         self.RefreshVisibleElements()
       
  3283         event.Skip()
       
  3284 
       
  3285     def DoDrawing(self, dc, printing = False):
       
  3286         if printing:
       
  3287             if getattr(dc, "printing", False):
       
  3288                 font = wx.Font(self.GetFont().GetPointSize(), wx.MODERN, wx.NORMAL, wx.NORMAL)
       
  3289                 dc.SetFont(font)
       
  3290             else:
       
  3291                 dc.SetFont(self.GetFont())
       
  3292         else:
       
  3293             dc.SetBackground(wx.Brush(self.Editor.GetBackgroundColour()))
       
  3294             dc.Clear()
       
  3295             dc.BeginDrawing()
       
  3296         if self.Scaling is not None and self.DrawGrid and not printing:
       
  3297             dc.SetPen(wx.TRANSPARENT_PEN)
       
  3298             dc.SetBrush(self.GridBrush)
       
  3299             xstart, ystart = self.GetViewStart()
       
  3300             window_size = self.Editor.GetClientSize()
       
  3301             width, height = self.Editor.GetVirtualSize()
       
  3302             width = int(max(width, xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[0])
       
  3303             height = int(max(height, ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[1])
       
  3304             dc.DrawRectangle(1, 1, width, height)
       
  3305         if self.PageSize is not None and not printing:
       
  3306             dc.SetPen(self.PagePen)
       
  3307             xstart, ystart = self.GetViewStart()
       
  3308             window_size = self.Editor.GetClientSize()
       
  3309             for x in xrange(self.PageSize[0] - (xstart * SCROLLBAR_UNIT) % self.PageSize[0], int(window_size[0] / self.ViewScale[0]), self.PageSize[0]):
       
  3310                 dc.DrawLine(xstart * SCROLLBAR_UNIT + x + 1, int(ystart * SCROLLBAR_UNIT / self.ViewScale[0]), 
       
  3311                             xstart * SCROLLBAR_UNIT + x + 1, int((ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[0]))
       
  3312             for y in xrange(self.PageSize[1] - (ystart * SCROLLBAR_UNIT) % self.PageSize[1], int(window_size[1] / self.ViewScale[1]), self.PageSize[1]):
       
  3313                 dc.DrawLine(int(xstart * SCROLLBAR_UNIT / self.ViewScale[0]), ystart * SCROLLBAR_UNIT + y + 1, 
       
  3314                             int((xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[1]), ystart * SCROLLBAR_UNIT + y + 1)
       
  3315         
       
  3316         # Draw all elements
       
  3317         for comment in self.Comments.itervalues():
       
  3318             if comment != self.SelectedElement and (comment.IsVisible() or printing):
       
  3319                 comment.Draw(dc)
       
  3320         for wire in self.Wires.iterkeys():
       
  3321             if wire != self.SelectedElement and (wire.IsVisible() or printing):
       
  3322                  if not self.Debug or wire.GetValue() != True:
       
  3323                     wire.Draw(dc)
       
  3324         if self.Debug:
       
  3325             for wire in self.Wires.iterkeys():
       
  3326                 if wire != self.SelectedElement and (wire.IsVisible() or printing) and wire.GetValue() == True:
       
  3327                     wire.Draw(dc)
       
  3328         for block in self.Blocks.itervalues():
       
  3329             if block != self.SelectedElement and (block.IsVisible() or printing):
       
  3330                 block.Draw(dc)
       
  3331         
       
  3332         if self.SelectedElement is not None and (self.SelectedElement.IsVisible() or printing):
       
  3333             self.SelectedElement.Draw(dc)
       
  3334         
       
  3335         if not printing:
       
  3336             if self.Debug:
       
  3337                 is_action = self.TagName.split("::")[0] == "A"
       
  3338                 text = _("Debug: %s") % self.InstancePath
       
  3339                 if is_action and self.Value is not None:
       
  3340                     text += " ("
       
  3341                 dc.DrawText(text, 2, 2)
       
  3342                 if is_action and self.Value is not None:
       
  3343                     value_text = self.VALUE_TRANSLATION[self.Value]
       
  3344                     tw, th = dc.GetTextExtent(text)
       
  3345                     if self.Value:
       
  3346                         dc.SetTextForeground(wx.GREEN)
       
  3347                     dc.DrawText(value_text, tw + 2, 2)
       
  3348                     if self.Value:
       
  3349                         dc.SetTextForeground(wx.BLACK)
       
  3350                     vw, vh = dc.GetTextExtent(value_text)
       
  3351                     dc.DrawText(")", tw + vw + 4, 2)
       
  3352             if self.rubberBand.IsShown():
       
  3353                 self.rubberBand.Draw(dc)
       
  3354             dc.EndDrawing()
       
  3355 
       
  3356     def OnPaint(self, event):
       
  3357         dc = self.GetLogicalDC(True)
       
  3358         self.DoDrawing(dc)
       
  3359         wx.BufferedPaintDC(self.Editor, dc.GetAsBitmap())
       
  3360         if self.Debug:
       
  3361             DebugViewer.RefreshNewData(self)
       
  3362         event.Skip()
       
  3363 
       
  3364