← Back to team overview

kicad-developers team mailing list archive

[PATCH] Dragging with tracks in GAL

 

Hi,

Here is a really basic concept patch for component dragging with
tracks ('G') in pcbnew GAL.

It uses the same dragging mechanism as legacy for modules and pads. If
it's not desired to continue to use that code for the time being, at
least this provides the TOOL_ACTION hook and outlines where new code
would have to be added.

However, the drag.h interface is pretty small, so I don't think using
it is too objectionable for the time being.

For dragging traces, the much nicer PNS dragging is used, but this
doesn't work with a block selection. I'm not that familiar with the
PNS, so I'm not sure where to start to do that.

Cheers,

John
From 7e493417cf1f04912a0f47681a40f30f2a9e96e3 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Thu, 2 Feb 2017 00:14:18 +0800
Subject: [PATCH] Add drag tool to GAL edit tool

This adds segment endpoint dragging when moving modules/pads and calls
the existing PNS interactive router for dragging tracks.

Drag tool is activated using the 'G' hotkey, same as legacy.

Fixes: lp:1661962
* https://bugs.launchpad.net/kicad/+bug/1661962
---
 pcbnew/tools/common_actions.cpp |  8 ++++-
 pcbnew/tools/common_actions.h   |  6 ++++
 pcbnew/tools/edit_tool.cpp      | 65 +++++++++++++++++++++++++++++++++++++++--
 pcbnew/tools/edit_tool.h        | 26 ++++++++++++++++-
 4 files changed, 100 insertions(+), 5 deletions(-)

diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp
index 850d8b2fa..783c8005f 100644
--- a/pcbnew/tools/common_actions.cpp
+++ b/pcbnew/tools/common_actions.cpp
@@ -98,7 +98,13 @@ TOOL_ACTION COMMON_ACTIONS::globalEditPads( "pcbnew.InteractiveEdit.globalPadEdi
 
 TOOL_ACTION COMMON_ACTIONS::editActivate( "pcbnew.InteractiveEdit",
         AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_MOVE_ITEM ),
-        _( "Move" ), _( "Moves the selected item(s)" ), move_xpm, AF_ACTIVATE );
+        _( "Move" ), _( "Moves the selected item(s)" ),
+        move_xpm, AF_ACTIVATE, (void*) MOVE_FLAGS::NORMAL );
+
+TOOL_ACTION COMMON_ACTIONS::drag( "pcbnew.InteractiveEdit.drag",
+        AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DRAG_ITEM ),
+        _( "Drag" ), _( "Drags the selected item(s) along with connected tracks" ),
+        drag_module_xpm, AF_ACTIVATE, (void*) MOVE_FLAGS::DRAG_TRACKS );
 
 TOOL_ACTION COMMON_ACTIONS::duplicate( "pcbnew.InteractiveEdit.duplicate",
         AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DUPLICATE_ITEM ),
diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h
index 61f1a4ec0..643252ee0 100644
--- a/pcbnew/tools/common_actions.h
+++ b/pcbnew/tools/common_actions.h
@@ -70,6 +70,9 @@ public:
     /// Activation of the edit tool
     static TOOL_ACTION editActivate;
 
+    /// Activation of the drag tool
+    static TOOL_ACTION drag;
+
     /// Rotation of selected objects clockwise
     static TOOL_ACTION rotateCw;
 
@@ -359,6 +362,9 @@ public:
 
     ///> Remove event modifier flags
     enum class REMOVE_FLAGS { NORMAL = 0x00, ALT = 0x01 };
+
+    ///> Move event modifier flags
+    enum class MOVE_FLAGS { NORMAL = 0x00, DRAG_TRACKS = 0x01 };
 };
 
 void registerAllTools( TOOL_MANAGER* aToolManager );
diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp
index 35cace213..ed2bad730 100644
--- a/pcbnew/tools/edit_tool.cpp
+++ b/pcbnew/tools/edit_tool.cpp
@@ -35,6 +35,7 @@
 #include <class_draw_panel_gal.h>
 #include <module_editor_frame.h>
 #include <array_creator.h>
+#include <drag.h>
 
 #include <tool/tool_manager.h>
 #include <view/view_controls.h>
@@ -125,7 +126,7 @@ bool EDIT_TOOL::Init()
 }
 
 
-bool EDIT_TOOL::invokeInlineRouter()
+bool EDIT_TOOL::invokeInlineRouter( bool aForce )
 {
     TRACK* track = uniqueSelected<TRACK>();
     VIA* via = uniqueSelected<VIA>();
@@ -135,7 +136,7 @@ bool EDIT_TOOL::invokeInlineRouter()
         ROUTER_TOOL* theRouter = static_cast<ROUTER_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) );
         assert( theRouter );
 
-        if( !theRouter->PNSSettings().InlineDragEnabled() )
+        if( !aForce && !theRouter->PNSSettings().InlineDragEnabled() )
             return false;
 
         m_toolMgr->RunAction( COMMON_ACTIONS::routerInlineDrag, true, track ? track : via );
