Fixed the issue of creating and event handling in context menus (GAL).

When creating a copy of CONTEXT_MENU, always a CONTEXT_MENU instance was
constructed, whereas an inherited type should be used. Solved with
CONTEXT_MENU::create() that has to be overridden in inheriting classes.

Event & update handlers are now virtual functions, instead of setting
the handlers with Set{Event,Update}Handler().
This commit is contained in:
Maciej Suminski 2017-01-20 18:33:11 +01:00
parent d7ed3ede72
commit 682da70a86
14 changed files with 201 additions and 177 deletions

View File

@ -1,7 +1,7 @@
/* /*
* 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-2015 CERN * Copyright (C) 2013-2017 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -30,44 +30,26 @@
#include <functional> #include <functional>
using namespace std::placeholders; using namespace std::placeholders;
#include <cassert>
CONTEXT_MENU::CONTEXT_MENU() : CONTEXT_MENU::CONTEXT_MENU() :
m_titleSet( false ), m_selected( -1 ), m_tool( NULL ), m_parent( NULL ), m_icon( NULL ), m_titleSet( false ), m_selected( -1 ), m_tool( nullptr ), m_parent( nullptr ), m_icon( nullptr )
m_menu_handler( CONTEXT_MENU::menuHandlerStub ),
m_update_handler( CONTEXT_MENU::updateHandlerStub )
{ {
setupEvents(); setupEvents();
} }
CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu )
{
copyFrom( aMenu );
setupEvents();
}
CONTEXT_MENU::~CONTEXT_MENU() CONTEXT_MENU::~CONTEXT_MENU()
{ {
// Set parent to NULL to prevent submenus from unregistering from a notexisting object // 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 ) //for( std::list<CONTEXT_MENU*>::iterator it = m_submenus.begin(); it != m_submenus.end(); ++it )
(*it)->m_parent = NULL; for( auto menu : m_submenus )
menu->m_parent = nullptr;
if( m_parent ) if( m_parent )
m_parent->m_submenus.remove( this ); m_parent->m_submenus.remove( this );
} }
CONTEXT_MENU& CONTEXT_MENU::operator=( const CONTEXT_MENU& aMenu )
{
Clear();
copyFrom( aMenu );
return *this;
}
void CONTEXT_MENU::setupEvents() void CONTEXT_MENU::setupEvents()
{ {
Connect( wxEVT_MENU_HIGHLIGHT, wxMenuEventHandler( CONTEXT_MENU::onMenuEvent ), NULL, this ); Connect( wxEVT_MENU_HIGHLIGHT, wxMenuEventHandler( CONTEXT_MENU::onMenuEvent ), NULL, this );
@ -124,14 +106,15 @@ wxMenuItem* CONTEXT_MENU::Add( const TOOL_ACTION& aAction )
m_toolActions[getMenuId( aAction )] = &aAction; m_toolActions[getMenuId( aAction )] = &aAction;
return Append( item ); wxMenuItem* i = Append( item );
return i;
} }
std::list<wxMenuItem*> CONTEXT_MENU::Add( CONTEXT_MENU* aMenu, const wxString& aLabel, bool aExpand ) std::list<wxMenuItem*> CONTEXT_MENU::Add( CONTEXT_MENU* aMenu, const wxString& aLabel, bool aExpand )
{ {
std::list<wxMenuItem*> items; std::list<wxMenuItem*> items;
CONTEXT_MENU* menuCopy = new CONTEXT_MENU( *aMenu ); CONTEXT_MENU* menuCopy = aMenu->Clone();
m_submenus.push_back( menuCopy ); m_submenus.push_back( menuCopy );
menuCopy->m_parent = this; menuCopy->m_parent = this;
@ -173,7 +156,7 @@ void CONTEXT_MENU::Clear()
m_submenus.clear(); m_submenus.clear();
m_parent = NULL; m_parent = NULL;
assert( GetMenuItemCount() == 0 ); wxASSERT( GetMenuItemCount() == 0 );
} }
@ -181,11 +164,11 @@ void CONTEXT_MENU::UpdateAll()
{ {
try try
{ {
m_update_handler(); update();
} }
catch( std::exception& e ) catch( std::exception& e )
{ {
std::cerr << "CONTEXT_MENU error running update handler: " << e.what() << std::endl; wxLogDebug( wxString::Format( "CONTEXT_MENU update handler exception: %s", e.what() ) );
} }
if( m_tool ) if( m_tool )
@ -198,15 +181,34 @@ void CONTEXT_MENU::UpdateAll()
void CONTEXT_MENU::SetTool( TOOL_INTERACTIVE* aTool ) void CONTEXT_MENU::SetTool( TOOL_INTERACTIVE* aTool )
{ {
m_tool = aTool; m_tool = aTool;
runOnSubmenus( std::bind( &CONTEXT_MENU::SetTool, _1, aTool ) ); runOnSubmenus( std::bind( &CONTEXT_MENU::SetTool, _1, aTool ) );
} }
CONTEXT_MENU* CONTEXT_MENU::Clone() const
{
CONTEXT_MENU* clone = create();
clone->Clear();
clone->copyFrom( *this );
return clone;
}
CONTEXT_MENU* CONTEXT_MENU::create() const
{
CONTEXT_MENU* menu = new CONTEXT_MENU();
wxASSERT_MSG( typeid( *this ) == typeid( *menu ),
wxString::Format( "You need to override create() method for class %s", typeid(*this).name() ) );
return menu;
}
TOOL_MANAGER* CONTEXT_MENU::getToolManager() TOOL_MANAGER* CONTEXT_MENU::getToolManager()
{ {
assert( m_tool ); wxASSERT( m_tool );
return m_tool->GetManager(); return m_tool ? m_tool->GetManager() : nullptr;
} }
@ -269,23 +271,22 @@ void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent )
} }
else else
{ {
runEventHandlers( aEvent, evt );
// Under Linux, every submenu can have a separate event handler, under
// Windows all submenus are handled by the main menu.
#ifdef __WINDOWS__ #ifdef __WINDOWS__
if( !evt ) if( !evt )
{ {
// Try to find the submenu which holds the selected item // Try to find the submenu which holds the selected item
wxMenu* menu = NULL; wxMenu* menu = nullptr;
FindItem( m_selected, &menu ); FindItem( m_selected, &menu );
if( menu && menu != this ) if( menu && menu != this )
{ {
menu->ProcessEvent( aEvent ); CONTEXT_MENU* cxmenu = static_cast<CONTEXT_MENU*>( menu );
return; evt = cxmenu->eventHandler( aEvent );
} }
} }
#else
if( !evt )
runEventHandlers( aEvent, evt );
#endif #endif
// Handling non-action menu entries (e.g. items in clarification list) // Handling non-action menu entries (e.g. items in clarification list)
@ -294,17 +295,20 @@ void CONTEXT_MENU::onMenuEvent( wxMenuEvent& aEvent )
} }
} }
assert( m_tool ); // without tool & tool manager we cannot handle events wxASSERT( m_tool ); // without tool & tool manager we cannot handle events
// forward the action/update event to the TOOL_MANAGER // forward the action/update event to the TOOL_MANAGER
if( evt && m_tool ) if( evt && m_tool )
{
//aEvent.StopPropagation();
m_tool->GetManager()->ProcessEvent( *evt ); m_tool->GetManager()->ProcessEvent( *evt );
}
} }
void CONTEXT_MENU::runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent ) void CONTEXT_MENU::runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent )
{ {
aToolEvent = m_menu_handler( aMenuEvent ); aToolEvent = eventHandler( aMenuEvent );
if( !aToolEvent ) if( !aToolEvent )
runOnSubmenus( std::bind( &CONTEXT_MENU::runEventHandlers, _1, aMenuEvent, aToolEvent ) ); runOnSubmenus( std::bind( &CONTEXT_MENU::runEventHandlers, _1, aMenuEvent, aToolEvent ) );
@ -319,7 +323,25 @@ void CONTEXT_MENU::runOnSubmenus( std::function<void(CONTEXT_MENU*)> aFunction )
} }
catch( std::exception& e ) catch( std::exception& e )
{ {
std::cerr << "CONTEXT_MENU runOnSubmenus error: " << e.what() << std::endl; wxLogDebug( wxString::Format( "CONTEXT_MENU runOnSubmenus exception: %s", e.what() ) );
}
}
void CONTEXT_MENU::copyFrom( const CONTEXT_MENU& aMenu )
{
m_icon = aMenu.m_icon;
m_titleSet = aMenu.m_titleSet;
m_selected = -1; // aMenu.m_selected;
m_tool = aMenu.m_tool;
m_toolActions = aMenu.m_toolActions;
m_parent = NULL; // aMenu.m_parent;
// Copy all the menu entries
for( int i = 0; i < (int) aMenu.GetMenuItemCount(); ++i )
{
wxMenuItem* item = aMenu.FindItemByPosition( i );
appendCopy( item );
} }
} }
@ -334,59 +356,25 @@ wxMenuItem* CONTEXT_MENU::appendCopy( const wxMenuItem* aSource )
if( aSource->IsSubMenu() ) if( aSource->IsSubMenu() )
{ {
#ifdef DEBUG CONTEXT_MENU* menu = dynamic_cast<CONTEXT_MENU*>( aSource->GetSubMenu() );
// Submenus of a CONTEXT_MENU are supposed to be CONTEXT_MENUs as well wxASSERT_MSG( menu, "Submenus are expected to be a CONTEXT_MENU" );
assert( dynamic_cast<CONTEXT_MENU*>( aSource->GetSubMenu() ) );
#endif
CONTEXT_MENU* menu = new CONTEXT_MENU( static_cast<const CONTEXT_MENU&>( *aSource->GetSubMenu() ) ); if( menu )
newItem->SetSubMenu( menu ); {
Append( newItem ); CONTEXT_MENU* menuCopy = menu->Clone();
newItem->SetSubMenu( menuCopy );
m_submenus.push_back( menu ); m_submenus.push_back( menuCopy );
menu->m_parent = this; menuCopy->m_parent = this; // TODO remove m_parent
}
} }
else
{
Append( newItem );
newItem->SetKind( aSource->GetKind() );
newItem->SetHelp( aSource->GetHelp() );
newItem->Enable( aSource->IsEnabled() );
if( aSource->IsCheckable() ) // wxMenuItem has to be added before enabling/disabling or checking
newItem->Check( aSource->IsChecked() ); Append( newItem );
}
if( aSource->IsCheckable() )
newItem->Check( aSource->IsChecked() );
newItem->Enable( aSource->IsEnabled() );
return newItem; return newItem;
} }
void CONTEXT_MENU::copyFrom( const CONTEXT_MENU& aMenu )
{
m_icon = aMenu.m_icon;
m_titleSet = aMenu.m_titleSet;
m_selected = -1; // aMenu.m_selected;
m_tool = aMenu.m_tool;
m_toolActions = aMenu.m_toolActions;
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
for( int i = 0; i < (int) aMenu.GetMenuItemCount(); ++i )
{
wxMenuItem* item = aMenu.FindItemByPosition( i );
appendCopy( item );
}
}
OPT_TOOL_EVENT CONTEXT_MENU::menuHandlerStub( const wxMenuEvent& )
{
return boost::none;
}
void CONTEXT_MENU::updateHandlerStub()
{
}

View File

@ -28,7 +28,6 @@
#include <stack> #include <stack>
#include <algorithm> #include <algorithm>
#include <boost/scoped_ptr.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/range/adaptor/map.hpp> #include <boost/range/adaptor/map.hpp>
@ -631,10 +630,11 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent )
VECTOR2D cursorPos = m_viewControls->GetCursorPosition(); VECTOR2D cursorPos = m_viewControls->GetCursorPosition();
m_viewControls->ForceCursorPosition( true, m_viewControls->GetCursorPosition() ); m_viewControls->ForceCursorPosition( true, m_viewControls->GetCursorPosition() );
// Run update handlers // Display a copy of menu
m->UpdateAll(); std::unique_ptr<CONTEXT_MENU> menu( m->Clone() );
boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *m ) ); // Run update handlers on the created copy
menu->UpdateAll();
GetEditFrame()->PopupMenu( menu.get() ); GetEditFrame()->PopupMenu( menu.get() );
// If nothing was chosen from the context menu, we must notify the tool as well // If nothing was chosen from the context menu, we must notify the tool as well
@ -645,12 +645,12 @@ void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent )
dispatchInternal( evt ); dispatchInternal( evt );
} }
// Notify the tools that menu has been closed
TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CLOSED ); TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CLOSED );
evt.SetParameter( m ); evt.SetParameter( m );
dispatchInternal( evt ); dispatchInternal( evt );
m_viewControls->ForceCursorPosition( forcedCursor, cursorPos ); m_viewControls->ForceCursorPosition( forcedCursor, cursorPos );
break; break;
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* 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-2015 CERN * Copyright (C) 2013-2017 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -47,12 +47,10 @@ public:
///> Default constructor ///> Default constructor
CONTEXT_MENU(); CONTEXT_MENU();
///> Copy constructor
CONTEXT_MENU( const CONTEXT_MENU& aMenu );
virtual ~CONTEXT_MENU(); virtual ~CONTEXT_MENU();
CONTEXT_MENU& operator=( const CONTEXT_MENU& aMenu ); CONTEXT_MENU( const CONTEXT_MENU& aMenu ) = delete;
CONTEXT_MENU& operator=( const CONTEXT_MENU& aMenu ) = delete;
/** /**
* Function SetTitle() * Function SetTitle()
@ -125,28 +123,6 @@ public:
*/ */
void UpdateAll(); void UpdateAll();
// Helper typedefs
typedef std::function<OPT_TOOL_EVENT(const wxMenuEvent&)> MENU_HANDLER;
typedef std::function<void()> UPDATE_HANDLER;
/**
* Function SetMenuHandler()
* Sets the menu event handler to another function.
*/
inline void SetMenuHandler( MENU_HANDLER aMenuHandler )
{
m_menu_handler = aMenuHandler;
}
/**
* Function SetUpdateHandler()
* Sets the update handler to a different function.
*/
inline void SetUpdateHandler( UPDATE_HANDLER aUpdateHandler )
{
m_update_handler = aUpdateHandler;
}
/** /**
* Function SetTool() * Function SetTool()
* Sets a tool that is the creator of the menu. * Sets a tool that is the creator of the menu.
@ -154,7 +130,15 @@ public:
*/ */
void SetTool( TOOL_INTERACTIVE* aTool ); void SetTool( TOOL_INTERACTIVE* aTool );
/**
* Creates a deep, recursive copy of this CONTEXT_MENU.
*/
CONTEXT_MENU* Clone() const;
protected: protected:
///> Returns an instance of this class. It has to be overridden in inheriting classes.
virtual CONTEXT_MENU* create() const;
///> Returns an instance of TOOL_MANAGER class. ///> Returns an instance of TOOL_MANAGER class.
TOOL_MANAGER* getToolManager(); TOOL_MANAGER* getToolManager();
@ -164,20 +148,36 @@ protected:
return aAction.GetId() + ACTION_ID; return aAction.GetId() + ACTION_ID;
} }
private: /**
// Empty stubs used by the default constructor * Update menu state stub. It is called before a menu is shown, in order to update its state.
static OPT_TOOL_EVENT menuHandlerStub(const wxMenuEvent& ); * Here you can tick current settings, enable/disable entries, etc.
static void updateHandlerStub(); */
virtual void update()
{
}
/**
* Event handler stub. It should be used if you want to generate a TOOL_EVENT from a wxMenuEvent.
* It will be called when a menu entry is clicked.
*/
virtual OPT_TOOL_EVENT eventHandler( const wxMenuEvent& )
{
return OPT_TOOL_EVENT();
}
/**
* Copies another menus data to this instance. Old entries are preserved, and ones form aMenu
* are copied.
*/
void copyFrom( const CONTEXT_MENU& aMenu );
private:
/** /**
* Function appendCopy * Function appendCopy
* Appends a copy of wxMenuItem. * Appends a copy of wxMenuItem.
*/ */
wxMenuItem* appendCopy( const wxMenuItem* aSource ); wxMenuItem* appendCopy( const wxMenuItem* aSource );
///> Common part of copy constructor and assignment operator.
void copyFrom( const CONTEXT_MENU& aMenu );
///> Initializes handlers for events. ///> Initializes handlers for events.
void setupEvents(); void setupEvents();
@ -204,7 +204,7 @@ private:
TOOL_INTERACTIVE* m_tool; TOOL_INTERACTIVE* m_tool;
///> Menu items with ID higher than that are considered TOOL_ACTIONs ///> Menu items with ID higher than that are considered TOOL_ACTIONs
static const int ACTION_ID = 30000; static const int ACTION_ID = 2000;
///> 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;
@ -218,12 +218,6 @@ private:
///> 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;
}; };

