graphics/SFC_Objects.py
changeset 2437 105c20fdeb19
parent 2432 dbc065a2f7a5
child 2457 9deec258ab1a
equal deleted inserted replaced
2436:82bfc75bcd9d 2437:105c20fdeb19
    22 # along with this program; if not, write to the Free Software
    22 # along with this program; if not, write to the Free Software
    23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    24 
    24 
    25 
    25 
    26 from __future__ import absolute_import
    26 from __future__ import absolute_import
       
    27 from __future__ import division
    27 import wx
    28 import wx
    28 from six.moves import xrange
    29 from six.moves import xrange
    29 
    30 
    30 from graphics.GraphicCommons import *
    31 from graphics.GraphicCommons import *
    31 from graphics.DebugDataConsumer import DebugDataConsumer
    32 from graphics.DebugDataConsumer import DebugDataConsumer
    57         self.Id = id
    58         self.Id = id
    58         self.Highlights = []
    59         self.Highlights = []
    59         self.Size = wx.Size(SFC_STEP_DEFAULT_SIZE[0], SFC_STEP_DEFAULT_SIZE[1])
    60         self.Size = wx.Size(SFC_STEP_DEFAULT_SIZE[0], SFC_STEP_DEFAULT_SIZE[1])
    60         # Create an input and output connector
    61         # Create an input and output connector
    61         if not self.Initial:
    62         if not self.Initial:
    62             self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH)
    63             self.Input = Connector(self, "", None, wx.Point(self.Size[0] // 2, 0), NORTH)
    63         else:
    64         else:
    64             self.Input = None
    65             self.Input = None
    65         self.Output = None
    66         self.Output = None
    66         self.Action = None
    67         self.Action = None
    67         self.PreviousValue = None
    68         self.PreviousValue = None
   169         self.NameSize = self.Parent.GetTextExtent(self.Name)
   170         self.NameSize = self.Parent.GetTextExtent(self.Name)
   170 
   171 
   171     # Add output connector to step
   172     # Add output connector to step
   172     def AddInput(self):
   173     def AddInput(self):
   173         if not self.Input:
   174         if not self.Input:
   174             self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH)
   175             self.Input = Connector(self, "", None, wx.Point(self.Size[0] // 2, 0), NORTH)
   175             self.RefreshBoundingBox()
   176             self.RefreshBoundingBox()
   176 
   177 
   177     # Remove output connector from step
   178     # Remove output connector from step
   178     def RemoveInput(self):
   179     def RemoveInput(self):
   179         if self.Input:
   180         if self.Input:
   182             self.RefreshBoundingBox()
   183             self.RefreshBoundingBox()
   183 
   184 
   184     # Add output connector to step
   185     # Add output connector to step
   185     def AddOutput(self):
   186     def AddOutput(self):
   186         if not self.Output:
   187         if not self.Output:
   187             self.Output = Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone=True)
   188             self.Output = Connector(self, "", None, wx.Point(self.Size[0] // 2, self.Size[1]), SOUTH, onlyone=True)
   188             self.RefreshBoundingBox()
   189             self.RefreshBoundingBox()
   189 
   190 
   190     # Remove output connector from step
   191     # Remove output connector from step
   191     def RemoveOutput(self):
   192     def RemoveOutput(self):
   192         if self.Output:
   193         if self.Output:
   195             self.RefreshBoundingBox()
   196             self.RefreshBoundingBox()
   196 
   197 
   197     # Add action connector to step
   198     # Add action connector to step
   198     def AddAction(self):
   199     def AddAction(self):
   199         if not self.Action:
   200         if not self.Action:
   200             self.Action = Connector(self, "", None, wx.Point(self.Size[0], self.Size[1] / 2), EAST, onlyone=True)
   201             self.Action = Connector(self, "", None, wx.Point(self.Size[0], self.Size[1] // 2), EAST, onlyone=True)
   201             self.RefreshBoundingBox()
   202             self.RefreshBoundingBox()
   202 
   203 
   203     # Remove action connector from step
   204     # Remove action connector from step
   204     def RemoveAction(self):
   205     def RemoveAction(self):
   205         if self.Action:
   206         if self.Action:
   230         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   231         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   231 
   232 
   232     # Refresh the positions of the step connectors
   233     # Refresh the positions of the step connectors
   233     def RefreshConnectors(self):
   234     def RefreshConnectors(self):
   234         scaling = self.Parent.GetScaling()
   235         scaling = self.Parent.GetScaling()
   235         horizontal_pos = self.Size[0] / 2
   236         horizontal_pos = self.Size[0] // 2
   236         vertical_pos = self.Size[1] / 2
   237         vertical_pos = self.Size[1] // 2
   237         if scaling is not None:
   238         if scaling is not None:
   238             horizontal_pos = round(float(self.Pos.x + horizontal_pos) / float(scaling[0])) * scaling[0] - self.Pos.x
   239             horizontal_pos = round((self.Pos.x + horizontal_pos) / scaling[0]) * scaling[0] - self.Pos.x
   239             vertical_pos = round(float(self.Pos.y + vertical_pos) / float(scaling[1])) * scaling[1] - self.Pos.y
   240             vertical_pos = round((self.Pos.y + vertical_pos) / scaling[1]) * scaling[1] - self.Pos.y
   240         # Update input position if it exists
   241         # Update input position if it exists
   241         if self.Input:
   242         if self.Input:
   242             self.Input.SetPosition(wx.Point(horizontal_pos, 0))
   243             self.Input.SetPosition(wx.Point(horizontal_pos, 0))
   243         # Update output position
   244         # Update output position
   244         if self.Output:
   245         if self.Output:
   361         else:
   362         else:
   362             return text_width + 10, text_height + 10
   363             return text_width + 10, text_height + 10
   363 
   364 
   364     # Updates the step size
   365     # Updates the step size
   365     def UpdateSize(self, width, height):
   366     def UpdateSize(self, width, height):
   366         diffx = self.Size.GetWidth() / 2 - width / 2
   367         diffx = self.Size.GetWidth() // 2 - width // 2
   367         diffy = height - self.Size.GetHeight()
   368         diffy = height - self.Size.GetHeight()
   368         self.Move(diffx, 0)
   369         self.Move(diffx, 0)
   369         Graphic_Element.SetSize(self, width, height)
   370         Graphic_Element.SetSize(self, width, height)
   370         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   371         if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   371             self.RefreshConnected()
   372             self.RefreshConnected()
   461         handle_type, _handle = self.Handle
   462         handle_type, _handle = self.Handle
   462         if handle_type == HANDLE_MOVE:
   463         if handle_type == HANDLE_MOVE:
   463             movex = max(-self.BoundingBox.x, movex)
   464             movex = max(-self.BoundingBox.x, movex)
   464             movey = max(-self.BoundingBox.y, movey)
   465             movey = max(-self.BoundingBox.y, movey)
   465             if scaling is not None:
   466             if scaling is not None:
   466                 movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
   467                 movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
   467                 movey = round(float(self.Pos.y + movey) / float(scaling[1])) * scaling[1] - self.Pos.y
   468                 movey = round((self.Pos.y + movey) / scaling[1]) * scaling[1] - self.Pos.y
   468             if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   469             if self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
   469                 self.Move(movex, movey)
   470                 self.Move(movex, movey)
   470                 self.RefreshConnected()
   471                 self.RefreshConnected()
   471                 return movex, movey
   472                 return movex, movey
   472             elif self.Initial:
   473             elif self.Initial:
   555         # Draw two rectangles for representing the step
   556         # Draw two rectangles for representing the step
   556         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   557         dc.DrawRectangle(self.Pos.x, self.Pos.y, self.Size[0] + 1, self.Size[1] + 1)
   557         if self.Initial:
   558         if self.Initial:
   558             dc.DrawRectangle(self.Pos.x + 2, self.Pos.y + 2, self.Size[0] - 3, self.Size[1] - 3)
   559             dc.DrawRectangle(self.Pos.x + 2, self.Pos.y + 2, self.Size[0] - 3, self.Size[1] - 3)
   559         # Draw step name
   560         # Draw step name
   560         name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) / 2,
   561         name_pos = (self.Pos.x + (self.Size[0] - name_size[0]) // 2,
   561                     self.Pos.y + (self.Size[1] - name_size[1]) / 2)
   562                     self.Pos.y + (self.Size[1] - name_size[1]) // 2)
   562         dc.DrawText(self.Name, name_pos[0], name_pos[1])
   563         dc.DrawText(self.Name, name_pos[0], name_pos[1])
   563         # Draw input and output connectors
   564         # Draw input and output connectors
   564         if self.Input:
   565         if self.Input:
   565             self.Input.Draw(dc)
   566             self.Input.Draw(dc)
   566         if self.Output:
   567         if self.Output:
   589         self.Type = None
   590         self.Type = None
   590         self.Id = id
   591         self.Id = id
   591         self.Priority = 0
   592         self.Priority = 0
   592         self.Size = wx.Size(SFC_TRANSITION_SIZE[0], SFC_TRANSITION_SIZE[1])
   593         self.Size = wx.Size(SFC_TRANSITION_SIZE[0], SFC_TRANSITION_SIZE[1])
   593         # Create an input and output connector
   594         # Create an input and output connector
   594         self.Input = Connector(self,  "", None, wx.Point(self.Size[0] / 2, 0),            NORTH, onlyone=True)
   595         self.Input = Connector(self,  "", None, wx.Point(self.Size[0] // 2, 0),            NORTH, onlyone=True)
   595         self.Output = Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone=True)
   596         self.Output = Connector(self, "", None, wx.Point(self.Size[0] // 2, self.Size[1]), SOUTH, onlyone=True)
   596         self.SetType(type, condition)
   597         self.SetType(type, condition)
   597         self.SetPriority(priority)
   598         self.SetPriority(priority)
   598         self.Highlights = {}
   599         self.Highlights = {}
   599         self.PreviousValue = None
   600         self.PreviousValue = None
   600         self.PreviousSpreading = False
   601         self.PreviousSpreading = False
   711     def HitTest(self, pt, connectors=True):
   712     def HitTest(self, pt, connectors=True):
   712         if self.Type != "connection":
   713         if self.Type != "connection":
   713             # Calculate the bounding box of the condition outside the transition
   714             # Calculate the bounding box of the condition outside the transition
   714             text_width, text_height = self.ConditionSize
   715             text_width, text_height = self.ConditionSize
   715             text_bbx = wx.Rect(self.Pos.x + self.Size[0] + 5,
   716             text_bbx = wx.Rect(self.Pos.x + self.Size[0] + 5,
   716                                self.Pos.y + (self.Size[1] - text_height) / 2,
   717                                self.Pos.y + (self.Size[1] - text_height) // 2,
   717                                text_width,
   718                                text_width,
   718                                text_height)
   719                                text_height)
   719             test_text = text_bbx.InsideXY(pt.x, pt.y)
   720             test_text = text_bbx.InsideXY(pt.x, pt.y)
   720         else:
   721         else:
   721             test_text = False
   722             test_text = False
   733             bbx_width = bbx_width + CONNECTOR_SIZE
   734             bbx_width = bbx_width + CONNECTOR_SIZE
   734         else:
   735         else:
   735             text_width, text_height = self.ConditionSize
   736             text_width, text_height = self.ConditionSize
   736             # Calculate the bounding box size
   737             # Calculate the bounding box size
   737             bbx_width = max(bbx_width, self.Size[0] + 5 + text_width)
   738             bbx_width = max(bbx_width, self.Size[0] + 5 + text_width)
   738             bbx_y = min(bbx_y, self.Pos.y - max(0, (text_height - self.Size[1]) / 2))
   739             bbx_y = min(bbx_y, self.Pos.y - max(0, (text_height - self.Size[1]) // 2))
   739             bbx_height = max(bbx_height, self.Pos.y - bbx_y + (self.Size[1] + text_height) / 2)
   740             bbx_height = max(bbx_height, self.Pos.y - bbx_y + (self.Size[1] + text_height) // 2)
   740         self.BoundingBox = wx.Rect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1)
   741         self.BoundingBox = wx.Rect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1)
   741 
   742 
   742     # Returns the connector connected to input
   743     # Returns the connector connected to input
   743     def GetPreviousConnector(self):
   744     def GetPreviousConnector(self):
   744         wires = self.Input.GetWires()
   745         wires = self.Input.GetWires()
   754         return None
   755         return None
   755 
   756 
   756     # Refresh the positions of the transition connectors
   757     # Refresh the positions of the transition connectors
   757     def RefreshConnectors(self):
   758     def RefreshConnectors(self):
   758         scaling = self.Parent.GetScaling()
   759         scaling = self.Parent.GetScaling()
   759         horizontal_pos = self.Size[0] / 2
   760         horizontal_pos = self.Size[0] // 2
   760         vertical_pos = self.Size[1] / 2
   761         vertical_pos = self.Size[1] // 2
   761         if scaling is not None:
   762         if scaling is not None:
   762             horizontal_pos = round(float(self.Pos.x + horizontal_pos) / float(scaling[0])) * scaling[0] - self.Pos.x
   763             horizontal_pos = round((self.Pos.x + horizontal_pos) / scaling[0]) * scaling[0] - self.Pos.x
   763             vertical_pos = round(float(self.Pos.y + vertical_pos) / float(scaling[1])) * scaling[1] - self.Pos.y
   764             vertical_pos = round((self.Pos.y + vertical_pos) / scaling[1]) * scaling[1] - self.Pos.y
   764         # Update input position
   765         # Update input position
   765         self.Input.SetPosition(wx.Point(horizontal_pos, 0))
   766         self.Input.SetPosition(wx.Point(horizontal_pos, 0))
   766         # Update output position
   767         # Update output position
   767         self.Output.SetPosition(wx.Point(horizontal_pos, self.Size[1]))
   768         self.Output.SetPosition(wx.Point(horizontal_pos, self.Size[1]))
   768         if self.Type == "connection":
   769         if self.Type == "connection":
   820         if self.Type != type:
   821         if self.Type != type:
   821             if self.Type == "connection":
   822             if self.Type == "connection":
   822                 self.Condition.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   823                 self.Condition.UnConnect(delete=self.Parent.GetDrawingMode() == FREEDRAWING_MODE)
   823             self.Type = type
   824             self.Type = type
   824             if type == "connection":
   825             if type == "connection":
   825                 self.Condition = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] / 2), WEST)
   826                 self.Condition = Connector(self, "", "BOOL", wx.Point(0, self.Size[1] // 2), WEST)
   826             else:
   827             else:
   827                 if condition is None:
   828                 if condition is None:
   828                     condition = ""
   829                     condition = ""
   829                 self.Condition = condition
   830                 self.Condition = condition
   830                 self.RefreshConditionSize()
   831                 self.RefreshConditionSize()
   915     # Refreshes the transition state according to move defined and handle selected
   916     # Refreshes the transition state according to move defined and handle selected
   916     def ProcessDragging(self, movex, movey, event, scaling):
   917     def ProcessDragging(self, movex, movey, event, scaling):
   917         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   918         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
   918             movex = max(-self.BoundingBox.x, movex)
   919             movex = max(-self.BoundingBox.x, movex)
   919             if scaling is not None:
   920             if scaling is not None:
   920                 movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
   921                 movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
   921             self.Move(movex, 0)
   922             self.Move(movex, 0)
   922             self.RefreshInputPosition()
   923             self.RefreshInputPosition()
   923             self.RefreshOutputPosition()
   924             self.RefreshOutputPosition()
   924             return movex, 0
   925             return movex, 0
   925         else:
   926         else:
  1007             if self.Priority != 0:
  1008             if self.Priority != 0:
  1008                 priority_size = self.PrioritySize
  1009                 priority_size = self.PrioritySize
  1009 
  1010 
  1010         # Draw plain rectangle for representing the transition
  1011         # Draw plain rectangle for representing the transition
  1011         dc.DrawRectangle(self.Pos.x,
  1012         dc.DrawRectangle(self.Pos.x,
  1012                          self.Pos.y + (self.Size[1] - SFC_TRANSITION_SIZE[1])/2,
  1013                          self.Pos.y + (self.Size[1] - SFC_TRANSITION_SIZE[1]) // 2,
  1013                          self.Size[0] + 1,
  1014                          self.Size[0] + 1,
  1014                          SFC_TRANSITION_SIZE[1] + 1)
  1015                          SFC_TRANSITION_SIZE[1] + 1)
  1015         vertical_line_x = self.Input.GetPosition()[0]
  1016         vertical_line_x = self.Input.GetPosition()[0]
  1016         dc.DrawLine(vertical_line_x, self.Pos.y, vertical_line_x, self.Pos.y + self.Size[1] + 1)
  1017         dc.DrawLine(vertical_line_x, self.Pos.y, vertical_line_x, self.Pos.y + self.Size[1] + 1)
  1017         # Draw transition condition
  1018         # Draw transition condition
  1019             if self.Condition != "":
  1020             if self.Condition != "":
  1020                 condition = self.Condition
  1021                 condition = self.Condition
  1021             else:
  1022             else:
  1022                 condition = "Transition"
  1023                 condition = "Transition"
  1023             condition_pos = (self.Pos.x + self.Size[0] + 5,
  1024             condition_pos = (self.Pos.x + self.Size[0] + 5,
  1024                              self.Pos.y + (self.Size[1] - condition_size[1]) / 2)
  1025                              self.Pos.y + (self.Size[1] - condition_size[1]) // 2)
  1025             dc.DrawText(condition, condition_pos[0], condition_pos[1])
  1026             dc.DrawText(condition, condition_pos[0], condition_pos[1])
  1026         # Draw priority number
  1027         # Draw priority number
  1027         if self.Priority != 0:
  1028         if self.Priority != 0:
  1028             priority_pos = (self.Pos.x, self.Pos.y - priority_size[1] - 2)
  1029             priority_pos = (self.Pos.x, self.Pos.y - priority_size[1] - 2)
  1029             dc.DrawText(str(self.Priority), priority_pos[0], priority_pos[1])
  1030             dc.DrawText(str(self.Priority), priority_pos[0], priority_pos[1])
  1060         self.RealConnectors = None
  1061         self.RealConnectors = None
  1061         number = max(2, number)
  1062         number = max(2, number)
  1062         self.Size = wx.Size((number - 1) * SFC_DEFAULT_SEQUENCE_INTERVAL, self.GetMinSize()[1])
  1063         self.Size = wx.Size((number - 1) * SFC_DEFAULT_SEQUENCE_INTERVAL, self.GetMinSize()[1])
  1063         # Create an input and output connector
  1064         # Create an input and output connector
  1064         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1065         if self.Type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
  1065             self.Inputs = [Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone=True)]
  1066             self.Inputs = [Connector(self, "", None, wx.Point(self.Size[0] // 2, 0), NORTH, onlyone=True)]
  1066             self.Outputs = []
  1067             self.Outputs = []
  1067             for i in xrange(number):
  1068             for i in xrange(number):
  1068                 self.Outputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, self.Size[1]), SOUTH, onlyone=True))
  1069                 self.Outputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, self.Size[1]), SOUTH, onlyone=True))
  1069         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1070         elif self.Type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
  1070             self.Inputs = []
  1071             self.Inputs = []
  1071             for i in xrange(number):
  1072             for i in xrange(number):
  1072                 self.Inputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, 0), NORTH, onlyone=True))
  1073                 self.Inputs.append(Connector(self, "", None, wx.Point(i * SFC_DEFAULT_SEQUENCE_INTERVAL, 0), NORTH, onlyone=True))
  1073             self.Outputs = [Connector(self, "", None, wx.Point(self.Size[0] / 2, self.Size[1]), SOUTH, onlyone=True)]
  1074             self.Outputs = [Connector(self, "", None, wx.Point(self.Size[0] // 2, self.Size[1]), SOUTH, onlyone=True)]
  1074         self.Value = None
  1075         self.Value = None
  1075         self.PreviousValue = None
  1076         self.PreviousValue = None
  1076 
  1077 
  1077     def Flush(self):
  1078     def Flush(self):
  1078         for input in self.Inputs:
  1079         for input in self.Inputs:
  1283         for i, input in enumerate(self.Inputs):
  1284         for i, input in enumerate(self.Inputs):
  1284             position = input.GetRelPosition()
  1285             position = input.GetRelPosition()
  1285             if self.RealConnectors:
  1286             if self.RealConnectors:
  1286                 input.SetPosition(wx.Point(int(round(self.RealConnectors["Inputs"][i] * width)), 0))
  1287                 input.SetPosition(wx.Point(int(round(self.RealConnectors["Inputs"][i] * width)), 0))
  1287             else:
  1288             else:
  1288                 input.SetPosition(wx.Point(int(round(float(position.x)*float(width)/float(self.Size[0]))), 0))
  1289                 input.SetPosition(wx.Point(int(round(position.x*width / self.Size[0])), 0))
  1289             input.MoveConnected()
  1290             input.MoveConnected()
  1290         for i, output in enumerate(self.Outputs):
  1291         for i, output in enumerate(self.Outputs):
  1291             position = output.GetRelPosition()
  1292             position = output.GetRelPosition()
  1292             if self.RealConnectors:
  1293             if self.RealConnectors:
  1293                 output.SetPosition(wx.Point(int(round(self.RealConnectors["Outputs"][i] * width)), height))
  1294                 output.SetPosition(wx.Point(int(round(self.RealConnectors["Outputs"][i] * width)), height))
  1294             else:
  1295             else:
  1295                 output.SetPosition(wx.Point(int(round(float(position.x)*float(width)/float(self.Size[0]))), height))
  1296                 output.SetPosition(wx.Point(int(round(position.x*width / self.Size[0])), height))
  1296             output.MoveConnected()
  1297             output.MoveConnected()
  1297         self.Size = wx.Size(width, height)
  1298         self.Size = wx.Size(width, height)
  1298         self.RefreshBoundingBox()
  1299         self.RefreshBoundingBox()
  1299 
  1300 
  1300     # Returns the divergence minimum size
  1301     # Returns the divergence minimum size
  1366     # Method called when a LeftDown event have been generated
  1367     # Method called when a LeftDown event have been generated
  1367     def OnLeftDown(self, event, dc, scaling):
  1368     def OnLeftDown(self, event, dc, scaling):
  1368         self.RealConnectors = {"Inputs": [], "Outputs": []}
  1369         self.RealConnectors = {"Inputs": [], "Outputs": []}
  1369         for input in self.Inputs:
  1370         for input in self.Inputs:
  1370             position = input.GetRelPosition()
  1371             position = input.GetRelPosition()
  1371             self.RealConnectors["Inputs"].append(float(position.x)/float(self.Size[0]))
  1372             self.RealConnectors["Inputs"].append(position.x / self.Size[0])
  1372         for output in self.Outputs:
  1373         for output in self.Outputs:
  1373             position = output.GetRelPosition()
  1374             position = output.GetRelPosition()
  1374             self.RealConnectors["Outputs"].append(float(position.x)/float(self.Size[0]))
  1375             self.RealConnectors["Outputs"].append(position.x / self.Size[0])
  1375         Graphic_Element.OnLeftDown(self, event, dc, scaling)
  1376         Graphic_Element.OnLeftDown(self, event, dc, scaling)
  1376 
  1377 
  1377     # Method called when a LeftUp event have been generated
  1378     # Method called when a LeftUp event have been generated
  1378     def OnLeftUp(self, event, dc, scaling):
  1379     def OnLeftUp(self, event, dc, scaling):
  1379         Graphic_Element.OnLeftUp(self, event, dc, scaling)
  1380         Graphic_Element.OnLeftUp(self, event, dc, scaling)
  1423         handle_type, handle = self.Handle
  1424         handle_type, handle = self.Handle
  1424         # A connector has been handled
  1425         # A connector has been handled
  1425         if handle_type == HANDLE_CONNECTOR:
  1426         if handle_type == HANDLE_CONNECTOR:
  1426             movex = max(-self.BoundingBox.x, movex)
  1427             movex = max(-self.BoundingBox.x, movex)
  1427             if scaling is not None:
  1428             if scaling is not None:
  1428                 movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
  1429                 movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
  1429             self.MoveConnector(handle, movex)
  1430             self.MoveConnector(handle, movex)
  1430             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1431             if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1431                 self.RefreshConnectedPosition(handle)
  1432                 self.RefreshConnectedPosition(handle)
  1432             return movex, 0
  1433             return movex, 0
  1433         elif self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1434         elif self.Parent.GetDrawingMode() == FREEDRAWING_MODE:
  1517         self.SetTarget(target)
  1518         self.SetTarget(target)
  1518         self.Id = id
  1519         self.Id = id
  1519         self.Size = wx.Size(SFC_JUMP_SIZE[0], SFC_JUMP_SIZE[1])
  1520         self.Size = wx.Size(SFC_JUMP_SIZE[0], SFC_JUMP_SIZE[1])
  1520         self.Highlights = []
  1521         self.Highlights = []
  1521         # Create an input and output connector
  1522         # Create an input and output connector
  1522         self.Input = Connector(self, "", None, wx.Point(self.Size[0] / 2, 0), NORTH, onlyone=True)
  1523         self.Input = Connector(self, "", None, wx.Point(self.Size[0] // 2, 0), NORTH, onlyone=True)
  1523         self.Value = None
  1524         self.Value = None
  1524         self.PreviousValue = None
  1525         self.PreviousValue = None
  1525 
  1526 
  1526     def Flush(self):
  1527     def Flush(self):
  1527         if self.Input is not None:
  1528         if self.Input is not None:
  1584     # Returns if the point given is in the bounding box
  1585     # Returns if the point given is in the bounding box
  1585     def HitTest(self, pt, connectors=True):
  1586     def HitTest(self, pt, connectors=True):
  1586         # Calculate the bounding box of the condition outside the transition
  1587         # Calculate the bounding box of the condition outside the transition
  1587         text_width, text_height = self.TargetSize
  1588         text_width, text_height = self.TargetSize
  1588         text_bbx = wx.Rect(self.Pos.x + self.Size[0] + 2,
  1589         text_bbx = wx.Rect(self.Pos.x + self.Size[0] + 2,
  1589                            self.Pos.y + (self.Size[1] - text_height) / 2,
  1590                            self.Pos.y + (self.Size[1] - text_height) // 2,
  1590                            text_width,
  1591                            text_width,
  1591                            text_height)
  1592                            text_height)
  1592         return text_bbx.InsideXY(pt.x, pt.y) or Graphic_Element.HitTest(self, pt, connectors)
  1593         return text_bbx.InsideXY(pt.x, pt.y) or Graphic_Element.HitTest(self, pt, connectors)
  1593 
  1594 
  1594     # Refresh the jump bounding box
  1595     # Refresh the jump bounding box
  1607         return None
  1608         return None
  1608 
  1609 
  1609     # Refresh the element connectors position
  1610     # Refresh the element connectors position
  1610     def RefreshConnectors(self):
  1611     def RefreshConnectors(self):
  1611         scaling = self.Parent.GetScaling()
  1612         scaling = self.Parent.GetScaling()
  1612         horizontal_pos = self.Size[0] / 2
  1613         horizontal_pos = self.Size[0] // 2
  1613         if scaling is not None:
  1614         if scaling is not None:
  1614             horizontal_pos = round(float(self.Pos.x + horizontal_pos) / float(scaling[0])) * scaling[0] - self.Pos.x
  1615             horizontal_pos = round((self.Pos.x + horizontal_pos) / scaling[0]) * scaling[0] - self.Pos.x
  1615         self.Input.SetPosition(wx.Point(horizontal_pos, 0))
  1616         self.Input.SetPosition(wx.Point(horizontal_pos, 0))
  1616         self.RefreshConnected()
  1617         self.RefreshConnected()
  1617 
  1618 
  1618     # Refresh the position of wires connected to jump
  1619     # Refresh the position of wires connected to jump
  1619     def RefreshConnected(self, exclude=None):
  1620     def RefreshConnected(self, exclude=None):
  1683     # Refreshes the jump state according to move defined and handle selected
  1684     # Refreshes the jump state according to move defined and handle selected
  1684     def ProcessDragging(self, movex, movey, event, scaling):
  1685     def ProcessDragging(self, movex, movey, event, scaling):
  1685         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1686         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1686             movex = max(-self.BoundingBox.x, movex)
  1687             movex = max(-self.BoundingBox.x, movex)
  1687             if scaling is not None:
  1688             if scaling is not None:
  1688                 movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
  1689                 movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
  1689             self.Move(movex, 0)
  1690             self.Move(movex, 0)
  1690             self.RefreshInputPosition()
  1691             self.RefreshInputPosition()
  1691             return movex, 0
  1692             return movex, 0
  1692         else:
  1693         else:
  1693             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, width_fac=2)
  1694             return Graphic_Element.ProcessDragging(self, movex, movey, event, scaling, width_fac=2)
  1758             target_size = dc.GetTextExtent(self.Target)
  1759             target_size = dc.GetTextExtent(self.Target)
  1759         else:
  1760         else:
  1760             target_size = self.TargetSize
  1761             target_size = self.TargetSize
  1761 
  1762 
  1762         # Draw plain rectangle for representing the divergence
  1763         # Draw plain rectangle for representing the divergence
  1763         dc.DrawLine(self.Pos.x + self.Size[0] / 2, self.Pos.y, self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1])
  1764         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])
  1764         points = [wx.Point(self.Pos.x, self.Pos.y),
  1765         points = [wx.Point(self.Pos.x, self.Pos.y),
  1765                   wx.Point(self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1] / 3),
  1766                   wx.Point(self.Pos.x + self.Size[0] // 2, self.Pos.y + self.Size[1] // 3),
  1766                   wx.Point(self.Pos.x + self.Size[0], self.Pos.y),
  1767                   wx.Point(self.Pos.x + self.Size[0], self.Pos.y),
  1767                   wx.Point(self.Pos.x + self.Size[0] / 2, self.Pos.y + self.Size[1])]
  1768                   wx.Point(self.Pos.x + self.Size[0] // 2, self.Pos.y + self.Size[1])]
  1768         dc.DrawPolygon(points)
  1769         dc.DrawPolygon(points)
  1769         target_pos = (self.Pos.x + self.Size[0] + 2,
  1770         target_pos = (self.Pos.x + self.Size[0] + 2,
  1770                       self.Pos.y + (self.Size[1] - target_size[1]) / 2)
  1771                       self.Pos.y + (self.Size[1] - target_size[1]) // 2)
  1771         dc.DrawText(self.Target, target_pos[0], target_pos[1])
  1772         dc.DrawText(self.Target, target_pos[0], target_pos[1])
  1772         # Draw input connector
  1773         # Draw input connector
  1773         if self.Input:
  1774         if self.Input:
  1774             self.Input.Draw(dc)
  1775             self.Input.Draw(dc)
  1775 
  1776 
  1793         self.Id = id
  1794         self.Id = id
  1794         self.Size = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
  1795         self.Size = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
  1795         self.MinSize = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
  1796         self.MinSize = wx.Size(SFC_ACTION_MIN_SIZE[0], SFC_ACTION_MIN_SIZE[1])
  1796         self.Highlights = {}
  1797         self.Highlights = {}
  1797         # Create an input and output connector
  1798         # Create an input and output connector
  1798         self.Input = Connector(self, "", None, wx.Point(0, SFC_ACTION_MIN_SIZE[1] / 2), WEST, onlyone=True)
  1799         self.Input = Connector(self, "", None, wx.Point(0, SFC_ACTION_MIN_SIZE[1] // 2), WEST, onlyone=True)
  1799         self.SetActions(actions)
  1800         self.SetActions(actions)
  1800         self.Value = None
  1801         self.Value = None
  1801         self.PreviousValue = None
  1802         self.PreviousValue = None
  1802 
  1803 
  1803     def Flush(self):
  1804     def Flush(self):
  1841     def GetLineNumber(self):
  1842     def GetLineNumber(self):
  1842         return len(self.Actions)
  1843         return len(self.Actions)
  1843 
  1844 
  1844     def GetLineSize(self):
  1845     def GetLineSize(self):
  1845         if len(self.Actions) > 0:
  1846         if len(self.Actions) > 0:
  1846             return self.Size[1] / len(self.Actions)
  1847             return self.Size[1] // len(self.Actions)
  1847         else:
  1848         else:
  1848             return SFC_ACTION_MIN_SIZE[1]
  1849             return SFC_ACTION_MIN_SIZE[1]
  1849 
  1850 
  1850     # Forbids to resize the action block
  1851     # Forbids to resize the action block
  1851     def Resize(self, x, y, width, height):
  1852     def Resize(self, x, y, width, height):
  1887         return None
  1888         return None
  1888 
  1889 
  1889     # Refresh the element connectors position
  1890     # Refresh the element connectors position
  1890     def RefreshConnectors(self):
  1891     def RefreshConnectors(self):
  1891         scaling = self.Parent.GetScaling()
  1892         scaling = self.Parent.GetScaling()
  1892         vertical_pos = SFC_ACTION_MIN_SIZE[1] / 2
  1893         vertical_pos = SFC_ACTION_MIN_SIZE[1] // 2
  1893         if scaling is not None:
  1894         if scaling is not None:
  1894             vertical_pos = round(float(self.Pos.y + vertical_pos) / float(scaling[1])) * scaling[1] - self.Pos.y
  1895             vertical_pos = round((self.Pos.y + vertical_pos) / scaling[1]) * scaling[1] - self.Pos.y
  1895         self.Input.SetPosition(wx.Point(0, vertical_pos))
  1896         self.Input.SetPosition(wx.Point(0, vertical_pos))
  1896         self.RefreshConnected()
  1897         self.RefreshConnected()
  1897 
  1898 
  1898     # Changes the action block actions
  1899     # Changes the action block actions
  1899     def SetActions(self, actions=None):
  1900     def SetActions(self, actions=None):
  1960         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1961         if self.Parent.GetDrawingMode() != FREEDRAWING_MODE:
  1961             handle_type, _handle = self.Handle
  1962             handle_type, _handle = self.Handle
  1962             if handle_type == HANDLE_MOVE:
  1963             if handle_type == HANDLE_MOVE:
  1963                 movex = max(-self.BoundingBox.x, movex)
  1964                 movex = max(-self.BoundingBox.x, movex)
  1964                 if scaling is not None:
  1965                 if scaling is not None:
  1965                     movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
  1966                     movex = round((self.Pos.x + movex) / scaling[0]) * scaling[0] - self.Pos.x
  1966                 wires = self.Input.GetWires()
  1967                 wires = self.Input.GetWires()
  1967                 if len(wires) == 1:
  1968                 if len(wires) == 1:
  1968                     input_pos = wires[0][0].GetOtherConnected(self.Input).GetPosition(False)
  1969                     input_pos = wires[0][0].GetOtherConnected(self.Input).GetPosition(False)
  1969                     if self.Pos.x - input_pos.x + movex >= SFC_WIRE_MIN_SIZE:
  1970                     if self.Pos.x - input_pos.x + movex >= SFC_WIRE_MIN_SIZE:
  1970                         self.Move(movex, 0)
  1971                         self.Move(movex, 0)
  2031             if i != 0:
  2032             if i != 0:
  2032                 dc.DrawLine(self.Pos.x, self.Pos.y + i * line_size,
  2033                 dc.DrawLine(self.Pos.x, self.Pos.y + i * line_size,
  2033                             self.Pos.x + self.Size[0], self.Pos.y + i * line_size)
  2034                             self.Pos.x + self.Size[0], self.Pos.y + i * line_size)
  2034             qualifier_size = dc.GetTextExtent(action.qualifier)
  2035             qualifier_size = dc.GetTextExtent(action.qualifier)
  2035             if action.duration != "":
  2036             if action.duration != "":
  2036                 qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) / 2,
  2037                 qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) // 2,
  2037                                  self.Pos.y + i * line_size + line_size / 2 - qualifier_size[1])
  2038                                  self.Pos.y + i * line_size + line_size // 2 - qualifier_size[1])
  2038                 duration_size = dc.GetTextExtent(action.duration)
  2039                 duration_size = dc.GetTextExtent(action.duration)
  2039                 duration_pos = (self.Pos.x + (colsize[0] - duration_size[0]) / 2,
  2040                 duration_pos = (self.Pos.x + (colsize[0] - duration_size[0]) // 2,
  2040                                 self.Pos.y + i * line_size + line_size / 2)
  2041                                 self.Pos.y + i * line_size + line_size // 2)
  2041                 dc.DrawText(action.duration, duration_pos[0], duration_pos[1])
  2042                 dc.DrawText(action.duration, duration_pos[0], duration_pos[1])
  2042             else:
  2043             else:
  2043                 qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) / 2,
  2044                 qualifier_pos = (self.Pos.x + (colsize[0] - qualifier_size[0]) // 2,
  2044                                  self.Pos.y + i * line_size + (line_size - qualifier_size[1]) / 2)
  2045                                  self.Pos.y + i * line_size + (line_size - qualifier_size[1]) // 2)
  2045             dc.DrawText(action.qualifier, qualifier_pos[0], qualifier_pos[1])
  2046             dc.DrawText(action.qualifier, qualifier_pos[0], qualifier_pos[1])
  2046             content_size = dc.GetTextExtent(action.value)
  2047             content_size = dc.GetTextExtent(action.value)
  2047             content_pos = (self.Pos.x + colsize[0] + (colsize[1] - content_size[0]) / 2,
  2048             content_pos = (self.Pos.x + colsize[0] + (colsize[1] - content_size[0]) // 2,
  2048                            self.Pos.y + i * line_size + (line_size - content_size[1]) / 2)
  2049                            self.Pos.y + i * line_size + (line_size - content_size[1]) // 2)
  2049             dc.DrawText(action.value, content_pos[0], content_pos[1])
  2050             dc.DrawText(action.value, content_pos[0], content_pos[1])
  2050             if action.indicator != "":
  2051             if action.indicator != "":
  2051                 indicator_size = dc.GetTextExtent(action.indicator)
  2052                 indicator_size = dc.GetTextExtent(action.indicator)
  2052                 indicator_pos = (self.Pos.x + colsize[0] + colsize[1] + (colsize[2] - indicator_size[0]) / 2,
  2053                 indicator_pos = (self.Pos.x + colsize[0] + colsize[1] + (colsize[2] - indicator_size[0]) // 2,
  2053                                  self.Pos.y + i * line_size + (line_size - indicator_size[1]) / 2)
  2054                                  self.Pos.y + i * line_size + (line_size - indicator_size[1]) // 2)
  2054                 dc.DrawText(action.indicator, indicator_pos[0], indicator_pos[1])
  2055                 dc.DrawText(action.indicator, indicator_pos[0], indicator_pos[1])
  2055 
  2056 
  2056             if not getattr(dc, "printing", False):
  2057             if not getattr(dc, "printing", False):
  2057                 action_highlights = self.Highlights.get(i, {})
  2058                 action_highlights = self.Highlights.get(i, {})
  2058                 for name, attribute_highlights in action_highlights.iteritems():
  2059                 for name, attribute_highlights in action_highlights.iteritems():