editors/LDViewer.py
changeset 814 5743cbdff669
child 890 b3cafb73c5e9
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 wx
       
    26 import time
       
    27 from types import *
       
    28 
       
    29 from Viewer import *
       
    30 
       
    31 def ExtractNextBlocks(block, block_list):
       
    32     current_list = [block]
       
    33     while len(current_list) > 0:
       
    34         next_list = []
       
    35         for current in current_list:
       
    36             connectors = current.GetConnectors()
       
    37             input_connectors = []
       
    38             if isinstance(current, LD_PowerRail) and current.GetType() == RIGHTRAIL:
       
    39                 input_connectors = connectors
       
    40             else:
       
    41                 if "inputs" in connectors:
       
    42                     input_connectors = connectors["inputs"]
       
    43                 if "input" in connectors:
       
    44                     input_connectors = [connectors["input"]]
       
    45             for connector in input_connectors:
       
    46                 for wire, handle in connector.GetWires():
       
    47                     next = wire.EndConnected.GetParentBlock()
       
    48                     if not isinstance(next, LD_PowerRail) and next not in block_list:
       
    49                         block_list.append(next)
       
    50                         next_list.append(next)
       
    51         current_list = next_list
       
    52     
       
    53 def CalcBranchSize(elements, stops):
       
    54     branch_size = 0
       
    55     stop_list = stops
       
    56     for stop in stops:
       
    57         ExtractNextBlocks(stop, stop_list)
       
    58     element_tree = {}
       
    59     for element in elements:
       
    60         if element not in element_tree:
       
    61             element_tree[element] = {"parents":["start"], "children":[], "weight":None}
       
    62             GenerateTree(element, element_tree, stop_list)
       
    63         elif element_tree[element]:
       
    64             element_tree[element]["parents"].append("start")
       
    65     remove_stops = {"start":[], "stop":[]}
       
    66     for element, values in element_tree.items():
       
    67         if "stop" in values["children"]:
       
    68             removed = []
       
    69             for child in values["children"]:
       
    70                 if child != "stop":
       
    71 ##                    if child in elements:
       
    72 ##                        RemoveElement(child, element_tree)
       
    73 ##                        removed.append(child)
       
    74                     if "start" in element_tree[child]["parents"]:
       
    75                         if element not in remove_stops["stop"]:
       
    76                             remove_stops["stop"].append(element)
       
    77                         if child not in remove_stops["start"]:
       
    78                             remove_stops["start"].append(child)
       
    79             for child in removed:
       
    80                 values["children"].remove(child)
       
    81     for element in remove_stops["start"]:
       
    82         element_tree[element]["parents"].remove("start")
       
    83     for element in remove_stops["stop"]:
       
    84         element_tree[element]["children"].remove("stop")
       
    85     for element, values in element_tree.items():
       
    86         if values and "stop" in values["children"]:
       
    87             CalcWeight(element, element_tree)
       
    88             if values["weight"]:
       
    89                 branch_size += values["weight"]
       
    90             else:
       
    91                 return 1
       
    92     #print branch_size
       
    93     return branch_size
       
    94 
       
    95 def RemoveElement(remove, element_tree):
       
    96     if remove in element_tree and element_tree[remove]:
       
    97         for child in element_tree[remove]["children"]:
       
    98             if child != "stop":
       
    99                 RemoveElement(child, element_tree)
       
   100         element_tree.pop(remove)
       
   101 ##        element_tree[remove] = None
       
   102 
       
   103 def GenerateTree(element, element_tree, stop_list):
       
   104     if element in element_tree:
       
   105         connectors = element.GetConnectors()
       
   106         input_connectors = []
       
   107         if isinstance(element, LD_PowerRail) and element.GetType() == RIGHTRAIL:
       
   108             input_connectors = connectors
       
   109         else:
       
   110             if "inputs" in connectors:
       
   111                 input_connectors = connectors["inputs"]
       
   112             if "input" in connectors:
       
   113                 input_connectors = [connectors["input"]]
       
   114         for connector in input_connectors:
       
   115             for wire, handle in connector.GetWires():
       
   116                 next = wire.EndConnected.GetParentBlock()
       
   117                 if isinstance(next, LD_PowerRail) and next.GetType() == LEFTRAIL or next in stop_list:
       
   118 ##                    for remove in element_tree[element]["children"]:
       
   119 ##                        RemoveElement(remove, element_tree)
       
   120 ##                    element_tree[element]["children"] = ["stop"]
       
   121                     element_tree[element]["children"].append("stop")
       
   122 ##                elif element_tree[element]["children"] == ["stop"]:
       
   123 ##                    element_tree[next] = None
       
   124                 elif next not in element_tree or element_tree[next]:
       
   125                     element_tree[element]["children"].append(next)
       
   126                     if next in element_tree:
       
   127                         element_tree[next]["parents"].append(element)
       
   128                     else:
       
   129                         element_tree[next] = {"parents":[element], "children":[], "weight":None}
       
   130                         GenerateTree(next, element_tree, stop_list)
       
   131 
       
   132 def CalcWeight(element, element_tree):
       
   133     weight = 0
       
   134     parts = None
       
   135     if element in element_tree:
       
   136         for parent in element_tree[element]["parents"]:
       
   137             if parent == "start":
       
   138                 weight += 1
       
   139             elif parent in element_tree:
       
   140                 if not parts:
       
   141                     parts = len(element_tree[parent]["children"])
       
   142                 else:
       
   143                     parts = min(parts, len(element_tree[parent]["children"]))
       
   144                 if not element_tree[parent]["weight"]:
       
   145                     CalcWeight(parent, element_tree)
       
   146                 if element_tree[parent]["weight"]:
       
   147                     weight += element_tree[parent]["weight"]
       
   148                 else:
       
   149                     element_tree[element]["weight"] = None
       
   150                     return
       
   151             else:
       
   152                 element_tree[element]["weight"] = None
       
   153                 return
       
   154         if not parts:
       
   155             parts = 1
       
   156         element_tree[element]["weight"] = max(1, weight / parts)
       
   157 
       
   158 
       
   159 #-------------------------------------------------------------------------------
       
   160 #                     Ladder Diagram Graphic elements Viewer class
       
   161 #-------------------------------------------------------------------------------
       
   162 
       
   163 
       
   164 """
       
   165 Class derived from Viewer class that implements a Viewer of Ladder Diagram
       
   166 """
       
   167 
       
   168 class LD_Viewer(Viewer):
       
   169 
       
   170     def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""):
       
   171         Viewer.__init__(self, parent, tagname, window, controler, debug, instancepath)
       
   172         self.Rungs = []
       
   173         self.RungComments = []
       
   174         self.CurrentLanguage = "LD"
       
   175 
       
   176 #-------------------------------------------------------------------------------
       
   177 #                          Refresh functions
       
   178 #-------------------------------------------------------------------------------
       
   179 
       
   180     def ResetView(self):
       
   181         self.Rungs = []
       
   182         self.RungComments = []
       
   183         Viewer.ResetView(self)
       
   184 
       
   185     def RefreshView(self, variablepanel=True, selection=None):
       
   186         Viewer.RefreshView(self, variablepanel, selection)
       
   187         wx.CallAfter(self.Refresh)
       
   188         for i, rung in enumerate(self.Rungs):
       
   189             bbox = rung.GetBoundingBox()
       
   190             if i < len(self.RungComments):
       
   191                 if self.RungComments[i]:
       
   192                     pos = self.RungComments[i].GetPosition()
       
   193                     if pos[1] > bbox.y:
       
   194                         self.RungComments.insert(i, None)
       
   195             else:
       
   196                 self.RungComments.insert(i, None)
       
   197     
       
   198     def loadInstance(self, instance, ids, selection):
       
   199         Viewer.loadInstance(self, instance, ids, selection)
       
   200         if self.GetDrawingMode() != FREEDRAWING_MODE:
       
   201             if instance["type"] == "leftPowerRail":
       
   202                 element = self.FindElementById(instance["id"])
       
   203                 rung = Graphic_Group(self)
       
   204                 rung.SelectElement(element)
       
   205                 self.Rungs.append(rung)
       
   206             elif instance["type"] == "rightPowerRail":
       
   207                 rungs = []
       
   208                 for connector in instance["inputs"]:
       
   209                     for link in connector["links"]:
       
   210                         connected = self.FindElementById(link["refLocalId"])
       
   211                         rung = self.FindRung(connected)
       
   212                         if rung not in rungs:
       
   213                             rungs.append(rung)
       
   214                 if len(rungs) > 1:
       
   215                     raise ValueError, _("Ladder element with id %d is on more than one rung.")%instance["id"]
       
   216                 element = self.FindElementById(instance["id"])
       
   217                 element_connectors = element.GetConnectors()
       
   218                 self.Rungs[rungs[0]].SelectElement(element)
       
   219                 for connector in element_connectors["inputs"]:
       
   220                     for wire, num in connector.GetWires():
       
   221                         self.Rungs[rungs[0]].SelectElement(wire)
       
   222                 wx.CallAfter(self.RefreshPosition, element)
       
   223             elif instance["type"] in ["contact", "coil"]:
       
   224                 rungs = []
       
   225                 for link in instance["inputs"][0]["links"]:
       
   226                     connected = self.FindElementById(link["refLocalId"])
       
   227                     rung = self.FindRung(connected)
       
   228                     if rung not in rungs:
       
   229                         rungs.append(rung)
       
   230                 if len(rungs) > 1:
       
   231                     raise ValueError, _("Ladder element with id %d is on more than one rung.")%instance["id"]
       
   232                 element = self.FindElementById(instance["id"])
       
   233                 element_connectors = element.GetConnectors() 
       
   234                 self.Rungs[rungs[0]].SelectElement(element)
       
   235                 for wire, num in element_connectors["inputs"][0].GetWires():
       
   236                     self.Rungs[rungs[0]].SelectElement(wire)
       
   237                 wx.CallAfter(self.RefreshPosition, element)
       
   238             elif instance["type"] == "comment":
       
   239                 element = self.FindElementById(instance["id"])
       
   240                 pos = element.GetPosition()
       
   241                 i = 0
       
   242                 inserted = False
       
   243                 while i < len(self.RungComments) and not inserted: 
       
   244                     ipos = self.RungComments[i].GetPosition()
       
   245                     if pos[1] < ipos[1]:
       
   246                         self.RungComments.insert(i, element)
       
   247                         inserted = True
       
   248                     i += 1
       
   249                 if not inserted:
       
   250                     self.RungComments.append(element)
       
   251             
       
   252 #-------------------------------------------------------------------------------
       
   253 #                          Search Element functions
       
   254 #-------------------------------------------------------------------------------
       
   255 
       
   256     def FindRung(self, element):
       
   257         for i, rung in enumerate(self.Rungs):
       
   258             if rung.IsElementIn(element):
       
   259                 return i
       
   260         return None
       
   261 
       
   262     def FindElement(self, event, exclude_group = False, connectors = True):
       
   263         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
   264             return Viewer.FindElement(self, event, exclude_group, connectors)
       
   265         
       
   266         dc = self.GetLogicalDC()
       
   267         pos = event.GetLogicalPosition(dc)
       
   268         if self.SelectedElement and not isinstance(self.SelectedElement, (Graphic_Group, Wire)):
       
   269             if self.SelectedElement.HitTest(pos, connectors) or self.SelectedElement.TestHandle(pos) != (0, 0):
       
   270                 return self.SelectedElement
       
   271         elements = []
       
   272         for element in self.GetElements(sort_wires=True):
       
   273             if element.HitTest(pos, connectors) or element.TestHandle(event) != (0, 0):
       
   274                 elements.append(element)
       
   275         if len(elements) == 1:
       
   276             return elements[0]
       
   277         elif len(elements) > 1:
       
   278             group = Graphic_Group(self)
       
   279             for element in elements:
       
   280                 if self.IsBlock(element):
       
   281                     return element
       
   282                 group.SelectElement(element)
       
   283             return group
       
   284         return None
       
   285 
       
   286     def SearchElements(self, bbox):
       
   287         elements = []
       
   288         for element in self.Blocks.values() + self.Comments.values():
       
   289             if element.IsInSelection(bbox):
       
   290                 elements.append(element)
       
   291         return elements
       
   292 
       
   293 #-------------------------------------------------------------------------------
       
   294 #                          Mouse event functions
       
   295 #-------------------------------------------------------------------------------
       
   296 
       
   297     def OnViewerLeftDown(self, event):
       
   298         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
   299             Viewer.OnViewerLeftDown(self, event)
       
   300         elif self.Mode == MODE_SELECTION:
       
   301             element = self.FindElement(event)
       
   302             if self.SelectedElement:
       
   303                 if not isinstance(self.SelectedElement, Graphic_Group):
       
   304                     if self.SelectedElement != element:
       
   305                         if self.IsWire(self.SelectedElement):
       
   306                             self.SelectedElement.SetSelectedSegment(None)
       
   307                         else:
       
   308                             self.SelectedElement.SetSelected(False)
       
   309                     else:
       
   310                         self.SelectedElement = None
       
   311                 elif element and isinstance(element, Graphic_Group):
       
   312                     if self.SelectedElement.GetElements() != element.GetElements():
       
   313                         for elt in self.SelectedElement.GetElements():
       
   314                             if self.IsWire(elt):
       
   315                                 elt.SetSelectedSegment(None)
       
   316                         self.SelectedElement.SetSelected(False)
       
   317                         self.SelectedElement = None
       
   318                 else:
       
   319                     for elt in self.SelectedElement.GetElements():
       
   320                         if self.IsWire(elt):
       
   321                             elt.SetSelectedSegment(None)
       
   322                     self.SelectedElement.SetSelected(False)
       
   323                     self.SelectedElement = None
       
   324             if element:
       
   325                 self.SelectedElement = element
       
   326                 self.SelectedElement.OnLeftDown(event, self.GetLogicalDC(), self.Scaling)
       
   327                 self.SelectedElement.Refresh()
       
   328             else:
       
   329                 self.rubberBand.Reset()
       
   330                 self.rubberBand.OnLeftDown(event, self.GetLogicalDC(), self.Scaling)
       
   331         event.Skip()
       
   332 
       
   333     def OnViewerLeftUp(self, event):
       
   334         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
   335             Viewer.OnViewerLeftUp(self, event)
       
   336         elif self.rubberBand.IsShown():
       
   337             if self.Mode == MODE_SELECTION:
       
   338                 elements = self.SearchElements(self.rubberBand.GetCurrentExtent())
       
   339                 self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling)
       
   340                 if len(elements) > 0:
       
   341                     self.SelectedElement = Graphic_Group(self)
       
   342                     self.SelectedElement.SetElements(elements)
       
   343                     self.SelectedElement.SetSelected(True)
       
   344         elif self.Mode == MODE_SELECTION and self.SelectedElement:
       
   345             dc = self.GetLogicalDC() 
       
   346             if not isinstance(self.SelectedElement, Graphic_Group):
       
   347                 if self.IsWire(self.SelectedElement):
       
   348                     result = self.SelectedElement.TestSegment(event.GetLogicalPosition(dc), True)
       
   349                     if result and result[1] in [EAST, WEST]:
       
   350                         self.SelectedElement.SetSelectedSegment(result[0])
       
   351                 else:
       
   352                     self.SelectedElement.OnLeftUp(event, dc, self.Scaling)
       
   353             else:
       
   354                 for element in self.SelectedElement.GetElements():
       
   355                     if self.IsWire(element):
       
   356                         result = element.TestSegment(event.GetLogicalPosition(dc), True)
       
   357                         if result and result[1] in [EAST, WEST]:
       
   358                             element.SetSelectedSegment(result[0])
       
   359                     else:
       
   360                         element.OnLeftUp(event, dc, self.Scaling)
       
   361             self.SelectedElement.Refresh()
       
   362             wx.CallAfter(self.SetCurrentCursor, 0)
       
   363         event.Skip()
       
   364 
       
   365     def OnViewerRightUp(self, event):
       
   366         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
   367             Viewer.OnViewerRightUp(self, event)
       
   368         else:
       
   369             element = self.FindElement(event)
       
   370             if element:
       
   371                 if self.SelectedElement and self.SelectedElement != element:
       
   372                     self.SelectedElement.SetSelected(False)
       
   373                 self.SelectedElement = element
       
   374                 if self.IsWire(self.SelectedElement):
       
   375                     self.SelectedElement.SetSelectedSegment(0)
       
   376                 else:
       
   377                     self.SelectedElement.SetSelected(True)
       
   378                     self.SelectedElement.OnRightUp(event, self.GetLogicalDC(), self.Scaling)
       
   379                     self.SelectedElement.Refresh()
       
   380                 wx.CallAfter(self.SetCurrentCursor, 0)
       
   381         event.Skip()
       
   382 
       
   383 #-------------------------------------------------------------------------------
       
   384 #                          Keyboard event functions
       
   385 #-------------------------------------------------------------------------------
       
   386 
       
   387     def OnChar(self, event):
       
   388         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
   389             Viewer.OnChar(self, event)
       
   390         else:
       
   391             xpos, ypos = self.GetScrollPos(wx.HORIZONTAL), self.GetScrollPos(wx.VERTICAL)
       
   392             xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
       
   393             ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
       
   394             keycode = event.GetKeyCode()
       
   395             if keycode == wx.WXK_DELETE and self.SelectedElement:
       
   396                 if self.IsBlock(self.SelectedElement):
       
   397                     self.SelectedElement.Delete()
       
   398                 elif self.IsWire(self.SelectedElement):
       
   399                     self.DeleteWire(self.SelectedElement)
       
   400                 elif isinstance(self.SelectedElement, Graphic_Group):
       
   401                     all_wires = True
       
   402                     for element in self.SelectedElement.GetElements():
       
   403                         all_wires &= self.IsWire(element)
       
   404                     if all_wires:
       
   405                         self.DeleteWire(self.SelectedElement)
       
   406                     else:
       
   407                         self.SelectedElement.Delete()
       
   408                 self.RefreshBuffer()
       
   409                 self.RefreshScrollBars()
       
   410                 self.Refresh(False)
       
   411             elif keycode == wx.WXK_LEFT:
       
   412                 if event.ControlDown() and event.ShiftDown():
       
   413                     self.Scroll(0, ypos)
       
   414                 elif event.ControlDown():
       
   415                     self.Scroll(max(0, xpos - 1), ypos)
       
   416             elif keycode == wx.WXK_RIGHT:
       
   417                 if event.ControlDown() and event.ShiftDown():
       
   418                     self.Scroll(xmax, ypos)
       
   419                 elif event.ControlDown():
       
   420                     self.Scroll(min(xpos + 1, xmax), ypos)
       
   421             elif keycode == wx.WXK_UP:
       
   422                 if event.ControlDown() and event.ShiftDown():
       
   423                     self.Scroll(xpos, 0)
       
   424                 elif event.ControlDown():
       
   425                     self.Scroll(xpos, max(0, ypos - 1))
       
   426             elif keycode == wx.WXK_DOWN:
       
   427                 if event.ControlDown() and event.ShiftDown():
       
   428                     self.Scroll(xpos, ymax)
       
   429                 elif event.ControlDown():
       
   430                     self.Scroll(xpos, min(ypos + 1, ymax))
       
   431             else:
       
   432                 event.Skip()
       
   433 
       
   434 #-------------------------------------------------------------------------------
       
   435 #                  Model adding functions from Drop Target
       
   436 #-------------------------------------------------------------------------------
       
   437 
       
   438     def AddVariableBlock(self, x, y, scaling, var_class, var_name, var_type):
       
   439         if var_type == "BOOL":
       
   440             id = self.GetNewId()
       
   441             if var_class == INPUT:
       
   442                 contact = LD_Contact(self, CONTACT_NORMAL, var_name, id)
       
   443                 width, height = contact.GetMinSize()
       
   444                 if scaling is not None:
       
   445                     x = round(float(x) / float(scaling[0])) * scaling[0]
       
   446                     y = round(float(y) / float(scaling[1])) * scaling[1]
       
   447                     width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
       
   448                     height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
       
   449                 contact.SetPosition(x, y)
       
   450                 contact.SetSize(width, height)
       
   451                 self.AddBlock(contact)
       
   452                 self.Controler.AddEditedElementContact(self.GetTagName(), id)
       
   453                 self.RefreshContactModel(contact)
       
   454             else:
       
   455                 coil = LD_Coil(self, COIL_NORMAL, var_name, id)
       
   456                 width, height = coil.GetMinSize()
       
   457                 if scaling is not None:
       
   458                     x = round(float(x) / float(scaling[0])) * scaling[0]
       
   459                     y = round(float(y) / float(scaling[1])) * scaling[1]
       
   460                     width = round(float(width) / float(scaling[0]) + 0.5) * scaling[0]
       
   461                     height = round(float(height) / float(scaling[1]) + 0.5) * scaling[1]
       
   462                 coil.SetPosition(x, y)
       
   463                 coil.SetSize(width, height)
       
   464                 self.AddBlock(coil)
       
   465                 self.Controler.AddEditedElementCoil(self.GetTagName(), id)
       
   466                 self.RefreshCoilModel(coil)
       
   467             self.RefreshBuffer()
       
   468             self.RefreshScrollBars()
       
   469             self.RefreshVisibleElements()
       
   470             self.Refresh(False)
       
   471         else:
       
   472             Viewer.AddVariableBlock(self, x, y, scaling, var_class, var_name, var_type)
       
   473 
       
   474 #-------------------------------------------------------------------------------
       
   475 #                          Adding element functions
       
   476 #-------------------------------------------------------------------------------
       
   477 
       
   478     def AddLadderRung(self):
       
   479         dialog = LDElementDialog(self.ParentWindow, self.Controler, "coil")
       
   480         dialog.SetPreviewFont(self.GetFont())
       
   481         varlist = []
       
   482         vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
       
   483         if vars:
       
   484             for var in vars:
       
   485                 if var["Class"] != "Input" and var["Type"] == "BOOL":
       
   486                     varlist.append(var["Name"])
       
   487         returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
       
   488         if returntype == "BOOL":
       
   489             varlist.append(self.Controler.GetEditedElementName(self.TagName))
       
   490         dialog.SetVariables(varlist)
       
   491         dialog.SetValues({"name":"","type":COIL_NORMAL})
       
   492         if dialog.ShowModal() == wx.ID_OK:
       
   493             values = dialog.GetValues()
       
   494             startx, starty = LD_OFFSET[0], 0
       
   495             if len(self.Rungs) > 0:
       
   496                 bbox = self.Rungs[-1].GetBoundingBox()
       
   497                 starty = bbox.y + bbox.height
       
   498             starty += LD_OFFSET[1]
       
   499             rung = Graphic_Group(self)
       
   500             
       
   501             # Create comment
       
   502             id = self.GetNewId()
       
   503             comment = Comment(self, _("Comment"), id)
       
   504             comment.SetPosition(startx, starty)
       
   505             comment.SetSize(LD_COMMENT_DEFAULTSIZE[0], LD_COMMENT_DEFAULTSIZE[1])
       
   506             self.AddComment(comment)
       
   507             self.RungComments.append(comment)
       
   508             self.Controler.AddEditedElementComment(self.TagName, id)
       
   509             self.RefreshCommentModel(comment)
       
   510             starty += LD_COMMENT_DEFAULTSIZE[1] + LD_OFFSET[1]
       
   511             
       
   512             # Create LeftPowerRail
       
   513             id = self.GetNewId()
       
   514             leftpowerrail = LD_PowerRail(self, LEFTRAIL, id)
       
   515             leftpowerrail.SetPosition(startx, starty)
       
   516             leftpowerrail_connectors = leftpowerrail.GetConnectors()
       
   517             self.AddBlock(leftpowerrail)
       
   518             rung.SelectElement(leftpowerrail)
       
   519             self.Controler.AddEditedElementPowerRail(self.TagName, id, LEFTRAIL)
       
   520             self.RefreshPowerRailModel(leftpowerrail)
       
   521             
       
   522             # Create Coil
       
   523             id = self.GetNewId()
       
   524             coil = LD_Coil(self, values["type"], values["name"], id)
       
   525             coil.SetPosition(startx, starty + (LD_LINE_SIZE - LD_ELEMENT_SIZE[1]) / 2)
       
   526             coil_connectors = coil.GetConnectors()
       
   527             self.AddBlock(coil)
       
   528             rung.SelectElement(coil)
       
   529             self.Controler.AddEditedElementCoil(self.TagName, id)
       
   530             
       
   531             # Create Wire between LeftPowerRail and Coil
       
   532             wire = Wire(self)
       
   533             start_connector = coil_connectors["inputs"][0]
       
   534             end_connector = leftpowerrail_connectors["outputs"][0]
       
   535             start_connector.Connect((wire, 0), False)
       
   536             end_connector.Connect((wire, -1), False)
       
   537             wire.ConnectStartPoint(None, start_connector)
       
   538             wire.ConnectEndPoint(None, end_connector)
       
   539             self.AddWire(wire)
       
   540             rung.SelectElement(wire)
       
   541             
       
   542             # Create RightPowerRail
       
   543             id = self.GetNewId()
       
   544             rightpowerrail = LD_PowerRail(self, RIGHTRAIL, id)
       
   545             rightpowerrail.SetPosition(startx, starty)
       
   546             rightpowerrail_connectors = rightpowerrail.GetConnectors()
       
   547             self.AddBlock(rightpowerrail)
       
   548             rung.SelectElement(rightpowerrail)
       
   549             self.Controler.AddEditedElementPowerRail(self.TagName, id, RIGHTRAIL)
       
   550             
       
   551             # Create Wire between LeftPowerRail and Coil
       
   552             wire = Wire(self)
       
   553             start_connector = rightpowerrail_connectors["inputs"][0]
       
   554             end_connector = coil_connectors["outputs"][0]
       
   555             start_connector.Connect((wire, 0), False)
       
   556             end_connector.Connect((wire, -1), False)
       
   557             wire.ConnectStartPoint(None, start_connector)
       
   558             wire.ConnectEndPoint(None, end_connector)
       
   559             self.AddWire(wire)
       
   560             rung.SelectElement(wire)
       
   561             self.RefreshPosition(coil)
       
   562             self.Rungs.append(rung)
       
   563             self.RefreshBuffer()
       
   564             self.RefreshScrollBars()
       
   565             self.RefreshVisibleElements()
       
   566             self.Refresh(False)
       
   567 
       
   568     def AddLadderContact(self):
       
   569         wires = []
       
   570         if self.IsWire(self.SelectedElement):
       
   571             left_element = self.SelectedElement.EndConnected
       
   572             if not isinstance(left_element.GetParentBlock(), LD_Coil):
       
   573                 wires.append(self.SelectedElement)
       
   574         elif self.SelectedElement and isinstance(self.SelectedElement,Graphic_Group):
       
   575             if False not in [self.IsWire(element) for element in self.SelectedElement.GetElements()]:
       
   576                 for element in self.SelectedElement.GetElements():
       
   577                     wires.append(element)
       
   578         if len(wires) > 0:
       
   579             dialog = LDElementDialog(self.ParentWindow, self.Controler, "contact")
       
   580             dialog.SetPreviewFont(self.GetFont())
       
   581             varlist = []
       
   582             vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
       
   583             if vars:
       
   584                 for var in vars:
       
   585                     if var["Class"] != "Output" and var["Type"] == "BOOL":
       
   586                         varlist.append(var["Name"])
       
   587             dialog.SetVariables(varlist)
       
   588             dialog.SetValues({"name":"","type":CONTACT_NORMAL})
       
   589             if dialog.ShowModal() == wx.ID_OK:
       
   590                 values = dialog.GetValues()
       
   591                 points = wires[0].GetSelectedSegmentPoints()
       
   592                 id = self.GetNewId()
       
   593                 contact = LD_Contact(self, values["type"], values["name"], id)
       
   594                 contact.SetPosition(0, points[0].y - (LD_ELEMENT_SIZE[1] + 1) / 2)
       
   595                 self.AddBlock(contact)
       
   596                 self.Controler.AddEditedElementContact(self.TagName, id)
       
   597                 rungindex = self.FindRung(wires[0])
       
   598                 rung = self.Rungs[rungindex]
       
   599                 old_bbox = rung.GetBoundingBox()
       
   600                 rung.SelectElement(contact)
       
   601                 connectors = contact.GetConnectors()
       
   602                 left_elements = []
       
   603                 right_elements = []
       
   604                 left_index = []
       
   605                 right_index = []
       
   606                 for wire in wires:
       
   607                     if wire.EndConnected not in left_elements:
       
   608                         left_elements.append(wire.EndConnected)
       
   609                         left_index.append(wire.EndConnected.GetWireIndex(wire))
       
   610                     else:
       
   611                         idx = left_elements.index(wire.EndConnected)
       
   612                         left_index[idx] = min(left_index[idx], wire.EndConnected.GetWireIndex(wire))
       
   613                     if wire.StartConnected not in right_elements:
       
   614                         right_elements.append(wire.StartConnected)
       
   615                         right_index.append(wire.StartConnected.GetWireIndex(wire))
       
   616                     else:
       
   617                         idx = right_elements.index(wire.StartConnected)
       
   618                         right_index[idx] = min(right_index[idx], wire.StartConnected.GetWireIndex(wire))
       
   619                     wire.SetSelectedSegment(None)
       
   620                     wire.Clean()
       
   621                     rung.SelectElement(wire)
       
   622                     self.RemoveWire(wire)
       
   623                 wires = []
       
   624                 right_wires = []
       
   625                 for i, left_element in enumerate(left_elements):
       
   626                     wire = Wire(self)
       
   627                     wires.append(wire)
       
   628                     connectors["inputs"][0].Connect((wire, 0), False)
       
   629                     left_element.InsertConnect(left_index[i], (wire, -1), False)
       
   630                     wire.ConnectStartPoint(None, connectors["inputs"][0])
       
   631                     wire.ConnectEndPoint(None, left_element)
       
   632                 for i, right_element in enumerate(right_elements):
       
   633                     wire = Wire(self)
       
   634                     wires.append(wire)
       
   635                     right_wires.append(wire)
       
   636                     right_element.InsertConnect(right_index[i], (wire, 0), False)
       
   637                     connectors["outputs"][0].Connect((wire, -1), False)
       
   638                     wire.ConnectStartPoint(None, right_element)
       
   639                     wire.ConnectEndPoint(None, connectors["outputs"][0])
       
   640                 right_wires.reverse()
       
   641                 for wire in wires:
       
   642                     self.AddWire(wire)
       
   643                     rung.SelectElement(wire)
       
   644                 self.RefreshPosition(contact)
       
   645                 if len(right_wires) > 1:
       
   646                     group = Graphic_Group(self)
       
   647                     group.SetSelected(False)
       
   648                     for wire in right_wires:
       
   649                         wire.SetSelectedSegment(-1)
       
   650                         group.SelectElement(wire)
       
   651                     self.SelectedElement = group
       
   652                 else:
       
   653                     right_wires[0].SetSelectedSegment(-1)
       
   654                     self.SelectedElement = right_wires[0]
       
   655                 rung.RefreshBoundingBox()
       
   656                 new_bbox = rung.GetBoundingBox()
       
   657                 self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1)
       
   658                 self.RefreshBuffer()
       
   659                 self.RefreshScrollBars()
       
   660                 self.RefreshVisibleElements()
       
   661                 self.Refresh(False)
       
   662         else:
       
   663             message = wx.MessageDialog(self, _("You must select the wire where a contact should be added!"), _("Error"), wx.OK|wx.ICON_ERROR)
       
   664             message.ShowModal()
       
   665             message.Destroy()
       
   666 
       
   667     def AddLadderBranch(self):
       
   668         blocks = []
       
   669         if self.IsBlock(self.SelectedElement):
       
   670             blocks = [self.SelectedElement]
       
   671         elif isinstance(self.SelectedElement, Graphic_Group):
       
   672             elements = self.SelectedElement.GetElements()
       
   673             for element in elements:
       
   674                 blocks.append(element)
       
   675         if len(blocks) > 0:
       
   676             blocks_infos = []
       
   677             left_elements = []
       
   678             left_index = []
       
   679             right_elements = []
       
   680             right_index = []
       
   681             for block in blocks:
       
   682                 connectors = block.GetConnectors()
       
   683                 block_infos = {"lefts":[],"rights":[]}
       
   684                 block_infos.update(connectors)
       
   685                 for connector in block_infos["inputs"]:
       
   686                     for wire, handle in connector.GetWires():
       
   687                         found = False
       
   688                         for infos in blocks_infos:
       
   689                             if wire.EndConnected in infos["outputs"]:
       
   690                                 for left_element in infos["lefts"]:
       
   691                                     if left_element not in block_infos["lefts"]:
       
   692                                         block_infos["lefts"].append(left_element)
       
   693                                 found = True
       
   694                         if not found and wire.EndConnected not in block_infos["lefts"]:
       
   695                             block_infos["lefts"].append(wire.EndConnected)
       
   696                             if wire.EndConnected not in left_elements:
       
   697                                 left_elements.append(wire.EndConnected)
       
   698                                 left_index.append(wire.EndConnected.GetWireIndex(wire))
       
   699                             else:
       
   700                                 index = left_elements.index(wire.EndConnected)
       
   701                                 left_index[index] = max(left_index[index], wire.EndConnected.GetWireIndex(wire))
       
   702                 for connector in block_infos["outputs"]:
       
   703                     for wire, handle in connector.GetWires():
       
   704                         found = False
       
   705                         for infos in blocks_infos:
       
   706                             if wire.StartConnected in infos["inputs"]:
       
   707                                 for right_element in infos["rights"]:
       
   708                                     if right_element not in block_infos["rights"]:
       
   709                                         block_infos["rights"].append(right_element)
       
   710                                 found = True
       
   711                         if not found and wire.StartConnected not in block_infos["rights"]:
       
   712                             block_infos["rights"].append(wire.StartConnected)
       
   713                             if wire.StartConnected not in right_elements:
       
   714                                 right_elements.append(wire.StartConnected)
       
   715                                 right_index.append(wire.StartConnected.GetWireIndex(wire))
       
   716                             else:
       
   717                                 index = right_elements.index(wire.StartConnected)
       
   718                                 right_index[index] = max(right_index[index], wire.StartConnected.GetWireIndex(wire))
       
   719                 for connector in block_infos["inputs"]:
       
   720                     for infos in blocks_infos:
       
   721                         if connector in infos["rights"]:
       
   722                             infos["rights"].remove(connector)
       
   723                             if connector in right_elements:
       
   724                                 index = right_elements.index(connector)
       
   725                                 right_elements.pop(index)
       
   726                                 right_index.pop(index)
       
   727                             for right_element in block_infos["rights"]:
       
   728                                 if right_element not in infos["rights"]:
       
   729                                     infos["rights"].append(right_element)
       
   730                 for connector in block_infos["outputs"]:
       
   731                     for infos in blocks_infos:
       
   732                         if connector in infos["lefts"]:
       
   733                             infos["lefts"].remove(connector)
       
   734                             if connector in left_elements:
       
   735                                 index = left_elements.index(connector)
       
   736                                 left_elements.pop(index)
       
   737                                 left_index.pop(index)
       
   738                             for left_element in block_infos["lefts"]:
       
   739                                 if left_element not in infos["lefts"]:
       
   740                                     infos["lefts"].append(left_element)
       
   741                 blocks_infos.append(block_infos)
       
   742             for infos in blocks_infos:
       
   743                 left_elements = [element for element in infos["lefts"]]
       
   744                 for left_element in left_elements:
       
   745                     if isinstance(left_element.GetParentBlock(), LD_PowerRail):
       
   746                         infos["lefts"].remove(left_element)
       
   747                         if "LD_PowerRail" not in infos["lefts"]:
       
   748                             infos["lefts"].append("LD_PowerRail")
       
   749                 right_elements = [element for element in infos["rights"]]
       
   750                 for right_element in right_elements:
       
   751                     if isinstance(right_element.GetParentBlock(), LD_PowerRail):
       
   752                         infos["rights"].remove(right_element)
       
   753                         if "LD_PowerRail" not in infos["rights"]:
       
   754                             infos["rights"].append("LD_PowerRail")
       
   755                 infos["lefts"].sort()
       
   756                 infos["rights"].sort()
       
   757             lefts = blocks_infos[0]["lefts"]
       
   758             rights = blocks_infos[0]["rights"]
       
   759             good = True
       
   760             for infos in blocks_infos[1:]:
       
   761                 good &= infos["lefts"] == lefts
       
   762                 good &= infos["rights"] == rights
       
   763             if good:
       
   764                 rungindex = self.FindRung(blocks[0])
       
   765                 rung = self.Rungs[rungindex]
       
   766                 old_bbox = rung.GetBoundingBox()
       
   767                 left_powerrail = True
       
   768                 right_powerrail = True
       
   769                 for element in left_elements:
       
   770                     left_powerrail &= isinstance(element.GetParentBlock(), LD_PowerRail)
       
   771                 for element in right_elements:
       
   772                     right_powerrail &= isinstance(element.GetParentBlock(), LD_PowerRail)
       
   773                 if not left_powerrail or not right_powerrail:
       
   774                     wires = []
       
   775                     if left_powerrail:
       
   776                         powerrail = left_elements[0].GetParentBlock()
       
   777                         index = 0
       
   778                         for left_element in left_elements: 
       
   779                             index = max(index, powerrail.GetConnectorIndex(left_element))
       
   780                         powerrail.InsertConnector(index + 1)
       
   781                         powerrail.RefreshModel()
       
   782                         connectors = powerrail.GetConnectors()
       
   783                         right_elements.reverse()
       
   784                         for i, right_element in enumerate(right_elements):
       
   785                             new_wire = Wire(self)
       
   786                             wires.append(new_wire)
       
   787                             right_element.InsertConnect(right_index[i] + 1, (new_wire, 0), False)
       
   788                             connectors["outputs"][index + 1].Connect((new_wire, -1), False)
       
   789                             new_wire.ConnectStartPoint(None, right_element)
       
   790                             new_wire.ConnectEndPoint(None, connectors["outputs"][index + 1])
       
   791                         right_elements.reverse()
       
   792                     elif right_powerrail:
       
   793                         dialog = LDElementDialog(self.ParentWindow, self.Controleur, "coil")
       
   794                         dialog.SetPreviewFont(self.GetFont())
       
   795                         varlist = []
       
   796                         vars = self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)
       
   797                         if vars:
       
   798                             for var in vars:
       
   799                                 if var["Class"] != "Input" and var["Type"] == "BOOL":
       
   800                                     varlist.append(var["Name"])
       
   801                         returntype = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug)
       
   802                         if returntype == "BOOL":
       
   803                             varlist.append(self.Controler.GetEditedElementName(self.TagName))
       
   804                         dialog.SetVariables(varlist)
       
   805                         dialog.SetValues({"name":"","type":COIL_NORMAL})
       
   806                         if dialog.ShowModal() == wx.ID_OK:
       
   807                             values = dialog.GetValues()
       
   808                             powerrail = right_elements[0].GetParentBlock()
       
   809                             index = 0
       
   810                             for right_element in right_elements: 
       
   811                                 index = max(index, powerrail.GetConnectorIndex(right_element))
       
   812                             powerrail.InsertConnector(index + 1)
       
   813                             powerrail.RefreshModel()
       
   814                             connectors = powerrail.GetConnectors()
       
   815                             
       
   816                             # Create Coil
       
   817                             id = self.GetNewId()
       
   818                             coil = LD_Coil(self, values["type"], values["name"], id)
       
   819                             pos = blocks[0].GetPosition()
       
   820                             coil.SetPosition(pos[0], pos[1] + LD_LINE_SIZE)
       
   821                             self.AddBlock(coil)
       
   822                             rung.SelectElement(coil)
       
   823                             self.Controler.AddEditedElementCoil(self.TagName, id)
       
   824                             coil_connectors = coil.GetConnectors()
       
   825                             
       
   826                             # Create Wire between LeftPowerRail and Coil
       
   827                             wire = Wire(self)
       
   828                             connectors["inputs"][index + 1].Connect((wire, 0), False)
       
   829                             coil_connectors["outputs"][0].Connect((wire, -1), False)
       
   830                             wire.ConnectStartPoint(None, connectors["inputs"][index + 1])
       
   831                             wire.ConnectEndPoint(None, coil_connectors["outputs"][0])
       
   832                             self.AddWire(wire)
       
   833                             rung.SelectElement(wire)
       
   834                             left_elements.reverse()
       
   835                             
       
   836                             for i, left_element in enumerate(left_elements):
       
   837                                 # Create Wire between LeftPowerRail and Coil
       
   838                                 new_wire = Wire(self)
       
   839                                 wires.append(new_wire)
       
   840                                 coil_connectors["inputs"][0].Connect((new_wire, 0), False)
       
   841                                 left_element.InsertConnect(left_index[i] + 1, (new_wire, -1), False)
       
   842                                 new_wire.ConnectStartPoint(None, coil_connectors["inputs"][0])
       
   843                                 new_wire.ConnectEndPoint(None, left_element)
       
   844                             
       
   845                             self.RefreshPosition(coil)
       
   846                     else:
       
   847                         left_elements.reverse()
       
   848                         right_elements.reverse()
       
   849                         for i, left_element in enumerate(left_elements):
       
   850                             for j, right_element in enumerate(right_elements):
       
   851                                 exist = False
       
   852                                 for wire, handle in right_element.GetWires():
       
   853                                     exist |= wire.EndConnected == left_element
       
   854                                 if not exist:
       
   855                                     new_wire = Wire(self)
       
   856                                     wires.append(new_wire)
       
   857                                     right_element.InsertConnect(right_index[j] + 1, (new_wire, 0), False)
       
   858                                     left_element.InsertConnect(left_index[i] + 1, (new_wire, -1), False)
       
   859                                     new_wire.ConnectStartPoint(None, right_element)
       
   860                                     new_wire.ConnectEndPoint(None, left_element)
       
   861                     wires.reverse()
       
   862                     for wire in wires:
       
   863                         self.AddWire(wire)
       
   864                         rung.SelectElement(wire)
       
   865                     right_elements.reverse()
       
   866                 for block in blocks:
       
   867                     self.RefreshPosition(block)
       
   868                 for right_element in right_elements:
       
   869                     self.RefreshPosition(right_element.GetParentBlock())
       
   870                 self.SelectedElement.RefreshBoundingBox()
       
   871                 rung.RefreshBoundingBox()
       
   872                 new_bbox = rung.GetBoundingBox()
       
   873                 self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1)
       
   874                 self.RefreshBuffer()
       
   875                 self.RefreshScrollBars()
       
   876                 self.RefreshVisibleElements()
       
   877                 self.Refresh(False)
       
   878             else:
       
   879                 message = wx.MessageDialog(self, _("The group of block must be coherent!"), _("Error"), wx.OK|wx.ICON_ERROR)
       
   880                 message.ShowModal()
       
   881                 message.Destroy()
       
   882         else:
       
   883             message = wx.MessageDialog(self, _("You must select the block or group of blocks around which a branch should be added!"), _("Error"), wx.OK|wx.ICON_ERROR)
       
   884             message.ShowModal()
       
   885             message.Destroy()
       
   886 
       
   887     def AddLadderBlock(self):
       
   888         message = wx.MessageDialog(self, _("This option isn't available yet!"), _("Warning"), wx.OK|wx.ICON_EXCLAMATION)
       
   889         message.ShowModal()
       
   890         message.Destroy()
       
   891 
       
   892 #-------------------------------------------------------------------------------
       
   893 #                          Delete element functions
       
   894 #-------------------------------------------------------------------------------
       
   895 
       
   896     def DeleteContact(self, contact):
       
   897         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
   898             Viewer.DeleteContact(self, contact)
       
   899         else:
       
   900             rungindex = self.FindRung(contact)
       
   901             rung = self.Rungs[rungindex]
       
   902             old_bbox = rung.GetBoundingBox()
       
   903             connectors = contact.GetConnectors()
       
   904             input_wires = [wire for wire, handle in connectors["inputs"][0].GetWires()]
       
   905             output_wires = [wire for wire, handle in connectors["outputs"][0].GetWires()]
       
   906             left_elements = [(wire.EndConnected, wire.EndConnected.GetWireIndex(wire)) for wire in input_wires]
       
   907             right_elements = [(wire.StartConnected, wire.StartConnected.GetWireIndex(wire)) for wire in output_wires]
       
   908             for wire in input_wires:
       
   909                 wire.Clean()
       
   910                 rung.SelectElement(wire)
       
   911                 self.RemoveWire(wire)
       
   912             for wire in output_wires:
       
   913                 wire.Clean()
       
   914                 rung.SelectElement(wire)
       
   915                 self.RemoveWire(wire)
       
   916             rung.SelectElement(contact)
       
   917             contact.Clean()
       
   918             left_elements.reverse()
       
   919             right_elements.reverse()
       
   920             powerrail = len(left_elements) == 1 and isinstance(left_elements[0][0].GetParentBlock(), LD_PowerRail)
       
   921             for left_element, left_index in left_elements:
       
   922                 for right_element, right_index in right_elements:
       
   923                     wire_removed = []
       
   924                     for wire, handle in right_element.GetWires():
       
   925                         if wire.EndConnected == left_element:
       
   926                             wire_removed.append(wire)
       
   927                         elif isinstance(wire.EndConnected.GetParentBlock(), LD_PowerRail) and powerrail:
       
   928                             left_powerrail = wire.EndConnected.GetParentBlock()
       
   929                             index = left_powerrail.GetConnectorIndex(wire.EndConnected)
       
   930                             left_powerrail.DeleteConnector(index)
       
   931                             wire_removed.append(wire)
       
   932                     for wire in wire_removed:
       
   933                         wire.Clean()
       
   934                         self.RemoveWire(wire)
       
   935                         rung.SelectElement(wire)
       
   936             wires = []
       
   937             for left_element, left_index in left_elements:
       
   938                 for right_element, right_index in right_elements:
       
   939                     wire = Wire(self)
       
   940                     wires.append(wire)
       
   941                     right_element.InsertConnect(right_index, (wire, 0), False)
       
   942                     left_element.InsertConnect(left_index, (wire, -1), False)
       
   943                     wire.ConnectStartPoint(None, right_element)
       
   944                     wire.ConnectEndPoint(None, left_element)
       
   945             wires.reverse()
       
   946             for wire in wires:
       
   947                 self.AddWire(wire)
       
   948                 rung.SelectElement(wire)
       
   949             right_elements.reverse()
       
   950             for right_element, right_index in right_elements:
       
   951                 self.RefreshPosition(right_element.GetParentBlock())
       
   952             self.RemoveBlock(contact)
       
   953             self.Controler.RemoveEditedElementInstance(self.TagName, contact.GetId())
       
   954             rung.RefreshBoundingBox()
       
   955             new_bbox = rung.GetBoundingBox()
       
   956             self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1)
       
   957             self.SelectedElement = None
       
   958 
       
   959     def RecursiveDeletion(self, element, rung):
       
   960         connectors = element.GetConnectors()
       
   961         input_wires = [wire for wire, handle in connectors["inputs"][0].GetWires()]
       
   962         left_elements = [wire.EndConnected for wire in input_wires]
       
   963         rung.SelectElement(element)
       
   964         element.Clean()
       
   965         for wire in input_wires:
       
   966             wire.Clean()
       
   967             self.RemoveWire(wire)
       
   968             rung.SelectElement(wire)
       
   969         self.RemoveBlock(element)
       
   970         self.Controler.RemoveEditedElementInstance(self.TagName, element.GetId())
       
   971         for left_element in left_elements:
       
   972             block = left_element.GetParentBlock()
       
   973             if len(left_element.GetWires()) == 0:
       
   974                 self.RecursiveDeletion(block, rung)
       
   975             else:
       
   976                 self.RefreshPosition(block)
       
   977 
       
   978     def DeleteCoil(self, coil):
       
   979         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
   980             Viewer.DeleteContact(self, coil)
       
   981         else:
       
   982             rungindex = self.FindRung(coil)
       
   983             rung = self.Rungs[rungindex]
       
   984             old_bbox = rung.GetBoundingBox()
       
   985             nbcoils = 0
       
   986             for element in rung.GetElements():
       
   987                 if isinstance(element, LD_Coil):
       
   988                     nbcoils += 1
       
   989             if nbcoils > 1:
       
   990                 connectors = coil.GetConnectors()
       
   991                 output_wires = [wire for wire, handle in connectors["outputs"][0].GetWires()]
       
   992                 right_elements = [wire.StartConnected for wire in output_wires]
       
   993                 for wire in output_wires:
       
   994                     wire.Clean()
       
   995                     self.Wires.remove(wire)
       
   996                     self.Elements.remove(wire)
       
   997                     rung.SelectElement(wire)
       
   998                 for right_element in right_elements:
       
   999                     right_block = right_element.GetParentBlock()
       
  1000                     if isinstance(right_block, LD_PowerRail):
       
  1001                         if len(right_element.GetWires()) == 0:
       
  1002                             index = right_block.GetConnectorIndex(right_element)
       
  1003                             right_block.DeleteConnector(index)
       
  1004                             powerrail_connectors = right_block.GetConnectors()
       
  1005                             for connector in powerrail_connectors["inputs"]:
       
  1006                                 for wire, handle in connector.GetWires():
       
  1007                                     block = wire.EndConnected.GetParentBlock()
       
  1008                                     endpoint = wire.EndConnected.GetPosition(False)
       
  1009                                     startpoint = connector.GetPosition(False)
       
  1010                                     block.Move(0, startpoint.y - endpoint.y)
       
  1011                                     self.RefreshPosition(block)
       
  1012                 self.RecursiveDeletion(coil, rung)
       
  1013             else:
       
  1014                 for element in rung.GetElements():
       
  1015                     if self.IsWire(element):
       
  1016                         element.Clean()
       
  1017                         self.RemoveWire(element)
       
  1018                 for element in rung.GetElements():
       
  1019                     if self.IsBlock(element):
       
  1020                         self.Controler.RemoveEditedElementInstance(self.TagName, element.GetId())
       
  1021                         self.RemoveBlock(element)
       
  1022                 self.Controler.RemoveEditedElementInstance(self.TagName, self.Comments[rungindex].GetId())
       
  1023                 self.RemoveComment(self.RungComments[rungindex])
       
  1024                 self.RungComments.pop(rungindex)
       
  1025                 self.Rungs.pop(rungindex)
       
  1026                 if rungindex < len(self.Rungs):
       
  1027                     next_bbox = self.Rungs[rungindex].GetBoundingBox()
       
  1028                     self.RefreshRungs(old_bbox.y - next_bbox.y, rungindex)
       
  1029             self.SelectedElement = None
       
  1030 
       
  1031     def DeleteWire(self, wire):
       
  1032         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  1033             Viewer.DeleteWire(self, wire)
       
  1034         else:
       
  1035             wires = []
       
  1036             left_elements = []
       
  1037             right_elements = []
       
  1038             if self.IsWire(wire):
       
  1039                 wires = [wire]
       
  1040             elif isinstance(wire, Graphic_Group):
       
  1041                 for element in wire.GetElements():
       
  1042                     if self.IsWire(element):
       
  1043                         wires.append(element)
       
  1044                     else:
       
  1045                         wires = []
       
  1046                         break
       
  1047             if len(wires) > 0:
       
  1048                 rungindex = self.FindRung(wires[0])
       
  1049                 rung = self.Rungs[rungindex]
       
  1050                 old_bbox = rung.GetBoundingBox()
       
  1051                 for wire in wires:
       
  1052                     connections = wire.GetSelectedSegmentConnections()
       
  1053                     left_block = wire.EndConnected.GetParentBlock()
       
  1054                     if wire.EndConnected not in left_elements:
       
  1055                         left_elements.append(wire.EndConnected)
       
  1056                     if wire.StartConnected not in right_elements:
       
  1057                         right_elements.append(wire.StartConnected)
       
  1058                     if connections == (False, False) or connections == (False, True) and isinstance(left_block, LD_PowerRail):
       
  1059                         wire.Clean()
       
  1060                         self.RemoveWire(wire)
       
  1061                         rung.SelectElement(wire)
       
  1062                 for left_element in left_elements:
       
  1063                     left_block = left_element.GetParentBlock()
       
  1064                     if isinstance(left_block, LD_PowerRail):
       
  1065                         if len(left_element.GetWires()) == 0:
       
  1066                             index = left_block.GetConnectorIndex(left_element)
       
  1067                             left_block.DeleteConnector(index)
       
  1068                     else:
       
  1069                         connectors = left_block.GetConnectors()
       
  1070                         for connector in connectors["outputs"]:
       
  1071                             for wire, handle in connector.GetWires():
       
  1072                                 self.RefreshPosition(wire.StartConnected.GetParentBlock())
       
  1073                 for right_element in right_elements:
       
  1074                     self.RefreshPosition(right_element.GetParentBlock())
       
  1075                 rung.RefreshBoundingBox()
       
  1076                 new_bbox = rung.GetBoundingBox()
       
  1077                 self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1)
       
  1078                 self.SelectedElement = None
       
  1079 
       
  1080 #-------------------------------------------------------------------------------
       
  1081 #                        Refresh element position functions
       
  1082 #-------------------------------------------------------------------------------
       
  1083 
       
  1084     def RefreshPosition(self, element, recursive=True):
       
  1085         # If element is LeftPowerRail, no need to update position
       
  1086         if isinstance(element, LD_PowerRail) and element.GetType() == LEFTRAIL:
       
  1087             element.RefreshModel()
       
  1088             return
       
  1089         
       
  1090         # Extract max position of the elements connected to input
       
  1091         connectors = element.GetConnectors()
       
  1092         position = element.GetPosition()
       
  1093         maxx = 0
       
  1094         onlyone = []
       
  1095         for connector in connectors["inputs"]:
       
  1096             onlyone.append(len(connector.GetWires()) == 1)
       
  1097             for wire, handle in connector.GetWires():
       
  1098                 onlyone[-1] &= len(wire.EndConnected.GetWires()) == 1
       
  1099                 leftblock = wire.EndConnected.GetParentBlock()
       
  1100                 pos = leftblock.GetPosition()
       
  1101                 size = leftblock.GetSize()
       
  1102                 maxx = max(maxx, pos[0] + size[0])
       
  1103         
       
  1104         # Refresh position of element
       
  1105         if isinstance(element, LD_Coil):
       
  1106             interval = LD_WIRECOIL_SIZE
       
  1107         else:
       
  1108             interval = LD_WIRE_SIZE
       
  1109         if False in onlyone:
       
  1110             interval += LD_WIRE_SIZE
       
  1111         movex = maxx + interval - position[0]
       
  1112         element.Move(movex, 0)
       
  1113         position = element.GetPosition()
       
  1114         
       
  1115         # Extract blocks connected to inputs
       
  1116         blocks = []
       
  1117         for i, connector in enumerate(connectors["inputs"]):
       
  1118             for j, (wire, handle) in enumerate(connector.GetWires()):
       
  1119                 blocks.append(wire.EndConnected.GetParentBlock())
       
  1120         
       
  1121         for i, connector in enumerate(connectors["inputs"]):
       
  1122             startpoint = connector.GetPosition(False)
       
  1123             previous_blocks = []
       
  1124             block_list = []
       
  1125             start_offset = 0
       
  1126             if not onlyone[i]:
       
  1127                 middlepoint = maxx + LD_WIRE_SIZE
       
  1128             for j, (wire, handle) in enumerate(connector.GetWires()):
       
  1129                 block = wire.EndConnected.GetParentBlock()
       
  1130                 if isinstance(element, LD_PowerRail):
       
  1131                     pos = block.GetPosition()
       
  1132                     size = leftblock.GetSize()
       
  1133                     movex = position[0] - LD_WIRE_SIZE - size[0] - pos[0]
       
  1134                     block.Move(movex, 0)
       
  1135                 endpoint = wire.EndConnected.GetPosition(False)
       
  1136                 if j == 0:
       
  1137                     if not onlyone[i] and wire.EndConnected.GetWireIndex(wire) > 0:
       
  1138                         start_offset = endpoint.y - startpoint.y
       
  1139                     offset = start_offset
       
  1140                 else:
       
  1141                     offset = start_offset + LD_LINE_SIZE * CalcBranchSize(previous_blocks, blocks)
       
  1142                 if block in block_list:
       
  1143                     wires = wire.EndConnected.GetWires()
       
  1144                     endmiddlepoint = wires[0][0].StartConnected.GetPosition(False)[0] - LD_WIRE_SIZE
       
  1145                     points = [startpoint, wx.Point(middlepoint, startpoint.y),
       
  1146                               wx.Point(middlepoint, startpoint.y + offset),
       
  1147                               wx.Point(endmiddlepoint, startpoint.y + offset),
       
  1148                               wx.Point(endmiddlepoint, endpoint.y), endpoint]
       
  1149                 else:
       
  1150                     if startpoint.y + offset != endpoint.y:
       
  1151                         if isinstance(element, LD_PowerRail):
       
  1152                             element.MoveConnector(connector, startpoint.y - endpoint.y)
       
  1153                         elif isinstance(block, LD_PowerRail):
       
  1154                             block.MoveConnector(wire.EndConnected, startpoint.y - endpoint.y)
       
  1155                         else:
       
  1156                             block.Move(0, startpoint.y + offset - endpoint.y)
       
  1157                             self.RefreshPosition(block, False)
       
  1158                         endpoint = wire.EndConnected.GetPosition(False)
       
  1159                     if not onlyone[i]:
       
  1160                         points = [startpoint, wx.Point(middlepoint, startpoint.y),
       
  1161                                   wx.Point(middlepoint, endpoint.y), endpoint]
       
  1162                     else:
       
  1163                         points = [startpoint, endpoint]
       
  1164                 wire.SetPoints(points, False)
       
  1165                 previous_blocks.append(block)
       
  1166                 blocks.remove(block)
       
  1167                 ExtractNextBlocks(block, block_list)
       
  1168         
       
  1169         element.RefreshModel(False)
       
  1170         if recursive:
       
  1171             for connector in connectors["outputs"]:
       
  1172                 for wire, handle in connector.GetWires():
       
  1173                     self.RefreshPosition(wire.StartConnected.GetParentBlock())
       
  1174     
       
  1175     def RefreshRungs(self, movey, fromidx):
       
  1176         if movey != 0:
       
  1177             for i in xrange(fromidx, len(self.Rungs)):
       
  1178                 self.RungComments[i].Move(0, movey)
       
  1179                 self.RungComments[i].RefreshModel()
       
  1180                 self.Rungs[i].Move(0, movey)
       
  1181                 for element in self.Rungs[i].GetElements():
       
  1182                     if self.IsBlock(element):
       
  1183                         self.RefreshPosition(element)
       
  1184 
       
  1185 #-------------------------------------------------------------------------------
       
  1186 #                          Edit element content functions
       
  1187 #-------------------------------------------------------------------------------
       
  1188 
       
  1189     def EditPowerRailContent(self, powerrail):
       
  1190         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  1191             Viewer.EditPowerRailContent(self, powerrail)
       
  1192