Added support for adding graphic element when dropping wire in midair
authorLaurent Bessard
Fri, 14 Jun 2013 10:54:21 +0200
changeset 1259 8350222a81c3
parent 1258 441f31474b50
child 1260 11903e79ce66
Added support for adding graphic element when dropping wire in midair
dialogs/FBDVariableDialog.py
dialogs/LDElementDialog.py
dialogs/LDPowerRailDialog.py
dialogs/SFCDivergenceDialog.py
editors/Viewer.py
--- a/dialogs/FBDVariableDialog.py	Fri Jun 14 10:52:08 2013 +0200
+++ b/dialogs/FBDVariableDialog.py	Fri Jun 14 10:54:21 2013 +0200
@@ -51,12 +51,13 @@
 
 class FBDVariableDialog(BlockPreviewDialog):
 
-    def __init__(self, parent, controller, tagname):
+    def __init__(self, parent, controller, tagname, exclude_input=False):
         """
         Constructor
         @param parent: Parent wx.Window of dialog for modal
         @param controller: Reference to project controller
         @param tagname: Tagname of project POU edited
+        @param exclude_input: Exclude input from variable class selection
         """
         BlockPreviewDialog.__init__(self, parent, controller, tagname,
               size=wx.Size(400, 380), title=_('Variable Properties'))
@@ -112,9 +113,10 @@
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
         
         # Set options that can be selected in class combo box
-        for choice in VARIABLE_CLASSES_DICT.itervalues():
-            self.Class.Append(choice)
-        self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[INPUT])
+        for var_class, choice in VARIABLE_CLASSES_DICT.iteritems():
+            if not exclude_input or var_class != INPUT:
+                self.Class.Append(choice)
+        self.Class.SetSelection(0)
         
         # Extract list of variables defined in POU
         self.RefreshVariableList()
