graphics/SFC_Objects.py
changeset 1784 64beb9e9c749
parent 1782 5b6ad7a7fd9d
child 1846 14b40afccd69
equal deleted inserted replaced
1729:31e63e25b4cc 1784:64beb9e9c749
    26 
    26 
    27 from graphics.GraphicCommons import *
    27 from graphics.GraphicCommons import *
    28 from graphics.DebugDataConsumer import DebugDataConsumer
    28 from graphics.DebugDataConsumer import DebugDataConsumer
    29 from plcopen.structures import *
    29 from plcopen.structures import *
    30 
    30 
       
    31 
    31 def GetWireSize(block):
    32 def GetWireSize(block):
    32     if isinstance(block, SFC_Step):
    33     if isinstance(block, SFC_Step):
    33         return SFC_WIRE_MIN_SIZE + block.GetActionExtraLineNumber() * SFC_ACTION_MIN_SIZE[1]
    34         return SFC_WIRE_MIN_SIZE + block.GetActionExtraLineNumber() * SFC_ACTION_MIN_SIZE[1]
    34     else:
    35     else:
    35         return SFC_WIRE_MIN_SIZE
    36         return SFC_WIRE_MIN_SIZE
    36 
    37 
    37 #-------------------------------------------------------------------------------
    38 # -------------------------------------------------------------------------------
    38 #                         Sequencial Function Chart Step
    39 #                         Sequencial Function Chart Step
    39 #-------------------------------------------------------------------------------
    40 # -------------------------------------------------------------------------------
    40 
    41 
    41 """
       
    42 Class that implements the graphic representation of a step
       
    43 """
       
    44 
    42 
    45 class SFC_Step(Graphic_Element, DebugDataConsumer):
    43 class SFC_Step(Graphic_Element, DebugDataConsumer):
    46     
    44     """
       
    45     Class that implements the graphic representation of a step
       
    46     """
       
    47 
    47     # Create a new step
    48     # Create a new step
    48     def __init__(self, parent, name, initial = False, id = None):
    49     def __init__(self, parent, name, initial=False, id=None):
    49         Graphic_Element.__init__(self, parent)
    50         Graphic_Element.__init__(self, parent)
    50         DebugDataConsumer.__init__(self)
    51         DebugDataConsumer.__init__(self)
    51         self.SetName(name)
    52         self.SetName(name)
    52         self.Initial = initial
    53         self.Initial = initial
    53         self.Id = id
    54         self.Id = id
    60             self.Input = None
    61             self.Input = None
    61         self.Output = None
    62         self.Output = None
    62         self.Action = None
    63         self.Action = None
    63         self.PreviousValue = None
    64         self.PreviousValue = None
    64         self.PreviousSpreading = False
    65         self.PreviousSpreading = False
    65     
    66 
    66     def Flush(self):
    67     def Flush(self):
    67         if self.Input is not None:
    68         if self.Input is not None:
    68             self.Input.Flush()
    69             self.Input.Flush()
    69             self.Input = None
    70             self.Input = None
    70         if self.Output is not None:
    71         if self.Output is not None:
    71             self.Output.Flush()
    72             self.Output.Flush()
    72             self.Output = None
    73             self.Output = None
    73         if self.Action is not None:
    74         if self.Action is not None:
    74             self.Action.Flush()
    75             self.Action.Flush()
    75             self.Action = None
    76             self.Action = None
    76     
    77 
    77     def SetForced(self, forced):
    78     def SetForced(self, forced):
    78         if self.Forced != forced:
    79         if self.Forced != forced:
    79             self.Forced = forced
    80             self.Forced = forced
    80             if self.Visible:
    81             if self.Visible:
    81                 self.Parent.ElementNeedRefresh(self)
    82                 self.Parent.ElementNeedRefresh(self)
    82     
    83 
    83     def SetValue(self, value):
    84     def SetValue(self, value):
    84         self.PreviousValue = self.Value
    85         self.PreviousValue = self.Value
    85         self.Value = value
    86         self.Value = value
    86         if self.Value != self.PreviousValue:
    87         if self.Value != self.PreviousValue:
    87             if self.Visible:
    88             if self.Visible:
    88                 self.Parent.ElementNeedRefresh(self)
    89                 self.Parent.ElementNeedRefresh(self)
    89             self.SpreadCurrent()
    90             self.SpreadCurrent()
    90     
    91 
    91     def SpreadCurrent(self):
    92     def SpreadCurrent(self):
    92         if self.Parent.Debug:
    93         if self.Parent.Debug:
    93             spreading = self.Value
    94             spreading = self.Value
    94             if spreading and not self.PreviousSpreading:
    95             if spreading and not self.PreviousSpreading:
    95                 if self.Output is not None:
    96                 if self.Output is not None:
   100                 if self.Output is not None:
   101                 if self.Output is not None:
   101                     self.Output.SpreadCurrent(False)
   102                     self.Output.SpreadCurrent(False)
   102                 if self.Action is not None:
   103                 if self.Action is not None:
   103                     self.Action.SpreadCurrent(False)
   104                     self.Action.SpreadCurrent(False)
   104             self.PreviousSpreading = spreading
   105             self.PreviousSpreading = spreading
   105     
   106 
   106     # Make a clone of this SFC_Step
   107     # Make a clone of this SFC_Step
   107     def Clone(self, parent, id = None, name = "Step", pos = None):
   108     def Clone(self, parent, id=None, name="Step", pos=None):
   108         step = SFC_Step(parent, name, self.Initial, id)
   109         step = SFC_Step(parent, name, self.Initial, id)
   109         step.SetSize(self.Size[0], self.Size[1])
   110         step.SetSize(self.Size[0], self.Size[1])
   110         if pos is not None:
   111         if pos is not None:
   111             step.SetPosition(pos.x, pos.y)
   112             step.SetPosition(pos.x, pos.y)
   112         else:
   113         else:
   116         if self.Output:
   117         if self.Output:
   117             step.Output = self.Output.Clone(step)
   118             step.Output = self.Output.Clone(step)
   118         if self.Action:
   119         if self.Action:
   119             step.Action = self.Action.Clone(step)
   120             step.Action = self.Action.Clone(step)
   120         return step
   121         return step
   121     
   122 
   122     def GetConnectorTranslation(self, element):
   123     def GetConnectorTranslation(self, element):
   123         connectors = {}
   124         connectors = {}
   124         if self.Input is not None:
   125         if self.Input is not None:
   125             connectors[self.Input] = element.Input
   126             connectors[self.Input] = element.Input
   126         if self.Output is not None:
   127         if self.Output is not None:
   127             connectors[self.Output] = element.Output
   128             connectors[self.Output] = element.Output
   128         if self.Action is not None:
   129         if self.Action is not None:
   129             connectors[self.Action] = element.Action
   130             connectors[self.Action] = element.Action
   130         return connectors
   131         return connectors
   131     
   132 
   132     # Returns the RedrawRect
   133     # Returns the RedrawRect
   133     def GetRedrawRect(self, movex = 0, movey = 0):
   134     def GetRedrawRect(self, movex=0, movey=0):
   134         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
   135         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
   135         if self.Input:
   136         if self.Input:
   136             rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
   137             rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
   137         if self.Output:
   138         if self.Output:
   138             rect = rect.Union(self.Output.GetRedrawRect(movex, movey))
   139             rect = rect.Union(self.Output.GetRedrawRect(movex, movey))
   144             if self.Output and self.Output.IsConnected():
   145             if self.Output and self.Output.IsConnected():
   145                 rect = rect.Union(self.Output.GetConnectedRedrawRect(movex, movey))
   146                 rect = rect.Union(self.Output.GetConnectedRedrawRect(movex, movey))
   146             if self.Action and self.Action.IsConnected():
   147             if self.Action and self.Action.IsConnected():
   147                 rect = rect.Union(self.Action.GetConnectedRedrawRect(movex, movey))
   148                 rect = rect.Union(self.Action.GetConnectedRedrawRect(movex, movey))
   148         return rect
   149         return rect
   149     
   150 
   150     # Delete this step by calling the appropriate method
   151     # Delete this step by calling the appropriate method
   151     def Delete(self):
   152     def Delete(self):
   152         self.Parent.DeleteStep(self)
   153         self.Parent.DeleteStep(self)
   153     
   154 
   154     # Unconnect input and output
   155     # Unconnect input and output
   155     def Clean(self):
   156     def Clean(self):
   156         if self.Input:
   157         if self.Input:
   157             self.Input.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   158             self.Input.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   158         if self.Output:
   159         if self.Output:
   159             self.Output.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   160             self.Output.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   160         if self.Action:
   161         if self.Action:
   161             self.Action.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   162             self.Action.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   162     
   163 
   163     # Refresh the size of text for name
   164     # Refresh the size of text for name
   164     def RefreshNameSize(self):
   165     def RefreshNameSize(self):
   165         self.NameSize = self.Parent.GetTextExtent(self.Name)
   166         self.NameSize = self.Parent.GetTextExtent(self.Name)
   166     
   167 
   167     # Add output connector to step
   168     # Add output connector to step
   168     def AddInput(self):
   169     def AddInput(self):
   169         if not self.Input:
   170         if not self.Input:
   170             self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH)
   171             self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH)
   171             self.RefreshBoundingBox()
   172             self.RefreshBoundingBox()
   172     
   173 
   173     # Remove output connector from step
   174     # Remove output connector from step
   174     def RemoveInput(self):
   175     def RemoveInput(self):
   175         if self.Input:
   176         if self.Input:
   176             self.Input.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   177             self.Input.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   177             self.Input = None
   178             self.Input = None
   178             self.RefreshBoundingBox()
   179             self.RefreshBoundingBox()
   179     
   180 
   180     # Add output connector to step
   181     # Add output connector to step
   181     def AddOutput(self):
   182     def AddOutput(self):
   182         if not self.Output:
   183         if not self.Output:
   183             self.Output = Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone = True)
   184             self.Output = Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone=True)
   184             self.RefreshBoundingBox()
   185             self.RefreshBoundingBox()
   185     
   186 
   186     # Remove output connector from step
   187     # Remove output connector from step
   187     def RemoveOutput(self):
   188     def RemoveOutput(self):
   188         if self.Output:
   189         if self.Output:
   189             self.Output.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   190             self.Output.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   190             self.Output = None
   191             self.Output = None
   191             self.RefreshBoundingBox()
   192             self.RefreshBoundingBox()
   192     
   193 
   193     # Add action connector to step
   194     # Add action connector to step
   194     def AddAction(self):
   195     def AddAction(self):
   195         if not self.Action:
   196         if not self.Action:
   196             self.Action = Connector(self, "", None, wx.Point(self.Size[0], self.Size[1] / 2), EAST, onlyone = True)
   197             self.Action = Connector(self, "", None, wx.Point(self.Size[0], self.Size[1] / 2), EAST, onlyone=True)
   197             self.RefreshBoundingBox()
   198             self.RefreshBoundingBox()
   198     
   199 
   199     # Remove action connector from step
   200     # Remove action connector from step
   200     def RemoveAction(self):
   201     def RemoveAction(self):
   201         if self.Action:
   202         if self.Action:
   202             self.Action.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   203             self.Action.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   203             self.Action = None
   204             self.Action = None
   204             self.RefreshBoundingBox()
   205             self.RefreshBoundingBox()
   205     
   206 
   206     # Refresh the step bounding box
   207     # Refresh the step bounding box
   207     def RefreshBoundingBox(self):
   208     def RefreshBoundingBox(self):
   208         # Calculate the bounding box size
   209         # Calculate the bounding box size
   209         if self.Action:
   210         if self.Action:
   210             bbx_width = self.Size[0] + CONNECTOR_SIZE
   211             bbx_width = self.Size[0] + CONNECTOR_SIZE
   218         else:
   219         else:
   219             bbx_y = self.Pos.y - CONNECTOR_SIZE
   220             bbx_y = self.Pos.y - CONNECTOR_SIZE
   220             bbx_height = self.Size[1] + CONNECTOR_SIZE
   221             bbx_height = self.Size[1] + CONNECTOR_SIZE
   221             if self.Output:
   222             if self.Output:
   222                 bbx_height += CONNECTOR_SIZE
   223                 bbx_height += CONNECTOR_SIZE
   223         #self.BoundingBox = wx.Rect(self.Pos.x, bbx_y, bbx_width + 1, bbx_height + 1)
   224         # self.BoundingBox = wx.Rect(self.Pos.x, bbx_y, bbx_width + 1, bbx_height + 1)
   224         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   225         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   225         
   226 
   226     # Refresh the positions of the step connectors
   227     # Refresh the positions of the step connectors
   227     def RefreshConnectors(self):
   228     def RefreshConnectors(self):
   228         scaling = self.Parent.GetScaling()
   229         scaling = self.Parent.GetScaling()
   229         horizontal_pos = self.Size[0] / 2
   230         horizontal_pos = self.Size[0] / 2
   230         vertical_pos = self.Size[1] / 2
   231         vertical_pos = self.Size[1] / 2
   239             self.Output.SetPosition(wx.Point(horizontal_pos, self.Size[1]))
   240             self.Output.SetPosition(wx.Point(horizontal_pos, self.Size[1]))
   240         # Update action position if it exists
   241         # Update action position if it exists
   241         if self.Action:
   242         if self.Action:
   242             self.Action.SetPosition(wx.Point(self.Size[0], vertical_pos))
   243             self.Action.SetPosition(wx.Point(self.Size[0], vertical_pos))
   243         self.RefreshConnected()
   244         self.RefreshConnected()
   244     
   245 
   245     # Refresh the position of wires connected to step
   246     # Refresh the position of wires connected to step
   246     def RefreshConnected(self, exclude = []):
   247     def RefreshConnected(self, exclude=[]):
   247         if self.Input:
   248         if self.Input:
   248             self.Input.MoveConnected(exclude)
   249             self.Input.MoveConnected(exclude)
   249         if self.Output:
   250         if self.Output:
   250             self.Output.MoveConnected(exclude)
   251             self.Output.MoveConnected(exclude)
   251         if self.Action:
   252         if self.Action:
   252             self.Action.MoveConnected(exclude)
   253             self.Action.MoveConnected(exclude)
   253     
   254 
   254     # Returns the step connector that starts with the point given if it exists 
   255     # Returns the step connector that starts with the point given if it exists
   255     def GetConnector(self, position, name = None):
   256     def GetConnector(self, position, name=None):
   256         # if a name is given
   257         # if a name is given
   257         if name is not None:
   258         if name is not None:
   258             # Test input, output and action connector if they exists
   259             # Test input, output and action connector if they exists
   259             #if self.Input and name == self.Input.GetName():
   260             # if self.Input and name == self.Input.GetName():
   260             #    return self.Input
   261             #    return self.Input
   261             if self.Output and name == self.Output.GetName():
   262             if self.Output and name == self.Output.GetName():
   262                 return self.Output
   263                 return self.Output
   263             if self.Action and name == self.Action.GetName():
   264             if self.Action and name == self.Action.GetName():
   264                 return self.Action
   265                 return self.Action
   271             connectors.append(self.Output)
   272             connectors.append(self.Output)
   272         # Test action connector if it exists
   273         # Test action connector if it exists
   273         if self.Action:
   274         if self.Action:
   274             connectors.append(self.Action)
   275             connectors.append(self.Action)
   275         return self.FindNearestConnector(position, connectors)
   276         return self.FindNearestConnector(position, connectors)
   276     
   277 
   277     # Returns action step connector 
   278     # Returns action step connector
   278     def GetActionConnector(self):
   279     def GetActionConnector(self):
   279         return self.Action
   280         return self.Action
   280         
   281 
   281     # Returns input and output step connectors 
   282     # Returns input and output step connectors
   282     def GetConnectors(self):
   283     def GetConnectors(self):
   283         connectors = {"inputs": [], "outputs": []}
   284         connectors = {"inputs": [], "outputs": []}
   284         if self.Input:
   285         if self.Input:
   285             connectors["inputs"].append(self.Input)
   286             connectors["inputs"].append(self.Input)
   286         if self.Output:
   287         if self.Output:
   287             connectors["outputs"].append(self.Output)
   288             connectors["outputs"].append(self.Output)
   288         return connectors
   289         return connectors
   289     
   290 
   290     # Test if point given is on step input or output connector
   291     # Test if point given is on step input or output connector
   291     def TestConnector(self, pt, direction = None, exclude=True):
   292     def TestConnector(self, pt, direction=None, exclude=True):
   292         # Test input connector if it exists
   293         # Test input connector if it exists
   293         if self.Input and self.Input.TestPoint(pt, direction, exclude):
   294         if self.Input and self.Input.TestPoint(pt, direction, exclude):
   294             return self.Input
   295             return self.Input
   295         # Test output connector
   296         # Test output connector
   296         if self.Output and self.Output.TestPoint(pt, direction, exclude):
   297         if self.Output and self.Output.TestPoint(pt, direction, exclude):
   310         return self.Name
   311         return self.Name
   311 
   312 
   312     # Returns the step initial property
   313     # Returns the step initial property
   313     def GetInitial(self):
   314     def GetInitial(self):
   314         return self.Initial
   315         return self.Initial
   315     
   316 
   316     # Returns the connector connected to input
   317     # Returns the connector connected to input
   317     def GetPreviousConnector(self):
   318     def GetPreviousConnector(self):
   318         if self.Input:
   319         if self.Input:
   319             wires = self.Input.GetWires()
   320             wires = self.Input.GetWires()
   320             if len(wires) == 1:
   321             if len(wires) == 1:
   321                 return wires[0][0].GetOtherConnected(self.Input)
   322                 return wires[0][0].GetOtherConnected(self.Input)
   322         return None
   323         return None
   323     
   324 
   324     # Returns the connector connected to output
   325     # Returns the connector connected to output
   325     def GetNextConnector(self):
   326     def GetNextConnector(self):
   326         if self.Output:
   327         if self.Output:
   327             wires = self.Output.GetWires()
   328             wires = self.Output.GetWires()
   328             if len(wires) == 1:
   329             if len(wires) == 1:
   329                 return wires[0][0].GetOtherConnected(self.Output)
   330                 return wires[0][0].GetOtherConnected(self.Output)
   330         return None
   331         return None
   331     
   332 
   332     # Returns the connector connected to action
   333     # Returns the connector connected to action
   333     def GetActionConnected(self):
   334     def GetActionConnected(self):
   334         if self.Action:
   335         if self.Action:
   335             wires = self.Action.GetWires()
   336             wires = self.Action.GetWires()
   336             if len(wires) == 1:
   337             if len(wires) == 1:
   337                 return wires[0][0].GetOtherConnected(self.Action)
   338                 return wires[0][0].GetOtherConnected(self.Action)
   338         return None
   339         return None
   339     
   340 
   340     # Returns the number of action line
   341     # Returns the number of action line
   341     def GetActionExtraLineNumber(self):
   342     def GetActionExtraLineNumber(self):
   342         if self.Action:
   343         if self.Action:
   343             wires = self.Action.GetWires()
   344             wires = self.Action.GetWires()
   344             if len(wires) != 1:
   345             if len(wires) != 1:
   345                 return 0
   346                 return 0
   346             action_block = wires[0][0].GetOtherConnected(self.Action).GetParentBlock()
   347             action_block = wires[0][0].GetOtherConnected(self.Action).GetParentBlock()
   347             return max(0, action_block.GetLineNumber() - 1)
   348             return max(0, action_block.GetLineNumber() - 1)
   348         return 0
   349         return 0
   349     
   350 
   350     # Returns the step minimum size
   351     # Returns the step minimum size
   351     def GetMinSize(self):
   352     def GetMinSize(self):
   352         text_width, text_height = self.Parent.GetTextExtent(self.Name)
   353         text_width, text_height = self.Parent.GetTextExtent(self.Name)
   353         if self.Initial:
   354         if self.Initial:
   354             return text_width + 14, text_height + 14
   355             return text_width + 14, text_height + 14
   355         else:
   356         else:
   356             return text_width + 10, text_height + 10
   357             return text_width + 10, text_height + 10
   357     
   358 
   358     # Updates the step size
   359     # Updates the step size
   359     def UpdateSize(self, width, height):
   360     def UpdateSize(self, width, height):
   360         diffx = self.Size.GetWidth() / 2 - width / 2
   361         diffx = self.Size.GetWidth() / 2 - width / 2
   361         diffy = height - self.Size.GetHeight()
   362         diffy = height - self.Size.GetHeight()
   362         self.Move(diffx, 0)
   363         self.Move(diffx, 0)
   363         Graphic_Element.SetSize(self, width, height)
   364         Graphic_Element.SetSize(self, width, height)
   364         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   365         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   365             self.RefreshConnected()
   366             self.RefreshConnected()
   366         else:
   367         else:
   367             self.RefreshOutputPosition((0, diffy))
   368             self.RefreshOutputPosition((0, diffy))
   368     
   369 
   369     # Align input element with this step
   370     # Align input element with this step
   370     def RefreshInputPosition(self):
   371     def RefreshInputPosition(self):
   371         if self.Input:
   372         if self.Input:
   372             current_pos = self.Input.GetPosition(False)
   373             current_pos = self.Input.GetPosition(False)
   373             input = self.GetPreviousConnector()
   374             input = self.GetPreviousConnector()
   380                 else:
   381                 else:
   381                     if isinstance(input_block, SFC_Step):
   382                     if isinstance(input_block, SFC_Step):
   382                         input_block.MoveActionBlock((diffx, 0))
   383                         input_block.MoveActionBlock((diffx, 0))
   383                     input_block.Move(diffx, 0)
   384                     input_block.Move(diffx, 0)
   384                     input_block.RefreshInputPosition()
   385                     input_block.RefreshInputPosition()
   385     
   386 
   386     # Align output element with this step
   387     # Align output element with this step
   387     def RefreshOutputPosition(self, move = None):
   388     def RefreshOutputPosition(self, move=None):
   388         if self.Output:
   389         if self.Output:
   389             wires = self.Output.GetWires()
   390             wires = self.Output.GetWires()
   390             if len(wires) != 1:
   391             if len(wires) != 1:
   391                 return
   392                 return
   392             current_pos = self.Output.GetPosition(False)
   393             current_pos = self.Output.GetPosition(False)
   398             diffy = wire_size - output_pos.y + current_pos.y
   399             diffy = wire_size - output_pos.y + current_pos.y
   399             if diffy != 0:
   400             if diffy != 0:
   400                 if isinstance(output_block, SFC_Step):
   401                 if isinstance(output_block, SFC_Step):
   401                     output_block.MoveActionBlock((diffx, diffy))
   402                     output_block.MoveActionBlock((diffx, diffy))
   402                 wires[0][0].SetPoints([wx.Point(current_pos.x, current_pos.y + wire_size),
   403                 wires[0][0].SetPoints([wx.Point(current_pos.x, current_pos.y + wire_size),
   403                     wx.Point(current_pos.x, current_pos.y)])
   404                                        wx.Point(current_pos.x, current_pos.y)])
   404                 if not isinstance(output_block, SFC_Divergence) or output_block.GetConnectors()["inputs"].index(output) == 0:
   405                 if not isinstance(output_block, SFC_Divergence) or output_block.GetConnectors()["inputs"].index(output) == 0:
   405                     output_block.Move(diffx, diffy, self.Parent.Wires)
   406                     output_block.Move(diffx, diffy, self.Parent.Wires)
   406                     output_block.RefreshOutputPosition((diffx, diffy))
   407                     output_block.RefreshOutputPosition((diffx, diffy))
   407                 else:
   408                 else:
   408                     output_block.RefreshPosition()
   409                     output_block.RefreshPosition()
   420             else:
   421             else:
   421                 if isinstance(output_block, SFC_Step):
   422                 if isinstance(output_block, SFC_Step):
   422                     output_block.MoveActionBlock((diffx, 0))
   423                     output_block.MoveActionBlock((diffx, 0))
   423                 output_block.Move(diffx, 0)
   424                 output_block.Move(diffx, 0)
   424                 output_block.RefreshOutputPosition()
   425                 output_block.RefreshOutputPosition()
   425     
   426 
   426     # Refresh action element with this step
   427     # Refresh action element with this step
   427     def MoveActionBlock(self, move):
   428     def MoveActionBlock(self, move):
   428         if self.Action:
   429         if self.Action:
   429             wires = self.Action.GetWires()
   430             wires = self.Action.GetWires()
   430             if len(wires) != 1:
   431             if len(wires) != 1:
   431                 return
   432                 return
   432             action_block = wires[0][0].GetOtherConnected(self.Action).GetParentBlock()
   433             action_block = wires[0][0].GetOtherConnected(self.Action).GetParentBlock()
   433             action_block.Move(move[0], move[1], self.Parent.Wires)
   434             action_block.Move(move[0], move[1], self.Parent.Wires)
   434             wires[0][0].Move(move[0], move[1], True)
   435             wires[0][0].Move(move[0], move[1], True)
   435     
   436 
   436     # Resize the divergence from position and size given
   437     # Resize the divergence from position and size given
   437     def Resize(self, x, y, width, height):
   438     def Resize(self, x, y, width, height):
   438         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   439         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   439             self.UpdateSize(width, height)
   440             self.UpdateSize(width, height)
   440         else:
   441         else:
   441             Graphic_Element.Resize(self, x, y, width, height)
   442             Graphic_Element.Resize(self, x, y, width, height)
   442     
   443 
   443     # Method called when a LeftDClick event have been generated
   444     # Method called when a LeftDClick event have been generated
   444     def OnLeftDClick(self, event, dc, scaling):
   445     def OnLeftDClick(self, event, dc, scaling):
   445         # Edit the step properties
   446         # Edit the step properties
   446         self.Parent.EditStepContent(self)
   447         self.Parent.EditStepContent(self)
   447     
   448 
   448     # Method called when a RightUp event have been generated
   449     # Method called when a RightUp event have been generated
   449     def OnRightUp(self, event, dc, scaling):
   450     def OnRightUp(self, event, dc, scaling):
   450         # Popup the menu with special items for a step
   451         # Popup the menu with special items for a step
   451         self.Parent.PopupDefaultMenu()
   452         self.Parent.PopupDefaultMenu()
   452     
   453 
   453     # Refreshes the step state according to move defined and handle selected
   454     # Refreshes the step state according to move defined and handle selected
   454     def ProcessDragging(self, movex, movey, event, scaling):
   455     def ProcessDragging(self, movex, movey, event, scaling):
   455         handle_type, handle = self.Handle
   456         handle_type, handle = self.Handle
   456         if handle_type == HANDLE_MOVE:
   457         if handle_type == HANDLE_MOVE:
   457             movex = max(-self.BoundingBox.x, movex)
   458             movex = max(-self.BoundingBox.x, movex)
   475                 self.RefreshInputPosition()
   476                 self.RefreshInputPosition()
   476                 self.RefreshOutputPosition()
   477                 self.RefreshOutputPosition()
   477                 return movex, 0
   478                 return movex, 0
   478         else:
   479         else:
   479             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
   480             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
   480     
   481 
   481     # Refresh input element model
   482     # Refresh input element model
   482     def RefreshInputModel(self):
   483     def RefreshInputModel(self):
   483         if self.Input:
   484         if self.Input:
   484             input = self.GetPreviousConnector()
   485             input = self.GetPreviousConnector()
   485             if input:                
   486             if input:
   486                 input_block = input.GetParentBlock()
   487                 input_block = input.GetParentBlock()
   487                 input_block.RefreshModel(False)
   488                 input_block.RefreshModel(False)
   488                 if not isinstance(input_block, SFC_Divergence):
   489                 if not isinstance(input_block, SFC_Divergence):
   489                     input_block.RefreshInputModel()
   490                     input_block.RefreshInputModel()
   490     
   491 
   491     # Refresh output element model
   492     # Refresh output element model
   492     def RefreshOutputModel(self, move=False):
   493     def RefreshOutputModel(self, move=False):
   493         if self.Output:
   494         if self.Output:
   494             output = self.GetNextConnector()
   495             output = self.GetNextConnector()
   495             if output:
   496             if output:
   496                 output_block = output.GetParentBlock()
   497                 output_block = output.GetParentBlock()
   497                 output_block.RefreshModel(False)
   498                 output_block.RefreshModel(False)
   498                 if not isinstance(output_block, SFC_Divergence) or move:
   499                 if not isinstance(output_block, SFC_Divergence) or move:
   499                     output_block.RefreshOutputModel(move)
   500                     output_block.RefreshOutputModel(move)
   500     
   501 
   501     # Refreshes the step model
   502     # Refreshes the step model
   502     def RefreshModel(self, move=True):
   503     def RefreshModel(self, move=True):
   503         self.Parent.RefreshStepModel(self)
   504         self.Parent.RefreshStepModel(self)
   504         if self.Action:
   505         if self.Action:
   505             action = self.GetActionConnected()
   506             action = self.GetActionConnected()
   511             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   512             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   512                 self.RefreshInputModel()
   513                 self.RefreshInputModel()
   513                 self.RefreshOutputModel(self.Initial)
   514                 self.RefreshOutputModel(self.Initial)
   514             elif self.Output:
   515             elif self.Output:
   515                 self.Output.RefreshWires()
   516                 self.Output.RefreshWires()
   516     
   517 
   517     # Adds an highlight to the connection
   518     # Adds an highlight to the connection
   518     def AddHighlight(self, infos, start, end, highlight_type):
   519     def AddHighlight(self, infos, start, end, highlight_type):
   519         if infos[0] == "name" and start[0] == 0 and end[0] == 0:
   520         if infos[0] == "name" and start[0] == 0 and end[0] == 0:
   520             AddHighlight(self.Highlights, (start, end, highlight_type))
   521             AddHighlight(self.Highlights, (start, end, highlight_type))
   521     
   522 
   522     # Removes an highlight from the connection
   523     # Removes an highlight from the connection
   523     def RemoveHighlight(self, infos, start, end, highlight_type):
   524     def RemoveHighlight(self, infos, start, end, highlight_type):
   524         if infos[0] == "name":
   525         if infos[0] == "name":
   525             RemoveHighlight(self.Highlights, (start, end, highlight_type))
   526             RemoveHighlight(self.Highlights, (start, end, highlight_type))
   526     
   527 
   527     # Removes all the highlights of one particular type from the connection
   528     # Removes all the highlights of one particular type from the connection
   528     def ClearHighlight(self, highlight_type=None):
   529     def ClearHighlight(self, highlight_type=None):
   529         ClearHighlights(self.Highlights, highlight_type)
   530         ClearHighlights(self.Highlights, highlight_type)
   530     
   531 
   531     # Draws step
   532     # Draws step
   532     def Draw(self, dc):
   533     def Draw(self, dc):
   533         Graphic_Element.Draw(self, dc)
   534         Graphic_Element.Draw(self, dc)
   534         if self.Value:
   535         if self.Value:
   535             if self.Forced:
   536             if self.Forced:
   539         elif self.Forced:
   540         elif self.Forced:
   540             dc.SetPen(MiterPen(wx.BLUE))
   541             dc.SetPen(MiterPen(wx.BLUE))
   541         else:
   542         else:
   542             dc.SetPen(MiterPen(wx.BLACK))
   543             dc.SetPen(MiterPen(wx.BLACK))
   543         dc.SetBrush(wx.WHITE_BRUSH)
   544         dc.SetBrush(wx.WHITE_BRUSH)
   544         
   545 
   545         if getattr(dc, "printing", False):
   546         if getattr(dc, "printing", False):
   546             name_size = dc.GetTextExtent(self.Name)
   547             name_size = dc.GetTextExtent(self.Name)
   547         else:
   548         else:
   548             name_size = self.NameSize
   549             name_size = self.NameSize
   549         
   550 
   550         # Draw two rectangles for representing the step
   551         # Draw two rectangles for representing the step
   551         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   552         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   552         if self.Initial:
   553         if self.Initial:
   553             dc.DrawRectangle(self.Pos.x + 2, self.Pos.y + 2, self.Size[0] - 3, self.Size[1] - 3)
   554             dc.DrawRectangle(self.Pos.x + 2, self.Pos.y + 2, self.Size[0] - 3, self.Size[1] - 3)
   554         # Draw step name
   555         # Draw step name
   560             self.Input.Draw(dc)
   561             self.Input.Draw(dc)
   561         if self.Output:
   562         if self.Output:
   562             self.Output.Draw(dc)
   563             self.Output.Draw(dc)
   563         if self.Action:
   564         if self.Action:
   564             self.Action.Draw(dc)
   565             self.Action.Draw(dc)
   565         
   566 
   566         if not getattr(dc, "printing", False):
   567         if not getattr(dc, "printing", False):
   567             DrawHighlightedText(dc, self.Name, self.Highlights, name_pos[0], name_pos[1])
   568             DrawHighlightedText(dc, self.Name, self.Highlights, name_pos[0], name_pos[1])
   568         
   569 
   569 
   570 
   570 #-------------------------------------------------------------------------------
   571 # -------------------------------------------------------------------------------
   571 #                       Sequencial Function Chart Transition
   572 #                       Sequencial Function Chart Transition
   572 #-------------------------------------------------------------------------------
   573 # -------------------------------------------------------------------------------
   573 
   574 
   574 """
       
   575 Class that implements the graphic representation of a transition
       
   576 """
       
   577 
   575 
   578 class SFC_Transition(Graphic_Element, DebugDataConsumer):
   576 class SFC_Transition(Graphic_Element, DebugDataConsumer):
   579     
   577     """
       
   578     Class that implements the graphic representation of a transition
       
   579     """
       
   580 
   580     # Create a new transition
   581     # Create a new transition
   581     def __init__(self, parent, type = "reference", condition = None, priority = 0, id = None):
   582     def __init__(self, parent, type="reference", condition=None, priority=0, id=None):
   582         Graphic_Element.__init__(self, parent)
   583         Graphic_Element.__init__(self, parent)
   583         DebugDataConsumer.__init__(self)
   584         DebugDataConsumer.__init__(self)
   584         self.Type = None
   585         self.Type = None
   585         self.Id = id
   586         self.Id = id
   586         self.Priority = 0
   587         self.Priority = 0
   587         self.Size = wx.Size(SFC_TRANSITION_SIZE[0], SFC_TRANSITION_SIZE[1])
   588         self.Size = wx.Size(SFC_TRANSITION_SIZE[0], SFC_TRANSITION_SIZE[1])
   588         # Create an input and output connector
   589         # Create an input and output connector
   589         self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone = True)
   590         self.Input = Connector(self,  "", None, wx.Point(self.Size[0] / 2, 0),            NORTH, onlyone=True)
   590         self.Output = Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone = True)
   591         self.Output = Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone=True)
   591         self.SetType(type, condition)
   592         self.SetType(type, condition)
   592         self.SetPriority(priority)
   593         self.SetPriority(priority)
   593         self.Highlights = {}
   594         self.Highlights = {}
   594         self.PreviousValue = None
   595         self.PreviousValue = None
   595         self.PreviousSpreading = False
   596         self.PreviousSpreading = False
   596     
   597 
   597     def Flush(self):
   598     def Flush(self):
   598         if self.Input is not None:
   599         if self.Input is not None:
   599             self.Input.Flush()
   600             self.Input.Flush()
   600             self.Input = None
   601             self.Input = None
   601         if self.Output is not None:
   602         if self.Output is not None:
   602             self.Output.Flush()
   603             self.Output.Flush()
   603             self.Output = None
   604             self.Output = None
   604         if self.Type == "connection" and self.Condition is not None:
   605         if self.Type == "connection" and self.Condition is not None:
   605             self.Condition.Flush()
   606             self.Condition.Flush()
   606             self.Condition = None
   607             self.Condition = None
   607     
   608 
   608     def SetForced(self, forced):
   609     def SetForced(self, forced):
   609         if self.Forced != forced:
   610         if self.Forced != forced:
   610             self.Forced = forced
   611             self.Forced = forced
   611             if self.Visible:
   612             if self.Visible:
   612                 self.Parent.ElementNeedRefresh(self)
   613                 self.Parent.ElementNeedRefresh(self)
   613         
   614 
   614     def SetValue(self, value):
   615     def SetValue(self, value):
   615         self.PreviousValue = self.Value
   616         self.PreviousValue = self.Value
   616         self.Value = value
   617         self.Value = value
   617         if self.Value != self.PreviousValue:
   618         if self.Value != self.PreviousValue:
   618             if self.Visible:
   619             if self.Visible:
   619                 self.Parent.ElementNeedRefresh(self)
   620                 self.Parent.ElementNeedRefresh(self)
   620             self.SpreadCurrent()
   621             self.SpreadCurrent()
   621     
   622 
   622     def SpreadCurrent(self):
   623     def SpreadCurrent(self):
   623         if self.Parent.Debug:
   624         if self.Parent.Debug:
   624             if self.Value is None:
   625             if self.Value is None:
   625                 self.Value = False
   626                 self.Value = False
   626             spreading = self.Input.ReceivingCurrent() & self.Value
   627             spreading = self.Input.ReceivingCurrent() & self.Value
   627             if spreading and not self.PreviousSpreading:
   628             if spreading and not self.PreviousSpreading:
   628                 self.Output.SpreadCurrent(True)
   629                 self.Output.SpreadCurrent(True)
   629             elif not spreading and self.PreviousSpreading:
   630             elif not spreading and self.PreviousSpreading:
   630                 self.Output.SpreadCurrent(False)
   631                 self.Output.SpreadCurrent(False)
   631             self.PreviousSpreading = spreading
   632             self.PreviousSpreading = spreading
   632     
   633 
   633     # Make a clone of this SFC_Transition
   634     # Make a clone of this SFC_Transition
   634     def Clone(self, parent, id = None, pos = None):
   635     def Clone(self, parent, id=None, pos=None):
   635         transition = SFC_Transition(parent, self.Type, self.Condition, self.Priority, id)
   636         transition = SFC_Transition(parent, self.Type, self.Condition, self.Priority, id)
   636         transition.SetSize(self.Size[0], self.Size[1])
   637         transition.SetSize(self.Size[0], self.Size[1])
   637         if pos is not None:
   638         if pos is not None:
   638             transition.SetPosition(pos.x, pos.y)
   639             transition.SetPosition(pos.x, pos.y)
   639         else:
   640         else:
   641         transition.Input = self.Input.Clone(transition)
   642         transition.Input = self.Input.Clone(transition)
   642         transition.Output = self.Output.Clone(transition)
   643         transition.Output = self.Output.Clone(transition)
   643         if self.Type == "connection":
   644         if self.Type == "connection":
   644             transition.Condition = self.Condition.Clone(transition)
   645             transition.Condition = self.Condition.Clone(transition)
   645         return transition
   646         return transition
   646     
   647 
   647     def GetConnectorTranslation(self, element):
   648     def GetConnectorTranslation(self, element):
   648         connectors = {self.Input : element.Input, self.Output : element.Output}
   649         connectors = {self.Input: element.Input, self.Output: element.Output}
   649         if self.Type == "connection" and self.Condition is not None:
   650         if self.Type == "connection" and self.Condition is not None:
   650             connectors[self.Condition] = element.Condition
   651             connectors[self.Condition] = element.Condition
   651         return connectors
   652         return connectors
   652     
   653 
   653     # Returns the RedrawRect
   654     # Returns the RedrawRect
   654     def GetRedrawRect(self, movex = 0, movey = 0):
   655     def GetRedrawRect(self, movex=0, movey=0):
   655         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
   656         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
   656         if self.Input:
   657         if self.Input:
   657             rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
   658             rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
   658         if self.Output:
   659         if self.Output:
   659             rect = rect.Union(self.Output.GetRedrawRect(movex, movey))
   660             rect = rect.Union(self.Output.GetRedrawRect(movex, movey))
   663             if self.Output.IsConnected():
   664             if self.Output.IsConnected():
   664                 rect = rect.Union(self.Output.GetConnectedRedrawRect(movex, movey))
   665                 rect = rect.Union(self.Output.GetConnectedRedrawRect(movex, movey))
   665             if self.Type == "connection" and self.Condition.IsConnected():
   666             if self.Type == "connection" and self.Condition.IsConnected():
   666                 rect = rect.Union(self.Condition.GetConnectedRedrawRect(movex, movey))
   667                 rect = rect.Union(self.Condition.GetConnectedRedrawRect(movex, movey))
   667         return rect
   668         return rect
   668     
   669 
   669     # Forbids to change the transition size
   670     # Forbids to change the transition size
   670     def SetSize(self, width, height):
   671     def SetSize(self, width, height):
   671         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   672         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   672             Graphic_Element.SetSize(self, width, height)
   673             Graphic_Element.SetSize(self, width, height)
   673     
   674 
   674     # Forbids to resize the transition
   675     # Forbids to resize the transition
   675     def Resize(self, x, y, width, height):
   676     def Resize(self, x, y, width, height):
   676         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   677         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   677             Graphic_Element.Resize(self, x, y, width, height)
   678             Graphic_Element.Resize(self, x, y, width, height)
   678     
   679 
   679     # Refresh the size of text for name
   680     # Refresh the size of text for name
   680     def RefreshConditionSize(self):
   681     def RefreshConditionSize(self):
   681         if self.Type != "connection":
   682         if self.Type != "connection":
   682             if self.Condition != "":
   683             if self.Condition != "":
   683                 self.ConditionSize = self.Parent.GetTextExtent(self.Condition)
   684                 self.ConditionSize = self.Parent.GetTextExtent(self.Condition)
   684             else:
   685             else:
   685                 self.ConditionSize = self.Parent.GetTextExtent("Transition")
   686                 self.ConditionSize = self.Parent.GetTextExtent("Transition")
   686     
   687 
   687     # Refresh the size of text for name
   688     # Refresh the size of text for name
   688     def RefreshPrioritySize(self):
   689     def RefreshPrioritySize(self):
   689         if self.Priority != "":
   690         if self.Priority != "":
   690             self.PrioritySize = self.Parent.GetTextExtent(str(self.Priority))
   691             self.PrioritySize = self.Parent.GetTextExtent(str(self.Priority))
   691         else:
   692         else:
   692             self.PrioritySize = None
   693             self.PrioritySize = None
   693 
   694 
   694     # Delete this transition by calling the appropriate method
   695     # Delete this transition by calling the appropriate method
   695     def Delete(self):
   696     def Delete(self):
   696         self.Parent.DeleteTransition(self)
   697         self.Parent.DeleteTransition(self)
   697     
   698 
   698     # Unconnect input and output
   699     # Unconnect input and output
   699     def Clean(self):
   700     def Clean(self):
   700         self.Input.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   701         self.Input.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   701         self.Output.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   702         self.Output.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   702         if self.Type == "connection":
   703         if self.Type == "connection":
   703             self.Condition.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   704             self.Condition.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   704     
   705 
   705     # Returns if the point given is in the bounding box
   706     # Returns if the point given is in the bounding box
   706     def HitTest(self, pt, connectors=True):
   707     def HitTest(self, pt, connectors=True):
   707         if self.Type != "connection":
   708         if self.Type != "connection":
   708             # Calculate the bounding box of the condition outside the transition
   709             # Calculate the bounding box of the condition outside the transition
   709             text_width, text_height = self.ConditionSize
   710             text_width, text_height = self.ConditionSize
   713                                text_height)
   714                                text_height)
   714             test_text = text_bbx.InsideXY(pt.x, pt.y)
   715             test_text = text_bbx.InsideXY(pt.x, pt.y)
   715         else:
   716         else:
   716             test_text = False
   717             test_text = False
   717         return test_text or Graphic_Element.HitTest(self, pt, connectors)
   718         return test_text or Graphic_Element.HitTest(self, pt, connectors)
   718     
   719 
   719     # Refresh the transition bounding box
   720     # Refresh the transition bounding box
   720     def RefreshBoundingBox(self):
   721     def RefreshBoundingBox(self):
   721         bbx_x, bbx_y, bbx_width, bbx_height = self.Pos.x, self.Pos.y, self.Size[0], self.Size[1]
   722         bbx_x, bbx_y, bbx_width, bbx_height = self.Pos.x, self.Pos.y, self.Size[0], self.Size[1]
   722         if self.Priority != 0:
   723         if self.Priority != 0:
   723             bbx_y = self.Pos.y - self.PrioritySize[1] - 2
   724             bbx_y = self.Pos.y - self.PrioritySize[1] - 2
   731             # Calculate the bounding box size
   732             # Calculate the bounding box size
   732             bbx_width = max(bbx_width, self.Size[0] + 5 + text_width)
   733             bbx_width = max(bbx_width, self.Size[0] + 5 + text_width)
   733             bbx_y = min(bbx_y, self.Pos.y - max(0, (text_height - self.Size[1]) / 2))
   734             bbx_y = min(bbx_y, self.Pos.y - max(0, (text_height - self.Size[1]) / 2))
   734             bbx_height = max(bbx_height, self.Pos.y - bbx_y + (self.Size[1] + text_height) / 2)
   735             bbx_height = max(bbx_height, self.Pos.y - bbx_y + (self.Size[1] + text_height) / 2)
   735         self.BoundingBox = wx.Rect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1)
   736         self.BoundingBox = wx.Rect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1)
   736         
   737 
   737     # Returns the connector connected to input
   738     # Returns the connector connected to input
   738     def GetPreviousConnector(self):
   739     def GetPreviousConnector(self):
   739         wires = self.Input.GetWires()
   740         wires = self.Input.GetWires()
   740         if len(wires) == 1:
   741         if len(wires) == 1:
   741             return wires[0][0].GetOtherConnected(self.Input)
   742             return wires[0][0].GetOtherConnected(self.Input)
   742         return None
   743         return None
   743     
   744 
   744     # Returns the connector connected to output
   745     # Returns the connector connected to output
   745     def GetNextConnector(self):
   746     def GetNextConnector(self):
   746         wires = self.Output.GetWires()
   747         wires = self.Output.GetWires()
   747         if len(wires) == 1:
   748         if len(wires) == 1:
   748             return wires[0][0].GetOtherConnected(self.Output)
   749             return wires[0][0].GetOtherConnected(self.Output)
   749         return None
   750         return None
   750     
   751 
   751     # Refresh the positions of the transition connectors
   752     # Refresh the positions of the transition connectors
   752     def RefreshConnectors(self):
   753     def RefreshConnectors(self):
   753         scaling = self.Parent.GetScaling()
   754         scaling = self.Parent.GetScaling()
   754         horizontal_pos = self.Size[0] / 2
   755         horizontal_pos = self.Size[0] / 2
   755         vertical_pos = self.Size[1] / 2
   756         vertical_pos = self.Size[1] / 2
   761         # Update output position
   762         # Update output position
   762         self.Output.SetPosition(wx.Point(horizontal_pos, self.Size[1]))
   763         self.Output.SetPosition(wx.Point(horizontal_pos, self.Size[1]))
   763         if self.Type == "connection":
   764         if self.Type == "connection":
   764             self.Condition.SetPosition(wx.Point(0, vertical_pos))
   765             self.Condition.SetPosition(wx.Point(0, vertical_pos))
   765         self.RefreshConnected()
   766         self.RefreshConnected()
   766     
   767 
   767     # Refresh the position of the wires connected to transition
   768     # Refresh the position of the wires connected to transition
   768     def RefreshConnected(self, exclude = []):
   769     def RefreshConnected(self, exclude=[]):
   769         self.Input.MoveConnected(exclude)
   770         self.Input.MoveConnected(exclude)
   770         self.Output.MoveConnected(exclude)
   771         self.Output.MoveConnected(exclude)
   771         if self.Type == "connection":
   772         if self.Type == "connection":
   772             self.Condition.MoveConnected(exclude)
   773             self.Condition.MoveConnected(exclude)
   773     
   774 
   774     # Returns the transition connector that starts with the point given if it exists 
   775     # Returns the transition connector that starts with the point given if it exists
   775     def GetConnector(self, position, name = None):
   776     def GetConnector(self, position, name=None):
   776         # if a name is given
   777         # if a name is given
   777         if name is not None:
   778         if name is not None:
   778             # Test input and output connector
   779             # Test input and output connector
   779             #if name == self.Input.GetName():
   780             # if name == self.Input.GetName():
   780             #    return self.Input
   781             #    return self.Input
   781             if name == self.Output.GetName():
   782             if name == self.Output.GetName():
   782                 return self.Output
   783                 return self.Output
   783             if self.Type == "connection" and name == self.Condition.GetName():
   784             if self.Type == "connection" and name == self.Condition.GetName():
   784                 return self.Condition
   785                 return self.Condition
   785         connectors = [self.Input, self.Output]
   786         connectors = [self.Input, self.Output]
   786         if self.Type == "connection":
   787         if self.Type == "connection":
   787             connectors.append(self.Condition)
   788             connectors.append(self.Condition)
   788         return self.FindNearestConnector(position, connectors)
   789         return self.FindNearestConnector(position, connectors)
   789     
   790 
   790     # Returns the transition condition connector
   791     # Returns the transition condition connector
   791     def GetConditionConnector(self):
   792     def GetConditionConnector(self):
   792         if self.Type == "connection":
   793         if self.Type == "connection":
   793             return self.Condition
   794             return self.Condition
   794         return None
   795         return None
   795         
   796 
   796     # Returns input and output transition connectors
   797     # Returns input and output transition connectors
   797     def GetConnectors(self):
   798     def GetConnectors(self):
   798         return {"inputs": [self.Input], "outputs": [self.Output]}
   799         return {"inputs": [self.Input], "outputs": [self.Output]}
   799         
   800 
   800     # Test if point given is on transition input or output connector
   801     # Test if point given is on transition input or output connector
   801     def TestConnector(self, pt, direction = None, exclude=True):
   802     def TestConnector(self, pt, direction=None, exclude=True):
   802         # Test input connector
   803         # Test input connector
   803         if self.Input.TestPoint(pt, direction, exclude):
   804         if self.Input.TestPoint(pt, direction, exclude):
   804             return self.Input
   805             return self.Input
   805         # Test output connector
   806         # Test output connector
   806         if self.Output.TestPoint(pt, direction, exclude):
   807         if self.Output.TestPoint(pt, direction, exclude):
   809         if self.Type == "connection" and self.Condition.TestPoint(pt, direction, exclude):
   810         if self.Type == "connection" and self.Condition.TestPoint(pt, direction, exclude):
   810             return self.Condition
   811             return self.Condition
   811         return None
   812         return None
   812 
   813 
   813     # Changes the transition type
   814     # Changes the transition type
   814     def SetType(self, type, condition = None):
   815     def SetType(self, type, condition=None):
   815         if self.Type != type:
   816         if self.Type != type:
   816             if self.Type == "connection":
   817             if self.Type == "connection":
   817                self.Condition.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE) 
   818                 self.Condition.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   818             self.Type = type
   819             self.Type = type
   819             if type == "connection":
   820             if type == "connection":
   820                 self.Condition = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] / 2), WEST)
   821                 self.Condition = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] / 2), WEST)
   821             else:
   822             else:
   822                 if condition == None:
   823                 if condition is None:
   823                     condition = ""
   824                     condition = ""
   824                 self.Condition = condition
   825                 self.Condition = condition
   825                 self.RefreshConditionSize()
   826                 self.RefreshConditionSize()
   826         elif self.Type != "connection":
   827         elif self.Type != "connection":
   827             if condition == None:
   828             if condition is None:
   828                 condition = ""
   829                 condition = ""
   829             self.Condition = condition
   830             self.Condition = condition
   830             self.RefreshConditionSize()
   831             self.RefreshConditionSize()
   831         self.RefreshBoundingBox()
   832         self.RefreshBoundingBox()
   832         
   833 
   833     # Returns the transition type
   834     # Returns the transition type
   834     def GetType(self):
   835     def GetType(self):
   835         return self.Type
   836         return self.Type
   836 
   837 
   837     # Changes the transition priority
   838     # Changes the transition priority
   838     def SetPriority(self, priority):
   839     def SetPriority(self, priority):
   839         self.Priority = priority
   840         self.Priority = priority
   840         self.RefreshPrioritySize()
   841         self.RefreshPrioritySize()
   841         self.RefreshBoundingBox()
   842         self.RefreshBoundingBox()
   842         
   843 
   843     # Returns the transition type
   844     # Returns the transition type
   844     def GetPriority(self):
   845     def GetPriority(self):
   845         return self.Priority
   846         return self.Priority
   846 
   847 
   847     # Returns the transition condition
   848     # Returns the transition condition
   848     def GetCondition(self):
   849     def GetCondition(self):
   849         if self.Type != "connection":
   850         if self.Type != "connection":
   850             return self.Condition
   851             return self.Condition
   851         return None
   852         return None
   852         
   853 
   853     # Returns the transition minimum size
   854     # Returns the transition minimum size
   854     def GetMinSize(self):
   855     def GetMinSize(self):
   855         return SFC_TRANSITION_SIZE
   856         return SFC_TRANSITION_SIZE
   856     
   857 
   857     # Align input element with this step
   858     # Align input element with this step
   858     def RefreshInputPosition(self):
   859     def RefreshInputPosition(self):
   859         wires = self.Input.GetWires()
   860         wires = self.Input.GetWires()
   860         current_pos = self.Input.GetPosition(False)
   861         current_pos = self.Input.GetPosition(False)
   861         input = self.GetPreviousConnector()
   862         input = self.GetPreviousConnector()
   868             else:
   869             else:
   869                 if isinstance(input_block, SFC_Step):
   870                 if isinstance(input_block, SFC_Step):
   870                     input_block.MoveActionBlock((diffx, 0))
   871                     input_block.MoveActionBlock((diffx, 0))
   871                 input_block.Move(diffx, 0)
   872                 input_block.Move(diffx, 0)
   872                 input_block.RefreshInputPosition()
   873                 input_block.RefreshInputPosition()
   873     
   874 
   874     # Align output element with this step
   875     # Align output element with this step
   875     def RefreshOutputPosition(self, move = None):
   876     def RefreshOutputPosition(self, move=None):
   876         wires = self.Output.GetWires()
   877         wires = self.Output.GetWires()
   877         if len(wires) != 1:
   878         if len(wires) != 1:
   878             return
   879             return
   879         current_pos = self.Output.GetPosition(False)
   880         current_pos = self.Output.GetPosition(False)
   880         output = wires[0][0].GetOtherConnected(self.Output)
   881         output = wires[0][0].GetOtherConnected(self.Output)
   900 
   901 
   901     # Method called when a LeftDClick event have been generated
   902     # Method called when a LeftDClick event have been generated
   902     def OnLeftDClick(self, event, dc, scaling):
   903     def OnLeftDClick(self, event, dc, scaling):
   903         # Edit the transition properties
   904         # Edit the transition properties
   904         self.Parent.EditTransitionContent(self)
   905         self.Parent.EditTransitionContent(self)
   905     
   906 
   906     # Method called when a RightUp event have been generated
   907     # Method called when a RightUp event have been generated
   907     def OnRightUp(self, event, dc, scaling):
   908     def OnRightUp(self, event, dc, scaling):
   908         # Popup the menu with special items for a step
   909         # Popup the menu with special items for a step
   909         self.Parent.PopupDefaultMenu()
   910         self.Parent.PopupDefaultMenu()
   910     
   911 
   911     # Refreshes the transition state according to move defined and handle selected
   912     # Refreshes the transition state according to move defined and handle selected
   912     def ProcessDragging(self, movex, movey, event, scaling):
   913     def ProcessDragging(self, movex, movey, event, scaling):
   913         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   914         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   914             movex = max(-self.BoundingBox.x, movex)
   915             movex = max(-self.BoundingBox.x, movex)
   915             if scaling is not None:
   916             if scaling is not None:
   917             self.Move(movex, 0)
   918             self.Move(movex, 0)
   918             self.RefreshInputPosition()
   919             self.RefreshInputPosition()
   919             self.RefreshOutputPosition()
   920             self.RefreshOutputPosition()
   920             return movex, 0
   921             return movex, 0
   921         else:
   922         else:
   922             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, width_fac = 2, height_fac = 2)
   923             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, width_fac=2, height_fac=2)
   923     
   924 
   924     # Refresh input element model
   925     # Refresh input element model
   925     def RefreshInputModel(self):
   926     def RefreshInputModel(self):
   926         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   927         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   927             input = self.GetPreviousConnector()
   928             input = self.GetPreviousConnector()
   928             if input:
   929             if input:
   929                 input_block = input.GetParentBlock()
   930                 input_block = input.GetParentBlock()
   930                 input_block.RefreshModel(False)
   931                 input_block.RefreshModel(False)
   931                 if not isinstance(input_block, SFC_Divergence):
   932                 if not isinstance(input_block, SFC_Divergence):
   932                     input_block.RefreshInputModel()
   933                     input_block.RefreshInputModel()
   933     
   934 
   934     # Refresh output element model
   935     # Refresh output element model
   935     def RefreshOutputModel(self, move=False):
   936     def RefreshOutputModel(self, move=False):
   936         output = self.GetNextConnector()
   937         output = self.GetNextConnector()
   937         if output:
   938         if output:
   938             output_block = output.GetParentBlock()
   939             output_block = output.GetParentBlock()
   939             output_block.RefreshModel(False)
   940             output_block.RefreshModel(False)
   940             if not isinstance(output_block, SFC_Divergence) or move:
   941             if not isinstance(output_block, SFC_Divergence) or move:
   941                 output_block.RefreshOutputModel(move)
   942                 output_block.RefreshOutputModel(move)
   942     
   943 
   943     # Refreshes the transition model
   944     # Refreshes the transition model
   944     def RefreshModel(self, move=True):
   945     def RefreshModel(self, move=True):
   945         self.Parent.RefreshTransitionModel(self)
   946         self.Parent.RefreshTransitionModel(self)
   946         # If transition has moved, refresh the model of wires connected to output
   947         # If transition has moved, refresh the model of wires connected to output
   947         if move:
   948         if move:
   948             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   949             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   949                 self.RefreshInputModel()
   950                 self.RefreshInputModel()
   950                 self.RefreshOutputModel()
   951                 self.RefreshOutputModel()
   951             else:
   952             else:
   952                 self.Output.RefreshWires()
   953                 self.Output.RefreshWires()
   953     
   954 
   954     # Adds an highlight to the block
   955     # Adds an highlight to the block
   955     def AddHighlight(self, infos, start, end ,highlight_type):
   956     def AddHighlight(self, infos, start, end, highlight_type):
   956         if infos[0] in ["reference", "inline", "priority"] and start[0] == 0 and end[0] == 0:
   957         if infos[0] in ["reference", "inline", "priority"] and start[0] == 0 and end[0] == 0:
   957             highlights = self.Highlights.setdefault(infos[0], [])
   958             highlights = self.Highlights.setdefault(infos[0], [])
   958             AddHighlight(highlights, (start, end, highlight_type))
   959             AddHighlight(highlights, (start, end, highlight_type))
   959     
   960 
   960     # Removes an highlight from the block
   961     # Removes an highlight from the block
   961     def RemoveHighlight(self, infos, start, end, highlight_type):
   962     def RemoveHighlight(self, infos, start, end, highlight_type):
   962         if infos[0] in ["reference", "inline", "priority"]:
   963         if infos[0] in ["reference", "inline", "priority"]:
   963             highlights = self.Highlights.get(infos[0], [])
   964             highlights = self.Highlights.get(infos[0], [])
   964             if RemoveHighlight(highlights, (start, end, highlight_type)) and len(highlights) == 0:
   965             if RemoveHighlight(highlights, (start, end, highlight_type)) and len(highlights) == 0:
   965                 self.Highlights.pop(infos[0])
   966                 self.Highlights.pop(infos[0])
   966             
   967 
   967     # Removes all the highlights of one particular type from the block
   968     # Removes all the highlights of one particular type from the block
   968     def ClearHighlight(self, highlight_type=None):
   969     def ClearHighlight(self, highlight_type=None):
   969         if highlight_type is None:
   970         if highlight_type is None:
   970             self.Highlights = {}
   971             self.Highlights = {}
   971         else:
   972         else:
   972             highlight_items = self.Highlights.items()
   973             highlight_items = self.Highlights.items()
   973             for name, highlights in highlight_items:
   974             for name, highlights in highlight_items:
   974                 highlights = ClearHighlights(highlight, highlight_type)
   975                 highlights = ClearHighlights(highlight, highlight_type)
   975                 if len(highlights) == 0:
   976                 if len(highlights) == 0:
   976                     self.Highlights.pop(name)
   977                     self.Highlights.pop(name)
   977     
   978 
   978     # Draws transition
   979     # Draws transition
   979     def Draw(self, dc):
   980     def Draw(self, dc):
   980         Graphic_Element.Draw(self, dc)
   981         Graphic_Element.Draw(self, dc)
   981         if self.Value:
   982         if self.Value:
   982             if self.Forced:
   983             if self.Forced:
   989             dc.SetPen(MiterPen(wx.BLUE))
   990             dc.SetPen(MiterPen(wx.BLUE))
   990             dc.SetBrush(wx.BLUE_BRUSH)
   991             dc.SetBrush(wx.BLUE_BRUSH)
   991         else:
   992         else:
   992             dc.SetPen(MiterPen(wx.BLACK))
   993             dc.SetPen(MiterPen(wx.BLACK))
   993             dc.SetBrush(wx.BLACK_BRUSH)
   994             dc.SetBrush(wx.BLACK_BRUSH)
   994         
   995 
   995         if getattr(dc, "printing", False):
   996         if getattr(dc, "printing", False):
   996             if self.Type != "connection":
   997             if self.Type != "connection":
   997                 condition_size = dc.GetTextExtent(self.Condition)
   998                 condition_size = dc.GetTextExtent(self.Condition)
   998             if self.Priority != 0:
   999             if self.Priority != 0:
   999                 priority_size = dc.GetTextExtent(str(self.Priority))
  1000                 priority_size = dc.GetTextExtent(str(self.Priority))
  1000         else:
  1001         else:
  1001             if self.Type != "connection":
  1002             if self.Type != "connection":
  1002                 condition_size = self.ConditionSize
  1003                 condition_size = self.ConditionSize
  1003             if self.Priority != 0:
  1004             if self.Priority != 0:
  1004                 priority_size = self.PrioritySize
  1005                 priority_size = self.PrioritySize
  1005         
  1006 
  1006         # Draw plain rectangle for representing the transition
  1007         # Draw plain rectangle for representing the transition
  1007         dc.DrawRectangle(self.Pos.x, 
  1008         dc.DrawRectangle(self.Pos.x,
  1008                          self.Pos.y + (self.Size[1] - SFC_TRANSITION_SIZE[1])/2, 
  1009                          self.Pos.y + (self.Size[1] - SFC_TRANSITION_SIZE[1])/2,
  1009                          self.Size[0] + 1,
  1010                          self.Size[0] + 1,
  1010                          SFC_TRANSITION_SIZE[1] + 1)
  1011                          SFC_TRANSITION_SIZE[1] + 1)
  1011         vertical_line_x = self.Input.GetPosition()[0]
  1012         vertical_line_x = self.Input.GetPosition()[0]
  1012         dc.DrawLine(vertical_line_x, self.Pos.y, vertical_line_x, self.Pos.y + self.Size[1] + 1) 
  1013         dc.DrawLine(vertical_line_x, self.Pos.y, vertical_line_x, self.Pos.y + self.Size[1] + 1)
  1013         # Draw transition condition
  1014         # Draw transition condition
  1014         if self.Type != "connection":
  1015         if self.Type != "connection":
  1015             if self.Condition != "":
  1016             if self.Condition != "":
  1016                 condition = self.Condition
  1017                 condition = self.Condition
  1017             else:
  1018             else:
  1026         # Draw input and output connectors
  1027         # Draw input and output connectors
  1027         self.Input.Draw(dc)
  1028         self.Input.Draw(dc)
  1028         self.Output.Draw(dc)
  1029         self.Output.Draw(dc)
  1029         if self.Type == "connection":
  1030         if self.Type == "connection":
  1030             self.Condition.Draw(dc)
  1031             self.Condition.Draw(dc)
  1031         
  1032 
  1032         if not getattr(dc, "printing", False):
  1033         if not getattr(dc, "printing", False):
  1033             for name, highlights in self.Highlights.iteritems():
  1034             for name, highlights in self.Highlights.iteritems():
  1034                 if name == "priority":
  1035                 if name == "priority":
  1035                     DrawHighlightedText(dc, str(self.Priority), highlights, priority_pos[0], priority_pos[1])
  1036                     DrawHighlightedText(dc, str(self.Priority), highlights, priority_pos[0], priority_pos[1])
  1036                 else:
  1037                 else:
  1037                     DrawHighlightedText(dc, condition, highlights, condition_pos[0], condition_pos[1])
  1038                     DrawHighlightedText(dc, condition, highlights, condition_pos[0], condition_pos[1])
  1038 
  1039 
  1039 #-------------------------------------------------------------------------------
  1040 
       
  1041 # -------------------------------------------------------------------------------
  1040 #                Sequencial Function Chart Divergence and Convergence
  1042 #                Sequencial Function Chart Divergence and Convergence
  1041 #-------------------------------------------------------------------------------
  1043 # -------------------------------------------------------------------------------
  1042 
  1044 
  1043 """
       
  1044 Class that implements the graphic representation of a divergence or convergence,
       
  1045 selection or simultaneous
       
  1046 """
       
  1047 
  1045 
  1048 class SFC_Divergence(Graphic_Element):
  1046 class SFC_Divergence(Graphic_Element):
  1049     
  1047     """
       
  1048     Class that implements the graphic representation of a divergence or convergence,
       
  1049     selection or simultaneous
       
  1050     """
       
  1051 
  1050     # Create a new divergence
  1052     # Create a new divergence
  1051     def __init__(self, parent, type, number = 2, id = None):
  1053     def __init__(self, parent, type, number=2, id=None):
  1052         Graphic_Element.__init__(self, parent)
  1054         Graphic_Element.__init__(self, parent)
  1053         self.Type = type
  1055         self.Type = type
  1054         self.Id = id
  1056         self.Id = id
  1055         self.RealConnectors = None
  1057         self.RealConnectors = None
  1056         number = max(2, number)
  1058         number = max(2, number)
  1057         self.Size = wx.Size((number - 1) * SFC_DEFAULT_SEQUENCE_INTERVAL, self.GetMinSize()[1])
  1059         self.Size = wx.Size((number - 1) * SFC_DEFAULT_SEQUENCE_INTERVAL, self.GetMinSize()[1])
  1058         # Create an input and output connector
  1060         # Create an input and output connector
  1059         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1061         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1060             self.Inputs = [Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone = True)]
  1062             self.Inputs = [Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone=True)]
  1061             self.Outputs = []
  1063             self.Outputs = []
  1062             for i in xrange(number):
  1064             for i in xrange(number):
  1063                 self.Outputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, self.Size[1]), SOUTH, onlyone = True))
  1065                 self.Outputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, self.Size[1]), SOUTH, onlyone=True))
  1064         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1066         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1065             self.Inputs = []
  1067             self.Inputs = []
  1066             for i in xrange(number):
  1068             for i in xrange(number):
  1067                 self.Inputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, 0), NORTH, onlyone = True))
  1069                 self.Inputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, 0), NORTH, onlyone=True))
  1068             self.Outputs = [Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone = True)]
  1070             self.Outputs = [Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone=True)]
  1069         self.Value = None
  1071         self.Value = None
  1070         self.PreviousValue = None
  1072         self.PreviousValue = None
  1071     
  1073 
  1072     def Flush(self):
  1074     def Flush(self):
  1073         for input in self.Inputs:
  1075         for input in self.Inputs:
  1074             input.Flush()
  1076             input.Flush()
  1075         self.Inputs = []
  1077         self.Inputs = []
  1076         for output in self.Outputs:
  1078         for output in self.Outputs:
  1077             output.Flush()
  1079             output.Flush()
  1078         self.Outputs = []
  1080         self.Outputs = []
  1079     
  1081 
  1080     def SpreadCurrent(self):
  1082     def SpreadCurrent(self):
  1081         if self.Parent.Debug:
  1083         if self.Parent.Debug:
  1082             self.PreviousValue = self.Value
  1084             self.PreviousValue = self.Value
  1083             if self.Type == SELECTION_CONVERGENCE:
  1085             if self.Type == SELECTION_CONVERGENCE:
  1084                 self.Value = False
  1086                 self.Value = False
  1100             elif not self.Value and self.PreviousValue:
  1102             elif not self.Value and self.PreviousValue:
  1101                 if self.Visible:
  1103                 if self.Visible:
  1102                     self.Parent.ElementNeedRefresh(self)
  1104                     self.Parent.ElementNeedRefresh(self)
  1103                 for output in self.Outputs:
  1105                 for output in self.Outputs:
  1104                     output.SpreadCurrent(False)
  1106                     output.SpreadCurrent(False)
  1105     
  1107 
  1106     # Make a clone of this SFC_Divergence
  1108     # Make a clone of this SFC_Divergence
  1107     def Clone(self, parent, id = None, pos = None):
  1109     def Clone(self, parent, id=None, pos=None):
  1108         divergence = SFC_Divergence(parent, self.Type, max(len(self.Inputs), len(self.Outputs)), id)
  1110         divergence = SFC_Divergence(parent, self.Type, max(len(self.Inputs), len(self.Outputs)), id)
  1109         divergence.SetSize(self.Size[0], self.Size[1])
  1111         divergence.SetSize(self.Size[0], self.Size[1])
  1110         if pos is not None:
  1112         if pos is not None:
  1111             divergence.SetPosition(pos.x, pos.y)
  1113             divergence.SetPosition(pos.x, pos.y)
  1112         else:
  1114         else:
  1113             divergence.SetPosition(self.Pos.x, self.Pos.y)
  1115             divergence.SetPosition(self.Pos.x, self.Pos.y)
  1114         divergence.Inputs = [input.Clone(divergence) for input in self.Inputs]
  1116         divergence.Inputs = [input.Clone(divergence) for input in self.Inputs]
  1115         divergence.Outputs = [output.Clone(divergence) for output in self.Outputs]
  1117         divergence.Outputs = [output.Clone(divergence) for output in self.Outputs]
  1116         return divergence
  1118         return divergence
  1117     
  1119 
  1118     def GetConnectorTranslation(self, element):
  1120     def GetConnectorTranslation(self, element):
  1119         return dict(zip(self.Inputs + self.Outputs, element.Inputs + element.Outputs))
  1121         return dict(zip(self.Inputs + self.Outputs, element.Inputs + element.Outputs))
  1120     
  1122 
  1121     # Returns the RedrawRect
  1123     # Returns the RedrawRect
  1122     def GetRedrawRect(self, movex = 0, movey = 0):
  1124     def GetRedrawRect(self, movex=0, movey=0):
  1123         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1125         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1124         if movex != 0 or movey != 0:
  1126         if movex != 0 or movey != 0:
  1125             for input in self.Inputs:
  1127             for input in self.Inputs:
  1126                 if input.IsConnected():
  1128                 if input.IsConnected():
  1127                     rect = rect.Union(input.GetConnectedRedrawRect(movex, movey))
  1129                     rect = rect.Union(input.GetConnectedRedrawRect(movex, movey))
  1128             for output in self.Outputs:
  1130             for output in self.Outputs:
  1129                 if output.IsConnected():
  1131                 if output.IsConnected():
  1130                     rect = rect.Union(output.GetConnectedRedrawRect(movex, movey))
  1132                     rect = rect.Union(output.GetConnectedRedrawRect(movex, movey))
  1131         return rect
  1133         return rect
  1132     
  1134 
  1133     # Forbids to resize the divergence
  1135     # Forbids to resize the divergence
  1134     def Resize(self, x, y, width, height):
  1136     def Resize(self, x, y, width, height):
  1135         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1137         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1136             Graphic_Element.Resize(self, x, 0, width, self.GetMinSize()[1])
  1138             Graphic_Element.Resize(self, x, 0, width, self.GetMinSize()[1])
  1137     
  1139 
  1138     # Delete this divergence by calling the appropriate method
  1140     # Delete this divergence by calling the appropriate method
  1139     def Delete(self):
  1141     def Delete(self):
  1140         self.Parent.DeleteDivergence(self)
  1142         self.Parent.DeleteDivergence(self)
  1141     
  1143 
  1142     # Returns the divergence type
  1144     # Returns the divergence type
  1143     def GetType(self):
  1145     def GetType(self):
  1144         return self.Type
  1146         return self.Type
  1145     
  1147 
  1146     # Unconnect input and output
  1148     # Unconnect input and output
  1147     def Clean(self):
  1149     def Clean(self):
  1148         for input in self.Inputs:
  1150         for input in self.Inputs:
  1149             input.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
  1151             input.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
  1150         for output in self.Outputs:
  1152         for output in self.Outputs:
  1151             output.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
  1153             output.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
  1152     
  1154 
  1153     # Add a branch to the divergence
  1155     # Add a branch to the divergence
  1154     def AddBranch(self):
  1156     def AddBranch(self):
  1155         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1157         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1156             maxx = 0
  1158             maxx = 0
  1157             for output in self.Outputs:
  1159             for output in self.Outputs:
  1158                 pos = output.GetRelPosition()
  1160                 pos = output.GetRelPosition()
  1159                 maxx = max(maxx, pos.x)
  1161                 maxx = max(maxx, pos.x)
  1160             connector = Connector(self, "", None, wx.Point(maxx + SFC_DEFAULT_SEQUENCE_INTERVAL, self.Size[1]), SOUTH, onlyone = True)
  1162             connector = Connector(self, "", None, wx.Point(maxx + SFC_DEFAULT_SEQUENCE_INTERVAL, self.Size[1]), SOUTH, onlyone=True)
  1161             self.Outputs.append(connector)
  1163             self.Outputs.append(connector)
  1162             self.MoveConnector(connector, 0)
  1164             self.MoveConnector(connector, 0)
  1163         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1165         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1164             maxx = 0
  1166             maxx = 0
  1165             for input in self.Inputs:
  1167             for input in self.Inputs:
  1166                 pos = input.GetRelPosition()
  1168                 pos = input.GetRelPosition()
  1167                 maxx = max(maxx, pos.x)
  1169                 maxx = max(maxx, pos.x)
  1168             connector = Connector(self, "", None, wx.Point(maxx + SFC_DEFAULT_SEQUENCE_INTERVAL, 0), NORTH, onlyone = True)
  1170             connector = Connector(self, "", None, wx.Point(maxx + SFC_DEFAULT_SEQUENCE_INTERVAL, 0), NORTH, onlyone=True)
  1169             self.Inputs.append(connector)
  1171             self.Inputs.append(connector)
  1170             self.MoveConnector(connector, SFC_DEFAULT_SEQUENCE_INTERVAL)
  1172             self.MoveConnector(connector, SFC_DEFAULT_SEQUENCE_INTERVAL)
  1171     
  1173 
  1172     # Remove a branch from the divergence
  1174     # Remove a branch from the divergence
  1173     def RemoveBranch(self, connector):
  1175     def RemoveBranch(self, connector):
  1174         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1176         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1175             if connector in self.Outputs and len(self.Outputs) > 2:
  1177             if connector in self.Outputs and len(self.Outputs) > 2:
  1176                 self.Outputs.remove(connector)
  1178                 self.Outputs.remove(connector)
  1177                 self.MoveConnector(self.Outputs[0], 0)
  1179                 self.MoveConnector(self.Outputs[0], 0)
  1178         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1180         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1179             if connector in self.Inputs and len(self.Inputs) > 2:
  1181             if connector in self.Inputs and len(self.Inputs) > 2:
  1180                 self.Inputs.remove(connector)
  1182                 self.Inputs.remove(connector)
  1181                 self.MoveConnector(self.Inputs[0], 0)
  1183                 self.MoveConnector(self.Inputs[0], 0)
  1182     
  1184 
  1183     # Remove the handled branch from the divergence
  1185     # Remove the handled branch from the divergence
  1184     def RemoveHandledBranch(self):
  1186     def RemoveHandledBranch(self):
  1185         handle_type, handle = self.Handle
  1187         handle_type, handle = self.Handle
  1186         if handle_type == HANDLE_CONNECTOR:
  1188         if handle_type == HANDLE_CONNECTOR:
  1187             handle.UnConnect(delete=True)
  1189             handle.UnConnect(delete=True)
  1188             self.RemoveBranch(handle)
  1190             self.RemoveBranch(handle)
  1189             
  1191 
  1190     # Return the number of branches for the divergence
  1192     # Return the number of branches for the divergence
  1191     def GetBranchNumber(self):
  1193     def GetBranchNumber(self):
  1192         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1194         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1193             return len(self.Outputs)
  1195             return len(self.Outputs)
  1194         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1196         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1195             return len(self.Inputs)
  1197             return len(self.Inputs)
  1196     
  1198 
  1197     # Returns if the point given is in the bounding box
  1199     # Returns if the point given is in the bounding box
  1198     def HitTest(self, pt, connectors=True):
  1200     def HitTest(self, pt, connectors=True):
  1199         return self.BoundingBox.InsideXY(pt.x, pt.y) or self.TestConnector(pt, exclude=False) != None
  1201         return self.BoundingBox.InsideXY(pt.x, pt.y) or self.TestConnector(pt, exclude=False) is not None
  1200     
  1202 
  1201     # Refresh the divergence bounding box
  1203     # Refresh the divergence bounding box
  1202     def RefreshBoundingBox(self):
  1204     def RefreshBoundingBox(self):
  1203         if self.Type in [SELECTION_DIVERGENCE, SELECTION_CONVERGENCE]:
  1205         if self.Type in [SELECTION_DIVERGENCE, SELECTION_CONVERGENCE]:
  1204             self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, 
  1206             self.BoundingBox = wx.Rect(self.Pos.x,       self.Pos.y,
  1205                 self.Size[0] + 1, self.Size[1] + 1)
  1207                                        self.Size[0] + 1, self.Size[1] + 1)
  1206         elif self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1208         elif self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1207             self.BoundingBox = wx.Rect(self.Pos.x - SFC_SIMULTANEOUS_SEQUENCE_EXTRA, self.Pos.y, 
  1209             self.BoundingBox = wx.Rect(
       
  1210                 self.Pos.x - SFC_SIMULTANEOUS_SEQUENCE_EXTRA,           self.Pos.y,
  1208                 self.Size[0] + 2 * SFC_SIMULTANEOUS_SEQUENCE_EXTRA + 1, self.Size[1] + 1)
  1211                 self.Size[0] + 2 * SFC_SIMULTANEOUS_SEQUENCE_EXTRA + 1, self.Size[1] + 1)
  1209     
  1212 
  1210     # Refresh the position of wires connected to divergence
  1213     # Refresh the position of wires connected to divergence
  1211     def RefreshConnected(self, exclude = []):
  1214     def RefreshConnected(self, exclude=[]):
  1212         for input in self.Inputs:
  1215         for input in self.Inputs:
  1213             input.MoveConnected(exclude)
  1216             input.MoveConnected(exclude)
  1214         for output in self.Outputs:
  1217         for output in self.Outputs:
  1215             output.MoveConnected(exclude)
  1218             output.MoveConnected(exclude)
  1216     
  1219 
  1217     # Moves the divergence connector given
  1220     # Moves the divergence connector given
  1218     def MoveConnector(self, connector, movex):
  1221     def MoveConnector(self, connector, movex):
  1219         position = connector.GetRelPosition()
  1222         position = connector.GetRelPosition()
  1220         connector.SetPosition(wx.Point(position.x + movex, position.y))
  1223         connector.SetPosition(wx.Point(position.x + movex, position.y))
  1221         minx = self.Size[0]
  1224         minx = self.Size[0]
  1239         self.Outputs.sort(lambda x, y: cmp(x.Pos.x, y.Pos.x))
  1242         self.Outputs.sort(lambda x, y: cmp(x.Pos.x, y.Pos.x))
  1240         self.Pos.x += minx
  1243         self.Pos.x += minx
  1241         self.Size[0] = maxx - minx
  1244         self.Size[0] = maxx - minx
  1242         connector.MoveConnected()
  1245         connector.MoveConnected()
  1243         self.RefreshBoundingBox()
  1246         self.RefreshBoundingBox()
  1244     
  1247 
  1245     # Returns the divergence connector that starts with the point given if it exists 
  1248     # Returns the divergence connector that starts with the point given if it exists
  1246     def GetConnector(self, position, name = None):
  1249     def GetConnector(self, position, name=None):
  1247         # if a name is given
  1250         # if a name is given
  1248         if name is not None:
  1251         if name is not None:
  1249             # Test each input and output connector
  1252             # Test each input and output connector
  1250             #for input in self.Inputs:
  1253             # for input in self.Inputs:
  1251             #    if name == input.GetName():
  1254             #    if name == input.GetName():
  1252             #        return input
  1255             #        return input
  1253             for output in self.Outputs:
  1256             for output in self.Outputs:
  1254                 if name == output.GetName():
  1257                 if name == output.GetName():
  1255                     return output
  1258                     return output
  1256         return self.FindNearestConnector(position, self.Inputs + self.Outputs)
  1259         return self.FindNearestConnector(position, self.Inputs + self.Outputs)
  1257     
  1260 
  1258     # Returns input and output divergence connectors 
  1261     # Returns input and output divergence connectors
  1259     def GetConnectors(self):
  1262     def GetConnectors(self):
  1260         return {"inputs": self.Inputs, "outputs": self.Outputs}
  1263         return {"inputs": self.Inputs, "outputs": self.Outputs}
  1261     
  1264 
  1262     # Test if point given is on divergence input or output connector
  1265     # Test if point given is on divergence input or output connector
  1263     def TestConnector(self, pt, direction = None, exclude=True):
  1266     def TestConnector(self, pt, direction=None, exclude=True):
  1264         # Test input connector
  1267         # Test input connector
  1265         for input in self.Inputs:
  1268         for input in self.Inputs:
  1266             if input.TestPoint(pt, direction, exclude):
  1269             if input.TestPoint(pt, direction, exclude):
  1267                 return input
  1270                 return input
  1268         # Test output connector
  1271         # Test output connector
  1269         for output in self.Outputs:
  1272         for output in self.Outputs:
  1270             if output.TestPoint(pt, direction, exclude):
  1273             if output.TestPoint(pt, direction, exclude):
  1271                 return output
  1274                 return output
  1272         return None
  1275         return None
  1273     
  1276 
  1274     # Changes the divergence size
  1277     # Changes the divergence size
  1275     def SetSize(self, width, height):
  1278     def SetSize(self, width, height):
  1276         height = self.GetMinSize()[1]
  1279         height = self.GetMinSize()[1]
  1277         for i, input in enumerate(self.Inputs):
  1280         for i, input in enumerate(self.Inputs):
  1278             position = input.GetRelPosition()
  1281             position = input.GetRelPosition()
  1288             else:
  1291             else:
  1289                 output.SetPosition(wx.Point(int(round(float(position.x)*float(width)/float(self.Size[0]))), height))
  1292                 output.SetPosition(wx.Point(int(round(float(position.x)*float(width)/float(self.Size[0]))), height))
  1290             output.MoveConnected()
  1293             output.MoveConnected()
  1291         self.Size = wx.Size(width, height)
  1294         self.Size = wx.Size(width, height)
  1292         self.RefreshBoundingBox()
  1295         self.RefreshBoundingBox()
  1293     
  1296 
  1294     # Returns the divergence minimum size
  1297     # Returns the divergence minimum size
  1295     def GetMinSize(self, default=False):
  1298     def GetMinSize(self, default=False):
  1296         width = 0
  1299         width = 0
  1297         if default:
  1300         if default:
  1298             if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1301             if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1302         if self.Type in [SELECTION_DIVERGENCE, SELECTION_CONVERGENCE]:
  1305         if self.Type in [SELECTION_DIVERGENCE, SELECTION_CONVERGENCE]:
  1303             return width, 1
  1306             return width, 1
  1304         elif self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1307         elif self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1305             return width, 3
  1308             return width, 3
  1306         return 0, 0
  1309         return 0, 0
  1307     
  1310 
  1308     # Refresh the position of the block connected to connector
  1311     # Refresh the position of the block connected to connector
  1309     def RefreshConnectedPosition(self, connector):
  1312     def RefreshConnectedPosition(self, connector):
  1310         wires = connector.GetWires()
  1313         wires = connector.GetWires()
  1311         if len(wires) != 1:
  1314         if len(wires) != 1:
  1312             return
  1315             return
  1338         if diffy != 0:
  1341         if diffy != 0:
  1339             self.Move(0, diffy, self.Parent.Wires)
  1342             self.Move(0, diffy, self.Parent.Wires)
  1340             self.RefreshOutputPosition((0, diffy))
  1343             self.RefreshOutputPosition((0, diffy))
  1341         for input in self.Inputs:
  1344         for input in self.Inputs:
  1342             input.MoveConnected()
  1345             input.MoveConnected()
  1343     
  1346 
  1344     # Align output element with this divergence
  1347     # Align output element with this divergence
  1345     def RefreshOutputPosition(self, move = None):
  1348     def RefreshOutputPosition(self, move=None):
  1346         if move:
  1349         if move:
  1347             for output_connector in self.Outputs:
  1350             for output_connector in self.Outputs:
  1348                 wires = output_connector.GetWires()
  1351                 wires = output_connector.GetWires()
  1349                 if len(wires) != 1:
  1352                 if len(wires) != 1:
  1350                     return
  1353                     return
  1357                     output_block.MoveActionBlock(move)
  1360                     output_block.MoveActionBlock(move)
  1358                 wires[0][0].Move(move[0], move[1], True)
  1361                 wires[0][0].Move(move[0], move[1], True)
  1359                 if not isinstance(output_block, SFC_Divergence) or output_block.GetConnectors()["inputs"].index(output) == 0:
  1362                 if not isinstance(output_block, SFC_Divergence) or output_block.GetConnectors()["inputs"].index(output) == 0:
  1360                     output_block.Move(move[0], move[1], self.Parent.Wires)
  1363                     output_block.Move(move[0], move[1], self.Parent.Wires)
  1361                     output_block.RefreshOutputPosition(move)
  1364                     output_block.RefreshOutputPosition(move)
  1362     
  1365 
  1363     # Method called when a LeftDown event have been generated
  1366     # Method called when a LeftDown event have been generated
  1364     def OnLeftDown(self, event, dc, scaling):
  1367     def OnLeftDown(self, event, dc, scaling):
  1365         self.RealConnectors = {"Inputs":[],"Outputs":[]}
  1368         self.RealConnectors = {"Inputs": [], "Outputs": []}
  1366         for input in self.Inputs:
  1369         for input in self.Inputs:
  1367             position = input.GetRelPosition()
  1370             position = input.GetRelPosition()
  1368             self.RealConnectors["Inputs"].append(float(position.x)/float(self.Size[0]))
  1371             self.RealConnectors["Inputs"].append(float(position.x)/float(self.Size[0]))
  1369         for output in self.Outputs:
  1372         for output in self.Outputs:
  1370             position = output.GetRelPosition()
  1373             position = output.GetRelPosition()
  1371             self.RealConnectors["Outputs"].append(float(position.x)/float(self.Size[0]))
  1374             self.RealConnectors["Outputs"].append(float(position.x)/float(self.Size[0]))
  1372         Graphic_Element.OnLeftDown(self, event, dc, scaling)
  1375         Graphic_Element.OnLeftDown(self, event, dc, scaling)
  1373     
  1376 
  1374     # Method called when a LeftUp event have been generated
  1377     # Method called when a LeftUp event have been generated
  1375     def OnLeftUp(self, event, dc, scaling):
  1378     def OnLeftUp(self, event, dc, scaling):
  1376         Graphic_Element.OnLeftUp(self, event, dc, scaling)
  1379         Graphic_Element.OnLeftUp(self, event, dc, scaling)
  1377         self.RealConnectors = None
  1380         self.RealConnectors = None
  1378     
  1381 
  1379     # Method called when a RightDown event have been generated
  1382     # Method called when a RightDown event have been generated
  1380     def OnRightDown(self, event, dc, scaling):
  1383     def OnRightDown(self, event, dc, scaling):
  1381         pos = GetScaledEventPosition(event, dc, scaling)
  1384         pos = GetScaledEventPosition(event, dc, scaling)
  1382         # Test if a connector have been handled
  1385         # Test if a connector have been handled
  1383         connector = self.TestConnector(pos, exclude=False)
  1386         connector = self.TestConnector(pos, exclude=False)
  1387             self.Selected = False
  1390             self.Selected = False
  1388             # Initializes the last position
  1391             # Initializes the last position
  1389             self.oldPos = GetScaledEventPosition(event, dc, scaling)
  1392             self.oldPos = GetScaledEventPosition(event, dc, scaling)
  1390         else:
  1393         else:
  1391             Graphic_Element.OnRightDown(self, event, dc, scaling)
  1394             Graphic_Element.OnRightDown(self, event, dc, scaling)
  1392     
  1395 
  1393     # Method called when a RightUp event have been generated
  1396     # Method called when a RightUp event have been generated
  1394     def OnRightUp(self, event, dc, scaling):
  1397     def OnRightUp(self, event, dc, scaling):
  1395         pos = GetScaledEventPosition(event, dc, scaling)
  1398         pos = GetScaledEventPosition(event, dc, scaling)
  1396         handle_type, handle = self.Handle
  1399         handle_type, handle = self.Handle
  1397         if handle_type == HANDLE_CONNECTOR and self.Dragging and self.oldPos:
  1400         if handle_type == HANDLE_CONNECTOR and self.Dragging and self.oldPos:
  1412                 self.Handle = (HANDLE_CONNECTOR, connector)
  1415                 self.Handle = (HANDLE_CONNECTOR, connector)
  1413                 self.Parent.PopupDivergenceMenu(True)
  1416                 self.Parent.PopupDivergenceMenu(True)
  1414             else:
  1417             else:
  1415                 # Popup the divergence menu without delete branch
  1418                 # Popup the divergence menu without delete branch
  1416                 self.Parent.PopupDivergenceMenu(False)
  1419                 self.Parent.PopupDivergenceMenu(False)
  1417         
  1420 
  1418     # Refreshes the divergence state according to move defined and handle selected
  1421     # Refreshes the divergence state according to move defined and handle selected
  1419     def ProcessDragging(self, movex, movey, event, scaling):
  1422     def ProcessDragging(self, movex, movey, event, scaling):
  1420         handle_type, handle = self.Handle
  1423         handle_type, handle = self.Handle
  1421         # A connector has been handled
  1424         # A connector has been handled
  1422         if handle_type == HANDLE_CONNECTOR:
  1425         if handle_type == HANDLE_CONNECTOR:
  1428                 self.RefreshConnectedPosition(handle)
  1431                 self.RefreshConnectedPosition(handle)
  1429             return movex, 0
  1432             return movex, 0
  1430         elif self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1433         elif self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1431             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  1434             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  1432         return 0, 0
  1435         return 0, 0
  1433     
  1436 
  1434     # Refresh output element model
  1437     # Refresh output element model
  1435     def RefreshOutputModel(self, move=False):
  1438     def RefreshOutputModel(self, move=False):
  1436         if move and self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1439         if move and self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1437             for output in self.Outputs:
  1440             for output in self.Outputs:
  1438                 wires = output.GetWires()
  1441                 wires = output.GetWires()
  1440                     return
  1443                     return
  1441                 output_block = wires[0][0].GetOtherConnected(output).GetParentBlock()
  1444                 output_block = wires[0][0].GetOtherConnected(output).GetParentBlock()
  1442                 output_block.RefreshModel(False)
  1445                 output_block.RefreshModel(False)
  1443                 if not isinstance(output_block, SFC_Divergence) or move:
  1446                 if not isinstance(output_block, SFC_Divergence) or move:
  1444                     output_block.RefreshOutputModel(move)
  1447                     output_block.RefreshOutputModel(move)
  1445     
  1448 
  1446     # Refreshes the divergence model
  1449     # Refreshes the divergence model
  1447     def RefreshModel(self, move=True):
  1450     def RefreshModel(self, move=True):
  1448         self.Parent.RefreshDivergenceModel(self)
  1451         self.Parent.RefreshDivergenceModel(self)
  1449         # If divergence has moved, refresh the model of wires connected to outputs
  1452         # If divergence has moved, refresh the model of wires connected to outputs
  1450         if move:
  1453         if move:
  1451             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1454             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1452                 self.RefreshOutputModel()
  1455                 self.RefreshOutputModel()
  1453             else:
  1456             else:
  1454                 for output in self.Outputs:
  1457                 for output in self.Outputs:
  1455                     output.RefreshWires()
  1458                     output.RefreshWires()
  1456     
  1459 
  1457     # Draws the highlightment of this element if it is highlighted
  1460     # Draws the highlightment of this element if it is highlighted
  1458     def DrawHighlightment(self, dc):
  1461     def DrawHighlightment(self, dc):
  1459         scalex, scaley = dc.GetUserScale()
  1462         scalex, scaley = dc.GetUserScale()
  1460         dc.SetUserScale(1, 1)
  1463         dc.SetUserScale(1, 1)
  1461         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  1464         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  1465         posx = self.Pos.x
  1468         posx = self.Pos.x
  1466         width = self.Size[0]
  1469         width = self.Size[0]
  1467         if self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1470         if self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1468             posx -= SFC_SIMULTANEOUS_SEQUENCE_EXTRA
  1471             posx -= SFC_SIMULTANEOUS_SEQUENCE_EXTRA
  1469             width += SFC_SIMULTANEOUS_SEQUENCE_EXTRA * 2
  1472             width += SFC_SIMULTANEOUS_SEQUENCE_EXTRA * 2
  1470         dc.DrawRectangle(int(round((posx - 1) * scalex)) - 2, 
  1473         dc.DrawRectangle(int(round((posx - 1) * scalex)) - 2,
  1471                          int(round((self.Pos.y - 1) * scaley)) - 2, 
  1474                          int(round((self.Pos.y - 1) * scaley)) - 2,
  1472                          int(round((width + 3) * scalex)) + 5, 
  1475                          int(round((width + 3) * scalex)) + 5,
  1473                          int(round((self.Size.height + 3) * scaley)) + 5)
  1476                          int(round((self.Size.height + 3) * scaley)) + 5)
  1474         dc.SetLogicalFunction(wx.COPY)
  1477         dc.SetLogicalFunction(wx.COPY)
  1475         dc.SetUserScale(scalex, scaley)
  1478         dc.SetUserScale(scalex, scaley)
  1476         
  1479 
  1477     # Draws divergence
  1480     # Draws divergence
  1478     def Draw(self, dc):
  1481     def Draw(self, dc):
  1479         Graphic_Element.Draw(self, dc)
  1482         Graphic_Element.Draw(self, dc)
  1480         if self.Value:
  1483         if self.Value:
  1481             dc.SetPen(MiterPen(wx.GREEN))
  1484             dc.SetPen(MiterPen(wx.GREEN))
  1485             dc.SetBrush(wx.BLACK_BRUSH)
  1488             dc.SetBrush(wx.BLACK_BRUSH)
  1486         # Draw plain rectangle for representing the divergence
  1489         # Draw plain rectangle for representing the divergence
  1487         if self.Type in [SELECTION_DIVERGENCE, SELECTION_CONVERGENCE]:
  1490         if self.Type in [SELECTION_DIVERGENCE, SELECTION_CONVERGENCE]:
  1488             dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  1491             dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  1489         elif self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1492         elif self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1490             dc.DrawLine(self.Pos.x - SFC_SIMULTANEOUS_SEQUENCE_EXTRA, self.Pos.y, 
  1493             dc.DrawLine(self.Pos.x - SFC_SIMULTANEOUS_SEQUENCE_EXTRA, self.Pos.y,
  1491                         self.Pos.x + self.Size[0] + SFC_SIMULTANEOUS_SEQUENCE_EXTRA + 1, self.Pos.y)
  1494                         self.Pos.x + self.Size[0] + SFC_SIMULTANEOUS_SEQUENCE_EXTRA + 1, self.Pos.y)
  1492             dc.DrawLine(self.Pos.x - SFC_SIMULTANEOUS_SEQUENCE_EXTRA, self.Pos.y + self.Size[1], 
  1495             dc.DrawLine(self.Pos.x - SFC_SIMULTANEOUS_SEQUENCE_EXTRA, self.Pos.y + self.Size[1],
  1493                         self.Pos.x + self.Size[0] + SFC_SIMULTANEOUS_SEQUENCE_EXTRA + 1, self.Pos.y + self.Size[1])
  1496                         self.Pos.x + self.Size[0] + SFC_SIMULTANEOUS_SEQUENCE_EXTRA + 1, self.Pos.y + self.Size[1])
  1494         # Draw inputs and outputs connectors
  1497         # Draw inputs and outputs connectors
  1495         for input in self.Inputs:
  1498         for input in self.Inputs:
  1496             input.Draw(dc)
  1499             input.Draw(dc)
  1497         for output in self.Outputs:
  1500         for output in self.Outputs:
  1498             output.Draw(dc)
  1501             output.Draw(dc)
  1499         
  1502 
  1500 
  1503 
  1501 #-------------------------------------------------------------------------------
  1504 # -------------------------------------------------------------------------------
  1502 #                   Sequencial Function Chart Jump to Step
  1505 #                   Sequencial Function Chart Jump to Step
  1503 #-------------------------------------------------------------------------------
  1506 # -------------------------------------------------------------------------------
  1504 
  1507 
  1505 """
       
  1506 Class that implements the graphic representation of a jump to step
       
  1507 """
       
  1508 
  1508 
  1509 class SFC_Jump(Graphic_Element):
  1509 class SFC_Jump(Graphic_Element):
  1510     
  1510     """
       
  1511     Class that implements the graphic representation of a jump to step
       
  1512     """
       
  1513 
  1511     # Create a new jump
  1514     # Create a new jump
  1512     def __init__(self, parent, target, id = None):
  1515     def __init__(self, parent, target, id=None):
  1513         Graphic_Element.__init__(self, parent)
  1516         Graphic_Element.__init__(self, parent)
  1514         self.SetTarget(target)
  1517         self.SetTarget(target)
  1515         self.Id = id
  1518         self.Id = id
  1516         self.Size = wx.Size(SFC_JUMP_SIZE[0], SFC_JUMP_SIZE[1])
  1519         self.Size = wx.Size(SFC_JUMP_SIZE[0], SFC_JUMP_SIZE[1])
  1517         self.Highlights = []
  1520         self.Highlights = []
  1518         # Create an input and output connector
  1521         # Create an input and output connector
  1519         self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone = True)
  1522         self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone=True)
  1520         self.Value = None
  1523         self.Value = None
  1521         self.PreviousValue = None
  1524         self.PreviousValue = None
  1522         
  1525 
  1523     def Flush(self):
  1526     def Flush(self):
  1524         if self.Input is not None:
  1527         if self.Input is not None:
  1525             self.Input.Flush()
  1528             self.Input.Flush()
  1526             self.Input = None
  1529             self.Input = None
  1527     
  1530 
  1528     def SpreadCurrent(self):
  1531     def SpreadCurrent(self):
  1529         if self.Parent.Debug:
  1532         if self.Parent.Debug:
  1530             self.PreviousValue = self.Value
  1533             self.PreviousValue = self.Value
  1531             self.Value = self.Input.ReceivingCurrent()
  1534             self.Value = self.Input.ReceivingCurrent()
  1532             if self.Value != self.PreviousValue and self.Visible:
  1535             if self.Value != self.PreviousValue and self.Visible:
  1533                 self.Parent.ElementNeedRefresh(self)
  1536                 self.Parent.ElementNeedRefresh(self)
  1534     
  1537 
  1535     # Make a clone of this SFC_Jump
  1538     # Make a clone of this SFC_Jump
  1536     def Clone(self, parent, id = None, pos = None):
  1539     def Clone(self, parent, id=None, pos=None):
  1537         jump = SFC_Jump(parent, self.Target, id)
  1540         jump = SFC_Jump(parent, self.Target, id)
  1538         jump.SetSize(self.Size[0], self.Size[1])
  1541         jump.SetSize(self.Size[0], self.Size[1])
  1539         if pos is not None:
  1542         if pos is not None:
  1540             jump.SetPosition(pos.x, pos.y)
  1543             jump.SetPosition(pos.x, pos.y)
  1541         else:
  1544         else:
  1542             jump.SetPosition(self.Pos.x, self.Pos.y)
  1545             jump.SetPosition(self.Pos.x, self.Pos.y)
  1543         jump.Input = self.Input.Clone(jump)
  1546         jump.Input = self.Input.Clone(jump)
  1544         return jump
  1547         return jump
  1545     
  1548 
  1546     def GetConnectorTranslation(self, element):
  1549     def GetConnectorTranslation(self, element):
  1547         return {self.Input : element.Input}
  1550         return {self.Input: element.Input}
  1548     
  1551 
  1549     # Returns the RedrawRect
  1552     # Returns the RedrawRect
  1550     def GetRedrawRect(self, movex = 0, movey = 0):
  1553     def GetRedrawRect(self, movex=0, movey=0):
  1551         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1554         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1552         if self.Input:
  1555         if self.Input:
  1553             rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
  1556             rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
  1554         if movex != 0 or movey != 0:
  1557         if movex != 0 or movey != 0:
  1555             if self.Input.IsConnected():
  1558             if self.Input.IsConnected():
  1556                 rect = rect.Union(self.Input.GetConnectedRedrawRect(movex, movey))
  1559                 rect = rect.Union(self.Input.GetConnectedRedrawRect(movex, movey))
  1557         return rect
  1560         return rect
  1558     
  1561 
  1559     # Forbids to change the jump size
  1562     # Forbids to change the jump size
  1560     def SetSize(self, width, height):
  1563     def SetSize(self, width, height):
  1561         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1564         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1562             Graphic_Element.SetSize(self, width, height)
  1565             Graphic_Element.SetSize(self, width, height)
  1563     
  1566 
  1564     # Forbids to resize jump
  1567     # Forbids to resize jump
  1565     def Resize(self, x, y, width, height):
  1568     def Resize(self, x, y, width, height):
  1566         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1569         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1567             Graphic_Element.Resize(self, x, y, width, height)
  1570             Graphic_Element.Resize(self, x, y, width, height)
  1568     
  1571 
  1569     # Delete this jump by calling the appropriate method
  1572     # Delete this jump by calling the appropriate method
  1570     def Delete(self):
  1573     def Delete(self):
  1571         self.Parent.DeleteJump(self)
  1574         self.Parent.DeleteJump(self)
  1572     
  1575 
  1573     # Unconnect input
  1576     # Unconnect input
  1574     def Clean(self):
  1577     def Clean(self):
  1575         self.Input.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
  1578         self.Input.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
  1576     
  1579 
  1577     # Refresh the size of text for target
  1580     # Refresh the size of text for target
  1578     def RefreshTargetSize(self):
  1581     def RefreshTargetSize(self):
  1579         self.TargetSize = self.Parent.GetTextExtent(self.Target)
  1582         self.TargetSize = self.Parent.GetTextExtent(self.Target)
  1580     
  1583 
  1581     # Returns if the point given is in the bounding box
  1584     # Returns if the point given is in the bounding box
  1582     def HitTest(self, pt, connectors=True):
  1585     def HitTest(self, pt, connectors=True):
  1583         # Calculate the bounding box of the condition outside the transition
  1586         # Calculate the bounding box of the condition outside the transition
  1584         text_width, text_height = self.TargetSize
  1587         text_width, text_height = self.TargetSize
  1585         text_bbx = wx.Rect(self.Pos.x + self.Size[0] + 2,
  1588         text_bbx = wx.Rect(self.Pos.x + self.Size[0] + 2,
  1586                            self.Pos.y + (self.Size[1] - text_height) / 2,
  1589                            self.Pos.y + (self.Size[1] - text_height) / 2,
  1587                            text_width,
  1590                            text_width,
  1588                            text_height)
  1591                            text_height)
  1589         return text_bbx.InsideXY(pt.x, pt.y) or Graphic_Element.HitTest(self, pt, connectors)
  1592         return text_bbx.InsideXY(pt.x, pt.y) or Graphic_Element.HitTest(self, pt, connectors)
  1590     
  1593 
  1591     # Refresh the jump bounding box
  1594     # Refresh the jump bounding box
  1592     def RefreshBoundingBox(self):
  1595     def RefreshBoundingBox(self):
  1593         text_width, text_height = self.Parent.GetTextExtent(self.Target)
  1596         text_width, text_height = self.Parent.GetTextExtent(self.Target)
  1594         # Calculate the bounding box size
  1597         # Calculate the bounding box size
  1595         bbx_width = self.Size[0] + 2 + text_width
  1598         bbx_width = self.Size[0] + 2 + text_width
  1596         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y - CONNECTOR_SIZE, 
  1599         self.BoundingBox = wx.Rect(self.Pos.x,    self.Pos.y - CONNECTOR_SIZE,
  1597                 bbx_width + 1, self.Size[1] + CONNECTOR_SIZE + 1)
  1600                                    bbx_width + 1, self.Size[1] + CONNECTOR_SIZE + 1)
  1598     
  1601 
  1599     # Returns the connector connected to input
  1602     # Returns the connector connected to input
  1600     def GetPreviousConnector(self):
  1603     def GetPreviousConnector(self):
  1601         wires = self.Input.GetWires()
  1604         wires = self.Input.GetWires()
  1602         if len(wires) == 1:
  1605         if len(wires) == 1:
  1603             return wires[0][0].GetOtherConnected(self.Input)
  1606             return wires[0][0].GetOtherConnected(self.Input)
  1604         return None
  1607         return None
  1605     
  1608 
  1606     # Refresh the element connectors position
  1609     # Refresh the element connectors position
  1607     def RefreshConnectors(self):
  1610     def RefreshConnectors(self):
  1608         scaling = self.Parent.GetScaling()
  1611         scaling = self.Parent.GetScaling()
  1609         horizontal_pos = self.Size[0] / 2
  1612         horizontal_pos = self.Size[0] / 2
  1610         if scaling is not None:
  1613         if scaling is not None:
  1611             horizontal_pos = round(float(self.Pos.x + horizontal_pos) / float(scaling[0])) * scaling[0] - self.Pos.x
  1614             horizontal_pos = round(float(self.Pos.x + horizontal_pos) / float(scaling[0])) * scaling[0] - self.Pos.x
  1612         self.Input.SetPosition(wx.Point(horizontal_pos, 0))
  1615         self.Input.SetPosition(wx.Point(horizontal_pos, 0))
  1613         self.RefreshConnected()
  1616         self.RefreshConnected()
  1614     
  1617 
  1615     # Refresh the position of wires connected to jump
  1618     # Refresh the position of wires connected to jump
  1616     def RefreshConnected(self, exclude = []):
  1619     def RefreshConnected(self, exclude=[]):
  1617         if self.Input:
  1620         if self.Input:
  1618             self.Input.MoveConnected(exclude)
  1621             self.Input.MoveConnected(exclude)
  1619     
  1622 
  1620     # Returns input jump connector 
  1623     # Returns input jump connector
  1621     def GetConnector(self, position = None, name = None):
  1624     def GetConnector(self, position=None, name=None):
  1622         return self.Input
  1625         return self.Input
  1623     
  1626 
  1624     # Returns all the jump connectors 
  1627     # Returns all the jump connectors
  1625     def GetConnectors(self):
  1628     def GetConnectors(self):
  1626         return {"inputs": [self.Input], "outputs": []}
  1629         return {"inputs": [self.Input], "outputs": []}
  1627     
  1630 
  1628     # Test if point given is on jump input connector
  1631     # Test if point given is on jump input connector
  1629     def TestConnector(self, pt, direction = None, exclude = True):
  1632     def TestConnector(self, pt, direction=None, exclude=True):
  1630         # Test input connector
  1633         # Test input connector
  1631         if self.Input and self.Input.TestPoint(pt, direction, exclude):
  1634         if self.Input and self.Input.TestPoint(pt, direction, exclude):
  1632             return self.Input
  1635             return self.Input
  1633         return None
  1636         return None
  1634     
  1637 
  1635     # Changes the jump target
  1638     # Changes the jump target
  1636     def SetTarget(self, target):
  1639     def SetTarget(self, target):
  1637         self.Target = target
  1640         self.Target = target
  1638         self.RefreshTargetSize()
  1641         self.RefreshTargetSize()
  1639         self.RefreshBoundingBox()
  1642         self.RefreshBoundingBox()
  1640     
  1643 
  1641     # Returns the jump target
  1644     # Returns the jump target
  1642     def GetTarget(self):
  1645     def GetTarget(self):
  1643         return self.Target
  1646         return self.Target
  1644     
  1647 
  1645     # Returns the jump minimum size
  1648     # Returns the jump minimum size
  1646     def GetMinSize(self):
  1649     def GetMinSize(self):
  1647         return SFC_JUMP_SIZE
  1650         return SFC_JUMP_SIZE
  1648     
  1651 
  1649     # Align input element with this jump
  1652     # Align input element with this jump
  1650     def RefreshInputPosition(self):
  1653     def RefreshInputPosition(self):
  1651         if self.Input:
  1654         if self.Input:
  1652             current_pos = self.Input.GetPosition(False)
  1655             current_pos = self.Input.GetPosition(False)
  1653             input = self.GetPreviousConnector()
  1656             input = self.GetPreviousConnector()
  1660                 else:
  1663                 else:
  1661                     if isinstance(input_block, SFC_Step):
  1664                     if isinstance(input_block, SFC_Step):
  1662                         input_block.MoveActionBlock((diffx, 0))
  1665                         input_block.MoveActionBlock((diffx, 0))
  1663                     input_block.Move(diffx, 0)
  1666                     input_block.Move(diffx, 0)
  1664                     input_block.RefreshInputPosition()
  1667                     input_block.RefreshInputPosition()
  1665     
  1668 
  1666     # Can't align output element, because there is no output
  1669     # Can't align output element, because there is no output
  1667     def RefreshOutputPosition(self, move = None):
  1670     def RefreshOutputPosition(self, move=None):
  1668         pass
  1671         pass
  1669     
  1672 
  1670     # Method called when a LeftDClick event have been generated
  1673     # Method called when a LeftDClick event have been generated
  1671     def OnLeftDClick(self, event, dc, scaling):
  1674     def OnLeftDClick(self, event, dc, scaling):
  1672         # Edit the jump properties
  1675         # Edit the jump properties
  1673         self.Parent.EditJumpContent(self)
  1676         self.Parent.EditJumpContent(self)
  1674     
  1677 
  1675     # Method called when a RightUp event have been generated
  1678     # Method called when a RightUp event have been generated
  1676     def OnRightUp(self, event, dc, scaling):
  1679     def OnRightUp(self, event, dc, scaling):
  1677         # Popup the default menu
  1680         # Popup the default menu
  1678         self.Parent.PopupDefaultMenu()
  1681         self.Parent.PopupDefaultMenu()
  1679     
  1682 
  1680     # Refreshes the jump state according to move defined and handle selected
  1683     # Refreshes the jump state according to move defined and handle selected
  1681     def ProcessDragging(self, movex, movey, event, scaling):
  1684     def ProcessDragging(self, movex, movey, event, scaling):
  1682         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1685         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1683             movex = max(-self.BoundingBox.x, movex)
  1686             movex = max(-self.BoundingBox.x, movex)
  1684             if scaling is not None:
  1687             if scaling is not None:
  1685                 movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
  1688                 movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
  1686             self.Move(movex, 0)
  1689             self.Move(movex, 0)
  1687             self.RefreshInputPosition()
  1690             self.RefreshInputPosition()
  1688             return movex, 0
  1691             return movex, 0
  1689         else:
  1692         else:
  1690             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, width_fac = 2)
  1693             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, width_fac=2)
  1691     
  1694 
  1692     # Refresh input element model
  1695     # Refresh input element model
  1693     def RefreshInputModel(self):
  1696     def RefreshInputModel(self):
  1694         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1697         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1695             input = self.GetPreviousConnector()
  1698             input = self.GetPreviousConnector()
  1696             if input:
  1699             if input:
  1697                 input_block = input.GetParentBlock()
  1700                 input_block = input.GetParentBlock()
  1698                 input_block.RefreshModel(False)
  1701                 input_block.RefreshModel(False)
  1699                 if not isinstance(input_block, SFC_Divergence):
  1702                 if not isinstance(input_block, SFC_Divergence):
  1700                     input_block.RefreshInputModel()
  1703                     input_block.RefreshInputModel()
  1701     
  1704 
  1702     # Refresh output element model
  1705     # Refresh output element model
  1703     def RefreshOutputModel(self, move=False):
  1706     def RefreshOutputModel(self, move=False):
  1704         pass
  1707         pass
  1705     
  1708 
  1706     # Refreshes the jump model
  1709     # Refreshes the jump model
  1707     def RefreshModel(self, move=True):
  1710     def RefreshModel(self, move=True):
  1708         self.Parent.RefreshJumpModel(self)
  1711         self.Parent.RefreshJumpModel(self)
  1709         if move:
  1712         if move:
  1710             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1713             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1711                 self.RefreshInputModel()
  1714                 self.RefreshInputModel()
  1712     
  1715 
  1713     # Adds an highlight to the variable
  1716     # Adds an highlight to the variable
  1714     def AddHighlight(self, infos, start, end, highlight_type):
  1717     def AddHighlight(self, infos, start, end, highlight_type):
  1715         if infos[0] == "target" and start[0] == 0 and end[0] == 0:
  1718         if infos[0] == "target" and start[0] == 0 and end[0] == 0:
  1716             AddHighlight(self.Highlights, (start, end, highlight_type))
  1719             AddHighlight(self.Highlights, (start, end, highlight_type))
  1717     
  1720 
  1718     # Removes an highlight from the variable
  1721     # Removes an highlight from the variable
  1719     def RemoveHighlight(self, infos, start, end, highlight_type):
  1722     def RemoveHighlight(self, infos, start, end, highlight_type):
  1720         if infos[0] == "target":
  1723         if infos[0] == "target":
  1721             RemoveHighlight(self.Highlights, (start, end, highlight_type))
  1724             RemoveHighlight(self.Highlights, (start, end, highlight_type))
  1722     
  1725 
  1723     # Removes all the highlights of one particular type from the variable
  1726     # Removes all the highlights of one particular type from the variable
  1724     def ClearHighlight(self, highlight_type=None):
  1727     def ClearHighlight(self, highlight_type=None):
  1725         ClearHighlights(self.Highlights, highlight_type)
  1728         ClearHighlights(self.Highlights, highlight_type)
  1726     
  1729 
  1727     # Draws the highlightment of this element if it is highlighted
  1730     # Draws the highlightment of this element if it is highlighted
  1728     def DrawHighlightment(self, dc):
  1731     def DrawHighlightment(self, dc):
  1729         scalex, scaley = dc.GetUserScale()
  1732         scalex, scaley = dc.GetUserScale()
  1730         dc.SetUserScale(1, 1)
  1733         dc.SetUserScale(1, 1)
  1731         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  1734         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  1732         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  1735         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  1733         dc.SetLogicalFunction(wx.AND)
  1736         dc.SetLogicalFunction(wx.AND)
  1734         points = [wx.Point(int(round((self.Pos.x - 2) * scalex)) - 3, 
  1737         points = [wx.Point(int(round((self.Pos.x - 2) * scalex)) - 3,
  1735                            int(round((self.Pos.y - 2) * scaley)) - 2),
  1738                            int(round((self.Pos.y - 2) * scaley)) - 2),
  1736                   wx.Point(int(round((self.Pos.x + self.Size[0] + 2) * scalex)) + 4, 
  1739                   wx.Point(int(round((self.Pos.x + self.Size[0] + 2) * scalex)) + 4,
  1737                            int(round((self.Pos.y - 2) * scaley)) - 2),
  1740                            int(round((self.Pos.y - 2) * scaley)) - 2),
  1738                   wx.Point(int(round((self.Pos.x + self.Size[0] / 2) * scalex)), 
  1741                   wx.Point(int(round((self.Pos.x + self.Size[0] / 2) * scalex)),
  1739                            int(round((self.Pos.y + self.Size[1] + 3) * scaley)) + 4)]
  1742                            int(round((self.Pos.y + self.Size[1] + 3) * scaley)) + 4)]
  1740         dc.DrawPolygon(points)
  1743         dc.DrawPolygon(points)
  1741         dc.SetLogicalFunction(wx.COPY)
  1744         dc.SetLogicalFunction(wx.COPY)
  1742         dc.SetUserScale(scalex, scaley)
  1745         dc.SetUserScale(scalex, scaley)
  1743     
  1746 
  1744     # Draws divergence
  1747     # Draws divergence
  1745     def Draw(self, dc):
  1748     def Draw(self, dc):
  1746         Graphic_Element.Draw(self, dc)
  1749         Graphic_Element.Draw(self, dc)
  1747         if self.Value:
  1750         if self.Value:
  1748             dc.SetPen(MiterPen(wx.GREEN))
  1751             dc.SetPen(MiterPen(wx.GREEN))
  1749             dc.SetBrush(wx.GREEN_BRUSH)
  1752             dc.SetBrush(wx.GREEN_BRUSH)
  1750         else:
  1753         else:
  1751             dc.SetPen(MiterPen(wx.BLACK))
  1754             dc.SetPen(MiterPen(wx.BLACK))
  1752             dc.SetBrush(wx.BLACK_BRUSH)
  1755             dc.SetBrush(wx.BLACK_BRUSH)
  1753         
  1756 
  1754         if getattr(dc, "printing", False):
  1757         if getattr(dc, "printing", False):
  1755             target_size = dc.GetTextExtent(self.Target)
  1758             target_size = dc.GetTextExtent(self.Target)
  1756         else:
  1759         else:
  1757             target_size = self.TargetSize
  1760             target_size = self.TargetSize
  1758         
  1761 
  1759         # Draw plain rectangle for representing the divergence
  1762         # Draw plain rectangle for representing the divergence
  1760         dc.DrawLine(self.Pos.x + self.Size[0] / 2, self.Pos.y, self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1])
  1763         dc.DrawLine(self.Pos.x + self.Size[0] / 2, self.Pos.y, self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1])
  1761         points = [wx.Point(self.Pos.x, self.Pos.y),
  1764         points = [wx.Point(self.Pos.x, self.Pos.y),
  1762                   wx.Point(self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1] / 3),
  1765                   wx.Point(self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1] / 3),
  1763                   wx.Point(self.Pos.x + self.Size[0], self.Pos.y),
  1766                   wx.Point(self.Pos.x + self.Size[0], self.Pos.y),
  1767                       self.Pos.y + (self.Size[1] - target_size[1]) / 2)
  1770                       self.Pos.y + (self.Size[1] - target_size[1]) / 2)
  1768         dc.DrawText(self.Target, target_pos[0], target_pos[1])
  1771         dc.DrawText(self.Target, target_pos[0], target_pos[1])
  1769         # Draw input connector
  1772         # Draw input connector
  1770         if self.Input:
  1773         if self.Input:
  1771             self.Input.Draw(dc)
  1774             self.Input.Draw(dc)
  1772             
  1775 
  1773         if not getattr(dc, "printing", False):
  1776         if not getattr(dc, "printing", False):
  1774             DrawHighlightedText(dc, self.Target, self.Highlights, target_pos[0], target_pos[1])
  1777             DrawHighlightedText(dc, self.Target, self.Highlights, target_pos[0], target_pos[1])
  1775         
  1778 
  1776 
  1779 
  1777 #-------------------------------------------------------------------------------
  1780 # -------------------------------------------------------------------------------
  1778 #                   Sequencial Function Chart Action Block
  1781 #                   Sequencial Function Chart Action Block
  1779 #-------------------------------------------------------------------------------
  1782 # -------------------------------------------------------------------------------
  1780 
  1783 
  1781 """
       
  1782 Class that implements the graphic representation of an action block
       
  1783 """
       
  1784 
  1784 
  1785 class SFC_ActionBlock(Graphic_Element):
  1785 class SFC_ActionBlock(Graphic_Element):
  1786     
  1786     """
       
  1787     Class that implements the graphic representation of an action block
       
  1788     """
       
  1789 
  1787     # Create a new action block
  1790     # Create a new action block
  1788     def __init__(self, parent, actions = [], id = None):
  1791     def __init__(self, parent, actions=[], id=None):
  1789         Graphic_Element.__init__(self, parent)
  1792         Graphic_Element.__init__(self, parent)
  1790         self.Id = id
  1793         self.Id = id
  1791         self.Size = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
  1794         self.Size = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
  1792         self.MinSize = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
  1795         self.MinSize = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
  1793         self.Highlights = {}
  1796         self.Highlights = {}
  1794         # Create an input and output connector
  1797         # Create an input and output connector
  1795         self.Input = Connector(self, "", None, wx.Point(0, SFC_ACTION_MIN_SIZE[1] / 2), WEST, onlyone = True)
  1798         self.Input = Connector(self, "", None, wx.Point(0, SFC_ACTION_MIN_SIZE[1] / 2), WEST, onlyone=True)
  1796         self.SetActions(actions)
  1799         self.SetActions(actions)
  1797         self.Value = None
  1800         self.Value = None
  1798         self.PreviousValue = None
  1801         self.PreviousValue = None
  1799     
  1802 
  1800     def Flush(self):
  1803     def Flush(self):
  1801         if self.Input is not None:
  1804         if self.Input is not None:
  1802             self.Input.Flush()
  1805             self.Input.Flush()
  1803             self.Input = None
  1806             self.Input = None
  1804     
  1807 
  1805     def SpreadCurrent(self):
  1808     def SpreadCurrent(self):
  1806         if self.Parent.Debug:
  1809         if self.Parent.Debug:
  1807             self.PreviousValue = self.Value
  1810             self.PreviousValue = self.Value
  1808             self.Value = self.Input.ReceivingCurrent()
  1811             self.Value = self.Input.ReceivingCurrent()
  1809             if self.Value != self.PreviousValue and self.Visible:
  1812             if self.Value != self.PreviousValue and self.Visible:
  1810                 self.Parent.ElementNeedRefresh(self)
  1813                 self.Parent.ElementNeedRefresh(self)
  1811     
  1814 
  1812     # Make a clone of this SFC_ActionBlock
  1815     # Make a clone of this SFC_ActionBlock
  1813     def Clone(self, parent, id = None, pos = None):
  1816     def Clone(self, parent, id=None, pos=None):
  1814         actions = [action.copy() for action in self.Actions]
  1817         actions = [action.copy() for action in self.Actions]
  1815         action_block = SFC_ActionBlock(parent, actions, id)
  1818         action_block = SFC_ActionBlock(parent, actions, id)
  1816         action_block.SetSize(self.Size[0], self.Size[1])
  1819         action_block.SetSize(self.Size[0], self.Size[1])
  1817         if pos is not None:
  1820         if pos is not None:
  1818             action_block.SetPosition(pos.x, pos.y)
  1821             action_block.SetPosition(pos.x, pos.y)
  1819         else:
  1822         else:
  1820             action_block.SetPosition(self.Pos.x, self.Pos.y)
  1823             action_block.SetPosition(self.Pos.x, self.Pos.y)
  1821         action_block.Input = self.Input.Clone(action_block)
  1824         action_block.Input = self.Input.Clone(action_block)
  1822         return action_block
  1825         return action_block
  1823     
  1826 
  1824     def GetConnectorTranslation(self, element):
  1827     def GetConnectorTranslation(self, element):
  1825         return {self.Input : element.Input}
  1828         return {self.Input: element.Input}
  1826     
  1829 
  1827     # Returns the RedrawRect
  1830     # Returns the RedrawRect
  1828     def GetRedrawRect(self, movex = 0, movey = 0):
  1831     def GetRedrawRect(self, movex=0, movey=0):
  1829         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1832         rect = Graphic_Element.GetRedrawRect(self, movex, movey)
  1830         if self.Input:
  1833         if self.Input:
  1831             rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
  1834             rect = rect.Union(self.Input.GetRedrawRect(movex, movey))
  1832         if movex != 0 or movey != 0:
  1835         if movex != 0 or movey != 0:
  1833             if self.Input.IsConnected():
  1836             if self.Input.IsConnected():
  1834                 rect = rect.Union(self.Input.GetConnectedRedrawRect(movex, movey))
  1837                 rect = rect.Union(self.Input.GetConnectedRedrawRect(movex, movey))
  1835         return rect
  1838         return rect
  1836     
  1839 
  1837     # Returns the number of action lines
  1840     # Returns the number of action lines
  1838     def GetLineNumber(self):
  1841     def GetLineNumber(self):
  1839         return len(self.Actions)
  1842         return len(self.Actions)
  1840     
  1843 
  1841     def GetLineSize(self):
  1844     def GetLineSize(self):
  1842         if len(self.Actions) > 0:
  1845         if len(self.Actions) > 0:
  1843             return self.Size[1] / len(self.Actions)
  1846             return self.Size[1] / len(self.Actions)
  1844         else:
  1847         else:
  1845             return SFC_ACTION_MIN_SIZE[1]
  1848             return SFC_ACTION_MIN_SIZE[1]
  1846     
  1849 
  1847     # Forbids to resize the action block
  1850     # Forbids to resize the action block
  1848     def Resize(self, x, y, width, height):
  1851     def Resize(self, x, y, width, height):
  1849         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1852         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1850             if x == 0:
  1853             if x == 0:
  1851                 self.SetSize(width, self.Size[1])
  1854                 self.SetSize(width, self.Size[1])
  1852         else:
  1855         else:
  1853             Graphic_Element.Resize(self, x, y, width, height)
  1856             Graphic_Element.Resize(self, x, y, width, height)
  1854     
  1857 
  1855     # Delete this action block by calling the appropriate method
  1858     # Delete this action block by calling the appropriate method
  1856     def Delete(self):
  1859     def Delete(self):
  1857         self.Parent.DeleteActionBlock(self)
  1860         self.Parent.DeleteActionBlock(self)
  1858     
  1861 
  1859     # Unconnect input and output
  1862     # Unconnect input and output
  1860     def Clean(self):
  1863     def Clean(self):
  1861         self.Input.UnConnect(delete = self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
  1864         self.Input.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
  1862         
  1865 
  1863     # Refresh the action block bounding box
  1866     # Refresh the action block bounding box
  1864     def RefreshBoundingBox(self):
  1867     def RefreshBoundingBox(self):
  1865         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  1868         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  1866     
  1869 
  1867     # Refresh the position of wires connected to action block
  1870     # Refresh the position of wires connected to action block
  1868     def RefreshConnected(self, exclude = []):
  1871     def RefreshConnected(self, exclude=[]):
  1869         self.Input.MoveConnected(exclude)
  1872         self.Input.MoveConnected(exclude)
  1870     
  1873 
  1871     # Returns input action block connector 
  1874     # Returns input action block connector
  1872     def GetConnector(self, position = None, name = None):
  1875     def GetConnector(self, position=None, name=None):
  1873         return self.Input
  1876         return self.Input
  1874     
  1877 
  1875     # Returns all the action block connectors 
  1878     # Returns all the action block connectors
  1876     def GetConnectors(self):
  1879     def GetConnectors(self):
  1877         return {"inputs": [self.Input], "outputs": []}
  1880         return {"inputs": [self.Input], "outputs": []}
  1878     
  1881 
  1879     # Test if point given is on action block input connector
  1882     # Test if point given is on action block input connector
  1880     def TestConnector(self, pt, direction = None, exclude = True):
  1883     def TestConnector(self, pt, direction=None, exclude=True):
  1881         # Test input connector
  1884         # Test input connector
  1882         if self.Input.TestPoint(pt, direction, exclude):
  1885         if self.Input.TestPoint(pt, direction, exclude):
  1883             return self.Input
  1886             return self.Input
  1884         return None
  1887         return None
  1885     
  1888 
  1886     # Refresh the element connectors position
  1889     # Refresh the element connectors position
  1887     def RefreshConnectors(self):
  1890     def RefreshConnectors(self):
  1888         scaling = self.Parent.GetScaling()
  1891         scaling = self.Parent.GetScaling()
  1889         vertical_pos = SFC_ACTION_MIN_SIZE[1] / 2
  1892         vertical_pos = SFC_ACTION_MIN_SIZE[1] / 2
  1890         if scaling is not None:
  1893         if scaling is not None:
  1891             vertical_pos = round(float(self.Pos.y + vertical_pos) / float(scaling[1])) * scaling[1] - self.Pos.y
  1894             vertical_pos = round(float(self.Pos.y + vertical_pos) / float(scaling[1])) * scaling[1] - self.Pos.y
  1892         self.Input.SetPosition(wx.Point(0, vertical_pos))
  1895         self.Input.SetPosition(wx.Point(0, vertical_pos))
  1893         self.RefreshConnected()
  1896         self.RefreshConnected()
  1894     
  1897 
  1895     # Changes the action block actions
  1898     # Changes the action block actions
  1896     def SetActions(self, actions):
  1899     def SetActions(self, actions):
  1897         self.Actions = actions
  1900         self.Actions = actions
  1898         self.ColSize = [0, 0, 0]
  1901         self.ColSize = [0, 0, 0]
  1899         min_height = 0
  1902         min_height = 0
  1915                 self.ColSize[2] = max(self.ColSize[2], width + 10)
  1918                 self.ColSize[2] = max(self.ColSize[2], width + 10)
  1916             min_height += row_height + 5
  1919             min_height += row_height + 5
  1917         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1920         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1918             self.Size = wx.Size(self.ColSize[0] + self.ColSize[1] + self.ColSize[2], max(min_height, SFC_ACTION_MIN_SIZE[1], self.Size[1]))
  1921             self.Size = wx.Size(self.ColSize[0] + self.ColSize[1] + self.ColSize[2], max(min_height, SFC_ACTION_MIN_SIZE[1], self.Size[1]))
  1919             self.MinSize = max(self.ColSize[0] + self.ColSize[1] + self.ColSize[2],
  1922             self.MinSize = max(self.ColSize[0] + self.ColSize[1] + self.ColSize[2],
  1920                 SFC_ACTION_MIN_SIZE[0]), max(SFC_ACTION_MIN_SIZE[1], min_height)
  1923                                SFC_ACTION_MIN_SIZE[0]), max(SFC_ACTION_MIN_SIZE[1], min_height)
  1921             self.RefreshBoundingBox()
  1924             self.RefreshBoundingBox()
  1922         else:
  1925         else:
  1923             self.Size = wx.Size(max(self.ColSize[0] + self.ColSize[1] + self.ColSize[2],
  1926             self.Size = wx.Size(max(self.ColSize[0] + self.ColSize[1] + self.ColSize[2],
  1924                 SFC_ACTION_MIN_SIZE[0]), len(self.Actions) * SFC_ACTION_MIN_SIZE[1])
  1927                                     SFC_ACTION_MIN_SIZE[0]),
       
  1928                                 len(self.Actions) * SFC_ACTION_MIN_SIZE[1])
  1925             self.MinSize = max(self.ColSize[0] + self.ColSize[1] + self.ColSize[2],
  1929             self.MinSize = max(self.ColSize[0] + self.ColSize[1] + self.ColSize[2],
  1926                 SFC_ACTION_MIN_SIZE[0]), len(self.Actions) * SFC_ACTION_MIN_SIZE[1]
  1930                                SFC_ACTION_MIN_SIZE[0]), len(self.Actions) * SFC_ACTION_MIN_SIZE[1]
  1927             self.RefreshBoundingBox()
  1931             self.RefreshBoundingBox()
  1928             if self.Input is not None:
  1932             if self.Input is not None:
  1929                 wires = self.Input.GetWires()
  1933                 wires = self.Input.GetWires()
  1930                 if len(wires) == 1:
  1934                 if len(wires) == 1:
  1931                     input_block = wires[0][0].GetOtherConnected(self.Input).GetParentBlock()
  1935                     input_block = wires[0][0].GetOtherConnected(self.Input).GetParentBlock()
  1932                     input_block.RefreshOutputPosition()
  1936                     input_block.RefreshOutputPosition()
  1933                     input_block.RefreshOutputModel(True)
  1937                     input_block.RefreshOutputModel(True)
  1934     
  1938 
  1935     # Returns the action block actions
  1939     # Returns the action block actions
  1936     def GetActions(self):
  1940     def GetActions(self):
  1937         return self.Actions
  1941         return self.Actions
  1938     
  1942 
  1939     # Returns the action block minimum size
  1943     # Returns the action block minimum size
  1940     def GetMinSize(self):
  1944     def GetMinSize(self):
  1941         return self.MinSize
  1945         return self.MinSize
  1942     
  1946 
  1943     # Method called when a LeftDClick event have been generated
  1947     # Method called when a LeftDClick event have been generated
  1944     def OnLeftDClick(self, event, dc, scaling):
  1948     def OnLeftDClick(self, event, dc, scaling):
  1945         # Edit the action block properties
  1949         # Edit the action block properties
  1946         self.Parent.EditActionBlockContent(self)
  1950         self.Parent.EditActionBlockContent(self)
  1947     
  1951 
  1948     # Method called when a RightUp event have been generated
  1952     # Method called when a RightUp event have been generated
  1949     def OnRightUp(self, event, dc, scaling):
  1953     def OnRightUp(self, event, dc, scaling):
  1950         # Popup the default menu
  1954         # Popup the default menu
  1951         self.Parent.PopupDefaultMenu()
  1955         self.Parent.PopupDefaultMenu()
  1952     
  1956 
  1953     # Refreshes the action block state according to move defined and handle selected
  1957     # Refreshes the action block state according to move defined and handle selected
  1954     def ProcessDragging(self, movex, movey, event, scaling):
  1958     def ProcessDragging(self, movex, movey, event, scaling):
  1955         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1959         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1956             handle_type, handle = self.Handle
  1960             handle_type, handle = self.Handle
  1957             if handle_type == HANDLE_MOVE:
  1961             if handle_type == HANDLE_MOVE:
  1968             else:
  1972             else:
  1969                 return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  1973                 return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  1970         else:
  1974         else:
  1971             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  1975             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling)
  1972 
  1976 
  1973     
       
  1974     # Refreshes the action block model
  1977     # Refreshes the action block model
  1975     def RefreshModel(self, move=True):
  1978     def RefreshModel(self, move=True):
  1976         self.Parent.RefreshActionBlockModel(self)
  1979         self.Parent.RefreshActionBlockModel(self)
  1977     
  1980 
  1978     # Adds an highlight to the variable
  1981     # Adds an highlight to the variable
  1979     def AddHighlight(self, infos, start, end, highlight_type):
  1982     def AddHighlight(self, infos, start, end, highlight_type):
  1980         if infos[0] == "action" and infos[1] < len(self.Actions):
  1983         if infos[0] == "action" and infos[1] < len(self.Actions):
  1981             action_highlights = self.Highlights.setdefault(infos[1], {})
  1984             action_highlights = self.Highlights.setdefault(infos[1], {})
  1982             attribute_highlights = action_highlights.setdefault(infos[2], [])
  1985             attribute_highlights = action_highlights.setdefault(infos[2], [])
  1983             AddHighlight(attribute_highlights, (start, end, highlight_type))
  1986             AddHighlight(attribute_highlights, (start, end, highlight_type))
  1984     
  1987 
  1985     # Removes an highlight from the block
  1988     # Removes an highlight from the block
  1986     def RemoveHighlight(self, infos, start, end, highlight_type):
  1989     def RemoveHighlight(self, infos, start, end, highlight_type):
  1987         if infos[0] == "action" and infos[1] < len(self.Actions):
  1990         if infos[0] == "action" and infos[1] < len(self.Actions):
  1988             action_highlights = self.Highlights.get(infos[1], {})
  1991             action_highlights = self.Highlights.get(infos[1], {})
  1989             attribute_highlights = action_highlights.setdefault(infos[2], [])
  1992             attribute_highlights = action_highlights.setdefault(infos[2], [])
  1990             if RemoveHighlight(attribute_highlights, (start, end, highlight_type)) and len(attribute_highlights) == 0:
  1993             if RemoveHighlight(attribute_highlights, (start, end, highlight_type)) and len(attribute_highlights) == 0:
  1991                 action_highlights.pop(infos[2])
  1994                 action_highlights.pop(infos[2])
  1992                 if len(action_highlights) == 0:
  1995                 if len(action_highlights) == 0:
  1993                     self.Highlights.pop(infos[1])
  1996                     self.Highlights.pop(infos[1])
  1994     
  1997 
  1995     # Removes all the highlights of one particular type from the block
  1998     # Removes all the highlights of one particular type from the block
  1996     def ClearHighlight(self, highlight_type=None):
  1999     def ClearHighlight(self, highlight_type=None):
  1997         if highlight_type is None:
  2000         if highlight_type is None:
  1998             self.Highlights = {}
  2001             self.Highlights = {}
  1999         else:
  2002         else:
  2004                     attribute_highlights = ClearHighlights(attribute_highlights, highlight_type)
  2007                     attribute_highlights = ClearHighlights(attribute_highlights, highlight_type)
  2005                     if len(attribute_highlights) == 0:
  2008                     if len(attribute_highlights) == 0:
  2006                         action_highlights.pop(name)
  2009                         action_highlights.pop(name)
  2007                 if len(action_highlights) == 0:
  2010                 if len(action_highlights) == 0:
  2008                     self.Highlights.pop(number)
  2011                     self.Highlights.pop(number)
  2009     
  2012 
  2010     # Draws divergence
  2013     # Draws divergence
  2011     def Draw(self, dc):
  2014     def Draw(self, dc):
  2012         Graphic_Element.Draw(self, dc)
  2015         Graphic_Element.Draw(self, dc)
  2013         if self.Value:
  2016         if self.Value:
  2014             dc.SetPen(MiterPen(wx.GREEN))
  2017             dc.SetPen(MiterPen(wx.GREEN))
  2016             dc.SetPen(MiterPen(wx.BLACK))
  2019             dc.SetPen(MiterPen(wx.BLACK))
  2017         dc.SetBrush(wx.WHITE_BRUSH)
  2020         dc.SetBrush(wx.WHITE_BRUSH)
  2018         colsize = [self.ColSize[0], self.Size[0] - self.ColSize[0] - self.ColSize[2], self.ColSize[2]]
  2021         colsize = [self.ColSize[0], self.Size[0] - self.ColSize[0] - self.ColSize[2], self.ColSize[2]]
  2019         # Draw plain rectangle for representing the action block
  2022         # Draw plain rectangle for representing the action block
  2020         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  2023         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
  2021         dc.DrawLine(self.Pos.x + colsize[0], self.Pos.y, 
  2024         dc.DrawLine(self.Pos.x + colsize[0], self.Pos.y,
  2022                 self.Pos.x + colsize[0], self.Pos.y + self.Size[1])
  2025                     self.Pos.x + colsize[0], self.Pos.y + self.Size[1])
  2023         dc.DrawLine(self.Pos.x + colsize[0] + colsize[1], self.Pos.y, 
  2026         dc.DrawLine(self.Pos.x + colsize[0] + colsize[1], self.Pos.y,
  2024                 self.Pos.x + colsize[0] + colsize[1], self.Pos.y + self.Size[1])
  2027                     self.Pos.x + colsize[0] + colsize[1], self.Pos.y + self.Size[1])
  2025         line_size = self.GetLineSize()
  2028         line_size = self.GetLineSize()
  2026         for i, action in enumerate(self.Actions):
  2029         for i, action in enumerate(self.Actions):
  2027             if i != 0:
  2030             if i != 0:
  2028                 dc.DrawLine(self.Pos.x, self.Pos.y + i * line_size, 
  2031                 dc.DrawLine(self.Pos.x, self.Pos.y + i * line_size,
  2029                     self.Pos.x + self.Size[0], self.Pos.y + i * line_size)
  2032                             self.Pos.x + self.Size[0], self.Pos.y + i * line_size)
  2030             qualifier_size = dc.GetTextExtent(action.qualifier)
  2033             qualifier_size = dc.GetTextExtent(action.qualifier)
  2031             if action.duration != "":
  2034             if action.duration != "":
  2032                 qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) / 2,
  2035                 qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) / 2,
  2033                                  self.Pos.y + i * line_size + line_size / 2 - qualifier_size[1])
  2036                                  self.Pos.y + i * line_size + line_size / 2 - qualifier_size[1])
  2034                 duration_size = dc.GetTextExtent(action.duration)
  2037                 duration_size = dc.GetTextExtent(action.duration)
  2046             if action.indicator != "":
  2049             if action.indicator != "":
  2047                 indicator_size = dc.GetTextExtent(action.indicator)
  2050                 indicator_size = dc.GetTextExtent(action.indicator)
  2048                 indicator_pos = (self.Pos.x + colsize[0] + colsize[1] + (colsize[2] - indicator_size[0]) / 2,
  2051                 indicator_pos = (self.Pos.x + colsize[0] + colsize[1] + (colsize[2] - indicator_size[0]) / 2,
  2049                                  self.Pos.y + i * line_size + (line_size - indicator_size[1]) / 2)
  2052                                  self.Pos.y + i * line_size + (line_size - indicator_size[1]) / 2)
  2050                 dc.DrawText(action.indicator, indicator_pos[0], indicator_pos[1])
  2053                 dc.DrawText(action.indicator, indicator_pos[0], indicator_pos[1])
  2051             
  2054 
  2052             if not getattr(dc, "printing", False):
  2055             if not getattr(dc, "printing", False):
  2053                 action_highlights = self.Highlights.get(i, {})
  2056                 action_highlights = self.Highlights.get(i, {})
  2054                 for name, attribute_highlights in action_highlights.iteritems():
  2057                 for name, attribute_highlights in action_highlights.iteritems():
  2055                     if name == "qualifier":
  2058                     if name == "qualifier":
  2056                         DrawHighlightedText(dc, action.qualifier, attribute_highlights, qualifier_pos[0], qualifier_pos[1])
  2059                         DrawHighlightedText(dc, action.qualifier, attribute_highlights, qualifier_pos[0], qualifier_pos[1])
  2058                         DrawHighlightedText(dc, action.duration, attribute_highlights, duration_pos[0], duration_pos[1])
  2061                         DrawHighlightedText(dc, action.duration, attribute_highlights, duration_pos[0], duration_pos[1])
  2059                     elif name in ["reference", "inline"]:
  2062                     elif name in ["reference", "inline"]:
  2060                         DrawHighlightedText(dc, action.value, attribute_highlights, content_pos[0], content_pos[1])
  2063                         DrawHighlightedText(dc, action.value, attribute_highlights, content_pos[0], content_pos[1])
  2061                     elif name == "indicator":
  2064                     elif name == "indicator":
  2062                         DrawHighlightedText(dc, action.indicator, attribute_highlights, indicator_pos[0], indicator_pos[1])
  2065                         DrawHighlightedText(dc, action.indicator, attribute_highlights, indicator_pos[0], indicator_pos[1])
  2063         
  2066 
  2064         # Draw input connector
  2067         # Draw input connector
  2065         self.Input.Draw(dc)
  2068         self.Input.Draw(dc)
  2066