graphics/GraphicCommons.py
changeset 1784 64beb9e9c749
parent 1782 5b6ad7a7fd9d
child 1828 396da88d7b5c
equal deleted inserted replaced
1729:31e63e25b4cc 1784:64beb9e9c749
    24 
    24 
    25 import wx
    25 import wx
    26 from math import *
    26 from math import *
    27 from types import *
    27 from types import *
    28 import datetime
    28 import datetime
    29 from threading import Lock,Timer
    29 from threading import Lock, Timer
    30 
    30 
    31 from graphics.ToolTipProducer import ToolTipProducer
    31 from graphics.ToolTipProducer import ToolTipProducer
    32 from graphics.DebugDataConsumer import DebugDataConsumer
    32 from graphics.DebugDataConsumer import DebugDataConsumer
    33 
    33 
    34 #-------------------------------------------------------------------------------
    34 # -------------------------------------------------------------------------------
    35 #                               Common constants
    35 #                               Common constants
    36 #-------------------------------------------------------------------------------
    36 # -------------------------------------------------------------------------------
    37 
    37 
    38 """
    38 """
    39 Definition of constants for dimensions of graphic elements
    39 Definition of constants for dimensions of graphic elements
    40 """
    40 """
    41 
    41 
    76 
    76 
    77 # Constants for defining the type of dragging that has been selected
    77 # Constants for defining the type of dragging that has been selected
    78 [HANDLE_MOVE, HANDLE_RESIZE, HANDLE_POINT, HANDLE_SEGMENT, HANDLE_CONNECTOR] = range(5)
    78 [HANDLE_MOVE, HANDLE_RESIZE, HANDLE_POINT, HANDLE_SEGMENT, HANDLE_CONNECTOR] = range(5)
    79 
    79 
    80 # List of value for resize handle that are valid
    80 # List of value for resize handle that are valid
    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 
   103 
   103 
   104 # Define highlight refresh inhibition period in second
   104 # Define highlight refresh inhibition period in second
   105 REFRESH_HIGHLIGHT_PERIOD = 0.1
   105 REFRESH_HIGHLIGHT_PERIOD = 0.1
   106 
   106 
   107 HANDLE_CURSORS = {
   107 HANDLE_CURSORS = {
   108     (1, 1) : 2,
   108     (1, 1): 2,
   109     (3, 3) : 2,
   109     (3, 3): 2,
   110     (1, 3) : 3,
   110     (1, 3): 3,
   111     (3, 1) : 3,
   111     (3, 1): 3,
   112     (1, 2) : 4,
   112     (1, 2): 4,
   113     (3, 2) : 4,
   113     (3, 2): 4,
   114     (2, 1) : 5,
   114     (2, 1): 5,
   115     (2, 3) : 5
   115     (2, 3): 5
   116 }
   116 }
       
   117 
   117 
   118 
   118 def round_scaling(x, n, constraint=0):
   119 def round_scaling(x, n, constraint=0):
   119     fraction = float(x) / float(n)
   120     fraction = float(x) / float(n)
   120     if constraint == -1:
   121     if constraint == -1:
   121         xround = int(fraction)
   122         xround = int(fraction)
   122     else:
   123     else:
   123         xround = round(fraction)
   124         xround = round(fraction)
   124         if constraint == 1 and xround < fraction:
   125         if constraint == 1 and xround < fraction:
   125             xround += 1 
   126             xround += 1
   126     return int(xround * n)
   127     return int(xround * n)
       
   128 
   127 
   129 
   128 """
   130 """
   129 Basic vector operations for calculate wire points
   131 Basic vector operations for calculate wire points
   130 """
   132 """
   131 
   133 
   132 # Create a vector from two points and define if vector must be normal
   134 
   133 def vector(p1, p2, normal = True):
   135 def vector(p1, p2, normal=True):
       
   136     """
       
   137     Create a vector from two points and define if vector must be normal
       
   138     """
   134     vector = (p2.x - p1.x, p2.y - p1.y)
   139     vector = (p2.x - p1.x, p2.y - p1.y)
   135     if normal:
   140     if normal:
   136         return normalize(vector)
   141         return normalize(vector)
   137     return vector
   142     return vector
   138 
   143 
   139 # Calculate the norm of a given vector
   144 
   140 def norm(v):
   145 def norm(v):
       
   146     """
       
   147     Calculate the norm of a given vector
       
   148     """
   141     return sqrt(v[0] * v[0] + v[1] * v[1])
   149     return sqrt(v[0] * v[0] + v[1] * v[1])
   142 
   150 
   143 # Normalize a given vector
   151 
   144 def normalize(v):
   152 def normalize(v):
       
   153     """
       
   154     Normalize a given vector
       
   155     """
   145     v_norm = norm(v)
   156     v_norm = norm(v)
   146     # Verifie if it is not a null vector
   157     # Verifie if it is not a null vector
   147     if v_norm > 0:
   158     if v_norm > 0:
   148         return (v[0] / v_norm, v[1] / v_norm)
   159         return (v[0] / v_norm, v[1] / v_norm)
   149     else:
   160     else:
   150         return v
   161         return v
   151 
   162 
   152 # Calculate the scalar product of two vectors
   163 
   153 def is_null_vector(v):
   164 def is_null_vector(v):
       
   165     """
       
   166     Calculate the scalar product of two vectors
       
   167     """
   154     return v == (0, 0)
   168     return v == (0, 0)
   155 
   169 
   156 # Calculate the scalar product of two vectors
   170 
   157 def add_vectors(v1, v2):
   171 def add_vectors(v1, v2):
       
   172     """
       
   173     Calculate the scalar product of two vectors
       
   174     """
   158     return (v1[0] + v2[0], v1[1] + v2[1])
   175     return (v1[0] + v2[0], v1[1] + v2[1])
   159 
   176 
   160 # Calculate the scalar product of two vectors
   177 
   161 def product(v1, v2):
   178 def product(v1, v2):
       
   179     """
       
   180     Calculate the scalar product of two vectors
       
   181     """
   162     return v1[0] * v2[0] + v1[1] * v2[1]
   182     return v1[0] * v2[0] + v1[1] * v2[1]
   163 
   183 
   164 
   184 
   165 """
       
   166 Function that calculates the nearest point of the grid defined by scaling for the given point
       
   167 """
       
   168 
       
   169 def GetScaledEventPosition(event, dc, scaling):
   185 def GetScaledEventPosition(event, dc, scaling):
       
   186     """
       
   187     Function that calculates the nearest point of the grid defined by scaling for the given point
       
   188     """
   170     pos = event.GetLogicalPosition(dc)
   189     pos = event.GetLogicalPosition(dc)
   171     if scaling:
   190     if scaling:
   172         pos.x = round(float(pos.x) / float(scaling[0])) * scaling[0]
   191         pos.x = round(float(pos.x) / float(scaling[0])) * scaling[0]
   173         pos.y = round(float(pos.y) / float(scaling[1])) * scaling[1]
   192         pos.y = round(float(pos.y) / float(scaling[1])) * scaling[1]
   174     return pos
   193     return pos
   175 
   194 
   176 
   195 
   177 """
       
   178 Function that choose a direction during the wire points generation
       
   179 """
       
   180 
       
   181 def DirectionChoice(v_base, v_target, dir_target):
   196 def DirectionChoice(v_base, v_target, dir_target):
       
   197     """
       
   198     Function that choose a direction during the wire points generation
       
   199     """
   182     dir_product = product(v_base, v_target)
   200     dir_product = product(v_base, v_target)
   183     if dir_product < 0:
   201     if dir_product < 0:
   184         return (-v_base[0], -v_base[1])
   202         return (-v_base[0], -v_base[1])
   185     elif dir_product == 0 and product(v_base, dir_target) != 0:
   203     elif dir_product == 0 and product(v_base, dir_target) != 0:
   186         return dir_target
   204         return dir_target
   187     return v_base
   205     return v_base
   188 
   206 
       
   207 
   189 def MiterPen(colour, width=1, style=wx.SOLID):
   208 def MiterPen(colour, width=1, style=wx.SOLID):
   190     pen = wx.Pen(colour, width, style)
   209     pen = wx.Pen(colour, width, style)
   191     pen.SetJoin(wx.JOIN_MITER)
   210     pen.SetJoin(wx.JOIN_MITER)
   192     pen.SetCap(wx.CAP_PROJECTING)
   211     pen.SetCap(wx.CAP_PROJECTING)
   193     return pen
   212     return pen
   194 
   213 
   195 #-------------------------------------------------------------------------------
   214 
       
   215 # -------------------------------------------------------------------------------
   196 #                    Helpers for highlighting text
   216 #                    Helpers for highlighting text
   197 #-------------------------------------------------------------------------------
   217 # -------------------------------------------------------------------------------
       
   218 
   198 
   219 
   199 def AddHighlight(highlights, infos):
   220 def AddHighlight(highlights, infos):
   200     RemoveHighlight(highlights, infos)
   221     RemoveHighlight(highlights, infos)
   201     highlights.append(infos)
   222     highlights.append(infos)
       
   223 
   202 
   224 
   203 def RemoveHighlight(highlights, infos):
   225 def RemoveHighlight(highlights, infos):
   204     if infos in highlights:
   226     if infos in highlights:
   205         highlights.remove(infos)
   227         highlights.remove(infos)
   206         return True
   228         return True
   207     return False
   229     return False
   208 
   230 
       
   231 
   209 def ClearHighlight(highlights, highlight_type=None):
   232 def ClearHighlight(highlights, highlight_type=None):
   210     if highlight_type is not None:
   233     if highlight_type is not None:
   211         return [highlight for highlight in highlights if highlight[2] != highlight_type]
   234         return [highlight for highlight in highlights if highlight[2] != highlight_type]
   212     return []
   235     return []
       
   236 
   213 
   237 
   214 def DrawHighlightedText(dc, text, highlights, x, y):
   238 def DrawHighlightedText(dc, text, highlights, x, y):
   215     current_pen = dc.GetPen()
   239     current_pen = dc.GetPen()
   216     dc.SetPen(wx.TRANSPARENT_PEN)
   240     dc.SetPen(wx.TRANSPARENT_PEN)
   217     for start, end, highlight_type in highlights:
   241     for start, end, highlight_type in highlights:
   222         dc.DrawRectangle(x + offset_width, y, part_width, part_height)
   246         dc.DrawRectangle(x + offset_width, y, part_width, part_height)
   223         dc.SetTextForeground(highlight_type[1])
   247         dc.SetTextForeground(highlight_type[1])
   224         dc.DrawText(part, x + offset_width, y)
   248         dc.DrawText(part, x + offset_width, y)
   225     dc.SetPen(current_pen)
   249     dc.SetPen(current_pen)
   226     dc.SetTextForeground(wx.BLACK)
   250     dc.SetTextForeground(wx.BLACK)
   227     
   251 
   228 #-------------------------------------------------------------------------------
   252 
       
   253 # -------------------------------------------------------------------------------
   229 #                           Graphic element base class
   254 #                           Graphic element base class
   230 #-------------------------------------------------------------------------------
   255 # -------------------------------------------------------------------------------
   231 
   256 
   232 """
       
   233 Class that implements a generic graphic element
       
   234 """
       
   235 
   257 
   236 class Graphic_Element(ToolTipProducer):
   258 class Graphic_Element(ToolTipProducer):
   237     
   259     """
       
   260     Class that implements a generic graphic element
       
   261     """
       
   262 
   238     # Create a new graphic element
   263     # Create a new graphic element
   239     def __init__(self, parent, id = None):
   264     def __init__(self, parent, id=None):
   240         ToolTipProducer.__init__(self, parent)
   265         ToolTipProducer.__init__(self, parent)
   241         self.Parent = parent
   266         self.Parent = parent
   242         self.Id = id
   267         self.Id = id
   243         self.oldPos = None
   268         self.oldPos = None
   244         self.StartPos = None
   269         self.StartPos = None
   245         self.CurrentDrag = None
   270         self.CurrentDrag = None
   246         self.Handle = (None,None)
   271         self.Handle = (None, None)
   247         self.Dragging = False
   272         self.Dragging = False
   248         self.Selected = False
   273         self.Selected = False
   249         self.Highlighted = False
   274         self.Highlighted = False
   250         self.Pos = wx.Point(0, 0)
   275         self.Pos = wx.Point(0, 0)
   251         self.Size = wx.Size(0, 0)
   276         self.Size = wx.Size(0, 0)
   252         self.BoundingBox = wx.Rect(0, 0, 0, 0)
   277         self.BoundingBox = wx.Rect(0, 0, 0, 0)
   253         self.Visible = False
   278         self.Visible = False
   254     
   279 
   255     def GetDefinition(self):
   280     def GetDefinition(self):
   256         return [self.Id], []
   281         return [self.Id], []
   257     
   282 
   258     def TestVisible(self, screen):
   283     def TestVisible(self, screen):
   259         self.Visible = self.Selected or self.GetRedrawRect().Intersects(screen)
   284         self.Visible = self.Selected or self.GetRedrawRect().Intersects(screen)
   260     
   285 
   261     def IsVisible(self):
   286     def IsVisible(self):
   262         return self.Visible
   287         return self.Visible
   263     
   288 
   264     def SpreadCurrent(self):
   289     def SpreadCurrent(self):
   265         pass
   290         pass
   266     
   291 
   267     def GetConnectorTranslation(self, element):
   292     def GetConnectorTranslation(self, element):
   268         return {}
   293         return {}
   269     
   294 
   270     def FindNearestConnector(self, position, connectors):
   295     def FindNearestConnector(self, position, connectors):
   271         distances = []
   296         distances = []
   272         for connector in connectors:
   297         for connector in connectors:
   273             connector_pos = connector.GetRelPosition()
   298             connector_pos = connector.GetRelPosition()
   274             distances.append((sqrt((self.Pos.x + connector_pos.x - position.x) ** 2 +
   299             distances.append((sqrt((self.Pos.x + connector_pos.x - position.x) ** 2 +
   276                               connector))
   301                               connector))
   277         distances.sort()
   302         distances.sort()
   278         if len(distances) > 0:
   303         if len(distances) > 0:
   279             return distances[0][1]
   304             return distances[0][1]
   280         return None
   305         return None
   281         
   306 
   282     def IsOfType(self, type, reference):
   307     def IsOfType(self, type, reference):
   283         return self.Parent.IsOfType(type, reference)
   308         return self.Parent.IsOfType(type, reference)
   284     
   309 
   285     def IsEndType(self, type):
   310     def IsEndType(self, type):
   286         return self.Parent.IsEndType(type)
   311         return self.Parent.IsEndType(type)
   287         
   312 
   288     def GetDragging(self):
   313     def GetDragging(self):
   289         return self.Dragging
   314         return self.Dragging
   290     
   315 
   291     # Make a clone of this element
   316     # Make a clone of this element
   292     def Clone(self, parent):
   317     def Clone(self, parent):
   293         return Graphic_Element(parent, self.Id)
   318         return Graphic_Element(parent, self.Id)
   294     
   319 
   295     # Changes the block position
   320     # Changes the block position
   296     def SetPosition(self, x, y):
   321     def SetPosition(self, x, y):
   297         self.Pos.x = x
   322         self.Pos.x = x
   298         self.Pos.y = y
   323         self.Pos.y = y
   299         self.RefreshConnected()
   324         self.RefreshConnected()
   300         self.RefreshBoundingBox()
   325         self.RefreshBoundingBox()
   301 
   326 
   302     # Returns the block position
   327     # Returns the block position
   303     def GetPosition(self):
   328     def GetPosition(self):
   304         return self.Pos.x, self.Pos.y
   329         return self.Pos.x, self.Pos.y
   305     
   330 
   306     # Changes the element size
   331     # Changes the element size
   307     def SetSize(self, width, height):
   332     def SetSize(self, width, height):
   308         self.Size.SetWidth(width)
   333         self.Size.SetWidth(width)
   309         self.Size.SetHeight(height)
   334         self.Size.SetHeight(height)
   310         self.RefreshConnectors()
   335         self.RefreshConnectors()
   311         self.RefreshBoundingBox()
   336         self.RefreshBoundingBox()
   312 
   337 
   313     # Returns the element size
   338     # Returns the element size
   314     def GetSize(self):
   339     def GetSize(self):
   315         return self.Size.GetWidth(), self.Size.GetHeight()
   340         return self.Size.GetWidth(), self.Size.GetHeight()
   316     
   341 
   317     # Returns the minimum element size
   342     # Returns the minimum element size
   318     def GetMinSize(self):
   343     def GetMinSize(self):
   319         return 0, 0
   344         return 0, 0
   320     
   345 
   321     # Set size of the element to the minimum size
   346     # Set size of the element to the minimum size
   322     def SetBestSize(self, scaling, x_factor=0.5, y_factor=0.5):
   347     def SetBestSize(self, scaling, x_factor=0.5, y_factor=0.5):
   323         width, height = self.GetSize()
   348         width, height = self.GetSize()
   324         posx, posy = self.GetPosition()
   349         posx, posy = self.GetPosition()
   325         min_width, min_height = self.GetMinSize()
   350         min_width, min_height = self.GetMinSize()
   334             self.Pos.y = round_scaling(self.Pos.y, scaling[1])
   359             self.Pos.y = round_scaling(self.Pos.y, scaling[1])
   335             width = round_scaling(width, scaling[0], 1)
   360             width = round_scaling(width, scaling[0], 1)
   336             height = round_scaling(height, scaling[1], 1)
   361             height = round_scaling(height, scaling[1], 1)
   337         self.SetSize(width, height)
   362         self.SetSize(width, height)
   338         return self.Pos.x - posx, self.Pos.y - posy
   363         return self.Pos.x - posx, self.Pos.y - posy
   339     
   364 
   340     # Refresh the element Bounding Box
   365     # Refresh the element Bounding Box
   341     def RefreshBoundingBox(self):
   366     def RefreshBoundingBox(self):
   342         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   367         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   343     
   368 
   344     # Refresh the element connectors position
   369     # Refresh the element connectors position
   345     def RefreshConnectors(self):
   370     def RefreshConnectors(self):
   346         pass
   371         pass
   347     
   372 
   348     # Refresh the position of wires connected to element inputs and outputs
   373     # Refresh the position of wires connected to element inputs and outputs
   349     def RefreshConnected(self):
   374     def RefreshConnected(self):
   350         pass
   375         pass
   351     
   376 
   352     # Change the parent
   377     # Change the parent
   353     def SetParent(self, parent):
   378     def SetParent(self, parent):
   354         self.Parent = parent
   379         self.Parent = parent
   355     
   380 
   356     # Override this method for defining the method to call for deleting this element
   381     # Override this method for defining the method to call for deleting this element
   357     def Delete(self):
   382     def Delete(self):
   358         pass
   383         pass
   359     
   384 
   360     # Returns the Id
   385     # Returns the Id
   361     def GetId(self):
   386     def GetId(self):
   362         return self.Id
   387         return self.Id
   363     
   388 
   364     # Returns if the point given is in the bounding box
   389     # Returns if the point given is in the bounding box
   365     def HitTest(self, pt, connectors=True):
   390     def HitTest(self, pt, connectors=True):
   366         if connectors:
   391         if connectors:
   367             rect = self.BoundingBox
   392             rect = self.BoundingBox
   368         else:
   393         else:
   369             rect = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   394             rect = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   370         return rect.InsideXY(pt.x, pt.y)
   395         return rect.InsideXY(pt.x, pt.y)
   371     
   396 
   372     # Returns if the point given is in the bounding box
   397     # Returns if the point given is in the bounding box
   373     def IsInSelection(self, rect):
   398     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)
   399         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     
   400 
   376     # Override this method for refreshing the bounding box
   401     # Override this method for refreshing the bounding box
   377     def RefreshBoundingBox(self):
   402     def RefreshBoundingBox(self):
   378         pass
   403         pass
   379     
   404 
   380     # Returns the bounding box
   405     # Returns the bounding box
   381     def GetBoundingBox(self):
   406     def GetBoundingBox(self):
   382         return self.BoundingBox
   407         return self.BoundingBox
   383     
   408 
   384     # Returns the RedrawRect
   409     # Returns the RedrawRect
   385     def GetRedrawRect(self, movex = 0, movey = 0):
   410     def GetRedrawRect(self, movex=0, movey=0):
   386         scalex, scaley = self.Parent.GetViewScale()
   411         scalex, scaley = self.Parent.GetViewScale()
   387         rect = wx.Rect()
   412         rect = wx.Rect()
   388         rect.x = self.BoundingBox.x - int(HANDLE_SIZE / scalex) - 3 - abs(movex)
   413         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)
   414         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
   415         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
   416         rect.height = self.BoundingBox.height + 2 * (int(HANDLE_SIZE / scaley) + abs(movey) + 1) + 4
   392         return rect
   417         return rect
   393     
   418 
   394     def Refresh(self, rect = None):
   419     def Refresh(self, rect=None):
   395         if self.Visible:
   420         if self.Visible:
   396             if rect is not None:
   421             if rect is not None:
   397                 self.Parent.RefreshRect(self.Parent.GetScrolledRect(rect), False)
   422                 self.Parent.RefreshRect(self.Parent.GetScrolledRect(rect), False)
   398             else:
   423             else:
   399                 self.Parent.RefreshRect(self.Parent.GetScrolledRect(self.GetRedrawRect()), False)
   424                 self.Parent.RefreshRect(self.Parent.GetScrolledRect(self.GetRedrawRect()), False)
   400     
   425 
   401     # Change the variable that indicates if this element is selected
   426     # Change the variable that indicates if this element is selected
   402     def SetSelected(self, selected):
   427     def SetSelected(self, selected):
   403         self.Selected = selected
   428         self.Selected = selected
   404         self.Refresh()
   429         self.Refresh()
   405     
   430 
   406     # Change the variable that indicates if this element is highlighted
   431     # Change the variable that indicates if this element is highlighted
   407     def SetHighlighted(self, highlighted):
   432     def SetHighlighted(self, highlighted):
   408         self.Highlighted = highlighted
   433         self.Highlighted = highlighted
   409         self.Refresh()
   434         self.Refresh()
   410     
   435 
   411     # Test if the point is on a handle of this element
   436     # Test if the point is on a handle of this element
   412     def TestHandle(self, event):
   437     def TestHandle(self, event):
   413         dc = self.Parent.GetLogicalDC()
   438         dc = self.Parent.GetLogicalDC()
   414         scalex, scaley = dc.GetUserScale()
   439         scalex, scaley = dc.GetUserScale()
   415         pos = event.GetPosition()
   440         pos = event.GetPosition()
   416         pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y))
   441         pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y))
   417         
   442 
   418         left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   443         left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   419         center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
   444         center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
   420         right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   445         right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   421         
   446 
   422         top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   447         top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   423         middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
   448         middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
   424         bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   449         bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   425         
   450 
   426         extern_rect = wx.Rect(left, top, right + HANDLE_SIZE - left, bottom + HANDLE_SIZE - top)
   451         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)
   452         intern_rect = wx.Rect(left + HANDLE_SIZE, top + HANDLE_SIZE, right - left - HANDLE_SIZE, bottom - top - HANDLE_SIZE)
   428         
   453 
   429         # Verify that this element is selected
   454         # 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):
   455         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
   456             # Find if point is on a handle horizontally
   432             if left <= pt.x < left + HANDLE_SIZE:
   457             if left <= pt.x < left + HANDLE_SIZE:
   433                 handle_x = 1
   458                 handle_x = 1
   448                 handle_y = 0
   473                 handle_y = 0
   449             # Verify that the result is valid
   474             # Verify that the result is valid
   450             if (handle_x, handle_y) in VALID_HANDLES:
   475             if (handle_x, handle_y) in VALID_HANDLES:
   451                 return handle_x, handle_y
   476                 return handle_x, handle_y
   452         return 0, 0
   477         return 0, 0
   453     
   478 
   454     # Method called when a LeftDown event have been generated
   479     # Method called when a LeftDown event have been generated
   455     def OnLeftDown(self, event, dc, scaling):
   480     def OnLeftDown(self, event, dc, scaling):
   456         pos = event.GetLogicalPosition(dc)
   481         pos = event.GetLogicalPosition(dc)
   457         # Test if an handle have been clicked
   482         # Test if an handle have been clicked
   458         handle = self.TestHandle(event)
   483         handle = self.TestHandle(event)
   467             self.SetSelected(False)
   492             self.SetSelected(False)
   468         # Initializes the last position
   493         # Initializes the last position
   469         self.oldPos = GetScaledEventPosition(event, dc, scaling)
   494         self.oldPos = GetScaledEventPosition(event, dc, scaling)
   470         self.StartPos = wx.Point(self.Pos.x, self.Pos.y)
   495         self.StartPos = wx.Point(self.Pos.x, self.Pos.y)
   471         self.CurrentDrag = wx.Point(0, 0)
   496         self.CurrentDrag = wx.Point(0, 0)
   472     
   497 
   473     # Method called when a LeftUp event have been generated
   498     # Method called when a LeftUp event have been generated
   474     def OnLeftUp(self, event, dc, scaling):
   499     def OnLeftUp(self, event, dc, scaling):
   475         # If a dragging have been initiated
   500         # If a dragging have been initiated
   476         if self.Dragging and self.oldPos:
   501         if self.Dragging and self.oldPos:
   477             self.RefreshModel()
   502             self.RefreshModel()
   496             self.Parent.PopupForceMenu()
   521             self.Parent.PopupForceMenu()
   497 
   522 
   498     # Method called when a LeftDClick event have been generated
   523     # Method called when a LeftDClick event have been generated
   499     def OnLeftDClick(self, event, dc, scaling):
   524     def OnLeftDClick(self, event, dc, scaling):
   500         pass
   525         pass
   501     
   526 
   502     # Method called when a Motion event have been generated
   527     # Method called when a Motion event have been generated
   503     def OnMotion(self, event, dc, scaling):
   528     def OnMotion(self, event, dc, scaling):
   504         # If the cursor is dragging and the element have been clicked
   529         # If the cursor is dragging and the element have been clicked
   505         if event.Dragging() and self.oldPos:
   530         if event.Dragging() and self.oldPos:
   506             # Calculate the movement of cursor
   531             # Calculate the movement of cursor
   530             cursor = HANDLE_CURSORS.get(handle, 0)
   555             cursor = HANDLE_CURSORS.get(handle, 0)
   531             wx.CallAfter(self.Parent.SetCurrentCursor, cursor)
   556             wx.CallAfter(self.Parent.SetCurrentCursor, cursor)
   532             return 0, 0
   557             return 0, 0
   533 
   558 
   534     # Moves the element
   559     # Moves the element
   535     def Move(self, dx, dy, exclude = []):
   560     def Move(self, dx, dy, exclude=[]):
   536         self.Pos.x += max(-self.BoundingBox.x, dx)
   561         self.Pos.x += max(-self.BoundingBox.x, dx)
   537         self.Pos.y += max(-self.BoundingBox.y, dy)
   562         self.Pos.y += max(-self.BoundingBox.y, dy)
   538         self.RefreshConnected(exclude)
   563         self.RefreshConnected(exclude)
   539         self.RefreshBoundingBox()
   564         self.RefreshBoundingBox()
   540     
   565 
   541     # Resizes the element from position and size given
   566     # Resizes the element from position and size given
   542     def Resize(self, x, y, width, height):
   567     def Resize(self, x, y, width, height):
   543         self.Move(x, y)
   568         self.Move(x, y)
   544         self.SetSize(width, height)
   569         self.SetSize(width, height)
   545     
   570 
   546     # Refreshes the element state according to move defined and handle selected
   571     # 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):
   572     def ProcessDragging(self, movex, movey, event, scaling, width_fac=1, height_fac=1):
   548         handle_type, handle = self.Handle
   573         handle_type, handle = self.Handle
   549         # If it is a resize handle, calculate the values from resizing
   574         # If it is a resize handle, calculate the values from resizing
   550         if handle_type == HANDLE_RESIZE:
   575         if handle_type == HANDLE_RESIZE:
   551             if scaling is not None:
   576             if scaling is not None:
   552                 scaling = (scaling[0] * width_fac, scaling[1] * height_fac)
   577                 scaling = (scaling[0] * width_fac, scaling[1] * height_fac)
   616                 if abs(self.CurrentDrag.x) > abs(self.CurrentDrag.y):
   641                 if abs(self.CurrentDrag.x) > abs(self.CurrentDrag.y):
   617                     movex = self.StartPos.x + self.CurrentDrag.x - self.Pos.x
   642                     movex = self.StartPos.x + self.CurrentDrag.x - self.Pos.x
   618                     movey = self.StartPos.y - self.Pos.y
   643                     movey = self.StartPos.y - self.Pos.y
   619                 else:
   644                 else:
   620                     movex = self.StartPos.x - self.Pos.x
   645                     movex = self.StartPos.x - self.Pos.x
   621                     movey = self.StartPos.y + self.CurrentDrag.y - self.Pos.y   
   646                     movey = self.StartPos.y + self.CurrentDrag.y - self.Pos.y
   622             self.Move(movex, movey)
   647             self.Move(movex, movey)
   623             return movex, movey
   648             return movex, movey
   624         return 0, 0
   649         return 0, 0
   625     
   650 
   626     # Override this method for defining the method to call for adding an highlight to this element
   651     # 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):
   652     def AddHighlight(self, infos, start, end, highlight_type):
   628         pass
   653         pass
   629     
   654 
   630     # Override this method for defining the method to call for removing an highlight from this element
   655     # 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):
   656     def RemoveHighlight(self, infos, start, end, highlight_type):
   632         pass
   657         pass
   633     
   658 
   634     # Override this method for defining the method to call for removing all the highlights of one particular type from this element
   659     # 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):
   660     def ClearHighlight(self, highlight_type=None):
   636         pass
   661         pass
   637     
   662 
   638     # Override this method for defining the method to call for refreshing the model of this element
   663     # Override this method for defining the method to call for refreshing the model of this element
   639     def RefreshModel(self, move=True):
   664     def RefreshModel(self, move=True):
   640         pass
   665         pass
   641     
   666 
   642     # Draws the highlightment of this element if it is highlighted (can be overwritten)
   667     # Draws the highlightment of this element if it is highlighted (can be overwritten)
   643     def DrawHighlightment(self, dc):
   668     def DrawHighlightment(self, dc):
   644         scalex, scaley = dc.GetUserScale()
   669         scalex, scaley = dc.GetUserScale()
   645         dc.SetUserScale(1, 1)
   670         dc.SetUserScale(1, 1)
   646         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
   671         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
   647         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
   672         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
   648         dc.SetLogicalFunction(wx.AND)
   673         dc.SetLogicalFunction(wx.AND)
   649         dc.DrawRectangle(int(round((self.Pos.x - 1) * scalex)) - 2, 
   674         dc.DrawRectangle(int(round((self.Pos.x - 1) * scalex)) - 2,
   650                          int(round((self.Pos.y - 1) * scaley)) - 2, 
   675                          int(round((self.Pos.y - 1) * scaley)) - 2,
   651                          int(round((self.Size.width + 3) * scalex)) + 5, 
   676                          int(round((self.Size.width + 3) * scalex)) + 5,
   652                          int(round((self.Size.height + 3) * scaley)) + 5)
   677                          int(round((self.Size.height + 3) * scaley)) + 5)
   653         dc.SetLogicalFunction(wx.COPY)
   678         dc.SetLogicalFunction(wx.COPY)
   654         dc.SetUserScale(scalex, scaley)
   679         dc.SetUserScale(scalex, scaley)
   655     
   680 
   656     # Draws the handles of this element if it is selected
   681     # Draws the handles of this element if it is selected
   657     def Draw(self, dc):
   682     def Draw(self, dc):
   658         if not getattr(dc, "printing", False):
   683         if not getattr(dc, "printing", False):
   659             if self.Highlighted:
   684             if self.Highlighted:
   660                 self.DrawHighlightment(dc)
   685                 self.DrawHighlightment(dc)
   661             if self.Selected:
   686             if self.Selected:
   662                 scalex, scaley = dc.GetUserScale()
   687                 scalex, scaley = dc.GetUserScale()
   663                 dc.SetUserScale(1, 1)
   688                 dc.SetUserScale(1, 1)
   664                 dc.SetPen(MiterPen(wx.BLACK))
   689                 dc.SetPen(MiterPen(wx.BLACK))
   665                 dc.SetBrush(wx.BLACK_BRUSH)
   690                 dc.SetBrush(wx.BLACK_BRUSH)
   666                 
   691 
   667                 left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   692                 left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   668                 center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
   693                 center = (self.BoundingBox.x + self.BoundingBox.width / 2) * scalex - HANDLE_SIZE / 2
   669                 right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   694                 right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   670                 
   695 
   671                 top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   696                 top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   672                 middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
   697                 middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE / 2
   673                 bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   698                 bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   674                 
   699 
   675                 for x, y in [(left, top), (center, top), (right, top),
   700                 for x, y in [(left, top), (center, top), (right, top),
   676                              (left, middle), (right, middle),
   701                              (left, middle), (right, middle),
   677                              (left, bottom), (center, bottom), (right, bottom)]:
   702                              (left, bottom), (center, bottom), (right, bottom)]:
   678                     dc.DrawRectangle(x, y, HANDLE_SIZE, HANDLE_SIZE)
   703                     dc.DrawRectangle(x, y, HANDLE_SIZE, HANDLE_SIZE)
   679                 
   704 
   680                 dc.SetUserScale(scalex, scaley)
   705                 dc.SetUserScale(scalex, scaley)
   681 
   706 
   682 
   707 
   683 #-------------------------------------------------------------------------------
   708 # -------------------------------------------------------------------------------
   684 #                           Group of graphic elements
   709 #                           Group of graphic elements
   685 #-------------------------------------------------------------------------------
   710 # -------------------------------------------------------------------------------
   686 
   711 
   687 """
       
   688 Class that implements a group of graphic elements
       
   689 """
       
   690 
   712 
   691 class Graphic_Group(Graphic_Element):
   713 class Graphic_Group(Graphic_Element):
   692     
   714     """
       
   715     Class that implements a group of graphic elements
       
   716     """
       
   717 
   693     # Create a new group of graphic elements
   718     # Create a new group of graphic elements
   694     def __init__(self, parent):
   719     def __init__(self, parent):
   695         Graphic_Element.__init__(self, parent)
   720         Graphic_Element.__init__(self, parent)
   696         self.Elements = []
   721         self.Elements = []
   697         self.RefreshWireExclusion()
   722         self.RefreshWireExclusion()
   698         self.RefreshBoundingBox()
   723         self.RefreshBoundingBox()
   699     
   724 
   700     # Destructor
   725     # Destructor
   701     def __del__(self):
   726     def __del__(self):
   702         self.Elements = []
   727         self.Elements = []
   703     
   728 
   704     def GetDefinition(self):
   729     def GetDefinition(self):
   705         blocks = [] 
   730         blocks = []
   706         wires = []
   731         wires = []
   707         for element in self.Elements:
   732         for element in self.Elements:
   708             block, wire = element.GetDefinition()
   733             block, wire = element.GetDefinition()
   709             blocks.extend(block)
   734             blocks.extend(block)
   710             wires.extend(wire)
   735             wires.extend(wire)
   711         return blocks, wires
   736         return blocks, wires
   712     
   737 
   713     # Make a clone of this element
   738     # Make a clone of this element
   714     def Clone(self, parent, pos = None):
   739     def Clone(self, parent, pos=None):
   715         group = Graphic_Group(parent)
   740         group = Graphic_Group(parent)
   716         connectors = {}
   741         connectors = {}
   717         exclude_names = {}
   742         exclude_names = {}
   718         wires = []
   743         wires = []
   719         if pos is not None:
   744         if pos is not None:
   727                     new_pos = wx.Point(x + dx, y + dy)
   752                     new_pos = wx.Point(x + dx, y + dy)
   728                     newid = parent.GetNewId()
   753                     newid = parent.GetNewId()
   729                     if parent.IsNamedElement(element):
   754                     if parent.IsNamedElement(element):
   730                         name = parent.GenerateNewName(element, exclude_names)
   755                         name = parent.GenerateNewName(element, exclude_names)
   731                         exclude_names[name.upper()] = True
   756                         exclude_names[name.upper()] = True
   732                         new_element = element.Clone(parent, newid, name, pos = new_pos)
   757                         new_element = element.Clone(parent, newid, name, pos=new_pos)
   733                     else:
   758                     else:
   734                         new_element = element.Clone(parent, newid, pos = new_pos)
   759                         new_element = element.Clone(parent, newid, pos=new_pos)
   735                     new_element.SetBestSize(parent.Scaling)
   760                     new_element.SetBestSize(parent.Scaling)
   736                 else:
   761                 else:
   737                     new_element = element.Clone(parent)
   762                     new_element = element.Clone(parent)
   738                 connectors.update(element.GetConnectorTranslation(new_element))
   763                 connectors.update(element.GetConnectorTranslation(new_element))
   739                 group.SelectElement(new_element)
   764                 group.SelectElement(new_element)
   749         if pos is not None:
   774         if pos is not None:
   750             for element in group.Elements:
   775             for element in group.Elements:
   751                 if not isinstance(element, Wire):
   776                 if not isinstance(element, Wire):
   752                     parent.AddBlockInModel(element)
   777                     parent.AddBlockInModel(element)
   753         return group
   778         return group
   754     
   779 
   755     def CanAddBlocks(self, parent):
   780     def CanAddBlocks(self, parent):
   756         valid = True
   781         valid = True
   757         for element in self.Elements:
   782         for element in self.Elements:
   758             if not isinstance(element, Wire):
   783             if not isinstance(element, Wire):
   759                 valid &= parent.CanAddElement(element)
   784                 valid &= parent.CanAddElement(element)
   760         return valid
   785         return valid
   761     
   786 
   762     def IsVisible(self):
   787     def IsVisible(self):
   763         for element in self.Elements:
   788         for element in self.Elements:
   764             if element.IsVisible():
   789             if element.IsVisible():
   765                 return True
   790                 return True
   766         return False
   791         return False
   767     
   792 
   768     # Refresh the list of wire excluded
   793     # Refresh the list of wire excluded
   769     def RefreshWireExclusion(self):
   794     def RefreshWireExclusion(self):
   770         self.WireExcluded = []
   795         self.WireExcluded = []
   771         for element in self.Elements:
   796         for element in self.Elements:
   772             if isinstance(element, Wire):
   797             if isinstance(element, Wire):
   773                 startblock = element.StartConnected.GetParentBlock()
   798                 startblock = element.StartConnected.GetParentBlock()
   774                 endblock = element.EndConnected.GetParentBlock()
   799                 endblock = element.EndConnected.GetParentBlock()
   775                 if startblock in self.Elements and endblock in self.Elements:
   800                 if startblock in self.Elements and endblock in self.Elements:
   776                     self.WireExcluded.append(element)
   801                     self.WireExcluded.append(element)
   777     
   802 
   778     # Returns the RedrawRect
   803     # Returns the RedrawRect
   779     def GetRedrawRect(self, movex = 0, movey = 0):
   804     def GetRedrawRect(self, movex=0, movey=0):
   780         rect = None
   805         rect = None
   781         for element in self.Elements:
   806         for element in self.Elements:
   782             if rect is None:
   807             if rect is None:
   783                 rect = element.GetRedrawRect(movex, movey)
   808                 rect = element.GetRedrawRect(movex, movey)
   784             else:
   809             else:
   785                 rect = rect.Union(element.GetRedrawRect(movex, movey))
   810                 rect = rect.Union(element.GetRedrawRect(movex, movey))
   786         return rect
   811         return rect
   787     
   812 
   788     # Clean this group of elements
   813     # Clean this group of elements
   789     def Clean(self):
   814     def Clean(self):
   790         # Clean all the elements of the group
   815         # Clean all the elements of the group
   791         for element in self.Elements:
   816         for element in self.Elements:
   792             element.Clean()
   817             element.Clean()
   793     
   818 
   794     # Delete this group of elements
   819     # Delete this group of elements
   795     def Delete(self):
   820     def Delete(self):
   796         # Delete all the elements of the group
   821         # Delete all the elements of the group
   797         for element in self.Elements:
   822         for element in self.Elements:
   798             element.Delete()
   823             element.Delete()
   799         self.WireExcluded = []
   824         self.WireExcluded = []
   800     
   825 
   801     # Returns if the point given is in the bounding box of one of the elements of this group
   826     # 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):
   827     def HitTest(self, pt, connectors=True):
   803         result = False
   828         result = False
   804         for element in self.Elements:
   829         for element in self.Elements:
   805             result |= element.HitTest(pt, connectors)
   830             result |= element.HitTest(pt, connectors)
   806         return result
   831         return result
   807     
   832 
   808     # Returns if the element given is in this group
   833     # Returns if the element given is in this group
   809     def IsElementIn(self, element):
   834     def IsElementIn(self, element):
   810         return element in self.Elements
   835         return element in self.Elements
   811     
   836 
   812     # Change the elements of the group
   837     # Change the elements of the group
   813     def SetElements(self, elements):
   838     def SetElements(self, elements):
   814         self.Elements = elements
   839         self.Elements = elements
   815         self.RefreshWireExclusion()
   840         self.RefreshWireExclusion()
   816         self.RefreshBoundingBox()
   841         self.RefreshBoundingBox()
   817     
   842 
   818     # Returns the elements of the group
   843     # Returns the elements of the group
   819     def GetElements(self):
   844     def GetElements(self):
   820         return self.Elements
   845         return self.Elements
   821     
   846 
   822     # Align the group elements
   847     # Align the group elements
   823     def AlignElements(self, horizontally, vertically):
   848     def AlignElements(self, horizontally, vertically):
   824         minx = self.BoundingBox.x + self.BoundingBox.width
   849         minx = self.BoundingBox.x + self.BoundingBox.width
   825         miny = self.BoundingBox.y + self.BoundingBox.height
   850         miny = self.BoundingBox.y + self.BoundingBox.height
   826         maxx = self.BoundingBox.x
   851         maxx = self.BoundingBox.x
   852                     movey = maxy - height - posy
   877                     movey = maxy - height - posy
   853                 if movex != 0 or movey != 0:
   878                 if movex != 0 or movey != 0:
   854                     element.Move(movex, movey)
   879                     element.Move(movex, movey)
   855                     element.RefreshModel()
   880                     element.RefreshModel()
   856         self.RefreshBoundingBox()
   881         self.RefreshBoundingBox()
   857     
   882 
   858     # Add the given element to the group of elements
   883     # Add the given element to the group of elements
   859     def AddElement(self, element):
   884     def AddElement(self, element):
   860         self.Elements.append(element)
   885         self.Elements.append(element)
   861         
   886 
   862     # Remove or select the given element if it is or not in the group
   887     # Remove or select the given element if it is or not in the group
   863     def SelectElement(self, element):
   888     def SelectElement(self, element):
   864         if element in self.Elements:
   889         if element in self.Elements:
   865             self.Elements.remove(element)
   890             self.Elements.remove(element)
   866         else:
   891         else:
   867             self.Elements.append(element)
   892             self.Elements.append(element)
   868         self.RefreshWireExclusion()
   893         self.RefreshWireExclusion()
   869         self.RefreshBoundingBox()
   894         self.RefreshBoundingBox()
   870     
   895 
   871     # Move this group of elements
   896     # Move this group of elements
   872     def Move(self, movex, movey):
   897     def Move(self, movex, movey):
   873         movex = max(-self.BoundingBox.x, movex)
   898         movex = max(-self.BoundingBox.x, movex)
   874         movey = max(-self.BoundingBox.y, movey)
   899         movey = max(-self.BoundingBox.y, movey)
   875         # Move all the elements of the group
   900         # Move all the elements of the group
   877             if not isinstance(element, Wire):
   902             if not isinstance(element, Wire):
   878                 element.Move(movex, movey, self.WireExcluded)
   903                 element.Move(movex, movey, self.WireExcluded)
   879             elif element in self.WireExcluded:
   904             elif element in self.WireExcluded:
   880                 element.Move(movex, movey, True)
   905                 element.Move(movex, movey, True)
   881         self.RefreshBoundingBox()
   906         self.RefreshBoundingBox()
   882     
   907 
   883     # Refreshes the bounding box of this group of elements
   908     # Refreshes the bounding box of this group of elements
   884     def RefreshBoundingBox(self):
   909     def RefreshBoundingBox(self):
   885         if len(self.Elements) > 0:
   910         if len(self.Elements) > 0:
   886             bbox = self.Elements[0].GetBoundingBox()
   911             bbox = self.Elements[0].GetBoundingBox()
   887             minx, miny = bbox.x, bbox.y
   912             minx, miny = bbox.x, bbox.y
   900         self.Size = wx.Size(self.BoundingBox.width, self.BoundingBox.height)
   925         self.Size = wx.Size(self.BoundingBox.width, self.BoundingBox.height)
   901 
   926 
   902     # Forbids to change the group position
   927     # Forbids to change the group position
   903     def SetPosition(x, y):
   928     def SetPosition(x, y):
   904         pass
   929         pass
   905     
   930 
   906     # Returns the position of this group
   931     # Returns the position of this group
   907     def GetPosition(self, exclude_wires=False):
   932     def GetPosition(self, exclude_wires=False):
   908         if exclude_wires:
   933         if exclude_wires:
   909             posx = posy = None
   934             posx = posy = None
   910             for element in self.Elements:
   935             for element in self.Elements:
   917                         posy = min(posy, bbox.y)
   942                         posy = min(posy, bbox.y)
   918             if posx is None and posy is None:
   943             if posx is None and posy is None:
   919                 return 0, 0
   944                 return 0, 0
   920             return posx, posy
   945             return posx, posy
   921         return self.BoundingBox.x, self.BoundingBox.y
   946         return self.BoundingBox.x, self.BoundingBox.y
   922     
   947 
   923     # Forbids to change the group size
   948     # Forbids to change the group size
   924     def SetSize(width, height):
   949     def SetSize(width, height):
   925         pass
   950         pass
   926     
   951 
   927     # Returns the size of this group
   952     # Returns the size of this group
   928     def GetSize(self):
   953     def GetSize(self):
   929         return self.BoundingBox.width, self.BoundingBox.height
   954         return self.BoundingBox.width, self.BoundingBox.height
   930     
   955 
   931     # Set size of the group elements to their minimum size
   956     # Set size of the group elements to their minimum size
   932     def SetBestSize(self, scaling):
   957     def SetBestSize(self, scaling):
   933         max_movex = max_movey = 0
   958         max_movex = max_movey = 0
   934         for element in self.Elements:
   959         for element in self.Elements:
   935             movex, movey = element.SetBestSize(scaling)
   960             movex, movey = element.SetBestSize(scaling)
   936             max_movex = max(max_movex, movex)
   961             max_movex = max(max_movex, movex)
   937             max_movey = max(max_movey, movey)
   962             max_movey = max(max_movey, movey)
   938         return max_movex, max_movey
   963         return max_movex, max_movey
   939     
   964 
   940     # Refreshes the group elements to move defined and handle selected
   965     # Refreshes the group elements to move defined and handle selected
   941     def ProcessDragging(self, movex, movey, event, scaling):
   966     def ProcessDragging(self, movex, movey, event, scaling):
   942         handle_type, handle = self.Handle
   967         handle_type, handle = self.Handle
   943         # If it is a move handle, Move this group elements
   968         # If it is a move handle, Move this group elements
   944         if handle_type == HANDLE_MOVE:
   969         if handle_type == HANDLE_MOVE:
   958                     movex = self.StartPos.x - posx
   983                     movex = self.StartPos.x - posx
   959                     movey = self.StartPos.y + self.CurrentDrag.y - posy
   984                     movey = self.StartPos.y + self.CurrentDrag.y - posy
   960             self.Move(movex, movey)
   985             self.Move(movex, movey)
   961             return movex, movey
   986             return movex, movey
   962         return 0, 0
   987         return 0, 0
   963     
   988 
   964     # Change the variable that indicates if this element is highlighted
   989     # Change the variable that indicates if this element is highlighted
   965     def SetHighlighted(self, highlighted):
   990     def SetHighlighted(self, highlighted):
   966         for element in self.Elements:
   991         for element in self.Elements:
   967             element.SetHighlighted(highlighted)
   992             element.SetHighlighted(highlighted)
   968     
   993 
   969     def HighlightPoint(self, pos):
   994     def HighlightPoint(self, pos):
   970         for element in self.Elements:
   995         for element in self.Elements:
   971             if isinstance(element, Wire):
   996             if isinstance(element, Wire):
   972                 element.HighlightPoint(pos)
   997                 element.HighlightPoint(pos)
   973     
   998 
   974     # Method called when a LeftDown event have been generated
   999     # Method called when a LeftDown event have been generated
   975     def OnLeftDown(self, event, dc, scaling):
  1000     def OnLeftDown(self, event, dc, scaling):
   976         Graphic_Element.OnLeftDown(self, event, dc, scaling)
  1001         Graphic_Element.OnLeftDown(self, event, dc, scaling)
   977         self.StartPos = wx.Point(*self.GetPosition(True))
  1002         self.StartPos = wx.Point(*self.GetPosition(True))
   978         for element in self.Elements:
  1003         for element in self.Elements:
   996     # Draws the handles of this element if it is selected
  1021     # Draws the handles of this element if it is selected
   997     def Draw(self, dc):
  1022     def Draw(self, dc):
   998         for element in self.Elements:
  1023         for element in self.Elements:
   999             element.Draw(dc)
  1024             element.Draw(dc)
  1000 
  1025 
  1001 #-------------------------------------------------------------------------------
  1026 
       
  1027 # -------------------------------------------------------------------------------
  1002 #                         Connector for all types of blocks
  1028 #                         Connector for all types of blocks
  1003 #-------------------------------------------------------------------------------
  1029 # -------------------------------------------------------------------------------
  1004 
  1030 
  1005 """
       
  1006 Class that implements a connector for any type of block
       
  1007 """
       
  1008 
  1031 
  1009 class Connector(DebugDataConsumer, ToolTipProducer):
  1032 class Connector(DebugDataConsumer, ToolTipProducer):
  1010     
  1033     """
       
  1034     Class that implements a connector for any type of block
       
  1035     """
       
  1036 
  1011     # Create a new connector
  1037     # Create a new connector
  1012     def __init__(self, parent, name, type, position, direction, negated = False, edge = "none", onlyone = False):
  1038     def __init__(self, parent, name, type, position, direction, negated=False, edge="none", onlyone=False):
  1013         DebugDataConsumer.__init__(self)
  1039         DebugDataConsumer.__init__(self)
  1014         ToolTipProducer.__init__(self, parent.Parent)
  1040         ToolTipProducer.__init__(self, parent.Parent)
  1015         self.ParentBlock = parent
  1041         self.ParentBlock = parent
  1016         self.Name = name
  1042         self.Name = name
  1017         self.Type = type
  1043         self.Type = type
  1031         self.ValueSize = None
  1057         self.ValueSize = None
  1032         self.ComputedValue = None
  1058         self.ComputedValue = None
  1033         self.Selected = False
  1059         self.Selected = False
  1034         self.Highlights = []
  1060         self.Highlights = []
  1035         self.RefreshNameSize()
  1061         self.RefreshNameSize()
  1036     
  1062 
  1037     def Flush(self):
  1063     def Flush(self):
  1038         self.ParentBlock = None
  1064         self.ParentBlock = None
  1039         for wire, handle in self.Wires:
  1065         for wire, handle in self.Wires:
  1040             wire.Flush()
  1066             wire.Flush()
  1041         self.Wires = []
  1067         self.Wires = []
  1042     
  1068 
  1043     # Returns the RedrawRect
  1069     # Returns the RedrawRect
  1044     def GetRedrawRect(self, movex = 0, movey = 0):
  1070     def GetRedrawRect(self, movex=0, movey=0):
  1045         parent_pos = self.ParentBlock.GetPosition()
  1071         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)
  1072         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)
  1073         y = min(parent_pos[1] + self.Pos.y, parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE)
  1048         has_modifier = self.Negated or self.Edge != "none"
  1074         has_modifier = self.Negated or self.Edge != "none"
  1049         if self.Direction[0] == 0:
  1075         if self.Direction[0] == 0:
  1058         else:
  1084         else:
  1059             height = CONNECTOR_SIZE
  1085             height = CONNECTOR_SIZE
  1060             if self.Edge == "rising" and self.Direction[1] == 1:
  1086             if self.Edge == "rising" and self.Direction[1] == 1:
  1061                 y -= 5
  1087                 y -= 5
  1062                 height += 5
  1088                 height += 5
  1063         rect =  wx.Rect(x - abs(movex), y - abs(movey), width + 2 * abs(movex), height + 2 * abs(movey))
  1089         rect = wx.Rect(x - abs(movex), y - abs(movey), width + 2 * abs(movex), height + 2 * abs(movey))
  1064         if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
  1090         if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
  1065             self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue)
  1091             self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue)
  1066         if self.ValueSize is not None:
  1092         if self.ValueSize is not None:
  1067             width, height = self.ValueSize
  1093             width, height = self.ValueSize
  1068             rect = rect.Union(wx.Rect(
  1094             rect = rect.Union(
  1069                     parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] + \
  1095                 wx.Rect(
  1070                                     width * (self.Direction[0] - 1) / 2,
  1096                     parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] +
  1071                     parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] + \
  1097                     width * (self.Direction[0] - 1) / 2,
  1072                                     height * (self.Direction[1] - 1),
  1098                     parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] +
       
  1099                     height * (self.Direction[1] - 1),
  1073                     width, height))
  1100                     width, height))
  1074         return rect
  1101         return rect
  1075     
  1102 
  1076     # Change the connector selection
  1103     # Change the connector selection
  1077     def SetSelected(self, selected):
  1104     def SetSelected(self, selected):
  1078         self.Selected = selected
  1105         self.Selected = selected
  1079     
  1106 
  1080     # Make a clone of the connector
  1107     # Make a clone of the connector
  1081     def Clone(self, parent = None):
  1108     def Clone(self, parent=None):
  1082         if parent is None:
  1109         if parent is None:
  1083             parent = self.ParentBlock
  1110             parent = self.ParentBlock
  1084         return Connector(parent, self.Name, self.Type, wx.Point(self.Pos[0], self.Pos[1]),
  1111         return Connector(parent, self.Name, self.Type, wx.Point(self.Pos[0], self.Pos[1]),
  1085                 self.Direction, self.Negated)
  1112                          self.Direction, self.Negated)
  1086     
  1113 
  1087     # Returns the connector parent block
  1114     # Returns the connector parent block
  1088     def GetParentBlock(self):
  1115     def GetParentBlock(self):
  1089         return self.ParentBlock
  1116         return self.ParentBlock
  1090     
  1117 
  1091     # Returns the connector type
  1118     # Returns the connector type
  1092     def GetType(self, raw = False):
  1119     def GetType(self, raw=False):
  1093         if self.ParentBlock.IsEndType(self.Type) or raw:
  1120         if self.ParentBlock.IsEndType(self.Type) or raw:
  1094             return self.Type
  1121             return self.Type
  1095         elif (self.Negated or self.Edge != "none") and self.ParentBlock.IsOfType("BOOL", self.Type):
  1122         elif (self.Negated or self.Edge != "none") and self.ParentBlock.IsOfType("BOOL", self.Type):
  1096             return "BOOL"
  1123             return "BOOL"
  1097         else:
  1124         else:
  1098             return self.ParentBlock.GetConnectionResultType(self, self.Type)
  1125             return self.ParentBlock.GetConnectionResultType(self, self.Type)
  1099     
  1126 
  1100     # Returns the connector type
  1127     # Returns the connector type
  1101     def GetConnectedType(self):
  1128     def GetConnectedType(self):
  1102         if self.ParentBlock.IsEndType(self.Type):
  1129         if self.ParentBlock.IsEndType(self.Type):
  1103             return self.Type
  1130             return self.Type
  1104         elif len(self.Wires) == 1:
  1131         elif len(self.Wires) == 1:
  1105             return self.Wires[0][0].GetOtherConnectedType(self.Wires[0][1])
  1132             return self.Wires[0][0].GetOtherConnectedType(self.Wires[0][1])
  1106         return self.Type
  1133         return self.Type
  1107     
  1134 
  1108     # Returns the connector type
  1135     # Returns the connector type
  1109     def GetConnectedRedrawRect(self, movex, movey):
  1136     def GetConnectedRedrawRect(self, movex, movey):
  1110         rect = None
  1137         rect = None
  1111         for wire, handle in self.Wires:
  1138         for wire, handle in self.Wires:
  1112             if rect is None:
  1139             if rect is None:
  1113                 rect = wire.GetRedrawRect()
  1140                 rect = wire.GetRedrawRect()
  1114             else:
  1141             else:
  1115                 rect = rect.Union(wire.GetRedrawRect())
  1142                 rect = rect.Union(wire.GetRedrawRect())
  1116         return rect
  1143         return rect
  1117     
  1144 
  1118     # Returns if connector type is compatible with type given
  1145     # Returns if connector type is compatible with type given
  1119     def IsCompatible(self, type):
  1146     def IsCompatible(self, type):
  1120         reference = self.GetType()
  1147         reference = self.GetType()
  1121         return self.ParentBlock.IsOfType(type, reference) or self.ParentBlock.IsOfType(reference, type)
  1148         return self.ParentBlock.IsOfType(type, reference) or self.ParentBlock.IsOfType(reference, type)
  1122     
  1149 
  1123     # Changes the connector name
  1150     # Changes the connector name
  1124     def SetType(self, type):
  1151     def SetType(self, type):
  1125         self.Type = type
  1152         self.Type = type
  1126         for wire, handle in self.Wires:
  1153         for wire, handle in self.Wires:
  1127             wire.SetValid(wire.IsConnectedCompatible())
  1154             wire.SetValid(wire.IsConnectedCompatible())
  1128     
  1155 
  1129     # Returns the connector name
  1156     # Returns the connector name
  1130     def GetName(self):
  1157     def GetName(self):
  1131         return self.Name
  1158         return self.Name
  1132     
  1159 
  1133     # Changes the connector name
  1160     # Changes the connector name
  1134     def SetName(self, name):
  1161     def SetName(self, name):
  1135         self.Name = name
  1162         self.Name = name
  1136         self.RefreshNameSize()
  1163         self.RefreshNameSize()
  1137 
  1164 
  1138     def SetForced(self, forced):
  1165     def SetForced(self, forced):
  1139         if self.Forced != forced:
  1166         if self.Forced != forced:
  1140             self.Forced = forced
  1167             self.Forced = forced
  1141             if self.Visible:
  1168             if self.Visible:
  1142                 self.Parent.ElementNeedRefresh(self)
  1169                 self.Parent.ElementNeedRefresh(self)
  1143     
  1170 
  1144     def GetComputedValue(self):
  1171     def GetComputedValue(self):
  1145         if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
  1172         if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
  1146             return self.Value
  1173             return self.Value
  1147         return None
  1174         return None
  1148     
  1175 
  1149     def GetToolTipValue(self):
  1176     def GetToolTipValue(self):
  1150         return self.GetComputedValue()
  1177         return self.GetComputedValue()
  1151     
  1178 
  1152     def SetValue(self, value):
  1179     def SetValue(self, value):
  1153         if self.Value != value:
  1180         if self.Value != value:
  1154             self.Value = value
  1181             self.Value = value
  1155             computed_value = self.GetComputedValue()
  1182             computed_value = self.GetComputedValue()
  1156             if computed_value is not None:
  1183             if computed_value is not None:
  1159                 if len(self.ComputedValue) > 4:
  1186                 if len(self.ComputedValue) > 4:
  1160                     self.ComputedValue = self.ComputedValue[:4] + "..."
  1187                     self.ComputedValue = self.ComputedValue[:4] + "..."
  1161             self.ValueSize = None
  1188             self.ValueSize = None
  1162             if self.ParentBlock.Visible:
  1189             if self.ParentBlock.Visible:
  1163                 self.ParentBlock.Parent.ElementNeedRefresh(self)
  1190                 self.ParentBlock.Parent.ElementNeedRefresh(self)
  1164     
  1191 
  1165     def RefreshForced(self):
  1192     def RefreshForced(self):
  1166         self.Forced = False
  1193         self.Forced = False
  1167         for wire, handle in self.Wires:
  1194         for wire, handle in self.Wires:
  1168             self.Forced |= wire.IsForced()
  1195             self.Forced |= wire.IsForced()
  1169 
  1196 
  1170     def RefreshValue(self):
  1197     def RefreshValue(self):
  1171         self.Value = self.ReceivingCurrent()
  1198         self.Value = self.ReceivingCurrent()
  1172     
  1199 
  1173     def RefreshValid(self):
  1200     def RefreshValid(self):
  1174         self.Valid = True
  1201         self.Valid = True
  1175         for wire, handle in self.Wires:
  1202         for wire, handle in self.Wires:
  1176             self.Valid &= wire.GetValid()
  1203             self.Valid &= wire.GetValid()
  1177     
  1204 
  1178     def ReceivingCurrent(self):
  1205     def ReceivingCurrent(self):
  1179         current = False
  1206         current = False
  1180         for wire, handle in self.Wires:
  1207         for wire, handle in self.Wires:
  1181             value = wire.GetValue()
  1208             value = wire.GetValue()
  1182             if current != "undefined" and isinstance(value, BooleanType):
  1209             if current != "undefined" and isinstance(value, BooleanType):
  1183                 current |= wire.GetValue()
  1210                 current |= wire.GetValue()
  1184             elif value == "undefined":
  1211             elif value == "undefined":
  1185                 current = "undefined"
  1212                 current = "undefined"
  1186         return current
  1213         return current
  1187     
  1214 
  1188     def SpreadCurrent(self, spreading):
  1215     def SpreadCurrent(self, spreading):
  1189         for wire, handle in self.Wires:
  1216         for wire, handle in self.Wires:
  1190             wire.SetValue(spreading)
  1217             wire.SetValue(spreading)
  1191     
  1218 
  1192     # Changes the connector name size
  1219     # Changes the connector name size
  1193     def RefreshNameSize(self):
  1220     def RefreshNameSize(self):
  1194         if self.Name != "":
  1221         if self.Name != "":
  1195             self.NameSize = self.ParentBlock.Parent.GetTextExtent(self.Name)
  1222             self.NameSize = self.ParentBlock.Parent.GetTextExtent(self.Name)
  1196         else:
  1223         else:
  1197             self.NameSize = 0, 0
  1224             self.NameSize = 0, 0
  1198     
  1225 
  1199     # Returns the connector name size
  1226     # Returns the connector name size
  1200     def GetNameSize(self):
  1227     def GetNameSize(self):
  1201         return self.NameSize
  1228         return self.NameSize
  1202     
  1229 
  1203     # Returns the wires connected to the connector
  1230     # Returns the wires connected to the connector
  1204     def GetWires(self):
  1231     def GetWires(self):
  1205         return self.Wires
  1232         return self.Wires
  1206     
  1233 
  1207     # Returns the parent block Id
  1234     # Returns the parent block Id
  1208     def GetBlockId(self):
  1235     def GetBlockId(self):
  1209         return self.ParentBlock.GetId()
  1236         return self.ParentBlock.GetId()
  1210     
  1237 
  1211     # Returns the connector relative position
  1238     # Returns the connector relative position
  1212     def GetRelPosition(self):
  1239     def GetRelPosition(self):
  1213         return self.Pos
  1240         return self.Pos
  1214     
  1241 
  1215     # Returns the connector absolute position
  1242     # Returns the connector absolute position
  1216     def GetPosition(self, size = True):
  1243     def GetPosition(self, size=True):
  1217         parent_pos = self.ParentBlock.GetPosition()
  1244         parent_pos = self.ParentBlock.GetPosition()
  1218         # If the position of the end of the connector is asked
  1245         # If the position of the end of the connector is asked
  1219         if size:
  1246         if size:
  1220             x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE
  1247             x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE
  1221             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE
  1248             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE
  1222         else:
  1249         else:
  1223             x = parent_pos[0] + self.Pos.x
  1250             x = parent_pos[0] + self.Pos.x
  1224             y = parent_pos[1] + self.Pos.y
  1251             y = parent_pos[1] + self.Pos.y
  1225         return wx.Point(x, y)
  1252         return wx.Point(x, y)
  1226     
  1253 
  1227     # Change the connector relative position
  1254     # Change the connector relative position
  1228     def SetPosition(self, pos):
  1255     def SetPosition(self, pos):
  1229         self.Pos = pos
  1256         self.Pos = pos
  1230     
  1257 
  1231     # Returns the connector direction
  1258     # Returns the connector direction
  1232     def GetDirection(self):
  1259     def GetDirection(self):
  1233         return self.Direction
  1260         return self.Direction
  1234     
  1261 
  1235     # Change the connector direction
  1262     # Change the connector direction
  1236     def SetDirection(self, direction):
  1263     def SetDirection(self, direction):
  1237         self.Direction = direction
  1264         self.Direction = direction
  1238     
  1265 
  1239     # Connect a wire to this connector at the last place
  1266     # Connect a wire to this connector at the last place
  1240     def Connect(self, wire, refresh = True):
  1267     def Connect(self, wire, refresh=True):
  1241         self.InsertConnect(len(self.Wires), wire, refresh)
  1268         self.InsertConnect(len(self.Wires), wire, refresh)
  1242     
  1269 
  1243     # Connect a wire to this connector at the place given
  1270     # Connect a wire to this connector at the place given
  1244     def InsertConnect(self, idx, wire, refresh = True):
  1271     def InsertConnect(self, idx, wire, refresh=True):
  1245         if wire not in self.Wires:
  1272         if wire not in self.Wires:
  1246             self.Wires.insert(idx, wire)
  1273             self.Wires.insert(idx, wire)
  1247             if wire[1] == 0:
  1274             if wire[1] == 0:
  1248                 wire[0].ConnectStartPoint(None, self)
  1275                 wire[0].ConnectStartPoint(None, self)
  1249             else:
  1276             else:
  1250                 wire[0].ConnectEndPoint(None, self)
  1277                 wire[0].ConnectEndPoint(None, self)
  1251             if refresh:
  1278             if refresh:
  1252                 self.ParentBlock.RefreshModel(False)
  1279                 self.ParentBlock.RefreshModel(False)
  1253     
  1280 
  1254     # Returns the index of the wire given in the list of connected
  1281     # Returns the index of the wire given in the list of connected
  1255     def GetWireIndex(self, wire):
  1282     def GetWireIndex(self, wire):
  1256         for i, (tmp_wire, handle) in enumerate(self.Wires):
  1283         for i, (tmp_wire, handle) in enumerate(self.Wires):
  1257             if tmp_wire == wire:
  1284             if tmp_wire == wire:
  1258                 return i
  1285                 return i
  1259         return None
  1286         return None
  1260     
  1287 
  1261     # Unconnect a wire or all wires connected to the connector
  1288     # Unconnect a wire or all wires connected to the connector
  1262     def UnConnect(self, wire = None, unconnect = True, delete = False):
  1289     def UnConnect(self, wire=None, unconnect=True, delete=False):
  1263         i = 0
  1290         i = 0
  1264         found = False
  1291         found = False
  1265         while i < len(self.Wires) and not found:
  1292         while i < len(self.Wires) and not found:
  1266             if not wire or self.Wires[i][0] == wire:
  1293             if not wire or self.Wires[i][0] == wire:
  1267                 # If Unconnect haven't been called from a wire, disconnect the connector in the wire
  1294                 # If Unconnect haven't been called from a wire, disconnect the connector in the wire
  1279         if not wire:
  1306         if not wire:
  1280             self.Wires = []
  1307             self.Wires = []
  1281         if not delete:
  1308         if not delete:
  1282             self.RefreshValid()
  1309             self.RefreshValid()
  1283             self.ParentBlock.RefreshModel(False)
  1310             self.ParentBlock.RefreshModel(False)
  1284     
  1311 
  1285     # Returns if connector has one or more wire connected
  1312     # Returns if connector has one or more wire connected
  1286     def IsConnected(self):
  1313     def IsConnected(self):
  1287         return len(self.Wires) > 0
  1314         return len(self.Wires) > 0
  1288     
  1315 
  1289     # Move the wires connected
  1316     # Move the wires connected
  1290     def MoveConnected(self, exclude = []):
  1317     def MoveConnected(self, exclude=[]):
  1291         if len(self.Wires) > 0:
  1318         if len(self.Wires) > 0:
  1292             # Calculate the new position of the end point
  1319             # Calculate the new position of the end point
  1293             parent_pos = self.ParentBlock.GetPosition()
  1320             parent_pos = self.ParentBlock.GetPosition()
  1294             x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE
  1321             x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE
  1295             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE
  1322             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE
  1298                 if wire not in exclude:
  1325                 if wire not in exclude:
  1299                     if index == 0:
  1326                     if index == 0:
  1300                         wire.MoveStartPoint(wx.Point(x, y))
  1327                         wire.MoveStartPoint(wx.Point(x, y))
  1301                     else:
  1328                     else:
  1302                         wire.MoveEndPoint(wx.Point(x, y))
  1329                         wire.MoveEndPoint(wx.Point(x, y))
  1303     
  1330 
  1304     # Refreshes the model of all the wires connected
  1331     # Refreshes the model of all the wires connected
  1305     def RefreshWires(self):
  1332     def RefreshWires(self):
  1306         for wire in self.Wires:
  1333         for wire in self.Wires:
  1307             wire[0].RefreshModel()
  1334             wire[0].RefreshModel()
  1308     
  1335 
  1309     # Refreshes the parent block model
  1336     # Refreshes the parent block model
  1310     def RefreshParentBlock(self):
  1337     def RefreshParentBlock(self):
  1311         self.ParentBlock.RefreshModel(False)
  1338         self.ParentBlock.RefreshModel(False)
  1312     
  1339 
  1313     # Highlight the parent block
  1340     # Highlight the parent block
  1314     def HighlightParentBlock(self, highlight):
  1341     def HighlightParentBlock(self, highlight):
  1315         self.ParentBlock.SetHighlighted(highlight)
  1342         self.ParentBlock.SetHighlighted(highlight)
  1316         self.ParentBlock.Refresh()
  1343         self.ParentBlock.Refresh()
  1317     
  1344 
  1318     # Returns all the blocks connected to this connector
  1345     # Returns all the blocks connected to this connector
  1319     def GetConnectedBlocks(self):
  1346     def GetConnectedBlocks(self):
  1320         blocks = []
  1347         blocks = []
  1321         for wire, handle in self.Wires:
  1348         for wire, handle in self.Wires:
  1322             # Get other connector connected to each wire
  1349             # Get other connector connected to each wire
  1328             if connector:
  1355             if connector:
  1329                 block = connector.GetParentBlock()
  1356                 block = connector.GetParentBlock()
  1330                 if block not in blocks:
  1357                 if block not in blocks:
  1331                     blocks.append(block)
  1358                     blocks.append(block)
  1332         return blocks
  1359         return blocks
  1333     
  1360 
  1334     # Returns the connector negated property
  1361     # Returns the connector negated property
  1335     def IsNegated(self):
  1362     def IsNegated(self):
  1336         return self.Negated
  1363         return self.Negated
  1337     
  1364 
  1338     # Changes the connector negated property
  1365     # Changes the connector negated property
  1339     def SetNegated(self, negated):
  1366     def SetNegated(self, negated):
  1340         if self.ParentBlock.IsOfType("BOOL", self.Type):
  1367         if self.ParentBlock.IsOfType("BOOL", self.Type):
  1341             self.Negated = negated
  1368             self.Negated = negated
  1342             self.Edge = "none"
  1369             self.Edge = "none"
  1343     
  1370 
  1344     # Returns the connector edge property
  1371     # Returns the connector edge property
  1345     def GetEdge(self):
  1372     def GetEdge(self):
  1346         return self.Edge
  1373         return self.Edge
  1347     
  1374 
  1348     # Changes the connector edge property
  1375     # Changes the connector edge property
  1349     def SetEdge(self, edge):
  1376     def SetEdge(self, edge):
  1350         if self.ParentBlock.IsOfType("BOOL", self.Type):
  1377         if self.ParentBlock.IsOfType("BOOL", self.Type):
  1351             self.Edge = edge    
  1378             self.Edge = edge
  1352             self.Negated = False
  1379             self.Negated = False
  1353     
  1380 
  1354     # assume that pointer is already inside of this connector
  1381     # assume that pointer is already inside of this connector
  1355     def ConnectionAvailable(self, direction=None, exclude=True):
  1382     def ConnectionAvailable(self, direction=None, exclude=True):
  1356         wire_nums = len(self.Wires)
  1383         wire_nums = len(self.Wires)
  1357         
  1384 
  1358         connector_free = (wire_nums<= 0)
  1385         connector_free = (wire_nums <= 0)
  1359         connector_max_used = ((wire_nums > 0) and self.OneConnected)
  1386         connector_max_used = ((wire_nums > 0) and self.OneConnected)
  1360         if (self.Parent.CurrentLanguage in ["SFC", "LD"]) and (self.Type == "BOOL"):
  1387         if (self.Parent.CurrentLanguage in ["SFC", "LD"]) and (self.Type == "BOOL"):
  1361             connector_max_used = False;
  1388             connector_max_used = False
  1362 
  1389 
  1363         # connector is available for new connection
  1390         # connector is available for new connection
  1364         connect  = connector_free or not connector_max_used
  1391         connect = connector_free or not connector_max_used
  1365         return connect, connector_max_used
  1392         return connect, connector_max_used
  1366                            
  1393 
  1367     # Tests if the point given is near from the end point of this connector
  1394     # Tests if the point given is near from the end point of this connector
  1368     def TestPoint(self, pt, direction=None, exclude=True):
  1395     def TestPoint(self, pt, direction=None, exclude=True):
  1369         inside = False;
  1396         inside = False
  1370         check_point = (not exclude) and (direction is None or self.Direction == direction);
  1397         check_point = (not exclude) and (direction is None or self.Direction == direction)
  1371 
  1398 
  1372         if check_point:
  1399         if check_point:
  1373             # Calculate a square around the end point of this connector
  1400             # Calculate a square around the end point of this connector
  1374             parent_pos = self.ParentBlock.GetPosition()
  1401             parent_pos = self.ParentBlock.GetPosition()
  1375             x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE - ANCHOR_DISTANCE
  1402             x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE - ANCHOR_DISTANCE
  1376             y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE - ANCHOR_DISTANCE
  1403             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
  1404             width = ANCHOR_DISTANCE * 2 + abs(self.Direction[0]) * CONNECTOR_SIZE
  1378             height = ANCHOR_DISTANCE * 2 + abs(self.Direction[1]) * CONNECTOR_SIZE
  1405             height = ANCHOR_DISTANCE * 2 + abs(self.Direction[1]) * CONNECTOR_SIZE
  1379             rect = wx.Rect(x, y, width, height)
  1406             rect = wx.Rect(x, y, width, height)
  1380             inside = rect.InsideXY(pt.x, pt.y);
  1407             inside = rect.InsideXY(pt.x, pt.y)
  1381                            
  1408 
  1382         return inside
  1409         return inside
  1383     
  1410 
  1384     # Draws the highlightment of this element if it is highlighted
  1411     # Draws the highlightment of this element if it is highlighted
  1385     def DrawHighlightment(self, dc):
  1412     def DrawHighlightment(self, dc):
  1386         scalex, scaley = dc.GetUserScale()
  1413         scalex, scaley = dc.GetUserScale()
  1387         dc.SetUserScale(1, 1)
  1414         dc.SetUserScale(1, 1)
  1388         pen = MiterPen(HIGHLIGHTCOLOR, 2 * scalex + 5)
  1415         pen = MiterPen(HIGHLIGHTCOLOR, 2 * scalex + 5)
  1391         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  1418         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  1392         dc.SetLogicalFunction(wx.AND)
  1419         dc.SetLogicalFunction(wx.AND)
  1393         parent_pos = self.ParentBlock.GetPosition()
  1420         parent_pos = self.ParentBlock.GetPosition()
  1394         posx = parent_pos[0] + self.Pos.x
  1421         posx = parent_pos[0] + self.Pos.x
  1395         posy = parent_pos[1] + self.Pos.y
  1422         posy = parent_pos[1] + self.Pos.y
  1396         xstart = parent_pos[0] + self.Pos.x 
  1423         xstart = parent_pos[0] + self.Pos.x
  1397         ystart = parent_pos[1] + self.Pos.y
  1424         ystart = parent_pos[1] + self.Pos.y
  1398         if self.Direction[0] < 0:
  1425         if self.Direction[0] < 0:
  1399             xstart += 1
  1426             xstart += 1
  1400         if self.Direction[1] < 0:
  1427         if self.Direction[1] < 0:
  1401             ystart += 1
  1428             ystart += 1
  1402         xend = xstart + CONNECTOR_SIZE * self.Direction[0]
  1429         xend = xstart + CONNECTOR_SIZE * self.Direction[0]
  1403         yend = ystart + CONNECTOR_SIZE * self.Direction[1]
  1430         yend = ystart + CONNECTOR_SIZE * self.Direction[1]
  1404         dc.DrawLine(round((xstart + self.Direction[0]) * scalex), round((ystart + self.Direction[1]) * scaley), 
  1431         dc.DrawLine(round((xstart + self.Direction[0]) * scalex), round((ystart + self.Direction[1]) * scaley),
  1405                     round(xend * scalex), round(yend * scaley))
  1432                     round(xend * scalex), round(yend * scaley))
  1406         dc.SetLogicalFunction(wx.COPY)
  1433         dc.SetLogicalFunction(wx.COPY)
  1407         dc.SetUserScale(scalex, scaley)
  1434         dc.SetUserScale(scalex, scaley)
  1408     
  1435 
  1409     # Adds an highlight to the connector
  1436     # Adds an highlight to the connector
  1410     def AddHighlight(self, infos, start, end, highlight_type):
  1437     def AddHighlight(self, infos, start, end, highlight_type):
  1411         if highlight_type == ERROR_HIGHLIGHT:
  1438         if highlight_type == ERROR_HIGHLIGHT:
  1412             for wire, handle in self.Wires:
  1439             for wire, handle in self.Wires:
  1413                 wire.SetValid(False)
  1440                 wire.SetValid(False)
  1414         AddHighlight(self.Highlights, (start, end, highlight_type))
  1441         AddHighlight(self.Highlights, (start, end, highlight_type))
  1415     
  1442 
  1416     # Removes an highlight from the connector
  1443     # Removes an highlight from the connector
  1417     def RemoveHighlight(self, infos, start, end, highlight_type):
  1444     def RemoveHighlight(self, infos, start, end, highlight_type):
  1418         error = False
  1445         error = False
  1419         highlights = []
  1446         highlights = []
  1420         for highlight in self.Highlights:
  1447         for highlight in self.Highlights:
  1423                 error |= highlight == ERROR_HIGHLIGHT
  1450                 error |= highlight == ERROR_HIGHLIGHT
  1424         self.Highlights = highlights
  1451         self.Highlights = highlights
  1425         if not error:
  1452         if not error:
  1426             for wire, handle in self.Wires:
  1453             for wire, handle in self.Wires:
  1427                 wire.SetValid(wire.IsConnectedCompatible())
  1454                 wire.SetValid(wire.IsConnectedCompatible())
  1428     
  1455 
  1429     # Removes all the highlights of one particular type from the connector
  1456     # Removes all the highlights of one particular type from the connector
  1430     def ClearHighlight(self, highlight_type=None):
  1457     def ClearHighlight(self, highlight_type=None):
  1431         error = False
  1458         error = False
  1432         if highlight_type is None:
  1459         if highlight_type is None:
  1433             self.Highlights = []
  1460             self.Highlights = []
  1439                     error |= highlight == ERROR_HIGHLIGHT
  1466                     error |= highlight == ERROR_HIGHLIGHT
  1440             self.Highlights = highlights
  1467             self.Highlights = highlights
  1441         if not error:
  1468         if not error:
  1442             for wire, handle in self.Wires:
  1469             for wire, handle in self.Wires:
  1443                 wire.SetValid(wire.IsConnectedCompatible())
  1470                 wire.SetValid(wire.IsConnectedCompatible())
  1444     
  1471 
  1445     # Draws the connector
  1472     # Draws the connector
  1446     def Draw(self, dc):
  1473     def Draw(self, dc):
  1447         if self.Selected:
  1474         if self.Selected:
  1448             dc.SetPen(MiterPen(wx.BLUE, 3))
  1475             dc.SetPen(MiterPen(wx.BLUE, 3))
  1449             dc.SetBrush(wx.WHITE_BRUSH)
  1476             dc.SetBrush(wx.WHITE_BRUSH)
  1450         #elif len(self.Highlights) > 0:
  1477         # elif len(self.Highlights) > 0:
  1451         #    dc.SetPen(MiterPen(self.Highlights[-1][1]))
  1478         #    dc.SetPen(MiterPen(self.Highlights[-1][1]))
  1452         #    dc.SetBrush(wx.Brush(self.Highlights[-1][0]))
  1479         #    dc.SetBrush(wx.Brush(self.Highlights[-1][0]))
  1453         else:
  1480         else:
  1454             if not self.Valid:
  1481             if not self.Valid:
  1455                 dc.SetPen(MiterPen(wx.RED))
  1482                 dc.SetPen(MiterPen(wx.RED))
  1464                 dc.SetPen(MiterPen(wx.BLUE))
  1491                 dc.SetPen(MiterPen(wx.BLUE))
  1465             else:
  1492             else:
  1466                 dc.SetPen(MiterPen(wx.BLACK))
  1493                 dc.SetPen(MiterPen(wx.BLACK))
  1467             dc.SetBrush(wx.WHITE_BRUSH)
  1494             dc.SetBrush(wx.WHITE_BRUSH)
  1468         parent_pos = self.ParentBlock.GetPosition()
  1495         parent_pos = self.ParentBlock.GetPosition()
  1469         
  1496 
  1470         if getattr(dc, "printing", False):
  1497         if getattr(dc, "printing", False):
  1471             name_size = dc.GetTextExtent(self.Name)
  1498             name_size = dc.GetTextExtent(self.Name)
  1472         else:
  1499         else:
  1473             name_size = self.NameSize
  1500             name_size = self.NameSize
  1474         
  1501 
  1475         if self.Negated:
  1502         if self.Negated:
  1476             # If connector is negated, draw a circle
  1503             # If connector is negated, draw a circle
  1477             xcenter = parent_pos[0] + self.Pos.x + (CONNECTOR_SIZE * self.Direction[0]) / 2
  1504             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
  1505             ycenter = parent_pos[1] + self.Pos.y + (CONNECTOR_SIZE * self.Direction[1]) / 2
  1479             dc.DrawCircle(xcenter, ycenter, CONNECTOR_SIZE / 2)
  1506             dc.DrawCircle(xcenter, ycenter, CONNECTOR_SIZE / 2)
  1480         else:
  1507         else:
  1481             xstart = parent_pos[0] + self.Pos.x 
  1508             xstart = parent_pos[0] + self.Pos.x
  1482             ystart = parent_pos[1] + self.Pos.y
  1509             ystart = parent_pos[1] + self.Pos.y
  1483             if self.Edge == "rising":
  1510             if self.Edge == "rising":
  1484                 # If connector has a rising edge, draw a right arrow
  1511                 # If connector has a rising edge, draw a right arrow
  1485                 dc.DrawLine(xstart, ystart, xstart - 4, ystart - 4)
  1512                 dc.DrawLine(xstart, ystart, xstart - 4, ystart - 4)
  1486                 dc.DrawLine(xstart, ystart, xstart - 4, ystart + 4)
  1513                 dc.DrawLine(xstart, ystart, xstart - 4, ystart + 4)
  1522             dc.SetTextForeground(wx.NamedColour("purple"))
  1549             dc.SetTextForeground(wx.NamedColour("purple"))
  1523             if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
  1550             if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)):
  1524                 self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue)
  1551                 self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue)
  1525             if self.ValueSize is not None:
  1552             if self.ValueSize is not None:
  1526                 width, height = self.ValueSize
  1553                 width, height = self.ValueSize
  1527                 dc.DrawText(self.ComputedValue, 
  1554                 dc.DrawText(self.ComputedValue,
  1528                     parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] + \
  1555                             parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] +
  1529                                     width * (self.Direction[0] - 1) / 2,
  1556                             width * (self.Direction[0] - 1) / 2,
  1530                     parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] + \
  1557                             parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] +
  1531                                     height * (self.Direction[1] - 1))
  1558                             height * (self.Direction[1] - 1))
  1532             dc.SetFont(self.ParentBlock.Parent.GetFont())
  1559             dc.SetFont(self.ParentBlock.Parent.GetFont())
  1533             dc.SetTextForeground(wx.BLACK)
  1560             dc.SetTextForeground(wx.BLACK)
  1534 
  1561 
  1535 #-------------------------------------------------------------------------------
  1562 
       
  1563 # -------------------------------------------------------------------------------
  1536 #                           Common Wire Element
  1564 #                           Common Wire Element
  1537 #-------------------------------------------------------------------------------
  1565 # -------------------------------------------------------------------------------
  1538 
  1566 
  1539 """
       
  1540 Class that implements a wire for connecting two blocks
       
  1541 """
       
  1542 
  1567 
  1543 class Wire(Graphic_Element, DebugDataConsumer):
  1568 class Wire(Graphic_Element, DebugDataConsumer):
  1544     
  1569     """
       
  1570     Class that implements a wire for connecting two blocks
       
  1571     """
       
  1572 
  1545     # Create a new wire
  1573     # Create a new wire
  1546     def __init__(self, parent, start = None, end = None):
  1574     def __init__(self, parent, start=None, end=None):
  1547         Graphic_Element.__init__(self, parent)
  1575         Graphic_Element.__init__(self, parent)
  1548         DebugDataConsumer.__init__(self)
  1576         DebugDataConsumer.__init__(self)
  1549         self.StartPoint = start
  1577         self.StartPoint = start
  1550         self.EndPoint = end
  1578         self.EndPoint = end
  1551         self.StartConnected = None
  1579         self.StartConnected = None
  1566         self.OverStart = False
  1594         self.OverStart = False
  1567         self.OverEnd = False
  1595         self.OverEnd = False
  1568         self.ComputingType = False
  1596         self.ComputingType = False
  1569         self.Font = parent.GetMiniFont()
  1597         self.Font = parent.GetMiniFont()
  1570         self.ErrHighlight = False
  1598         self.ErrHighlight = False
  1571     
  1599 
  1572     def GetDefinition(self):
  1600     def GetDefinition(self):
  1573         if self.StartConnected is not None and self.EndConnected is not None:
  1601         if self.StartConnected is not None and self.EndConnected is not None:
  1574             startblock = self.StartConnected.GetParentBlock()
  1602             startblock = self.StartConnected.GetParentBlock()
  1575             endblock = self.EndConnected.GetParentBlock()
  1603             endblock = self.EndConnected.GetParentBlock()
  1576             return [], [(startblock.GetId(), endblock.GetId())]
  1604             return [], [(startblock.GetId(), endblock.GetId())]
  1577         return [], []
  1605         return [], []
  1578     
  1606 
  1579     def Flush(self):
  1607     def Flush(self):
  1580         self.StartConnected = None
  1608         self.StartConnected = None
  1581         self.EndConnected = None
  1609         self.EndConnected = None
  1582     
  1610 
  1583     # Returns the RedrawRect
  1611     # Returns the RedrawRect
  1584     def GetRedrawRect(self, movex = 0, movey = 0):
  1612     def GetRedrawRect(self, movex=0, movey=0):
  1585         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1613         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1586         if self.StartConnected:
  1614         if self.StartConnected:
  1587             rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey))
  1615             rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey))
  1588         if self.EndConnected:
  1616         if self.EndConnected:
  1589             rect = rect.Union(self.EndConnected.GetRedrawRect(movex, movey))
  1617             rect = rect.Union(self.EndConnected.GetRedrawRect(movex, movey))
  1605                     y = (self.Points[middle].y + self.Points[middle + 1].y - height) / 2
  1633                     y = (self.Points[middle].y + self.Points[middle + 1].y - height) / 2
  1606                 else:
  1634                 else:
  1607                     y = self.Points[middle].y - height
  1635                     y = self.Points[middle].y - height
  1608                 rect = rect.Union(wx.Rect(x, y, width, height))
  1636                 rect = rect.Union(wx.Rect(x, y, width, height))
  1609         return rect
  1637         return rect
  1610     
  1638 
  1611     def Clone(self, parent, connectors = {}, dx = 0, dy = 0):
  1639     def Clone(self, parent, connectors={}, dx=0, dy=0):
  1612         start_connector = connectors.get(self.StartConnected, None)
  1640         start_connector = connectors.get(self.StartConnected, None)
  1613         end_connector = connectors.get(self.EndConnected, None)
  1641         end_connector = connectors.get(self.EndConnected, None)
  1614         if start_connector is not None and end_connector is not None:
  1642         if start_connector is not None and end_connector is not None:
  1615             wire = Wire(parent)
  1643             wire = Wire(parent)
  1616             wire.SetPoints([(point.x + dx, point.y + dy) for point in self.Points])
  1644             wire.SetPoints([(point.x + dx, point.y + dy) for point in self.Points])
  1618             end_connector.Connect((wire, -1), False)
  1646             end_connector.Connect((wire, -1), False)
  1619             wire.ConnectStartPoint(start_connector.GetPosition(), start_connector)
  1647             wire.ConnectStartPoint(start_connector.GetPosition(), start_connector)
  1620             wire.ConnectEndPoint(end_connector.GetPosition(), end_connector)
  1648             wire.ConnectEndPoint(end_connector.GetPosition(), end_connector)
  1621             return wire
  1649             return wire
  1622         return None
  1650         return None
  1623     
  1651 
  1624     # Forbids to change the wire position
  1652     # Forbids to change the wire position
  1625     def SetPosition(x, y):
  1653     def SetPosition(x, y):
  1626         pass
  1654         pass
  1627     
  1655 
  1628     # Forbids to change the wire size
  1656     # Forbids to change the wire size
  1629     def SetSize(width, height):
  1657     def SetSize(width, height):
  1630         pass
  1658         pass
  1631     
  1659 
  1632     # Forbids to et size of the group elements to their minimum size
  1660     # Forbids to et size of the group elements to their minimum size
  1633         pass
  1661         pass
  1634     
  1662 
  1635     # Moves and Resizes the element for fitting scaling
  1663     # Moves and Resizes the element for fitting scaling
  1636     def SetBestSize(self, scaling):
  1664     def SetBestSize(self, scaling):
  1637         if scaling is not None:
  1665         if scaling is not None:
  1638             movex_max = movey_max = 0
  1666             movex_max = movey_max = 0
  1639             for idx, point in enumerate(self.Points):
  1667             for idx, point in enumerate(self.Points):
  1662                     movey_max = max(movey_max, movey)
  1690                     movey_max = max(movey_max, movey)
  1663                     point.x += movex
  1691                     point.x += movex
  1664                     point.y += movey
  1692                     point.y += movey
  1665             return movex_max, movey_max
  1693             return movex_max, movey_max
  1666         return 0, 0
  1694         return 0, 0
  1667     
  1695 
  1668     # Returns connector to which start point is connected
  1696     # Returns connector to which start point is connected
  1669     def GetStartConnected(self):
  1697     def GetStartConnected(self):
  1670         return self.StartConnected
  1698         return self.StartConnected
  1671     
  1699 
  1672     # Returns connector to which start point is connected
  1700     # Returns connector to which start point is connected
  1673     def GetStartConnectedType(self):
  1701     def GetStartConnectedType(self):
  1674         if self.StartConnected and not self.ComputingType:
  1702         if self.StartConnected and not self.ComputingType:
  1675             self.ComputingType = True
  1703             self.ComputingType = True
  1676             computed_type = self.StartConnected.GetType()
  1704             computed_type = self.StartConnected.GetType()
  1677             self.ComputingType = False
  1705             self.ComputingType = False
  1678             return computed_type
  1706             return computed_type
  1679         return None
  1707         return None
  1680     
  1708 
  1681     # Returns connector to which end point is connected
  1709     # Returns connector to which end point is connected
  1682     def GetEndConnected(self):
  1710     def GetEndConnected(self):
  1683         return self.EndConnected
  1711         return self.EndConnected
  1684     
  1712 
  1685     # Returns connector to which end point is connected
  1713     # Returns connector to which end point is connected
  1686     def GetEndConnectedType(self):
  1714     def GetEndConnectedType(self):
  1687         if self.EndConnected and not self.ComputingType:
  1715         if self.EndConnected and not self.ComputingType:
  1688             self.ComputingType = True
  1716             self.ComputingType = True
  1689             computed_type = self.EndConnected.GetType()
  1717             computed_type = self.EndConnected.GetType()
  1690             self.ComputingType = False
  1718             self.ComputingType = False
  1691             return computed_type
  1719             return computed_type
  1692         return None
  1720         return None
  1693     
  1721 
  1694     def GetConnectionDirection(self):
  1722     def GetConnectionDirection(self):
  1695         if self.StartConnected is None and self.EndConnected is None:
  1723         if self.StartConnected is None and self.EndConnected is None:
  1696             return None
  1724             return None
  1697         elif self.StartConnected is not None and self.EndConnected is None:
  1725         elif self.StartConnected is not None and self.EndConnected is None:
  1698             return (-self.StartPoint[1][0], -self.StartPoint[1][1])
  1726             return (-self.StartPoint[1][0], -self.StartPoint[1][1])
  1705                 if handle == 0:
  1733                 if handle == 0:
  1706                     return self.EndPoint
  1734                     return self.EndPoint
  1707                 else:
  1735                 else:
  1708                     return (-self.StartPoint[1][0], -self.StartPoint[1][1])
  1736                     return (-self.StartPoint[1][0], -self.StartPoint[1][1])
  1709         return None
  1737         return None
  1710     
  1738 
  1711     def GetOtherConnected(self, connector):
  1739     def GetOtherConnected(self, connector):
  1712         if self.StartConnected == connector:
  1740         if self.StartConnected == connector:
  1713             return self.EndConnected
  1741             return self.EndConnected
  1714         else:
  1742         else:
  1715             return self.StartConnected
  1743             return self.StartConnected
  1716     
  1744 
  1717     def GetOtherConnectedType(self, handle):
  1745     def GetOtherConnectedType(self, handle):
  1718         if handle == 0:
  1746         if handle == 0:
  1719             return self.GetEndConnectedType()
  1747             return self.GetEndConnectedType()
  1720         else:
  1748         else:
  1721             return self.GetStartConnectedType()
  1749             return self.GetStartConnectedType()
  1722     
  1750 
  1723     def IsConnectedCompatible(self):
  1751     def IsConnectedCompatible(self):
  1724         if self.StartConnected:
  1752         if self.StartConnected:
  1725             return self.StartConnected.IsCompatible(self.GetEndConnectedType())
  1753             return self.StartConnected.IsCompatible(self.GetEndConnectedType())
  1726         elif self.EndConnected:
  1754         elif self.EndConnected:
  1727             return True
  1755             return True
  1728         return False
  1756         return False
  1729     
  1757 
  1730     def SetForced(self, forced):
  1758     def SetForced(self, forced):
  1731         if self.Forced != forced:
  1759         if self.Forced != forced:
  1732             self.Forced = forced
  1760             self.Forced = forced
  1733             if self.StartConnected:
  1761             if self.StartConnected:
  1734                 self.StartConnected.RefreshForced()
  1762                 self.StartConnected.RefreshForced()
  1739 
  1767 
  1740     def GetComputedValue(self):
  1768     def GetComputedValue(self):
  1741         if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
  1769         if self.Value is not None and self.Value != "undefined" and not isinstance(self.Value, BooleanType):
  1742             return self.Value
  1770             return self.Value
  1743         return None
  1771         return None
  1744     
  1772 
  1745     def GetToolTipValue(self):
  1773     def GetToolTipValue(self):
  1746         return self.GetComputedValue()
  1774         return self.GetComputedValue()
  1747 
  1775 
  1748     def SetModifier(self, modifier):
  1776     def SetModifier(self, modifier):
  1749         self.Modifier = modifier
  1777         self.Modifier = modifier
  1771             if self.Visible:
  1799             if self.Visible:
  1772                 self.Parent.ElementNeedRefresh(self)
  1800                 self.Parent.ElementNeedRefresh(self)
  1773             if isinstance(value, BooleanType) and self.StartConnected is not None:
  1801             if isinstance(value, BooleanType) and self.StartConnected is not None:
  1774                 block = self.StartConnected.GetParentBlock()
  1802                 block = self.StartConnected.GetParentBlock()
  1775                 block.SpreadCurrent()
  1803                 block.SpreadCurrent()
  1776     
  1804 
  1777     # Unconnect the start and end points
  1805     # Unconnect the start and end points
  1778     def Clean(self):
  1806     def Clean(self):
  1779         if self.StartConnected:
  1807         if self.StartConnected:
  1780             self.UnConnectStartPoint()
  1808             self.UnConnectStartPoint()
  1781         if self.EndConnected:
  1809         if self.EndConnected:
  1782             self.UnConnectEndPoint()
  1810             self.UnConnectEndPoint()
  1783     
  1811 
  1784     # Delete this wire by calling the corresponding method
  1812     # Delete this wire by calling the corresponding method
  1785     def Delete(self):
  1813     def Delete(self):
  1786         self.Parent.DeleteWire(self)
  1814         self.Parent.DeleteWire(self)
  1787     
  1815 
  1788     # Select a segment and not the whole wire. It's useful for Ladder Diagram
  1816     # Select a segment and not the whole wire. It's useful for Ladder Diagram
  1789     def SetSelectedSegment(self, segment):
  1817     def SetSelectedSegment(self, segment):
  1790         # The last segment is indicated
  1818         # The last segment is indicated
  1791         if segment == -1:
  1819         if segment == -1:
  1792             segment = len(self.Segments) - 1
  1820             segment = len(self.Segments) - 1
  1793         # The selected segment is reinitialised
  1821         # The selected segment is reinitialised
  1794         if segment == None:
  1822         if segment is None:
  1795             if self.StartConnected:
  1823             if self.StartConnected:
  1796                 self.StartConnected.SetSelected(False)
  1824                 self.StartConnected.SetSelected(False)
  1797             if self.EndConnected:
  1825             if self.EndConnected:
  1798                 self.EndConnected.SetSelected(False)
  1826                 self.EndConnected.SetSelected(False)
  1799         # The segment selected is the first
  1827         # The segment selected is the first
  1812                 self.StartConnected.SetSelected(False)
  1840                 self.StartConnected.SetSelected(False)
  1813             if self.EndConnected:
  1841             if self.EndConnected:
  1814                 self.EndConnected.SetSelected(True)
  1842                 self.EndConnected.SetSelected(True)
  1815         self.SelectedSegment = segment
  1843         self.SelectedSegment = segment
  1816         self.Refresh()
  1844         self.Refresh()
  1817     
  1845 
  1818     def SetValid(self, valid):
  1846     def SetValid(self, valid):
  1819         self.Valid = valid
  1847         self.Valid = valid
  1820         if self.StartConnected:
  1848         if self.StartConnected:
  1821             self.StartConnected.RefreshValid()
  1849             self.StartConnected.RefreshValid()
  1822         if self.EndConnected:
  1850         if self.EndConnected:
  1823             self.EndConnected.RefreshValid()
  1851             self.EndConnected.RefreshValid()
  1824     
  1852 
  1825     def GetValid(self):
  1853     def GetValid(self):
  1826         return self.Valid
  1854         return self.Valid
  1827     
  1855 
  1828     # Reinitialize the wire points
  1856     # Reinitialize the wire points
  1829     def ResetPoints(self):
  1857     def ResetPoints(self):
  1830         if self.StartPoint and self.EndPoint:
  1858         if self.StartPoint and self.EndPoint:
  1831             self.Points = [self.StartPoint[0], self.EndPoint[0]]
  1859             self.Points = [self.StartPoint[0], self.EndPoint[0]]
  1832             self.Segments = [self.StartPoint[1]]
  1860             self.Segments = [self.StartPoint[1]]
  1833         else:
  1861         else:
  1834             self.Points = []
  1862             self.Points = []
  1835             self.Segments = []
  1863             self.Segments = []
  1836     
  1864 
  1837     # Refresh the wire bounding box
  1865     # Refresh the wire bounding box
  1838     def RefreshBoundingBox(self):
  1866     def RefreshBoundingBox(self):
  1839         if len(self.Points) > 0:
  1867         if len(self.Points) > 0:
  1840             # If startpoint or endpoint is connected, save the point radius
  1868             # If startpoint or endpoint is connected, save the point radius
  1841             start_radius = end_radius = 0
  1869             start_radius = end_radius = 0
  1860                 miny, minbbxy = min(miny, self.Points[-1].y), min(minbbxy, self.Points[-1].y - end_radius)
  1888                 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)
  1889                 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
  1890             self.Pos.x, self.Pos.y = minx, miny
  1863             self.Size = wx.Size(maxx - minx, maxy - miny)
  1891             self.Size = wx.Size(maxx - minx, maxy - miny)
  1864             self.BoundingBox = wx.Rect(minbbxx, minbbxy, maxbbxx - minbbxx + 1, maxbbxy - minbbxy + 1)
  1892             self.BoundingBox = wx.Rect(minbbxx, minbbxy, maxbbxx - minbbxx + 1, maxbbxy - minbbxy + 1)
  1865     
  1893 
  1866     # Refresh the realpoints that permits to keep the proportionality in wire during resizing
  1894     # Refresh the realpoints that permits to keep the proportionality in wire during resizing
  1867     def RefreshRealPoints(self):
  1895     def RefreshRealPoints(self):
  1868         if len(self.Points) > 0:
  1896         if len(self.Points) > 0:
  1869             self.RealPoints = []
  1897             self.RealPoints = []
  1870             # Calculate float relative position of each point with the minimum point
  1898             # Calculate float relative position of each point with the minimum point
  1871             for point in self.Points:
  1899             for point in self.Points:
  1872                 self.RealPoints.append([float(point.x - self.Pos.x), float(point.y - self.Pos.y)])
  1900                 self.RealPoints.append([float(point.x - self.Pos.x), float(point.y - self.Pos.y)])
  1873     
  1901 
  1874     # Returns the wire minimum size 
  1902     # Returns the wire minimum size
  1875     def GetMinSize(self):
  1903     def GetMinSize(self):
  1876         width = 1
  1904         width = 1
  1877         height = 1
  1905         height = 1
  1878         dir_product = product(self.StartPoint[1], self.EndPoint[1])
  1906         dir_product = product(self.StartPoint[1], self.EndPoint[1])
  1879         # The directions are opposed
  1907         # The directions are opposed
  1891         # The directions are perpendiculars
  1919         # The directions are perpendiculars
  1892         else:
  1920         else:
  1893             width = MIN_SEGMENT_SIZE
  1921             width = MIN_SEGMENT_SIZE
  1894             height = MIN_SEGMENT_SIZE
  1922             height = MIN_SEGMENT_SIZE
  1895         return width + 1, height + 1
  1923         return width + 1, height + 1
  1896     
  1924 
  1897     # Returns if the point given is on one of the wire segments
  1925     # Returns if the point given is on one of the wire segments
  1898     def HitTest(self, pt, connectors=True):
  1926     def HitTest(self, pt, connectors=True):
  1899         test = False
  1927         test = False
  1900         for i in xrange(len(self.Points) - 1):
  1928         for i in xrange(len(self.Points) - 1):
  1901             rect = wx.Rect(0, 0, 0, 0)
  1929             rect = wx.Rect(0, 0, 0, 0)
  1902             if i == 0 and self.StartConnected is not None:
  1930             if i == 0 and self.StartConnected is not None:
  1903                 x1 = self.Points[i].x - self.Segments[0][0] * CONNECTOR_SIZE
  1931                 x1 = self.Points[i].x - self.Segments[0][0] * CONNECTOR_SIZE
  1904                 y1 = self.Points[i].y - self.Segments[0][1] * CONNECTOR_SIZE
  1932                 y1 = self.Points[i].y - self.Segments[0][1] * CONNECTOR_SIZE
  1905             else:
  1933             else:
  1906                 x1, y1 = self.Points[i].x, self.Points[i].y    
  1934                 x1, y1 = self.Points[i].x, self.Points[i].y
  1907             if i == len(self.Points) - 2 and self.EndConnected is not None:
  1935             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
  1936                 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
  1937                 y2 = self.Points[i + 1].y + self.Segments[-1][1] * CONNECTOR_SIZE
  1910             else:
  1938             else:
  1911                 x2, y2 = self.Points[i + 1].x, self.Points[i + 1].y
  1939                 x2, y2 = self.Points[i + 1].x, self.Points[i + 1].y
  1912             # Calculate a rectangle around the segment
  1940             # Calculate a rectangle around the segment
  1913             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,
  1914                 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)
  1915             test |= rect.InsideXY(pt.x, pt.y) 
  1943             test |= rect.InsideXY(pt.x, pt.y)
  1916         return test
  1944         return test
  1917     
  1945 
  1918     # Returns the wire start or end point if the point given is on one of them 
  1946     # Returns the wire start or end point if the point given is on one of them
  1919     def TestPoint(self, pt):
  1947     def TestPoint(self, pt):
  1920         # Test the wire start point
  1948         # Test the wire start point
  1921         rect = wx.Rect(self.Points[0].x - ANCHOR_DISTANCE, self.Points[0].y - ANCHOR_DISTANCE,
  1949         rect = wx.Rect(self.Points[0].x - ANCHOR_DISTANCE, self.Points[0].y - ANCHOR_DISTANCE,
  1922             2 * ANCHOR_DISTANCE, 2 * ANCHOR_DISTANCE)
  1950                        2 * ANCHOR_DISTANCE, 2 * ANCHOR_DISTANCE)
  1923         if rect.InsideXY(pt.x, pt.y):
  1951         if rect.InsideXY(pt.x, pt.y):
  1924             return 0
  1952             return 0
  1925         # Test the wire end point
  1953         # Test the wire end point
  1926         if len(self.Points) > 1:
  1954         if len(self.Points) > 1:
  1927             rect = wx.Rect(self.Points[-1].x - ANCHOR_DISTANCE, self.Points[-1].y - ANCHOR_DISTANCE,
  1955             rect = wx.Rect(self.Points[-1].x - ANCHOR_DISTANCE, self.Points[-1].y - ANCHOR_DISTANCE,
  1928                 2 * ANCHOR_DISTANCE, 2 * ANCHOR_DISTANCE)
  1956                            2 * ANCHOR_DISTANCE, 2 * ANCHOR_DISTANCE)
  1929             if rect.InsideXY(pt.x, pt.y):
  1957             if rect.InsideXY(pt.x, pt.y):
  1930                 return -1
  1958                 return -1
  1931         return None
  1959         return None
  1932     
  1960 
  1933     # Returns the wire segment if the point given is on it
  1961     # Returns the wire segment if the point given is on it
  1934     def TestSegment(self, pt, all=False):
  1962     def TestSegment(self, pt, all=False):
  1935         for i in xrange(len(self.Segments)):
  1963         for i in xrange(len(self.Segments)):
  1936             # If wire is not in a Ladder Diagram, first and last segments are excluded
  1964             # If wire is not in a Ladder Diagram, first and last segments are excluded
  1937             if all or 0 < i < len(self.Segments) - 1:
  1965             if all or 0 < i < len(self.Segments) - 1:
  1938                 x1, y1 = self.Points[i].x, self.Points[i].y
  1966                 x1, y1 = self.Points[i].x, self.Points[i].y
  1939                 x2, y2 = self.Points[i + 1].x, self.Points[i + 1].y
  1967                 x2, y2 = self.Points[i + 1].x, self.Points[i + 1].y
  1940                 # Calculate a rectangle around the segment
  1968                 # Calculate a rectangle around the segment
  1941                 rect = wx.Rect(min(x1, x2) - ANCHOR_DISTANCE, min(y1, y2) - ANCHOR_DISTANCE,
  1969                 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)
  1970                                abs(x1 - x2) + 2 * ANCHOR_DISTANCE, abs(y1 - y2) + 2 * ANCHOR_DISTANCE)
  1943                 if rect.InsideXY(pt.x, pt.y):
  1971                 if rect.InsideXY(pt.x, pt.y):
  1944                     return i, self.Segments[i]
  1972                     return i, self.Segments[i]
  1945         return None
  1973         return None
  1946     
  1974 
  1947     # Define the wire points
  1975     # Define the wire points
  1948     def SetPoints(self, points, verify=True):
  1976     def SetPoints(self, points, verify=True):
  1949         if len(points) > 1:
  1977         if len(points) > 1:
  1950             self.Points = [wx.Point(x, y) for x, y in points]
  1978             self.Points = [wx.Point(x, y) for x, y in points]
  1951             # Calculate the start and end directions
  1979             # Calculate the start and end directions
  1952             self.StartPoint = [None, vector(self.Points[0], self.Points[1])]
  1980             self.StartPoint = [None, vector(self.Points[0], self.Points[1])]
  1953             self.EndPoint = [None, vector(self.Points[-1], self.Points[-2])]
  1981             self.EndPoint = [None, vector(self.Points[-1], self.Points[-2])]
  1954             # Calculate the start and end points
  1982             # Calculate the start and end points
  1955             self.StartPoint[0] = wx.Point(self.Points[0].x + CONNECTOR_SIZE * self.StartPoint[1][0], 
  1983             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])
  1984                                           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], 
  1985             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])
  1986                                         self.Points[-1].y + CONNECTOR_SIZE * self.EndPoint[1][1])
  1959             self.Points[0] = self.StartPoint[0]
  1987             self.Points[0] = self.StartPoint[0]
  1960             self.Points[-1] = self.EndPoint[0]
  1988             self.Points[-1] = self.EndPoint[0]
  1961             # Calculate the segments directions
  1989             # Calculate the segments directions
  1962             self.Segments = []
  1990             self.Segments = []
  1963             i = 0
  1991             i = 0
  1977                             self.Points.insert(i + 1, wx.Point(self.Points[i + 1].x, self.Points[i + 1].y))
  2005                             self.Points.insert(i + 1, wx.Point(self.Points[i + 1].x, self.Points[i + 1].y))
  1978                     self.Segments.append(segment)
  2006                     self.Segments.append(segment)
  1979                     i += 1
  2007                     i += 1
  1980             self.RefreshBoundingBox()
  2008             self.RefreshBoundingBox()
  1981             self.RefreshRealPoints()
  2009             self.RefreshRealPoints()
  1982     
  2010 
  1983     # Returns the position of the point indicated
  2011     # Returns the position of the point indicated
  1984     def GetPoint(self, index):
  2012     def GetPoint(self, index):
  1985         if index < len(self.Points):
  2013         if index < len(self.Points):
  1986             return self.Points[index].x, self.Points[index].y
  2014             return self.Points[index].x, self.Points[index].y
  1987         return None
  2015         return None
  1988     
  2016 
  1989     # Returns a list of the position of all wire points
  2017     # Returns a list of the position of all wire points
  1990     def GetPoints(self, invert = False):
  2018     def GetPoints(self, invert=False):
  1991         points = self.VerifyPoints()
  2019         points = self.VerifyPoints()
  1992         points[0] = wx.Point(points[0].x - CONNECTOR_SIZE * self.StartPoint[1][0], 
  2020         points[0] = wx.Point(points[0].x - CONNECTOR_SIZE * self.StartPoint[1][0],
  1993                 points[0].y - CONNECTOR_SIZE * self.StartPoint[1][1])
  2021                              points[0].y - CONNECTOR_SIZE * self.StartPoint[1][1])
  1994         points[-1] = wx.Point(points[-1].x - CONNECTOR_SIZE * self.EndPoint[1][0], 
  2022         points[-1] = wx.Point(points[-1].x - CONNECTOR_SIZE * self.EndPoint[1][0],
  1995                 points[-1].y - CONNECTOR_SIZE * self.EndPoint[1][1])
  2023                               points[-1].y - CONNECTOR_SIZE * self.EndPoint[1][1])
  1996         # An inversion of the list is asked
  2024         # An inversion of the list is asked
  1997         if invert:
  2025         if invert:
  1998             points.reverse()
  2026             points.reverse()
  1999         return points
  2027         return points
  2000     
  2028 
  2001     # Returns the position of the two selected segment points
  2029     # Returns the position of the two selected segment points
  2002     def GetSelectedSegmentPoints(self):
  2030     def GetSelectedSegmentPoints(self):
  2003         if self.SelectedSegment != None and len(self.Points) > 1:
  2031         if self.SelectedSegment is not None and len(self.Points) > 1:
  2004             return self.Points[self.SelectedSegment:self.SelectedSegment + 2]
  2032             return self.Points[self.SelectedSegment:self.SelectedSegment + 2]
  2005         return []
  2033         return []
  2006     
  2034 
  2007     # Returns if the selected segment is the first and/or the last of the wire
  2035     # Returns if the selected segment is the first and/or the last of the wire
  2008     def GetSelectedSegmentConnections(self):
  2036     def GetSelectedSegmentConnections(self):
  2009         if self.SelectedSegment != None and len(self.Points) > 1:
  2037         if self.SelectedSegment is not None and len(self.Points) > 1:
  2010             return self.SelectedSegment == 0, self.SelectedSegment == len(self.Segments) - 1
  2038             return self.SelectedSegment == 0, self.SelectedSegment == len(self.Segments) - 1
  2011         return (True, True)
  2039         return (True, True)
  2012     
  2040 
  2013     # Returns the connectors on which the wire is connected
  2041     # Returns the connectors on which the wire is connected
  2014     def GetConnected(self):
  2042     def GetConnected(self):
  2015         connected = []
  2043         connected = []
  2016         if self.StartConnected and self.StartPoint[1] == WEST:
  2044         if self.StartConnected and self.StartPoint[1] == WEST:
  2017             connected.append(self.StartConnected)
  2045             connected.append(self.StartConnected)
  2018         if self.EndConnected and self.EndPoint[1] == WEST:
  2046         if self.EndConnected and self.EndPoint[1] == WEST:
  2019             connected.append(self.EndConnected)
  2047             connected.append(self.EndConnected)
  2020         return connected
  2048         return connected
  2021     
  2049 
  2022     # Returns the id of the block connected to the first or the last wire point
  2050     # Returns the id of the block connected to the first or the last wire point
  2023     def GetConnectedInfos(self, index):
  2051     def GetConnectedInfos(self, index):
  2024         if index == 0 and self.StartConnected:
  2052         if index == 0 and self.StartConnected:
  2025             return self.StartConnected.GetBlockId(), self.StartConnected.GetName()
  2053             return self.StartConnected.GetBlockId(), self.StartConnected.GetName()
  2026         elif index == -1 and self.EndConnected:
  2054         elif index == -1 and self.EndConnected:
  2027             return self.EndConnected.GetBlockId(), self.EndConnected.GetName()
  2055             return self.EndConnected.GetBlockId(), self.EndConnected.GetName()
  2028         return None
  2056         return None
  2029     
  2057 
  2030     # Update the wire points position by keeping at most possible the current positions
  2058     # Update the wire points position by keeping at most possible the current positions
  2031     def GeneratePoints(self, realpoints = True):
  2059     def GeneratePoints(self, realpoints=True):
  2032         i = 0
  2060         i = 0
  2033         # Calculate the start enad end points with the minimum segment size in the right direction
  2061         # 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,
  2062         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)
  2063                        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, 
  2064         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)
  2065                          self.StartPoint[0].y + self.StartPoint[1][1] * MIN_SEGMENT_SIZE)
  2038         # Evaluate the point till it's the last
  2066         # Evaluate the point till it's the last
  2039         while i < len(self.Points) - 1:
  2067         while i < len(self.Points) - 1:
  2040             # The next point is the last
  2068             # The next point is the last
  2041             if i + 1 == len(self.Points) - 1:
  2069             if i + 1 == len(self.Points) - 1:
  2042                 # Calculate the direction from current point to end point
  2070                 # Calculate the direction from current point to end point
  2044                 # The current point is the first
  2072                 # The current point is the first
  2045                 if i == 0:
  2073                 if i == 0:
  2046                     # If the end point is not in the start direction, a point is added
  2074                     # 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]:
  2075                     if v_end != self.Segments[0] or v_end == self.EndPoint[1]:
  2048                         self.Points.insert(1, wx.Point(start.x, start.y))
  2076                         self.Points.insert(1, wx.Point(start.x, start.y))
  2049                         self.Segments.insert(1, DirectionChoice((self.Segments[0][1], 
  2077                         self.Segments.insert(1, DirectionChoice(
  2050                             self.Segments[0][0]), v_end, self.EndPoint[1]))
  2078                             (self.Segments[0][1],
       
  2079                              self.Segments[0][0]), v_end, self.EndPoint[1]))
  2051                 # The current point is the second
  2080                 # The current point is the second
  2052                 elif i == 1:
  2081                 elif i == 1:
  2053                     # The previous direction and the target direction are mainly opposed, a point is added
  2082                     # The previous direction and the target direction are mainly opposed, a point is added
  2054                     if product(v_end, self.Segments[0]) < 0:
  2083                     if product(v_end, self.Segments[0]) < 0:
  2055                         self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2084                         self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2056                         self.Segments.insert(2, DirectionChoice((self.Segments[1][1], 
  2085                         self.Segments.insert(2, DirectionChoice(
  2057                             self.Segments[1][0]), v_end, self.EndPoint[1]))
  2086                             (self.Segments[1][1],
       
  2087                              self.Segments[1][0]), v_end, self.EndPoint[1]))
  2058                     # The previous direction and the end direction are the same or they are
  2088                     # The previous direction and the end direction are the same or they are
  2059                     # perpendiculars and the end direction points towards current segment
  2089                     # 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:
  2090                     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
  2091                         # Current point and end point are aligned
  2062                         if self.Segments[0][0] != 0:
  2092                         if self.Segments[0][0] != 0:
  2064                         if self.Segments[0][1] != 0:
  2094                         if self.Segments[0][1] != 0:
  2065                             self.Points[1].y = end.y
  2095                             self.Points[1].y = end.y
  2066                         # If the previous direction and the end direction are the same, a point is added
  2096                         # 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:
  2097                         if product(self.Segments[0], self.EndPoint[1]) > 0:
  2068                             self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2098                             self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2069                             self.Segments.insert(2, DirectionChoice((self.Segments[1][1], 
  2099                             self.Segments.insert(2, DirectionChoice(
  2070                                 self.Segments[1][0]), v_end, self.EndPoint[1]))
  2100                                 (self.Segments[1][1],
       
  2101                                  self.Segments[1][0]), v_end, self.EndPoint[1]))
  2071                     else:
  2102                     else:
  2072                         # Current point is positioned in the middle of start point
  2103                         # Current point is positioned in the middle of start point
  2073                         # and end point on the current direction and a point is added
  2104                         # and end point on the current direction and a point is added
  2074                         if self.Segments[0][0] != 0:
  2105                         if self.Segments[0][0] != 0:
  2075                             self.Points[1].x = (end.x + start.x) / 2
  2106                             self.Points[1].x = (end.x + start.x) / 2
  2076                         if self.Segments[0][1] != 0:
  2107                         if self.Segments[0][1] != 0:
  2077                             self.Points[1].y = (end.y + start.y) / 2
  2108                             self.Points[1].y = (end.y + start.y) / 2
  2078                         self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2109                         self.Points.insert(2, wx.Point(self.Points[1].x, self.Points[1].y))
  2079                         self.Segments.insert(2, DirectionChoice((self.Segments[1][1], 
  2110                         self.Segments.insert(2, DirectionChoice(
  2080                             self.Segments[1][0]), v_end, self.EndPoint[1]))
  2111                             (self.Segments[1][1],
       
  2112                              self.Segments[1][0]), v_end, self.EndPoint[1]))
  2081                 else:
  2113                 else:
  2082                     # The previous direction and the end direction are perpendiculars
  2114                     # The previous direction and the end direction are perpendiculars
  2083                     if product(self.Segments[i - 1], self.EndPoint[1]) == 0:
  2115                     if product(self.Segments[i - 1], self.EndPoint[1]) == 0:
  2084                         # The target direction and the end direction aren't mainly the same
  2116                         # The target direction and the end direction aren't mainly the same
  2085                         if product(v_end, self.EndPoint[1]) <= 0:
  2117                         if product(v_end, self.EndPoint[1]) <= 0:
  2091                             # Previous direction is updated from the new point
  2123                             # Previous direction is updated from the new point
  2092                             if product(vector(self.Points[i - 1], self.Points[i]), self.Segments[i - 1]) < 0:
  2124                             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])
  2125                                 self.Segments[i - 1] = (-self.Segments[i - 1][0], -self.Segments[i - 1][1])
  2094                         else:
  2126                         else:
  2095                             test = True
  2127                             test = True
  2096                             # If the current point is the third, test if the second 
  2128                             # If the current point is the third, test if the second
  2097                             # point can be aligned with the end point
  2129                             # point can be aligned with the end point
  2098                             if i == 2:
  2130                             if i == 2:
  2099                                 test_point = wx.Point(self.Points[1].x, self.Points[1].y)
  2131                                 test_point = wx.Point(self.Points[1].x, self.Points[1].y)
  2100                                 if self.Segments[1][0] != 0:
  2132                                 if self.Segments[1][0] != 0:
  2101                                     test_point.y = end.y
  2133                                     test_point.y = end.y
  2117                                 if self.Segments[1][0] != 0:
  2149                                 if self.Segments[1][0] != 0:
  2118                                     self.Points[2].x = (self.Points[1].x + end.x) / 2
  2150                                     self.Points[2].x = (self.Points[1].x + end.x) / 2
  2119                                 if self.Segments[1][1] != 0:
  2151                                 if self.Segments[1][1] != 0:
  2120                                     self.Points[2].y = (self.Points[1].y + end.y) / 2
  2152                                     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))
  2153                                 self.Points.insert(3, wx.Point(self.Points[2].x, self.Points[2].y))
  2122                                 self.Segments.insert(3, DirectionChoice((self.Segments[2][1], 
  2154                                 self.Segments.insert(
  2123                                     self.Segments[2][0]), v_end, self.EndPoint[1]))
  2155                                     3,
       
  2156                                     DirectionChoice((self.Segments[2][1],
       
  2157                                                      self.Segments[2][0]),
       
  2158                                                     v_end,
       
  2159                                                     self.EndPoint[1]))
  2124                     else:
  2160                     else:
  2125                         # Current point is aligned with end point
  2161                         # Current point is aligned with end point
  2126                         if self.Segments[i - 1][0] != 0:
  2162                         if self.Segments[i - 1][0] != 0:
  2127                             self.Points[i].x = end.x
  2163                             self.Points[i].x = end.x
  2128                         if self.Segments[i - 1][1] != 0:
  2164                         if self.Segments[i - 1][1] != 0:
  2138                                 self.Points[i].x = (end.x + self.Points[i - 1].x) / 2
  2174                                 self.Points[i].x = (end.x + self.Points[i - 1].x) / 2
  2139                             if self.Segments[i - 1][1] != 0:
  2175                             if self.Segments[i - 1][1] != 0:
  2140                                 self.Points[i].y = (end.y + self.Points[i - 1].y) / 2
  2176                                 self.Points[i].y = (end.y + self.Points[i - 1].y) / 2
  2141                         # A point is added
  2177                         # A point is added
  2142                         self.Points.insert(i + 1, wx.Point(self.Points[i].x, self.Points[i].y))
  2178                         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], 
  2179                         self.Segments.insert(
  2144                                 self.Segments[i][0]), v_end, self.EndPoint[1]))
  2180                             i + 1,
       
  2181                             DirectionChoice((self.Segments[i][1],
       
  2182                                              self.Segments[i][0]), v_end, self.EndPoint[1]))
  2145             else:
  2183             else:
  2146                 # Current point is the first, and second is not mainly in the first direction
  2184                 # 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:
  2185                 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 
  2186                     # If first and second directions aren't perpendiculars, a point is added
  2149                     if product(self.Segments[0], self.Segments[1]) != 0:
  2187                     if product(self.Segments[0], self.Segments[1]) != 0:
  2150                         self.Points.insert(1, wx.Point(start.x, start.y))
  2188                         self.Points.insert(1, wx.Point(start.x, start.y))
  2151                         self.Segments.insert(1, DirectionChoice((self.Segments[0][1], 
  2189                         self.Segments.insert(
  2152                             self.Segments[0][0]), vector(start, self.Points[1]), self.Segments[1]))
  2190                             1,
       
  2191                             DirectionChoice((self.Segments[0][1],
       
  2192                                              self.Segments[0][0]),
       
  2193                                             vector(start, self.Points[1]),
       
  2194                                             self.Segments[1]))
  2153                     else:
  2195                     else:
  2154                         self.Points[1].x, self.Points[1].y = start.x, start.y
  2196                         self.Points[1].x, self.Points[1].y = start.x, start.y
  2155                 else:
  2197                 else:
  2156                     # Next point is aligned with current point
  2198                     # Next point is aligned with current point
  2157                     if self.Segments[i][0] != 0:
  2199                     if self.Segments[i][0] != 0:
  2163                         self.Segments[i] = (-self.Segments[i][0], -self.Segments[i][1])
  2205                         self.Segments[i] = (-self.Segments[i][0], -self.Segments[i][1])
  2164             i += 1
  2206             i += 1
  2165         self.RefreshBoundingBox()
  2207         self.RefreshBoundingBox()
  2166         if realpoints:
  2208         if realpoints:
  2167             self.RefreshRealPoints()
  2209             self.RefreshRealPoints()
  2168     
  2210 
  2169     # Verify that two consecutive points haven't the same position
  2211     # Verify that two consecutive points haven't the same position
  2170     def VerifyPoints(self):
  2212     def VerifyPoints(self):
  2171         points = [point for point in self.Points]
  2213         points = [point for point in self.Points]
  2172         segments = [segment for segment in self.Segments]
  2214         segments = [segment for segment in self.Segments]
  2173         i = 1
  2215         i = 1
  2183             self.Points = [point for point in points]
  2225             self.Points = [point for point in points]
  2184             self.Segments = [segment for segment in segments]
  2226             self.Segments = [segment for segment in segments]
  2185             self.RefreshBoundingBox()
  2227             self.RefreshBoundingBox()
  2186             self.RefreshRealPoints()
  2228             self.RefreshRealPoints()
  2187         return points
  2229         return points
  2188     
  2230 
  2189     # Moves all the wire points except the first and the last if they are connected
  2231     # Moves all the wire points except the first and the last if they are connected
  2190     def Move(self, dx, dy, endpoints = False):
  2232     def Move(self, dx, dy, endpoints=False):
  2191         for i, point in enumerate(self.Points):
  2233         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):
  2234             if endpoints or not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
  2193                 point.x += dx
  2235                 point.x += dx
  2194                 point.y += dy
  2236                 point.y += dy
  2195         self.StartPoint[0] = self.Points[0]
  2237         self.StartPoint[0] = self.Points[0]
  2196         self.EndPoint[0] = self.Points[-1]
  2238         self.EndPoint[0] = self.Points[-1]
  2197         self.GeneratePoints()
  2239         self.GeneratePoints()
  2198     
  2240 
  2199     # Resize the wire from position and size given
  2241     # Resize the wire from position and size given
  2200     def Resize(self, x, y, width, height):
  2242     def Resize(self, x, y, width, height):
  2201         if len(self.Points) > 1:
  2243         if len(self.Points) > 1:
  2202             # Calculate the new position of each point for testing the new size
  2244             # Calculate the new position of each point for testing the new size
  2203             minx, miny = self.Pos.x, self.Pos.y
  2245             minx, miny = self.Pos.x, self.Pos.y
  2210                     elif i == len(self.Points) - 1:
  2252                     elif i == len(self.Points) - 1:
  2211                         dir = self.EndPoint[1]
  2253                         dir = self.EndPoint[1]
  2212                     else:
  2254                     else:
  2213                         dir = (0, 0)
  2255                         dir = (0, 0)
  2214                     pointx = max(-dir[0] * MIN_SEGMENT_SIZE, min(int(round(point[0] * width / float(max(lastwidth, 1)))),
  2256                     pointx = max(-dir[0] * MIN_SEGMENT_SIZE, min(int(round(point[0] * width / float(max(lastwidth, 1)))),
  2215                             width - dir[0] * MIN_SEGMENT_SIZE))
  2257                                                                  width - dir[0] * MIN_SEGMENT_SIZE))
  2216                     pointy = max(-dir[1] * MIN_SEGMENT_SIZE, min(int(round(point[1] * height / float(max(lastheight, 1)))),
  2258                     pointy = max(-dir[1] * MIN_SEGMENT_SIZE, min(int(round(point[1] * height / float(max(lastheight, 1)))),
  2217                             height - dir[1] * MIN_SEGMENT_SIZE))
  2259                                                                  height - dir[1] * MIN_SEGMENT_SIZE))
  2218                     self.Points[i] = wx.Point(minx + x + pointx, miny + y + pointy)
  2260                     self.Points[i] = wx.Point(minx + x + pointx, miny + y + pointy)
  2219             self.StartPoint[0] = self.Points[0]
  2261             self.StartPoint[0] = self.Points[0]
  2220             self.EndPoint[0] = self.Points[-1]
  2262             self.EndPoint[0] = self.Points[-1]
  2221             self.GeneratePoints(False)
  2263             self.GeneratePoints(False)
  2222             # Test if the wire position or size have changed
  2264             # Test if the wire position or size have changed
  2244                         dir = self.StartPoint[1]
  2286                         dir = self.StartPoint[1]
  2245                     elif i == len(self.Points) - 1:
  2287                     elif i == len(self.Points) - 1:
  2246                         dir = self.EndPoint[1]
  2288                         dir = self.EndPoint[1]
  2247                     else:
  2289                     else:
  2248                         dir = (0, 0)
  2290                         dir = (0, 0)
  2249                     realpointx = max(-dir[0] * MIN_SEGMENT_SIZE, min(int(round(point[0])),
  2291                     realpointx = max(-dir[0] * MIN_SEGMENT_SIZE,
  2250                             width - dir[0] * MIN_SEGMENT_SIZE))
  2292                                      min(int(round(point[0])),
  2251                     realpointy = max(-dir[1] * MIN_SEGMENT_SIZE, min(int(round(point[1])),
  2293                                          width - dir[0] * MIN_SEGMENT_SIZE))
  2252                             height - dir[1] * MIN_SEGMENT_SIZE))
  2294                     realpointy = max(-dir[1] * MIN_SEGMENT_SIZE,
       
  2295                                      min(int(round(point[1])),
       
  2296                                          height - dir[1] * MIN_SEGMENT_SIZE))
  2253                     self.Points[i] = wx.Point(minx + x + realpointx, miny + y + realpointy)
  2297                     self.Points[i] = wx.Point(minx + x + realpointx, miny + y + realpointy)
  2254             self.StartPoint[0] = self.Points[0]
  2298             self.StartPoint[0] = self.Points[0]
  2255             self.EndPoint[0] = self.Points[-1]
  2299             self.EndPoint[0] = self.Points[-1]
  2256             self.GeneratePoints(False)
  2300             self.GeneratePoints(False)
  2257     
  2301 
  2258     # Moves the wire start point and update the wire points
  2302     # Moves the wire start point and update the wire points
  2259     def MoveStartPoint(self, point):
  2303     def MoveStartPoint(self, point):
  2260         if len(self.Points) > 1:
  2304         if len(self.Points) > 1:
  2261             self.StartPoint[0] = point
  2305             self.StartPoint[0] = point
  2262             self.Points[0] = point
  2306             self.Points[0] = point
  2263             self.GeneratePoints()
  2307             self.GeneratePoints()
  2264     
  2308 
  2265     # Changes the wire start direction and update the wire points
  2309     # Changes the wire start direction and update the wire points
  2266     def SetStartPointDirection(self, dir):
  2310     def SetStartPointDirection(self, dir):
  2267         if len(self.Points) > 1:
  2311         if len(self.Points) > 1:
  2268             self.StartPoint[1] = dir
  2312             self.StartPoint[1] = dir
  2269             self.Segments[0] = dir
  2313             self.Segments[0] = dir
  2270             self.GeneratePoints()
  2314             self.GeneratePoints()
  2271     
  2315 
  2272     # Rotates the wire start direction by an angle of 90 degrees anticlockwise
  2316     # Rotates the wire start direction by an angle of 90 degrees anticlockwise
  2273     def RotateStartPoint(self):
  2317     def RotateStartPoint(self):
  2274         self.SetStartPointDirection((self.StartPoint[1][1], -self.StartPoint[1][0]))
  2318         self.SetStartPointDirection((self.StartPoint[1][1], -self.StartPoint[1][0]))
  2275     
  2319 
  2276     # Connects wire start point to the connector given and moves wire start point
  2320     # Connects wire start point to the connector given and moves wire start point
  2277     # to given point
  2321     # to given point
  2278     def ConnectStartPoint(self, point, connector):
  2322     def ConnectStartPoint(self, point, connector):
  2279         if point:
  2323         if point:
  2280             self.MoveStartPoint(point)
  2324             self.MoveStartPoint(point)
  2281         self.StartConnected = connector
  2325         self.StartConnected = connector
  2282         self.RefreshBoundingBox()
  2326         self.RefreshBoundingBox()
  2283     
  2327 
  2284     # Unconnects wire start point
  2328     # Unconnects wire start point
  2285     def UnConnectStartPoint(self, delete = False):
  2329     def UnConnectStartPoint(self, delete=False):
  2286         if delete:
  2330         if delete:
  2287             self.StartConnected = None
  2331             self.StartConnected = None
  2288             self.Delete()
  2332             self.Delete()
  2289         elif self.StartConnected:
  2333         elif self.StartConnected:
  2290             self.StartConnected.UnConnect(self, unconnect = False)
  2334             self.StartConnected.UnConnect(self, unconnect=False)
  2291             self.StartConnected = None
  2335             self.StartConnected = None
  2292             self.RefreshBoundingBox()
  2336             self.RefreshBoundingBox()
  2293     
  2337 
  2294     # Moves the wire end point and update the wire points
  2338     # Moves the wire end point and update the wire points
  2295     def MoveEndPoint(self, point):
  2339     def MoveEndPoint(self, point):
  2296         if len(self.Points) > 1:
  2340         if len(self.Points) > 1:
  2297             self.EndPoint[0] = point
  2341             self.EndPoint[0] = point
  2298             self.Points[-1] = point
  2342             self.Points[-1] = point
  2301     # Changes the wire end direction and update the wire points
  2345     # Changes the wire end direction and update the wire points
  2302     def SetEndPointDirection(self, dir):
  2346     def SetEndPointDirection(self, dir):
  2303         if len(self.Points) > 1:
  2347         if len(self.Points) > 1:
  2304             self.EndPoint[1] = dir
  2348             self.EndPoint[1] = dir
  2305             self.GeneratePoints()
  2349             self.GeneratePoints()
  2306             
  2350 
  2307     # Rotates the wire end direction by an angle of 90 degrees anticlockwise
  2351     # Rotates the wire end direction by an angle of 90 degrees anticlockwise
  2308     def RotateEndPoint(self):
  2352     def RotateEndPoint(self):
  2309         self.SetEndPointDirection((self.EndPoint[1][1], -self.EndPoint[1][0]))
  2353         self.SetEndPointDirection((self.EndPoint[1][1], -self.EndPoint[1][0]))
  2310 
  2354 
  2311     # Connects wire end point to the connector given and moves wire end point
  2355     # Connects wire end point to the connector given and moves wire end point
  2313     def ConnectEndPoint(self, point, connector):
  2357     def ConnectEndPoint(self, point, connector):
  2314         if point:
  2358         if point:
  2315             self.MoveEndPoint(point)
  2359             self.MoveEndPoint(point)
  2316         self.EndConnected = connector
  2360         self.EndConnected = connector
  2317         self.RefreshBoundingBox()
  2361         self.RefreshBoundingBox()
  2318     
  2362 
  2319     # Unconnects wire end point
  2363     # Unconnects wire end point
  2320     def UnConnectEndPoint(self, delete = False):
  2364     def UnConnectEndPoint(self, delete=False):
  2321         if delete:
  2365         if delete:
  2322             self.EndConnected = None
  2366             self.EndConnected = None
  2323             self.Delete()
  2367             self.Delete()
  2324         elif self.EndConnected:
  2368         elif self.EndConnected:
  2325             self.EndConnected.UnConnect(self, unconnect = False)
  2369             self.EndConnected.UnConnect(self, unconnect=False)
  2326             self.EndConnected = None
  2370             self.EndConnected = None
  2327             self.RefreshBoundingBox()
  2371             self.RefreshBoundingBox()
  2328     
  2372 
  2329     # Moves the wire segment given by its index
  2373     # Moves the wire segment given by its index
  2330     def MoveSegment(self, idx, movex, movey, scaling):
  2374     def MoveSegment(self, idx, movex, movey, scaling):
  2331         if 0 < idx < len(self.Segments) - 1:
  2375         if 0 < idx < len(self.Segments) - 1:
  2332             if self.Segments[idx] in (NORTH, SOUTH):
  2376             if self.Segments[idx] in (NORTH, SOUTH):
  2333                 start_x = self.Points[idx].x
  2377                 start_x = self.Points[idx].x
  2354                 self.Points[idx + 1].y += movey
  2398                 self.Points[idx + 1].y += movey
  2355                 self.GeneratePoints()
  2399                 self.GeneratePoints()
  2356                 if start_y != self.Points[idx].y:
  2400                 if start_y != self.Points[idx].y:
  2357                     return 0, self.Points[idx].y - start_y
  2401                     return 0, self.Points[idx].y - start_y
  2358         return 0, 0
  2402         return 0, 0
  2359     
  2403 
  2360     # Adds two points in the middle of the handled segment
  2404     # Adds two points in the middle of the handled segment
  2361     def AddSegment(self):
  2405     def AddSegment(self):
  2362         handle_type, handle = self.Handle
  2406         handle_type, handle = self.Handle
  2363         if handle_type == HANDLE_SEGMENT:
  2407         if handle_type == HANDLE_SEGMENT:
  2364             segment, dir = handle
  2408             segment, dir = handle
  2389                 self.Points.insert(segment + 3, wx.Point(p2x, p2y))
  2433                 self.Points.insert(segment + 3, wx.Point(p2x, p2y))
  2390                 self.Segments.insert(segment + 3, (dir[1], dir[0]))
  2434                 self.Segments.insert(segment + 3, (dir[1], dir[0]))
  2391                 self.Points.insert(segment + 4, wx.Point(p2x, p2y))
  2435                 self.Points.insert(segment + 4, wx.Point(p2x, p2y))
  2392                 self.Segments.insert(segment + 4, dir)
  2436                 self.Segments.insert(segment + 4, dir)
  2393             self.GeneratePoints()
  2437             self.GeneratePoints()
  2394     
  2438 
  2395     # Delete the handled segment by removing the two segment points
  2439     # Delete the handled segment by removing the two segment points
  2396     def DeleteSegment(self):
  2440     def DeleteSegment(self):
  2397         handle_type, handle = self.Handle
  2441         handle_type, handle = self.Handle
  2398         if handle_type == HANDLE_SEGMENT:
  2442         if handle_type == HANDLE_SEGMENT:
  2399             segment, dir = handle
  2443             segment, dir = handle
  2400             for i in xrange(2):
  2444             for i in xrange(2):
  2401                 self.Points.pop(segment)
  2445                 self.Points.pop(segment)
  2402                 self.Segments.pop(segment)
  2446                 self.Segments.pop(segment)
  2403             self.GeneratePoints()
  2447             self.GeneratePoints()
  2404             self.RefreshModel()
  2448             self.RefreshModel()
  2405             
  2449 
  2406     # Method called when a LeftDown event have been generated
  2450     # Method called when a LeftDown event have been generated
  2407     def OnLeftDown(self, event, dc, scaling):
  2451     def OnLeftDown(self, event, dc, scaling):
  2408         pos = GetScaledEventPosition(event, dc, scaling)
  2452         pos = GetScaledEventPosition(event, dc, scaling)
  2409         # Test if a point have been handled
  2453         # Test if a point have been handled
  2410         #result = self.TestPoint(pos)
  2454         # result = self.TestPoint(pos)
  2411         #if result != None:
  2455         # if result != None:
  2412         #    self.Handle = (HANDLE_POINT, result)
  2456         #    self.Handle = (HANDLE_POINT, result)
  2413         #    wx.CallAfter(self.Parent.SetCurrentCursor, 1)
  2457         #    wx.CallAfter(self.Parent.SetCurrentCursor, 1)
  2414         #else:
  2458         # else:
  2415         # Test if a segment have been handled
  2459         # Test if a segment have been handled
  2416         result = self.TestSegment(pos)
  2460         result = self.TestSegment(pos)
  2417         if result != None:
  2461         if result is not None:
  2418             if result[1] in (NORTH, SOUTH):
  2462             if result[1] in (NORTH, SOUTH):
  2419                 wx.CallAfter(self.Parent.SetCurrentCursor, 4)
  2463                 wx.CallAfter(self.Parent.SetCurrentCursor, 4)
  2420             elif result[1] in (EAST, WEST):
  2464             elif result[1] in (EAST, WEST):
  2421                 wx.CallAfter(self.Parent.SetCurrentCursor, 5)
  2465                 wx.CallAfter(self.Parent.SetCurrentCursor, 5)
  2422             self.Handle = (HANDLE_SEGMENT, result)
  2466             self.Handle = (HANDLE_SEGMENT, result)
  2423         # Execute the default method for a graphic element
  2467         # Execute the default method for a graphic element
  2424         else:
  2468         else:
  2425             Graphic_Element.OnLeftDown(self, event, dc, scaling)
  2469             Graphic_Element.OnLeftDown(self, event, dc, scaling)
  2426         self.oldPos = pos
  2470         self.oldPos = pos
  2427     
  2471 
  2428     # Method called when a RightUp event has been generated
  2472     # Method called when a RightUp event has been generated
  2429     def OnRightUp(self, event, dc, scaling):
  2473     def OnRightUp(self, event, dc, scaling):
  2430         pos = GetScaledEventPosition(event, dc, scaling)
  2474         pos = GetScaledEventPosition(event, dc, scaling)
  2431         # Test if a segment has been handled
  2475         # Test if a segment has been handled
  2432         result = self.TestSegment(pos, True)
  2476         result = self.TestSegment(pos, True)
  2433         if result != None:
  2477         if result is not None:
  2434             self.Handle = (HANDLE_SEGMENT, result)
  2478             self.Handle = (HANDLE_SEGMENT, result)
  2435             # Popup the menu with special items for a wire
  2479             # Popup the menu with special items for a wire
  2436             self.Parent.PopupWireMenu(0 < result[0] < len(self.Segments) - 1)
  2480             self.Parent.PopupWireMenu(0 < result[0] < len(self.Segments) - 1)
  2437         else:
  2481         else:
  2438             # Execute the default method for a graphic element
  2482             # Execute the default method for a graphic element
  2439             Graphic_Element.OnRightUp(self, event, dc, scaling)
  2483             Graphic_Element.OnRightUp(self, event, dc, scaling)
  2440     
  2484 
  2441     # Method called when a LeftDClick event has been generated
  2485     # Method called when a LeftDClick event has been generated
  2442     def OnLeftDClick(self, event, dc, scaling):
  2486     def OnLeftDClick(self, event, dc, scaling):
  2443         rect = self.GetRedrawRect()
  2487         rect = self.GetRedrawRect()
  2444         if event.ControlDown():
  2488         if event.ControlDown():
  2445             direction = (self.StartPoint[1], self.EndPoint[1])
  2489             direction = (self.StartPoint[1], self.EndPoint[1])
  2490             self.GeneratePoints()
  2534             self.GeneratePoints()
  2491             self.RefreshModel()
  2535             self.RefreshModel()
  2492             self.Parent.RefreshBuffer()
  2536             self.Parent.RefreshBuffer()
  2493         rect.Union(self.GetRedrawRect())
  2537         rect.Union(self.GetRedrawRect())
  2494         self.Parent.RefreshRect(self.Parent.GetScrolledRect(rect), False)
  2538         self.Parent.RefreshRect(self.Parent.GetScrolledRect(rect), False)
  2495         
  2539 
  2496     # Method called when a Motion event has been generated
  2540     # Method called when a Motion event has been generated
  2497     def OnMotion(self, event, dc, scaling):
  2541     def OnMotion(self, event, dc, scaling):
  2498         pos = GetScaledEventPosition(event, dc, scaling)
  2542         pos = GetScaledEventPosition(event, dc, scaling)
  2499         if not event.Dragging():
  2543         if not event.Dragging():
  2500             # Test if a segment has been handled
  2544             # Test if a segment has been handled
  2509                 # Execute the default method for a graphic element
  2553                 # Execute the default method for a graphic element
  2510                 return Graphic_Element.OnMotion(self, event, dc, scaling)
  2554                 return Graphic_Element.OnMotion(self, event, dc, scaling)
  2511         else:
  2555         else:
  2512             # Execute the default method for a graphic element
  2556             # Execute the default method for a graphic element
  2513             return Graphic_Element.OnMotion(self, event, dc, scaling)
  2557             return Graphic_Element.OnMotion(self, event, dc, scaling)
  2514     
  2558 
  2515     # Refreshes the wire state according to move defined and handle selected
  2559     # Refreshes the wire state according to move defined and handle selected
  2516     def ProcessDragging(self, movex, movey, event, scaling):
  2560     def ProcessDragging(self, movex, movey, event, scaling):
  2517         handle_type, handle = self.Handle
  2561         handle_type, handle = self.Handle
  2518         # A point has been handled
  2562         # A point has been handled
  2519         if handle_type == HANDLE_POINT:
  2563         if handle_type == HANDLE_POINT:
  2570         elif handle_type == HANDLE_SEGMENT:
  2614         elif handle_type == HANDLE_SEGMENT:
  2571             return self.MoveSegment(handle[0], movex, movey, scaling)
  2615             return self.MoveSegment(handle[0], movex, movey, scaling)
  2572         # Execute the default method for a graphic element
  2616         # Execute the default method for a graphic element
  2573         else:
  2617         else:
  2574             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  2618             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  2575     
  2619 
  2576     # Refreshes the wire model
  2620     # Refreshes the wire model
  2577     def RefreshModel(self, move=True):
  2621     def RefreshModel(self, move=True):
  2578         if self.StartConnected and self.StartPoint[1] in [WEST, NORTH]:
  2622         if self.StartConnected and self.StartPoint[1] in [WEST, NORTH]:
  2579             self.StartConnected.RefreshParentBlock()
  2623             self.StartConnected.RefreshParentBlock()
  2580         if self.EndConnected and self.EndPoint[1] in [WEST, NORTH]:
  2624         if self.EndConnected and self.EndPoint[1] in [WEST, NORTH]:
  2581             self.EndConnected.RefreshParentBlock()
  2625             self.EndConnected.RefreshParentBlock()
  2582     
  2626 
  2583     # Change the variable that indicates if this element is highlighted
  2627     # Change the variable that indicates if this element is highlighted
  2584     def SetHighlighted(self, highlighted):
  2628     def SetHighlighted(self, highlighted):
  2585         self.Highlighted = highlighted
  2629         self.Highlighted = highlighted
  2586         if not highlighted:
  2630         if not highlighted:
  2587             self.OverStart = False
  2631             self.OverStart = False
  2588             self.OverEnd = False
  2632             self.OverEnd = False
  2589         self.Refresh()
  2633         self.Refresh()
  2590     
  2634 
  2591     def HighlightPoint(self, pos):
  2635     def HighlightPoint(self, pos):
  2592         refresh = False
  2636         refresh = False
  2593         start, end = self.OverStart, self.OverEnd
  2637         start, end = self.OverStart, self.OverEnd
  2594         self.OverStart = False
  2638         self.OverStart = False
  2595         self.OverEnd = False
  2639         self.OverEnd = False
  2596         # Test if a point has been handled
  2640         # Test if a point has been handled
  2597         result = self.TestPoint(pos)
  2641         result = self.TestPoint(pos)
  2598         if result != None:
  2642         if result is not None:
  2599             if result == 0 and self.StartConnected is not None:
  2643             if result == 0 and self.StartConnected is not None:
  2600                 self.OverStart = True
  2644                 self.OverStart = True
  2601             elif result != 0 and self.EndConnected is not None:
  2645             elif result != 0 and self.EndConnected is not None:
  2602                 self.OverEnd = True
  2646                 self.OverEnd = True
  2603         if start != self.OverStart or end != self.OverEnd:
  2647         if start != self.OverStart or end != self.OverEnd:
  2604             self.Refresh()
  2648             self.Refresh()
  2605     
  2649 
  2606     # Draws the highlightment of this element if it is highlighted
  2650     # Draws the highlightment of this element if it is highlighted
  2607     def DrawHighlightment(self, dc):
  2651     def DrawHighlightment(self, dc):
  2608         scalex, scaley = dc.GetUserScale()
  2652         scalex, scaley = dc.GetUserScale()
  2609         dc.SetUserScale(1, 1)
  2653         dc.SetUserScale(1, 1)
  2610         # If user trying to connect wire with wrong input, highlight will become red.
  2654         # If user trying to connect wire with wrong input, highlight will become red.
  2611         if self.ErrHighlight == True and not (self.EndConnected):
  2655         if self.ErrHighlight and not (self.EndConnected):
  2612             highlightcolor = wx.RED
  2656             highlightcolor = wx.RED
  2613         else:
  2657         else:
  2614             highlightcolor = HIGHLIGHTCOLOR
  2658             highlightcolor = HIGHLIGHTCOLOR
  2615         dc.SetPen(MiterPen(highlightcolor, (2 * scalex + 5)))
  2659         dc.SetPen(MiterPen(highlightcolor, (2 * scalex + 5)))
  2616         dc.SetBrush(wx.Brush(highlightcolor))
  2660         dc.SetBrush(wx.Brush(highlightcolor))
  2617         dc.SetLogicalFunction(wx.AND)
  2661         dc.SetLogicalFunction(wx.AND)
  2618         # Draw the start and end points if they are not connected or the mouse is over them
  2662         # 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):
  2663         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2620             dc.DrawCircle(round(self.Points[0].x * scalex), 
  2664             dc.DrawCircle(round(self.Points[0].x * scalex),
  2621                           round(self.Points[0].y * scaley), 
  2665                           round(self.Points[0].y * scaley),
  2622                           (POINT_RADIUS + 1) * scalex + 2)
  2666                           (POINT_RADIUS + 1) * scalex + 2)
  2623         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2667         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)
  2668             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)
  2669         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2626         if len(self.Points) > 1:
  2670         if len(self.Points) > 1:
  2627             points = [wx.Point(round((self.Points[0].x - self.Segments[0][0]) * scalex), 
  2671             points = [wx.Point(round((self.Points[0].x - self.Segments[0][0]) * scalex),
  2628                                round((self.Points[0].y - self.Segments[0][1]) * scaley))]
  2672                                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]])
  2673             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), 
  2674             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)))
  2675                                    round((self.Points[-1].y + self.Segments[-1][1]) * scaley)))
  2632         else:
  2676         else:
  2633             points = []
  2677             points = []
  2634         dc.DrawLines(points)
  2678         dc.DrawLines(points)
  2635         dc.SetLogicalFunction(wx.COPY)
  2679         dc.SetLogicalFunction(wx.COPY)
  2636         dc.SetUserScale(scalex, scaley)
  2680         dc.SetUserScale(scalex, scaley)
  2637         
  2681 
  2638         if self.StartConnected is not None:
  2682         if self.StartConnected is not None:
  2639             self.StartConnected.DrawHighlightment(dc)
  2683             self.StartConnected.DrawHighlightment(dc)
  2640             self.StartConnected.Draw(dc)
  2684             self.StartConnected.Draw(dc)
  2641         if self.EndConnected is not None:
  2685         if self.EndConnected is not None:
  2642             self.EndConnected.DrawHighlightment(dc)
  2686             self.EndConnected.DrawHighlightment(dc)
  2643             self.EndConnected.Draw(dc)
  2687             self.EndConnected.Draw(dc)
  2644     
  2688 
  2645     # Draws the wire lines and points
  2689     # Draws the wire lines and points
  2646     def Draw(self, dc):
  2690     def Draw(self, dc):
  2647         Graphic_Element.Draw(self, dc)
  2691         Graphic_Element.Draw(self, dc)
  2648         if not self.Valid:
  2692         if not self.Valid:
  2649             dc.SetPen(MiterPen(wx.RED))
  2693             dc.SetPen(MiterPen(wx.RED))
  2710                     dc.DrawText(self.ComputedValue, x, y)
  2754                     dc.DrawText(self.ComputedValue, x, y)
  2711             dc.SetFont(self.Parent.GetFont())
  2755             dc.SetFont(self.Parent.GetFont())
  2712             dc.SetTextForeground(wx.BLACK)
  2756             dc.SetTextForeground(wx.BLACK)
  2713 
  2757 
  2714 
  2758 
  2715 #-------------------------------------------------------------------------------
  2759 # -------------------------------------------------------------------------------
  2716 #                           Graphic comment element
  2760 #                           Graphic comment element
  2717 #-------------------------------------------------------------------------------
  2761 # -------------------------------------------------------------------------------
       
  2762 
  2718 
  2763 
  2719 def FilterHighlightsByRow(highlights, row, length):
  2764 def FilterHighlightsByRow(highlights, row, length):
  2720     _highlights = []
  2765     _highlights = []
  2721     for start, end, highlight_type in highlights:
  2766     for start, end, highlight_type in highlights:
  2722         if start[0] <= row and end[0] >= row:
  2767         if start[0] <= row and end[0] >= row:
  2725             if end[0] > row:
  2770             if end[0] > row:
  2726                 end = (row, length)
  2771                 end = (row, length)
  2727             _highlights.append((start, end, highlight_type))
  2772             _highlights.append((start, end, highlight_type))
  2728     return _highlights
  2773     return _highlights
  2729 
  2774 
       
  2775 
  2730 def FilterHighlightsByColumn(highlights, start_col, end_col):
  2776 def FilterHighlightsByColumn(highlights, start_col, end_col):
  2731     _highlights = []
  2777     _highlights = []
  2732     for start, end, highlight_type in highlights:
  2778     for start, end, highlight_type in highlights:
  2733         if end[1] > start_col and start[1] < end_col:
  2779         if end[1] > start_col and start[1] < end_col:
  2734             start = (start[0], max(start[1], start_col) - start_col)
  2780             start = (start[0], max(start[1], start_col) - start_col)
  2735             end = (end[0], min(end[1], end_col) - start_col)
  2781             end = (end[0], min(end[1], end_col) - start_col)
  2736             _highlights.append((start, end, highlight_type))
  2782             _highlights.append((start, end, highlight_type))
  2737     return _highlights
  2783     return _highlights
  2738 
  2784 
  2739 """
       
  2740 Class that implements a comment
       
  2741 """
       
  2742 
  2785 
  2743 class Comment(Graphic_Element):
  2786 class Comment(Graphic_Element):
       
  2787     """
       
  2788     Class that implements a comment
       
  2789     """
  2744 
  2790 
  2745     # Create a new comment
  2791     # Create a new comment
  2746     def __init__(self, parent, content, id = None):
  2792     def __init__(self, parent, content, id=None):
  2747         Graphic_Element.__init__(self, parent)
  2793         Graphic_Element.__init__(self, parent)
  2748         self.Id = id
  2794         self.Id = id
  2749         self.Content = content
  2795         self.Content = content
  2750         self.Pos = wx.Point(0, 0)
  2796         self.Pos = wx.Point(0, 0)
  2751         self.Size = wx.Size(0, 0)
  2797         self.Size = wx.Size(0, 0)
  2752         self.Highlights = []
  2798         self.Highlights = []
  2753     
  2799 
  2754     # Make a clone of this comment
  2800     # Make a clone of this comment
  2755     def Clone(self, parent, id = None, pos = None):
  2801     def Clone(self, parent, id=None, pos=None):
  2756         comment = Comment(parent, self.Content, id)
  2802         comment = Comment(parent, self.Content, id)
  2757         if pos is not None:
  2803         if pos is not None:
  2758             comment.SetPosition(pos.x, pos.y)
  2804             comment.SetPosition(pos.x, pos.y)
  2759         comment.SetSize(self.Size[0], self.Size[1])
  2805         comment.SetSize(self.Size[0], self.Size[1])
  2760         return comment
  2806         return comment
  2761     
  2807 
  2762     # Method for keeping compatibility with others
  2808     # Method for keeping compatibility with others
  2763     def Clean(self):
  2809     def Clean(self):
  2764         pass
  2810         pass
  2765     
  2811 
  2766     # Delete this comment by calling the corresponding method
  2812     # Delete this comment by calling the corresponding method
  2767     def Delete(self):
  2813     def Delete(self):
  2768         self.Parent.DeleteComment(self)
  2814         self.Parent.DeleteComment(self)
  2769     
  2815 
  2770     # Refresh the comment bounding box
  2816     # Refresh the comment bounding box
  2771     def RefreshBoundingBox(self):
  2817     def RefreshBoundingBox(self):
  2772         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  2818         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  2773     
  2819 
  2774     # Changes the comment size
  2820     # Changes the comment size
  2775     def SetSize(self, width, height):
  2821     def SetSize(self, width, height):
  2776         self.Size.SetWidth(width)
  2822         self.Size.SetWidth(width)
  2777         self.Size.SetHeight(height)
  2823         self.Size.SetHeight(height)
  2778         self.RefreshBoundingBox()
  2824         self.RefreshBoundingBox()
  2779 
  2825 
  2780     # Returns the comment size
  2826     # Returns the comment size
  2781     def GetSize(self):
  2827     def GetSize(self):
  2782         return self.Size.GetWidth(), self.Size.GetHeight()
  2828         return self.Size.GetWidth(), self.Size.GetHeight()
  2783     
  2829 
  2784     # Returns the comment minimum size
  2830     # Returns the comment minimum size
  2785     def GetMinSize(self):
  2831     def GetMinSize(self):
  2786         dc = wx.ClientDC(self.Parent)
  2832         dc = wx.ClientDC(self.Parent)
  2787         min_width = 0
  2833         min_width = 0
  2788         min_height = 0
  2834         min_height = 0
  2791             for word in line.split(" "):
  2837             for word in line.split(" "):
  2792                 wordwidth, wordheight = dc.GetTextExtent(word)
  2838                 wordwidth, wordheight = dc.GetTextExtent(word)
  2793                 min_width = max(min_width, wordwidth)
  2839                 min_width = max(min_width, wordwidth)
  2794                 min_height = max(min_height, wordheight)
  2840                 min_height = max(min_height, wordheight)
  2795         return min_width + 20, min_height + 20
  2841         return min_width + 20, min_height + 20
  2796     
  2842 
  2797     # Changes the comment position
  2843     # Changes the comment position
  2798     def SetPosition(self, x, y):
  2844     def SetPosition(self, x, y):
  2799         self.Pos.x = x
  2845         self.Pos.x = x
  2800         self.Pos.y = y
  2846         self.Pos.y = y
  2801         self.RefreshBoundingBox()
  2847         self.RefreshBoundingBox()
  2813         return self.Content
  2859         return self.Content
  2814 
  2860 
  2815     # Returns the comment position
  2861     # Returns the comment position
  2816     def GetPosition(self):
  2862     def GetPosition(self):
  2817         return self.Pos.x, self.Pos.y
  2863         return self.Pos.x, self.Pos.y
  2818     
  2864 
  2819     # Moves the comment
  2865     # Moves the comment
  2820     def Move(self, dx, dy, connected = True):
  2866     def Move(self, dx, dy, connected=True):
  2821         self.Pos.x += dx
  2867         self.Pos.x += dx
  2822         self.Pos.y += dy
  2868         self.Pos.y += dy
  2823         self.RefreshBoundingBox()
  2869         self.RefreshBoundingBox()
  2824     
  2870 
  2825     # Resizes the comment with the position and the size given
  2871     # Resizes the comment with the position and the size given
  2826     def Resize(self, x, y, width, height):
  2872     def Resize(self, x, y, width, height):
  2827         self.Move(x, y)
  2873         self.Move(x, y)
  2828         self.SetSize(width, height)
  2874         self.SetSize(width, height)
  2829     
  2875 
  2830     # Method called when a RightUp event have been generated
  2876     # Method called when a RightUp event have been generated
  2831     def OnRightUp(self, event, dc, scaling):
  2877     def OnRightUp(self, event, dc, scaling):
  2832         # Popup the default menu
  2878         # Popup the default menu
  2833         self.Parent.PopupDefaultMenu()
  2879         self.Parent.PopupDefaultMenu()
  2834     
  2880 
  2835     # Refreshes the wire state according to move defined and handle selected
  2881     # Refreshes the wire state according to move defined and handle selected
  2836     def ProcessDragging(self, movex, movey, event, scaling):
  2882     def ProcessDragging(self, movex, movey, event, scaling):
  2837         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE and self.Parent.CurrentLanguage == "LD":
  2883         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE and self.Parent.CurrentLanguage == "LD":
  2838             movex = movey = 0
  2884             movex = movey = 0
  2839         return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  2885         return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  2840         
  2886 
  2841     # Refreshes the comment model
  2887     # Refreshes the comment model
  2842     def RefreshModel(self, move=True):
  2888     def RefreshModel(self, move=True):
  2843         self.Parent.RefreshCommentModel(self)
  2889         self.Parent.RefreshCommentModel(self)
  2844     
  2890 
  2845     # Method called when a LeftDClick event have been generated
  2891     # Method called when a LeftDClick event have been generated
  2846     def OnLeftDClick(self, event, dc, scaling):
  2892     def OnLeftDClick(self, event, dc, scaling):
  2847         # Edit the comment content
  2893         # Edit the comment content
  2848         self.Parent.EditCommentContent(self)
  2894         self.Parent.EditCommentContent(self)
  2849     
  2895 
  2850     # Adds an highlight to the comment
  2896     # Adds an highlight to the comment
  2851     def AddHighlight(self, infos, start, end, highlight_type):
  2897     def AddHighlight(self, infos, start, end, highlight_type):
  2852         if infos[0] == "content":
  2898         if infos[0] == "content":
  2853             AddHighlight(self.Highlights, (start, end, highlight_type))
  2899             AddHighlight(self.Highlights, (start, end, highlight_type))
  2854     
  2900 
  2855     # Removes an highlight from the comment
  2901     # Removes an highlight from the comment
  2856     def RemoveHighlight(self, infos, start, end, highlight_type):
  2902     def RemoveHighlight(self, infos, start, end, highlight_type):
  2857         RemoveHighlight(self.Highlights, (start, end, highlight_type))
  2903         RemoveHighlight(self.Highlights, (start, end, highlight_type))
  2858     
  2904 
  2859     # Removes all the highlights of one particular type from the comment
  2905     # Removes all the highlights of one particular type from the comment
  2860     def ClearHighlight(self, highlight_type=None):
  2906     def ClearHighlight(self, highlight_type=None):
  2861         self.Highlights = ClearHighlights(self.Highlights, highlight_type)
  2907         self.Highlights = ClearHighlights(self.Highlights, highlight_type)
  2862     
  2908 
  2863     # Draws the highlightment of this element if it is highlighted
  2909     # Draws the highlightment of this element if it is highlighted
  2864     def DrawHighlightment(self, dc):
  2910     def DrawHighlightment(self, dc):
  2865         scalex, scaley = dc.GetUserScale()
  2911         scalex, scaley = dc.GetUserScale()
  2866         dc.SetUserScale(1, 1)
  2912         dc.SetUserScale(1, 1)
  2867         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  2913         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  2868         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2914         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2869         dc.SetLogicalFunction(wx.AND)
  2915         dc.SetLogicalFunction(wx.AND)
  2870         
  2916 
  2871         left = (self.Pos.x - 1) * scalex - 2
  2917         left = (self.Pos.x - 1) * scalex - 2
  2872         right = (self.Pos.x + self.Size[0] + 1) * scalex + 2
  2918         right = (self.Pos.x + self.Size[0] + 1) * scalex + 2
  2873         top = (self.Pos.y - 1) * scaley - 2
  2919         top = (self.Pos.y - 1) * scaley - 2
  2874         bottom = (self.Pos.y + self.Size[1] + 1) * scaley + 2
  2920         bottom = (self.Pos.y + self.Size[1] + 1) * scaley + 2
  2875         angle_top = (self.Pos.x + self.Size[0] - 9) * scalex + 2
  2921         angle_top = (self.Pos.x + self.Size[0] - 9) * scalex + 2
  2876         angle_right = (self.Pos.y + 9) * scaley - 2
  2922         angle_right = (self.Pos.y + 9) * scaley - 2
  2877         
  2923 
  2878         polygon = [wx.Point(left, top), wx.Point(angle_top, top),
  2924         polygon = [wx.Point(left, top), wx.Point(angle_top, top),
  2879                    wx.Point(right, angle_right), wx.Point(right, bottom),
  2925                    wx.Point(right, angle_right), wx.Point(right, bottom),
  2880                    wx.Point(left, bottom)]
  2926                    wx.Point(left, bottom)]
  2881         dc.DrawPolygon(polygon)
  2927         dc.DrawPolygon(polygon)
  2882         
  2928 
  2883         dc.SetLogicalFunction(wx.COPY)
  2929         dc.SetLogicalFunction(wx.COPY)
  2884         dc.SetUserScale(scalex, scaley)
  2930         dc.SetUserScale(scalex, scaley)
  2885         
  2931 
  2886     # Draws the comment and its content
  2932     # Draws the comment and its content
  2887     def Draw(self, dc):
  2933     def Draw(self, dc):
  2888         Graphic_Element.Draw(self, dc)
  2934         Graphic_Element.Draw(self, dc)
  2889         dc.SetPen(MiterPen(wx.BLACK))
  2935         dc.SetPen(MiterPen(wx.BLACK))
  2890         dc.SetBrush(wx.WHITE_BRUSH)
  2936         dc.SetBrush(wx.WHITE_BRUSH)
  2891         # Draws the comment shape
  2937         # Draws the comment shape
  2892         polygon = [wx.Point(self.Pos.x, self.Pos.y), 
  2938         polygon = [wx.Point(self.Pos.x, self.Pos.y),
  2893                    wx.Point(self.Pos.x + self.Size[0] - 10, self.Pos.y),
  2939                    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),
  2940                    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]),
  2941                    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])]
  2942                    wx.Point(self.Pos.x, self.Pos.y + self.Size[1])]
  2897         dc.DrawPolygon(polygon)
  2943         dc.DrawPolygon(polygon)
  2949                     else:
  2995                     else:
  2950                         linetext = word
  2996                         linetext = word
  2951                     y += wordheight + 5
  2997                     y += wordheight + 5
  2952             if y + wordheight > self.Pos.y + self.Size[1] - 10:
  2998             if y + wordheight > self.Pos.y + self.Size[1] - 10:
  2953                 break
  2999                 break
  2954