--- a/dialogs/LDElementDialog.py	Fri Jun 14 10:52:08 2013 +0200
+++ b/dialogs/LDElementDialog.py	Fri Jun 14 10:54:21 2013 +0200
@@ -50,7 +50,7 @@
         @param type: Type of LD element ('contact or 'coil')
         """
         BlockPreviewDialog.__init__(self, parent, controller, tagname, 
-              size=wx.Size(350, 260 if type == "contact" else 310),
+              size=wx.Size(350, 280 if type == "contact" else 330),
               title=(_("Edit Contact Values")
                      if type == "contact"
                      else _("Edit Coil Values")))
@@ -91,7 +91,7 @@
               flag=wx.GROW|wx.TOP)
         
         # Create a combo box for defining LD element variable
-        self.ElementVariable = wx.ComboBox(self, style=wx.CB_READONLY)
+        self.ElementVariable = wx.ComboBox(self, style=wx.CB_READONLY|wx.CB_SORT)
         self.Bind(wx.EVT_COMBOBOX, self.OnVariableChanged, 
                   self.ElementVariable)
         self.LeftGridSizer.AddWindow(self.ElementVariable, border=5,
--- a/dialogs/LDPowerRailDialog.py	Fri Jun 14 10:52:08 2013 +0200
+++ b/dialogs/LDPowerRailDialog.py	Fri Jun 14 10:54:21 2013 +0200
@@ -95,7 +95,7 @@
         @return: Tuple containing minimal size (width, height) or None if no
         element defined
         """
-        return (2, LD_LINE_SIZE * self.PinNumber.GetValue())
+        return self.Element.GetMinSize(True)
     
     def GetPowerRailType(self):
         """
--- a/dialogs/SFCDivergenceDialog.py	Fri Jun 14 10:52:08 2013 +0200
+++ b/dialogs/SFCDivergenceDialog.py	Fri Jun 14 10:54:21 2013 +0200
@@ -101,7 +101,7 @@
         @return: Tuple containing minimal size (width, height) or None if no
         element defined
         """
-        return self.Element.GetSize()
+        return self.Element.GetMinSize(True)
     
     def GetDivergenceType(self):
         """
--- a/editors/Viewer.py	Fri Jun 14 10:52:08 2013 +0200
+++ b/editors/Viewer.py	Fri Jun 14 10:54:21 2013 +0200
@@ -1650,6 +1650,12 @@
             wx.CallAfter(func, self.rubberBand.GetCurrentExtent(), *args)
         return AddMenuCallBack
 
+    def GetAddToWireMenuCallBack(self, func, *args):
+        args += (self.SelectedElement,)
+        def AddToWireMenuCallBack(event):
+            func(wx.Rect(0, 0, 0, 0), *args)
+        return AddToWireMenuCallBack
+
     def GetClipboardCallBack(self, func):
         def ClipboardCallback(event):
             wx.CallAfter(func)
@@ -1738,10 +1744,15 @@
                 elif not self.Debug and connector is not None and not event.ControlDown():
                     self.DrawingWire = True
                     scaled_pos = GetScaledEventPosition(event, dc, self.Scaling)
-                    if (connector.GetDirection() == EAST):
-                        wire = Wire(self, [wx.Point(pos.x, pos.y), EAST], [wx.Point(scaled_pos.x, scaled_pos.y), WEST])
-                    else:
-                        wire = Wire(self, [wx.Point(pos.x, pos.y), WEST], [wx.Point(scaled_pos.x, scaled_pos.y), EAST])
+                    directions = {
+                        EAST: [EAST, WEST],
+                        WEST: [WEST, EAST],
+                        NORTH: [NORTH, SOUTH],
+                        SOUTH: [SOUTH, NORTH]}[connector.GetDirection()]
+                    wire = Wire(self, *map(list, zip(
+                                           [wx.Point(pos.x, pos.y), 
+                                            wx.Point(scaled_pos.x, scaled_pos.y)],
+                                           directions)))
                     wire.oldPos = scaled_pos
                     wire.Handle = (HANDLE_POINT, 0)
                     wire.ProcessDragging(0, 0, event, None)
@@ -1755,6 +1766,7 @@
                     self.HighlightedElement = wire
                     self.RefreshVisibleElements()
                     self.SelectedElement.SetHighlighted(True)
+                    self.SelectedElement.StartConnected.HighlightParentBlock(True)
                 else:
                     if self.SelectedElement is not None and self.SelectedElement != element:
                         self.SelectedElement.SetSelected(False)
@@ -1847,14 +1859,70 @@
                     self.SelectedElement.HighlightPoint(pos)
                     self.RefreshBuffer()
                 elif connector is None or self.SelectedElement.GetDragging():
-                    self.DrawingWire = False
-                    rect = self.SelectedElement.GetRedrawRect()
-                    wire = self.SelectedElement
-                    self.SelectedElement = self.SelectedElement.StartConnected.GetParentBlock()
-                    self.SelectedElement.SetSelected(True)
-                    rect.Union(self.SelectedElement.GetRedrawRect())
-                    wire.Delete()
-                    self.RefreshRect(self.GetScrolledRect(rect), False)
+                    start_connector = self.SelectedElement.GetStartConnected()
+                    start_direction = start_connector.GetDirection()
+                    
+                    items = []
+                    
+                    if self.CurrentLanguage == "SFC" and start_direction == SOUTH:
+                        items.extend([
+                            (_(u'Initial Step'), self.GetAddToWireMenuCallBack(self.AddNewStep, True)),
+                            (_(u'Step'), self.GetAddToWireMenuCallBack(self.AddNewStep, False)),
+                            (_(u'Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, False)),
+                            (_(u'Divergence'), self.GetAddToWireMenuCallBack(self.AddNewDivergence)),
+                            (_(u'Jump'), self.GetAddToWireMenuCallBack(self.AddNewJump)),
+                        ])
+                    
+                    elif start_direction == EAST:
+                        
+                        if isinstance(start_connector.GetParentBlock(), SFC_Step):
+                            items.append(
+                                (_(u'Action Block'), self.GetAddToWireMenuCallBack(self.AddNewActionBlock))
+                            )
+                        else:
+                            items.extend([
+                                (_(u'Block'), self.GetAddToWireMenuCallBack(self.AddNewBlock)),
+                                (_(u'Variable'), self.GetAddToWireMenuCallBack(self.AddNewVariable, True)),
+                                (_(u'Connection'), self.GetAddToWireMenuCallBack(self.AddNewConnection)),
+                            ])
+                            
+                            if self.CurrentLanguage != "FBD":
+                                items.append(
+                                    (_(u'Contact'), self.GetAddToWireMenuCallBack(self.AddNewContact))
+                                )
+                            if self.CurrentLanguage == "LD":
+                                items.extend([
+                                    (_(u'Coil'), self.GetAddToWireMenuCallBack(self.AddNewCoil)),
+                                    (_(u'Power Rail'), self.GetAddToWireMenuCallBack(self.AddNewPowerRail)),
+                                ])
+                            if self.CurrentLanguage == "SFC":
+                                items.append(
+                                    (_(u'Transition'), self.GetAddToWireMenuCallBack(self.AddNewTransition, True))
+                                )
+                                
+                    if len(items) > 0:
+                        if self.Editor.HasCapture():
+                            self.Editor.ReleaseMouse()
+                        
+                        # Popup contextual menu
+                        menu = wx.Menu()
+                        self.AddMenuItems(menu, 
+                            [(wx.NewId(), wx.ITEM_NORMAL, text, '', callback)
+                             for text, callback in items])
+                        self.PopupMenu(menu)
+                    
+                    self.SelectedElement.StartConnected.HighlightParentBlock(False)
+                    if self.DrawingWire:
+                        self.DrawingWire = False
+                        rect = self.SelectedElement.GetRedrawRect()
+                        wire = self.SelectedElement
+                        self.SelectedElement = self.SelectedElement.StartConnected.GetParentBlock()
+                        self.SelectedElement.SetSelected(True)
+                        rect.Union(self.SelectedElement.GetRedrawRect())
+                        wire.Delete()
+                        self.RefreshRect(self.GetScrolledRect(rect), False)
+                    else:
+                        self.SelectedElement.SetSelected(True)
             else:
                 if self.Debug:
                     Graphic_Element.OnLeftUp(self.SelectedElement, event, dc, self.Scaling)
@@ -2196,7 +2264,36 @@
             height = round(float(height) / float(self.Scaling[1]) + 0.4) * self.Scaling[1]
         return width, height
     
-    def AddNewBlock(self, bbox):
+    def AddNewElement(self, element, bbox, wire=None, connector=None):
+        min_width, min_height = (element.GetMinSize(True)
+                                 if isinstance(element, (LD_PowerRail,
+                                                         SFC_Divergence))
+                                 else element.GetMinSize())
+        element.SetSize(*self.GetScaledSize(
+            max(bbox.width, min_width), max(bbox.height, min_height)))
+        if wire is not None:
+            if connector is None:
+                connector = element.GetConnectors()["inputs"][0]
+            point = wire.GetPoint(-1)
+            rel_pos = connector.GetRelPosition()
+            direction = connector.GetDirection()
+            element.SetPosition(
+                point[0] - rel_pos[0] - direction[0] * CONNECTOR_SIZE,
+                point[1] - rel_pos[1] - direction[1] * CONNECTOR_SIZE,
+            )
+            connector.Connect((wire, -1))
+            wire.Refresh()
+            self.DrawingWire = False
+        else:
+            element.SetPosition(bbox.x, bbox.y)
+        self.AddBlock(element)
+        element.RefreshModel()
+        self.RefreshBuffer()
+        self.RefreshScrollBars()
+        self.RefreshVisibleElements()
+        element.Refresh()
+    
+    def AddNewBlock(self, bbox, wire=None):
         dialog = FBDBlockDialog(self.ParentWindow, self.Controler, self.TagName)
         dialog.SetPreviewFont(self.GetFont())
         dialog.SetMinElementSize((bbox.width, bbox.height))
@@ -2208,21 +2305,17 @@
                     values["extension"], values["inputs"], 
                     executionControl = values["executionControl"],
                     executionOrder = values["executionOrder"])
-            block.SetPosition(bbox.x, bbox.y)
-            block.SetSize(*self.GetScaledSize(values["width"], values["height"]))
-            self.AddBlock(block)
-            self.Controler.AddEditedElementBlock(self.TagName, id, values["type"], values.get("name", None))
-            self.RefreshBlockModel(block)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            self.RefreshVariablePanel()
-            self.ParentWindow.RefreshPouInstanceVariablesPanel()
-            block.Refresh()
+            connector = None
+            for input_connector in block.GetConnectors()["inputs"]:
+                if input_connector.IsCompatible(
+                        wire.GetStartConnectedType()):
+                    connector = input_connector
+                    break
+            self.AddNewElement(block, bbox, wire, connector)
         dialog.Destroy()
     
-    def AddNewVariable(self, bbox):
-        dialog = FBDVariableDialog(self.ParentWindow, self.Controler, self.TagName)
+    def AddNewVariable(self, bbox, exclude_input=False, wire=None):
+        dialog = FBDVariableDialog(self.ParentWindow, self.Controler, self.TagName, exclude_input)
         dialog.SetPreviewFont(self.GetFont())
         dialog.SetMinElementSize((bbox.width, bbox.height))
         if dialog.ShowModal() == wx.ID_OK:
@@ -2230,36 +2323,30 @@
             values = dialog.GetValues()
             variable = FBD_Variable(self, values["class"], values["expression"], values["var_type"], id)
             variable.SetExecutionOrder(values["executionOrder"])
-            variable.SetPosition(bbox.x, bbox.y)
-            variable.SetSize(*self.GetScaledSize(values["width"], values["height"]))
-            self.AddBlock(variable)
             self.Controler.AddEditedElementVariable(self.TagName, id, values["class"])
-            self.RefreshVariableModel(variable)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            variable.Refresh()
+            self.AddNewElement(variable, bbox, wire)
         dialog.Destroy()
 
-    def AddNewConnection(self, bbox):
-        dialog = ConnectionDialog(self.ParentWindow, self.Controler, self.TagName)
-        dialog.SetPreviewFont(self.GetFont())
-        dialog.SetMinElementSize((bbox.width, bbox.height))
-        if dialog.ShowModal() == wx.ID_OK:
+    def AddNewConnection(self, bbox, wire=None):
+        if wire is not None:
+            values = {
+                "type": CONNECTOR,
+                "name": self.Controler.GenerateNewName(
+                    self.TagName, None, "Connection%d", 0)}
+        else:
+            dialog = ConnectionDialog(self.ParentWindow, self.Controler, self.TagName)
+            dialog.SetPreviewFont(self.GetFont())
+            dialog.SetMinElementSize((bbox.width, bbox.height))
+            values = (dialog.GetValues()
+                      if dialog.ShowModal() == wx.ID_OK
+                      else None)
+            dialog.Destroy()
+        if values is not None:
             id = self.GetNewId()
-            values = dialog.GetValues()
             connection = FBD_Connector(self, values["type"], values["name"], id)
-            connection.SetPosition(bbox.x, bbox.y)
-            connection.SetSize(*self.GetScaledSize(values["width"], values["height"]))
-            self.AddBlock(connection)
             self.Controler.AddEditedElementConnection(self.TagName, id, values["type"])
-            self.RefreshConnectionModel(connection)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            connection.Refresh()
-        dialog.Destroy()
-
+            self.AddNewElement(connection, bbox, wire)
+    
     def AddNewComment(self, bbox):
         dialog = wx.TextEntryDialog(self.ParentWindow, 
                                     _("Edit comment"), 
@@ -2282,7 +2369,7 @@
             comment.Refresh()
         dialog.Destroy()
 
-    def AddNewContact(self, bbox):
+    def AddNewContact(self, bbox, wire=None):
         dialog = LDElementDialog(self.ParentWindow, self.Controler, self.TagName, "contact")
         dialog.SetPreviewFont(self.GetFont())
         dialog.SetMinElementSize((bbox.width, bbox.height))
@@ -2290,18 +2377,11 @@
             id = self.GetNewId()
             values = dialog.GetValues()
             contact = LD_Contact(self, values["modifier"], values["variable"], id)
-            contact.SetPosition(bbox.x, bbox.y)
-            contact.SetSize(*self.GetScaledSize(values["width"], values["height"]))
-            self.AddBlock(contact)
             self.Controler.AddEditedElementContact(self.TagName, id)
-            self.RefreshContactModel(contact)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            contact.Refresh()
+            self.AddNewElement(contact, bbox, wire)
         dialog.Destroy()
 
-    def AddNewCoil(self, bbox):
+    def AddNewCoil(self, bbox, wire=None):
         dialog = LDElementDialog(self.ParentWindow, self.Controler, self.TagName, "coil")
         dialog.SetPreviewFont(self.GetFont())
         dialog.SetMinElementSize((bbox.width, bbox.height))
@@ -2309,89 +2389,80 @@
             id = self.GetNewId()
             values = dialog.GetValues()
             coil = LD_Coil(self, values["modifier"], values["variable"], id)
-            coil.SetPosition(bbox.x, bbox.y)
-            coil.SetSize(*self.GetScaledSize(values["width"], values["height"]))
-            self.AddBlock(coil)
             self.Controler.AddEditedElementCoil(self.TagName, id)
-            self.RefreshCoilModel(coil)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            coil.Refresh()
+            self.AddNewElement(coil, bbox, wire)
         dialog.Destroy()
 
-    def AddNewPowerRail(self, bbox):
-        dialog = LDPowerRailDialog(self.ParentWindow, self.Controler, self.TagName)
-        dialog.SetPreviewFont(self.GetFont())
-        dialog.SetMinElementSize((bbox.width, bbox.height))
-        if dialog.ShowModal() == wx.ID_OK:
+    def AddNewPowerRail(self, bbox, wire=None):
+        if wire is not None:
+            values = {
+                "type": RIGHTRAIL,
+                "pin_number": 1}
+        else:
+            dialog = LDPowerRailDialog(self.ParentWindow, self.Controler, self.TagName)
+            dialog.SetPreviewFont(self.GetFont())
+            dialog.SetMinElementSize((bbox.width, bbox.height))
+            values = (dialog.GetValues()
+                      if dialog.ShowModal() == wx.ID_OK
+                      else None)
+            dialog.Destroy()
+        if values is not None:
             id = self.GetNewId()
-            values = dialog.GetValues()
             powerrail = LD_PowerRail(self, values["type"], id, values["pin_number"])
-            powerrail.SetPosition(bbox.x, bbox.y)
-            powerrail.SetSize(*self.GetScaledSize(values["width"], values["height"]))
-            self.AddBlock(powerrail)
             self.Controler.AddEditedElementPowerRail(self.TagName, id, values["type"])
-            self.RefreshPowerRailModel(powerrail)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            powerrail.Refresh()
-        dialog.Destroy()
-
-    def AddNewStep(self, bbox, initial = False):
-        dialog = SFCStepDialog(self.ParentWindow, self.Controler, self.TagName, initial)
-        dialog.SetPreviewFont(self.GetFont())
-        dialog.SetMinElementSize((bbox.width, bbox.height))
-        if dialog.ShowModal() == wx.ID_OK:
+            self.AddNewElement(powerrail, bbox, wire)
+
+    def AddNewStep(self, bbox, initial=False, wire=None):
+        if wire is not None:
+            values = {
+                "name": self.Controler.GenerateNewName(
+                    self.TagName, None, "Step%d", 0),
+                "input": True,
+                "output": False,
+                "action":False}
+        else:
+            dialog = SFCStepDialog(self.ParentWindow, self.Controler, self.TagName, initial)
+            dialog.SetPreviewFont(self.GetFont())
+            dialog.SetMinElementSize((bbox.width, bbox.height))
+            values = (dialog.GetValues()
+                      if dialog.ShowModal() == wx.ID_OK
+                      else None)
+            dialog.Destroy()
+        if values is not None:
             id = self.GetNewId()
-            values = dialog.GetValues()
             step = SFC_Step(self, values["name"], initial, id)
-            if values["input"]:
-                step.AddInput()
+            self.Controler.AddEditedElementStep(self.TagName, id)
+            for connector in ["input", "output", "action"]:
+                getattr(step, ("Add" 
+                               if values[connector] 
+                               else "Remove") + connector.capitalize())()
+            self.AddNewElement(step, bbox, wire)
+    
+    def AddNewTransition(self, bbox, connection=False, wire=None):
+        if wire is not None and connection:
+            values = {
+                "type": "connection",
+                "value": None,
+                "priority": 0}
+        else:
+            dialog = SFCTransitionDialog(self.ParentWindow, self.Controler, self.TagName, self.GetDrawingMode() == FREEDRAWING_MODE)
+            dialog.SetPreviewFont(self.GetFont())
+            dialog.SetMinElementSize((bbox.width, bbox.height))
+            values = (dialog.GetValues()
+                      if dialog.ShowModal() == wx.ID_OK
+                      else None)
+            dialog.Destroy()
+        if values is not None:
+            id = self.GetNewId()
+            transition = SFC_Transition(self, values["type"], values["value"], values["priority"], id)
+            self.Controler.AddEditedElementTransition(self.TagName, id)
+            if connection:
+                connector = transition.GetConditionConnector()
             else:
-                step.RemoveInput()
-            if values["output"]:
-                step.AddOutput()
-            else:
-                step.RemoveOutput()
-            if values["action"]:
-                step.AddAction()    
-            else:
-                step.RemoveAction()
-            step.SetPosition(bbox.x, bbox.y)
-            min_width, min_height = step.GetMinSize()
-            step.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
-            self.AddBlock(step)
-            self.Controler.AddEditedElementStep(self.TagName, id)
-            self.RefreshStepModel(step)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            step.Refresh()
-        dialog.Destroy()
-
-    def AddNewTransition(self, bbox):
-        dialog = SFCTransitionDialog(self.ParentWindow, self.Controler, self.TagName, self.GetDrawingMode() == FREEDRAWING_MODE)
-        dialog.SetPreviewFont(self.GetFont())
-        dialog.SetMinElementSize((bbox.width, bbox.height))
-        if dialog.ShowModal() == wx.ID_OK:
-            id = self.GetNewId()
-            values = dialog.GetValues()
-            transition = SFC_Transition(self, values["type"], values["value"], values["priority"], id)
-            transition.SetPosition(bbox.x, bbox.y)
-            min_width, min_height = transition.GetMinSize()
-            transition.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
-            self.AddBlock(transition)
-            self.Controler.AddEditedElementTransition(self.TagName, id)
-            self.RefreshTransitionModel(transition)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            transition.Refresh()
-        dialog.Destroy()
-
-    def AddNewDivergence(self, bbox):
+                connector = transition.GetConnectors()["inputs"][0]
+            self.AddNewElement(transition, bbox, wire, connector)
+    
+    def AddNewDivergence(self, bbox, wire=None):
         dialog = SFCDivergenceDialog(self.ParentWindow, self.Controler, self.TagName)
         dialog.SetPreviewFont(self.GetFont())
         dialog.SetMinElementSize((bbox.width, bbox.height))
@@ -2399,19 +2470,11 @@
             id = self.GetNewId()
             values = dialog.GetValues()
             divergence = SFC_Divergence(self, values["type"], values["number"], id)
-            divergence.SetPosition(bbox.x, bbox.y)
-            min_width, min_height = divergence.GetMinSize(True)
-            divergence.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
-            self.AddBlock(divergence)
             self.Controler.AddEditedElementDivergence(self.TagName, id, values["type"])
-            self.RefreshDivergenceModel(divergence)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            divergence.Refresh()
+            self.AddNewElement(divergence, bbox, wire)
         dialog.Destroy()
 
-    def AddNewJump(self, bbox):
+    def AddNewJump(self, bbox, wire=None):
         choices = []
         for block in self.Blocks.itervalues():
             if isinstance(block, SFC_Step):
@@ -2421,39 +2484,21 @@
               choices, wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
         if dialog.ShowModal() == wx.ID_OK:
             id = self.GetNewId()
-            value = dialog.GetStringSelection()
-            jump = SFC_Jump(self, value, id)
-            jump.SetPosition(bbox.x, bbox.y)
-            min_width, min_height = jump.GetMinSize()
-            jump.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
-            self.AddBlock(jump)
+            jump = SFC_Jump(self, dialog.GetStringSelection(), id)
             self.Controler.AddEditedElementJump(self.TagName, id)
-            self.RefreshJumpModel(jump)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            jump.Refresh()
+            self.AddNewElement(jump, bbox, wire)
         dialog.Destroy()
 
-    def AddNewActionBlock(self, bbox):
+    def AddNewActionBlock(self, bbox, wire=None):
         dialog = ActionBlockDialog(self.ParentWindow)
         dialog.SetQualifierList(self.Controler.GetQualifierTypes())
         dialog.SetActionList(self.Controler.GetEditedElementActions(self.TagName, self.Debug))
         dialog.SetVariableList(self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug))
         if dialog.ShowModal() == wx.ID_OK:
-            actions = dialog.GetValues()
             id = self.GetNewId()
-            actionblock = SFC_ActionBlock(self, actions, id)
-            actionblock.SetPosition(bbox.x, bbox.y)
-            min_width, min_height = actionblock.GetMinSize()
-            actionblock.SetSize(*self.GetScaledSize(max(bbox.width, min_width), max(bbox.height, min_height)))
-            self.AddBlock(actionblock)
+            actionblock = SFC_ActionBlock(self, dialog.GetValues(), id)
             self.Controler.AddEditedElementActionBlock(self.TagName, id)
-            self.RefreshActionBlockModel(actionblock)
-            self.RefreshBuffer()
-            self.RefreshScrollBars()
-            self.RefreshVisibleElements()
-            actionblock.Refresh()
+            self.AddNewElement(actionblock, bbox, wire)
         dialog.Destroy()
 
 #-------------------------------------------------------------------------------