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