View File

@ -33,6 +33,7 @@
#if BOOST_VERSION < 106100 #if BOOST_VERSION < 106100
#include <boost/context/fcontext.hpp> #include <boost/context/fcontext.hpp>
#include <memory>
#else #else
#include <boost/context/execution_context.hpp> #include <boost/context/execution_context.hpp>
#include <boost/context/protected_fixedsize_stack.hpp> #include <boost/context/protected_fixedsize_stack.hpp>

View File

@ -73,10 +73,10 @@ LENGTH_TUNER_TOOL::LENGTH_TUNER_TOOL() :
} }
class TUNER_TOOL_MENU: public CONTEXT_MENU class TUNER_TOOL_MENU : public CONTEXT_MENU
{ {
public: public:
TUNER_TOOL_MENU( BOARD* aBoard ) TUNER_TOOL_MENU()
{ {
SetTitle( _( "Length Tuner" ) ); SetTitle( _( "Length Tuner" ) );
@ -91,6 +91,12 @@ public:
Add( ACT_AmplDecrease ); Add( ACT_AmplDecrease );
Add( ACT_Settings ); Add( ACT_Settings );
} }
private:
CONTEXT_MENU* create() const override
{
return new TUNER_TOOL_MENU();
}
}; };
@ -242,7 +248,7 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
m_ctls->ShowCursor( true ); m_ctls->ShowCursor( true );
m_frame->UndoRedoBlock( true ); m_frame->UndoRedoBlock( true );
std::unique_ptr<TUNER_TOOL_MENU> ctxMenu( new TUNER_TOOL_MENU( m_board ) ); std::unique_ptr<TUNER_TOOL_MENU> ctxMenu( new TUNER_TOOL_MENU );
SetContextMenu( ctxMenu.get() ); SetContextMenu( ctxMenu.get() );
// Main loop: keep receiving events // Main loop: keep receiving events

