Audacity 3.2.0
PopupMenuTable.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5PopupMenuTable.cpp
6
7Paul Licameli split from TrackPanel.cpp
8
9**********************************************************************/
10
11
12#include "PopupMenuTable.h"
13#include "widgets/BasicMenu.h"
15
17{}
18
20{}
21
23 const TranslatableString &caption_, PopupMenuTable &table_ )
24 : ConcreteGroupItem< false >{ stringId }
25 , WholeMenu{ caption_.empty() }
26 , caption{ caption_ }
27 , table{ table_ }
28{
29}
30
31PopupMenu::~PopupMenu() = default;
32
33namespace {
34struct PopupMenuImpl : PopupMenu, wxMenu
35{
36 PopupMenuImpl(void *pUserData_)
37 : pUserData{ pUserData_ } {}
38
39 ~PopupMenuImpl() override;
40
41 void Popup( wxWindow &window, const wxPoint &pos ) override;
42
43 void Extend(PopupMenuTable *pTable);
44
45 void *pUserData;
46};
47
49public:
50 explicit
51 PopupMenuBuilder( PopupMenuTable &table, PopupMenuImpl &menu, void *pUserData )
52 : PopupMenuVisitor{ table }
53 , mMenu{ &menu }
54 , mRoot{ mMenu }
55 , mpUserData{ pUserData }
56 {}
57
58 void DoBeginGroup( Registry::GroupItem &item, const Path &path ) override;
59 void DoEndGroup( Registry::GroupItem &item, const Path &path ) override;
60 void DoVisit( Registry::SingleItem &item, const Path &path ) override;
61 void DoSeparator() override;
62
63 std::vector< std::unique_ptr<PopupMenuImpl> > mMenus;
65 void *const mpUserData;
66};
67
68void PopupMenuBuilder::DoBeginGroup( Registry::GroupItem &item, const Path &path )
69{
70 if ( auto pItem = dynamic_cast<PopupSubMenu*>(&item) ) {
71 if ( !pItem->caption.empty() ) {
72 auto newMenu =
73 std::make_unique<PopupMenuImpl>( mMenu->pUserData );
74 mMenu = newMenu.get();
75 mMenus.push_back( std::move( newMenu ) );
76 }
77 }
78}
79
80void PopupMenuBuilder::DoEndGroup( Registry::GroupItem &item, const Path &path )
81{
82 if ( auto pItem = dynamic_cast<PopupSubMenu*>(&item) ) {
83 if ( !pItem->caption.empty() ) {
84 auto subMenu = std::move( mMenus.back() );
85 mMenus.pop_back();
86 mMenu = mMenus.empty() ? mRoot : mMenus.back().get();
87 mMenu->AppendSubMenu( subMenu.release(), pItem->caption.Translation());
88 }
89 }
90}
91
92void PopupMenuBuilder::DoVisit( Registry::SingleItem &item, const Path &path )
93{
94 auto pEntry = static_cast<PopupMenuTableEntry*>( &item );
95 switch (pEntry->type) {
97 {
98 mMenu->Append(pEntry->id, pEntry->caption.Translation());
99 break;
100 }
102 {
103 mMenu->AppendRadioItem(pEntry->id, pEntry->caption.Translation());
104 break;
105 }
107 {
108 mMenu->AppendCheckItem(pEntry->id, pEntry->caption.Translation());
109 break;
110 }
111 default:
112 wxASSERT( false );
113 break;
114 }
115
116 // This call necessary for externally registered items, else harmlessly
117 // redundant
118 pEntry->handler.InitUserData( mpUserData );
119
120 if ( pEntry->init )
121 pEntry->init( pEntry->handler, *mMenu, pEntry->id );
122
123 mMenu->Bind(
124 wxEVT_COMMAND_MENU_SELECTED, pEntry->func, &pEntry->handler, pEntry->id);
125}
126
127void PopupMenuBuilder::DoSeparator()
128{
129 mMenu->AppendSeparator();
130}
131
132PopupMenuImpl::~PopupMenuImpl()
133{
134 // Event connections between the parent window and the singleton table
135 // object must be broken when this menu is destroyed.
136 Disconnect();
137}
138
139void PopupMenuImpl::Popup( wxWindow &window, const wxPoint &pos )
140{
141 BasicMenu::Handle{ this }.Popup(
142 wxWidgetsWindowPlacement{ &window }, { pos.x, pos.y }
143 );
144}
145}
146
148{
149 auto &theMenu = dynamic_cast<PopupMenuImpl&>(menu);
150
151 PopupMenuBuilder visitor{ table, theMenu, theMenu.pUserData };
153 visitor, table.Get( theMenu.pUserData ).get(), table.GetRegistry() );
154}
155
157 const Registry::Placement &placement, Registry::BaseItemPtr pItem )
158{
159 Registry::RegisterItem( *mRegistry, placement, std::move( pItem ) );
160}
161
163{
164 mStack.back()->items.push_back( std::move( pItem ) );
165}
166
168 const Identifier &stringId, PopupMenuTableEntry::Type type, int id,
169 const TranslatableString &string, wxCommandEventFunction memFn,
171{
172 Append( std::make_unique<Entry>(
173 stringId, type, id, string, memFn, *this, init ) );
174}
175
177{
178 auto uSection = std::make_unique< PopupMenuSection >( name );
179 auto section = uSection.get();
180 mStack.back()->items.push_back( std::move( uSection ) );
181 mStack.push_back( section );
182}
183
185{
186 mStack.pop_back();
187}
188
189// static
190std::unique_ptr< PopupMenu > PopupMenuTable::BuildMenu(
191 PopupMenuTable *pTable, void *pUserData )
192{
193 // Rebuild as needed each time. That makes it safe in case of language change.
194 auto theMenu = std::make_unique<PopupMenuImpl>( pUserData );
195 ExtendMenu( *theMenu, *pTable );
196 return theMenu;
197}
198
Abstractions of menus and their items.
const TranslatableString name
Definition: Distortion.cpp:74
void Popup(const BasicUI::WindowPlacement &window, const Point &pos={})
Display the menu at pos, invoke at most one action, then hide it.
Definition: BasicMenu.cpp:209
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
bool empty() const
Definition: Identifier.h:61
virtual ~PopupMenu()
static void ExtendMenu(PopupMenu &menu, PopupMenuTable &otherTable)
std::vector< Registry::GroupItem * > mStack
void BeginSection(const Identifier &name)
void Append(Registry::BaseItemPtr pItem)
static std::unique_ptr< PopupMenu > BuildMenu(PopupMenuTable *pTable, void *pUserData=NULL)
void RegisterItem(const Registry::Placement &placement, Registry::BaseItemPtr pItem)
std::unique_ptr< Registry::GroupItem > mRegistry
const std::shared_ptr< Registry::GroupItem > & Get(void *pUserData)
const Registry::GroupItem * GetRegistry() const
std::vector< Identifier > Path
Definition: Registry.h:245
Holds a msgid for the translation catalog; may also bind format arguments.
PopupMenuBuilder(PopupMenuTable &table, PopupMenuImpl &menu, void *pUserData)
std::vector< std::unique_ptr< PopupMenuImpl > > mMenus
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItem *pRegistry)
Definition: Registry.cpp:713
std::unique_ptr< BaseItem > BaseItemPtr
Definition: Registry.h:71
void RegisterItem(GroupItem &registry, const Placement &placement, BaseItemPtr pItem)
Definition: Registry.cpp:750
filesystem::path Path
Type
@ Item
@ CheckItem
@ RadioItem
~PopupMenuTableEntry() override
std::function< void(PopupMenuHandler &handler, wxMenu &menu, int id) > InitFunction
~PopupSubMenu() override
PopupSubMenu(const Identifier &stringId, const TranslatableString &caption_, PopupMenuTable &table)
Window placement information for wxWidgetsBasicUI can be constructed from a wxWindow pointer.