graphics/GraphicCommons.py
changeset 1730 64d8f52bc8c8
parent 1631 940e20a8865b
child 1736 7e61baa047f0
equal deleted inserted replaced
1726:d51af006fa6b 1730:64d8f52bc8c8
    81 VALID_HANDLES = [(1,1), (1,2), (1,3), (2,3), (3,3), (3,2), (3,1), (2,1)]
    81 VALID_HANDLES = [(1,1), (1,2), (1,3), (2,3), (3,3), (3,2), (3,1), (2,1)]
    82 
    82 
    83 # Contants for defining the direction of a connector
    83 # Contants for defining the direction of a connector
    84 [EAST, NORTH, WEST, SOUTH] = [(1,0), (0,-1), (-1,0), (0,1)]
    84 [EAST, NORTH, WEST, SOUTH] = [(1,0), (0,-1), (-1,0), (0,1)]
    85 
    85 
    86 # Contants for defining which mode is selected for each view 
    86 # Contants for defining which mode is selected for each view
    87 [MODE_SELECTION, MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT, 
    87 [MODE_SELECTION, MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT,
    88  MODE_COIL, MODE_CONTACT, MODE_POWERRAIL, MODE_INITIALSTEP, MODE_STEP, 
    88  MODE_COIL, MODE_CONTACT, MODE_POWERRAIL, MODE_INITIALSTEP, MODE_STEP,
    89  MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION, MODE_MOTION] = range(15)
    89  MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION, MODE_MOTION] = range(15)
    90 
    90 
    91 # Contants for defining alignment types for graphic group 
    91 # Contants for defining alignment types for graphic group
    92 [ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_TOP, ALIGN_MIDDLE, ALIGN_BOTTOM] = range(6)
    92 [ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_TOP, ALIGN_MIDDLE, ALIGN_BOTTOM] = range(6)
    93 
    93 
    94 # Contants for defining which drawing mode is selected for app
    94 # Contants for defining which drawing mode is selected for app
    95 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2]
    95 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2]
    96 
    96 
   120     if constraint == -1:
   120     if constraint == -1:
   121         xround = int(fraction)
   121         xround = int(fraction)
   122     else:
   122     else:
   123         xround = round(fraction)
   123         xround = round(fraction)
   124         if constraint == 1 and xround < fraction:
   124         if constraint == 1 and xround < fraction:
   125             xround += 1 
   125             xround += 1
   126     return int(xround * n)
   126     return int(xround * n)
   127 
   127 
   128 """
   128 """
   129 Basic vector operations for calculate wire points
   129 Basic vector operations for calculate wire points
   130 """
   130 """
   222         dc.DrawRectangle(x + offset_width, y, part_width, part_height)
   222         dc.DrawRectangle(x + offset_width, y, part_width, part_height)
   223         dc.SetTextForeground(highlight_type[1])
   223         dc.SetTextForeground(highlight_type[1])
   224         dc.DrawText(part, x + offset_width, y)
   224         dc.DrawText(part, x + offset_width, y)
   225     dc.SetPen(current_pen)
   225     dc.SetPen(current_pen)
   226     dc.SetTextForeground(wx.BLACK)
   226     dc.SetTextForeground(wx.BLACK)
   227     
   227 
   228 #-------------------------------------------------------------------------------
   228 #-------------------------------------------------------------------------------
   229 #                           Graphic element base class
   229 #                           Graphic element base class
   230 #-------------------------------------------------------------------------------
   230 #-------------------------------------------------------------------------------
   231 
   231 
   232 """
   232 """
   233 Class that implements a generic graphic element
   233 Class that implements a generic graphic element
   234 """
   234 """
   235 
   235 
   236 class Graphic_Element(ToolTipProducer):
   236 class Graphic_Element(ToolTipProducer):
   237     
   237 
   238     # Create a new graphic element
   238     # Create a new graphic element
   239     def __init__(self, parent, id = None):
   239     def __init__(self, parent, id = None):
   240         ToolTipProducer.__init__(self, parent)
   240         ToolTipProducer.__init__(self, parent)
   241         self.Parent = parent
   241         self.Parent = parent
   242         self.Id = id
   242         self.Id = id
   249         self.Highlighted = False
   249         self.Highlighted = False
   250         self.Pos = wx.Point(0, 0)
   250         self.Pos = wx.Point(0, 0)
   251         self.Size = wx.Size(0, 0)
   251         self.Size = wx.Size(0, 0)
   252         self.BoundingBox = wx.Rect(0, 0, 0, 0)
   252         self.BoundingBox = wx.Rect(0, 0, 0, 0)
   253         self.Visible = False
   253         self.Visible = False
   254     
   254 
   255     def GetDefinition(self):
   255     def GetDefinition(self):
   256         return [self.Id], []
   256         return [self.Id], []
   257     
   257 
   258     def TestVisible(self, screen):
   258     def TestVisible(self, screen):
   259         self.Visible = self.Selected or self.GetRedrawRect().Intersects(screen)
   259         self.Visible = self.Selected or self.GetRedrawRect().Intersects(screen)
   260     
   260 
   261     def IsVisible(self):
   261     def IsVisible(self):
   262         return self.Visible
   262         return self.Visible
   263     
   263 
   264     def SpreadCurrent(self):
   264     def SpreadCurrent(self):
   265         pass
   265         pass
   266     
   266 
   267     def GetConnectorTranslation(self, element):
   267     def GetConnectorTranslation(self, element):
   268         return {}
   268         return {}
   269     
   269 
   270     def FindNearestConnector(self, position, connectors):
   270     def FindNearestConnector(self, position, connectors):
   271         distances = []
   271         distances = []
   272         for connector in connectors:
   272         for connector in connectors:
   273             connector_pos = connector.GetRelPosition()
   273             connector_pos = connector.GetRelPosition()
   274             distances.append((sqrt((self.Pos.x + connector_pos.x - position.x) ** 2 +
   274             distances.append((sqrt((self.Pos.x + connector_pos.x - position.x) ** 2 +
   276                               connector))
   276                               connector))
   277         distances.sort()
   277         distances.sort()
   278         if len(distances) > 0:
   278         if len(distances) > 0:
   279             return distances[0][1]
   279             return distances[0][1]
   280         return None
   280         return None
   281         
   281 
   282     def IsOfType(self, type, reference):
   282     def IsOfType(self, type, reference):
   283         return self.Parent.IsOfType(type, reference)
   283         return self.Parent.IsOfType(type, reference)
   284     
   284 
   285     def IsEndType(self, type):
   285     def IsEndType(self, type):
   286         return self.Parent.IsEndType(type)
   286         return self.Parent.IsEndType(type)
   287         
   287 
   288     def GetDragging(self):
   288     def GetDragging(self):
   289         return self.Dragging
   289         return self.Dragging
   290     
   290 
   291     # Make a clone of this element
   291     # Make a clone of this element
   292     def Clone(self, parent):
   292     def Clone(self, parent):
   293         return Graphic_Element(parent, self.Id)
   293         return Graphic_Element(parent, self.Id)
   294     
   294 
   295     # Changes the block position
   295     # Changes the block position
   296     def SetPosition(self, x, y):
   296     def SetPosition(self, x, y):
   297         self.Pos.x = x
   297         self.Pos.x = x
   298         self.Pos.y = y
   298         self.Pos.y = y
   299         self.RefreshConnected()
   299         self.RefreshConnected()
   300         self.RefreshBoundingBox()
   300         self.RefreshBoundingBox()
   301 
   301 
   302     # Returns the block position
   302     # Returns the block position
   303     def GetPosition(self):
   303     def GetPosition(self):
   304         return self.Pos.x, self.Pos.y
   304         return self.Pos.x, self.Pos.y
   305     
   305 
   306     # Changes the element size
   306     # Changes the element size
   307     def SetSize(self, width, height):
   307     def SetSize(self, width, height):
   308         self.Size.SetWidth(width)
   308         self.Size.SetWidth(width)
   309         self.Size.SetHeight(height)
   309         self.Size.SetHeight(height)
   310         self.RefreshConnectors()
   310         self.RefreshConnectors()
   311         self.RefreshBoundingBox()
   311         self.RefreshBoundingBox()
   312 
   312 
   313     # Returns the element size
   313     # Returns the element size
   314     def GetSize(self):
   314     def GetSize(self):
   315         return self.Size.GetWidth(), self.Size.GetHeight()
   315         return self.Size.GetWidth(), self.Size.GetHeight()
   316     
   316 
   317     # Returns the minimum element size
   317     # Returns the minimum element size
   318     def GetMinSize(self):
   318     def GetMinSize(self):
   319         return 0, 0
   319         return 0, 0
   320     
   320 
   321     # Set size of the element to the minimum size
   321     # Set size of the element to the minimum size
   322     def SetBestSize(self, scaling, x_factor=0.5, y_factor=0.5):
   322     def SetBestSize(self, scaling, x_factor=0.5, y_factor=0.5):
   323         width, height = self.GetSize()
   323         width, height = self.GetSize()
   324         posx, posy = self.GetPosition()
   324         posx, posy = self.GetPosition()
   325         min_width, min_height = self.GetMinSize()
   325         min_width, min_height = self.GetMinSize()
   334             self.Pos.y = round_scaling(self.Pos.y, scaling[1])
   334             self.Pos.y = round_scaling(self.Pos.y, scaling[1])
   335             width = round_scaling(width, scaling[0], 1)
   335             width = round_scaling(width, scaling[0], 1)
   336             height = round_scaling(height, scaling[1], 1)
   336             height = round_scaling(height, scaling[1], 1)
   337         self.SetSize(width, height)
   337         self.SetSize(width, height)
   338         return self.Pos.x - posx, self.Pos.y - posy
   338         return self.Pos.x - posx, self.Pos.y - posy
   339     
   339 
   340     # Refresh the element Bounding Box
   340     # Refresh the element Bounding Box
   341     def RefreshBoundingBox(self):
   341     def RefreshBoundingBox(self):
   342         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   342         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   343     
   343 
   344     # Refresh the element connectors position
   344     # Refresh the element connectors position
   345     def RefreshConnectors(self):
   345     def RefreshConnectors(self):
   346         pass
   346         pass
   347     
   347 
   348     # Refresh the position of wires connected to element inputs and outputs
   348     # Refresh the position of wires connected to element inputs and outputs
   349     def RefreshConnected(self):
   349     def RefreshConnected(self):
   350         pass
   350         pass
   351     
   351 
   352     # Change the parent
   352     # Change the parent
   353     def SetParent(self, parent):
   353     def SetParent(self, parent):
   354         self.Parent = parent
   354         self.Parent = parent
   355     
   355 
   356     # Override this method for defining the method to call for deleting this element
   356     # Override this method for defining the method to call for deleting this element
   357     def Delete(self):
   357     def Delete(self):
   358         pass
   358         pass
   359     
   359 
   360     # Returns the Id
   360     # Returns the Id
   361     def GetId(self):
   361     def GetId(self):
   362         return self.Id
   362         return self.Id
   363     
   363 
   364     # Returns if the point given is in the bounding box
   364     # Returns if the point given is in the bounding box
   365     def HitTest(self, pt, connectors=True):
   365     def HitTest(self, pt, connectors=True):
   366         if connectors:
   366         if connectors:
   367             rect = self.BoundingBox
   367             rect = self.BoundingBox
   368         else:
   368         else:
   369             rect = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   369             rect = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   370         return rect.InsideXY(pt.x, pt.y)
   370         return rect.InsideXY(pt.x, pt.y)
   371     
   371 
   372     # Returns if the point given is in the bounding box
   372     # Returns if the point given is in the bounding box
   373     def IsInSelection(self, rect):
   373     def IsInSelection(self, rect):
   374         return rect.InsideXY(self.BoundingBox.x, self.BoundingBox.y) and rect.InsideXY(self.BoundingBox.x + self.BoundingBox.width, self.BoundingBox.y + self.BoundingBox.height)
   374         return rect.InsideXY(self.BoundingBox.x, self.BoundingBox.y) and rect.InsideXY(self.BoundingBox.x + self.BoundingBox.width, self.BoundingBox.y + self.BoundingBox.height)
   375     
   375 
   376     # Override this method for refreshing the bounding box
   376     # Override this method for refreshing the bounding box
   377     def RefreshBoundingBox(self):
   377     def RefreshBoundingBox(self):
   378         pass
   378         pass
   379     
   379 
   380     # Returns the bounding box
   380     # Returns the bounding box
   381     def GetBoundingBox(self):
   381     def GetBoundingBox(self):
   382         return self.BoundingBox
   382         return self.BoundingBox
   383     
   383 
   384     # Returns the RedrawRect
   384     # Returns the RedrawRect
   385     def GetRedrawRect(self, movex = 0, movey = 0):
   385     def GetRedrawRect(self, movex = 0, movey = 0):
   386         scalex, scaley = self.Parent.GetViewScale()
   386         scalex, scaley = self.Parent.GetViewScale()
   387         rect = wx.Rect()
   387         rect = wx.Rect()
   388         rect.x = self.BoundingBox.x - int(HANDLE_SIZE / scalex) - 3 - abs(movex)
   388         rect.x = self.BoundingBox.x - int(HANDLE_SIZE / scalex) - 3 - abs(movex)
   389         rect.y = self.BoundingBox.y - int(HANDLE_SIZE / scaley) - 3 - abs(movey)
   389         rect.y = self.BoundingBox.y - int(HANDLE_SIZE / scaley) - 3 - abs(movey)
   390         rect.width = self.BoundingBox.width + 2 * (int(HANDLE_SIZE / scalex) + abs(movex) + 1) + 4
   390         rect.width = self.BoundingBox.width + 2 * (int(HANDLE_SIZE / scalex) + abs(movex) + 1) + 4
   391         rect.height = self.BoundingBox.height + 2 * (int(HANDLE_SIZE / scaley) + abs(movey) + 1) + 4
   391         rect.height = self.BoundingBox.height + 2 * (int(HANDLE_SIZE / scaley) + abs(movey) + 1) + 4
   392         return rect
   392         return rect
   393     
   393 
   394     def Refresh(self, rect = None):
   394     def Refresh(self, rect = None):
   395         if self.Visible:
   395         if self.Visible:
   396             if rect is not None:
   396             if rect is not None:
   397                 self.Parent.RefreshRect(self.Parent.GetScrolledRect(rect), False)
   397                 self.Parent.RefreshRect(self.Parent.GetScrolledRect(rect), False)
   398             else:
   398             else:
   399                 self.Parent.RefreshRect(self.Parent.GetScrolledRect(self.GetRedrawRect()), False)
   399                 self.Parent.RefreshRect(self.Parent.GetScrolledRect(self.GetRedrawRect()), False)
   400     
   400 
   401     # Change the variable that indicates if this element is selected
   401     # Change the variable that indicates if this element is selected
   402     def SetSelected(self, selected):
   402     def SetSelected(self, selected):
   403         self.Selected = selected
   403         self.Selected = selected
   404         self.Refresh()
   404         self.Refresh()
   405     
   405 
   406     # Change the variable that indicates if this element is highlighted
   406     # Change the variable that indicates if this element is highlighted
   407     def SetHighlighted(self, highlighted):
   407     def SetHighlighted(self, highlighted):
   408         self.Highlighted = highlighted
   408         self.Highlighted = highlighted
   409         self.Refresh()
   409         self.Refresh()
   410     
   410 
   411     # Test if the point is on a handle of this element
   411     # Test if the point is on a handle of this element
   412     def TestHandle(self, event):
   412     def TestHandle(self, event):
   413         dc = self.Parent.GetLogicalDC()
   413         dc = self.Parent.GetLogicalDC()
   414         scalex, scaley = dc.GetUserScale()
   414         scalex, scaley = dc.GetUserScale()
   415         pos = event.GetPosition()
   415         pos = event.GetPosition()
   416         pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y))
   416         pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y))
   417         
   417 
   418         left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   418         left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   419         center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
   419         center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
   420         right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   420         right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   421         
   421 
   422         top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   422         top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   423         middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
   423         middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
   424         bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   424         bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   425         
   425 
   426         extern_rect = wx.Rect(left, top, right + HANDLE_SIZE - left, bottom + HANDLE_SIZE - top)
   426         extern_rect = wx.Rect(left, top, right + HANDLE_SIZE - left, bottom + HANDLE_SIZE - top)
   427         intern_rect = wx.Rect(left + HANDLE_SIZE, top + HANDLE_SIZE, right - left - HANDLE_SIZE, bottom - top - HANDLE_SIZE)
   427         intern_rect = wx.Rect(left + HANDLE_SIZE, top + HANDLE_SIZE, right - left - HANDLE_SIZE, bottom - top - HANDLE_SIZE)
   428         
   428 
   429         # Verify that this element is selected
   429         # Verify that this element is selected
   430         if self.Selected and extern_rect.InsideXY(pt.x, pt.y) and not intern_rect.InsideXY(pt.x, pt.y):
   430         if self.Selected and extern_rect.InsideXY(pt.x, pt.y) and not intern_rect.InsideXY(pt.x, pt.y):
   431             # Find if point is on a handle horizontally
   431             # Find if point is on a handle horizontally
   432             if left <= pt.x < left + HANDLE_SIZE:
   432             if left <= pt.x < left + HANDLE_SIZE:
   433                 handle_x = 1
   433                 handle_x = 1
   448                 handle_y = 0
   448                 handle_y = 0
   449             # Verify that the result is valid
   449             # Verify that the result is valid
   450             if (handle_x, handle_y) in VALID_HANDLES:
   450             if (handle_x, handle_y) in VALID_HANDLES:
   451                 return handle_x, handle_y
   451                 return handle_x, handle_y
   452         return 0, 0
   452         return 0, 0
   453     
   453 
   454     # Method called when a LeftDown event have been generated
   454     # Method called when a LeftDown event have been generated
   455     def OnLeftDown(self, event, dc, scaling):
   455     def OnLeftDown(self, event, dc, scaling):
   456         pos = event.GetLogicalPosition(dc)
   456         pos = event.GetLogicalPosition(dc)
   457         # Test if an handle have been clicked
   457         # Test if an handle have been clicked
   458         handle = self.TestHandle(event)
   458         handle = self.TestHandle(event)
   467             self.SetSelected(False)
   467             self.SetSelected(False)
   468         # Initializes the last position
   468         # Initializes the last position
   469         self.oldPos = GetScaledEventPosition(event, dc, scaling)
   469         self.oldPos = GetScaledEventPosition(event, dc, scaling)
   470         self.StartPos = wx.Point(self.Pos.x, self.Pos.y)
   470         self.StartPos = wx.Point(self.Pos.x, self.Pos.y)
   471         self.CurrentDrag = wx.Point(0, 0)
   471         self.CurrentDrag = wx.Point(0, 0)
   472     
   472 
   473     # Method called when a LeftUp event have been generated
   473     # Method called when a LeftUp event have been generated
   474     def OnLeftUp(self, event, dc, scaling):
   474     def OnLeftUp(self, event, dc, scaling):
   475         # If a dragging have been initiated
   475         # If a dragging have been initiated
   476         if self.Dragging and self.oldPos:
   476         if self.Dragging and self.oldPos:
   477             self.RefreshModel()
   477             self.RefreshModel()
   496             self.Parent.PopupForceMenu()
   496             self.Parent.PopupForceMenu()
   497 
   497 
   498     # Method called when a LeftDClick event have been generated
   498     # Method called when a LeftDClick event have been generated
   499     def OnLeftDClick(self, event, dc, scaling):
   499     def OnLeftDClick(self, event, dc, scaling):
   500         pass
   500         pass
   501     
   501 
   502     # Method called when a Motion event have been generated
   502     # Method called when a Motion event have been generated
   503     def OnMotion(self, event, dc, scaling):
   503     def OnMotion(self, event, dc, scaling):
   504         # If the cursor is dragging and the element have been clicked
   504         # If the cursor is dragging and the element have been clicked
   505         if event.Dragging() and self.oldPos:
   505         if event.Dragging() and self.oldPos:
   506             # Calculate the movement of cursor
   506             # Calculate the movement of cursor
   535     def Move(self, dx, dy, exclude = []):
   535     def Move(self, dx, dy, exclude = []):
   536         self.Pos.x += max(-self.BoundingBox.x, dx)
   536         self.Pos.x += max(-self.BoundingBox.x, dx)
   537         self.Pos.y += max(-self.BoundingBox.y, dy)
   537         self.Pos.y += max(-self.BoundingBox.y, dy)
   538         self.RefreshConnected(exclude)
   538         self.RefreshConnected(exclude)
   539         self.RefreshBoundingBox()
   539         self.RefreshBoundingBox()
   540     
   540 
   541     # Resizes the element from position and size given
   541     # Resizes the element from position and size given
   542     def Resize(self, x, y, width, height):
   542     def Resize(self, x, y, width, height):
   543         self.Move(x, y)
   543         self.Move(x, y)
   544         self.SetSize(width, height)
   544         self.SetSize(width, height)
   545     
   545 
   546     # Refreshes the element state according to move defined and handle selected
   546     # Refreshes the element state according to move defined and handle selected
   547     def ProcessDragging(self, movex, movey, event, scaling, width_fac = 1, height_fac = 1):
   547     def ProcessDragging(self, movex, movey, event, scaling, width_fac = 1, height_fac = 1):
   548         handle_type, handle = self.Handle
   548         handle_type, handle = self.Handle
   549         # If it is a resize handle, calculate the values from resizing
   549         # If it is a resize handle, calculate the values from resizing
   550         if handle_type == HANDLE_RESIZE:
   550         if handle_type == HANDLE_RESIZE:
   616                 if abs(self.CurrentDrag.x) > abs(self.CurrentDrag.y):
   616                 if abs(self.CurrentDrag.x) > abs(self.CurrentDrag.y):
   617                     movex = self.StartPos.x + self.CurrentDrag.x - self.Pos.x
   617                     movex = self.StartPos.x + self.CurrentDrag.x - self.Pos.x
   618                     movey = self.StartPos.y - self.Pos.y
   618                     movey = self.StartPos.y - self.Pos.y
   619                 else:
   619                 else:
   620                     movex = self.StartPos.x - self.Pos.x
   620                     movex = self.StartPos.x - self.Pos.x
   621                     movey = self.StartPos.y + self.CurrentDrag.y - self.Pos.y   
   621                     movey = self.StartPos.y + self.CurrentDrag.y - self.Pos.y
   622             self.Move(movex, movey)
   622             self.Move(movex, movey)
   623             return movex, movey
   623             return movex, movey
   624         return 0, 0
   624         return 0, 0
   625     
   625 
   626     # Override this method for defining the method to call for adding an highlight to this element
   626     # Override this method for defining the method to call for adding an highlight to this element
   627     def AddHighlight(self, infos, start, end, highlight_type):
   627     def AddHighlight(self, infos, start, end, highlight_type):
   628         pass
   628         pass
   629     
   629 
   630     # Override this method for defining the method to call for removing an highlight from this element
   630     # Override this method for defining the method to call for removing an highlight from this element
   631     def RemoveHighlight(self, infos, start, end, highlight_type):
   631     def RemoveHighlight(self, infos, start, end, highlight_type):
   632         pass
   632         pass
   633     
   633 
   634     # Override this method for defining the method to call for removing all the highlights of one particular type from this element
   634     # Override this method for defining the method to call for removing all the highlights of one particular type from this element
   635     def ClearHighlight(self, highlight_type=None):
   635     def ClearHighlight(self, highlight_type=None):
   636         pass
   636         pass
   637     
   637 
   638     # Override this method for defining the method to call for refreshing the model of this element
   638     # Override this method for defining the method to call for refreshing the model of this element
   639     def RefreshModel(self, move=True):
   639     def RefreshModel(self, move=True):
   640         pass
   640         pass
   641     
   641 
   642     # Draws the highlightment of this element if it is highlighted (can be overwritten)
   642     # Draws the highlightment of this element if it is highlighted (can be overwritten)
   643     def DrawHighlightment(self, dc):
   643     def DrawHighlightment(self, dc):
   644         scalex, scaley = dc.GetUserScale()
   644         scalex, scaley = dc.GetUserScale()
   645         dc.SetUserScale(1, 1)
   645         dc.SetUserScale(1, 1)
   646         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
   646         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
   647         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
   647         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
   648         dc.SetLogicalFunction(wx.AND)
   648         dc.SetLogicalFunction(wx.AND)
   649         dc.DrawRectangle(int(round((self.Pos.x - 1) * scalex)) - 2, 
   649         dc.DrawRectangle(int(round((self.Pos.x - 1) * scalex)) - 2,
   650                          int(round((self.Pos.y - 1) * scaley)) - 2, 
   650                          int(round((self.Pos.y - 1) * scaley)) - 2,
   651                          int(round((self.Size.width + 3) * scalex)) + 5, 
   651                          int(round((self.Size.width + 3) * scalex)) + 5,
   652                          int(round((self.Size.height + 3) * scaley)) + 5)
   652                          int(round((self.Size.height + 3) * scaley)) + 5)
   653         dc.SetLogicalFunction(wx.COPY)
   653         dc.SetLogicalFunction(wx.COPY)
   654         dc.SetUserScale(scalex, scaley)
   654         dc.SetUserScale(scalex, scaley)
   655     
   655 
   656     # Draws the handles of this element if it is selected
   656     # Draws the handles of this element if it is selected
   657     def Draw(self, dc):
   657     def Draw(self, dc):
   658         if not getattr(dc, "printing", False):
   658         if not getattr(dc, "printing", False):
   659             if self.Highlighted:
   659             if self.Highlighted:
   660                 self.DrawHighlightment(dc)
   660                 self.DrawHighlightment(dc)
   661             if self.Selected:
   661             if self.Selected:
   662                 scalex, scaley = dc.GetUserScale()
   662                 scalex, scaley = dc.GetUserScale()
   663                 dc.SetUserScale(1, 1)
   663                 dc.SetUserScale(1, 1)
   664                 dc.SetPen(MiterPen(wx.BLACK))
   664                 dc.SetPen(MiterPen(wx.BLACK))
   665                 dc.SetBrush(wx.BLACK_BRUSH)
   665                 dc.SetBrush(wx.BLACK_BRUSH)
   666                 
   666 
   667                 left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   667                 left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   668                 center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
   668                 center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
   669                 right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   669                 right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   670                 
   670 
   671                 top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   671                 top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   672                 middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
   672                 middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
   673                 bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   673                 bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   674                 
   674 
   675                 for x, y in [(left, top), (center, top), (right, top),
   675                 for x, y in [(left, top), (center, top), (right, top),
   676                              (left, middle), (right, middle),
   676                              (left, middle), (right, middle),
   677                              (left, bottom), (center, bottom), (right, bottom)]:
   677                              (left, bottom), (center, bottom), (right, bottom)]:
   678                     dc.DrawRectangle(x, y, HANDLE_SIZE, HANDLE_SIZE)
   678                     dc.DrawRectangle(x, y, HANDLE_SIZE, HANDLE_SIZE)
   679                 
   679 
   680                 dc.SetUserScale(scalex, scaley)
   680                 dc.SetUserScale(scalex, scaley)
   681 
   681 
   682 
   682 
   683 #-------------------------------------------------------------------------------
   683 #-------------------------------------------------------------------------------
   684 #                           Group of graphic elements
   684 #                           Group of graphic elements
   687 """
   687 """
   688 Class that implements a group of graphic elements
   688 Class that implements a group of graphic elements
   689 """
   689 """
   690 
   690 
   691 class Graphic_Group(Graphic_Element):
   691 class Graphic_Group(Graphic_Element):
   692     
   692 
   693     # Create a new group of graphic elements
   693     # Create a new group of graphic elements
   694     def __init__(self, parent):
   694     def __init__(self, parent):
   695         Graphic_Element.__init__(self, parent)
   695         Graphic_Element.__init__(self, parent)
   696         self.Elements = []
   696         self.Elements = []
   697         self.RefreshWireExclusion()
   697         self.RefreshWireExclusion()
   698         self.RefreshBoundingBox()
   698         self.RefreshBoundingBox()
   699     
   699 
   700     # Destructor
   700     # Destructor
   701     def __del__(self):
   701     def __del__(self):
   702         self.Elements = []
   702         self.Elements = []
   703     
   703 
   704     def GetDefinition(self):
   704     def GetDefinition(self):
   705         blocks = [] 
   705         blocks = []
   706         wires = []
   706         wires = []
   707         for element in self.Elements:
   707         for element in self.Elements:
   708             block, wire = element.GetDefinition()
   708             block, wire = element.GetDefinition()
   709             blocks.extend(block)
   709             blocks.extend(block)
   710             wires.extend(wire)
   710             wires.extend(wire)
   711         return blocks, wires
   711         return blocks, wires
   712     
   712 
   713     # Make a clone of this element
   713     # Make a clone of this element
   714     def Clone(self, parent, pos = None):
   714     def Clone(self, parent, pos = None):
   715         group = Graphic_Group(parent)
   715         group = Graphic_Group(parent)
   716         connectors = {}
   716         connectors = {}
   717         exclude_names = {}
   717         exclude_names = {}
   749         if pos is not None:
   749         if pos is not None:
   750             for element in group.Elements:
   750             for element in group.Elements:
   751                 if not isinstance(element, Wire):
   751                 if not isinstance(element, Wire):
   752                     parent.AddBlockInModel(element)
   752                     parent.AddBlockInModel(element)
   753         return group
   753         return group
   754     
   754 
   755     def CanAddBlocks(self, parent):
   755     def CanAddBlocks(self, parent):
   756         valid = True
   756         valid = True
   757         for element in self.Elements:
   757         for element in self.Elements:
   758             if not isinstance(element, Wire):
   758             if not isinstance(element, Wire):
   759                 valid &= parent.CanAddElement(element)
   759                 valid &= parent.CanAddElement(element)
   760         return valid
   760         return valid
   761     
   761 
   762     def IsVisible(self):
   762     def IsVisible(self):
   763         for element in self.Elements:
   763         for element in self.Elements:
   764             if element.IsVisible():
   764             if element.IsVisible():
   765                 return True
   765                 return True
   766         return False
   766         return False
   767     
   767 
   768     # Refresh the list of wire excluded
   768     # Refresh the list of wire excluded
   769     def RefreshWireExclusion(self):
   769     def RefreshWireExclusion(self):
   770         self.WireExcluded = []
   770         self.WireExcluded = []
   771         for element in self.Elements:
   771         for element in self.Elements:
   772             if isinstance(element, Wire):
   772             if isinstance(element, Wire):
   773                 startblock = element.StartConnected.GetParentBlock()
   773                 startblock = element.StartConnected.GetParentBlock()
   774                 endblock = element.EndConnected.GetParentBlock()
   774                 endblock = element.EndConnected.GetParentBlock()
   775                 if startblock in self.Elements and endblock in self.Elements:
   775                 if startblock in self.Elements and endblock in self.Elements:
   776                     self.WireExcluded.append(element)
   776                     self.WireExcluded.append(element)
   777     
   777 
   778     # Returns the RedrawRect
   778     # Returns the RedrawRect
   779     def GetRedrawRect(self, movex = 0, movey = 0):
   779     def GetRedrawRect(self, movex = 0, movey = 0):
   780         rect = None
   780         rect = None
   781         for element in self.Elements:
   781         for element in self.Elements:
   782             if rect is None:
   782             if rect is None:
   783                 rect = element.GetRedrawRect(movex, movey)
   783                 rect = element.GetRedrawRect(movex, movey)
   784             else:
   784             else:
   785                 rect = rect.Union(element.GetRedrawRect(movex, movey))
   785                 rect = rect.Union(element.GetRedrawRect(movex, movey))
   786         return rect
   786         return rect
   787     
   787 
   788     # Clean this group of elements
   788     # Clean this group of elements
   789     def Clean(self):
   789     def Clean(self):
   790         # Clean all the elements of the group
   790         # Clean all the elements of the group
   791         for element in self.Elements:
   791         for element in self.Elements:
   792             element.Clean()
   792             element.Clean()
   793     
   793 
   794     # Delete this group of elements
   794     # Delete this group of elements
   795     def Delete(self):
   795     def Delete(self):
   796         # Delete all the elements of the group
   796         # Delete all the elements of the group
   797         for element in self.Elements:
   797         for element in self.Elements:
   798             element.Delete()
   798             element.Delete()
   799         self.WireExcluded = []
   799         self.WireExcluded = []
   800     
   800 
   801     # Returns if the point given is in the bounding box of one of the elements of this group
   801     # Returns if the point given is in the bounding box of one of the elements of this group
   802     def HitTest(self, pt, connectors=True):
   802     def HitTest(self, pt, connectors=True):
   803         result = False
   803         result = False
   804         for element in self.Elements:
   804         for element in self.Elements:
   805             result |= element.HitTest(pt, connectors)
   805             result |= element.HitTest(pt, connectors)
   806         return result
   806         return result
   807     
   807 
   808     # Returns if the element given is in this group
   808     # Returns if the element given is in this group
   809     def IsElementIn(self, element):
   809     def IsElementIn(self, element):
   810         return element in self.Elements
   810         return element in self.Elements
   811     
   811 
   812     # Change the elements of the group
   812     # Change the elements of the group
   813     def SetElements(self, elements):
   813     def SetElements(self, elements):
   814         self.Elements = elements
   814         self.Elements = elements
   815         self.RefreshWireExclusion()
   815         self.RefreshWireExclusion()
   816         self.RefreshBoundingBox()
   816         self.RefreshBoundingBox()
   817     
   817 
   818     # Returns the elements of the group
   818     # Returns the elements of the group
   819     def GetElements(self):
   819     def GetElements(self):
   820         return self.Elements
   820         return self.Elements
   821     
   821 
   822     # Align the group elements
   822     # Align the group elements
   823     def AlignElements(self, horizontally, vertically):
   823     def AlignElements(self, horizontally, vertically):
   824         minx = self.BoundingBox.x + self.BoundingBox.width
   824         minx = self.BoundingBox.x + self.BoundingBox.width
   825         miny = self.BoundingBox.y + self.BoundingBox.height
   825         miny = self.BoundingBox.y + self.BoundingBox.height
   826         maxx = self.BoundingBox.x
   826         maxx = self.BoundingBox.x
   852                     movey = maxy - height - posy
   852                     movey = maxy - height - posy
   853                 if movex != 0 or movey != 0:
   853                 if movex != 0 or movey != 0:
   854                     element.Move(movex, movey)
   854                     element.Move(movex, movey)
   855                     element.RefreshModel()
   855                     element.RefreshModel()
   856         self.RefreshBoundingBox()
   856         self.RefreshBoundingBox()
   857     
   857 
   858     # Add the given element to the group of elements
   858     # Add the given element to the group of elements
   859     def AddElement(self, element):
   859     def AddElement(self, element):
   860         self.Elements.append(element)
   860         self.Elements.append(element)
   861         
   861 
   862     # Remove or select the given element if it is or not in the group
   862     # Remove or select the given element if it is or not in the group
   863     def SelectElement(self, element):
   863     def SelectElement(self, element):
   864         if element in self.Elements:
   864         if element in self.Elements:
   865             self.Elements.remove(element)
   865             self.Elements.remove(element)
   866         else:
   866         else:
   867             self.Elements.append(element)
   867             self.Elements.append(element)
   868         self.RefreshWireExclusion()
   868         self.RefreshWireExclusion()
   869         self.RefreshBoundingBox()
   869         self.RefreshBoundingBox()
   870     
   870 
   871     # Move this group of elements
   871     # Move this group of elements
   872     def Move(self, movex, movey):
   872     def Move(self, movex, movey):
   873         movex = max(-self.BoundingBox.x, movex)
   873         movex = max(-self.BoundingBox.x, movex)
   874         movey = max(-self.BoundingBox.y, movey)
   874         movey = max(-self.BoundingBox.y, movey)
   875         # Move all the elements of the group
   875         # Move all the elements of the group
   877             if not isinstance(element, Wire):
   877             if not isinstance(element, Wire):
   878                 element.Move(movex, movey, self.WireExcluded)
   878                 element.Move(movex, movey, self.WireExcluded)
   879             elif element in self.WireExcluded:
   879             elif element in self.WireExcluded:
   880                 element.Move(movex, movey, True)
   880                 element.Move(movex, movey, True)
   881         self.RefreshBoundingBox()
   881         self.RefreshBoundingBox()
   882     
   882 
   883     # Refreshes the bounding box of this group of elements
   883     # Refreshes the bounding box of this group of elements
   884     def RefreshBoundingBox(self):
   884     def RefreshBoundingBox(self):
   885         if len(self.Elements) > 0:
   885         if len(self.Elements) > 0:
   886             bbox = self.Elements[0].GetBoundingBox()
   886             bbox = self.Elements[0].GetBoundingBox()
   887             minx, miny = bbox.x, bbox.y
   887             minx, miny = bbox.x, bbox.y
   900         self.Size = wx.Size(self.BoundingBox.width, self.BoundingBox.height)
   900         self.Size = wx.Size(self.BoundingBox.width, self.BoundingBox.height)
   901 
   901 
   902     # Forbids to change the group position
   902     # Forbids to change the group position
   903     def SetPosition(x, y):
   903     def SetPosition(x, y):
   904         pass
   904         pass
   905     
   905 
   906     # Returns the position of this group
   906     # Returns the position of this group
   907     def GetPosition(self, exclude_wires=False):
   907     def GetPosition(self, exclude_wires=False):
   908         if exclude_wires:
   908         if exclude_wires:
   909             posx = posy = None
   909             posx = posy = None
   910             for element in self.Elements:
   910             for element in self.Elements:
   917                         posy = min(posy, bbox.y)
   917                         posy = min(posy, bbox.y)
   918             if posx is None and posy is None:
   918             if posx is None and posy is None:
   919                 return 0, 0
   919                 return 0, 0
   920             return posx, posy
   920             return posx, posy
   921         return self.BoundingBox.x, self.BoundingBox.y
   921         return self.BoundingBox.x, self.BoundingBox.y
   922     
   922 
   923     # Forbids to change the group size
   923     # Forbids to change the group size
   924     def SetSize(width, height):
   924     def SetSize(width, height):
   925         pass
   925         pass
   926     
   926 
   927     # Returns the size of this group
   927     # Returns the size of this group
   928     def GetSize(self):
   928     def GetSize(self):
   929         return self.BoundingBox.width, self.BoundingBox.height
   929         return self.BoundingBox.width, self.BoundingBox.height
   930     
   930 
   931     # Set size of the group elements to their minimum size
   931     # Set size of the group elements to their minimum size
   932     def SetBestSize(self, scaling):
   932     def SetBestSize(self, scaling):
   933         max_movex = max_movey = 0
   933         max_movex = max_movey = 0
   934         for element in self.Elements:
   934         for element in self.Elements:
   935             movex, movey = element.SetBestSize(scaling)
   935             movex, movey = element.SetBestSize(scaling)
   936             max_movex = max(max_movex, movex)
   936             max_movex = max(max_movex, movex)
   937             max_movey = max(max_movey, movey)
   937             max_movey = max(max_movey, movey)
   938         return max_movex, max_movey
   938         return max_movex, max_movey
   939     
   939 
   940     # Refreshes the group elements to move defined and handle selected
   940     # Refreshes the group elements to move defined and handle selected
   941     def ProcessDragging(self, movex, movey, event, scaling):
   941     def ProcessDragging(self, movex, movey, event, scaling):
   942         handle_type, handle = self.Handle
   942         handle_type, handle = self.Handle
   943         # If it is a move handle, Move this group elements
   943         # If it is a move handle, Move this group elements
   944         if handle_type == HANDLE_MOVE:
   944         if handle_type == HANDLE_MOVE:
   958                     movex = self.StartPos.x - posx
   958                     movex = self.StartPos.x - posx
   959                     movey = self.StartPos.y + self.CurrentDrag.y - posy
   959                     movey = self.StartPos.y + self.CurrentDrag.y - posy
   960             self.Move(movex, movey)
   960             self.Move(movex, movey)
   961             return movex, movey
   961             return movex, movey
   962         return 0, 0
   962         return 0, 0
   963     
   963 
   964     # Change the variable that indicates if this element is highlighted
   964     # Change the variable that indicates if this element is highlighted
   965     def SetHighlighted(self, highlighted):
   965     def SetHighlighted(self, highlighted):
   966         for element in self.Elements:
   966         for element in self.Elements:
   967             element.SetHighlighted(highlighted)
   967             element.SetHighlighted(highlighted)
   968     
   968 
   969     def HighlightPoint(self, pos):
   969     def HighlightPoint(self, pos):
   970         for element in self.Elements:
   970         for element in self.Elements:
   971             if isinstance(element, Wire):
   971             if isinstance(element, Wire):
   972                 element.HighlightPoint(pos)
   972                 element.HighlightPoint(pos)
   973     
   973 
   974     # Method called when a LeftDown event have been generated
   974     # Method called when a LeftDown event have been generated
   975     def OnLeftDown(self, event, dc, scaling):
   975     def OnLeftDown(self, event, dc, scaling):
   976         Graphic_Element.OnLeftDown(self, event, dc, scaling)
   976         Graphic_Element.OnLeftDown(self, event, dc, scaling)
   977         self.StartPos = wx.Point(*self.GetPosition(True))
   977         self.StartPos = wx.Point(*self.GetPosition(True))
   978         for element in self.Elements:
   978         for element in self.Elements:
  1005 """
  1005 """
  1006 Class that implements a connector for any type of block
  1006 Class that implements a connector for any type of block
  1007 """
  1007 """
  1008 
  1008 
  1009 class Connector(DebugDataConsumer, ToolTipProducer):
  1009 class Connector(DebugDataConsumer, ToolTipProducer):
  1010     
  1010 
  1011     # Create a new connector
  1011     # Create a new connector
  1012     def __init__(self, parent, name, type, position, direction, negated = False, edge = "none", onlyone = False):
  1012     def __init__(self, parent, name, type, position, direction, negated = False, edge = "none", onlyone = False):
  1013         DebugDataConsumer.__init__(self)
  1013         DebugDataConsumer.__init__(self)
  1014         ToolTipProducer.__init__(self, parent.Parent)
  1014         ToolTipProducer.__init__(self, parent.Parent)
  1015         self.ParentBlock = parent
  1015         self.ParentBlock = parent
  1031         self.ValueSize = None
  1031         self.ValueSize = None
  1032         self.ComputedValue = None
  1032         self.ComputedValue = None
  1033         self.Selected = False
  1033         self.Selected = False
  1034         self.Highlights = []
  1034         self.Highlights = []
  1035         self.RefreshNameSize()
  1035         self.RefreshNameSize()
  1036     
  1036 
  1037     def Flush(self):
  1037     def Flush(self):
  1038         self.ParentBlock = None
  1038         self.ParentBlock = None
  1039         for wire, handle in self.Wires:
  1039         for wire, handle in self.Wires:
  1040             wire.Flush()
  1040             wire.Flush()
  1041         self.Wires = []
  1041         self.Wires = []
  1042     
  1042 
  1043     # Returns the RedrawRect
  1043     # Returns the RedrawRect
  1044     def GetRedrawRect(self, movex = 0, movey = 0):
  1044     def GetRedrawRect(self, movex = 0, movey = 0):
  1045         parent_pos = self.ParentBlock.GetPosition()
  1045         parent_pos = self.ParentBlock.GetPosition()
  1046         x = min(parent_pos[0] + self.Pos.x, parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE)
  1046         x = min(parent_pos[0] + self.Pos.x, parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE)
  1047         y = min(parent_pos[1] + self.Pos.y, parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE)
  1047         y = min(parent_pos[1] + self.Pos.y, parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE)
  1070                                     width * (self.Direction[0] - 1) / 2,
  1070                                     width * (self.Direction[0] - 1) / 2,
  1071                     parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] + \
  1071                     parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] + \
  1072                                     height * (self.Direction[1] - 1),
  1072                                     height * (self.Direction[1] - 1),
  1073                     width, height))
  1073                     width, height))
  1074         return rect
  1074         return rect
  1075     
  1075 
  1076     # Change the connector selection
  1076     # Change the connector selection
  1077     def SetSelected(self, selected):
  1077     def SetSelected(self, selected):
  1078         self.Selected = selected
  1078         self.Selected = selected
  1079     
  1079 
  1080     # Make a clone of the connector
  1080     # Make a clone of the connector
  1081     def Clone(self, parent = None):
  1081     def Clone(self, parent = None):
  1082         if parent is None:
  1082         if parent is None:
  1083             parent = self.ParentBlock
  1083             parent = self.ParentBlock
  1084         return Connector(parent, self.Name, self.Type, wx.Point(self.Pos[0], self.Pos[1]),
  1084         return Connector(parent, self.Name, self.Type, wx.Point(self.Pos[0], self.Pos[1]),
  1085                 self.Direction, self.Negated)
  1085                 self.Direction, self.Negated)
  1086     
  1086 
  1087     # Returns the connector parent block
  1087     # Returns the connector parent block
  1088     def GetParentBlock(self):
  1088     def GetParentBlock(self):
  1089         return self.ParentBlock
  1089         return self.ParentBlock
  1090     
  1090 
  1091     # Returns the connector type
  1091     # Returns the connector type
  1092     def GetType(self, raw = False):
  1092     def GetType(self, raw = False):
  1093         if self.ParentBlock.IsEndType(self.Type) or raw:
  1093         if self.ParentBlock.IsEndType(self.Type) or raw:
  1094             return self.Type
  1094             return self.Type
  1095         elif (self.Negated or self.Edge != "none") and self.ParentBlock.IsOfType("BOOL", self.Type):
  1095         elif (self.Negated or self.Edge != "none") and self.ParentBlock.IsOfType("BOOL", self.Type):
  1096             return "BOOL"
  1096             return "BOOL"
  1097         else:
  1097         else:
  1098             return self.ParentBlock.GetConnectionResultType(self, self.Type)
  1098             return self.ParentBlock.GetConnectionResultType(self, self.Type)
  1099     
  1099 
  1100     # Returns the connector type
  1100     # Returns the connector type
  1101     def GetConnectedType(self):
  1101     def GetConnectedType(self):
  1102         if self.ParentBlock.IsEndType(self.Type):
  1102         if self.ParentBlock.IsEndType(self.Type):
  1103             return self.Type
  1103             return self.Type
  1104         elif len(self.Wires) == 1:
  1104         elif len(self.Wires) == 1:
  1105             return self.Wires[0][0].GetOtherConnectedType(self.Wires[0][1])
  1105             return self.Wires[0][0].GetOtherConnectedType(self.Wires[0][1])
  1106         return self.Type
  1106         return self.Type
  1107     
  1107 
  1108     # Returns the connector type
  1108     # Returns the connector type
  1109     def GetConnectedRedrawRect(self, movex, movey):
  1109     def GetConnectedRedrawRect(self, movex, movey):
  1110         rect = None
  1110         rect = None
  1111         for wire, handle in self.Wires:
  1111         for wire, handle in self.Wires:
  1112             if rect is None:
  1112             if rect is None:
  1113                 rect = wire.GetRedrawRect()
  1113                 rect = wire.GetRedrawRect()
  1114             else:
  1114             else:
  1115                 rect = rect.Union(wire.GetRedrawRect())
  1115                 rect = rect.Union(wire.GetRedrawRect())
  1116         return rect
  1116         return rect
  1117     
  1117 
  1118     # Returns if connector type is compatible with type given
  1118     # Returns if connector type is compatible with type given
  1119     def IsCompatible(self, type):
  1119     def IsCompatible(self, type):
  1120         reference = self.GetType()
  1120         reference = self.GetType()
  1121         return self.ParentBlock.IsOfType(type, reference) or self.ParentBlock.IsOfType(reference, type)
  1121         return self.ParentBlock.IsOfType(type, reference) or self.ParentBlock.IsOfType(reference, type)
  1122     
  1122 
  1123     # Changes the connector name
  1123     # Changes the connector name
  1124     def SetType(self, type):
  1124     def SetType(self, type):
  1125         self.Type = type
  1125         self.Type = type
  1126         for wire, handle in self.Wires:
  1126         for wire, handle in self.Wires:
  1127             wire.SetValid(wire.IsConnectedCompatible())
  1127             wire.SetValid(wire.IsConnectedCompatible())
  1128     
  1128 
  1129     # Returns the connector name
  1129     # Returns the connector name
  1130     def GetName(self):
  1130     def GetName(self):
  1131         return self.Name
  1131         return self.Name
  1132     
  1132 
  1133     # Changes the connector name
  1133     # Changes the connector name
  1134     def SetName(self, name):
  1134     def SetName(self, name):
  1135         self.Name = name
  1135         self.Name = name
  1136         self.RefreshNameSize()
  1136         self.RefreshNameSize()
  1137 
  1137 
  1138     def SetForced(self, forced):
  1138     def SetForced(self, forced):
  1139         if self.Forced != forced:
  1139         if self.Forced != forced:
  1140             self.Forced = forced
  1140             self.Forced = forced
  1141             if self.Visible:
  1141             if self.Visible:
  1142                 self.Parent.ElementNeedRefresh(self)
  1142                 self.Parent.ElementNeedRefresh(self)
  1143     
  1143 
  1144     def GetComputedValue(self):
  1144     def GetComputedValue(self):
  1145         if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
  1145         if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
  1146             return self.Value
  1146             return self.Value
  1147         return None
  1147         return None
  1148     
  1148 
  1149     def GetToolTipValue(self):
  1149     def GetToolTipValue(self):
  1150         return self.GetComputedValue()
  1150         return self.GetComputedValue()
  1151     
  1151 
  1152     def SetValue(self, value):
  1152     def SetValue(self, value):
  1153         if self.Value != value:
  1153         if self.Value != value:
  1154             self.Value = value
  1154             self.Value = value
  1155             computed_value = self.GetComputedValue()
  1155             computed_value = self.GetComputedValue()
  1156             if computed_value is not None:
  1156             if computed_value is not None:
  1159                 if len(self.ComputedValue) > 4:
  1159                 if len(self.ComputedValue) > 4:
  1160                     self.ComputedValue = self.ComputedValue[:4] + "..."
  1160                     self.ComputedValue = self.ComputedValue[:4] + "..."
  1161             self.ValueSize = None
  1161             self.ValueSize = None
  1162             if self.ParentBlock.Visible:
  1162             if self.ParentBlock.Visible:
  1163                 self.ParentBlock.Parent.ElementNeedRefresh(self)
  1163                 self.ParentBlock.Parent.ElementNeedRefresh(self)
  1164     
  1164 
  1165     def RefreshForced(self):
  1165     def RefreshForced(self):
  1166         self.Forced = False
  1166         self.Forced = False
  1167         for wire, handle in self.Wires:
  1167         for wire, handle in self.Wires:
  1168             self.Forced |= wire.IsForced()
  1168             self.Forced |= wire.IsForced()
  1169 
  1169 
  1170     def RefreshValue(self):
  1170     def RefreshValue(self):
  1171         self.Value = self.ReceivingCurrent()
  1171         self.Value = self.ReceivingCurrent()
  1172     
  1172 
  1173     def RefreshValid(self):
  1173     def RefreshValid(self):
  1174         self.Valid = True
  1174         self.Valid = True
  1175         for wire, handle in self.Wires:
  1175         for wire, handle in self.Wires:
  1176             self.Valid &= wire.GetValid()
  1176             self.Valid &= wire.GetValid()
  1177     
  1177 
  1178     def ReceivingCurrent(self):
  1178     def ReceivingCurrent(self):
  1179         current = False
  1179         current = False
  1180         for wire, handle in self.Wires:
  1180         for wire, handle in self.Wires:
  1181             value = wire.GetValue()
  1181             value = wire.GetValue()
  1182             if current != "undefined" and isinstance(value, BooleanType):
  1182             if current != "undefined" and isinstance(value, BooleanType):
  1183                 current |= wire.GetValue()
  1183                 current |= wire.GetValue()
  1184             elif value == "undefined":
  1184             elif value == "undefined":
  1185                 current = "undefined"
  1185                 current = "undefined"
  1186         return current
  1186         return current
  1187     
  1187 
  1188     def SpreadCurrent(self, spreading):
  1188     def SpreadCurrent(self, spreading):
  1189         for wire, handle in self.Wires:
  1189         for wire, handle in self.Wires:
  1190             wire.SetValue(spreading)
  1190             wire.SetValue(spreading)
  1191     
  1191 
  1192     # Changes the connector name size
  1192     # Changes the connector name size
  1193     def RefreshNameSize(self):
  1193     def RefreshNameSize(self):
  1194         if self.Name != "":
  1194         if self.Name != "":
  1195             self.NameSize = self.ParentBlock.Parent.GetTextExtent(self.Name)
  1195             self.NameSize = self.ParentBlock.Parent.GetTextExtent(self.Name)
  1196         else:
  1196         else:
  1197             self.NameSize = 0, 0
  1197             self.NameSize = 0, 0
  1198     
  1198 
  1199     # Returns the connector name size
  1199     # Returns the connector name size
  1200     def GetNameSize(self):
  1200     def GetNameSize(self):
  1201         return self.NameSize
  1201         return self.NameSize
  1202     
  1202 
  1203     # Returns the wires connected to the connector
  1203     # Returns the wires connected to the connector
  1204     def GetWires(self):
  1204     def GetWires(self):
  1205         return self.Wires
  1205         return self.Wires
  1206     
  1206 
  1207     # Returns the parent block Id
  1207     # Returns the parent block Id
  1208     def GetBlockId(self):
  1208     def GetBlockId(self):
  1209         return self.ParentBlock.GetId()
  1209         return self.ParentBlock.GetId()
  1210     
  1210 
  1211     # Returns the connector relative position
  1211     # Returns the connector relative position
  1212     def GetRelPosition(self):
  1212     def GetRelPosition(self):
  1213         return self.Pos
  1213         return self.Pos
  1214     
  1214 
  1215     # Returns the connector absolute position
  1215     # Returns the connector absolute position
  1216     def GetPosition(self, size = True):
  1216     def GetPosition(self, size = True):
  1217         parent_pos = self.ParentBlock.GetPosition()
  1217         parent_pos = self.ParentBlock.GetPosition()
  1218         # If the position of the end of the connector is asked
  1218         # If the position of the end of the connector is asked
  1219         if size:
  1219         if size:
  1221             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE
  1221             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE
  1222         else:
  1222         else:
  1223             x = parent_pos[0] + self.Pos.x
  1223             x = parent_pos[0] + self.Pos.x
  1224             y = parent_pos[1] + self.Pos.y
  1224             y = parent_pos[1] + self.Pos.y
  1225         return wx.Point(x, y)
  1225         return wx.Point(x, y)
  1226     
  1226 
  1227     # Change the connector relative position
  1227     # Change the connector relative position
  1228     def SetPosition(self, pos):
  1228     def SetPosition(self, pos):
  1229         self.Pos = pos
  1229         self.Pos = pos
  1230     
  1230 
  1231     # Returns the connector direction
  1231     # Returns the connector direction
  1232     def GetDirection(self):
  1232     def GetDirection(self):
  1233         return self.Direction
  1233         return self.Direction
  1234     
  1234 
  1235     # Change the connector direction
  1235     # Change the connector direction
  1236     def SetDirection(self, direction):
  1236     def SetDirection(self, direction):
  1237         self.Direction = direction
  1237         self.Direction = direction
  1238     
  1238 
  1239     # Connect a wire to this connector at the last place
  1239     # Connect a wire to this connector at the last place
  1240     def Connect(self, wire, refresh = True):
  1240     def Connect(self, wire, refresh = True):
  1241         self.InsertConnect(len(self.Wires), wire, refresh)
  1241         self.InsertConnect(len(self.Wires), wire, refresh)
  1242     
  1242 
  1243     # Connect a wire to this connector at the place given
  1243     # Connect a wire to this connector at the place given
  1244     def InsertConnect(self, idx, wire, refresh = True):
  1244     def InsertConnect(self, idx, wire, refresh = True):
  1245         if wire not in self.Wires:
  1245         if wire not in self.Wires:
  1246             self.Wires.insert(idx, wire)
  1246             self.Wires.insert(idx, wire)
  1247             if wire[1] == 0:
  1247             if wire[1] == 0:
  1248                 wire[0].ConnectStartPoint(None, self)
  1248                 wire[0].ConnectStartPoint(None, self)
  1249             else:
  1249             else:
  1250                 wire[0].ConnectEndPoint(None, self)
  1250                 wire[0].ConnectEndPoint(None, self)
  1251             if refresh:
  1251             if refresh:
  1252                 self.ParentBlock.RefreshModel(False)
  1252                 self.ParentBlock.RefreshModel(False)
  1253     
  1253 
  1254     # Returns the index of the wire given in the list of connected
  1254     # Returns the index of the wire given in the list of connected
  1255     def GetWireIndex(self, wire):
  1255     def GetWireIndex(self, wire):
  1256         for i, (tmp_wire, handle) in enumerate(self.Wires):
  1256         for i, (tmp_wire, handle) in enumerate(self.Wires):
  1257             if tmp_wire == wire:
  1257             if tmp_wire == wire:
  1258                 return i
  1258                 return i
  1259         return None
  1259         return None
  1260     
  1260 
  1261     # Unconnect a wire or all wires connected to the connector
  1261     # Unconnect a wire or all wires connected to the connector
  1262     def UnConnect(self, wire = None, unconnect = True, delete = False):
  1262     def UnConnect(self, wire = None, unconnect = True, delete = False):
  1263         i = 0
  1263         i = 0
  1264         found = False
  1264         found = False
  1265         while i < len(self.Wires) and not found:
  1265         while i < len(self.Wires) and not found:
  1279         if not wire:
  1279         if not wire:
  1280             self.Wires = []
  1280             self.Wires = []
  1281         if not delete:
  1281         if not delete:
  1282             self.RefreshValid()
  1282             self.RefreshValid()
  1283             self.ParentBlock.RefreshModel(False)
  1283             self.ParentBlock.RefreshModel(False)
  1284     
  1284 
  1285     # Returns if connector has one or more wire connected
  1285     # Returns if connector has one or more wire connected
  1286     def IsConnected(self):
  1286     def IsConnected(self):
  1287         return len(self.Wires) > 0
  1287         return len(self.Wires) > 0
  1288     
  1288 
  1289     # Move the wires connected
  1289     # Move the wires connected
  1290     def MoveConnected(self, exclude = []):
  1290     def MoveConnected(self, exclude = []):
  1291         if len(self.Wires) > 0:
  1291         if len(self.Wires) > 0:
  1292             # Calculate the new position of the end point
  1292             # Calculate the new position of the end point
  1293             parent_pos = self.ParentBlock.GetPosition()
  1293             parent_pos = self.ParentBlock.GetPosition()
  1298                 if wire not in exclude:
  1298                 if wire not in exclude:
  1299                     if index == 0:
  1299                     if index == 0:
  1300                         wire.MoveStartPoint(wx.Point(x, y))
  1300                         wire.MoveStartPoint(wx.Point(x, y))
  1301                     else:
  1301                     else:
  1302                         wire.MoveEndPoint(wx.Point(x, y))
  1302                         wire.MoveEndPoint(wx.Point(x, y))
  1303     
  1303 
  1304     # Refreshes the model of all the wires connected
  1304     # Refreshes the model of all the wires connected
  1305     def RefreshWires(self):
  1305     def RefreshWires(self):
  1306         for wire in self.Wires:
  1306         for wire in self.Wires:
  1307             wire[0].RefreshModel()
  1307             wire[0].RefreshModel()
  1308     
  1308 
  1309     # Refreshes the parent block model
  1309     # Refreshes the parent block model
  1310     def RefreshParentBlock(self):
  1310     def RefreshParentBlock(self):
  1311         self.ParentBlock.RefreshModel(False)
  1311         self.ParentBlock.RefreshModel(False)
  1312     
  1312 
  1313     # Highlight the parent block
  1313     # Highlight the parent block
  1314     def HighlightParentBlock(self, highlight):
  1314     def HighlightParentBlock(self, highlight):
  1315         self.ParentBlock.SetHighlighted(highlight)
  1315         self.ParentBlock.SetHighlighted(highlight)
  1316         self.ParentBlock.Refresh()
  1316         self.ParentBlock.Refresh()
  1317     
  1317 
  1318     # Returns all the blocks connected to this connector
  1318     # Returns all the blocks connected to this connector
  1319     def GetConnectedBlocks(self):
  1319     def GetConnectedBlocks(self):
  1320         blocks = []
  1320         blocks = []
  1321         for wire, handle in self.Wires:
  1321         for wire, handle in self.Wires:
  1322             # Get other connector connected to each wire
  1322             # Get other connector connected to each wire
  1328             if connector:
  1328             if connector:
  1329                 block = connector.GetParentBlock()
  1329                 block = connector.GetParentBlock()
  1330                 if block not in blocks:
  1330                 if block not in blocks:
  1331                     blocks.append(block)
  1331                     blocks.append(block)
  1332         return blocks
  1332         return blocks
  1333     
  1333 
  1334     # Returns the connector negated property
  1334     # Returns the connector negated property
  1335     def IsNegated(self):
  1335     def IsNegated(self):
  1336         return self.Negated
  1336         return self.Negated
  1337     
  1337 
  1338     # Changes the connector negated property
  1338     # Changes the connector negated property
  1339     def SetNegated(self, negated):
  1339     def SetNegated(self, negated):
  1340         if self.ParentBlock.IsOfType("BOOL", self.Type):
  1340         if self.ParentBlock.IsOfType("BOOL", self.Type):
  1341             self.Negated = negated
  1341             self.Negated = negated
  1342             self.Edge = "none"
  1342             self.Edge = "none"
  1343     
  1343 
  1344     # Returns the connector edge property
  1344     # Returns the connector edge property
  1345     def GetEdge(self):
  1345     def GetEdge(self):
  1346         return self.Edge
  1346         return self.Edge
  1347     
  1347 
  1348     # Changes the connector edge property
  1348     # Changes the connector edge property
  1349     def SetEdge(self, edge):
  1349     def SetEdge(self, edge):
  1350         if self.ParentBlock.IsOfType("BOOL", self.Type):
  1350         if self.ParentBlock.IsOfType("BOOL", self.Type):
  1351             self.Edge = edge    
  1351             self.Edge = edge
  1352             self.Negated = False
  1352             self.Negated = False
  1353     
  1353 
  1354     # assume that pointer is already inside of this connector
  1354     # assume that pointer is already inside of this connector
  1355     def ConnectionAvailable(self, direction=None, exclude=True):
  1355     def ConnectionAvailable(self, direction=None, exclude=True):
  1356         wire_nums = len(self.Wires)
  1356         wire_nums = len(self.Wires)
  1357         
  1357 
  1358         connector_free = (wire_nums<= 0)
  1358         connector_free = (wire_nums<= 0)
  1359         connector_max_used = ((wire_nums > 0) and self.OneConnected)
  1359         connector_max_used = ((wire_nums > 0) and self.OneConnected)
  1360         if (self.Parent.CurrentLanguage in ["SFC", "LD"]) and (self.Type == "BOOL"):
  1360         if (self.Parent.CurrentLanguage in ["SFC", "LD"]) and (self.Type == "BOOL"):
  1361             connector_max_used = False;
  1361             connector_max_used = False;
  1362 
  1362 
  1363         # connector is available for new connection
  1363         # connector is available for new connection
  1364         connect  = connector_free or not connector_max_used
  1364         connect  = connector_free or not connector_max_used
  1365         return connect, connector_max_used
  1365         return connect, connector_max_used
  1366                            
  1366 
  1367     # Tests if the point given is near from the end point of this connector
  1367     # Tests if the point given is near from the end point of this connector
  1368     def TestPoint(self, pt, direction=None, exclude=True):
  1368     def TestPoint(self, pt, direction=None, exclude=True):
  1369         inside = False;
  1369         inside = False;
  1370         check_point = (not exclude) and (direction is None or self.Direction == direction);
  1370         check_point = (not exclude) and (direction is None or self.Direction == direction);
  1371 
  1371 
  1376             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE - ANCHOR_DISTANCE
  1376             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE - ANCHOR_DISTANCE
  1377             width = ANCHOR_DISTANCE * 2 + abs(self.Direction[0]) * CONNECTOR_SIZE
  1377             width = ANCHOR_DISTANCE * 2 + abs(self.Direction[0]) * CONNECTOR_SIZE
  1378             height = ANCHOR_DISTANCE * 2 + abs(self.Direction[1]) * CONNECTOR_SIZE
  1378             height = ANCHOR_DISTANCE * 2 + abs(self.Direction[1]) * CONNECTOR_SIZE
  1379             rect = wx.Rect(x, y, width, height)
  1379             rect = wx.Rect(x, y, width, height)
  1380             inside = rect.InsideXY(pt.x, pt.y);
  1380             inside = rect.InsideXY(pt.x, pt.y);
  1381                            
  1381 
  1382         return inside
  1382         return inside
  1383     
  1383 
  1384     # Draws the highlightment of this element if it is highlighted
  1384     # Draws the highlightment of this element if it is highlighted
  1385     def DrawHighlightment(self, dc):
  1385     def DrawHighlightment(self, dc):
  1386         scalex, scaley = dc.GetUserScale()
  1386         scalex, scaley = dc.GetUserScale()
  1387         dc.SetUserScale(1, 1)
  1387         dc.SetUserScale(1, 1)
  1388         pen = MiterPen(HIGHLIGHTCOLOR, 2 * scalex + 5)
  1388         pen = MiterPen(HIGHLIGHTCOLOR, 2 * scalex + 5)
  1391         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  1391         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  1392         dc.SetLogicalFunction(wx.AND)
  1392         dc.SetLogicalFunction(wx.AND)
  1393         parent_pos = self.ParentBlock.GetPosition()
  1393         parent_pos = self.ParentBlock.GetPosition()
  1394         posx = parent_pos[0] + self.Pos.x
  1394         posx = parent_pos[0] + self.Pos.x
  1395         posy = parent_pos[1] + self.Pos.y
  1395         posy = parent_pos[1] + self.Pos.y
  1396         xstart = parent_pos[0] + self.Pos.x 
  1396         xstart = parent_pos[0] + self.Pos.x
  1397         ystart = parent_pos[1] + self.Pos.y
  1397         ystart = parent_pos[1] + self.Pos.y
  1398         if self.Direction[0] < 0:
  1398         if self.Direction[0] < 0:
  1399             xstart += 1
  1399             xstart += 1
  1400         if self.Direction[1] < 0:
  1400         if self.Direction[1] < 0:
  1401             ystart += 1
  1401             ystart += 1
  1402         xend = xstart + CONNECTOR_SIZE * self.Direction[0]
  1402         xend = xstart + CONNECTOR_SIZE * self.Direction[0]
  1403         yend = ystart + CONNECTOR_SIZE * self.Direction[1]
  1403         yend = ystart + CONNECTOR_SIZE * self.Direction[1]
  1404         dc.DrawLine(round((xstart + self.Direction[0]) * scalex), round((ystart + self.Direction[1]) * scaley), 
  1404         dc.DrawLine(round((xstart + self.Direction[0]) * scalex), round((ystart + self.Direction[1]) * scaley),
  1405                     round(xend * scalex), round(yend * scaley))
  1405                     round(xend * scalex), round(yend * scaley))
  1406         dc.SetLogicalFunction(wx.COPY)
  1406         dc.SetLogicalFunction(wx.COPY)
  1407         dc.SetUserScale(scalex, scaley)
  1407         dc.SetUserScale(scalex, scaley)
  1408     
  1408 
  1409     # Adds an highlight to the connector
  1409     # Adds an highlight to the connector
  1410     def AddHighlight(self, infos, start, end, highlight_type):
  1410     def AddHighlight(self, infos, start, end, highlight_type):
  1411         if highlight_type == ERROR_HIGHLIGHT:
  1411         if highlight_type == ERROR_HIGHLIGHT:
  1412             for wire, handle in self.Wires:
  1412             for wire, handle in self.Wires:
  1413                 wire.SetValid(False)
  1413                 wire.SetValid(False)
  1414         AddHighlight(self.Highlights, (start, end, highlight_type))
  1414         AddHighlight(self.Highlights, (start, end, highlight_type))
  1415     
  1415 
  1416     # Removes an highlight from the connector
  1416     # Removes an highlight from the connector
  1417     def RemoveHighlight(self, infos, start, end, highlight_type):
  1417     def RemoveHighlight(self, infos, start, end, highlight_type):
  1418         error = False
  1418         error = False
  1419         highlights = []
  1419         highlights = []
  1420         for highlight in self.Highlights:
  1420         for highlight in self.Highlights:
  1423                 error |= highlight == ERROR_HIGHLIGHT
  1423                 error |= highlight == ERROR_HIGHLIGHT
  1424         self.Highlights = highlights
  1424         self.Highlights = highlights
  1425         if not error:
  1425         if not error:
  1426             for wire, handle in self.Wires:
  1426             for wire, handle in self.Wires:
  1427                 wire.SetValid(wire.IsConnectedCompatible())
  1427                 wire.SetValid(wire.IsConnectedCompatible())
  1428     
  1428 
  1429     # Removes all the highlights of one particular type from the connector
  1429     # Removes all the highlights of one particular type from the connector
  1430     def ClearHighlight(self, highlight_type=None):
  1430     def ClearHighlight(self, highlight_type=None):
  1431         error = False
  1431         error = False
  1432         if highlight_type is None:
  1432         if highlight_type is None:
  1433             self.Highlights = []
  1433             self.Highlights = []
  1439                     error |= highlight == ERROR_HIGHLIGHT
  1439                     error |= highlight == ERROR_HIGHLIGHT
  1440             self.Highlights = highlights
  1440             self.Highlights = highlights
  1441         if not error:
  1441         if not error:
  1442             for wire, handle in self.Wires:
  1442             for wire, handle in self.Wires:
  1443                 wire.SetValid(wire.IsConnectedCompatible())
  1443                 wire.SetValid(wire.IsConnectedCompatible())
  1444     
  1444 
  1445     # Draws the connector
  1445     # Draws the connector
  1446     def Draw(self, dc):
  1446     def Draw(self, dc):
  1447         if self.Selected:
  1447         if self.Selected:
  1448             dc.SetPen(MiterPen(wx.BLUE, 3))
  1448             dc.SetPen(MiterPen(wx.BLUE, 3))
  1449             dc.SetBrush(wx.WHITE_BRUSH)
  1449             dc.SetBrush(wx.WHITE_BRUSH)
  1464                 dc.SetPen(MiterPen(wx.BLUE))
  1464                 dc.SetPen(MiterPen(wx.BLUE))
  1465             else:
  1465             else:
  1466                 dc.SetPen(MiterPen(wx.BLACK))
  1466                 dc.SetPen(MiterPen(wx.BLACK))
  1467             dc.SetBrush(wx.WHITE_BRUSH)
  1467             dc.SetBrush(wx.WHITE_BRUSH)
  1468         parent_pos = self.ParentBlock.GetPosition()
  1468         parent_pos = self.ParentBlock.GetPosition()
  1469         
  1469 
  1470         if getattr(dc, "printing", False):
  1470         if getattr(dc, "printing", False):
  1471             name_size = dc.GetTextExtent(self.Name)
  1471             name_size = dc.GetTextExtent(self.Name)
  1472         else:
  1472         else:
  1473             name_size = self.NameSize
  1473             name_size = self.NameSize
  1474         
  1474 
  1475         if self.Negated:
  1475         if self.Negated:
  1476             # If connector is negated, draw a circle
  1476             # If connector is negated, draw a circle
  1477             xcenter = parent_pos[0] + self.Pos.x + (CONNECTOR_SIZE * self.Direction[0]) / 2
  1477             xcenter = parent_pos[0] + self.Pos.x + (CONNECTOR_SIZE * self.Direction[0]) / 2
  1478             ycenter = parent_pos[1] + self.Pos.y + (CONNECTOR_SIZE * self.Direction[1]) / 2
  1478             ycenter = parent_pos[1] + self.Pos.y + (CONNECTOR_SIZE * self.Direction[1]) / 2
  1479             dc.DrawCircle(xcenter, ycenter, CONNECTOR_SIZE / 2)
  1479             dc.DrawCircle(xcenter, ycenter, CONNECTOR_SIZE / 2)
  1480         else:
  1480         else:
  1481             xstart = parent_pos[0] + self.Pos.x 
  1481             xstart = parent_pos[0] + self.Pos.x
  1482             ystart = parent_pos[1] + self.Pos.y
  1482             ystart = parent_pos[1] + self.Pos.y
  1483             if self.Edge == "rising":
  1483             if self.Edge == "rising":
  1484                 # If connector has a rising edge, draw a right arrow
  1484                 # If connector has a rising edge, draw a right arrow
  1485                 dc.DrawLine(xstart, ystart, xstart - 4, ystart - 4)
  1485                 dc.DrawLine(xstart, ystart, xstart - 4, ystart - 4)
  1486                 dc.DrawLine(xstart, ystart, xstart - 4, ystart + 4)
  1486                 dc.DrawLine(xstart, ystart, xstart - 4, ystart + 4)
  1522             dc.SetTextForeground(wx.NamedColour("purple"))
  1522             dc.SetTextForeground(wx.NamedColour("purple"))
  1523             if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
  1523             if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
  1524                 self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue)
  1524                 self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue)
  1525             if self.ValueSize is not None:
  1525             if self.ValueSize is not None:
  1526                 width, height = self.ValueSize
  1526                 width, height = self.ValueSize
  1527                 dc.DrawText(self.ComputedValue, 
  1527                 dc.DrawText(self.ComputedValue,
  1528                     parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] + \
  1528                     parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] + \
  1529                                     width * (self.Direction[0] - 1) / 2,
  1529                                     width * (self.Direction[0] - 1) / 2,
  1530                     parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] + \
  1530                     parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] + \
  1531                                     height * (self.Direction[1] - 1))
  1531                                     height * (self.Direction[1] - 1))
  1532             dc.SetFont(self.ParentBlock.Parent.GetFont())
  1532             dc.SetFont(self.ParentBlock.Parent.GetFont())
  1539 """
  1539 """
  1540 Class that implements a wire for connecting two blocks
  1540 Class that implements a wire for connecting two blocks
  1541 """
  1541 """
  1542 
  1542 
  1543 class Wire(Graphic_Element, DebugDataConsumer):
  1543 class Wire(Graphic_Element, DebugDataConsumer):
  1544     
  1544 
  1545     # Create a new wire
  1545     # Create a new wire
  1546     def __init__(self, parent, start = None, end = None):
  1546     def __init__(self, parent, start = None, end = None):
  1547         Graphic_Element.__init__(self, parent)
  1547         Graphic_Element.__init__(self, parent)
  1548         DebugDataConsumer.__init__(self)
  1548         DebugDataConsumer.__init__(self)
  1549         self.StartPoint = start
  1549         self.StartPoint = start
  1566         self.OverStart = False
  1566         self.OverStart = False
  1567         self.OverEnd = False
  1567         self.OverEnd = False
  1568         self.ComputingType = False
  1568         self.ComputingType = False
  1569         self.Font = parent.GetMiniFont()
  1569         self.Font = parent.GetMiniFont()
  1570         self.ErrHighlight = False
  1570         self.ErrHighlight = False
  1571     
  1571 
  1572     def GetDefinition(self):
  1572     def GetDefinition(self):
  1573         if self.StartConnected is not None and self.EndConnected is not None:
  1573         if self.StartConnected is not None and self.EndConnected is not None:
  1574             startblock = self.StartConnected.GetParentBlock()
  1574             startblock = self.StartConnected.GetParentBlock()
  1575             endblock = self.EndConnected.GetParentBlock()
  1575             endblock = self.EndConnected.GetParentBlock()
  1576             return [], [(startblock.GetId(), endblock.GetId())]
  1576             return [], [(startblock.GetId(), endblock.GetId())]
  1577         return [], []
  1577         return [], []
  1578     
  1578 
  1579     def Flush(self):
  1579     def Flush(self):
  1580         self.StartConnected = None
  1580         self.StartConnected = None
  1581         self.EndConnected = None
  1581         self.EndConnected = None
  1582     
  1582 
  1583     # Returns the RedrawRect
  1583     # Returns the RedrawRect
  1584     def GetRedrawRect(self, movex = 0, movey = 0):
  1584     def GetRedrawRect(self, movex = 0, movey = 0):
  1585         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1585         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1586         if self.StartConnected:
  1586         if self.StartConnected:
  1587             rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey))
  1587             rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey))
  1605                     y = (self.Points[middle].y + self.Points[middle + 1].y - height) / 2
  1605                     y = (self.Points[middle].y + self.Points[middle + 1].y - height) / 2
  1606                 else:
  1606                 else:
  1607                     y = self.Points[middle].y - height
  1607                     y = self.Points[middle].y - height
  1608                 rect = rect.Union(wx.Rect(x, y, width, height))
  1608                 rect = rect.Union(wx.Rect(x, y, width, height))
  1609         return rect
  1609         return rect
  1610     
  1610 
  1611     def Clone(self, parent, connectors = {}, dx = 0, dy = 0):
  1611     def Clone(self, parent, connectors = {}, dx = 0, dy = 0):
  1612         start_connector = connectors.get(self.StartConnected, None)
  1612         start_connector = connectors.get(self.StartConnected, None)
  1613         end_connector = connectors.get(self.EndConnected, None)
  1613         end_connector = connectors.get(self.EndConnected, None)
  1614         if start_connector is not None and end_connector is not None:
  1614         if start_connector is not None and end_connector is not None:
  1615             wire = Wire(parent)
  1615             wire = Wire(parent)
  1618             end_connector.Connect((wire, -1), False)
  1618             end_connector.Connect((wire, -1), False)
  1619             wire.ConnectStartPoint(start_connector.GetPosition(), start_connector)
  1619             wire.ConnectStartPoint(start_connector.GetPosition(), start_connector)
  1620             wire.ConnectEndPoint(end_connector.GetPosition(), end_connector)
  1620             wire.ConnectEndPoint(end_connector.GetPosition(), end_connector)
  1621             return wire
  1621             return wire
  1622         return None
  1622         return None
  1623     
  1623 
  1624     # Forbids to change the wire position
  1624     # Forbids to change the wire position
  1625     def SetPosition(x, y):
  1625     def SetPosition(x, y):
  1626         pass
  1626         pass
  1627     
  1627 
  1628     # Forbids to change the wire size
  1628     # Forbids to change the wire size
  1629     def SetSize(width, height):
  1629     def SetSize(width, height):
  1630         pass
  1630         pass
  1631     
  1631 
  1632     # Forbids to et size of the group elements to their minimum size
  1632     # Forbids to et size of the group elements to their minimum size
  1633         pass
  1633         pass
  1634     
  1634 
  1635     # Moves and Resizes the element for fitting scaling
  1635     # Moves and Resizes the element for fitting scaling
  1636     def SetBestSize(self, scaling):
  1636     def SetBestSize(self, scaling):
  1637         if scaling is not None:
  1637         if scaling is not None:
  1638             movex_max = movey_max = 0
  1638             movex_max = movey_max = 0
  1639             for idx, point in enumerate(self.Points):
  1639             for idx, point in enumerate(self.Points):
  1662                     movey_max = max(movey_max, movey)
  1662                     movey_max = max(movey_max, movey)
  1663                     point.x += movex
  1663                     point.x += movex
  1664                     point.y += movey
  1664                     point.y += movey
  1665             return movex_max, movey_max
  1665             return movex_max, movey_max
  1666         return 0, 0
  1666         return 0, 0
  1667     
  1667 
  1668     # Returns connector to which start point is connected
  1668     # Returns connector to which start point is connected
  1669     def GetStartConnected(self):
  1669     def GetStartConnected(self):
  1670         return self.StartConnected
  1670         return self.StartConnected
  1671     
  1671 
  1672     # Returns connector to which start point is connected
  1672     # Returns connector to which start point is connected
  1673     def GetStartConnectedType(self):
  1673     def GetStartConnectedType(self):
  1674         if self.StartConnected and not self.ComputingType:
  1674         if self.StartConnected and not self.ComputingType:
  1675             self.ComputingType = True
  1675             self.ComputingType = True
  1676             computed_type = self.StartConnected.GetType()
  1676             computed_type = self.StartConnected.GetType()
  1677             self.ComputingType = False
  1677             self.ComputingType = False
  1678             return computed_type
  1678             return computed_type
  1679         return None
  1679         return None
  1680     
  1680 
  1681     # Returns connector to which end point is connected
  1681     # Returns connector to which end point is connected
  1682     def GetEndConnected(self):
  1682     def GetEndConnected(self):
  1683         return self.EndConnected
  1683         return self.EndConnected
  1684     
  1684 
  1685     # Returns connector to which end point is connected
  1685     # Returns connector to which end point is connected
  1686     def GetEndConnectedType(self):
  1686     def GetEndConnectedType(self):
  1687         if self.EndConnected and not self.ComputingType:
  1687         if self.EndConnected and not self.ComputingType:
  1688             self.ComputingType = True
  1688             self.ComputingType = True
  1689             computed_type = self.EndConnected.GetType()
  1689             computed_type = self.EndConnected.GetType()
  1690             self.ComputingType = False
  1690             self.ComputingType = False
  1691             return computed_type
  1691             return computed_type
  1692         return None
  1692         return None
  1693     
  1693 
  1694     def GetConnectionDirection(self):
  1694     def GetConnectionDirection(self):
  1695         if self.StartConnected is None and self.EndConnected is None:
  1695         if self.StartConnected is None and self.EndConnected is None:
  1696             return None
  1696             return None
  1697         elif self.StartConnected is not None and self.EndConnected is None:
  1697         elif self.StartConnected is not None and self.EndConnected is None:
  1698             return (-self.StartPoint[1][0], -self.StartPoint[1][1])
  1698             return (-self.StartPoint[1][0], -self.StartPoint[1][1])
  1705                 if handle == 0:
  1705                 if handle == 0:
  1706                     return self.EndPoint
  1706                     return self.EndPoint
  1707                 else:
  1707                 else:
  1708                     return (-self.StartPoint[1][0], -self.StartPoint[1][1])
  1708                     return (-self.StartPoint[1][0], -self.StartPoint[1][1])
  1709         return None
  1709         return None
  1710     
  1710 
  1711     def GetOtherConnected(self, connector):
  1711     def GetOtherConnected(self, connector):
  1712         if self.StartConnected == connector:
  1712         if self.StartConnected == connector:
  1713             return self.EndConnected
  1713             return self.EndConnected
  1714         else:
  1714         else:
  1715             return self.StartConnected
  1715             return self.StartConnected
  1716     
  1716 
  1717     def GetOtherConnectedType(self, handle):
  1717     def GetOtherConnectedType(self, handle):
  1718         if handle == 0:
  1718         if handle == 0:
  1719             return self.GetEndConnectedType()
  1719             return self.GetEndConnectedType()
  1720         else:
  1720         else:
  1721             return self.GetStartConnectedType()
  1721             return self.GetStartConnectedType()
  1722     
  1722 
  1723     def IsConnectedCompatible(self):
  1723     def IsConnectedCompatible(self):
  1724         if self.StartConnected:
  1724         if self.StartConnected:
  1725             return self.StartConnected.IsCompatible(self.GetEndConnectedType())
  1725             return self.StartConnected.IsCompatible(self.GetEndConnectedType())
  1726         elif self.EndConnected:
  1726         elif self.EndConnected:
  1727             return True
  1727             return True
  1728         return False
  1728         return False
  1729     
  1729 
  1730     def SetForced(self, forced):
  1730     def SetForced(self, forced):
  1731         if self.Forced != forced:
  1731         if self.Forced != forced:
  1732             self.Forced = forced
  1732             self.Forced = forced
  1733             if self.StartConnected:
  1733             if self.StartConnected:
  1734                 self.StartConnected.RefreshForced()
  1734                 self.StartConnected.RefreshForced()
  1739 
  1739 
  1740     def GetComputedValue(self):
  1740     def GetComputedValue(self):
  1741         if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
  1741         if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
  1742             return self.Value
  1742             return self.Value
  1743         return None
  1743         return None
  1744     
  1744 
  1745     def GetToolTipValue(self):
  1745     def GetToolTipValue(self):
  1746         return self.GetComputedValue()
  1746         return self.GetComputedValue()
  1747 
  1747 
  1748     def SetModifier(self, modifier):
  1748     def SetModifier(self, modifier):
  1749         self.Modifier = modifier
  1749         self.Modifier = modifier
  1771             if self.Visible:
  1771             if self.Visible:
  1772                 self.Parent.ElementNeedRefresh(self)
  1772                 self.Parent.ElementNeedRefresh(self)
  1773             if isinstance(value, BooleanType) and self.StartConnected is not None:
  1773             if isinstance(value, BooleanType) and self.StartConnected is not None:
  1774                 block = self.StartConnected.GetParentBlock()
  1774                 block = self.StartConnected.GetParentBlock()
  1775                 block.SpreadCurrent()
  1775                 block.SpreadCurrent()
  1776     
  1776 
  1777     # Unconnect the start and end points
  1777     # Unconnect the start and end points
  1778     def Clean(self):
  1778     def Clean(self):
  1779         if self.StartConnected:
  1779         if self.StartConnected:
  1780             self.UnConnectStartPoint()
  1780             self.UnConnectStartPoint()
  1781         if self.EndConnected:
  1781         if self.EndConnected:
  1782             self.UnConnectEndPoint()
  1782             self.UnConnectEndPoint()
  1783     
  1783 
  1784     # Delete this wire by calling the corresponding method
  1784     # Delete this wire by calling the corresponding method
  1785     def Delete(self):
  1785     def Delete(self):
  1786         self.Parent.DeleteWire(self)
  1786         self.Parent.DeleteWire(self)
  1787     
  1787 
  1788     # Select a segment and not the whole wire. It's useful for Ladder Diagram
  1788     # Select a segment and not the whole wire. It's useful for Ladder Diagram
  1789     def SetSelectedSegment(self, segment):
  1789     def SetSelectedSegment(self, segment):
  1790         # The last segment is indicated
  1790         # The last segment is indicated
  1791         if segment == -1:
  1791         if segment == -1:
  1792             segment = len(self.Segments) - 1
  1792             segment = len(self.Segments) - 1
  1812                 self.StartConnected.SetSelected(False)
  1812                 self.StartConnected.SetSelected(False)
  1813             if self.EndConnected:
  1813             if self.EndConnected:
  1814                 self.EndConnected.SetSelected(True)
  1814                 self.EndConnected.SetSelected(True)
  1815         self.SelectedSegment = segment
  1815         self.SelectedSegment = segment
  1816         self.Refresh()
  1816         self.Refresh()
  1817     
  1817 
  1818     def SetValid(self, valid):
  1818     def SetValid(self, valid):
  1819         self.Valid = valid
  1819         self.Valid = valid
  1820         if self.StartConnected:
  1820         if self.StartConnected:
  1821             self.StartConnected.RefreshValid()
  1821             self.StartConnected.RefreshValid()
  1822         if self.EndConnected:
  1822         if self.EndConnected:
  1823             self.EndConnected.RefreshValid()
  1823             self.EndConnected.RefreshValid()
  1824     
  1824 
  1825     def GetValid(self):
  1825     def GetValid(self):
  1826         return self.Valid
  1826         return self.Valid
  1827     
  1827 
  1828     # Reinitialize the wire points
  1828     # Reinitialize the wire points
  1829     def ResetPoints(self):
  1829     def ResetPoints(self):
  1830         if self.StartPoint and self.EndPoint:
  1830         if self.StartPoint and self.EndPoint:
  1831             self.Points = [self.StartPoint[0], self.EndPoint[0]]
  1831             self.Points = [self.StartPoint[0], self.EndPoint[0]]
  1832             self.Segments = [self.StartPoint[1]]
  1832             self.Segments = [self.StartPoint[1]]
  1833         else:
  1833         else:
  1834             self.Points = []
  1834             self.Points = []
  1835             self.Segments = []
  1835             self.Segments = []
  1836     
  1836 
  1837     # Refresh the wire bounding box
  1837     # Refresh the wire bounding box
  1838     def RefreshBoundingBox(self):
  1838     def RefreshBoundingBox(self):
  1839         if len(self.Points) > 0:
  1839         if len(self.Points) > 0:
  1840             # If startpoint or endpoint is connected, save the point radius
  1840             # If startpoint or endpoint is connected, save the point radius
  1841             start_radius = end_radius = 0
  1841             start_radius = end_radius = 0
  1860                 miny, minbbxy = min(miny, self.Points[-1].y), min(minbbxy, self.Points[-1].y - end_radius)
  1860                 miny, minbbxy = min(miny, self.Points[-1].y), min(minbbxy, self.Points[-1].y - end_radius)
  1861                 maxy, maxbbxy = max(maxy, self.Points[-1].y), max(maxbbxy, self.Points[-1].y + end_radius)
  1861                 maxy, maxbbxy = max(maxy, self.Points[-1].y), max(maxbbxy, self.Points[-1].y + end_radius)
  1862             self.Pos.x, self.Pos.y = minx, miny
  1862             self.Pos.x, self.Pos.y = minx, miny
  1863             self.Size = wx.Size(maxx - minx, maxy - miny)
  1863             self.Size = wx.Size(maxx - minx, maxy - miny)
  1864             self.BoundingBox = wx.Rect(minbbxx, minbbxy, maxbbxx - minbbxx + 1, maxbbxy - minbbxy + 1)
  1864             self.BoundingBox = wx.Rect(minbbxx, minbbxy, maxbbxx - minbbxx + 1, maxbbxy - minbbxy + 1)
  1865     
  1865 
  1866     # Refresh the realpoints that permits to keep the proportionality in wire during resizing
  1866     # Refresh the realpoints that permits to keep the proportionality in wire during resizing
  1867     def RefreshRealPoints(self):
  1867     def RefreshRealPoints(self):
  1868         if len(self.Points) > 0:
  1868         if len(self.Points) > 0:
  1869             self.RealPoints = []
  1869             self.RealPoints = []
  1870             # Calculate float relative position of each point with the minimum point
  1870             # Calculate float relative position of each point with the minimum point
  1871             for point in self.Points:
  1871             for point in self.Points:
  1872                 self.RealPoints.append([float(point.x - self.Pos.x), float(point.y - self.Pos.y)])
  1872                 self.RealPoints.append([float(point.x - self.Pos.x), float(point.y - self.Pos.y)])
  1873     
  1873 
  1874     # Returns the wire minimum size 
  1874     # Returns the wire minimum size
  1875     def GetMinSize(self):
  1875     def GetMinSize(self):
  1876         width = 1
  1876         width = 1
  1877         height = 1
  1877         height = 1
  1878         dir_product = product(self.StartPoint[1], self.EndPoint[1])
  1878         dir_product = product(self.StartPoint[1], self.EndPoint[1])
  1879         # The directions are opposed
  1879         # The directions are opposed
  1891         # The directions are perpendiculars
  1891         # The directions are perpendiculars
  1892         else:
  1892         else:
  1893             width = MIN_SEGMENT_SIZE
  1893             width = MIN_SEGMENT_SIZE
  1894             height = MIN_SEGMENT_SIZE
  1894             height = MIN_SEGMENT_SIZE
  1895         return width + 1, height + 1
  1895         return width + 1, height + 1
  1896     
  1896 
  1897     # Returns if the point given is on one of the wire segments
  1897     # Returns if the point given is on one of the wire segments
  1898     def HitTest(self, pt, connectors=True):
  1898     def HitTest(self, pt, connectors=True):
  1899         test = False
  1899         test = False
  1900         for i in xrange(len(self.Points) - 1):
  1900         for i in xrange(len(self.Points) - 1):
  1901             rect = wx.Rect(0, 0, 0, 0)
  1901             rect = wx.Rect(0, 0, 0, 0)
  1902             if i == 0 and self.StartConnected is not None:
  1902             if i == 0 and self.StartConnected is not None:
  1903                 x1 = self.Points[i].x - self.Segments[0][0] * CONNECTOR_SIZE
  1903                 x1 = self.Points[i].x - self.Segments[0][0] * CONNECTOR_SIZE
  1904                 y1 = self.Points[i].y - self.Segments[0][1] * CONNECTOR_SIZE
  1904                 y1 = self.Points[i].y - self.Segments[0][1] * CONNECTOR_SIZE
  1905             else:
  1905             else:
  1906                 x1, y1 = self.Points[i].x, self.Points[i].y    
  1906                 x1, y1 = self.Points[i].x, self.Points[i].y
  1907             if i == len(self.Points) - 2 and self.EndConnected is not None:
  1907             if i == len(self.Points) - 2 and self.EndConnected is not None:
  1908                 x2 = self.Points[i + 1].x + self.Segments[-1][0] * CONNECTOR_SIZE
  1908                 x2 = self.Points[i + 1].x + self.Segments[-1][0] * CONNECTOR_SIZE
  1909                 y2 = self.Points[i + 1].y + self.Segments[-1][1] * CONNECTOR_SIZE
  1909                 y2 = self.Points[i + 1].y + self.Segments[-1][1] * CONNECTOR_SIZE
  1910             else:
  1910             else:
  1911                 x2, y2 = self.Points[i + 1].x, self.Points[i + 1].y
  1911                 x2, y2 = self.Points[i + 1].x, self.Points[i + 1].y
  1912             # Calculate a rectangle around the segment
  1912             # Calculate a rectangle around the segment
  1913             rect = wx.Rect(min(x1, x2) - ANCHOR_DISTANCE, min(y1, y2) - ANCHOR_DISTANCE,
  1913             rect = wx.Rect(min(x1, x2) - ANCHOR_DISTANCE, min(y1, y2) - ANCHOR_DISTANCE,
  1914                 abs(x1 - x2) + 2 * ANCHOR_DISTANCE, abs(y1 - y2) + 2 * ANCHOR_DISTANCE)
  1914                 abs(x1 - x2) + 2 * ANCHOR_DISTANCE, abs(y1 - y2) + 2 * ANCHOR_DISTANCE)
  1915             test |= rect.InsideXY(pt.x, pt.y) 
  1915             test |= rect.InsideXY(pt.x, pt.y)
  1916         return test
  1916         return test
  1917     
  1917 
  1918     # Returns the wire start or end point if the point given is on one of them 
  1918     # Returns the wire start or end point if the point given is on one of them
  1919     def TestPoint(self, pt):
  1919     def TestPoint(self, pt):
  1920         # Test the wire start point
  1920         # Test the wire start point
  1921         rect = wx.Rect(self.Points[0].x - ANCHOR_DISTANCE, self.Points[0].y - ANCHOR_DISTANCE,
  1921         rect = wx.Rect(self.Points[0].x - ANCHOR_DISTANCE, self.Points[0].y - ANCHOR_DISTANCE,
  1922             2 * ANCHOR_DISTANCE, 2 * ANCHOR_DISTANCE)
  1922             2 * ANCHOR_DISTANCE, 2 * ANCHOR_DISTANCE)
  1923         if rect.InsideXY(pt.x, pt.y):
  1923         if rect.InsideXY(pt.x, pt.y):
  1927             rect = wx.Rect(self.Points[-1].x - ANCHOR_DISTANCE, self.Points[-1].y - ANCHOR_DISTANCE,
  1927             rect = wx.Rect(self.Points[-1].x - ANCHOR_DISTANCE, self.Points[-1].y - ANCHOR_DISTANCE,
  1928                 2 * ANCHOR_DISTANCE, 2 * ANCHOR_DISTANCE)
  1928                 2 * ANCHOR_DISTANCE, 2 * ANCHOR_DISTANCE)
  1929             if rect.InsideXY(pt.x, pt.y):
  1929             if rect.InsideXY(pt.x, pt.y):
  1930                 return -1
  1930                 return -1
  1931         return None
  1931         return None
  1932     
  1932 
  1933     # Returns the wire segment if the point given is on it
  1933     # Returns the wire segment if the point given is on it
  1934     def TestSegment(self, pt, all=False):
  1934     def TestSegment(self, pt, all=False):
  1935         for i in xrange(len(self.Segments)):
  1935         for i in xrange(len(self.Segments)):
  1936             # If wire is not in a Ladder Diagram, first and last segments are excluded
  1936             # If wire is not in a Ladder Diagram, first and last segments are excluded
  1937             if all or 0 < i < len(self.Segments) - 1:
  1937             if all or 0 < i < len(self.Segments) - 1:
  1941                 rect = wx.Rect(min(x1, x2) - ANCHOR_DISTANCE, min(y1, y2) - ANCHOR_DISTANCE,
  1941                 rect = wx.Rect(min(x1, x2) - ANCHOR_DISTANCE, min(y1, y2) - ANCHOR_DISTANCE,
  1942                     abs(x1 - x2) + 2 * ANCHOR_DISTANCE, abs(y1 - y2) + 2 * ANCHOR_DISTANCE)
  1942                     abs(x1 - x2) + 2 * ANCHOR_DISTANCE, abs(y1 - y2) + 2 * ANCHOR_DISTANCE)
  1943                 if rect.InsideXY(pt.x, pt.y):
  1943                 if rect.InsideXY(pt.x, pt.y):
  1944                     return i, self.Segments[i]
  1944                     return i, self.Segments[i]
  1945         return None
  1945         return None
  1946     
  1946 
  1947     # Define the wire points
  1947     # Define the wire points
  1948     def SetPoints(self, points, verify=True):
  1948     def SetPoints(self, points, verify=True):
  1949         if len(points) > 1:
  1949         if len(points) > 1:
  1950             self.Points = [wx.Point(x, y) for x, y in points]
  1950             self.Points = [wx.Point(x, y) for x, y in points]
  1951             # Calculate the start and end directions
  1951             # Calculate the start and end directions
  1952             self.StartPoint = [None, vector(self.Points[0], self.Points[1])]
  1952             self.StartPoint = [None, vector(self.Points[0], self.Points[1])]
  1953             self.EndPoint = [None, vector(self.Points[-1], self.Points[-2])]
  1953             self.EndPoint = [None, vector(self.Points[-1], self.Points[-2])]
  1954             # Calculate the start and end points
  1954             # Calculate the start and end points
  1955             self.StartPoint[0] = wx.Point(self.Points[0].x + CONNECTOR_SIZE * self.StartPoint[1][0], 
  1955             self.StartPoint[0] = wx.Point(self.Points[0].x + CONNECTOR_SIZE * self.StartPoint[1][0],
  1956                 self.Points[0].y + CONNECTOR_SIZE * self.StartPoint[1][1])
  1956                 self.Points[0].y + CONNECTOR_SIZE * self.StartPoint[1][1])
  1957             self.EndPoint[0] = wx.Point(self.Points[-1].x + CONNECTOR_SIZE * self.EndPoint[1][0], 
  1957             self.EndPoint[0] = wx.Point(self.Points[-1].x + CONNECTOR_SIZE * self.EndPoint[1][0],
  1958                 self.Points[-1].y + CONNECTOR_SIZE * self.EndPoint[1][1])
  1958                 self.Points[-1].y + CONNECTOR_SIZE * self.EndPoint[1][1])
  1959             self.Points[0] = self.StartPoint[0]
  1959             self.Points[0] = self.StartPoint[0]
  1960             self.Points[-1] = self.EndPoint[0]
  1960             self.Points[-1] = self.EndPoint[0]
  1961             # Calculate the segments directions
  1961             # Calculate the segments directions
  1962             self.Segments = []
  1962             self.Segments = []
  1977                             self.Points.insert(i + 1, wx.Point(self.Points[i + 1].x, self.Points[i + 1].y))
  1977                             self.Points.insert(i + 1, wx.Point(self.Points[i + 1].x, self.Points[i + 1].y))
  1978                     self.Segments.append(segment)
  1978                     self.Segments.append(segment)
  1979                     i += 1
  1979                     i += 1
  1980             self.RefreshBoundingBox()
  1980             self.RefreshBoundingBox()
  1981             self.RefreshRealPoints()
  1981             self.RefreshRealPoints()
  1982     
  1982 
  1983     # Returns the position of the point indicated
  1983     # Returns the position of the point indicated
  1984     def GetPoint(self, index):
  1984     def GetPoint(self, index):
  1985         if index < len(self.Points):
  1985         if index < len(self.Points):
  1986             return self.Points[index].x, self.Points[index].y
  1986             return self.Points[index].x, self.Points[index].y
  1987         return None
  1987         return None
  1988     
  1988 
  1989     # Returns a list of the position of all wire points
  1989     # Returns a list of the position of all wire points
  1990     def GetPoints(self, invert = False):
  1990     def GetPoints(self, invert = False):
  1991         points = self.VerifyPoints()
  1991         points = self.VerifyPoints()
  1992         points[0] = wx.Point(points[0].x - CONNECTOR_SIZE * self.StartPoint[1][0], 
  1992         points[0] = wx.Point(points[0].x - CONNECTOR_SIZE * self.StartPoint[1][0],
  1993                 points[0].y - CONNECTOR_SIZE * self.StartPoint[1][1])
  1993                 points[0].y - CONNECTOR_SIZE * self.StartPoint[1][1])
  1994         points[-1] = wx.Point(points[-1].x - CONNECTOR_SIZE * self.EndPoint[1][0], 
  1994         points[-1] = wx.Point(points[-1].x - CONNECTOR_SIZE * self.EndPoint[1][0],
  1995                 points[-1].y - CONNECTOR_SIZE * self.EndPoint[1][1])
  1995                 points[-1].y - CONNECTOR_SIZE * self.EndPoint[1][1])
  1996         # An inversion of the list is asked
  1996         # An inversion of the list is asked
  1997         if invert:
  1997         if invert:
  1998             points.reverse()
  1998             points.reverse()
  1999         return points
  1999         return points
  2000     
  2000 
  2001     # Returns the position of the two selected segment points
  2001     # Returns the position of the two selected segment points
  2002     def GetSelectedSegmentPoints(self):
  2002     def GetSelectedSegmentPoints(self):
  2003         if self.SelectedSegment != None and len(self.Points) > 1:
  2003         if self.SelectedSegment != None and len(self.Points) > 1:
  2004             return self.Points[self.SelectedSegment:self.SelectedSegment + 2]
  2004             return self.Points[self.SelectedSegment:self.SelectedSegment + 2]
  2005         return []
  2005         return []
  2006     
  2006 
  2007     # Returns if the selected segment is the first and/or the last of the wire
  2007     # Returns if the selected segment is the first and/or the last of the wire
  2008     def GetSelectedSegmentConnections(self):
  2008     def GetSelectedSegmentConnections(self):
  2009         if self.SelectedSegment != None and len(self.Points) > 1:
  2009         if self.SelectedSegment != None and len(self.Points) > 1:
  2010             return self.SelectedSegment == 0, self.SelectedSegment == len(self.Segments) - 1
  2010             return self.SelectedSegment == 0, self.SelectedSegment == len(self.Segments) - 1
  2011         return (True, True)
  2011         return (True, True)
  2012     
  2012 
  2013     # Returns the connectors on which the wire is connected
  2013     # Returns the connectors on which the wire is connected
  2014     def GetConnected(self):
  2014     def GetConnected(self):
  2015         connected = []
  2015         connected = []
  2016         if self.StartConnected and self.StartPoint[1] == WEST:
  2016         if self.StartConnected and self.StartPoint[1] == WEST:
  2017             connected.append(self.StartConnected)
  2017             connected.append(self.StartConnected)
  2018         if self.EndConnected and self.EndPoint[1] == WEST:
  2018         if self.EndConnected and self.EndPoint[1] == WEST:
  2019             connected.append(self.EndConnected)
  2019             connected.append(self.EndConnected)
  2020         return connected
  2020         return connected
  2021     
  2021 
  2022     # Returns the id of the block connected to the first or the last wire point
  2022     # Returns the id of the block connected to the first or the last wire point
  2023     def GetConnectedInfos(self, index):
  2023     def GetConnectedInfos(self, index):
  2024         if index == 0 and self.StartConnected:
  2024         if index == 0 and self.StartConnected:
  2025             return self.StartConnected.GetBlockId(), self.StartConnected.GetName()
  2025             return self.StartConnected.GetBlockId(), self.StartConnected.GetName()
  2026         elif index == -1 and self.EndConnected:
  2026         elif index == -1 and self.EndConnected:
  2027             return self.EndConnected.GetBlockId(), self.EndConnected.GetName()
  2027             return self.EndConnected.GetBlockId(), self.EndConnected.GetName()
  2028         return None
  2028         return None
  2029     
  2029 
  2030     # Update the wire points position by keeping at most possible the current positions
  2030     # Update the wire points position by keeping at most possible the current positions
  2031     def GeneratePoints(self, realpoints = True):
  2031     def GeneratePoints(self, realpoints = True):
  2032         i = 0
  2032         i = 0
  2033         # Calculate the start enad end points with the minimum segment size in the right direction
  2033         # Calculate the start enad end points with the minimum segment size in the right direction
  2034         end = wx.Point(self.EndPoint[0].x + self.EndPoint[1][0] * MIN_SEGMENT_SIZE,
  2034         end = wx.Point(self.EndPoint[0].x + self.EndPoint[1][0] * MIN_SEGMENT_SIZE,
  2035             self.EndPoint[0].y + self.EndPoint[1][1] * MIN_SEGMENT_SIZE)
  2035             self.EndPoint[0].y + self.EndPoint[1][1] * MIN_SEGMENT_SIZE)
  2036         start = wx.Point(self.StartPoint[0].x + self.StartPoint[1][0] * MIN_SEGMENT_SIZE, 
  2036         start = wx.Point(self.StartPoint[0].x + self.StartPoint[1][0] * MIN_SEGMENT_SIZE,
  2037             self.StartPoint[0].y + self.StartPoint[1][1] * MIN_SEGMENT_SIZE)
  2037             self.StartPoint[0].y + self.StartPoint[1][1] * MIN_SEGMENT_SIZE)
  2038         # Evaluate the point till it's the last
  2038         # Evaluate the point till it's the last
  2039         while i < len(self.Points) - 1:
  2039         while i < len(self.Points) - 1:
  2040             # The next point is the last
  2040             # The next point is the last
  2041             if i + 1 == len(self.Points) - 1:
  2041             if i + 1 == len(self.Points) - 1:
  2044                 # The current point is the first
  2044                 # The current point is the first
  2045                 if i == 0:
  2045                 if i == 0:
  2046                     # If the end point is not in the start direction, a point is added
  2046                     # If the end point is not in the start direction, a point is added
  2047                     if v_end != self.Segments[0] or v_end == self.EndPoint[1]:
  2047                     if v_end != self.Segments[0] or v_end == self.EndPoint[1]:
  2048                         self.Points.insert(1, wx.Point(start.x, start.y))
  2048                         self.Points.insert(1, wx.Point(start.x, start.y))
  2049                         self.Segments.insert(1, DirectionChoice((self.Segments[0][1], 
  2049                         self.Segments.insert(1, DirectionChoice((self.Segments[0][1],
  2050                             self.Segments[0][0]), v_end, self.EndPoint[1]))
  2050                             self.Segments[0][0]), v_end, self.EndPoint[1]))
  2051                 # The current point is the second
  2051                 # The current point is the second
  2052                 elif i == 1:
  2052                 elif i == 1:
  2053                     # The previous direction and the target direction are mainly opposed, a point is added
  2053                     # The previous direction and the target direction are mainly opposed, a point is added
  2054                     if product(v_end, self.Segments[0]) < 0:
  2054                     if product(v_end, self.Segments[0]) < 0:
  2055                         self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2055                         self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2056                         self.Segments.insert(2, DirectionChoice((self.Segments[1][1], 
  2056                         self.Segments.insert(2, DirectionChoice((self.Segments[1][1],
  2057                             self.Segments[1][0]), v_end, self.EndPoint[1]))
  2057                             self.Segments[1][0]), v_end, self.EndPoint[1]))
  2058                     # The previous direction and the end direction are the same or they are
  2058                     # The previous direction and the end direction are the same or they are
  2059                     # perpendiculars and the end direction points towards current segment
  2059                     # perpendiculars and the end direction points towards current segment
  2060                     elif product(self.Segments[0], self.EndPoint[1]) >= 0 and product(self.Segments[1], self.EndPoint[1]) <= 0:
  2060                     elif product(self.Segments[0], self.EndPoint[1]) >= 0 and product(self.Segments[1], self.EndPoint[1]) <= 0:
  2061                         # Current point and end point are aligned
  2061                         # Current point and end point are aligned
  2064                         if self.Segments[0][1] != 0:
  2064                         if self.Segments[0][1] != 0:
  2065                             self.Points[1].y = end.y
  2065                             self.Points[1].y = end.y
  2066                         # If the previous direction and the end direction are the same, a point is added
  2066                         # If the previous direction and the end direction are the same, a point is added
  2067                         if product(self.Segments[0], self.EndPoint[1]) > 0:
  2067                         if product(self.Segments[0], self.EndPoint[1]) > 0:
  2068                             self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2068                             self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2069                             self.Segments.insert(2, DirectionChoice((self.Segments[1][1], 
  2069                             self.Segments.insert(2, DirectionChoice((self.Segments[1][1],
  2070                                 self.Segments[1][0]), v_end, self.EndPoint[1]))
  2070                                 self.Segments[1][0]), v_end, self.EndPoint[1]))
  2071                     else:
  2071                     else:
  2072                         # Current point is positioned in the middle of start point
  2072                         # Current point is positioned in the middle of start point
  2073                         # and end point on the current direction and a point is added
  2073                         # and end point on the current direction and a point is added
  2074                         if self.Segments[0][0] != 0:
  2074                         if self.Segments[0][0] != 0:
  2075                             self.Points[1].x = (end.x + start.x) / 2
  2075                             self.Points[1].x = (end.x + start.x) / 2
  2076                         if self.Segments[0][1] != 0:
  2076                         if self.Segments[0][1] != 0:
  2077                             self.Points[1].y = (end.y + start.y) / 2
  2077                             self.Points[1].y = (end.y + start.y) / 2
  2078                         self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2078                         self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2079                         self.Segments.insert(2, DirectionChoice((self.Segments[1][1], 
  2079                         self.Segments.insert(2, DirectionChoice((self.Segments[1][1],
  2080                             self.Segments[1][0]), v_end, self.EndPoint[1]))
  2080                             self.Segments[1][0]), v_end, self.EndPoint[1]))
  2081                 else:
  2081                 else:
  2082                     # The previous direction and the end direction are perpendiculars
  2082                     # The previous direction and the end direction are perpendiculars
  2083                     if product(self.Segments[i - 1], self.EndPoint[1]) == 0:
  2083                     if product(self.Segments[i - 1], self.EndPoint[1]) == 0:
  2084                         # The target direction and the end direction aren't mainly the same
  2084                         # The target direction and the end direction aren't mainly the same
  2091                             # Previous direction is updated from the new point
  2091                             # Previous direction is updated from the new point
  2092                             if product(vector(self.Points[i - 1], self.Points[i]), self.Segments[i - 1]) < 0:
  2092                             if product(vector(self.Points[i - 1], self.Points[i]), self.Segments[i - 1]) < 0:
  2093                                 self.Segments[i - 1] = (-self.Segments[i - 1][0], -self.Segments[i - 1][1])
  2093                                 self.Segments[i - 1] = (-self.Segments[i - 1][0], -self.Segments[i - 1][1])
  2094                         else:
  2094                         else:
  2095                             test = True
  2095                             test = True
  2096                             # If the current point is the third, test if the second 
  2096                             # If the current point is the third, test if the second
  2097                             # point can be aligned with the end point
  2097                             # point can be aligned with the end point
  2098                             if i == 2:
  2098                             if i == 2:
  2099                                 test_point = wx.Point(self.Points[1].x, self.Points[1].y)
  2099                                 test_point = wx.Point(self.Points[1].x, self.Points[1].y)
  2100                                 if self.Segments[1][0] != 0:
  2100                                 if self.Segments[1][0] != 0:
  2101                                     test_point.y = end.y
  2101                                     test_point.y = end.y
  2117                                 if self.Segments[1][0] != 0:
  2117                                 if self.Segments[1][0] != 0:
  2118                                     self.Points[2].x = (self.Points[1].x + end.x) / 2
  2118                                     self.Points[2].x = (self.Points[1].x + end.x) / 2
  2119                                 if self.Segments[1][1] != 0:
  2119                                 if self.Segments[1][1] != 0:
  2120                                     self.Points[2].y = (self.Points[1].y + end.y) / 2
  2120                                     self.Points[2].y = (self.Points[1].y + end.y) / 2
  2121                                 self.Points.insert(3, wx.Point(self.Points[2].x, self.Points[2].y))
  2121                                 self.Points.insert(3, wx.Point(self.Points[2].x, self.Points[2].y))
  2122                                 self.Segments.insert(3, DirectionChoice((self.Segments[2][1], 
  2122                                 self.Segments.insert(3, DirectionChoice((self.Segments[2][1],
  2123                                     self.Segments[2][0]), v_end, self.EndPoint[1]))
  2123                                     self.Segments[2][0]), v_end, self.EndPoint[1]))
  2124                     else:
  2124                     else:
  2125                         # Current point is aligned with end point
  2125                         # Current point is aligned with end point
  2126                         if self.Segments[i - 1][0] != 0:
  2126                         if self.Segments[i - 1][0] != 0:
  2127                             self.Points[i].x = end.x
  2127                             self.Points[i].x = end.x
  2138                                 self.Points[i].x = (end.x + self.Points[i - 1].x) / 2
  2138                                 self.Points[i].x = (end.x + self.Points[i - 1].x) / 2
  2139                             if self.Segments[i - 1][1] != 0:
  2139                             if self.Segments[i - 1][1] != 0:
  2140                                 self.Points[i].y = (end.y + self.Points[i - 1].y) / 2
  2140                                 self.Points[i].y = (end.y + self.Points[i - 1].y) / 2
  2141                         # A point is added
  2141                         # A point is added
  2142                         self.Points.insert(i + 1, wx.Point(self.Points[i].x, self.Points[i].y))
  2142                         self.Points.insert(i + 1, wx.Point(self.Points[i].x, self.Points[i].y))
  2143                         self.Segments.insert(i + 1, DirectionChoice((self.Segments[i][1], 
  2143                         self.Segments.insert(i + 1, DirectionChoice((self.Segments[i][1],
  2144                                 self.Segments[i][0]), v_end, self.EndPoint[1]))
  2144                                 self.Segments[i][0]), v_end, self.EndPoint[1]))
  2145             else:
  2145             else:
  2146                 # Current point is the first, and second is not mainly in the first direction
  2146                 # Current point is the first, and second is not mainly in the first direction
  2147                 if i == 0 and product(vector(start, self.Points[1]), self.Segments[0]) < 0:
  2147                 if i == 0 and product(vector(start, self.Points[1]), self.Segments[0]) < 0:
  2148                     # If first and second directions aren't perpendiculars, a point is added 
  2148                     # If first and second directions aren't perpendiculars, a point is added
  2149                     if product(self.Segments[0], self.Segments[1]) != 0:
  2149                     if product(self.Segments[0], self.Segments[1]) != 0:
  2150                         self.Points.insert(1, wx.Point(start.x, start.y))
  2150                         self.Points.insert(1, wx.Point(start.x, start.y))
  2151                         self.Segments.insert(1, DirectionChoice((self.Segments[0][1], 
  2151                         self.Segments.insert(1, DirectionChoice((self.Segments[0][1],
  2152                             self.Segments[0][0]), vector(start, self.Points[1]), self.Segments[1]))
  2152                             self.Segments[0][0]), vector(start, self.Points[1]), self.Segments[1]))
  2153                     else:
  2153                     else:
  2154                         self.Points[1].x, self.Points[1].y = start.x, start.y
  2154                         self.Points[1].x, self.Points[1].y = start.x, start.y
  2155                 else:
  2155                 else:
  2156                     # Next point is aligned with current point
  2156                     # Next point is aligned with current point
  2163                         self.Segments[i] = (-self.Segments[i][0], -self.Segments[i][1])
  2163                         self.Segments[i] = (-self.Segments[i][0], -self.Segments[i][1])
  2164             i += 1
  2164             i += 1
  2165         self.RefreshBoundingBox()
  2165         self.RefreshBoundingBox()
  2166         if realpoints:
  2166         if realpoints:
  2167             self.RefreshRealPoints()
  2167             self.RefreshRealPoints()
  2168     
  2168 
  2169     # Verify that two consecutive points haven't the same position
  2169     # Verify that two consecutive points haven't the same position
  2170     def VerifyPoints(self):
  2170     def VerifyPoints(self):
  2171         points = [point for point in self.Points]
  2171         points = [point for point in self.Points]
  2172         segments = [segment for segment in self.Segments]
  2172         segments = [segment for segment in self.Segments]
  2173         i = 1
  2173         i = 1
  2183             self.Points = [point for point in points]
  2183             self.Points = [point for point in points]
  2184             self.Segments = [segment for segment in segments]
  2184             self.Segments = [segment for segment in segments]
  2185             self.RefreshBoundingBox()
  2185             self.RefreshBoundingBox()
  2186             self.RefreshRealPoints()
  2186             self.RefreshRealPoints()
  2187         return points
  2187         return points
  2188     
  2188 
  2189     # Moves all the wire points except the first and the last if they are connected
  2189     # Moves all the wire points except the first and the last if they are connected
  2190     def Move(self, dx, dy, endpoints = False):
  2190     def Move(self, dx, dy, endpoints = False):
  2191         for i, point in enumerate(self.Points):
  2191         for i, point in enumerate(self.Points):
  2192             if endpoints or not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
  2192             if endpoints or not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
  2193                 point.x += dx
  2193                 point.x += dx
  2194                 point.y += dy
  2194                 point.y += dy
  2195         self.StartPoint[0] = self.Points[0]
  2195         self.StartPoint[0] = self.Points[0]
  2196         self.EndPoint[0] = self.Points[-1]
  2196         self.EndPoint[0] = self.Points[-1]
  2197         self.GeneratePoints()
  2197         self.GeneratePoints()
  2198     
  2198 
  2199     # Resize the wire from position and size given
  2199     # Resize the wire from position and size given
  2200     def Resize(self, x, y, width, height):
  2200     def Resize(self, x, y, width, height):
  2201         if len(self.Points) > 1:
  2201         if len(self.Points) > 1:
  2202             # Calculate the new position of each point for testing the new size
  2202             # Calculate the new position of each point for testing the new size
  2203             minx, miny = self.Pos.x, self.Pos.y
  2203             minx, miny = self.Pos.x, self.Pos.y
  2252                             height - dir[1] * MIN_SEGMENT_SIZE))
  2252                             height - dir[1] * MIN_SEGMENT_SIZE))
  2253                     self.Points[i] = wx.Point(minx + x + realpointx, miny + y + realpointy)
  2253                     self.Points[i] = wx.Point(minx + x + realpointx, miny + y + realpointy)
  2254             self.StartPoint[0] = self.Points[0]
  2254             self.StartPoint[0] = self.Points[0]
  2255             self.EndPoint[0] = self.Points[-1]
  2255             self.EndPoint[0] = self.Points[-1]
  2256             self.GeneratePoints(False)
  2256             self.GeneratePoints(False)
  2257     
  2257 
  2258     # Moves the wire start point and update the wire points
  2258     # Moves the wire start point and update the wire points
  2259     def MoveStartPoint(self, point):
  2259     def MoveStartPoint(self, point):
  2260         if len(self.Points) > 1:
  2260         if len(self.Points) > 1:
  2261             self.StartPoint[0] = point
  2261             self.StartPoint[0] = point
  2262             self.Points[0] = point
  2262             self.Points[0] = point
  2263             self.GeneratePoints()
  2263             self.GeneratePoints()
  2264     
  2264 
  2265     # Changes the wire start direction and update the wire points
  2265     # Changes the wire start direction and update the wire points
  2266     def SetStartPointDirection(self, dir):
  2266     def SetStartPointDirection(self, dir):
  2267         if len(self.Points) > 1:
  2267         if len(self.Points) > 1:
  2268             self.StartPoint[1] = dir
  2268             self.StartPoint[1] = dir
  2269             self.Segments[0] = dir
  2269             self.Segments[0] = dir
  2270             self.GeneratePoints()
  2270             self.GeneratePoints()
  2271     
  2271 
  2272     # Rotates the wire start direction by an angle of 90 degrees anticlockwise
  2272     # Rotates the wire start direction by an angle of 90 degrees anticlockwise
  2273     def RotateStartPoint(self):
  2273     def RotateStartPoint(self):
  2274         self.SetStartPointDirection((self.StartPoint[1][1], -self.StartPoint[1][0]))
  2274         self.SetStartPointDirection((self.StartPoint[1][1], -self.StartPoint[1][0]))
  2275     
  2275 
  2276     # Connects wire start point to the connector given and moves wire start point
  2276     # Connects wire start point to the connector given and moves wire start point
  2277     # to given point
  2277     # to given point
  2278     def ConnectStartPoint(self, point, connector):
  2278     def ConnectStartPoint(self, point, connector):
  2279         if point:
  2279         if point:
  2280             self.MoveStartPoint(point)
  2280             self.MoveStartPoint(point)
  2281         self.StartConnected = connector
  2281         self.StartConnected = connector
  2282         self.RefreshBoundingBox()
  2282         self.RefreshBoundingBox()
  2283     
  2283 
  2284     # Unconnects wire start point
  2284     # Unconnects wire start point
  2285     def UnConnectStartPoint(self, delete = False):
  2285     def UnConnectStartPoint(self, delete = False):
  2286         if delete:
  2286         if delete:
  2287             self.StartConnected = None
  2287             self.StartConnected = None
  2288             self.Delete()
  2288             self.Delete()
  2289         elif self.StartConnected:
  2289         elif self.StartConnected:
  2290             self.StartConnected.UnConnect(self, unconnect = False)
  2290             self.StartConnected.UnConnect(self, unconnect = False)
  2291             self.StartConnected = None
  2291             self.StartConnected = None
  2292             self.RefreshBoundingBox()
  2292             self.RefreshBoundingBox()
  2293     
  2293 
  2294     # Moves the wire end point and update the wire points
  2294     # Moves the wire end point and update the wire points
  2295     def MoveEndPoint(self, point):
  2295     def MoveEndPoint(self, point):
  2296         if len(self.Points) > 1:
  2296         if len(self.Points) > 1:
  2297             self.EndPoint[0] = point
  2297             self.EndPoint[0] = point
  2298             self.Points[-1] = point
  2298             self.Points[-1] = point
  2301     # Changes the wire end direction and update the wire points
  2301     # Changes the wire end direction and update the wire points
  2302     def SetEndPointDirection(self, dir):
  2302     def SetEndPointDirection(self, dir):
  2303         if len(self.Points) > 1:
  2303         if len(self.Points) > 1:
  2304             self.EndPoint[1] = dir
  2304             self.EndPoint[1] = dir
  2305             self.GeneratePoints()
  2305             self.GeneratePoints()
  2306             
  2306 
  2307     # Rotates the wire end direction by an angle of 90 degrees anticlockwise
  2307     # Rotates the wire end direction by an angle of 90 degrees anticlockwise
  2308     def RotateEndPoint(self):
  2308     def RotateEndPoint(self):
  2309         self.SetEndPointDirection((self.EndPoint[1][1], -self.EndPoint[1][0]))
  2309         self.SetEndPointDirection((self.EndPoint[1][1], -self.EndPoint[1][0]))
  2310 
  2310 
  2311     # Connects wire end point to the connector given and moves wire end point
  2311     # Connects wire end point to the connector given and moves wire end point
  2313     def ConnectEndPoint(self, point, connector):
  2313     def ConnectEndPoint(self, point, connector):
  2314         if point:
  2314         if point:
  2315             self.MoveEndPoint(point)
  2315             self.MoveEndPoint(point)
  2316         self.EndConnected = connector
  2316         self.EndConnected = connector
  2317         self.RefreshBoundingBox()
  2317         self.RefreshBoundingBox()
  2318     
  2318 
  2319     # Unconnects wire end point
  2319     # Unconnects wire end point
  2320     def UnConnectEndPoint(self, delete = False):
  2320     def UnConnectEndPoint(self, delete = False):
  2321         if delete:
  2321         if delete:
  2322             self.EndConnected = None
  2322             self.EndConnected = None
  2323             self.Delete()
  2323             self.Delete()
  2324         elif self.EndConnected:
  2324         elif self.EndConnected:
  2325             self.EndConnected.UnConnect(self, unconnect = False)
  2325             self.EndConnected.UnConnect(self, unconnect = False)
  2326             self.EndConnected = None
  2326             self.EndConnected = None
  2327             self.RefreshBoundingBox()
  2327             self.RefreshBoundingBox()
  2328     
  2328 
  2329     # Moves the wire segment given by its index
  2329     # Moves the wire segment given by its index
  2330     def MoveSegment(self, idx, movex, movey, scaling):
  2330     def MoveSegment(self, idx, movex, movey, scaling):
  2331         if 0 < idx < len(self.Segments) - 1:
  2331         if 0 < idx < len(self.Segments) - 1:
  2332             if self.Segments[idx] in (NORTH, SOUTH):
  2332             if self.Segments[idx] in (NORTH, SOUTH):
  2333                 start_x = self.Points[idx].x
  2333                 start_x = self.Points[idx].x
  2354                 self.Points[idx + 1].y += movey
  2354                 self.Points[idx + 1].y += movey
  2355                 self.GeneratePoints()
  2355                 self.GeneratePoints()
  2356                 if start_y != self.Points[idx].y:
  2356                 if start_y != self.Points[idx].y:
  2357                     return 0, self.Points[idx].y - start_y
  2357                     return 0, self.Points[idx].y - start_y
  2358         return 0, 0
  2358         return 0, 0
  2359     
  2359 
  2360     # Adds two points in the middle of the handled segment
  2360     # Adds two points in the middle of the handled segment
  2361     def AddSegment(self):
  2361     def AddSegment(self):
  2362         handle_type, handle = self.Handle
  2362         handle_type, handle = self.Handle
  2363         if handle_type == HANDLE_SEGMENT:
  2363         if handle_type == HANDLE_SEGMENT:
  2364             segment, dir = handle
  2364             segment, dir = handle
  2389                 self.Points.insert(segment + 3, wx.Point(p2x, p2y))
  2389                 self.Points.insert(segment + 3, wx.Point(p2x, p2y))
  2390                 self.Segments.insert(segment + 3, (dir[1], dir[0]))
  2390                 self.Segments.insert(segment + 3, (dir[1], dir[0]))
  2391                 self.Points.insert(segment + 4, wx.Point(p2x, p2y))
  2391                 self.Points.insert(segment + 4, wx.Point(p2x, p2y))
  2392                 self.Segments.insert(segment + 4, dir)
  2392                 self.Segments.insert(segment + 4, dir)
  2393             self.GeneratePoints()
  2393             self.GeneratePoints()
  2394     
  2394 
  2395     # Delete the handled segment by removing the two segment points
  2395     # Delete the handled segment by removing the two segment points
  2396     def DeleteSegment(self):
  2396     def DeleteSegment(self):
  2397         handle_type, handle = self.Handle
  2397         handle_type, handle = self.Handle
  2398         if handle_type == HANDLE_SEGMENT:
  2398         if handle_type == HANDLE_SEGMENT:
  2399             segment, dir = handle
  2399             segment, dir = handle
  2400             for i in xrange(2):
  2400             for i in xrange(2):
  2401                 self.Points.pop(segment)
  2401                 self.Points.pop(segment)
  2402                 self.Segments.pop(segment)
  2402                 self.Segments.pop(segment)
  2403             self.GeneratePoints()
  2403             self.GeneratePoints()
  2404             self.RefreshModel()
  2404             self.RefreshModel()
  2405             
  2405 
  2406     # Method called when a LeftDown event have been generated
  2406     # Method called when a LeftDown event have been generated
  2407     def OnLeftDown(self, event, dc, scaling):
  2407     def OnLeftDown(self, event, dc, scaling):
  2408         pos = GetScaledEventPosition(event, dc, scaling)
  2408         pos = GetScaledEventPosition(event, dc, scaling)
  2409         # Test if a point have been handled
  2409         # Test if a point have been handled
  2410         #result = self.TestPoint(pos)
  2410         #result = self.TestPoint(pos)
  2422             self.Handle = (HANDLE_SEGMENT, result)
  2422             self.Handle = (HANDLE_SEGMENT, result)
  2423         # Execute the default method for a graphic element
  2423         # Execute the default method for a graphic element
  2424         else:
  2424         else:
  2425             Graphic_Element.OnLeftDown(self, event, dc, scaling)
  2425             Graphic_Element.OnLeftDown(self, event, dc, scaling)
  2426         self.oldPos = pos
  2426         self.oldPos = pos
  2427     
  2427 
  2428     # Method called when a RightUp event has been generated
  2428     # Method called when a RightUp event has been generated
  2429     def OnRightUp(self, event, dc, scaling):
  2429     def OnRightUp(self, event, dc, scaling):
  2430         pos = GetScaledEventPosition(event, dc, scaling)
  2430         pos = GetScaledEventPosition(event, dc, scaling)
  2431         # Test if a segment has been handled
  2431         # Test if a segment has been handled
  2432         result = self.TestSegment(pos, True)
  2432         result = self.TestSegment(pos, True)
  2435             # Popup the menu with special items for a wire
  2435             # Popup the menu with special items for a wire
  2436             self.Parent.PopupWireMenu(0 < result[0] < len(self.Segments) - 1)
  2436             self.Parent.PopupWireMenu(0 < result[0] < len(self.Segments) - 1)
  2437         else:
  2437         else:
  2438             # Execute the default method for a graphic element
  2438             # Execute the default method for a graphic element
  2439             Graphic_Element.OnRightUp(self, event, dc, scaling)
  2439             Graphic_Element.OnRightUp(self, event, dc, scaling)
  2440     
  2440 
  2441     # Method called when a LeftDClick event has been generated
  2441     # Method called when a LeftDClick event has been generated
  2442     def OnLeftDClick(self, event, dc, scaling):
  2442     def OnLeftDClick(self, event, dc, scaling):
  2443         rect = self.GetRedrawRect()
  2443         rect = self.GetRedrawRect()
  2444         if event.ControlDown():
  2444         if event.ControlDown():
  2445             direction = (self.StartPoint[1], self.EndPoint[1])
  2445             direction = (self.StartPoint[1], self.EndPoint[1])
  2490             self.GeneratePoints()
  2490             self.GeneratePoints()
  2491             self.RefreshModel()
  2491             self.RefreshModel()
  2492             self.Parent.RefreshBuffer()
  2492             self.Parent.RefreshBuffer()
  2493         rect.Union(self.GetRedrawRect())
  2493         rect.Union(self.GetRedrawRect())
  2494         self.Parent.RefreshRect(self.Parent.GetScrolledRect(rect), False)
  2494         self.Parent.RefreshRect(self.Parent.GetScrolledRect(rect), False)
  2495         
  2495 
  2496     # Method called when a Motion event has been generated
  2496     # Method called when a Motion event has been generated
  2497     def OnMotion(self, event, dc, scaling):
  2497     def OnMotion(self, event, dc, scaling):
  2498         pos = GetScaledEventPosition(event, dc, scaling)
  2498         pos = GetScaledEventPosition(event, dc, scaling)
  2499         if not event.Dragging():
  2499         if not event.Dragging():
  2500             # Test if a segment has been handled
  2500             # Test if a segment has been handled
  2509                 # Execute the default method for a graphic element
  2509                 # Execute the default method for a graphic element
  2510                 return Graphic_Element.OnMotion(self, event, dc, scaling)
  2510                 return Graphic_Element.OnMotion(self, event, dc, scaling)
  2511         else:
  2511         else:
  2512             # Execute the default method for a graphic element
  2512             # Execute the default method for a graphic element
  2513             return Graphic_Element.OnMotion(self, event, dc, scaling)
  2513             return Graphic_Element.OnMotion(self, event, dc, scaling)
  2514     
  2514 
  2515     # Refreshes the wire state according to move defined and handle selected
  2515     # Refreshes the wire state according to move defined and handle selected
  2516     def ProcessDragging(self, movex, movey, event, scaling):
  2516     def ProcessDragging(self, movex, movey, event, scaling):
  2517         handle_type, handle = self.Handle
  2517         handle_type, handle = self.Handle
  2518         # A point has been handled
  2518         # A point has been handled
  2519         if handle_type == HANDLE_POINT:
  2519         if handle_type == HANDLE_POINT:
  2570         elif handle_type == HANDLE_SEGMENT:
  2570         elif handle_type == HANDLE_SEGMENT:
  2571             return self.MoveSegment(handle[0], movex, movey, scaling)
  2571             return self.MoveSegment(handle[0], movex, movey, scaling)
  2572         # Execute the default method for a graphic element
  2572         # Execute the default method for a graphic element
  2573         else:
  2573         else:
  2574             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  2574             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  2575     
  2575 
  2576     # Refreshes the wire model
  2576     # Refreshes the wire model
  2577     def RefreshModel(self, move=True):
  2577     def RefreshModel(self, move=True):
  2578         if self.StartConnected and self.StartPoint[1] in [WEST, NORTH]:
  2578         if self.StartConnected and self.StartPoint[1] in [WEST, NORTH]:
  2579             self.StartConnected.RefreshParentBlock()
  2579             self.StartConnected.RefreshParentBlock()
  2580         if self.EndConnected and self.EndPoint[1] in [WEST, NORTH]:
  2580         if self.EndConnected and self.EndPoint[1] in [WEST, NORTH]:
  2581             self.EndConnected.RefreshParentBlock()
  2581             self.EndConnected.RefreshParentBlock()
  2582     
  2582 
  2583     # Change the variable that indicates if this element is highlighted
  2583     # Change the variable that indicates if this element is highlighted
  2584     def SetHighlighted(self, highlighted):
  2584     def SetHighlighted(self, highlighted):
  2585         self.Highlighted = highlighted
  2585         self.Highlighted = highlighted
  2586         if not highlighted:
  2586         if not highlighted:
  2587             self.OverStart = False
  2587             self.OverStart = False
  2588             self.OverEnd = False
  2588             self.OverEnd = False
  2589         self.Refresh()
  2589         self.Refresh()
  2590     
  2590 
  2591     def HighlightPoint(self, pos):
  2591     def HighlightPoint(self, pos):
  2592         refresh = False
  2592         refresh = False
  2593         start, end = self.OverStart, self.OverEnd
  2593         start, end = self.OverStart, self.OverEnd
  2594         self.OverStart = False
  2594         self.OverStart = False
  2595         self.OverEnd = False
  2595         self.OverEnd = False
  2600                 self.OverStart = True
  2600                 self.OverStart = True
  2601             elif result != 0 and self.EndConnected is not None:
  2601             elif result != 0 and self.EndConnected is not None:
  2602                 self.OverEnd = True
  2602                 self.OverEnd = True
  2603         if start != self.OverStart or end != self.OverEnd:
  2603         if start != self.OverStart or end != self.OverEnd:
  2604             self.Refresh()
  2604             self.Refresh()
  2605     
  2605 
  2606     # Draws the highlightment of this element if it is highlighted
  2606     # Draws the highlightment of this element if it is highlighted
  2607     def DrawHighlightment(self, dc):
  2607     def DrawHighlightment(self, dc):
  2608         scalex, scaley = dc.GetUserScale()
  2608         scalex, scaley = dc.GetUserScale()
  2609         dc.SetUserScale(1, 1)
  2609         dc.SetUserScale(1, 1)
  2610         # If user trying to connect wire with wrong input, highlight will become red.
  2610         # If user trying to connect wire with wrong input, highlight will become red.
  2615         dc.SetPen(MiterPen(highlightcolor, (2 * scalex + 5)))
  2615         dc.SetPen(MiterPen(highlightcolor, (2 * scalex + 5)))
  2616         dc.SetBrush(wx.Brush(highlightcolor))
  2616         dc.SetBrush(wx.Brush(highlightcolor))
  2617         dc.SetLogicalFunction(wx.AND)
  2617         dc.SetLogicalFunction(wx.AND)
  2618         # Draw the start and end points if they are not connected or the mouse is over them
  2618         # Draw the start and end points if they are not connected or the mouse is over them
  2619         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2619         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2620             dc.DrawCircle(round(self.Points[0].x * scalex), 
  2620             dc.DrawCircle(round(self.Points[0].x * scalex),
  2621                           round(self.Points[0].y * scaley), 
  2621                           round(self.Points[0].y * scaley),
  2622                           (POINT_RADIUS + 1) * scalex + 2)
  2622                           (POINT_RADIUS + 1) * scalex + 2)
  2623         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2623         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2624             dc.DrawCircle(self.Points[-1].x * scalex, self.Points[-1].y * scaley, (POINT_RADIUS + 1) * scalex + 2)
  2624             dc.DrawCircle(self.Points[-1].x * scalex, self.Points[-1].y * scaley, (POINT_RADIUS + 1) * scalex + 2)
  2625         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2625         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2626         if len(self.Points) > 1:
  2626         if len(self.Points) > 1:
  2627             points = [wx.Point(round((self.Points[0].x - self.Segments[0][0]) * scalex), 
  2627             points = [wx.Point(round((self.Points[0].x - self.Segments[0][0]) * scalex),
  2628                                round((self.Points[0].y - self.Segments[0][1]) * scaley))]
  2628                                round((self.Points[0].y - self.Segments[0][1]) * scaley))]
  2629             points.extend([wx.Point(round(point.x * scalex), round(point.y * scaley)) for point in self.Points[1:-1]])
  2629             points.extend([wx.Point(round(point.x * scalex), round(point.y * scaley)) for point in self.Points[1:-1]])
  2630             points.append(wx.Point(round((self.Points[-1].x + self.Segments[-1][0]) * scalex), 
  2630             points.append(wx.Point(round((self.Points[-1].x + self.Segments[-1][0]) * scalex),
  2631                                    round((self.Points[-1].y + self.Segments[-1][1]) * scaley)))
  2631                                    round((self.Points[-1].y + self.Segments[-1][1]) * scaley)))
  2632         else:
  2632         else:
  2633             points = []
  2633             points = []
  2634         dc.DrawLines(points)
  2634         dc.DrawLines(points)
  2635         dc.SetLogicalFunction(wx.COPY)
  2635         dc.SetLogicalFunction(wx.COPY)
  2636         dc.SetUserScale(scalex, scaley)
  2636         dc.SetUserScale(scalex, scaley)
  2637         
  2637 
  2638         if self.StartConnected is not None:
  2638         if self.StartConnected is not None:
  2639             self.StartConnected.DrawHighlightment(dc)
  2639             self.StartConnected.DrawHighlightment(dc)
  2640             self.StartConnected.Draw(dc)
  2640             self.StartConnected.Draw(dc)
  2641         if self.EndConnected is not None:
  2641         if self.EndConnected is not None:
  2642             self.EndConnected.DrawHighlightment(dc)
  2642             self.EndConnected.DrawHighlightment(dc)
  2643             self.EndConnected.Draw(dc)
  2643             self.EndConnected.Draw(dc)
  2644     
  2644 
  2645     # Draws the wire lines and points
  2645     # Draws the wire lines and points
  2646     def Draw(self, dc):
  2646     def Draw(self, dc):
  2647         Graphic_Element.Draw(self, dc)
  2647         Graphic_Element.Draw(self, dc)
  2648         if not self.Valid:
  2648         if not self.Valid:
  2649             dc.SetPen(MiterPen(wx.RED))
  2649             dc.SetPen(MiterPen(wx.RED))
  2748         self.Id = id
  2748         self.Id = id
  2749         self.Content = content
  2749         self.Content = content
  2750         self.Pos = wx.Point(0, 0)
  2750         self.Pos = wx.Point(0, 0)
  2751         self.Size = wx.Size(0, 0)
  2751         self.Size = wx.Size(0, 0)
  2752         self.Highlights = []
  2752         self.Highlights = []
  2753     
  2753 
  2754     # Make a clone of this comment
  2754     # Make a clone of this comment
  2755     def Clone(self, parent, id = None, pos = None):
  2755     def Clone(self, parent, id = None, pos = None):
  2756         comment = Comment(parent, self.Content, id)
  2756         comment = Comment(parent, self.Content, id)
  2757         if pos is not None:
  2757         if pos is not None:
  2758             comment.SetPosition(pos.x, pos.y)
  2758             comment.SetPosition(pos.x, pos.y)
  2759         comment.SetSize(self.Size[0], self.Size[1])
  2759         comment.SetSize(self.Size[0], self.Size[1])
  2760         return comment
  2760         return comment
  2761     
  2761 
  2762     # Method for keeping compatibility with others
  2762     # Method for keeping compatibility with others
  2763     def Clean(self):
  2763     def Clean(self):
  2764         pass
  2764         pass
  2765     
  2765 
  2766     # Delete this comment by calling the corresponding method
  2766     # Delete this comment by calling the corresponding method
  2767     def Delete(self):
  2767     def Delete(self):
  2768         self.Parent.DeleteComment(self)
  2768         self.Parent.DeleteComment(self)
  2769     
  2769 
  2770     # Refresh the comment bounding box
  2770     # Refresh the comment bounding box
  2771     def RefreshBoundingBox(self):
  2771     def RefreshBoundingBox(self):
  2772         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  2772         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  2773     
  2773 
  2774     # Changes the comment size
  2774     # Changes the comment size
  2775     def SetSize(self, width, height):
  2775     def SetSize(self, width, height):
  2776         self.Size.SetWidth(width)
  2776         self.Size.SetWidth(width)
  2777         self.Size.SetHeight(height)
  2777         self.Size.SetHeight(height)
  2778         self.RefreshBoundingBox()
  2778         self.RefreshBoundingBox()
  2779 
  2779 
  2780     # Returns the comment size
  2780     # Returns the comment size
  2781     def GetSize(self):
  2781     def GetSize(self):
  2782         return self.Size.GetWidth(), self.Size.GetHeight()
  2782         return self.Size.GetWidth(), self.Size.GetHeight()
  2783     
  2783 
  2784     # Returns the comment minimum size
  2784     # Returns the comment minimum size
  2785     def GetMinSize(self):
  2785     def GetMinSize(self):
  2786         dc = wx.ClientDC(self.Parent)
  2786         dc = wx.ClientDC(self.Parent)
  2787         min_width = 0
  2787         min_width = 0
  2788         min_height = 0
  2788         min_height = 0
  2791             for word in line.split(" "):
  2791             for word in line.split(" "):
  2792                 wordwidth, wordheight = dc.GetTextExtent(word)
  2792                 wordwidth, wordheight = dc.GetTextExtent(word)
  2793                 min_width = max(min_width, wordwidth)
  2793                 min_width = max(min_width, wordwidth)
  2794                 min_height = max(min_height, wordheight)
  2794                 min_height = max(min_height, wordheight)
  2795         return min_width + 20, min_height + 20
  2795         return min_width + 20, min_height + 20
  2796     
  2796 
  2797     # Changes the comment position
  2797     # Changes the comment position
  2798     def SetPosition(self, x, y):
  2798     def SetPosition(self, x, y):
  2799         self.Pos.x = x
  2799         self.Pos.x = x
  2800         self.Pos.y = y
  2800         self.Pos.y = y
  2801         self.RefreshBoundingBox()
  2801         self.RefreshBoundingBox()
  2813         return self.Content
  2813         return self.Content
  2814 
  2814 
  2815     # Returns the comment position
  2815     # Returns the comment position
  2816     def GetPosition(self):
  2816     def GetPosition(self):
  2817         return self.Pos.x, self.Pos.y
  2817         return self.Pos.x, self.Pos.y
  2818     
  2818 
  2819     # Moves the comment
  2819     # Moves the comment
  2820     def Move(self, dx, dy, connected = True):
  2820     def Move(self, dx, dy, connected = True):
  2821         self.Pos.x += dx
  2821         self.Pos.x += dx
  2822         self.Pos.y += dy
  2822         self.Pos.y += dy
  2823         self.RefreshBoundingBox()
  2823         self.RefreshBoundingBox()
  2824     
  2824 
  2825     # Resizes the comment with the position and the size given
  2825     # Resizes the comment with the position and the size given
  2826     def Resize(self, x, y, width, height):
  2826     def Resize(self, x, y, width, height):
  2827         self.Move(x, y)
  2827         self.Move(x, y)
  2828         self.SetSize(width, height)
  2828         self.SetSize(width, height)
  2829     
  2829 
  2830     # Method called when a RightUp event have been generated
  2830     # Method called when a RightUp event have been generated
  2831     def OnRightUp(self, event, dc, scaling):
  2831     def OnRightUp(self, event, dc, scaling):
  2832         # Popup the default menu
  2832         # Popup the default menu
  2833         self.Parent.PopupDefaultMenu()
  2833         self.Parent.PopupDefaultMenu()
  2834     
  2834 
  2835     # Refreshes the wire state according to move defined and handle selected
  2835     # Refreshes the wire state according to move defined and handle selected
  2836     def ProcessDragging(self, movex, movey, event, scaling):
  2836     def ProcessDragging(self, movex, movey, event, scaling):
  2837         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE and self.Parent.CurrentLanguage == "LD":
  2837         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE and self.Parent.CurrentLanguage == "LD":
  2838             movex = movey = 0
  2838             movex = movey = 0
  2839         return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  2839         return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  2840         
  2840 
  2841     # Refreshes the comment model
  2841     # Refreshes the comment model
  2842     def RefreshModel(self, move=True):
  2842     def RefreshModel(self, move=True):
  2843         self.Parent.RefreshCommentModel(self)
  2843         self.Parent.RefreshCommentModel(self)
  2844     
  2844 
  2845     # Method called when a LeftDClick event have been generated
  2845     # Method called when a LeftDClick event have been generated
  2846     def OnLeftDClick(self, event, dc, scaling):
  2846     def OnLeftDClick(self, event, dc, scaling):
  2847         # Edit the comment content
  2847         # Edit the comment content
  2848         self.Parent.EditCommentContent(self)
  2848         self.Parent.EditCommentContent(self)
  2849     
  2849 
  2850     # Adds an highlight to the comment
  2850     # Adds an highlight to the comment
  2851     def AddHighlight(self, infos, start, end, highlight_type):
  2851     def AddHighlight(self, infos, start, end, highlight_type):
  2852         if infos[0] == "content":
  2852         if infos[0] == "content":
  2853             AddHighlight(self.Highlights, (start, end, highlight_type))
  2853             AddHighlight(self.Highlights, (start, end, highlight_type))
  2854     
  2854 
  2855     # Removes an highlight from the comment
  2855     # Removes an highlight from the comment
  2856     def RemoveHighlight(self, infos, start, end, highlight_type):
  2856     def RemoveHighlight(self, infos, start, end, highlight_type):
  2857         RemoveHighlight(self.Highlights, (start, end, highlight_type))
  2857         RemoveHighlight(self.Highlights, (start, end, highlight_type))
  2858     
  2858 
  2859     # Removes all the highlights of one particular type from the comment
  2859     # Removes all the highlights of one particular type from the comment
  2860     def ClearHighlight(self, highlight_type=None):
  2860     def ClearHighlight(self, highlight_type=None):
  2861         self.Highlights = ClearHighlights(self.Highlights, highlight_type)
  2861         self.Highlights = ClearHighlights(self.Highlights, highlight_type)
  2862     
  2862 
  2863     # Draws the highlightment of this element if it is highlighted
  2863     # Draws the highlightment of this element if it is highlighted
  2864     def DrawHighlightment(self, dc):
  2864     def DrawHighlightment(self, dc):
  2865         scalex, scaley = dc.GetUserScale()
  2865         scalex, scaley = dc.GetUserScale()
  2866         dc.SetUserScale(1, 1)
  2866         dc.SetUserScale(1, 1)
  2867         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  2867         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  2868         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2868         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2869         dc.SetLogicalFunction(wx.AND)
  2869         dc.SetLogicalFunction(wx.AND)
  2870         
  2870 
  2871         left = (self.Pos.x - 1) * scalex - 2
  2871         left = (self.Pos.x - 1) * scalex - 2
  2872         right = (self.Pos.x + self.Size[0] + 1) * scalex + 2
  2872         right = (self.Pos.x + self.Size[0] + 1) * scalex + 2
  2873         top = (self.Pos.y - 1) * scaley - 2
  2873         top = (self.Pos.y - 1) * scaley - 2
  2874         bottom = (self.Pos.y + self.Size[1] + 1) * scaley + 2
  2874         bottom = (self.Pos.y + self.Size[1] + 1) * scaley + 2
  2875         angle_top = (self.Pos.x + self.Size[0] - 9) * scalex + 2
  2875         angle_top = (self.Pos.x + self.Size[0] - 9) * scalex + 2
  2876         angle_right = (self.Pos.y + 9) * scaley - 2
  2876         angle_right = (self.Pos.y + 9) * scaley - 2
  2877         
  2877 
  2878         polygon = [wx.Point(left, top), wx.Point(angle_top, top),
  2878         polygon = [wx.Point(left, top), wx.Point(angle_top, top),
  2879                    wx.Point(right, angle_right), wx.Point(right, bottom),
  2879                    wx.Point(right, angle_right), wx.Point(right, bottom),
  2880                    wx.Point(left, bottom)]
  2880                    wx.Point(left, bottom)]
  2881         dc.DrawPolygon(polygon)
  2881         dc.DrawPolygon(polygon)
  2882         
  2882 
  2883         dc.SetLogicalFunction(wx.COPY)
  2883         dc.SetLogicalFunction(wx.COPY)
  2884         dc.SetUserScale(scalex, scaley)
  2884         dc.SetUserScale(scalex, scaley)
  2885         
  2885 
  2886     # Draws the comment and its content
  2886     # Draws the comment and its content
  2887     def Draw(self, dc):
  2887     def Draw(self, dc):
  2888         Graphic_Element.Draw(self, dc)
  2888         Graphic_Element.Draw(self, dc)
  2889         dc.SetPen(MiterPen(wx.BLACK))
  2889         dc.SetPen(MiterPen(wx.BLACK))
  2890         dc.SetBrush(wx.WHITE_BRUSH)
  2890         dc.SetBrush(wx.WHITE_BRUSH)
  2891         # Draws the comment shape
  2891         # Draws the comment shape
  2892         polygon = [wx.Point(self.Pos.x, self.Pos.y), 
  2892         polygon = [wx.Point(self.Pos.x, self.Pos.y),
  2893                    wx.Point(self.Pos.x + self.Size[0] - 10, self.Pos.y),
  2893                    wx.Point(self.Pos.x + self.Size[0] - 10, self.Pos.y),
  2894                    wx.Point(self.Pos.x + self.Size[0], self.Pos.y + 10),
  2894                    wx.Point(self.Pos.x + self.Size[0], self.Pos.y + 10),
  2895                    wx.Point(self.Pos.x + self.Size[0], self.Pos.y + self.Size[1]),
  2895                    wx.Point(self.Pos.x + self.Size[0], self.Pos.y + self.Size[1]),
  2896                    wx.Point(self.Pos.x, self.Pos.y + self.Size[1])]
  2896                    wx.Point(self.Pos.x, self.Pos.y + self.Size[1])]
  2897         dc.DrawPolygon(polygon)
  2897         dc.DrawPolygon(polygon)
  2949                     else:
  2949                     else:
  2950                         linetext = word
  2950                         linetext = word
  2951                     y += wordheight + 5
  2951                     y += wordheight + 5
  2952             if y + wordheight > self.Pos.y + self.Size[1] - 10:
  2952             if y + wordheight > self.Pos.y + self.Size[1] - 10:
  2953                 break
  2953                 break
  2954