View File

@ -117,19 +117,21 @@ ROUTER_TOOL::ROUTER_TOOL() :
} }
class CONTEXT_TRACK_WIDTH_MENU: public CONTEXT_TRACK_VIA_SIZE_MENU class TRACK_WIDTH_MENU: public TRACK_VIA_SIZE_MENU
{ {
public: public:
CONTEXT_TRACK_WIDTH_MENU() TRACK_WIDTH_MENU( const BOARD* aBoard )
: CONTEXT_TRACK_VIA_SIZE_MENU( true, true ), m_board( NULL ) : TRACK_VIA_SIZE_MENU( true, true )
{ {
SetMenuHandler( std::bind( &CONTEXT_TRACK_WIDTH_MENU::EventHandler, this, _1 ) ); SetBoard( aBoard );
} }
void SetBoard( BOARD* aBoard ) void SetBoard( const BOARD* aBoard )
{ {
m_board = aBoard; m_board = aBoard;
Clear();
Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Custom size" ), Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Custom size" ),
wxEmptyString, wxITEM_CHECK ); wxEmptyString, wxITEM_CHECK );
@ -145,7 +147,13 @@ public:
AppendSizes( aBoard ); AppendSizes( aBoard );
} }
OPT_TOOL_EVENT EventHandler( const wxMenuEvent& aEvent ) protected:
CONTEXT_MENU* create() const override
{
return new TRACK_WIDTH_MENU( m_board );
}
OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
{ {
BOARD_DESIGN_SETTINGS &bds = m_board->GetDesignSettings(); BOARD_DESIGN_SETTINGS &bds = m_board->GetDesignSettings();
int id = aEvent.GetId(); int id = aEvent.GetId();
@ -198,20 +206,20 @@ public:
bds.UseCustomTrackViaSize( useCustomTrackViaSize ); bds.UseCustomTrackViaSize( useCustomTrackViaSize );
} }
return OPT_TOOL_EVENT( COMMON_ACTIONS::trackViaSizeChanged.MakeEvent() ); return OPT_TOOL_EVENT( COMMON_ACTIONS::trackViaSizeChanged.MakeEvent() );
} }
private: private:
BOARD* m_board; const BOARD* m_board;
}; };
class ROUTER_TOOL_MENU: public CONTEXT_MENU class ROUTER_TOOL_MENU : public CONTEXT_MENU
{ {
public: public:
ROUTER_TOOL_MENU( BOARD* aBoard, PCB_EDIT_FRAME& frame, PNS::ROUTER_MODE aMode ) : ROUTER_TOOL_MENU( const BOARD* aBoard, PCB_EDIT_FRAME& aFrame, PNS::ROUTER_MODE aMode ) :
m_zoomMenu( &frame ), m_gridMenu( &frame ) m_board( aBoard ), m_frame( aFrame ), m_mode( aMode ),
m_widthMenu( aBoard ), m_zoomMenu( &aFrame ), m_gridMenu( &aFrame )
{ {
SetTitle( _( "Interactive Router" ) ); SetTitle( _( "Interactive Router" ) );
Add( ACT_NewTrack ); Add( ACT_NewTrack );
@ -242,7 +250,15 @@ public:
} }
private: private:
CONTEXT_TRACK_WIDTH_MENU m_widthMenu; CONTEXT_MENU* create() const override
{
return new ROUTER_TOOL_MENU( m_board, m_frame, m_mode );
}
const BOARD* m_board;
PCB_EDIT_FRAME& m_frame;
PNS::ROUTER_MODE m_mode;
TRACK_WIDTH_MENU m_widthMenu;
ZOOM_MENU m_zoomMenu; ZOOM_MENU m_zoomMenu;
GRID_MENU m_gridMenu; GRID_MENU m_gridMenu;
}; };
@ -253,6 +269,7 @@ ROUTER_TOOL::~ROUTER_TOOL()
m_savedSettings.Save( GetSettings() ); m_savedSettings.Save( GetSettings() );
} }
bool ROUTER_TOOL::Init() bool ROUTER_TOOL::Init()
{ {
m_savedSettings.Load( GetSettings() ); m_savedSettings.Load( GetSettings() );
@ -724,9 +741,6 @@ int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
m_savedSettings = m_router->Settings(); m_savedSettings = m_router->Settings();
m_savedSizes = m_router->Sizes(); m_savedSizes = m_router->Sizes();
// Disable the context menu before it is destroyed
SetContextMenu( NULL, CMENU_OFF );
return 0; return 0;
} }

