Audacity 3.2.0
Registry.h
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5Registry.h
6
7Paul Licameli split from CommandManager.h
8
9**********************************************************************/
10
11#ifndef __AUDACITY_REGISTRY__
12#define __AUDACITY_REGISTRY__
13
14#include "Prefs.h"
15
16// Define classes and functions that associate parts of the user interface
17// with path names
18namespace Registry {
19 // Items in the registry form an unordered tree, but each may also describe a
20 // desired insertion point among its peers. The request might not be honored
21 // (as when the other name is not found, or when more than one item requests
22 // the same ordering), but this is not treated as an error.
24 {
30 enum Type : int {
33 Unspecified // keep this last
34 } type{ Unspecified };
35
36 // name of some other BaseItem; significant only when type is Before or
37 // After:
39
41 OrderingHint( Type type_, const wxString &name_ = {} )
42 : type(type_), name(name_) {}
43
44 bool operator == ( const OrderingHint &other ) const
45 { return name == other.name && type == other.type; }
46
47 bool operator < ( const OrderingHint &other ) const
48 {
49 // This sorts unspecified placements later
50 return std::make_pair( type, name ) <
51 std::make_pair( other.type, other.name );
52 }
53 };
54
55 // TODO C++17: maybe use std::variant (discriminated unions) to achieve
56 // polymorphism by other means, not needing unique_ptr and dynamic_cast
57 // and using less heap.
58 // Most items in the table will be the large ones describing commands, so the
59 // waste of space in unions for separators and sub-menus should not be
60 // large.
61 struct REGISTRIES_API BaseItem {
62 // declare at least one virtual function so dynamic_cast will work
63 explicit
64 BaseItem( const Identifier &internalName )
65 : name{ internalName }
66 {}
67 virtual ~BaseItem();
68
70
72 };
73 using BaseItemPtr = std::unique_ptr<BaseItem>;
74 using BaseItemSharedPtr = std::shared_ptr<BaseItem>;
75 using BaseItemPtrs = std::vector<BaseItemPtr>;
76
77 class Visitor;
78
79
81
86 struct REGISTRIES_API IndirectItem final : BaseItem {
87 explicit IndirectItem( const BaseItemSharedPtr &ptr_ )
88 : BaseItem{ wxEmptyString }
89 , ptr{ ptr_ }
90 {}
91 ~IndirectItem() override;
92
94 };
95
97 inline std::unique_ptr<IndirectItem> Indirect(const BaseItemSharedPtr &ptr)
98 { return std::make_unique<IndirectItem>(ptr); }
99
100 // An item that computes some other item to substitute for it, each time
101 // the ComputedItem is visited
102 // The name of the substitute is significant for path calculations, but the
103 // ComputedItem's ordering hint is used if the substitute has none
104 struct REGISTRIES_API ComputedItem final : BaseItem {
105 // The type of functions that generate descriptions of items.
106 // Return type is a shared_ptr to let the function decide whether to
107 // recycle the object or rebuild it on demand each time.
108 // Return value from the factory may be null
109 template< typename VisitorType >
110 using Factory = std::function< BaseItemSharedPtr( VisitorType & ) >;
111
113
114 explicit ComputedItem( const Factory< DefaultVisitor > &factory_ )
115 : BaseItem( wxEmptyString )
116 , factory{ factory_ }
117 {}
118 ~ComputedItem() override;
119
121 };
122
123 // Common abstract base class for items that are not groups
124 struct REGISTRIES_API SingleItem : BaseItem {
125 using BaseItem::BaseItem;
126 ~SingleItem() override = 0;
127 };
128
130 struct REGISTRIES_API GroupItemBase : BaseItem {
131 using BaseItem::BaseItem;
132
135 GroupItemBase( const Identifier &internalName, BaseItemPtrs &&items_ )
136 : BaseItem{ internalName }, items{ std::move( items_ ) }
137 {}
138 GroupItemBase( const GroupItemBase& ) PROHIBITED;
139 ~GroupItemBase() override = 0;
140
142 enum Ordering {
153 };
154
156 virtual Ordering GetOrdering() const;
157
159 };
160
161 // GroupItemBase adding variadic constructor conveniences
162 template< typename VisitorType = ComputedItem::DefaultVisitor >
165 // In-line, variadic constructor that doesn't require building a vector
166 template< typename... Args >
167 GroupItem( const Identifier &internalName, Args&&... args )
168 : GroupItemBase( internalName )
169 { Append( std::forward< Args >( args )... ); }
170
171 private:
172 // nullary overload grounds the recursion
173 void Append() {}
174 // recursive overload
175 template< typename Arg, typename... Args >
176 void Append( Arg &&arg, Args&&... moreArgs )
177 {
178 // Dispatch one argument to the proper overload of AppendOne.
179 // std::forward preserves rvalue/lvalue distinction of the actual
180 // argument of the constructor call; that is, it inserts a
181 // std::move() if and only if the original argument is rvalue
182 AppendOne( std::forward<Arg>( arg ) );
183 // recur with the rest of the arguments
184 Append( std::forward<Args>(moreArgs)... );
185 };
186
187 // Move one unique_ptr to an item into our array
188 void AppendOne( BaseItemPtr&& ptr )
189 {
190 items.push_back( std::move( ptr ) );
191 }
192 // This overload allows a lambda or function pointer in the variadic
193 // argument lists without any other syntactic wrapping, and also
194 // allows implicit conversions to type Factory.
195 // (Thus, a lambda can return a unique_ptr<BaseItem> rvalue even though
196 // Factory's return type is shared_ptr, and the needed conversion is
197 // applied implicitly.)
199 {
200 auto adaptedFactory = [factory]( Registry::Visitor &visitor ){
201 return factory( dynamic_cast< VisitorType& >( visitor ) );
202 };
203 AppendOne( std::make_unique<ComputedItem>( adaptedFactory ) );
204 }
205 // This overload lets you supply a shared pointer to an item, directly
206 template<typename Subtype>
207 void AppendOne( const std::shared_ptr<Subtype> &ptr )
208 { AppendOne( std::make_unique<IndirectItem>(ptr) ); }
209 };
210
211 // The /-separated path is relative to the GroupItem supplied to
212 // RegisterItem.
213 // For instance, wxT("Transport/Cursor") to locate an item under a sub-menu
214 // of a main menu
215 struct Placement {
216 wxString path;
218
219 Placement( const wxString &path_, const OrderingHint &hint_ = {} )
220 : path( path_ ), hint( hint_ )
221 {}
222 };
223
224 // registry collects items, before consulting preferences and ordering
225 // hints, and applying the merge procedure to them.
226 // This function puts one more item into the registry.
227 // The sequence of calls to RegisterItem has no significance for
228 // determining the visitation ordering. When sequence is important, register
229 // a GroupItem.
230 REGISTRIES_API
231 void RegisterItem( GroupItemBase &registry, const Placement &placement,
232 BaseItemPtr pItem
233 );
234
236
242 template<typename Item, typename RegistryClass = Item> class RegisteredItem {
243 public:
244 RegisteredItem(std::unique_ptr<Item> pItem, const Placement &placement)
245 {
246 if (pItem)
248 RegistryClass::Registry(), placement, std::move( pItem ) );
249 }
250 };
251
252 // Define actions to be done in Visit.
253 // Default implementations do nothing
254 // The supplied path does not include the name of the item
255 class REGISTRIES_API Visitor
256 {
257 public:
258 virtual ~Visitor();
259 using Path = std::vector< Identifier >;
260 virtual void BeginGroup( GroupItemBase &item, const Path &path );
261 virtual void EndGroup( GroupItemBase &item, const Path &path );
262 virtual void Visit( SingleItem &item, const Path &path );
263 };
264
265 // Top-down visitation of all items and groups in a tree rooted in
266 // pTopItem, as merged with pRegistry.
267 // The merger of the trees is recomputed in each call, not saved.
268 // So neither given tree is modified.
269 // But there may be a side effect on preferences to remember the ordering
270 // imposed on each node of the unordered tree of registered items; each item
271 // seen in the registry for the first time is placed somehere, and that
272 // ordering should be kept the same thereafter in later runs (which may add
273 // yet other previously unknown items).
274 REGISTRIES_API void Visit(
275 Visitor &visitor,
276 BaseItem *pTopItem,
277 const GroupItemBase *pRegistry = nullptr );
278
279 // Typically a static object. Constructor initializes certain preferences
280 // if they are not present. These preferences determine an extrinsic
281 // visitation ordering for registered items. This is needed in some
282 // places that have migrated from a system of exhaustive listings, to a
283 // registry of plug-ins, and something must be done to preserve old
284 // behavior. It can be done in the central place using string literal
285 // identifiers only, not requiring static compilation or linkage dependency.
286 struct REGISTRIES_API
288 using Literal = const wxChar *;
289 using Pair = std::pair< Literal, Literal >;
290 using Pairs = std::vector< Pair >;
292 // Specifies the topmost preference section:
293 Literal root,
294 // Specifies /-separated Registry paths relative to root
295 // (these should be blank or start with / and not end with /),
296 // each with a ,-separated sequence of identifiers, which specify a
297 // desired ordering at one node of the tree:
298 Pairs pairs );
299
300 void operator () () override;
301
302 private:
305 };
306
307extern template struct GroupItem<>;
308}
309
310#endif
311
const TranslatableString name
Definition: Distortion.cpp:76
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
Generates classes whose instances register items at construction.
Definition: Registry.h:242
RegisteredItem(std::unique_ptr< Item > pItem, const Placement &placement)
Definition: Registry.h:244
std::vector< Identifier > Path
Definition: Registry.h:259
Definition: Menus.h:35
void RegisterItem(GroupItemBase &registry, const Placement &placement, BaseItemPtr pItem)
Definition: Registry.cpp:774
std::unique_ptr< BaseItem > BaseItemPtr
Definition: Registry.h:73
std::vector< BaseItemPtr > BaseItemPtrs
Definition: Registry.h:75
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItemBase *pRegistry)
Definition: Registry.cpp:737
std::unique_ptr< IndirectItem > Indirect(const BaseItemSharedPtr &ptr)
A convenience function.
Definition: Registry.h:97
std::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:74
static RegisteredToolbarFactory factory
STL namespace.
const Identifier name
Definition: Registry.h:69
OrderingHint orderingHint
Definition: Registry.h:71
BaseItem(const Identifier &internalName)
Definition: Registry.h:64
Factory< DefaultVisitor > factory
Definition: Registry.h:120
ComputedItem(const Factory< DefaultVisitor > &factory_)
Definition: Registry.h:114
std::function< BaseItemSharedPtr(VisitorType &) > Factory
Definition: Registry.h:110
Common abstract base class for items that group other items.
Definition: Registry.h:130
GroupItemBase(const GroupItemBase &) PROHIBITED
Ordering
Choose treatment of the children of the group when merging trees.
Definition: Registry.h:142
GroupItemBase(const Identifier &internalName, BaseItemPtrs &&items_)
Definition: Registry.h:135
BaseItemPtrs items
Definition: Registry.h:158
void Append(Arg &&arg, Args &&... moreArgs)
Definition: Registry.h:176
void AppendOne(const ComputedItem::Factory< VisitorType > &factory)
Definition: Registry.h:198
GroupItem(const Identifier &internalName, Args &&... args)
Definition: Registry.h:167
void AppendOne(const std::shared_ptr< Subtype > &ptr)
Definition: Registry.h:207
void AppendOne(BaseItemPtr &&ptr)
Definition: Registry.h:188
An item that delegates to another held in a shared pointer.
Definition: Registry.h:86
IndirectItem(const BaseItemSharedPtr &ptr_)
Definition: Registry.h:87
BaseItemSharedPtr ptr
Definition: Registry.h:93
enum Registry::OrderingHint::Type Unspecified
OrderingHint(Type type_, const wxString &name_={})
Definition: Registry.h:41
bool operator==(const OrderingHint &other) const
Definition: Registry.h:44
bool operator<(const OrderingHint &other) const
Definition: Registry.h:47
std::pair< Literal, Literal > Pair
Definition: Registry.h:289
OrderingHint hint
Definition: Registry.h:217
Placement(const wxString &path_, const OrderingHint &hint_={})
Definition: Registry.h:219