diff --git a/3d-viewer/3d_viewer/3d_toolbar.cpp b/3d-viewer/3d_viewer/3d_toolbar.cpp index ded2f6dd67..c85588e687 100644 --- a/3d-viewer/3d_viewer/3d_toolbar.cpp +++ b/3d-viewer/3d_viewer/3d_toolbar.cpp @@ -43,7 +43,7 @@ void EDA_3D_VIEWER::ReCreateMainToolbar() wxWindowUpdateLocker dummy( this ); if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); diff --git a/common/tool/action_toolbar.cpp b/common/tool/action_toolbar.cpp index 3c6a4dc3ce..a6f65a31c1 100644 --- a/common/tool/action_toolbar.cpp +++ b/common/tool/action_toolbar.cpp @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -37,7 +40,20 @@ ACTION_TOOLBAR::ACTION_TOOLBAR( EDA_BASE_FRAME* parent, wxWindowID id, const wxP wxAuiToolBar( parent, id, pos, size, style ), m_toolManager( parent->GetToolManager() ) { - Connect( wxEVT_COMMAND_TOOL_CLICKED, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onToolEvent ), NULL, this ); + Connect( wxEVT_COMMAND_TOOL_CLICKED, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onToolEvent ), + NULL, this ); + Connect( wxEVT_AUITOOLBAR_RIGHT_CLICK, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onToolRightClick ), + NULL, this ); +} + + +ACTION_TOOLBAR::~ACTION_TOOLBAR() +{ + // Delete all the menus + for( auto it = m_toolMenus.begin(); it != m_toolMenus.end(); it++ ) + delete it->second; + + m_toolMenus.clear(); } @@ -84,6 +100,38 @@ void ACTION_TOOLBAR::AddScaledSeparator( wxWindow* aWindow ) } +void ACTION_TOOLBAR::AddToolContextMenu( const TOOL_ACTION& aAction, CONDITIONAL_MENU* aMenu ) +{ + int toolId = aAction.GetId() + ACTION_ID; + + // If this is replacing an existing menu, delete the existing menu before adding the new one + const auto it = m_toolMenus.find( toolId ); + + if( it != m_toolMenus.end() ) + { + // Don't delete it if it is the same menu, just ignore this call + if( it->second == aMenu ) + return; + + delete it->second; + } + + m_toolMenus[toolId] = aMenu; +} + + +void ACTION_TOOLBAR::ClearToolbar() +{ + // Delete all the menus + for( auto it = m_toolMenus.begin(); it != m_toolMenus.end(); it++ ) + delete it->second; + + // Clear the menu items and the actual toolbar + m_toolMenus.clear(); + Clear(); +} + + void ACTION_TOOLBAR::SetToolBitmap( const TOOL_ACTION& aAction, const wxBitmap& aBitmap ) { int toolId = aAction.GetId() + ACTION_ID; @@ -145,3 +193,29 @@ void ACTION_TOOLBAR::onToolEvent( wxAuiToolBarEvent& aEvent ) } } + +void ACTION_TOOLBAR::onToolRightClick( wxAuiToolBarEvent& aEvent ) +{ + int toolId = aEvent.GetToolId(); + + // This means the event was not on a button + if( toolId == -1 ) + return; + + const auto it = m_toolMenus.find( aEvent.GetId() ); + + if( it == m_toolMenus.end() ) + return; + + // Update and show the menu + CONDITIONAL_MENU* menu = it->second; + SELECTION dummySel; + + menu->Evaluate( dummySel ); + menu->UpdateAll(); + PopupMenu( menu ); + + // Remove hovered item when the menu closes, otherwise it remains hovered even if the + // mouse is not on the toolbar + SetHoverItem( nullptr ); +} diff --git a/cvpcb/display_footprints_frame.cpp b/cvpcb/display_footprints_frame.cpp index 0366a84712..60edcaa7d6 100644 --- a/cvpcb/display_footprints_frame.cpp +++ b/cvpcb/display_footprints_frame.cpp @@ -192,7 +192,7 @@ void DISPLAY_FOOTPRINTS_FRAME::ReCreateVToolbar() void DISPLAY_FOOTPRINTS_FRAME::ReCreateOptToolbar() { if( m_optionsToolBar ) - m_optionsToolBar->Clear(); + m_optionsToolBar->ClearToolbar(); else m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); @@ -227,7 +227,7 @@ void DISPLAY_FOOTPRINTS_FRAME::ReCreateHToolbar() // So we do not recreate them after clearing the tools. if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); diff --git a/cvpcb/toolbars_cvpcb.cpp b/cvpcb/toolbars_cvpcb.cpp index f63d232173..c3318bf48c 100644 --- a/cvpcb/toolbars_cvpcb.cpp +++ b/cvpcb/toolbars_cvpcb.cpp @@ -35,7 +35,7 @@ void CVPCB_MAINFRAME::ReCreateHToolbar() { if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); diff --git a/eeschema/libedit/toolbars_libedit.cpp b/eeschema/libedit/toolbars_libedit.cpp index a4c171335d..1083456be9 100644 --- a/eeschema/libedit/toolbars_libedit.cpp +++ b/eeschema/libedit/toolbars_libedit.cpp @@ -45,7 +45,7 @@ void LIB_EDIT_FRAME::ReCreateVToolbar() { if( m_drawToolBar ) - m_drawToolBar->Clear(); + m_drawToolBar->ClearToolbar(); else m_drawToolBar = new ACTION_TOOLBAR( this, ID_V_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); @@ -79,7 +79,7 @@ void LIB_EDIT_FRAME::ReCreateVToolbar() void LIB_EDIT_FRAME::ReCreateHToolbar() { if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); @@ -133,7 +133,7 @@ void LIB_EDIT_FRAME::ReCreateHToolbar() void LIB_EDIT_FRAME::ReCreateOptToolbar() { if( m_optionsToolBar ) - m_optionsToolBar->Clear(); + m_optionsToolBar->ClearToolbar(); else m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, diff --git a/eeschema/toolbars_lib_view.cpp b/eeschema/toolbars_lib_view.cpp index 6fb5cc0a35..74542d4773 100644 --- a/eeschema/toolbars_lib_view.cpp +++ b/eeschema/toolbars_lib_view.cpp @@ -37,7 +37,7 @@ void LIB_VIEW_FRAME::ReCreateHToolbar() { if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, diff --git a/eeschema/toolbars_sch_editor.cpp b/eeschema/toolbars_sch_editor.cpp index 05bd8b435a..fba557b25c 100644 --- a/eeschema/toolbars_sch_editor.cpp +++ b/eeschema/toolbars_sch_editor.cpp @@ -39,7 +39,7 @@ void SCH_EDIT_FRAME::ReCreateHToolbar() { if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, @@ -109,7 +109,7 @@ void SCH_EDIT_FRAME::ReCreateHToolbar() void SCH_EDIT_FRAME::ReCreateVToolbar() { if( m_drawToolBar ) - m_drawToolBar->Clear(); + m_drawToolBar->ClearToolbar(); else m_drawToolBar = new ACTION_TOOLBAR( this, ID_V_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); @@ -147,7 +147,7 @@ void SCH_EDIT_FRAME::ReCreateVToolbar() void SCH_EDIT_FRAME::ReCreateOptToolbar() { if( m_optionsToolBar ) - m_optionsToolBar->Clear(); + m_optionsToolBar->ClearToolbar(); else m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, diff --git a/gerbview/toolbars_gerber.cpp b/gerbview/toolbars_gerber.cpp index 15ea4b2c89..5465a233bd 100644 --- a/gerbview/toolbars_gerber.cpp +++ b/gerbview/toolbars_gerber.cpp @@ -47,7 +47,7 @@ void GERBVIEW_FRAME::ReCreateHToolbar() // So we do not recreate them after clearing the tools. if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); @@ -103,7 +103,7 @@ void GERBVIEW_FRAME::ReCreateAuxiliaryToolbar() wxStaticText* text; if( m_auxiliaryToolBar ) - m_auxiliaryToolBar->Clear(); + m_auxiliaryToolBar->ClearToolbar(); else m_auxiliaryToolBar = new ACTION_TOOLBAR( this, ID_AUX_TOOLBAR, wxDefaultPosition, wxDefaultSize, @@ -208,7 +208,7 @@ void GERBVIEW_FRAME::ReCreateVToolbar() void GERBVIEW_FRAME::ReCreateOptToolbar() { if( m_optionsToolBar ) - m_optionsToolBar->Clear(); + m_optionsToolBar->ClearToolbar(); else m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); diff --git a/include/tool/action_toolbar.h b/include/tool/action_toolbar.h index 2e7b10c371..439802cf2b 100644 --- a/include/tool/action_toolbar.h +++ b/include/tool/action_toolbar.h @@ -29,6 +29,7 @@ #include #include +class CONDITIONAL_MENU; class EDA_BASE_FRAME; class TOOL_MANAGER; class TOOL_ACTION; @@ -45,7 +46,7 @@ public: const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxAUI_TB_DEFAULT_STYLE ); - virtual ~ACTION_TOOLBAR() {} + virtual ~ACTION_TOOLBAR(); /** * Function Add() @@ -69,6 +70,21 @@ public: */ void AddScaledSeparator( wxWindow* aWindow ); + /** + * Add a context menu to a specific tool item on the toolbar. + * This toolbar gets ownership of the menu object, and will delete it when the + * ClearToolbar() function is called. + * + * @param aAction is the action to get the menu + * @param aMenu is the context menu + */ + void AddToolContextMenu( const TOOL_ACTION& aAction, CONDITIONAL_MENU* aMenu ); + + /** + * Clear the toolbar and remove all associated menus. + */ + void ClearToolbar(); + /** * Function SetToolBitmap() * Updates the bitmap of a particular tool. Not icon-based because we use it @@ -90,6 +106,9 @@ protected: ///> The default tool event handler. void onToolEvent( wxAuiToolBarEvent& aEvent ); + ///> Handle a right-click on a menu item + void onToolRightClick( wxAuiToolBarEvent& aEvent ); + protected: ///> Tool items with ID higher than that are considered TOOL_ACTIONs static const int ACTION_ID = 10000; @@ -97,6 +116,7 @@ protected: TOOL_MANAGER* m_toolManager; std::map m_toolKinds; std::map m_toolActions; + std::map m_toolMenus; }; #endif diff --git a/kicad/menubar.cpp b/kicad/menubar.cpp index f187530f87..2df94b1ea0 100644 --- a/kicad/menubar.cpp +++ b/kicad/menubar.cpp @@ -174,7 +174,7 @@ void KICAD_MANAGER_FRAME::ReCreateMenuBar() void KICAD_MANAGER_FRAME::RecreateBaseHToolbar() { if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); diff --git a/pagelayout_editor/toolbars_pl_editor.cpp b/pagelayout_editor/toolbars_pl_editor.cpp index 319a7f2009..e1a199b221 100644 --- a/pagelayout_editor/toolbars_pl_editor.cpp +++ b/pagelayout_editor/toolbars_pl_editor.cpp @@ -31,7 +31,7 @@ void PL_EDITOR_FRAME::ReCreateHToolbar() { if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); @@ -120,7 +120,7 @@ void PL_EDITOR_FRAME::ReCreateHToolbar() void PL_EDITOR_FRAME::ReCreateVToolbar() { if( m_drawToolBar ) - m_drawToolBar->Clear(); + m_drawToolBar->ClearToolbar(); else m_drawToolBar = new ACTION_TOOLBAR( this, ID_V_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); diff --git a/pcbnew/footprint_wizard_frame.cpp b/pcbnew/footprint_wizard_frame.cpp index c6b3cee93c..9a560b9e8f 100644 --- a/pcbnew/footprint_wizard_frame.cpp +++ b/pcbnew/footprint_wizard_frame.cpp @@ -589,7 +589,7 @@ void FOOTPRINT_WIZARD_FRAME::Update3DView( bool aForceReload, const wxString* aT void FOOTPRINT_WIZARD_FRAME::ReCreateHToolbar() { if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); diff --git a/pcbnew/toolbars_footprint_editor.cpp b/pcbnew/toolbars_footprint_editor.cpp index 26a1b198fe..028bda8e3f 100644 --- a/pcbnew/toolbars_footprint_editor.cpp +++ b/pcbnew/toolbars_footprint_editor.cpp @@ -42,7 +42,7 @@ void FOOTPRINT_EDIT_FRAME::ReCreateHToolbar() // So we do not recreate them after clearing the tools. if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); @@ -140,7 +140,7 @@ void FOOTPRINT_EDIT_FRAME::ReCreateHToolbar() void FOOTPRINT_EDIT_FRAME::ReCreateVToolbar() { if( m_drawToolBar ) - m_drawToolBar->Clear(); + m_drawToolBar->ClearToolbar(); else m_drawToolBar = new ACTION_TOOLBAR( this, ID_V_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); @@ -170,7 +170,7 @@ void FOOTPRINT_EDIT_FRAME::ReCreateVToolbar() void FOOTPRINT_EDIT_FRAME::ReCreateOptToolbar() { if( m_optionsToolBar ) - m_optionsToolBar->Clear(); + m_optionsToolBar->ClearToolbar(); else m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); diff --git a/pcbnew/toolbars_footprint_viewer.cpp b/pcbnew/toolbars_footprint_viewer.cpp index 541317ae55..b5206caae6 100644 --- a/pcbnew/toolbars_footprint_viewer.cpp +++ b/pcbnew/toolbars_footprint_viewer.cpp @@ -43,7 +43,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateHToolbar() // So we do not recreate them after clearing the tools. if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); @@ -99,7 +99,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateHToolbar() void FOOTPRINT_VIEWER_FRAME::ReCreateOptToolbar() { if( m_optionsToolBar ) - m_optionsToolBar->Clear(); + m_optionsToolBar->ClearToolbar(); else m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); diff --git a/pcbnew/toolbars_pcb_editor.cpp b/pcbnew/toolbars_pcb_editor.cpp index e69a5b2f78..8a00136953 100644 --- a/pcbnew/toolbars_pcb_editor.cpp +++ b/pcbnew/toolbars_pcb_editor.cpp @@ -216,7 +216,7 @@ void PCB_EDIT_FRAME::ReCreateHToolbar() wxWindowUpdateLocker dummy( this ); if( m_mainToolBar ) - m_mainToolBar->Clear(); + m_mainToolBar->ClearToolbar(); else m_mainToolBar = new ACTION_TOOLBAR( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); @@ -307,7 +307,7 @@ void PCB_EDIT_FRAME::ReCreateOptToolbar() wxWindowUpdateLocker dummy( this ); if( m_optionsToolBar ) - m_optionsToolBar->Clear(); + m_optionsToolBar->ClearToolbar(); else m_optionsToolBar = new ACTION_TOOLBAR( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, @@ -349,7 +349,7 @@ void PCB_EDIT_FRAME::ReCreateVToolbar() wxWindowUpdateLocker dummy( this ); if( m_drawToolBar ) - m_drawToolBar->Clear(); + m_drawToolBar->ClearToolbar(); else m_drawToolBar = new ACTION_TOOLBAR( this, ID_V_TOOLBAR, wxDefaultPosition, wxDefaultSize, KICAD_AUI_TB_STYLE | wxAUI_TB_VERTICAL ); @@ -391,7 +391,7 @@ void PCB_EDIT_FRAME::ReCreateMicrowaveVToolbar() wxWindowUpdateLocker dummy(this); if( m_microWaveToolBar ) - m_microWaveToolBar->Clear(); + m_microWaveToolBar->ClearToolbar(); else m_microWaveToolBar = new ACTION_TOOLBAR( this, ID_MICROWAVE_V_TOOLBAR, wxDefaultPosition, wxDefaultSize,