View File

@ -72,7 +72,6 @@ CONTEXT_MENU* CONDITIONAL_MENU::Generate( SELECTION& aSelection )
break; break;
case ENTRY::MENU: case ENTRY::MENU:
it->Menu()->UpdateAll();
m_menu->Add( it->Menu(), it->Label(), it->Expand() ); m_menu->Add( it->Menu(), it->Label(), it->Expand() );
break; break;

View File

@ -37,8 +37,6 @@ GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
BASE_SCREEN* screen = aParent->GetScreen(); BASE_SCREEN* screen = aParent->GetScreen();
SetIcon( grid_select_xpm ); SetIcon( grid_select_xpm );
SetMenuHandler( std::bind( &GRID_MENU::EventHandler, this, _1 ) );
SetUpdateHandler( std::bind( &GRID_MENU::Update, this ) );
wxArrayString gridsList; wxArrayString gridsList;
screen->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES ); screen->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES );
@ -51,7 +49,7 @@ GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
} }
OPT_TOOL_EVENT GRID_MENU::EventHandler( const wxMenuEvent& aEvent ) OPT_TOOL_EVENT GRID_MENU::eventHandler( const wxMenuEvent& aEvent )
{ {
OPT_TOOL_EVENT event( COMMON_ACTIONS::gridPreset.MakeEvent() ); OPT_TOOL_EVENT event( COMMON_ACTIONS::gridPreset.MakeEvent() );
long idx = aEvent.GetId() - ID_POPUP_GRID_SELECT - 1; long idx = aEvent.GetId() - ID_POPUP_GRID_SELECT - 1;
@ -61,10 +59,11 @@ OPT_TOOL_EVENT GRID_MENU::EventHandler( const wxMenuEvent& aEvent )
} }
void GRID_MENU::Update() void GRID_MENU::update()
{ {
for( unsigned int i = 0; i < GetMenuItemCount(); ++i ) for( unsigned int i = 0; i < GetMenuItemCount(); ++i )
Check( ID_POPUP_GRID_SELECT + 1 + i, false ); Check( ID_POPUP_GRID_SELECT + 1 + i, false );
// Check the current grid size
Check( m_parent->GetScreen()->GetGridCmdId(), true ); Check( m_parent->GetScreen()->GetGridCmdId(), true );
} }

