graphics/LD_Objects.py
changeset 1784 64beb9e9c749
parent 1782 5b6ad7a7fd9d
child 1847 6198190bc121
equal deleted inserted replaced
1729:31e63e25b4cc 1784:64beb9e9c749
    26 
    26 
    27 from graphics.GraphicCommons import *
    27 from graphics.GraphicCommons import *
    28 from graphics.DebugDataConsumer import DebugDataConsumer
    28 from graphics.DebugDataConsumer import DebugDataConsumer
    29 from plcopen.structures import *
    29 from plcopen.structures import *
    30 
    30 
    31 #-------------------------------------------------------------------------------
    31 
       
    32 # -------------------------------------------------------------------------------
    32 #                         Ladder Diagram PowerRail
    33 #                         Ladder Diagram PowerRail
    33 #-------------------------------------------------------------------------------
    34 # -------------------------------------------------------------------------------
    34 
    35 
    35 """
       
    36 Class that implements the graphic representation of a power rail
       
    37 """
       
    38 
    36 
    39 class LD_PowerRail(Graphic_Element):
    37 class LD_PowerRail(Graphic_Element):
    40     
    38     """
       
    39     Class that implements the graphic representation of a power rail
       
    40     """
       
    41 
    41     # Create a new power rail
    42     # Create a new power rail
    42     def __init__(self, parent, type, id=None, connectors=1):
    43     def __init__(self, parent, type, id=None, connectors=1):
    43         Graphic_Element.__init__(self, parent)
    44         Graphic_Element.__init__(self, parent)
    44         self.Type = None
    45         self.Type = None
    45         self.Connectors = []
    46         self.Connectors = []
    46         self.RealConnectors = None
    47         self.RealConnectors = None
    47         self.Id = id
    48         self.Id = id
    48         self.Extensions = [LD_LINE_SIZE / 2, LD_LINE_SIZE / 2]
    49         self.Extensions = [LD_LINE_SIZE / 2, LD_LINE_SIZE / 2]
    49         self.SetType(type, connectors)
    50         self.SetType(type, connectors)
    50         
    51 
    51     def Flush(self):
    52     def Flush(self):
    52         for connector in self.Connectors:
    53         for connector in self.Connectors:
    53             connector.Flush()
    54             connector.Flush()
    54         self.Connectors = []
    55         self.Connectors = []
    55     
    56 
    56     # Make a clone of this LD_PowerRail
    57     # Make a clone of this LD_PowerRail
    57     def Clone(self, parent, id = None, pos = None):
    58     def Clone(self, parent, id=None, pos=None):
    58         powerrail = LD_PowerRail(parent, self.Type, id)
    59         powerrail = LD_PowerRail(parent, self.Type, id)
    59         powerrail.SetSize(self.Size[0], self.Size[1])
    60         powerrail.SetSize(self.Size[0], self.Size[1])
    60         if pos is not None:
    61         if pos is not None:
    61             powerrail.SetPosition(pos.x, pos.y)
    62             powerrail.SetPosition(pos.x, pos.y)
    62         else:
    63         else:
    63             powerrail.SetPosition(self.Pos.x, self.Pos.y)
    64             powerrail.SetPosition(self.Pos.x, self.Pos.y)
    64         powerrail.Connectors = []
    65         powerrail.Connectors = []
    65         for connector in self.Connectors:
    66         for connector in self.Connectors:
    66             powerrail.Connectors.append(connector.Clone(powerrail))
    67             powerrail.Connectors.append(connector.Clone(powerrail))
    67         return powerrail
    68         return powerrail
    68     
    69 
    69     def GetConnectorTranslation(self, element):
    70     def GetConnectorTranslation(self, element):
    70         return dict(zip([connector for connector in self.Connectors],
    71         return dict(zip([connector for connector in self.Connectors],
    71                         [connector for connector in element.Connectors]))
    72                         [connector for connector in element.Connectors]))
    72     
    73 
    73     # Returns the RedrawRect
    74     # Returns the RedrawRect
    74     def GetRedrawRect(self, movex = 0, movey = 0):
    75     def GetRedrawRect(self, movex=0, movey=0):
    75         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
    76         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
    76         for connector in self.Connectors:
    77         for connector in self.Connectors:
    77             rect = rect.Union(connector.GetRedrawRect(movex, movey))
    78             rect = rect.Union(connector.GetRedrawRect(movex, movey))
    78         if movex != 0 or movey != 0:
    79         if movex != 0 or movey != 0:
    79             for connector in self.Connectors:
    80             for connector in self.Connectors:
    80                 if connector.IsConnected():
    81                 if connector.IsConnected():
    81                     rect = rect.Union(connector.GetConnectedRedrawRect(movex, movey))
    82                     rect = rect.Union(connector.GetConnectedRedrawRect(movex, movey))
    82         return rect
    83         return rect
    83     
    84 
    84     # Forbids to change the power rail size
    85     # Forbids to change the power rail size
    85     def SetSize(self, width, height):
    86     def SetSize(self, width, height):
    86         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
    87         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
    87             Graphic_Element.SetSize(self, width, height)
    88             Graphic_Element.SetSize(self, width, height)
    88         else:
    89         else:
    89             Graphic_Element.SetSize(self, LD_POWERRAIL_WIDTH, height)
    90             Graphic_Element.SetSize(self, LD_POWERRAIL_WIDTH, height)
    90         self.RefreshConnectors()
    91         self.RefreshConnectors()
    91     
    92 
    92     # Forbids to select a power rail
    93     # Forbids to select a power rail
    93     def HitTest(self, pt, connectors=True):
    94     def HitTest(self, pt, connectors=True):
    94         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
    95         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
    95             return Graphic_Element.HitTest(self, pt, connectors) or self.TestConnector(pt, exclude=False) != None
    96             return Graphic_Element.HitTest(self, pt, connectors) or self.TestConnector(pt, exclude=False) is not None
    96         return False
    97         return False
    97     
    98 
    98     # Forbids to select a power rail
    99     # Forbids to select a power rail
    99     def IsInSelection(self, rect):
   100     def IsInSelection(self, rect):
   100         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   101         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   101             return Graphic_Element.IsInSelection(self, rect)
   102             return Graphic_Element.IsInSelection(self, rect)
   102         return False
   103         return False
   103     
   104 
   104     # Deletes this power rail by calling the appropriate method
   105     # Deletes this power rail by calling the appropriate method
   105     def Delete(self):
   106     def Delete(self):
   106         self.Parent.DeletePowerRail(self)
   107         self.Parent.DeletePowerRail(self)
   107     
   108 
   108     # Unconnect all connectors
   109     # Unconnect all connectors
   109     def Clean(self):
   110     def Clean(self):
   110         for connector in self.Connectors:
   111         for connector in self.Connectors:
   111             connector.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   112             connector.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   112                 
   113 
   113     # Refresh the power rail bounding box
   114     # Refresh the power rail bounding box
   114     def RefreshBoundingBox(self):
   115     def RefreshBoundingBox(self):
   115         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   116         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   116     
   117 
   117     # Refresh the power rail size
   118     # Refresh the power rail size
   118     def RefreshSize(self):
   119     def RefreshSize(self):
   119         self.Size = wx.Size(LD_POWERRAIL_WIDTH, max(LD_LINE_SIZE * len(self.Connectors), self.Size[1]))
   120         self.Size = wx.Size(LD_POWERRAIL_WIDTH, max(LD_LINE_SIZE * len(self.Connectors), self.Size[1]))
   120         self.RefreshBoundingBox()
   121         self.RefreshBoundingBox()
   121     
   122 
   122     # Returns the block minimum size
   123     # Returns the block minimum size
   123     def GetMinSize(self, default=False):
   124     def GetMinSize(self, default=False):
   124         height = (LD_LINE_SIZE * (len(self.Connectors) - 1)
   125         height = (LD_LINE_SIZE * (len(self.Connectors) - 1)
   125                   if default else 0)
   126                   if default else 0)
   126         return LD_POWERRAIL_WIDTH, height + self.Extensions[0] + self.Extensions[1]
   127         return LD_POWERRAIL_WIDTH, height + self.Extensions[0] + self.Extensions[1]
   127     
   128 
   128     # Add a connector or a blank to this power rail at the last place
   129     # Add a connector or a blank to this power rail at the last place
   129     def AddConnector(self):
   130     def AddConnector(self):
   130         self.InsertConnector(len(self.Connectors))
   131         self.InsertConnector(len(self.Connectors))
   131     
   132 
   132     # Add a connector or a blank to this power rail at the place given
   133     # Add a connector or a blank to this power rail at the place given
   133     def InsertConnector(self, idx):
   134     def InsertConnector(self, idx):
   134         if self.Type == LEFTRAIL:
   135         if self.Type == LEFTRAIL:
   135             connector = Connector(self, "", "BOOL", wx.Point(self.Size[0], 0), EAST)
   136             connector = Connector(self, "", "BOOL", wx.Point(self.Size[0], 0), EAST)
   136         elif self.Type == RIGHTRAIL:
   137         elif self.Type == RIGHTRAIL:
   137             connector = Connector(self, "", "BOOL", wx.Point(0, 0), WEST)
   138             connector = Connector(self, "", "BOOL", wx.Point(0, 0), WEST)
   138         self.Connectors.insert(idx, connector)
   139         self.Connectors.insert(idx, connector)
   139         self.RefreshSize()
   140         self.RefreshSize()
   140         self.RefreshConnectors()
   141         self.RefreshConnectors()
   141     
   142 
   142     # Moves the divergence connector given
   143     # Moves the divergence connector given
   143     def MoveConnector(self, connector, movey):
   144     def MoveConnector(self, connector, movey):
   144         position = connector.GetRelPosition()
   145         position = connector.GetRelPosition()
   145         connector.SetPosition(wx.Point(position.x, position.y + movey))
   146         connector.SetPosition(wx.Point(position.x, position.y + movey))
   146         miny = self.Size[1]
   147         miny = self.Size[1]
   161             connect_pos = connect.GetRelPosition()
   162             connect_pos = connect.GetRelPosition()
   162             maxy = max(maxy, connect_pos.y)
   163             maxy = max(maxy, connect_pos.y)
   163         self.Size[1] = max(maxy + self.Extensions[1], self.Size[1])
   164         self.Size[1] = max(maxy + self.Extensions[1], self.Size[1])
   164         connector.MoveConnected()
   165         connector.MoveConnected()
   165         self.RefreshBoundingBox()
   166         self.RefreshBoundingBox()
   166     
   167 
   167     # Returns the index in connectors list for the connector given
   168     # Returns the index in connectors list for the connector given
   168     def GetConnectorIndex(self, connector):
   169     def GetConnectorIndex(self, connector):
   169         if connector in self.Connectors:
   170         if connector in self.Connectors:
   170             return self.Connectors.index(connector)
   171             return self.Connectors.index(connector)
   171         return None
   172         return None
   172     
   173 
   173     # Delete the connector or blank from connectors list at the index given
   174     # Delete the connector or blank from connectors list at the index given
   174     def DeleteConnector(self, idx):
   175     def DeleteConnector(self, idx):
   175         self.Connectors.pop(idx)
   176         self.Connectors.pop(idx)
   176         self.RefreshConnectors()
   177         self.RefreshConnectors()
   177         self.RefreshSize()
   178         self.RefreshSize()
   178     
   179 
   179     # Refresh the positions of the power rail connectors
   180     # Refresh the positions of the power rail connectors
   180     def RefreshConnectors(self):
   181     def RefreshConnectors(self):
   181         scaling = self.Parent.GetScaling()
   182         scaling = self.Parent.GetScaling()
   182         height = self.Size[1] - self.Extensions[0] - self.Extensions[1]
   183         height = self.Size[1] - self.Extensions[0] - self.Extensions[1]
   183         interval = float(height) / float(max(len(self.Connectors) - 1, 1))
   184         interval = float(height) / float(max(len(self.Connectors) - 1, 1))
   191             if self.Type == LEFTRAIL:
   192             if self.Type == LEFTRAIL:
   192                 connector.SetPosition(wx.Point(self.Size[0], position))
   193                 connector.SetPosition(wx.Point(self.Size[0], position))
   193             elif self.Type == RIGHTRAIL:
   194             elif self.Type == RIGHTRAIL:
   194                 connector.SetPosition(wx.Point(0, position))
   195                 connector.SetPosition(wx.Point(0, position))
   195         self.RefreshConnected()
   196         self.RefreshConnected()
   196     
   197 
   197     # Refresh the position of wires connected to power rail
   198     # Refresh the position of wires connected to power rail
   198     def RefreshConnected(self, exclude = []):
   199     def RefreshConnected(self, exclude=[]):
   199         for connector in self.Connectors:
   200         for connector in self.Connectors:
   200             connector.MoveConnected(exclude)
   201             connector.MoveConnected(exclude)
   201     
   202 
   202     # Returns the power rail connector that starts with the point given if it exists 
   203     # Returns the power rail connector that starts with the point given if it exists
   203     def GetConnector(self, position, name = None):
   204     def GetConnector(self, position, name=None):
   204         # if a name is given
   205         # if a name is given
   205         if name is not None:
   206         if name is not None:
   206             # Test each connector if it exists
   207             # Test each connector if it exists
   207             for connector in self.Connectors:
   208             for connector in self.Connectors:
   208                 if name == connector.GetName():
   209                 if name == connector.GetName():
   209                     return connector
   210                     return connector
   210         return self.FindNearestConnector(position, [connector for connector in self.Connectors if connector is not None])
   211         return self.FindNearestConnector(position, [connector for connector in self.Connectors if connector is not None])
   211     
   212 
   212     # Returns all the power rail connectors 
   213     # Returns all the power rail connectors
   213     def GetConnectors(self):
   214     def GetConnectors(self):
   214         connectors = [connector for connector in self.Connectors if connector]
   215         connectors = [connector for connector in self.Connectors if connector]
   215         if self.Type == LEFTRAIL:
   216         if self.Type == LEFTRAIL:
   216             return {"inputs": [], "outputs": connectors}
   217             return {"inputs": [], "outputs": connectors}
   217         else:
   218         else:
   218             return {"inputs": connectors, "outputs": []}
   219             return {"inputs": connectors, "outputs": []}
   219     
   220 
   220     # Test if point given is on one of the power rail connectors
   221     # Test if point given is on one of the power rail connectors
   221     def TestConnector(self, pt, direction = None, exclude = True):
   222     def TestConnector(self, pt, direction=None, exclude=True):
   222         for connector in self.Connectors:
   223         for connector in self.Connectors:
   223             if connector.TestPoint(pt, direction, exclude):
   224             if connector.TestPoint(pt, direction, exclude):
   224                 return connector
   225                 return connector
   225         return None
   226         return None
   226     
   227 
   227     # Returns the power rail type
   228     # Returns the power rail type
   228     def SetType(self, type, connectors):
   229     def SetType(self, type, connectors):
   229         if type != self.Type or len(self.Connectors) != connectors:
   230         if type != self.Type or len(self.Connectors) != connectors:
   230             # Create a connector or a blank according to 'connectors' and add it in
   231             # Create a connector or a blank according to 'connectors' and add it in
   231             # the connectors list
   232             # the connectors list
   233             self.Clean()
   234             self.Clean()
   234             self.Connectors = []
   235             self.Connectors = []
   235             for connector in xrange(connectors):
   236             for connector in xrange(connectors):
   236                 self.AddConnector()
   237                 self.AddConnector()
   237             self.RefreshSize()
   238             self.RefreshSize()
   238     
   239 
   239     # Returns the power rail type
   240     # Returns the power rail type
   240     def GetType(self):
   241     def GetType(self):
   241         return self.Type
   242         return self.Type
   242     
   243 
   243     # Method called when a LeftDown event have been generated
   244     # Method called when a LeftDown event have been generated
   244     def OnLeftDown(self, event, dc, scaling):
   245     def OnLeftDown(self, event, dc, scaling):
   245         self.RealConnectors = []
   246         self.RealConnectors = []
   246         height = self.Size[1] - self.Extensions[0] - self.Extensions[1]
   247         height = self.Size[1] - self.Extensions[0] - self.Extensions[1]
   247         if height > 0:
   248         if height > 0:
   248             for connector in self.Connectors:
   249             for connector in self.Connectors:
   249                 position = connector.GetRelPosition()
   250                 position = connector.GetRelPosition()
   250                 self.RealConnectors.append(max(0., min(float(position.y - self.Extensions[0]) / float(height), 1.)))
   251                 self.RealConnectors.append(max(0., min(float(position.y - self.Extensions[0]) / float(height), 1.)))
   251         elif len(self.Connectors) > 1:
   252         elif len(self.Connectors) > 1:
   252             self.RealConnectors = map(lambda x : x * 1 / (len(self.Connectors) - 1), xrange(len(self.Connectors)))
   253             self.RealConnectors = map(lambda x: x * 1 / (len(self.Connectors) - 1), xrange(len(self.Connectors)))
   253         else:
   254         else:
   254             self.RealConnectors = [0.5]
   255             self.RealConnectors = [0.5]
   255         Graphic_Element.OnLeftDown(self, event, dc, scaling)
   256         Graphic_Element.OnLeftDown(self, event, dc, scaling)
   256     
   257 
   257     # Method called when a LeftUp event have been generated
   258     # Method called when a LeftUp event have been generated
   258     def OnLeftUp(self, event, dc, scaling):
   259     def OnLeftUp(self, event, dc, scaling):
   259         Graphic_Element.OnLeftUp(self, event, dc, scaling)
   260         Graphic_Element.OnLeftUp(self, event, dc, scaling)
   260         self.RealConnectors = None
   261         self.RealConnectors = None
   261     
   262 
   262     # Method called when a LeftDown event have been generated
   263     # Method called when a LeftDown event have been generated
   263     def OnRightDown(self, event, dc, scaling):
   264     def OnRightDown(self, event, dc, scaling):
   264         pos = GetScaledEventPosition(event, dc, scaling)
   265         pos = GetScaledEventPosition(event, dc, scaling)
   265         # Test if a connector have been handled
   266         # Test if a connector have been handled
   266         connector = self.TestConnector(pos, exclude=False)
   267         connector = self.TestConnector(pos, exclude=False)
   270             self.Selected = False
   271             self.Selected = False
   271             # Initializes the last position
   272             # Initializes the last position
   272             self.oldPos = GetScaledEventPosition(event, dc, scaling)
   273             self.oldPos = GetScaledEventPosition(event, dc, scaling)
   273         else:
   274         else:
   274             Graphic_Element.OnRightDown(self, event, dc, scaling)
   275             Graphic_Element.OnRightDown(self, event, dc, scaling)
   275     
   276 
   276     # Method called when a LeftDClick event have been generated
   277     # Method called when a LeftDClick event have been generated
   277     def OnLeftDClick(self, event, dc, scaling):
   278     def OnLeftDClick(self, event, dc, scaling):
   278         # Edit the powerrail properties
   279         # Edit the powerrail properties
   279         self.Parent.EditPowerRailContent(self)
   280         self.Parent.EditPowerRailContent(self)
   280     
   281 
   281     # Method called when a RightUp event have been generated
   282     # Method called when a RightUp event have been generated
   282     def OnRightUp(self, event, dc, scaling):
   283     def OnRightUp(self, event, dc, scaling):
   283         handle_type, handle = self.Handle
   284         handle_type, handle = self.Handle
   284         if handle_type == HANDLE_CONNECTOR and self.Dragging and self.oldPos:
   285         if handle_type == HANDLE_CONNECTOR and self.Dragging and self.oldPos:
   285             wires = handle.GetWires()
   286             wires = handle.GetWires()
   290                     block = wires[0][0].StartConnected.GetParentBlock()
   291                     block = wires[0][0].StartConnected.GetParentBlock()
   291                 block.RefreshModel(False)
   292                 block.RefreshModel(False)
   292             Graphic_Element.OnRightUp(self, event, dc, scaling)
   293             Graphic_Element.OnRightUp(self, event, dc, scaling)
   293         else:
   294         else:
   294             self.Parent.PopupDefaultMenu()
   295             self.Parent.PopupDefaultMenu()
   295     
   296 
   296     def Resize(self, x, y, width, height):
   297     def Resize(self, x, y, width, height):
   297         self.Move(x, y)
   298         self.Move(x, y)
   298         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   299         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   299             self.SetSize(width, height)
   300             self.SetSize(width, height)
   300         else:
   301         else:
   312             self.MoveConnector(handle, movey)
   313             self.MoveConnector(handle, movey)
   313             return 0, movey
   314             return 0, movey
   314         elif self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   315         elif self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   315             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
   316             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
   316         return 0, 0
   317         return 0, 0
   317     
   318 
   318     # Refreshes the power rail model
   319     # Refreshes the power rail model
   319     def RefreshModel(self, move=True):
   320     def RefreshModel(self, move=True):
   320         self.Parent.RefreshPowerRailModel(self)
   321         self.Parent.RefreshPowerRailModel(self)
   321         # If power rail has moved and power rail is of type LEFT, refresh the model 
   322         # If power rail has moved and power rail is of type LEFT, refresh the model
   322         # of wires connected to connectors
   323         # of wires connected to connectors
   323         if move and self.Type == LEFTRAIL:
   324         if move and self.Type == LEFTRAIL:
   324             for connector in self.Connectors:
   325             for connector in self.Connectors:
   325                 connector.RefreshWires()
   326                 connector.RefreshWires()
   326     
   327 
   327     # Draws power rail
   328     # Draws power rail
   328     def Draw(self, dc):
   329     def Draw(self, dc):
   329         Graphic_Element.Draw(self, dc)
   330         Graphic_Element.Draw(self, dc)
   330         dc.SetPen(MiterPen(wx.BLACK))
   331         dc.SetPen(MiterPen(wx.BLACK))
   331         dc.SetBrush(wx.BLACK_BRUSH)
   332         dc.SetBrush(wx.BLACK_BRUSH)
   335         else:
   336         else:
   336             dc.DrawRectangle(self.Pos.x, self.Pos.y, LD_POWERRAIL_WIDTH + 1, self.Size[1] + 1)
   337             dc.DrawRectangle(self.Pos.x, self.Pos.y, LD_POWERRAIL_WIDTH + 1, self.Size[1] + 1)
   337         # Draw connectors
   338         # Draw connectors
   338         for connector in self.Connectors:
   339         for connector in self.Connectors:
   339             connector.Draw(dc)
   340             connector.Draw(dc)
   340         
   341 
   341 
   342 
   342 #-------------------------------------------------------------------------------
   343 # -------------------------------------------------------------------------------
   343 #                         Ladder Diagram Contact
   344 #                         Ladder Diagram Contact
   344 #-------------------------------------------------------------------------------
   345 # -------------------------------------------------------------------------------
   345 
   346 
   346 """
       
   347 Class that implements the graphic representation of a contact
       
   348 """
       
   349 
   347 
   350 class LD_Contact(Graphic_Element, DebugDataConsumer):
   348 class LD_Contact(Graphic_Element, DebugDataConsumer):
   351     
   349     """
       
   350     Class that implements the graphic representation of a contact
       
   351     """
       
   352 
   352     # Create a new contact
   353     # Create a new contact
   353     def __init__(self, parent, type, name, id = None):
   354     def __init__(self, parent, type, name, id=None):
   354         Graphic_Element.__init__(self, parent)
   355         Graphic_Element.__init__(self, parent)
   355         DebugDataConsumer.__init__(self)
   356         DebugDataConsumer.__init__(self)
   356         self.Type = type
   357         self.Type = type
   357         self.Name = name
   358         self.Name = name
   358         self.Id = id
   359         self.Id = id
   363         self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] / 2 + 1), EAST)
   364         self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] / 2 + 1), EAST)
   364         self.PreviousValue = False
   365         self.PreviousValue = False
   365         self.PreviousSpreading = False
   366         self.PreviousSpreading = False
   366         self.RefreshNameSize()
   367         self.RefreshNameSize()
   367         self.RefreshTypeSize()
   368         self.RefreshTypeSize()
   368     
   369 
   369     def Flush(self):
   370     def Flush(self):
   370         if self.Input is not None:
   371         if self.Input is not None:
   371             self.Input.Flush()
   372             self.Input.Flush()
   372             self.Input = None
   373             self.Input = None
   373         if self.Output is not None:
   374         if self.Output is not None:
   374             self.Output.Flush()
   375             self.Output.Flush()
   375             self.Output = None
   376             self.Output = None
   376     
   377 
   377     def SetForced(self, forced):
   378     def SetForced(self, forced):
   378         if self.Forced != forced:
   379         if self.Forced != forced:
   379             self.Forced = forced
   380             self.Forced = forced
   380             if self.Visible:
   381             if self.Visible:
   381                 self.Parent.ElementNeedRefresh(self)
   382                 self.Parent.ElementNeedRefresh(self)
   382     
   383 
   383     def SetValue(self, value):
   384     def SetValue(self, value):
   384         if self.Type == CONTACT_RISING:
   385         if self.Type == CONTACT_RISING:
   385             refresh = self.Value and not self.PreviousValue
   386             refresh = self.Value and not self.PreviousValue
   386         elif self.Type == CONTACT_FALLING:
   387         elif self.Type == CONTACT_FALLING:
   387             refresh = not self.Value and self.PreviousValue
   388             refresh = not self.Value and self.PreviousValue
   391         self.Value = value
   392         self.Value = value
   392         if self.Value != self.PreviousValue or refresh:
   393         if self.Value != self.PreviousValue or refresh:
   393             if self.Visible:
   394             if self.Visible:
   394                 self.Parent.ElementNeedRefresh(self)
   395                 self.Parent.ElementNeedRefresh(self)
   395             self.SpreadCurrent()
   396             self.SpreadCurrent()
   396     
   397 
   397     def SpreadCurrent(self):
   398     def SpreadCurrent(self):
   398         if self.Parent.Debug:
   399         if self.Parent.Debug:
   399             if self.Value is None:
   400             if self.Value is None:
   400                 self.Value = False
   401                 self.Value = False
   401             spreading = self.Input.ReceivingCurrent()
   402             spreading = self.Input.ReceivingCurrent()
   412             if spreading and not self.PreviousSpreading:
   413             if spreading and not self.PreviousSpreading:
   413                 self.Output.SpreadCurrent(True)
   414                 self.Output.SpreadCurrent(True)
   414             elif not spreading and self.PreviousSpreading:
   415             elif not spreading and self.PreviousSpreading:
   415                 self.Output.SpreadCurrent(False)
   416                 self.Output.SpreadCurrent(False)
   416             self.PreviousSpreading = spreading
   417             self.PreviousSpreading = spreading
   417     
   418 
   418     # Make a clone of this LD_Contact
   419     # Make a clone of this LD_Contact
   419     def Clone(self, parent, id = None, pos = None):
   420     def Clone(self, parent, id=None, pos=None):
   420         contact = LD_Contact(parent, self.Type, self.Name, id)
   421         contact = LD_Contact(parent, self.Type, self.Name, id)
   421         contact.SetSize(self.Size[0], self.Size[1])
   422         contact.SetSize(self.Size[0], self.Size[1])
   422         if pos is not None:
   423         if pos is not None:
   423             contact.SetPosition(pos.x, pos.y)
   424             contact.SetPosition(pos.x, pos.y)
   424         else:
   425         else:
   425             contact.SetPosition(self.Pos.x, self.Pos.y)
   426             contact.SetPosition(self.Pos.x, self.Pos.y)
   426         contact.Input = self.Input.Clone(contact)
   427         contact.Input = self.Input.Clone(contact)
   427         contact.Output = self.Output.Clone(contact)
   428         contact.Output = self.Output.Clone(contact)
   428         return contact
   429         return contact
   429     
   430 
   430     def GetConnectorTranslation(self, element):
   431     def GetConnectorTranslation(self, element):
   431         return {self.Input : element.Input, self.Output : element.Output}
   432         return {self.Input: element.Input, self.Output: element.Output}
   432     
   433 
   433     # Returns the RedrawRect
   434     # Returns the RedrawRect
   434     def GetRedrawRect(self, movex = 0, movey = 0):
   435     def GetRedrawRect(self, movex=0, movey=0):
   435         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
   436         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
   436         rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
   437         rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
   437         rect = rect.Union(self.Output.GetRedrawRect(movex, movey))
   438         rect = rect.Union(self.Output.GetRedrawRect(movex, movey))
   438         if movex != 0 or movey != 0:
   439         if movex != 0 or movey != 0:
   439             if self.Input.IsConnected():
   440             if self.Input.IsConnected():
   443         return rect
   444         return rect
   444 
   445 
   445     def ProcessDragging(self, movex, movey, event, scaling):
   446     def ProcessDragging(self, movex, movey, event, scaling):
   446         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   447         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   447             movex = movey = 0
   448             movex = movey = 0
   448         return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, height_fac = 2)
   449         return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, height_fac=2)
   449     
   450 
   450     # Forbids to change the contact size
   451     # Forbids to change the contact size
   451     def SetSize(self, width, height):
   452     def SetSize(self, width, height):
   452         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   453         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   453             Graphic_Element.SetSize(self, width, height)
   454             Graphic_Element.SetSize(self, width, height)
   454             self.RefreshConnectors()
   455             self.RefreshConnectors()
   455     
   456 
   456     # Delete this contact by calling the appropriate method
   457     # Delete this contact by calling the appropriate method
   457     def Delete(self):
   458     def Delete(self):
   458         self.Parent.DeleteContact(self)
   459         self.Parent.DeleteContact(self)
   459     
   460 
   460     # Unconnect input and output
   461     # Unconnect input and output
   461     def Clean(self):
   462     def Clean(self):
   462         self.Input.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   463         self.Input.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   463         self.Output.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   464         self.Output.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   464     
   465 
   465     # Refresh the size of text for name
   466     # Refresh the size of text for name
   466     def RefreshNameSize(self):
   467     def RefreshNameSize(self):
   467         if self.Name != "":
   468         if self.Name != "":
   468             self.NameSize = self.Parent.GetTextExtent(self.Name)
   469             self.NameSize = self.Parent.GetTextExtent(self.Name)
   469         else:
   470         else:
   470             self.NameSize = 0, 0
   471             self.NameSize = 0, 0
   471     
   472 
   472     # Refresh the size of text for type
   473     # Refresh the size of text for type
   473     def RefreshTypeSize(self):
   474     def RefreshTypeSize(self):
   474         typetext = ""
   475         typetext = ""
   475         if self.Type == CONTACT_REVERSE:
   476         if self.Type == CONTACT_REVERSE:
   476             typetext = "/"
   477             typetext = "/"
   480             typetext = "N"
   481             typetext = "N"
   481         if typetext != "":
   482         if typetext != "":
   482             self.TypeSize = self.Parent.GetTextExtent(typetext)
   483             self.TypeSize = self.Parent.GetTextExtent(typetext)
   483         else:
   484         else:
   484             self.TypeSize = 0, 0
   485             self.TypeSize = 0, 0
   485     
   486 
   486     # Refresh the contact bounding box
   487     # Refresh the contact bounding box
   487     def RefreshBoundingBox(self):
   488     def RefreshBoundingBox(self):
   488         # Calculate the size of the name outside the contact
   489         # Calculate the size of the name outside the contact
   489         text_width, text_height = self.Parent.GetTextExtent(self.Name)
   490         text_width, text_height = self.Parent.GetTextExtent(self.Name)
   490         # Calculate the bounding box size
   491         # Calculate the bounding box size
   497             bbx_x = self.Pos.x
   498             bbx_x = self.Pos.x
   498             bbx_width = self.Size[0]
   499             bbx_width = self.Size[0]
   499             bbx_y = self.Pos.y
   500             bbx_y = self.Pos.y
   500             bbx_height = self.Size[1]
   501             bbx_height = self.Size[1]
   501         self.BoundingBox = wx.Rect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1)
   502         self.BoundingBox = wx.Rect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1)
   502     
   503 
   503     # Returns the block minimum size
   504     # Returns the block minimum size
   504     def GetMinSize(self):
   505     def GetMinSize(self):
   505         return LD_ELEMENT_SIZE
   506         return LD_ELEMENT_SIZE
   506     
   507 
   507     # Refresh the position of wire connected to contact
   508     # Refresh the position of wire connected to contact
   508     def RefreshConnected(self, exclude = []):
   509     def RefreshConnected(self, exclude=[]):
   509         self.Input.MoveConnected(exclude)
   510         self.Input.MoveConnected(exclude)
   510         self.Output.MoveConnected(exclude)
   511         self.Output.MoveConnected(exclude)
   511     
   512 
   512     # Returns the contact connector that starts with the point given if it exists 
   513     # Returns the contact connector that starts with the point given if it exists
   513     def GetConnector(self, position, name = None):
   514     def GetConnector(self, position, name=None):
   514         # if a name is given
   515         # if a name is given
   515         if name is not None:
   516         if name is not None:
   516             # Test input and output connector
   517             # Test input and output connector
   517             #if name == self.Input.GetName():
   518             # if name == self.Input.GetName():
   518             #    return self.Input
   519             #    return self.Input
   519             if name == self.Output.GetName():
   520             if name == self.Output.GetName():
   520                 return self.Output
   521                 return self.Output
   521         return self.FindNearestConnector(position, [self.Input, self.Output])
   522         return self.FindNearestConnector(position, [self.Input, self.Output])
   522     
   523 
   523     # Returns input and output contact connectors 
   524     # Returns input and output contact connectors
   524     def GetConnectors(self):
   525     def GetConnectors(self):
   525         return {"inputs": [self.Input], "outputs": [self.Output]}
   526         return {"inputs": [self.Input], "outputs": [self.Output]}
   526     
   527 
   527     # Test if point given is on contact input or output connector
   528     # Test if point given is on contact input or output connector
   528     def TestConnector(self, pt, direction = None, exclude=True):
   529     def TestConnector(self, pt, direction=None, exclude=True):
   529         # Test input connector
   530         # Test input connector
   530         if self.Input.TestPoint(pt, direction, exclude):
   531         if self.Input.TestPoint(pt, direction, exclude):
   531             return self.Input
   532             return self.Input
   532         # Test output connector
   533         # Test output connector
   533         if self.Output.TestPoint(pt, direction, exclude):
   534         if self.Output.TestPoint(pt, direction, exclude):
   559         self.RefreshTypeSize()
   560         self.RefreshTypeSize()
   560 
   561 
   561     # Returns the contact type
   562     # Returns the contact type
   562     def GetType(self):
   563     def GetType(self):
   563         return self.Type
   564         return self.Type
   564     
   565 
   565     # Method called when a LeftDClick event have been generated
   566     # Method called when a LeftDClick event have been generated
   566     def OnLeftDClick(self, event, dc, scaling):
   567     def OnLeftDClick(self, event, dc, scaling):
   567         # Edit the contact properties
   568         # Edit the contact properties
   568         self.Parent.EditContactContent(self)
   569         self.Parent.EditContactContent(self)
   569     
   570 
   570     # Method called when a RightUp event have been generated
   571     # Method called when a RightUp event have been generated
   571     def OnRightUp(self, event, dc, scaling):
   572     def OnRightUp(self, event, dc, scaling):
   572         # Popup the default menu
   573         # Popup the default menu
   573         self.Parent.PopupDefaultMenu()
   574         self.Parent.PopupDefaultMenu()
   574     
   575 
   575     # Refreshes the contact model
   576     # Refreshes the contact model
   576     def RefreshModel(self, move=True):
   577     def RefreshModel(self, move=True):
   577         self.Parent.RefreshContactModel(self)
   578         self.Parent.RefreshContactModel(self)
   578         # If contact has moved, refresh the model of wires connected to output
   579         # If contact has moved, refresh the model of wires connected to output
   579         if move:
   580         if move:
   580             self.Output.RefreshWires()
   581             self.Output.RefreshWires()
   581     
   582 
   582     # Draws the highlightment of this element if it is highlighted
   583     # Draws the highlightment of this element if it is highlighted
   583     def DrawHighlightment(self, dc):
   584     def DrawHighlightment(self, dc):
   584         scalex, scaley = dc.GetUserScale()
   585         scalex, scaley = dc.GetUserScale()
   585         dc.SetUserScale(1, 1)
   586         dc.SetUserScale(1, 1)
   586         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
   587         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
   590         left_left = (self.Pos.x - 1) * scalex - 2
   591         left_left = (self.Pos.x - 1) * scalex - 2
   591         right_left = (self.Pos.x + self.Size[0] - 2) * scalex - 2
   592         right_left = (self.Pos.x + self.Size[0] - 2) * scalex - 2
   592         top = (self.Pos.y - 1) * scaley - 2
   593         top = (self.Pos.y - 1) * scaley - 2
   593         width = 4 * scalex + 5
   594         width = 4 * scalex + 5
   594         height = (self.Size[1] + 3) * scaley + 5
   595         height = (self.Size[1] + 3) * scaley + 5
   595         
   596 
   596         dc.DrawRectangle(left_left, top, width, height)
   597         dc.DrawRectangle(left_left, top, width, height)
   597         dc.DrawRectangle(right_left, top, width, height)
   598         dc.DrawRectangle(right_left, top, width, height)
   598         dc.SetLogicalFunction(wx.COPY)
   599         dc.SetLogicalFunction(wx.COPY)
   599         dc.SetUserScale(scalex, scaley)
   600         dc.SetUserScale(scalex, scaley)
   600     
   601 
   601     # Adds an highlight to the connection
   602     # Adds an highlight to the connection
   602     def AddHighlight(self, infos, start, end, highlight_type):
   603     def AddHighlight(self, infos, start, end, highlight_type):
   603         highlights = self.Highlights.setdefault(infos[0], [])
   604         highlights = self.Highlights.setdefault(infos[0], [])
   604         if infos[0] == "reference":
   605         if infos[0] == "reference":
   605             if start[0] == 0 and end[0] == 0:
   606             if start[0] == 0 and end[0] == 0:
   606                 AddHighlight(highlights, (start, end, highlight_type))
   607                 AddHighlight(highlights, (start, end, highlight_type))
   607         else:
   608         else:
   608             AddHighlight(highlights, ((0, 0), (0, 1), highlight_type))
   609             AddHighlight(highlights, ((0, 0), (0, 1), highlight_type))
   609     
   610 
   610     # Removes an highlight from the connection
   611     # Removes an highlight from the connection
   611     def RemoveHighlight(self, infos, start, end, highlight_type):
   612     def RemoveHighlight(self, infos, start, end, highlight_type):
   612         highlights = self.Highlights.get(infos[0], [])
   613         highlights = self.Highlights.get(infos[0], [])
   613         if RemoveHighlight(highlights, (start, end, highlight_type)) and len(highlights) == 0:
   614         if RemoveHighlight(highlights, (start, end, highlight_type)) and len(highlights) == 0:
   614             self.Highlights.pop(infos[0])
   615             self.Highlights.pop(infos[0])
   615     
   616 
   616     # Removes all the highlights of one particular type from the connection
   617     # Removes all the highlights of one particular type from the connection
   617     def ClearHighlight(self, highlight_type=None):
   618     def ClearHighlight(self, highlight_type=None):
   618         if highlight_type is None:
   619         if highlight_type is None:
   619             self.Highlights = {}
   620             self.Highlights = {}
   620         else:
   621         else:
   621             highlight_items = self.Highlights.items()
   622             highlight_items = self.Highlights.items()
   622             for name, highlights in highlight_items:
   623             for name, highlights in highlight_items:
   623                 highlights = ClearHighlights(highlight, highlight_type)
   624                 highlights = ClearHighlights(highlight, highlight_type)
   624                 if len(highlights) == 0:
   625                 if len(highlights) == 0:
   625                     self.Highlights.pop(name)
   626                     self.Highlights.pop(name)
   626     
   627 
   627     # Draws contact
   628     # Draws contact
   628     def Draw(self, dc):
   629     def Draw(self, dc):
   629         Graphic_Element.Draw(self, dc)
   630         Graphic_Element.Draw(self, dc)
   630         if self.Value is not None:            
   631         if self.Value is not None:
   631             if self.Type == CONTACT_NORMAL and self.Value or \
   632             if self.Type == CONTACT_NORMAL and self.Value or \
   632                self.Type == CONTACT_REVERSE and not self.Value or \
   633                self.Type == CONTACT_REVERSE and not self.Value or \
   633                self.Type == CONTACT_RISING and self.Value and not self.PreviousValue or \
   634                self.Type == CONTACT_RISING and self.Value and not self.PreviousValue or \
   634                self.Type == CONTACT_RISING and not self.Value and self.PreviousValue:
   635                self.Type == CONTACT_RISING and not self.Value and self.PreviousValue:
   635                 if self.Forced:
   636                 if self.Forced:
   641             else:
   642             else:
   642                 dc.SetPen(MiterPen(wx.BLACK))
   643                 dc.SetPen(MiterPen(wx.BLACK))
   643         else:
   644         else:
   644             dc.SetPen(MiterPen(wx.BLACK))
   645             dc.SetPen(MiterPen(wx.BLACK))
   645         dc.SetBrush(wx.BLACK_BRUSH)
   646         dc.SetBrush(wx.BLACK_BRUSH)
   646         
   647 
   647         # Compiling contact type modifier symbol
   648         # Compiling contact type modifier symbol
   648         typetext = ""
   649         typetext = ""
   649         if self.Type == CONTACT_REVERSE:
   650         if self.Type == CONTACT_REVERSE:
   650             typetext = "/"
   651             typetext = "/"
   651         elif self.Type == CONTACT_RISING:
   652         elif self.Type == CONTACT_RISING:
   652             typetext = "P"
   653             typetext = "P"
   653         elif self.Type == CONTACT_FALLING:
   654         elif self.Type == CONTACT_FALLING:
   654             typetext = "N"
   655             typetext = "N"
   655         
   656 
   656         if getattr(dc, "printing", False):
   657         if getattr(dc, "printing", False):
   657             name_size = dc.GetTextExtent(self.Name)
   658             name_size = dc.GetTextExtent(self.Name)
   658             if typetext != "":
   659             if typetext != "":
   659                 type_size = dc.GetTextExtent(typetext)
   660                 type_size = dc.GetTextExtent(typetext)
   660         else:
   661         else:
   661             name_size = self.NameSize
   662             name_size = self.NameSize
   662             if typetext != "":
   663             if typetext != "":
   663                 type_size = self.TypeSize
   664                 type_size = self.TypeSize
   664         
   665 
   665         # Draw two rectangles for representing the contact
   666         # Draw two rectangles for representing the contact
   666         dc.DrawRectangle(self.Pos.x, self.Pos.y, 2, self.Size[1] + 1)
   667         dc.DrawRectangle(self.Pos.x, self.Pos.y, 2, self.Size[1] + 1)
   667         dc.DrawRectangle(self.Pos.x + self.Size[0] - 1, self.Pos.y, 2, self.Size[1] + 1)
   668         dc.DrawRectangle(self.Pos.x + self.Size[0] - 1, self.Pos.y, 2, self.Size[1] + 1)
   668         # Draw contact name
   669         # Draw contact name
   669         name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
   670         name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
   675                         self.Pos.y + (self.Size[1] - type_size[1]) / 2)
   676                         self.Pos.y + (self.Size[1] - type_size[1]) / 2)
   676             dc.DrawText(typetext, type_pos[0], type_pos[1])
   677             dc.DrawText(typetext, type_pos[0], type_pos[1])
   677         # Draw input and output connectors
   678         # Draw input and output connectors
   678         self.Input.Draw(dc)
   679         self.Input.Draw(dc)
   679         self.Output.Draw(dc)
   680         self.Output.Draw(dc)
   680         
   681 
   681         if not getattr(dc, "printing", False):
   682         if not getattr(dc, "printing", False):
   682             for name, highlights in self.Highlights.iteritems():
   683             for name, highlights in self.Highlights.iteritems():
   683                 if name == "reference":
   684                 if name == "reference":
   684                     DrawHighlightedText(dc, self.Name, highlights, name_pos[0], name_pos[1])
   685                     DrawHighlightedText(dc, self.Name, highlights, name_pos[0], name_pos[1])
   685                 elif typetext != "":
   686                 elif typetext != "":
   686                     DrawHighlightedText(dc, typetext, highlights, type_pos[0], type_pos[1])
   687                     DrawHighlightedText(dc, typetext, highlights, type_pos[0], type_pos[1])
   687 
   688 
   688 #-------------------------------------------------------------------------------
   689 
       
   690 # -------------------------------------------------------------------------------
   689 #                         Ladder Diagram Coil
   691 #                         Ladder Diagram Coil
   690 #-------------------------------------------------------------------------------
   692 # -------------------------------------------------------------------------------
   691 
   693 
   692 """
       
   693 Class that implements the graphic representation of a coil
       
   694 """
       
   695 
   694 
   696 class LD_Coil(Graphic_Element):
   695 class LD_Coil(Graphic_Element):
   697     
   696     """
       
   697     Class that implements the graphic representation of a coil
       
   698     """
       
   699 
   698     # Create a new coil
   700     # Create a new coil
   699     def __init__(self, parent, type, name, id = None):
   701     def __init__(self, parent, type, name, id=None):
   700         Graphic_Element.__init__(self, parent)
   702         Graphic_Element.__init__(self, parent)
   701         self.Type = type
   703         self.Type = type
   702         self.Name = name
   704         self.Name = name
   703         self.Id = id
   705         self.Id = id
   704         self.Size = wx.Size(LD_ELEMENT_SIZE[0], LD_ELEMENT_SIZE[1])
   706         self.Size = wx.Size(LD_ELEMENT_SIZE[0], LD_ELEMENT_SIZE[1])
   708         self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] / 2 + 1), EAST)
   710         self.Output = Connector(self, "", "BOOL", wx.Point(self.Size[0], self.Size[1] / 2 + 1), EAST)
   709         self.Value = None
   711         self.Value = None
   710         self.PreviousValue = False
   712         self.PreviousValue = False
   711         self.RefreshNameSize()
   713         self.RefreshNameSize()
   712         self.RefreshTypeSize()
   714         self.RefreshTypeSize()
   713         
   715 
   714     def Flush(self):
   716     def Flush(self):
   715         if self.Input is not None:
   717         if self.Input is not None:
   716             self.Input.Flush()
   718             self.Input.Flush()
   717             self.Input = None
   719             self.Input = None
   718         if self.Output is not None:
   720         if self.Output is not None:
   719             self.Output.Flush()
   721             self.Output.Flush()
   720             self.Output = None
   722             self.Output = None
   721     
   723 
   722     def SpreadCurrent(self):
   724     def SpreadCurrent(self):
   723         if self.Parent.Debug:
   725         if self.Parent.Debug:
   724             self.PreviousValue = self.Value
   726             self.PreviousValue = self.Value
   725             self.Value = self.Input.ReceivingCurrent()
   727             self.Value = self.Input.ReceivingCurrent()
   726             if self.Value and not self.PreviousValue:
   728             if self.Value and not self.PreviousValue:
   727                 self.Output.SpreadCurrent(True)
   729                 self.Output.SpreadCurrent(True)
   728             elif not self.Value and self.PreviousValue:
   730             elif not self.Value and self.PreviousValue:
   729                 self.Output.SpreadCurrent(False)
   731                 self.Output.SpreadCurrent(False)
   730             if self.Value != self.PreviousValue and self.Visible:
   732             if self.Value != self.PreviousValue and self.Visible:
   731                 self.Parent.ElementNeedRefresh(self)
   733                 self.Parent.ElementNeedRefresh(self)
   732     
   734 
   733     # Make a clone of this LD_Coil
   735     # Make a clone of this LD_Coil
   734     def Clone(self, parent, id = None, pos = None):
   736     def Clone(self, parent, id=None, pos=None):
   735         coil = LD_Coil(parent, self.Type, self.Name, id)
   737         coil = LD_Coil(parent, self.Type, self.Name, id)
   736         coil.SetSize(self.Size[0], self.Size[1])
   738         coil.SetSize(self.Size[0], self.Size[1])
   737         if pos is not None:
   739         if pos is not None:
   738             coil.SetPosition(pos.x, pos.y)
   740             coil.SetPosition(pos.x, pos.y)
   739         else:
   741         else:
   740             coil.SetPosition(self.Pos.x, self.Pos.y)
   742             coil.SetPosition(self.Pos.x, self.Pos.y)
   741         coil.Input = self.Input.Clone(coil)
   743         coil.Input = self.Input.Clone(coil)
   742         coil.Output = self.Output.Clone(coil)
   744         coil.Output = self.Output.Clone(coil)
   743         return coil
   745         return coil
   744     
   746 
   745     def GetConnectorTranslation(self, element):
   747     def GetConnectorTranslation(self, element):
   746         return {self.Input : element.Input, self.Output : element.Output}
   748         return {self.Input: element.Input, self.Output: element.Output}
   747     
   749 
   748     # Returns the RedrawRect
   750     # Returns the RedrawRect
   749     def GetRedrawRect(self, movex = 0, movey = 0):
   751     def GetRedrawRect(self, movex=0, movey=0):
   750         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
   752         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
   751         rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
   753         rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
   752         rect = rect.Union(self.Output.GetRedrawRect(movex, movey))
   754         rect = rect.Union(self.Output.GetRedrawRect(movex, movey))
   753         if movex != 0 or movey != 0:
   755         if movex != 0 or movey != 0:
   754             if self.Input.IsConnected():
   756             if self.Input.IsConnected():
   755                 rect = rect.Union(self.Input.GetConnectedRedrawRect(movex, movey))
   757                 rect = rect.Union(self.Input.GetConnectedRedrawRect(movex, movey))
   756             if self.Output.IsConnected():
   758             if self.Output.IsConnected():
   757                 rect = rect.Union(self.Output.GetConnectedRedrawRect(movex, movey))
   759                 rect = rect.Union(self.Output.GetConnectedRedrawRect(movex, movey))
   758         return rect
   760         return rect
   759     
   761 
   760     def ProcessDragging(self, movex, movey, event, scaling):
   762     def ProcessDragging(self, movex, movey, event, scaling):
   761         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   763         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   762             movex = movey = 0
   764             movex = movey = 0
   763         return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, height_fac = 2)    
   765         return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, height_fac=2)
   764     
   766 
   765     # Forbids to change the Coil size
   767     # Forbids to change the Coil size
   766     def SetSize(self, width, height):
   768     def SetSize(self, width, height):
   767         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   769         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   768             Graphic_Element.SetSize(self, width, height)
   770             Graphic_Element.SetSize(self, width, height)
   769             self.RefreshConnectors()
   771             self.RefreshConnectors()
   770     
   772 
   771     # Delete this coil by calling the appropriate method
   773     # Delete this coil by calling the appropriate method
   772     def Delete(self):
   774     def Delete(self):
   773         self.Parent.DeleteCoil(self)
   775         self.Parent.DeleteCoil(self)
   774     
   776 
   775     # Unconnect input and output
   777     # Unconnect input and output
   776     def Clean(self):
   778     def Clean(self):
   777         self.Input.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   779         self.Input.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   778         self.Output.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   780         self.Output.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   779                 
   781 
   780     # Refresh the size of text for name
   782     # Refresh the size of text for name
   781     def RefreshNameSize(self):
   783     def RefreshNameSize(self):
   782         if self.Name != "":
   784         if self.Name != "":
   783             self.NameSize = self.Parent.GetTextExtent(self.Name)
   785             self.NameSize = self.Parent.GetTextExtent(self.Name)
   784         else:
   786         else:
   785             self.NameSize = 0, 0
   787             self.NameSize = 0, 0
   786     
   788 
   787     # Refresh the size of text for type
   789     # Refresh the size of text for type
   788     def RefreshTypeSize(self):
   790     def RefreshTypeSize(self):
   789         typetext = ""
   791         typetext = ""
   790         if self.Type == COIL_REVERSE:
   792         if self.Type == COIL_REVERSE:
   791             typetext = "/"
   793             typetext = "/"
   799             typetext = "N"
   801             typetext = "N"
   800         if typetext != "":
   802         if typetext != "":
   801             self.TypeSize = self.Parent.GetTextExtent(typetext)
   803             self.TypeSize = self.Parent.GetTextExtent(typetext)
   802         else:
   804         else:
   803             self.TypeSize = 0, 0
   805             self.TypeSize = 0, 0
   804     
   806 
   805     # Refresh the coil bounding box
   807     # Refresh the coil bounding box
   806     def RefreshBoundingBox(self):
   808     def RefreshBoundingBox(self):
   807         # Calculate the size of the name outside the coil
   809         # Calculate the size of the name outside the coil
   808         text_width, text_height = self.Parent.GetTextExtent(self.Name)
   810         text_width, text_height = self.Parent.GetTextExtent(self.Name)
   809         # Calculate the bounding box size
   811         # Calculate the bounding box size
   816             bbx_x = self.Pos.x
   818             bbx_x = self.Pos.x
   817             bbx_width = self.Size[0]
   819             bbx_width = self.Size[0]
   818             bbx_y = self.Pos.y
   820             bbx_y = self.Pos.y
   819             bbx_height = self.Size[1]
   821             bbx_height = self.Size[1]
   820         self.BoundingBox = wx.Rect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1)
   822         self.BoundingBox = wx.Rect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1)
   821         
   823 
   822     # Returns the block minimum size
   824     # Returns the block minimum size
   823     def GetMinSize(self):
   825     def GetMinSize(self):
   824         return LD_ELEMENT_SIZE
   826         return LD_ELEMENT_SIZE
   825     
   827 
   826     # Refresh the position of wire connected to coil
   828     # Refresh the position of wire connected to coil
   827     def RefreshConnected(self, exclude = []):
   829     def RefreshConnected(self, exclude=[]):
   828         self.Input.MoveConnected(exclude)
   830         self.Input.MoveConnected(exclude)
   829         self.Output.MoveConnected(exclude)
   831         self.Output.MoveConnected(exclude)
   830     
   832 
   831     # Returns the coil connector that starts with the point given if it exists 
   833     # Returns the coil connector that starts with the point given if it exists
   832     def GetConnector(self, position, name = None):
   834     def GetConnector(self, position, name=None):
   833         # if a name is given
   835         # if a name is given
   834         if name is not None:
   836         if name is not None:
   835             # Test input and output connector
   837             # Test input and output connector
   836             #if self.Input and name == self.Input.GetName():
   838             # if self.Input and name == self.Input.GetName():
   837             #    return self.Input
   839             #    return self.Input
   838             if self.Output and name == self.Output.GetName():
   840             if self.Output and name == self.Output.GetName():
   839                 return self.Output
   841                 return self.Output
   840         return self.FindNearestConnector(position, [self.Input, self.Output])
   842         return self.FindNearestConnector(position, [self.Input, self.Output])
   841     
   843 
   842     # Returns input and output coil connectors 
   844     # Returns input and output coil connectors
   843     def GetConnectors(self):
   845     def GetConnectors(self):
   844         return {"inputs": [self.Input], "outputs": [self.Output]}
   846         return {"inputs": [self.Input], "outputs": [self.Output]}
   845     
   847 
   846     # Test if point given is on coil input or output connector
   848     # Test if point given is on coil input or output connector
   847     def TestConnector(self, pt, direction = None, exclude=True):
   849     def TestConnector(self, pt, direction=None, exclude=True):
   848         # Test input connector
   850         # Test input connector
   849         if self.Input.TestPoint(pt, direction, exclude):
   851         if self.Input.TestPoint(pt, direction, exclude):
   850             return self.Input
   852             return self.Input
   851         # Test output connector
   853         # Test output connector
   852         if self.Output.TestPoint(pt, direction, exclude):
   854         if self.Output.TestPoint(pt, direction, exclude):
   853             return self.Output
   855             return self.Output
   854         return None
   856         return None
   855     
   857 
   856     # Refresh the positions of the block connectors
   858     # Refresh the positions of the block connectors
   857     def RefreshConnectors(self):
   859     def RefreshConnectors(self):
   858         scaling = self.Parent.GetScaling()
   860         scaling = self.Parent.GetScaling()
   859         position = self.Size[1] / 2 + 1
   861         position = self.Size[1] / 2 + 1
   860         if scaling is not None:
   862         if scaling is not None:
   861             position = round(float(self.Pos.y + position) / float(scaling[1])) * scaling[1] - self.Pos.y
   863             position = round(float(self.Pos.y + position) / float(scaling[1])) * scaling[1] - self.Pos.y
   862         self.Input.SetPosition(wx.Point(0, position))
   864         self.Input.SetPosition(wx.Point(0, position))
   863         self.Output.SetPosition(wx.Point(self.Size[0], position))
   865         self.Output.SetPosition(wx.Point(self.Size[0], position))
   864         self.RefreshConnected()
   866         self.RefreshConnected()
   865     
   867 
   866     # Changes the coil name
   868     # Changes the coil name
   867     def SetName(self, name):
   869     def SetName(self, name):
   868         self.Name = name
   870         self.Name = name
   869         self.RefreshNameSize()
   871         self.RefreshNameSize()
   870 
   872 
   871     # Returns the coil name
   873     # Returns the coil name
   872     def GetName(self):
   874     def GetName(self):
   873         return self.Name
   875         return self.Name
   874     
   876 
   875     # Changes the coil type
   877     # Changes the coil type
   876     def SetType(self, type):
   878     def SetType(self, type):
   877         self.Type = type
   879         self.Type = type
   878         self.RefreshTypeSize()
   880         self.RefreshTypeSize()
   879     
   881 
   880     # Returns the coil type
   882     # Returns the coil type
   881     def GetType(self):
   883     def GetType(self):
   882         return self.Type
   884         return self.Type
   883     
   885 
   884     # Method called when a LeftDClick event have been generated
   886     # Method called when a LeftDClick event have been generated
   885     def OnLeftDClick(self, event, dc, scaling):
   887     def OnLeftDClick(self, event, dc, scaling):
   886         # Edit the coil properties
   888         # Edit the coil properties
   887         self.Parent.EditCoilContent(self)
   889         self.Parent.EditCoilContent(self)
   888     
   890 
   889     # Method called when a RightUp event have been generated
   891     # Method called when a RightUp event have been generated
   890     def OnRightUp(self, event, dc, scaling):
   892     def OnRightUp(self, event, dc, scaling):
   891         # Popup the default menu
   893         # Popup the default menu
   892         self.Parent.PopupDefaultMenu()
   894         self.Parent.PopupDefaultMenu()
   893     
   895 
   894     # Refreshes the coil model
   896     # Refreshes the coil model
   895     def RefreshModel(self, move=True):
   897     def RefreshModel(self, move=True):
   896         self.Parent.RefreshCoilModel(self)
   898         self.Parent.RefreshCoilModel(self)
   897         # If coil has moved, refresh the model of wires connected to output
   899         # If coil has moved, refresh the model of wires connected to output
   898         if move:
   900         if move:
   899             self.Output.RefreshWires()
   901             self.Output.RefreshWires()
   900     
   902 
   901     # Draws the highlightment of this element if it is highlighted
   903     # Draws the highlightment of this element if it is highlighted
   902     def DrawHighlightment(self, dc):
   904     def DrawHighlightment(self, dc):
   903         scalex, scaley = dc.GetUserScale()
   905         scalex, scaley = dc.GetUserScale()
   904         dc.SetUserScale(1, 1)
   906         dc.SetUserScale(1, 1)
   905         dc.SetPen(MiterPen(HIGHLIGHTCOLOR, (3 * scalex + 5), wx.SOLID))
   907         dc.SetPen(MiterPen(HIGHLIGHTCOLOR, (3 * scalex + 5), wx.SOLID))
   906         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   908         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   907         dc.SetLogicalFunction(wx.AND)
   909         dc.SetLogicalFunction(wx.AND)
   908         # Draw a two circle arcs for representing the coil
   910         # Draw a two circle arcs for representing the coil
   909         dc.DrawEllipticArc(round(self.Pos.x * scalex), 
   911         dc.DrawEllipticArc(round(self.Pos.x * scalex),
   910                            round((self.Pos.y - int(self.Size[1] * (sqrt(2) - 1.) / 2.) + 1) * scaley), 
   912                            round((self.Pos.y - int(self.Size[1] * (sqrt(2) - 1.) / 2.) + 1) * scaley),
   911                            round(self.Size[0] * scalex), 
   913                            round(self.Size[0] * scalex),
   912                            round((int(self.Size[1] * sqrt(2)) - 1) * scaley),
   914                            round((int(self.Size[1] * sqrt(2)) - 1) * scaley),
   913                            135, 225)
   915                            135, 225)
   914         dc.DrawEllipticArc(round(self.Pos.x * scalex), 
   916         dc.DrawEllipticArc(round(self.Pos.x * scalex),
   915                            round((self.Pos.y - int(self.Size[1] * (sqrt(2) - 1.) / 2.) + 1) * scaley), 
   917                            round((self.Pos.y - int(self.Size[1] * (sqrt(2) - 1.) / 2.) + 1) * scaley),
   916                            round(self.Size[0] * scalex), 
   918                            round(self.Size[0] * scalex),
   917                            round((int(self.Size[1] * sqrt(2)) - 1) * scaley),
   919                            round((int(self.Size[1] * sqrt(2)) - 1) * scaley),
   918                            -45, 45)
   920                            -45, 45)
   919         dc.SetLogicalFunction(wx.COPY)
   921         dc.SetLogicalFunction(wx.COPY)
   920         dc.SetUserScale(scalex, scaley)
   922         dc.SetUserScale(scalex, scaley)
   921     
   923 
   922     # Adds an highlight to the connection
   924     # Adds an highlight to the connection
   923     def AddHighlight(self, infos, start, end, highlight_type):
   925     def AddHighlight(self, infos, start, end, highlight_type):
   924         highlights = self.Highlights.setdefault(infos[0], [])
   926         highlights = self.Highlights.setdefault(infos[0], [])
   925         if infos[0] == "reference":
   927         if infos[0] == "reference":
   926             if start[0] == 0 and end[0] == 0:
   928             if start[0] == 0 and end[0] == 0:
   927                 AddHighlight(highlights, (start, end, highlight_type))
   929                 AddHighlight(highlights, (start, end, highlight_type))
   928         else:
   930         else:
   929             AddHighlight(highlights, ((0, 0), (0, 1), highlight_type))
   931             AddHighlight(highlights, ((0, 0), (0, 1), highlight_type))
   930     
   932 
   931     # Removes an highlight from the connection
   933     # Removes an highlight from the connection
   932     def RemoveHighlight(self, infos, start, end, highlight_type):
   934     def RemoveHighlight(self, infos, start, end, highlight_type):
   933         highlights = self.Highlights.get(infos[0], [])
   935         highlights = self.Highlights.get(infos[0], [])
   934         if RemoveHighlight(highlights, (start, end, highlight_type)) and len(highlights) == 0:
   936         if RemoveHighlight(highlights, (start, end, highlight_type)) and len(highlights) == 0:
   935             self.Highlights.pop(infos[0])
   937             self.Highlights.pop(infos[0])
   936     
   938 
   937     # Removes all the highlights of one particular type from the connection
   939     # Removes all the highlights of one particular type from the connection
   938     def ClearHighlight(self, highlight_type=None):
   940     def ClearHighlight(self, highlight_type=None):
   939         if highlight_type is None:
   941         if highlight_type is None:
   940             self.Highlights = {}
   942             self.Highlights = {}
   941         else:
   943         else:
   942             highlight_items = self.Highlights.items()
   944             highlight_items = self.Highlights.items()
   943             for name, highlights in highlight_items:
   945             for name, highlights in highlight_items:
   944                 highlights = ClearHighlights(highlight, highlight_type)
   946                 highlights = ClearHighlights(highlight, highlight_type)
   945                 if len(highlights) == 0:
   947                 if len(highlights) == 0:
   946                     self.Highlights.pop(name)
   948                     self.Highlights.pop(name)
   947     
   949 
   948     # Draws coil
   950     # Draws coil
   949     def Draw(self, dc):
   951     def Draw(self, dc):
   950         Graphic_Element.Draw(self, dc)
   952         Graphic_Element.Draw(self, dc)
   951         if self.Value is not None and self.Value:
   953         if self.Value is not None and self.Value:
   952             dc.SetPen(MiterPen(wx.GREEN, 2, wx.SOLID))
   954             dc.SetPen(MiterPen(wx.GREEN, 2, wx.SOLID))
   953         else:
   955         else:
   954             dc.SetPen(MiterPen(wx.BLACK, 2, wx.SOLID))
   956             dc.SetPen(MiterPen(wx.BLACK, 2, wx.SOLID))
   955         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   957         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   956         
   958 
   957         # Compiling coil type modifier symbol 
   959         # Compiling coil type modifier symbol
   958         typetext = ""
   960         typetext = ""
   959         if self.Type == COIL_REVERSE:
   961         if self.Type == COIL_REVERSE:
   960             typetext = "/"
   962             typetext = "/"
   961         elif self.Type == COIL_SET:
   963         elif self.Type == COIL_SET:
   962             typetext = "S"
   964             typetext = "S"
   964             typetext = "R"
   966             typetext = "R"
   965         elif self.Type == COIL_RISING:
   967         elif self.Type == COIL_RISING:
   966             typetext = "P"
   968             typetext = "P"
   967         elif self.Type == COIL_FALLING:
   969         elif self.Type == COIL_FALLING:
   968             typetext = "N"
   970             typetext = "N"
   969         
   971 
   970         if getattr(dc, "printing", False) and not isinstance(dc, wx.PostScriptDC):
   972         if getattr(dc, "printing", False) and not isinstance(dc, wx.PostScriptDC):
   971             # Draw an clipped ellipse for representing the coil
   973             # Draw an clipped ellipse for representing the coil
   972             clipping_box = dc.GetClippingBox()
   974             clipping_box = dc.GetClippingBox()
   973             dc.SetClippingRegion(self.Pos.x - 1, self.Pos.y, self.Size[0] + 2, self.Size[1] + 1)
   975             dc.SetClippingRegion(self.Pos.x - 1, self.Pos.y, self.Size[0] + 2, self.Size[1] + 1)
   974             dc.DrawEllipse(self.Pos.x, self.Pos.y - int(self.Size[1] * (sqrt(2) - 1.) / 2.) + 1, self.Size[0], int(self.Size[1] * sqrt(2)) - 1)
   976             dc.DrawEllipse(self.Pos.x, self.Pos.y - int(self.Size[1] * (sqrt(2) - 1.) / 2.) + 1, self.Size[0], int(self.Size[1] * sqrt(2)) - 1)
   990                     dc.SetPen(MiterPen(wx.BLACK))
   992                     dc.SetPen(MiterPen(wx.BLACK))
   991                 dc.DrawPoint(self.Pos.x + 1, self.Pos.y + self.Size[1] / 2 + 1)
   993                 dc.DrawPoint(self.Pos.x + 1, self.Pos.y + self.Size[1] / 2 + 1)
   992             name_size = self.NameSize
   994             name_size = self.NameSize
   993             if typetext != "":
   995             if typetext != "":
   994                 type_size = self.TypeSize
   996                 type_size = self.TypeSize
   995             
   997 
   996         # Draw coil name
   998         # Draw coil name
   997         name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
   999         name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
   998                     self.Pos.y - (name_size[1] + 2))
  1000                     self.Pos.y - (name_size[1] + 2))
   999         dc.DrawText(self.Name, name_pos[0], name_pos[1])
  1001         dc.DrawText(self.Name, name_pos[0], name_pos[1])
  1000         # Draw the modifier symbol in the middle of coil
  1002         # Draw the modifier symbol in the middle of coil
  1010             for name, highlights in self.Highlights.iteritems():
  1012             for name, highlights in self.Highlights.iteritems():
  1011                 if name == "reference":
  1013                 if name == "reference":
  1012                     DrawHighlightedText(dc, self.Name, highlights, name_pos[0], name_pos[1])
  1014                     DrawHighlightedText(dc, self.Name, highlights, name_pos[0], name_pos[1])
  1013                 elif typetext != "":
  1015                 elif typetext != "":
  1014                     DrawHighlightedText(dc, typetext, highlights, type_pos[0], type_pos[1])
  1016                     DrawHighlightedText(dc, typetext, highlights, type_pos[0], type_pos[1])
  1015             
       
  1016