diff --git a/src/widgets/PopupMenuTable.cpp b/src/widgets/PopupMenuTable.cpp index 39a210332..a157ef828 100644 --- a/src/widgets/PopupMenuTable.cpp +++ b/src/widgets/PopupMenuTable.cpp @@ -92,35 +92,34 @@ void PopupMenuBuilder::DoEndGroup( Registry::GroupItem &item, const Path &path ) void PopupMenuBuilder::DoVisit( Registry::SingleItem &item, const Path &path ) { - auto connect = [this]( const PopupMenuTable::Entry *pEntry ) { - mMenu->pParent->Bind - (wxEVT_COMMAND_MENU_SELECTED, - pEntry->func, mMenu->tables.back(), pEntry->id); - }; - auto pEntry = static_cast( &item ); switch (pEntry->type) { case PopupMenuTable::Entry::Item: { mMenu->Append(pEntry->id, pEntry->caption.Translation()); - connect( pEntry ); break; } case PopupMenuTable::Entry::RadioItem: { mMenu->AppendRadioItem(pEntry->id, pEntry->caption.Translation()); - connect( pEntry ); break; } case PopupMenuTable::Entry::CheckItem: { mMenu->AppendCheckItem(pEntry->id, pEntry->caption.Translation()); - connect( pEntry ); break; } default: + wxASSERT( false ); break; } + + // This call necessary for externally registered items, else harmlessly + // redundant + pEntry->handler.InitUserData( mpUserData ); + + mMenu->pParent->Bind( + wxEVT_COMMAND_MENU_SELECTED, pEntry->func, &pEntry->handler, pEntry->id); } void PopupMenuBuilder::DoSeparator() @@ -150,7 +149,7 @@ void PopupMenuTable::Append( const TranslatableString &string, wxCommandEventFunction memFn) { mStack.back()->items.push_back( std::make_unique( - stringId, type, id, string, memFn + stringId, type, id, string, memFn, *this ) ); } @@ -182,7 +181,8 @@ void PopupMenu::DisconnectTable(PopupMenuTable *pTable) { auto pEntry = static_cast( &item ); mMenu.pParent->Unbind( wxEVT_COMMAND_MENU_SELECTED, - pEntry->func, &mTable, pEntry->id ); + pEntry->func, &pEntry->handler, pEntry->id ); + pEntry->handler.DestroyMenu(); } PopupMenuTable &mTable; @@ -191,8 +191,6 @@ void PopupMenu::DisconnectTable(PopupMenuTable *pTable) PopupMenuDestroyer visitor{ *pTable, *this }; Registry::Visit( visitor, pTable->Get( nullptr ).get() ); - - pTable->DestroyMenu(); } void PopupMenu::Disconnect() @@ -202,7 +200,7 @@ void PopupMenu::Disconnect() } } -void PopupMenuTable::InitMenu(wxMenu *) +void PopupMenuHandler::InitMenu(wxMenu *) { } diff --git a/src/widgets/PopupMenuTable.h b/src/widgets/PopupMenuTable.h index 1885d2437..0113ac97c 100644 --- a/src/widgets/PopupMenuTable.h +++ b/src/widgets/PopupMenuTable.h @@ -27,6 +27,7 @@ class wxString; #include "../Internat.h" #include "../commands/CommandManager.h" +class PopupMenuHandler; class PopupMenuTable; struct PopupMenuTableEntry : Registry::SingleItem @@ -37,16 +38,17 @@ struct PopupMenuTableEntry : Registry::SingleItem int id; TranslatableString caption; wxCommandEventFunction func; - PopupMenuTable *subTable; + PopupMenuHandler &handler; PopupMenuTableEntry( const Identifier &stringId, Type type_, int id_, const TranslatableString &caption_, - wxCommandEventFunction func_) + wxCommandEventFunction func_, PopupMenuHandler &handler_ ) : SingleItem{ stringId } , type(type_) , id(id_) , caption(caption_) , func(func_) + , handler( handler_ ) {} ~PopupMenuTableEntry() override; @@ -70,7 +72,29 @@ struct PopupMenuSection using ConcreteGroupItem< false >::ConcreteGroupItem; }; -class PopupMenuTable : public wxEvtHandler +class PopupMenuHandler : public wxEvtHandler +{ +public: + PopupMenuHandler() = default; + PopupMenuHandler( const PopupMenuHandler& ) = delete; + PopupMenuHandler& operator=( const PopupMenuHandler& ) = delete; + + // Called before the menu items are appended. + // Store context data, if needed. + // May be called more than once before the menu opens. + virtual void InitUserData(void *pUserData) = 0; + + // Called when the menu is about to pop up. + // Your chance to enable and disable items. + // Default implementation does nothing. + virtual void InitMenu(wxMenu *pMenu); + + // Called when menu is destroyed. + // May be called more than once. + virtual void DestroyMenu() = 0; +}; + +class PopupMenuTable : public PopupMenuHandler { public: using Entry = PopupMenuTableEntry; @@ -81,18 +105,6 @@ public: , mCaption{ caption } {} - // Called before the menu items are appended. - // Store user data, if needed. - virtual void InitUserData(void *pUserData) = 0; - - // Called when the menu is about to pop up. - // Your chance to enable and disable items. - // Default implementation does nothing. - virtual void InitMenu(wxMenu *pMenu); - - // Called when menu is destroyed. - virtual void DestroyMenu() = 0; - // Optional pUserData gets passed to the InitUserData routines of tables. // No memory management responsibility is assumed by this function. static std::unique_ptr BuildMenu