View File

@ -34,10 +34,15 @@ class GRID_MENU : public CONTEXT_MENU
public: public:
GRID_MENU( EDA_DRAW_FRAME* aParent ); GRID_MENU( EDA_DRAW_FRAME* aParent );
OPT_TOOL_EVENT EventHandler( const wxMenuEvent& aEvent );
void Update();
private: private:
CONTEXT_MENU* create() const override
{
return new GRID_MENU( m_parent );
}
OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override;
void update() override;
EDA_DRAW_FRAME* m_parent; EDA_DRAW_FRAME* m_parent;
}; };

View File

@ -60,7 +60,6 @@ public:
ZONE_CONTEXT_MENU() ZONE_CONTEXT_MENU()
{ {
SetIcon( add_zone_xpm ); SetIcon( add_zone_xpm );
SetUpdateHandler( std::bind( &ZONE_CONTEXT_MENU::update, this ) );
Add( COMMON_ACTIONS::zoneFill ); Add( COMMON_ACTIONS::zoneFill );
Add( COMMON_ACTIONS::zoneFillAll ); Add( COMMON_ACTIONS::zoneFillAll );
Add( COMMON_ACTIONS::zoneUnfill ); Add( COMMON_ACTIONS::zoneUnfill );
@ -68,8 +67,14 @@ public:
Add( COMMON_ACTIONS::zoneMerge ); Add( COMMON_ACTIONS::zoneMerge );
} }
protected:
CONTEXT_MENU* create() const override
{
return new ZONE_CONTEXT_MENU();
}
private: private:
void update() void update() override
{ {
SELECTION_TOOL* selTool = getToolManager()->GetTool<SELECTION_TOOL>(); SELECTION_TOOL* selTool = getToolManager()->GetTool<SELECTION_TOOL>();
@ -100,6 +105,11 @@ public:
Add( COMMON_ACTIONS::unlock ); Add( COMMON_ACTIONS::unlock );
Add( COMMON_ACTIONS::toggleLock ); Add( COMMON_ACTIONS::toggleLock );
} }
CONTEXT_MENU* create() const override
{
return new LOCK_CONTEXT_MENU();
}
}; };

