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