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