View File

@ -24,14 +24,14 @@
#include <class_board.h> #include <class_board.h>
#include <pcbnew_id.h> #include <pcbnew_id.h>
CONTEXT_TRACK_VIA_SIZE_MENU::CONTEXT_TRACK_VIA_SIZE_MENU( bool aTrackSizes, bool aViaSizes ) : TRACK_VIA_SIZE_MENU::TRACK_VIA_SIZE_MENU( bool aTrackSizes, bool aViaSizes ) :
m_tracks( aTrackSizes ), m_vias( aViaSizes ) m_tracks( aTrackSizes ), m_vias( aViaSizes )
{ {
SetIcon( width_track_via_xpm ); SetIcon( width_track_via_xpm );
} }
void CONTEXT_TRACK_VIA_SIZE_MENU::AppendSizes( const BOARD* aBoard ) void TRACK_VIA_SIZE_MENU::AppendSizes( const BOARD* aBoard )
{ {
wxString msg; wxString msg;

View File

@ -27,7 +27,7 @@ class BOARD;
* @brief Context menu that displays track and/or via sizes basing on the board design settings * @brief Context menu that displays track and/or via sizes basing on the board design settings
* of a BOARD object. * of a BOARD object.
*/ */
class CONTEXT_TRACK_VIA_SIZE_MENU: public CONTEXT_MENU class TRACK_VIA_SIZE_MENU : public CONTEXT_MENU
{ {
public: public:
/** /**
@ -35,9 +35,9 @@ public:
* @param aTrackSizes decides if the context menu should contain track sizes. * @param aTrackSizes decides if the context menu should contain track sizes.
* @param aTrackSizes decides if the context menu should contain via sizes. * @param aTrackSizes decides if the context menu should contain via sizes.
*/ */
CONTEXT_TRACK_VIA_SIZE_MENU( bool aTrackSizes, bool aViaSizes ); TRACK_VIA_SIZE_MENU( bool aTrackSizes, bool aViaSizes );
virtual ~CONTEXT_TRACK_VIA_SIZE_MENU() {} virtual ~TRACK_VIA_SIZE_MENU() {}
/** /**
* Function AppendSizes() * Function AppendSizes()
@ -46,6 +46,11 @@ public:
*/ */
virtual void AppendSizes( const BOARD* aBoard ); virtual void AppendSizes( const BOARD* aBoard );
virtual CONTEXT_MENU* create() const override
{
return new TRACK_VIA_SIZE_MENU( m_tracks, m_vias );
}
protected: protected:
///> Whether the generated menu should contain track sizes. ///> Whether the generated menu should contain track sizes.
bool m_tracks; bool m_tracks;

View File

@ -34,10 +34,7 @@ using namespace std::placeholders;
ZOOM_MENU::ZOOM_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent ) ZOOM_MENU::ZOOM_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
{ {
BASE_SCREEN* screen = aParent->GetScreen(); BASE_SCREEN* screen = aParent->GetScreen();
SetIcon( zoom_selection_xpm ); SetIcon( zoom_selection_xpm );
SetMenuHandler( std::bind( &ZOOM_MENU::EventHandler, this, _1 ) );
SetUpdateHandler( std::bind( &ZOOM_MENU::Update, this ) );
//int zoom = screen->GetZoom(); //int zoom = screen->GetZoom();
int maxZoomIds = std::min( ID_POPUP_ZOOM_LEVEL_END - ID_POPUP_ZOOM_LEVEL_START, int maxZoomIds = std::min( ID_POPUP_ZOOM_LEVEL_END - ID_POPUP_ZOOM_LEVEL_START,
@ -52,7 +49,7 @@ ZOOM_MENU::ZOOM_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
} }
OPT_TOOL_EVENT ZOOM_MENU::EventHandler( const wxMenuEvent& aEvent ) OPT_TOOL_EVENT ZOOM_MENU::eventHandler( const wxMenuEvent& aEvent )
{ {
OPT_TOOL_EVENT event( COMMON_ACTIONS::zoomPreset.MakeEvent() ); OPT_TOOL_EVENT event( COMMON_ACTIONS::zoomPreset.MakeEvent() );
long idx = aEvent.GetId() - ID_POPUP_ZOOM_LEVEL_START; long idx = aEvent.GetId() - ID_POPUP_ZOOM_LEVEL_START;
@ -62,11 +59,12 @@ OPT_TOOL_EVENT ZOOM_MENU::EventHandler( const wxMenuEvent& aEvent )
} }
void ZOOM_MENU::Update() void ZOOM_MENU::update()
{ {
double zoom = m_parent->GetScreen()->GetZoom(); double zoom = m_parent->GetScreen()->GetZoom();
const std::vector<double>& zoomList = m_parent->GetScreen()->m_ZoomList; const std::vector<double>& zoomList = m_parent->GetScreen()->m_ZoomList;
// Check the current zoom
for( unsigned int i = 0; i < GetMenuItemCount(); ++i ) for( unsigned int i = 0; i < GetMenuItemCount(); ++i )
Check( ID_POPUP_ZOOM_LEVEL_START + i, std::fabs( zoomList[i] - zoom ) < 1e-6 ); Check( ID_POPUP_ZOOM_LEVEL_START + i, std::fabs( zoomList[i] - zoom ) < 1e-6 );
} }

View File

@ -35,8 +35,13 @@ public:
ZOOM_MENU( EDA_DRAW_FRAME* aParent ); ZOOM_MENU( EDA_DRAW_FRAME* aParent );
private: private:
OPT_TOOL_EVENT EventHandler( const wxMenuEvent& aEvent ); CONTEXT_MENU* create() const override
void Update(); {
return new ZOOM_MENU( m_parent );
}
OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override;
void update() override;
EDA_DRAW_FRAME* m_parent; EDA_DRAW_FRAME* m_parent;
}; };