Audacity  3.0.3
Registry.h
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 Registry.h
6 
7 Paul 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
18 namespace 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.
23  struct OrderingHint
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 AUDACITY_DLL_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 AUDACITY_DLL_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 AUDACITY_DLL_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 AUDACITY_DLL_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 AUDACITY_DLL_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  {
212  ~TransparentGroupItem() override {}
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  AUDACITY_DLL_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 AUDACITY_DLL_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  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 AUDACITY_DLL_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 
Registry::TransparentGroupItem
Definition: Registry.h:210
Registry::SingleItem
Definition: Registry.h:120
Registry::Placement::path
wxString path
Definition: Registry.h:220
Registry::OrderingHint::End
@ End
Definition: Registry.h:30
Registry
Definition: Menus.h:35
Registry::GroupItem::GroupItem
GroupItem(const Identifier &internalName, BaseItemPtrs &&items_)
Definition: Registry.h:131
Registry::InlineGroupItem::Append
void Append(Arg &&arg, Args &&... moreArgs)
Definition: Registry.h:159
Registry::OrderingHint::operator==
bool operator==(const OrderingHint &other) const
Definition: Registry.h:42
Registry::InlineGroupItem::AppendOne
void AppendOne(BaseItemPtr &&ptr)
Definition: Registry.h:171
Registry::SharedItem::ptr
BaseItemSharedPtr ptr
Definition: Registry.h:89
Registry::OrderingPreferenceInitializer::Pair
std::pair< Literal, Literal > Pair
Definition: Registry.h:275
Registry::InlineGroupItem::AppendOne
void AppendOne(const std::shared_ptr< Subtype > &ptr)
Definition: Registry.h:190
Registry::OrderingPreferenceInitializer::mPairs
Pairs mPairs
Definition: Registry.h:289
Registry::ConcreteGroupItem::~ConcreteGroupItem
~ConcreteGroupItem()
Definition: Registry.h:200
Registry::Shared
std::unique_ptr< SharedItem > Shared(const BaseItemSharedPtr &ptr)
Definition: Registry.h:93
Registry::ComputedItem::factory
Factory< DefaultVisitor > factory
Definition: Registry.h:116
Registry::OrderingHint::After
@ After
Definition: Registry.h:29
Registry::OrderingPreferenceInitializer::Pairs
std::vector< Pair > Pairs
Definition: Registry.h:276
Registry::OrderingHint::OrderingHint
OrderingHint(Type type_, const wxString &name_={})
Definition: Registry.h:39
Registry::Placement
Definition: Registry.h:219
Registry::OrderingPreferenceInitializer::Literal
const wxChar * Literal
Definition: Registry.h:274
Registry::OrderingHint::Type
Type
Definition: Registry.h:28
Registry::BaseItem::orderingHint
OrderingHint orderingHint
Definition: Registry.h:69
Identifier
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
Registry::BaseItem::name
const Identifier name
Definition: Registry.h:67
Registry::ComputedItem::DefaultVisitor
Visitor DefaultVisitor
Definition: Registry.h:108
Registry::Visitor
Definition: Registry.h:242
Registry::Visit
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItem *pRegistry)
Definition: Registry.cpp:713
Registry::ComputedItem::ComputedItem
ComputedItem(const Factory< DefaultVisitor > &factory_)
Definition: Registry.h:110
Registry::OrderingHint::Begin
@ Begin
Definition: Registry.h:30
Registry::BaseItemPtr
std::unique_ptr< BaseItem > BaseItemPtr
Definition: Registry.h:71
factory
static RegisteredToolbarFactory factory
Definition: ControlToolBar.cpp:806
Registry::InlineGroupItem::AppendOne
void AppendOne(const ComputedItem::Factory< VisitorType > &factory)
Definition: Registry.h:181
Registry::Visitor::Path
std::vector< Identifier > Path
Definition: Registry.h:245
Registry::BaseItemSharedPtr
std::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:72
Registry::Placement::hint
OrderingHint hint
Definition: Registry.h:221
Registry::ComputedItem::Factory
std::function< BaseItemSharedPtr(VisitorType &) > Factory
Definition: Registry.h:106
name
const TranslatableString name
Definition: Distortion.cpp:98
Registry::OrderingHint::Before
@ Before
Definition: Registry.h:29
Registry::GroupItem::Transparent
virtual bool Transparent() const =0
Registry::InlineGroupItem::InlineGroupItem
InlineGroupItem(const Identifier &internalName, Args &&... args)
Definition: Registry.h:150
Registry::TransparentGroupItem::~TransparentGroupItem
~TransparentGroupItem() override
Definition: Registry.h:212
Registry::BaseItem::BaseItem
BaseItem(const Identifier &internalName)
Definition: Registry.h:62
Registry::OrderingHint::operator<
bool operator<(const OrderingHint &other) const
Definition: Registry.h:45
Registry::OrderingHint
Definition: Registry.h:24
Registry::Placement::Placement
Placement(const wxString &path_, const OrderingHint &hint_={})
Definition: Registry.h:223
Registry::BaseItemPtrs
std::vector< BaseItemPtr > BaseItemPtrs
Definition: Registry.h:73
Registry::OrderingPreferenceInitializer::mRoot
Literal mRoot
Definition: Registry.h:290
Registry::ConcreteGroupItem
Definition: Registry.h:198
Registry::SharedItem::SharedItem
SharedItem(const BaseItemSharedPtr &ptr_)
Definition: Registry.h:83
Registry::InlineGroupItem::Append
void Append()
Definition: Registry.h:156
Registry::GroupItem
Definition: Registry.h:126
Registry::OrderingHint::Unspecified
enum Registry::OrderingHint::Type Unspecified
Prefs.h
Registry::RegisterItem
void RegisterItem(GroupItem &registry, const Placement &placement, BaseItemPtr pItem)
Definition: Registry.cpp:750
Registry::BaseItem
Definition: Registry.h:59
Registry::ComputedItem
Definition: Registry.h:100
Registry::GroupItem::items
BaseItemPtrs items
Definition: Registry.h:141
Registry::InlineGroupItem
Definition: Registry.h:146
PreferenceInitializer
Definition: Prefs.h:429
Registry::ConcreteGroupItem::Transparent
bool Transparent() const override
Definition: Registry.h:201
Registry::OrderingHint::name
Identifier name
Definition: Registry.h:36
Registry::SharedItem
Definition: Registry.h:82
Registry::OrderingHint::OrderingHint
OrderingHint()
Definition: Registry.h:38
Registry::OrderingPreferenceInitializer
Definition: Registry.h:273