Loading common/tool/context_menu.cpp +65 −32 Original line number Original line Diff line number Diff line /* /* * This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application. * * * Copyright (C) 2013 CERN * Copyright (C) 2013-2015 CERN * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch> * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License Loading Loading @@ -31,7 +32,9 @@ #include <cassert> #include <cassert> CONTEXT_MENU::CONTEXT_MENU() : CONTEXT_MENU::CONTEXT_MENU() : m_titleSet( false ), m_selected( -1 ), m_tool( NULL ), m_icon( NULL ) m_titleSet( false ), m_selected( -1 ), m_tool( NULL ), m_parent( NULL ), m_icon( NULL ), m_menu_handler( CONTEXT_MENU::menuHandlerStub ), m_update_handler( CONTEXT_MENU::updateHandlerStub ) { { setupEvents(); setupEvents(); } } Loading @@ -44,12 +47,22 @@ CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) } } CONTEXT_MENU::~CONTEXT_MENU() { // Set parent to NULL to prevent submenus from unregistering from a notexisting object for( std::list<CONTEXT_MENU*>::iterator it = m_submenus.begin(); it != m_submenus.end(); ++it ) (*it)->m_parent = NULL; if( m_parent ) m_parent->m_submenus.remove( this ); } CONTEXT_MENU& CONTEXT_MENU::operator=( const CONTEXT_MENU& aMenu ) CONTEXT_MENU& CONTEXT_MENU::operator=( const CONTEXT_MENU& aMenu ) { { Clear(); Clear(); copyFrom( aMenu ); copyFrom( aMenu ); setupEvents(); return *this; return *this; } } Loading Loading @@ -84,11 +97,11 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle ) wxMenuItem* CONTEXT_MENU::Add( const wxString& aLabel, int aId, const BITMAP_OPAQUE* aIcon ) wxMenuItem* CONTEXT_MENU::Add( const wxString& aLabel, int aId, const BITMAP_OPAQUE* aIcon ) { { #ifdef DEBUG #ifdef DEBUG if( FindItem( aId ) != NULL ) if( FindItem( aId ) != NULL ) wxLogWarning( wxT( "Adding more than one menu entry with the same ID may result in" wxLogWarning( wxT( "Adding more than one menu entry with the same ID may result in" "undefined behaviour" ) ); "undefined behaviour" ) ); #endif #endif wxMenuItem* item = new wxMenuItem( this, aId, aLabel, wxEmptyString, wxITEM_NORMAL ); wxMenuItem* item = new wxMenuItem( this, aId, aLabel, wxEmptyString, wxITEM_NORMAL ); if( aIcon ) if( aIcon ) Loading Loading @@ -139,9 +152,7 @@ std::list<wxMenuItem*> CONTEXT_MENU::Add( CONTEXT_MENU* aMenu, const wxString& a if( aExpand ) if( aExpand ) { { unsigned int i = 0; for( unsigned int i = 0; i < aMenu->GetMenuItemCount(); ++i ) for( i = 0; i < aMenu->GetMenuItemCount(); ++i ) { { wxMenuItem* item = aMenu->FindItemByPosition( i ); wxMenuItem* item = aMenu->FindItemByPosition( i ); items.push_back( appendCopy( item ) ); items.push_back( appendCopy( item ) ); Loading @@ -162,8 +173,8 @@ std::list<wxMenuItem*> CONTEXT_MENU::Add( CONTEXT_MENU* aMenu, const wxString& a } } } } m_toolActions.insert( aMenu->m_toolActions.begin(), aMenu->m_toolActions.end() ); m_submenus.push_back( aMenu ); m_handlers.insert( m_handlers.end(), aMenu->m_handlers.begin(), aMenu->m_handlers.end() ); aMenu->m_parent = this; return items; return items; } } Loading @@ -176,13 +187,22 @@ void CONTEXT_MENU::Clear() GetMenuItems().DeleteContents( true ); GetMenuItems().DeleteContents( true ); GetMenuItems().Clear(); GetMenuItems().Clear(); m_toolActions.clear(); m_toolActions.clear(); m_handlers.clear(); GetMenuItems().DeleteContents( false ); // restore the default so destructor does not go wild GetMenuItems().DeleteContents( false ); // restore the default so destructor does not go wild m_submenus.clear(); m_parent = NULL; assert( GetMenuItemCount() == 0 ); assert( GetMenuItemCount() == 0 ); } } void CONTEXT_MENU::UpdateAll() { m_update_handler(); runOnSubmenus( boost::bind( &CONTEXT_MENU::UpdateAll, _1 ) ); } void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) { { OPT_TOOL_EVENT evt; OPT_TOOL_EVENT evt; Loading @@ -208,6 +228,8 @@ void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) } } else else { { runEventHandlers( aEvent, evt ); // Under Linux, every submenu can have a separate event handler, under // Under Linux, every submenu can have a separate event handler, under // Windows all submenus are handled by the main menu. // Windows all submenus are handled by the main menu. #ifdef __WINDOWS__ #ifdef __WINDOWS__ Loading @@ -224,14 +246,6 @@ void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) } } } } #endif #endif for( std::list<CUSTOM_MENU_HANDLER>::iterator it = m_handlers.begin(); it != m_handlers.end(); ++it ) { evt = (*it)( aEvent ); if( evt ) break; } // Handling non-action menu entries (e.g. items in clarification list) // Handling non-action menu entries (e.g. items in clarification list) if( !evt ) if( !evt ) Loading @@ -251,16 +265,22 @@ void CONTEXT_MENU::setTool( TOOL_INTERACTIVE* aTool ) { { m_tool = aTool; m_tool = aTool; for( unsigned i = 0; i < GetMenuItemCount(); ++i ) runOnSubmenus( boost::bind( &CONTEXT_MENU::setTool, _1, aTool ) ); { } wxMenuItem* item = FindItemByPosition( i ); if( item->IsSubMenu() ) void CONTEXT_MENU::runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent ) { { CONTEXT_MENU* menu = static_cast<CONTEXT_MENU*>( item->GetSubMenu() ); aToolEvent = m_menu_handler( aMenuEvent ); menu->setTool( aTool ); } if( !aToolEvent ) runOnSubmenus( boost::bind( &CONTEXT_MENU::runEventHandlers, _1, aMenuEvent, aToolEvent ) ); } } void CONTEXT_MENU::runOnSubmenus( boost::function<void(CONTEXT_MENU*)> aFunction ) { std::for_each( m_submenus.begin(), m_submenus.end(), aFunction ); } } Loading @@ -283,8 +303,8 @@ wxMenuItem* CONTEXT_MENU::appendCopy( const wxMenuItem* aSource ) newItem->SetSubMenu( menu ); newItem->SetSubMenu( menu ); Append( newItem ); Append( newItem ); m_toolActions.insert( menu->m_toolActions.begin(), menu->m_toolActions.end() ); m_submenus.push_back( menu ); m_handlers.insert( m_handlers.end(), menu->m_handlers.begin(), menu->m_handlers.end() ); menu->m_parent = this; } } else else { { Loading @@ -308,7 +328,9 @@ void CONTEXT_MENU::copyFrom( const CONTEXT_MENU& aMenu ) m_selected = -1; // aMenu.m_selected; m_selected = -1; // aMenu.m_selected; m_tool = aMenu.m_tool; m_tool = aMenu.m_tool; m_toolActions = aMenu.m_toolActions; m_toolActions = aMenu.m_toolActions; m_handlers = aMenu.m_handlers; m_parent = NULL; // aMenu.m_parent; m_menu_handler = aMenu.m_menu_handler; m_update_handler = aMenu.m_update_handler; // Copy all the menu entries // Copy all the menu entries for( unsigned i = 0; i < aMenu.GetMenuItemCount(); ++i ) for( unsigned i = 0; i < aMenu.GetMenuItemCount(); ++i ) Loading @@ -317,3 +339,14 @@ void CONTEXT_MENU::copyFrom( const CONTEXT_MENU& aMenu ) appendCopy( item ); appendCopy( item ); } } } } OPT_TOOL_EVENT CONTEXT_MENU::menuHandlerStub( const wxMenuEvent& ) { return OPT_TOOL_EVENT(); } void CONTEXT_MENU::updateHandlerStub() { } common/tool/tool_manager.cpp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -596,6 +596,9 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent ) // using the point where the user has invoked a context menu // using the point where the user has invoked a context menu m_viewControls->ForceCursorPosition( true, m_viewControls->GetCursorPosition() ); m_viewControls->ForceCursorPosition( true, m_viewControls->GetCursorPosition() ); // Run update handlers st->contextMenu->UpdateAll(); boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) ); boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) ); GetEditFrame()->PopupMenu( menu.get() ); GetEditFrame()->PopupMenu( menu.get() ); Loading include/tool/context_menu.h +52 −13 Original line number Original line Diff line number Diff line /* /* * This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application. * * * Copyright (C) 2013 CERN * Copyright (C) 2013-2015 CERN * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch> * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License Loading Loading @@ -47,9 +48,9 @@ public: ///> Copy constructor ///> Copy constructor CONTEXT_MENU( const CONTEXT_MENU& aMenu ); CONTEXT_MENU( const CONTEXT_MENU& aMenu ); CONTEXT_MENU& operator=( const CONTEXT_MENU& aMenu ); virtual ~CONTEXT_MENU(); virtual ~CONTEXT_MENU() {} CONTEXT_MENU& operator=( const CONTEXT_MENU& aMenu ); /** /** * Function SetTitle() * Function SetTitle() Loading @@ -64,7 +65,7 @@ public: * Assigns an icon for the entry. * Assigns an icon for the entry. * @param aIcon is the icon to be assigned. NULL is used to remove icon. * @param aIcon is the icon to be assigned. NULL is used to remove icon. */ */ void SetIcon( const BITMAP_OPAQUE* aIcon ) inline void SetIcon( const BITMAP_OPAQUE* aIcon ) { { m_icon = aIcon; m_icon = aIcon; } } Loading Loading @@ -111,21 +112,43 @@ public: * menu was dismissed. * menu was dismissed. * @return The position of selected item in the context menu. * @return The position of selected item in the context menu. */ */ int GetSelected() const inline int GetSelected() const { { return m_selected; return m_selected; } } ///> Function type to handle menu events in a custom way. /** typedef boost::function<OPT_TOOL_EVENT(const wxMenuEvent&)> CUSTOM_MENU_HANDLER; * Function UpdateAll() * Runs update handlers for the menu and its submenus. */ void UpdateAll(); typedef boost::function<OPT_TOOL_EVENT(const wxMenuEvent&)> MENU_HANDLER; typedef boost::function<void()> UPDATE_HANDLER; /** * Function SetMenuHandler() * Sets the menu event handler to another function. */ inline void SetMenuHandler( MENU_HANDLER aMenuHandler ) { m_menu_handler = aMenuHandler; } ///> Adds an event handler to the custom menu event handlers chain. /** void AppendCustomEventHandler( CUSTOM_MENU_HANDLER aHandler ) * Function SetUpdateHandler() * Sets the update handler to a different function. */ inline void SetUpdateHandler( UPDATE_HANDLER aUpdateHandler ) { { m_handlers.push_back( aHandler ); m_update_handler = aUpdateHandler; } } private: private: // Empty stubs used by the default constructor static OPT_TOOL_EVENT menuHandlerStub(const wxMenuEvent& ); static void updateHandlerStub(); /** /** * Function appendCopy * Function appendCopy * Appends a copy of wxMenuItem. * Appends a copy of wxMenuItem. Loading @@ -138,7 +161,7 @@ private: ///> Initializes handlers for events. ///> Initializes handlers for events. void setupEvents(); void setupEvents(); ///> Event handler. ///> The default menu event handler. void onMenuEvent( wxMenuEvent& aEvent ); void onMenuEvent( wxMenuEvent& aEvent ); /** /** Loading @@ -148,6 +171,13 @@ private: */ */ void setTool( TOOL_INTERACTIVE* aTool ); void setTool( TOOL_INTERACTIVE* aTool ); ///> Traverses the submenus tree looking for a submenu capable of handling a particular menu ///> event. In case it is handled, it is returned the aToolEvent parameter. void runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent ); ///> Runs a function on the menu and all its submenus. void runOnSubmenus( boost::function<void(CONTEXT_MENU*)> aFunction ); ///> Flag indicating that the menu title was set up. ///> Flag indicating that the menu title was set up. bool m_titleSet; bool m_titleSet; Loading @@ -163,12 +193,21 @@ private: ///> Associates tool actions with menu item IDs. Non-owning. ///> Associates tool actions with menu item IDs. Non-owning. std::map<int, const TOOL_ACTION*> m_toolActions; std::map<int, const TOOL_ACTION*> m_toolActions; ///> Chain of custom menu event handlers. ///> List of submenus. std::list<CUSTOM_MENU_HANDLER> m_handlers; std::list<CONTEXT_MENU*> m_submenus; ///> Parent CONTEXT_MENU. CONTEXT_MENU* m_parent; ///> Optional icon ///> Optional icon const BITMAP_OPAQUE* m_icon; const BITMAP_OPAQUE* m_icon; ///> Optional callback to translate wxMenuEvents to TOOL_EVENTs. MENU_HANDLER m_menu_handler; ///> Optional callback to update the menu state before it is displayed. UPDATE_HANDLER m_update_handler; friend class TOOL_INTERACTIVE; friend class TOOL_INTERACTIVE; }; }; Loading pcbnew/router/router_tool.cpp +2 −4 Original line number Original line Diff line number Diff line Loading @@ -96,8 +96,7 @@ public: { { m_board = NULL; m_board = NULL; SetIcon( width_track_via_xpm ); SetIcon( width_track_via_xpm ); AppendCustomEventHandler( boost::bind( &CONTEXT_TRACK_WIDTH_MENU::handleCustomEvent, SetMenuHandler( boost::bind( &CONTEXT_TRACK_WIDTH_MENU::EventHandler, this, _1 ) ); this, _1 ) ); } } void SetBoard( BOARD* aBoard ) void SetBoard( BOARD* aBoard ) Loading Loading @@ -153,8 +152,7 @@ public: } } } } protected: OPT_TOOL_EVENT EventHandler( const wxMenuEvent& aEvent ) OPT_TOOL_EVENT handleCustomEvent( const wxMenuEvent& aEvent ) { { #if ID_POPUP_PCB_SELECT_VIASIZE1 < ID_POPUP_PCB_SELECT_WIDTH1 #if ID_POPUP_PCB_SELECT_VIASIZE1 < ID_POPUP_PCB_SELECT_WIDTH1 #error You have changed event ids order, it breaks code. Check the source code for more details. #error You have changed event ids order, it breaks code. Check the source code for more details. Loading pcbnew/tools/selection_tool.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -1282,6 +1282,10 @@ bool SELECTION_TOOL::SanitizeSelection() void SELECTION_TOOL::generateMenu() void SELECTION_TOOL::generateMenu() { { // Menu has to be updated before its copy is created. Copying does not preserve subtypes of the // stored menus, so updating may not work correctly. m_menu.UpdateAll(); // Create a copy of the master context menu // Create a copy of the master context menu m_menuCopy = m_menu; m_menuCopy = m_menu; Loading Loading
common/tool/context_menu.cpp +65 −32 Original line number Original line Diff line number Diff line /* /* * This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application. * * * Copyright (C) 2013 CERN * Copyright (C) 2013-2015 CERN * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch> * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License Loading Loading @@ -31,7 +32,9 @@ #include <cassert> #include <cassert> CONTEXT_MENU::CONTEXT_MENU() : CONTEXT_MENU::CONTEXT_MENU() : m_titleSet( false ), m_selected( -1 ), m_tool( NULL ), m_icon( NULL ) m_titleSet( false ), m_selected( -1 ), m_tool( NULL ), m_parent( NULL ), m_icon( NULL ), m_menu_handler( CONTEXT_MENU::menuHandlerStub ), m_update_handler( CONTEXT_MENU::updateHandlerStub ) { { setupEvents(); setupEvents(); } } Loading @@ -44,12 +47,22 @@ CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) } } CONTEXT_MENU::~CONTEXT_MENU() { // Set parent to NULL to prevent submenus from unregistering from a notexisting object for( std::list<CONTEXT_MENU*>::iterator it = m_submenus.begin(); it != m_submenus.end(); ++it ) (*it)->m_parent = NULL; if( m_parent ) m_parent->m_submenus.remove( this ); } CONTEXT_MENU& CONTEXT_MENU::operator=( const CONTEXT_MENU& aMenu ) CONTEXT_MENU& CONTEXT_MENU::operator=( const CONTEXT_MENU& aMenu ) { { Clear(); Clear(); copyFrom( aMenu ); copyFrom( aMenu ); setupEvents(); return *this; return *this; } } Loading Loading @@ -84,11 +97,11 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle ) wxMenuItem* CONTEXT_MENU::Add( const wxString& aLabel, int aId, const BITMAP_OPAQUE* aIcon ) wxMenuItem* CONTEXT_MENU::Add( const wxString& aLabel, int aId, const BITMAP_OPAQUE* aIcon ) { { #ifdef DEBUG #ifdef DEBUG if( FindItem( aId ) != NULL ) if( FindItem( aId ) != NULL ) wxLogWarning( wxT( "Adding more than one menu entry with the same ID may result in" wxLogWarning( wxT( "Adding more than one menu entry with the same ID may result in" "undefined behaviour" ) ); "undefined behaviour" ) ); #endif #endif wxMenuItem* item = new wxMenuItem( this, aId, aLabel, wxEmptyString, wxITEM_NORMAL ); wxMenuItem* item = new wxMenuItem( this, aId, aLabel, wxEmptyString, wxITEM_NORMAL ); if( aIcon ) if( aIcon ) Loading Loading @@ -139,9 +152,7 @@ std::list<wxMenuItem*> CONTEXT_MENU::Add( CONTEXT_MENU* aMenu, const wxString& a if( aExpand ) if( aExpand ) { { unsigned int i = 0; for( unsigned int i = 0; i < aMenu->GetMenuItemCount(); ++i ) for( i = 0; i < aMenu->GetMenuItemCount(); ++i ) { { wxMenuItem* item = aMenu->FindItemByPosition( i ); wxMenuItem* item = aMenu->FindItemByPosition( i ); items.push_back( appendCopy( item ) ); items.push_back( appendCopy( item ) ); Loading @@ -162,8 +173,8 @@ std::list<wxMenuItem*> CONTEXT_MENU::Add( CONTEXT_MENU* aMenu, const wxString& a } } } } m_toolActions.insert( aMenu->m_toolActions.begin(), aMenu->m_toolActions.end() ); m_submenus.push_back( aMenu ); m_handlers.insert( m_handlers.end(), aMenu->m_handlers.begin(), aMenu->m_handlers.end() ); aMenu->m_parent = this; return items; return items; } } Loading @@ -176,13 +187,22 @@ void CONTEXT_MENU::Clear() GetMenuItems().DeleteContents( true ); GetMenuItems().DeleteContents( true ); GetMenuItems().Clear(); GetMenuItems().Clear(); m_toolActions.clear(); m_toolActions.clear(); m_handlers.clear(); GetMenuItems().DeleteContents( false ); // restore the default so destructor does not go wild GetMenuItems().DeleteContents( false ); // restore the default so destructor does not go wild m_submenus.clear(); m_parent = NULL; assert( GetMenuItemCount() == 0 ); assert( GetMenuItemCount() == 0 ); } } void CONTEXT_MENU::UpdateAll() { m_update_handler(); runOnSubmenus( boost::bind( &CONTEXT_MENU::UpdateAll, _1 ) ); } void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) { { OPT_TOOL_EVENT evt; OPT_TOOL_EVENT evt; Loading @@ -208,6 +228,8 @@ void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) } } else else { { runEventHandlers( aEvent, evt ); // Under Linux, every submenu can have a separate event handler, under // Under Linux, every submenu can have a separate event handler, under // Windows all submenus are handled by the main menu. // Windows all submenus are handled by the main menu. #ifdef __WINDOWS__ #ifdef __WINDOWS__ Loading @@ -224,14 +246,6 @@ void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent ) } } } } #endif #endif for( std::list<CUSTOM_MENU_HANDLER>::iterator it = m_handlers.begin(); it != m_handlers.end(); ++it ) { evt = (*it)( aEvent ); if( evt ) break; } // Handling non-action menu entries (e.g. items in clarification list) // Handling non-action menu entries (e.g. items in clarification list) if( !evt ) if( !evt ) Loading @@ -251,16 +265,22 @@ void CONTEXT_MENU::setTool( TOOL_INTERACTIVE* aTool ) { { m_tool = aTool; m_tool = aTool; for( unsigned i = 0; i < GetMenuItemCount(); ++i ) runOnSubmenus( boost::bind( &CONTEXT_MENU::setTool, _1, aTool ) ); { } wxMenuItem* item = FindItemByPosition( i ); if( item->IsSubMenu() ) void CONTEXT_MENU::runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent ) { { CONTEXT_MENU* menu = static_cast<CONTEXT_MENU*>( item->GetSubMenu() ); aToolEvent = m_menu_handler( aMenuEvent ); menu->setTool( aTool ); } if( !aToolEvent ) runOnSubmenus( boost::bind( &CONTEXT_MENU::runEventHandlers, _1, aMenuEvent, aToolEvent ) ); } } void CONTEXT_MENU::runOnSubmenus( boost::function<void(CONTEXT_MENU*)> aFunction ) { std::for_each( m_submenus.begin(), m_submenus.end(), aFunction ); } } Loading @@ -283,8 +303,8 @@ wxMenuItem* CONTEXT_MENU::appendCopy( const wxMenuItem* aSource ) newItem->SetSubMenu( menu ); newItem->SetSubMenu( menu ); Append( newItem ); Append( newItem ); m_toolActions.insert( menu->m_toolActions.begin(), menu->m_toolActions.end() ); m_submenus.push_back( menu ); m_handlers.insert( m_handlers.end(), menu->m_handlers.begin(), menu->m_handlers.end() ); menu->m_parent = this; } } else else { { Loading @@ -308,7 +328,9 @@ void CONTEXT_MENU::copyFrom( const CONTEXT_MENU& aMenu ) m_selected = -1; // aMenu.m_selected; m_selected = -1; // aMenu.m_selected; m_tool = aMenu.m_tool; m_tool = aMenu.m_tool; m_toolActions = aMenu.m_toolActions; m_toolActions = aMenu.m_toolActions; m_handlers = aMenu.m_handlers; m_parent = NULL; // aMenu.m_parent; m_menu_handler = aMenu.m_menu_handler; m_update_handler = aMenu.m_update_handler; // Copy all the menu entries // Copy all the menu entries for( unsigned i = 0; i < aMenu.GetMenuItemCount(); ++i ) for( unsigned i = 0; i < aMenu.GetMenuItemCount(); ++i ) Loading @@ -317,3 +339,14 @@ void CONTEXT_MENU::copyFrom( const CONTEXT_MENU& aMenu ) appendCopy( item ); appendCopy( item ); } } } } OPT_TOOL_EVENT CONTEXT_MENU::menuHandlerStub( const wxMenuEvent& ) { return OPT_TOOL_EVENT(); } void CONTEXT_MENU::updateHandlerStub() { }
common/tool/tool_manager.cpp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -596,6 +596,9 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent ) // using the point where the user has invoked a context menu // using the point where the user has invoked a context menu m_viewControls->ForceCursorPosition( true, m_viewControls->GetCursorPosition() ); m_viewControls->ForceCursorPosition( true, m_viewControls->GetCursorPosition() ); // Run update handlers st->contextMenu->UpdateAll(); boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) ); boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) ); GetEditFrame()->PopupMenu( menu.get() ); GetEditFrame()->PopupMenu( menu.get() ); Loading
include/tool/context_menu.h +52 −13 Original line number Original line Diff line number Diff line /* /* * This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application. * * * Copyright (C) 2013 CERN * Copyright (C) 2013-2015 CERN * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch> * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License Loading Loading @@ -47,9 +48,9 @@ public: ///> Copy constructor ///> Copy constructor CONTEXT_MENU( const CONTEXT_MENU& aMenu ); CONTEXT_MENU( const CONTEXT_MENU& aMenu ); CONTEXT_MENU& operator=( const CONTEXT_MENU& aMenu ); virtual ~CONTEXT_MENU(); virtual ~CONTEXT_MENU() {} CONTEXT_MENU& operator=( const CONTEXT_MENU& aMenu ); /** /** * Function SetTitle() * Function SetTitle() Loading @@ -64,7 +65,7 @@ public: * Assigns an icon for the entry. * Assigns an icon for the entry. * @param aIcon is the icon to be assigned. NULL is used to remove icon. * @param aIcon is the icon to be assigned. NULL is used to remove icon. */ */ void SetIcon( const BITMAP_OPAQUE* aIcon ) inline void SetIcon( const BITMAP_OPAQUE* aIcon ) { { m_icon = aIcon; m_icon = aIcon; } } Loading Loading @@ -111,21 +112,43 @@ public: * menu was dismissed. * menu was dismissed. * @return The position of selected item in the context menu. * @return The position of selected item in the context menu. */ */ int GetSelected() const inline int GetSelected() const { { return m_selected; return m_selected; } } ///> Function type to handle menu events in a custom way. /** typedef boost::function<OPT_TOOL_EVENT(const wxMenuEvent&)> CUSTOM_MENU_HANDLER; * Function UpdateAll() * Runs update handlers for the menu and its submenus. */ void UpdateAll(); typedef boost::function<OPT_TOOL_EVENT(const wxMenuEvent&)> MENU_HANDLER; typedef boost::function<void()> UPDATE_HANDLER; /** * Function SetMenuHandler() * Sets the menu event handler to another function. */ inline void SetMenuHandler( MENU_HANDLER aMenuHandler ) { m_menu_handler = aMenuHandler; } ///> Adds an event handler to the custom menu event handlers chain. /** void AppendCustomEventHandler( CUSTOM_MENU_HANDLER aHandler ) * Function SetUpdateHandler() * Sets the update handler to a different function. */ inline void SetUpdateHandler( UPDATE_HANDLER aUpdateHandler ) { { m_handlers.push_back( aHandler ); m_update_handler = aUpdateHandler; } } private: private: // Empty stubs used by the default constructor static OPT_TOOL_EVENT menuHandlerStub(const wxMenuEvent& ); static void updateHandlerStub(); /** /** * Function appendCopy * Function appendCopy * Appends a copy of wxMenuItem. * Appends a copy of wxMenuItem. Loading @@ -138,7 +161,7 @@ private: ///> Initializes handlers for events. ///> Initializes handlers for events. void setupEvents(); void setupEvents(); ///> Event handler. ///> The default menu event handler. void onMenuEvent( wxMenuEvent& aEvent ); void onMenuEvent( wxMenuEvent& aEvent ); /** /** Loading @@ -148,6 +171,13 @@ private: */ */ void setTool( TOOL_INTERACTIVE* aTool ); void setTool( TOOL_INTERACTIVE* aTool ); ///> Traverses the submenus tree looking for a submenu capable of handling a particular menu ///> event. In case it is handled, it is returned the aToolEvent parameter. void runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent ); ///> Runs a function on the menu and all its submenus. void runOnSubmenus( boost::function<void(CONTEXT_MENU*)> aFunction ); ///> Flag indicating that the menu title was set up. ///> Flag indicating that the menu title was set up. bool m_titleSet; bool m_titleSet; Loading @@ -163,12 +193,21 @@ private: ///> Associates tool actions with menu item IDs. Non-owning. ///> Associates tool actions with menu item IDs. Non-owning. std::map<int, const TOOL_ACTION*> m_toolActions; std::map<int, const TOOL_ACTION*> m_toolActions; ///> Chain of custom menu event handlers. ///> List of submenus. std::list<CUSTOM_MENU_HANDLER> m_handlers; std::list<CONTEXT_MENU*> m_submenus; ///> Parent CONTEXT_MENU. CONTEXT_MENU* m_parent; ///> Optional icon ///> Optional icon const BITMAP_OPAQUE* m_icon; const BITMAP_OPAQUE* m_icon; ///> Optional callback to translate wxMenuEvents to TOOL_EVENTs. MENU_HANDLER m_menu_handler; ///> Optional callback to update the menu state before it is displayed. UPDATE_HANDLER m_update_handler; friend class TOOL_INTERACTIVE; friend class TOOL_INTERACTIVE; }; }; Loading
pcbnew/router/router_tool.cpp +2 −4 Original line number Original line Diff line number Diff line Loading @@ -96,8 +96,7 @@ public: { { m_board = NULL; m_board = NULL; SetIcon( width_track_via_xpm ); SetIcon( width_track_via_xpm ); AppendCustomEventHandler( boost::bind( &CONTEXT_TRACK_WIDTH_MENU::handleCustomEvent, SetMenuHandler( boost::bind( &CONTEXT_TRACK_WIDTH_MENU::EventHandler, this, _1 ) ); this, _1 ) ); } } void SetBoard( BOARD* aBoard ) void SetBoard( BOARD* aBoard ) Loading Loading @@ -153,8 +152,7 @@ public: } } } } protected: OPT_TOOL_EVENT EventHandler( const wxMenuEvent& aEvent ) OPT_TOOL_EVENT handleCustomEvent( const wxMenuEvent& aEvent ) { { #if ID_POPUP_PCB_SELECT_VIASIZE1 < ID_POPUP_PCB_SELECT_WIDTH1 #if ID_POPUP_PCB_SELECT_VIASIZE1 < ID_POPUP_PCB_SELECT_WIDTH1 #error You have changed event ids order, it breaks code. Check the source code for more details. #error You have changed event ids order, it breaks code. Check the source code for more details. Loading
pcbnew/tools/selection_tool.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -1282,6 +1282,10 @@ bool SELECTION_TOOL::SanitizeSelection() void SELECTION_TOOL::generateMenu() void SELECTION_TOOL::generateMenu() { { // Menu has to be updated before its copy is created. Copying does not preserve subtypes of the // stored menus, so updating may not work correctly. m_menu.UpdateAll(); // Create a copy of the master context menu // Create a copy of the master context menu m_menuCopy = m_menu; m_menuCopy = m_menu; Loading