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 {
25 // The default Unspecified hint is just like End, except that in case the
26 // item is delegated to (by a SharedItem, ComputedItem, or nameless
27 // transparent group), the delegating item's hint will be used instead
28 enum Type : int {
31 Unspecified // keep this last
32 } type{ Unspecified };
33
34 // name of some other BaseItem; significant only when type is Before or
35 // After:
37
39 OrderingHint( Type type_, const wxString &name_ = {} )
40 : type(type_), name(name_) {}
41
42 bool operator == ( const OrderingHint &other ) const
43 { return name == other.name && type == other.type; }
44
45 bool operator < ( const OrderingHint &other ) const
46 {
47 // This sorts unspecified placements later
48 return std::make_pair( type, name ) <
49 std::make_pair( other.type, other.name );
50 }
51 };
52
53 // TODO C++17: maybe use std::variant (discriminated unions) to achieve
54 // polymorphism by other means, not needing unique_ptr and dynamic_cast
55 // and using less heap.
56 // Most items in the table will be the large ones describing commands, so the
57 // waste of space in unions for separators and sub-menus should not be
58 // large.
59 struct REGISTRIES_API BaseItem {
60 // declare at least one virtual function so dynamic_cast will work
61 explicit
62 BaseItem( const Identifier &internalName )
63 : name{ internalName }
64 {}
65 virtual ~BaseItem();
66
68
70 };
71 using BaseItemPtr = std::unique_ptr<BaseItem>;
72 using BaseItemSharedPtr = std::shared_ptr<BaseItem>;
73 using BaseItemPtrs = std::vector<BaseItemPtr>;
74
75 class Visitor;
76
77
78 // An item that delegates to another held in a shared pointer; this allows
79 // static tables of items to be computed once and reused
80 // The name of the delegate is significant for path calculations, but the
81 // SharedItem's ordering hint is used if the delegate has none
82 struct REGISTRIES_API SharedItem final : BaseItem {
83 explicit SharedItem( const BaseItemSharedPtr &ptr_ )
84 : BaseItem{ wxEmptyString }
85 , ptr{ ptr_ }
86 {}
87 ~SharedItem() override;
88
90 };
91
92 // A convenience function
93 inline std::unique_ptr<SharedItem> Shared( const BaseItemSharedPtr &ptr )
94 { return std::make_unique<SharedItem>( ptr ); }
95
96 // An item that computes some other item to substitute for it, each time
97 // the ComputedItem is visited
98 // The name of the substitute is significant for path calculations, but the
99 // ComputedItem's ordering hint is used if the substitute has none
100 struct REGISTRIES_API ComputedItem final : BaseItem {
101 // The type of functions that generate descriptions of items.
102 // Return type is a shared_ptr to let the function decide whether to
103 // recycle the object or rebuild it on demand each time.
104 // Return value from the factory may be null
105 template< typename VisitorType >
106 using Factory = std::function< BaseItemSharedPtr( VisitorType & ) >;
107
109
110 explicit ComputedItem( const Factory< DefaultVisitor > &factory_ )
111 : BaseItem( wxEmptyString )
112 , factory{ factory_ }
113 {}
114 ~ComputedItem() override;
115
117 };
118
119 // Common abstract base class for items that are not groups
120 struct REGISTRIES_API SingleItem : BaseItem {
121 using BaseItem::BaseItem;
122 ~SingleItem() override = 0;
123 };
124
125 // Common abstract base class for items that group other items
126 struct REGISTRIES_API GroupItem : BaseItem {
127 using BaseItem::BaseItem;
128
129 // Construction from an internal name and a previously built-up
130 // vector of pointers
131 GroupItem( const Identifier &internalName, BaseItemPtrs &&items_ )
132 : BaseItem{ internalName }, items{ std::move( items_ ) }
133 {}
134 GroupItem( const GroupItem& ) PROHIBITED;
135 ~GroupItem() override = 0;
136
137 // Whether the item is non-significant for path naming
138 // when it also has an empty name
139 virtual bool Transparent() const = 0;
140
142 };
143
144 // GroupItem adding variadic constructor conveniences
145 template< typename VisitorType = ComputedItem::DefaultVisitor >
148 // In-line, variadic constructor that doesn't require building a vector
149 template< typename... Args >
150 InlineGroupItem( const Identifier &internalName, Args&&... args )
151 : GroupItem( internalName )
152 { Append( std::forward< Args >( args )... ); }
153
154 private:
155 // nullary overload grounds the recursion
156 void Append() {}
157 // recursive overload
158 template< typename Arg, typename... Args >
159 void Append( Arg &&arg, Args&&... moreArgs )
160 {
161 // Dispatch one argument to the proper overload of AppendOne.
162 // std::forward preserves rvalue/lvalue distinction of the actual
163 // argument of the constructor call; that is, it inserts a
164 // std::move() if and only if the original argument is rvalue
165 AppendOne( std::forward<Arg>( arg ) );
166 // recur with the rest of the arguments
167 Append( std::forward<Args>(moreArgs)... );
168 };
169
170 // Move one unique_ptr to an item into our array
171 void AppendOne( BaseItemPtr&& ptr )
172 {
173 items.push_back( std::move( ptr ) );
174 }
175 // This overload allows a lambda or function pointer in the variadic
176 // argument lists without any other syntactic wrapping, and also
177 // allows implicit conversions to type Factory.
178 // (Thus, a lambda can return a unique_ptr<BaseItem> rvalue even though
179 // Factory's return type is shared_ptr, and the needed conversion is
180 // applied implicitly.)
182 {
183 auto adaptedFactory = [factory]( Registry::Visitor &visitor ){
184 return factory( dynamic_cast< VisitorType& >( visitor ) );
185 };
186 AppendOne( std::make_unique<ComputedItem>( adaptedFactory ) );
187 }
188 // This overload lets you supply a shared pointer to an item, directly
189 template<typename Subtype>
190 void AppendOne( const std::shared_ptr<Subtype> &ptr )
191 { AppendOne( std::make_unique<SharedItem>(ptr) ); }
192 };
193
194 // Inline group item also specifying transparency
195 template< bool transparent,
196 typename VisitorType = ComputedItem::DefaultVisitor >
197 struct ConcreteGroupItem : InlineGroupItem< VisitorType >
198 {
201 bool Transparent() const override { return transparent; }
202 };
203
204 // Concrete subclass of GroupItem that adds nothing else
205 // TransparentGroupItem with an empty name is transparent to item path calculations
206 // and propagates its ordering hint if subordinates don't specify hints
207 // and it does specify one
208 template< typename VisitorType = ComputedItem::DefaultVisitor >
209 struct TransparentGroupItem final : ConcreteGroupItem< true, VisitorType >
210 {
213 };
214
215 // The /-separated path is relative to the GroupItem supplied to
216 // RegisterItem.
217 // For instance, wxT("Transport/Cursor") to locate an item under a sub-menu
218 // of a main menu
219 struct Placement {
220 wxString path;
222
223 Placement( const wxString &path_, const OrderingHint &hint_ = {} )
224 : path( path_ ), hint( hint_ )
225 {}
226 };
227
228 // registry collects items, before consulting preferences and ordering
229 // hints, and applying the merge procedure to them.
230 // This function puts one more item into the registry.
231 // The sequence of calls to RegisterItem has no significance for
232 // determining the visitation ordering. When sequence is important, register
233 // a GroupItem.
234 REGISTRIES_API
235 void RegisterItem( GroupItem &registry, const Placement &placement,
236 BaseItemPtr pItem );
237
238 // Define actions to be done in Visit.
239 // Default implementations do nothing
240 // The supplied path does not include the name of the item
241 class REGISTRIES_API Visitor
242 {
243 public:
244 virtual ~Visitor();
245 using Path = std::vector< Identifier >;
246 virtual void BeginGroup( GroupItem &item, const Path &path );
247 virtual void EndGroup( GroupItem &item, const Path &path );
248 virtual void Visit( SingleItem &item, const Path &path );
249 };
250
251 // Top-down visitation of all items and groups in a tree rooted in
252 // pTopItem, as merged with pRegistry.
253 // The merger of the trees is recomputed in each call, not saved.
254 // So neither given tree is modified.
255 // But there may be a side effect on preferences to remember the ordering
256 // imposed on each node of the unordered tree of registered items; each item
257 // seen in the registry for the first time is placed somehere, and that
258 // ordering should be kept the same thereafter in later runs (which may add
259 // yet other previously unknown items).
260 REGISTRIES_API void Visit(
261 Visitor &visitor,
262 BaseItem *pTopItem,
263 const GroupItem *pRegistry = nullptr );
264
265 // Typically a static object. Constructor initializes certain preferences
266 // if they are not present. These preferences determine an extrinsic
267 // visitation ordering for registered items. This is needed in some
268 // places that have migrated from a system of exhaustive listings, to a
269 // registry of plug-ins, and something must be done to preserve old
270 // behavior. It can be done in the central place using string literal
271 // identifiers only, not requiring static compilation or linkage dependency.
272 struct REGISTRIES_API
274 using Literal = const wxChar *;
275 using Pair = std::pair< Literal, Literal >;
276 using Pairs = std::vector< Pair >;
278 // Specifies the topmost preference section:
279 Literal root,
280 // Specifies /-separated Registry paths relative to root
281 // (these should be blank or start with / and not end with /),
282 // each with a ,-separated sequence of identifiers, which specify a
283 // desired ordering at one node of the tree:
284 Pairs pairs );
285
286 void operator () () override;
287
288 private:
291 };
292}
293
294#endif
295
static RegisteredToolbarFactory factory
const TranslatableString name
Definition: Distortion.cpp:82
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
std::vector< Identifier > Path
Definition: Registry.h:245
Definition: Menus.h:36
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItem *pRegistry)
Definition: Registry.cpp:713
std::unique_ptr< BaseItem > BaseItemPtr
Definition: Registry.h:71
std::vector< BaseItemPtr > BaseItemPtrs
Definition: Registry.h:73
std::unique_ptr< SharedItem > Shared(const BaseItemSharedPtr &ptr)
Definition: Registry.h:93
std::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:72
void RegisterItem(GroupItem &registry, const Placement &placement, BaseItemPtr pItem)
Definition: Registry.cpp:750
STL namespace.
const Identifier name
Definition: Registry.h:67
OrderingHint orderingHint
Definition: Registry.h:69
BaseItem(const Identifier &internalName)
Definition: Registry.h:62
Factory< DefaultVisitor > factory
Definition: Registry.h:116
ComputedItem(const Factory< DefaultVisitor > &factory_)
Definition: Registry.h:110
std::function< BaseItemSharedPtr(VisitorType &) > Factory
Definition: Registry.h:106
bool Transparent() const override
Definition: Registry.h:201
virtual bool Transparent() const =0
GroupItem(const GroupItem &) PROHIBITED
GroupItem(const Identifier &internalName, BaseItemPtrs &&items_)
Definition: Registry.h:131
BaseItemPtrs items
Definition: Registry.h:141
void AppendOne(const std::shared_ptr< Subtype > &ptr)
Definition: Registry.h:190
void Append(Arg &&arg, Args &&... moreArgs)
Definition: Registry.h:159
InlineGroupItem(const Identifier &internalName, Args &&... args)
Definition: Registry.h:150
void AppendOne(const ComputedItem::Factory< VisitorType > &factory)
Definition: Registry.h:181
void AppendOne(BaseItemPtr &&ptr)
Definition: Registry.h:171
enum Registry::OrderingHint::Type Unspecified
OrderingHint(Type type_, const wxString &name_={})
Definition: Registry.h:39
bool operator==(const OrderingHint &other) const
Definition: Registry.h:42
bool operator<(const OrderingHint &other) const
Definition: Registry.h:45
std::pair< Literal, Literal > Pair
Definition: Registry.h:275
OrderingHint hint
Definition: Registry.h:221
Placement(const wxString &path_, const OrderingHint &hint_={})
Definition: Registry.h:223
BaseItemSharedPtr ptr
Definition: Registry.h:89
SharedItem(const BaseItemSharedPtr &ptr_)
Definition: Registry.h:83