diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 6278911fea..10947d3caf 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -287,6 +287,10 @@ bool EDIT_TOOL::Init() auto singleModuleCondition = SELECTION_CONDITIONS::OnlyType( PCB_MODULE_T ) && SELECTION_CONDITIONS::Count( 1 ); + auto noActiveToolCondition = [ this ] ( const SELECTION& aSelection ) { + return ( frame()->GetToolId() == ID_NO_TOOL_SELECTED ); + }; + // Add context menu entries that are displayed when selection tool is active CONDITIONAL_MENU& menu = m_selectionTool->GetToolMenu().GetMenu(); @@ -309,8 +313,10 @@ bool EDIT_TOOL::Init() menu.AddItem( PCB_ACTIONS::copyToClipboard, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( PCB_ACTIONS::cutToClipboard, SELECTION_CONDITIONS::NotEmpty ); - menu.AddItem( PCB_ACTIONS::pasteFromClipboard ); - menu.AddSeparator(); + // Selection tool handles the context menu for some other tools, such as the Picker. + // Don't add things like Paste when another tool is active. + menu.AddItem( PCB_ACTIONS::pasteFromClipboard, noActiveToolCondition ); + menu.AddSeparator( noActiveToolCondition ); // Mirror only available in modedit menu.AddItem( PCB_ACTIONS::mirror, editingModuleCondition && SELECTION_CONDITIONS::NotEmpty ); diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp index a0af906f71..78f05ecf3c 100644 --- a/pcbnew/tools/pcb_editor_control.cpp +++ b/pcbnew/tools/pcb_editor_control.cpp @@ -226,7 +226,8 @@ public: PCB_EDITOR_CONTROL::PCB_EDITOR_CONTROL() : PCB_TOOL( "pcbnew.EditorControl" ), - m_frame( nullptr ) + m_frame( nullptr ), + m_menu( *this ) { m_placeOrigin.reset( new KIGFX::ORIGIN_VIEWITEM( KIGFX::COLOR4D( 0.8, 0.0, 0.0, 1.0 ), KIGFX::ORIGIN_VIEWITEM::CIRCLE_CROSS ) ); @@ -255,6 +256,31 @@ void PCB_EDITOR_CONTROL::Reset( RESET_REASON aReason ) bool PCB_EDITOR_CONTROL::Init() { + auto activeToolCondition = [ this ] ( const SELECTION& aSel ) { + return ( m_frame->GetToolId() != ID_NO_TOOL_SELECTED ); + }; + + auto inactiveStateCondition = [ this ] ( const SELECTION& aSel ) { + return ( m_frame->GetToolId() == ID_NO_TOOL_SELECTED && aSel.Size() == 0 ); + }; + + auto placeModuleCondition = [ this ] ( const SELECTION& aSel ) { + return ( m_frame->GetToolId() == ID_PCB_MODULE_BUTT && aSel.GetSize() == 0 ); + }; + + auto& ctxMenu = m_menu.GetMenu(); + + // "Cancel" goes at the top of the context menu when a tool is active + ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolCondition, 1000 ); + ctxMenu.AddSeparator( activeToolCondition, 1000 ); + + // "Get and Place Footprint" should be available for Place Footprint tool + ctxMenu.AddItem( PCB_ACTIONS::findMove, placeModuleCondition, 1000 ); + ctxMenu.AddSeparator( placeModuleCondition, 1000 ); + + // Finally, add the standard zoom & grid items + m_menu.AddStandardSubMenus( *getEditFrame() ); + auto zoneMenu = std::make_shared(); zoneMenu->SetTool( this ); @@ -270,6 +296,10 @@ bool PCB_EDITOR_CONTROL::Init() auto& toolMenu = selTool->GetToolMenu(); auto& menu = toolMenu.GetMenu(); + // Add "Get and Place Footprint" when Selection tool is in an inactive state + menu.AddItem( PCB_ACTIONS::findMove, inactiveStateCondition ); + menu.AddSeparator( inactiveStateCondition ); + toolMenu.AddSubMenu( zoneMenu ); toolMenu.AddSubMenu( lockMenu ); @@ -413,7 +443,7 @@ int PCB_EDITOR_CONTROL::PlaceModule( const TOOL_EVENT& aEvent ) if( reselect && module ) m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, module ); - if( evt->IsCancel() || evt->IsActivate() ) + if( evt->IsCancel() || TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() ) { if( module ) { @@ -459,6 +489,11 @@ int PCB_EDITOR_CONTROL::PlaceModule( const TOOL_EVENT& aEvent ) controls->CaptureCursor( placing ); } + else if( evt->IsClick( BUT_RIGHT ) ) + { + m_menu.ShowContextMenu( selTool->GetSelection() ); + } + else if( module && evt->IsMotion() ) { module->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); @@ -541,6 +576,7 @@ int PCB_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode ) int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent ) { + auto selTool = m_toolMgr->GetTool(); KIGFX::VIEW* view = getView(); KIGFX::VIEW_CONTROLS* controls = getViewControls(); BOARD* board = getModel(); @@ -569,7 +605,7 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent ) { cursorPos = controls->GetCursorPosition(); - if( evt->IsCancel() || evt->IsActivate() ) + if( evt->IsCancel() || TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() ) break; else if( evt->IsAction( &PCB_ACTIONS::incWidth ) ) @@ -605,6 +641,11 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent ) preview.Add( target ); } + else if( evt->IsClick( BUT_RIGHT ) ) + { + m_menu.ShowContextMenu( selTool->GetSelection() ); + } + else if( evt->IsMotion() ) { target->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); diff --git a/pcbnew/tools/pcb_editor_control.h b/pcbnew/tools/pcb_editor_control.h index 9027de6978..91fb25b05d 100644 --- a/pcbnew/tools/pcb_editor_control.h +++ b/pcbnew/tools/pcb_editor_control.h @@ -26,6 +26,7 @@ #define PCB_EDITOR_CONTROL_H #include +#include namespace KIGFX { class ORIGIN_VIEWITEM; @@ -128,6 +129,9 @@ private: ///> Pointer to the currently used edit frame. PCB_EDIT_FRAME* m_frame; + /// Menu model displayed by the tool. + TOOL_MENU m_menu; + ///> Place & drill origin marker. std::unique_ptr m_placeOrigin; diff --git a/pcbnew/tools/picker_tool.cpp b/pcbnew/tools/picker_tool.cpp index 79b5913030..bf3c2eb97c 100644 --- a/pcbnew/tools/picker_tool.cpp +++ b/pcbnew/tools/picker_tool.cpp @@ -29,6 +29,9 @@ #include #include #include +#include "tool_event_utils.h" +#include "selection_tool.h" + TOOL_ACTION PCB_ACTIONS::pickerTool( "pcbnew.Picker", AS_GLOBAL, 0, "", "", NULL, AF_ACTIVATE ); @@ -40,6 +43,29 @@ PICKER_TOOL::PICKER_TOOL() } +bool PICKER_TOOL::Init() +{ + auto activeToolCondition = [ this ] ( const SELECTION& aSel ) { + return ( frame()->GetToolId() != ID_NO_TOOL_SELECTED ); + }; + + SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + + // We delegate our context menu to the Selection tool, so make sure it has a + // "Cancel" item at the top. + if( selTool ) + { + auto& toolMenu = selTool->GetToolMenu(); + auto& menu = toolMenu.GetMenu(); + + menu.AddItem( ACTIONS::cancelInteractive, activeToolCondition, 1000 ); + menu.AddSeparator( activeToolCondition, 1000 ); + } + + return true; +} + + int PICKER_TOOL::Main( const TOOL_EVENT& aEvent ) { KIGFX::VIEW_CONTROLS* controls = getViewControls(); @@ -83,7 +109,7 @@ int PICKER_TOOL::Main( const TOOL_EVENT& aEvent ) setControls(); } - else if( evt->IsCancel() || evt->IsActivate() ) + else if( evt->IsCancel() || TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() ) break; else diff --git a/pcbnew/tools/picker_tool.h b/pcbnew/tools/picker_tool.h index 9cdc74a740..f92c01b580 100644 --- a/pcbnew/tools/picker_tool.h +++ b/pcbnew/tools/picker_tool.h @@ -40,6 +40,9 @@ public: ///> Mouse event click handler type. typedef std::function CLICK_HANDLER; + /// @copydoc TOOL_INTERACTIVE::Init() + bool Init() override; + ///> @copydoc TOOL_INTERACTIVE::Reset() void Reset( RESET_REASON aReason ) override {} diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index c8ce568c19..33e3d32005 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -117,7 +117,9 @@ TOOL_ACTION PCB_ACTIONS::find( "pcbnew.InteractiveSelection.Find", _( "Find Item..." ),_( "Searches the document for an item" ), find_xpm ); TOOL_ACTION PCB_ACTIONS::findMove( "pcbnew.InteractiveSelection.FindMove", - AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_GET_AND_MOVE_FOOTPRINT ) ); + AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_GET_AND_MOVE_FOOTPRINT ), + _( "Get and Move Footprint" ), + _( "Selects a footprint by reference and places it under the cursor for moving")); TOOL_ACTION PCB_ACTIONS::filterSelection( "pcbnew.InteractiveSelection.FilterSelection", AS_GLOBAL, 0, @@ -204,7 +206,6 @@ bool SELECTION_TOOL::Init() auto& menu = m_menu.GetMenu(); menu.AddMenu( selectMenu.get(), false, SELECTION_CONDITIONS::NotEmpty ); - // only show separator if there is a Select menu to show above it menu.AddSeparator( SELECTION_CONDITIONS::NotEmpty, 1000 ); auto frame = getEditFrame();