diff --git a/common/dialog_about/dialog_about.cpp b/common/dialog_about/dialog_about.cpp index 7686bf6f0b..b4d8ebef2a 100644 --- a/common/dialog_about/dialog_about.cpp +++ b/common/dialog_about/dialog_about.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2010 Rafael Sokolowski - * Copyright (C) 2016 KiCad Developers, see CHANGELOG.TXT for contributors. + * Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -525,6 +525,13 @@ void dialog_about::OnCopyVersionInfo( wxCommandEvent& event ) msg_version << OFF; #endif + msg_version << " KICAD_SCRIPTING_ACTION_MENU="; +#ifdef KICAD_SCRIPTING_ACTION_MENU + msg_version << ON; +#else + msg_version << OFF; +#endif + msg_version << " BUILD_GITHUB_PLUGIN="; #ifdef BUILD_GITHUB_PLUGIN msg_version << ON; diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index dc4200e447..671da135e3 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -119,10 +119,10 @@ protected: #if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) /** - * Function initActionPluginMenus + * Function RebuildActionPluginMenus * Fill action menu with all registred action plugins */ - void initActionPluginMenus(); + void RebuildActionPluginMenus(); /** * Function OnActionPlugin diff --git a/pcbnew/class_action_plugin.cpp b/pcbnew/class_action_plugin.cpp index 413390716b..70b54d048e 100644 --- a/pcbnew/class_action_plugin.cpp +++ b/pcbnew/class_action_plugin.cpp @@ -41,24 +41,23 @@ void ACTION_PLUGIN::register_action() } -std::vector ACTION_PLUGINS::m_Actions; -std::vector ACTION_PLUGINS::m_ActionsMenu; +std::vector ACTION_PLUGINS::m_actionsList; ACTION_PLUGIN* ACTION_PLUGINS::GetAction( int aIndex ) { - return m_Actions[aIndex]; + return m_actionsList[aIndex]; } -ACTION_PLUGIN* ACTION_PLUGINS::GetActionByMenu( int menu ) +ACTION_PLUGIN* ACTION_PLUGINS::GetActionByMenu( int aMenu ) { int max = GetActionsCount(); - for( int i = 0; im_actionMenuId == aMenu ) + return m_actionsList[i]; } return NULL; @@ -67,13 +66,13 @@ ACTION_PLUGIN* ACTION_PLUGINS::GetActionByMenu( int menu ) void ACTION_PLUGINS::SetActionMenu( int aIndex, int idMenu ) { - m_ActionsMenu[aIndex] = idMenu; + m_actionsList[aIndex]->m_actionMenuId = idMenu; } int ACTION_PLUGINS::GetActionMenu( int aIndex ) { - return m_ActionsMenu[aIndex]; + return m_actionsList[aIndex]->m_actionMenuId; } @@ -97,14 +96,12 @@ ACTION_PLUGIN* ACTION_PLUGINS::GetAction( wxString aName ) int ACTION_PLUGINS::GetActionsCount() { - return m_Actions.size(); + return m_actionsList.size(); } void ACTION_PLUGINS::register_action( ACTION_PLUGIN* aAction ) { - int updatedMenu = 0; - // Search for this entry do not register twice this action: for( int ii = 0; ii < GetActionsCount(); ii++ ) { @@ -119,9 +116,7 @@ void ACTION_PLUGINS::register_action( ACTION_PLUGIN* aAction ) if( action->GetName() == aAction->GetName() ) { - updatedMenu = GetActionMenu( ii ); - m_Actions.erase( m_Actions.begin() + ii ); - m_ActionsMenu.erase( m_ActionsMenu.begin() + ii ); + m_actionsList.erase( m_actionsList.begin() + ii ); delete action; @@ -129,8 +124,7 @@ void ACTION_PLUGINS::register_action( ACTION_PLUGIN* aAction ) } } - m_Actions.push_back( aAction ); - m_ActionsMenu.push_back( updatedMenu ); + m_actionsList.push_back( aAction ); } @@ -144,8 +138,8 @@ bool ACTION_PLUGINS::deregister_object( void* aObject ) if( action->GetObject() == aObject ) { - m_Actions.erase( m_Actions.begin() + i ); - m_ActionsMenu.erase( m_ActionsMenu.begin() + i ); + m_actionsList.erase( m_actionsList.begin() + i ); + //m_actionsListMenu.erase( m_actionsListMenu.begin() + i ); delete action; return true; } diff --git a/pcbnew/class_action_plugin.h b/pcbnew/class_action_plugin.h index 5249e93ed0..e3be28c922 100644 --- a/pcbnew/class_action_plugin.h +++ b/pcbnew/class_action_plugin.h @@ -40,7 +40,13 @@ class ACTION_PLUGIN { public: - ACTION_PLUGIN() {} + // association between the plugin and its menu id + // m_actionMenuId set to 0 means the corresponding menuitem to call this + // action is not yet created + int m_actionMenuId; + +public: + ACTION_PLUGIN() : m_actionMenuId( 0 ) {} virtual ~ACTION_PLUGIN(); /** @@ -94,15 +100,9 @@ private: /** * ACTION_PLUGIN system wide static list */ - static std::vector m_Actions; - - /** - * system wide static association between Plugin and menu id - */ - static std::vector m_ActionsMenu; + static std::vector m_actionsList; public: - /** * Function register_action * An action calls this static method when it wants to register itself @@ -150,10 +150,10 @@ public: /** * Function GetActionByMenu * find action plugin associated to a menu id - * @param menu is the menu id (defined with SetActionMenu) + * @param aMenu is the menu id (defined with SetActionMenu) * @return the associated ACTION_PLUGIN (or null if not found) */ - static ACTION_PLUGIN* GetActionByMenu( int menu ); + static ACTION_PLUGIN* GetActionByMenu( int aMenu ); /** diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp index b007a5419d..e25ea79a5d 100644 --- a/pcbnew/menubar_pcbframe.cpp +++ b/pcbnew/menubar_pcbframe.cpp @@ -658,11 +658,8 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() KiBitmap( reload_xpm ) ); submenuActionPluginsMenu->AppendSeparator(); - #endif - - wxMenu* designRulesMenu = new wxMenu; AddMenuItem( designRulesMenu, ID_MENU_PCB_SHOW_DESIGN_RULES_DIALOG, @@ -723,4 +720,10 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() SetMenuBar( menuBar ); else menuBar->Refresh(); + +#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) + // Populate the Action Plugin sub-menu + RebuildActionPluginMenus(); +#endif + } diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 016bf309fc..2f1c2e59ee 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -479,10 +479,6 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : enableGALSpecificMenus(); -#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) - initActionPluginMenus(); -#endif - // disable Export STEP item if kicad2step does not exist wxString strK2S = Pgm().GetExecutablePath(); #ifdef __WXMAC__ diff --git a/pcbnew/swig/pcbnew_action_plugins.cpp b/pcbnew/swig/pcbnew_action_plugins.cpp index 5a2a248d49..3ca5aa4a21 100644 --- a/pcbnew/swig/pcbnew_action_plugins.cpp +++ b/pcbnew/swig/pcbnew_action_plugins.cpp @@ -208,33 +208,67 @@ void PCB_EDIT_FRAME::OnActionPluginRefresh( wxCommandEvent& aEvent ) // ReRun the Python method pcbnew.LoadPlugins (already called when starting Pcbnew) PyRun_SimpleString( cmd ); - initActionPluginMenus(); + RebuildActionPluginMenus(); } -void PCB_EDIT_FRAME::initActionPluginMenus() +void PCB_EDIT_FRAME::RebuildActionPluginMenus() { wxMenu* actionMenu = GetMenuBar()->FindItem( ID_TOOLBARH_PCB_ACTION_PLUGIN )->GetSubMenu(); - for( int i = 0; i < ACTION_PLUGINS::GetActionsCount(); i++ ) + if( !actionMenu ) // Should not occur. + return; + + // First, remove existing submenus, if they are too many + wxMenuItemList list = actionMenu->GetMenuItems(); + // The first menuitems are the refresh menu and separator. do not count them + int act_menu_count = -2; + + std::vector available_menus; + + for( auto iter = list.begin(); iter != list.end(); ++iter, act_menu_count++ ) { - // Init menu only for not already created Items - if( ACTION_PLUGINS::GetActionMenu( i ) == 0 ) + if( act_menu_count < 0 ) + continue; + + wxMenuItem* item = *iter; + + if( act_menu_count < ACTION_PLUGINS::GetActionsCount() ) { - wxMenuItem* item = AddMenuItem( actionMenu, wxID_ANY, - ACTION_PLUGINS::GetAction( i )->GetName(), - ACTION_PLUGINS::GetAction( i )->GetDescription(), - KiBitmap( hammer_xpm ) ); - - ACTION_PLUGINS::SetActionMenu( i, item->GetId() ); - - Connect( - item->GetId(), wxEVT_COMMAND_MENU_SELECTED, - (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & - PCB_EDIT_FRAME::OnActionPlugin ); + available_menus.push_back( item ); + continue; } - // Delete is not handled by plugins system (yet) + // Remove menus which are not usable for our current plugin list + Disconnect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & + PCB_EDIT_FRAME::OnActionPlugin ); + actionMenu->Delete( item ); + } + + for( int ii = 0; ii < ACTION_PLUGINS::GetActionsCount(); ii++ ) + { + wxMenuItem* item; + + if( ii < (int)available_menus.size() ) + { + item = available_menus[ii]; + item->SetItemLabel( ACTION_PLUGINS::GetAction( ii )->GetName() ); + item->SetHelp( ACTION_PLUGINS::GetAction( ii )->GetDescription() ); + } + else + { + item = AddMenuItem( actionMenu, wxID_ANY, + ACTION_PLUGINS::GetAction( ii )->GetName(), + ACTION_PLUGINS::GetAction( ii )->GetDescription(), + KiBitmap( hammer_xpm ) ); + + Connect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & + PCB_EDIT_FRAME::OnActionPlugin ); + } + + ACTION_PLUGINS::SetActionMenu( ii, item->GetId() ); } }