@@ -145,6 +146,50 @@ bool EDIT_TOOL::invokeInlineRouter()
     return false;
 }
 
+void EDIT_TOOL::setupDragList( const SELECTION& aSelection )
+{
+    EraseDragList();
+    DRAG_LIST drglist( getModel<BOARD>() );
+
+    for( auto item : aSelection )
+    {
+        switch( item->Type() )
+        {
+        case PCB_PAD_T:
+        {
+            auto pad = static_cast<D_PAD*>( item );
+            drglist.BuildDragListe( pad );
+            break;
+        }
+        case PCB_MODULE_T:
+        {
+            auto module = static_cast<MODULE*>( item );
+            drglist.BuildDragListe( module );
+            break;
+        }
+        default:
+            break;
+        }
+    }
+
+    // save modifications to dragged segments
+    for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
+    {
+        TRACK* segm = g_DragSegmentList[ii].m_Track;
+        m_commit->Modify( segm );
+    }
+}
+
+void EDIT_TOOL::dragItemsInDragList()
+{
+    for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
+    {
+        TRACK* segm = g_DragSegmentList[ii].m_Track;
+
+        g_DragSegmentList[ii].SetTrackEndsCoordinates( wxPoint( 0, 0 ) );
+        getView()->Update( segm, KIGFX::GEOMETRY );
+    }
+}
 
 int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
 {
@@ -168,6 +213,9 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
     bool restore = false;       // Should items' state be restored when finishing the tool?
     bool lockOverride = false;
 
+    const bool dragTracks = aEvent.Parameter<intptr_t>() ==
+            (int) COMMON_ACTIONS::MOVE_FLAGS::DRAG_TRACKS;
+
     controls->ShowCursor( true );
 
     // cumulative translation
@@ -180,6 +228,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
     do
     {
         if( evt->IsAction( &COMMON_ACTIONS::editActivate )
+                || evt->IsAction( &COMMON_ACTIONS::drag )
                 || evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
         {
             if( selection.Empty() )
@@ -199,11 +248,15 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
                 for( auto item : selection )
                     item->Move( movement + m_offset );
 
+                // update any dragged tracks
+                if( dragTracks )
+                    dragItemsInDragList();
+
                 updateRatsnest( true );
             }
             else if( !m_dragging )    // Prepare to start dragging
             {
-                if( !invokeInlineRouter() )
+                if( !invokeInlineRouter( dragTracks ) )
                 {
                     m_selectionTool->SanitizeSelection();
 
@@ -222,6 +275,11 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
                     for( auto item : selection )
                         m_commit->Modify( item );
 
+                    // if dragging connected segments, work out which
+                    // segments to drag at this point
+                    if( dragTracks )
+                        setupDragList( selection );
+
                     m_cursor = controls->GetCursorPosition();
 
                     if( selection.Size() == 1 )
@@ -832,6 +890,7 @@ int EDIT_TOOL::ExchangeFootprints( const TOOL_EVENT& aEvent )
 void EDIT_TOOL::SetTransitions()
 {
     Go( &EDIT_TOOL::Main,       COMMON_ACTIONS::editActivate.MakeEvent() );
+    Go( &EDIT_TOOL::Main,       COMMON_ACTIONS::drag.MakeEvent() );
     Go( &EDIT_TOOL::Rotate,     COMMON_ACTIONS::rotateCw.MakeEvent() );
     Go( &EDIT_TOOL::Rotate,     COMMON_ACTIONS::rotateCcw.MakeEvent() );
     Go( &EDIT_TOOL::Flip,       COMMON_ACTIONS::flip.MakeEvent() );
diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h
index 93adf2a1a..5db91066b 100644
--- a/pcbnew/tools/edit_tool.h
+++ b/pcbnew/tools/edit_tool.h
@@ -152,7 +152,31 @@ private:
 
     int editFootprintInFpEditor( const TOOL_EVENT& aEvent );
 
-    bool invokeInlineRouter();
+    /**
+     * Invoke the interactive PNS router (used when dragging tracks/vias)
+     *
+     * @param aForce invoke the router even if the PNS settings aren't
+     * set to normally invoke drag-routing (used when the drag tool is
+     * used to override these settings).
+     *
+     * @return true if the router ran
+     */
+    bool invokeInlineRouter( bool aForce );
+
+    /**
+     * Collect connected segments into the drag list so that they can
+     * be updated too when an item is moved
+     *
+     * @param aSelection selection of items to gather connected segments
+     * for
+     */
+    void setupDragList( const SELECTION& aSelection );
+
+    /**
+     * Update items in the drag list when the connected item is moved
+     * so that the connected items stay connected
+     */
+    void dragItemsInDragList();
 
     /**
      * Function hoverSelection()
-- 
2.11.0


Follow ups