mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-19 17:40:15 +02:00
... it's the more modern way, and does better type checking, without the dubious casts of pointers-to-member-functions.
97 lines
2.6 KiB
C++
97 lines
2.6 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
PopupMenuTable.cpp
|
|
|
|
Paul Licameli split from TrackPanel.cpp
|
|
|
|
**********************************************************************/
|
|
|
|
#include "../Audacity.h"
|
|
#include "PopupMenuTable.h"
|
|
|
|
PopupMenuTable::Menu::~Menu()
|
|
{
|
|
// Event connections between the parent window and the singleton table
|
|
// object must be broken when this menu is destroyed.
|
|
Disconnect();
|
|
}
|
|
|
|
void PopupMenuTable::Menu::Extend(PopupMenuTable *pTable)
|
|
{
|
|
auto connect = [&]( const PopupMenuTable::Entry *pEntry ) {
|
|
this->pParent->Bind
|
|
(wxEVT_COMMAND_MENU_SELECTED,
|
|
pEntry->func, pTable, pEntry->id);
|
|
};
|
|
|
|
for (const PopupMenuTable::Entry *pEntry = &*pTable->Get().begin();
|
|
pEntry->IsValid(); ++pEntry) {
|
|
switch (pEntry->type) {
|
|
case PopupMenuTable::Entry::Item:
|
|
{
|
|
this->Append(pEntry->id, pEntry->caption);
|
|
connect( pEntry );
|
|
break;
|
|
}
|
|
case PopupMenuTable::Entry::RadioItem:
|
|
{
|
|
this->AppendRadioItem(pEntry->id, pEntry->caption);
|
|
connect( pEntry );
|
|
break;
|
|
}
|
|
case PopupMenuTable::Entry::CheckItem:
|
|
{
|
|
this->AppendCheckItem(pEntry->id, pEntry->caption);
|
|
connect( pEntry );
|
|
break;
|
|
}
|
|
case PopupMenuTable::Entry::Separator:
|
|
this->AppendSeparator();
|
|
break;
|
|
case PopupMenuTable::Entry::SubMenu:
|
|
{
|
|
const auto subTable = pEntry->subTable;
|
|
auto subMenu = BuildMenu( this->pParent, subTable, pUserData );
|
|
this->AppendSubMenu( subMenu.release(), pEntry->caption );
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
pTable->InitMenu(this, pUserData);
|
|
}
|
|
|
|
void PopupMenuTable::Menu::DisconnectTable(PopupMenuTable *pTable)
|
|
{
|
|
for (const PopupMenuTable::Entry *pEntry = &*pTable->Get().begin();
|
|
pEntry->IsValid(); ++pEntry) {
|
|
if ( pEntry->IsItem() )
|
|
pParent->Unbind( wxEVT_COMMAND_MENU_SELECTED,
|
|
pEntry->func, pTable, pEntry->id );
|
|
else if ( pEntry->IsSubMenu() )
|
|
// recur
|
|
DisconnectTable(pEntry->subTable);
|
|
}
|
|
|
|
pTable->DestroyMenu();
|
|
}
|
|
|
|
void PopupMenuTable::Menu::Disconnect()
|
|
{
|
|
for ( auto pTable : tables )
|
|
DisconnectTable(pTable);
|
|
}
|
|
|
|
// static
|
|
std::unique_ptr<PopupMenuTable::Menu> PopupMenuTable::BuildMenu
|
|
( wxEvtHandler *pParent, PopupMenuTable *pTable, void *pUserData )
|
|
{
|
|
// Rebuild as needed each time. That makes it safe in case of language change.
|
|
std::unique_ptr<Menu> theMenu{ safenew Menu( pParent, pUserData ) };
|
|
theMenu->Extend(pTable);
|
|
return std::move( theMenu );
|
|
}
|