mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-25 08:38:39 +02:00
Improve registry visitation procedure so it doesn't require a project...
... though the specific visitations for Menu items (the only ones that exist now) still do require a project, to construct the visitor.
This commit is contained in:
commit
c44f2cf755
@ -110,18 +110,8 @@ ComputedItem::~ComputedItem() {}
|
|||||||
|
|
||||||
SingleItem::~SingleItem() {}
|
SingleItem::~SingleItem() {}
|
||||||
|
|
||||||
GroupItem::GroupItem( const wxString &internalName, BaseItemPtrs &&items_ )
|
|
||||||
: BaseItem{ internalName }, items{ std::move( items_ ) }
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void GroupItem::AppendOne( BaseItemPtr&& ptr )
|
|
||||||
{
|
|
||||||
items.push_back( std::move( ptr ) );
|
|
||||||
}
|
|
||||||
GroupItem::~GroupItem() {}
|
GroupItem::~GroupItem() {}
|
||||||
|
|
||||||
TransparentGroupItem::~TransparentGroupItem() {}
|
|
||||||
|
|
||||||
Visitor::~Visitor(){}
|
Visitor::~Visitor(){}
|
||||||
void Visitor::BeginGroup(GroupItem &, const Path &) {}
|
void Visitor::BeginGroup(GroupItem &, const Path &) {}
|
||||||
void Visitor::EndGroup(GroupItem &, const Path &) {}
|
void Visitor::EndGroup(GroupItem &, const Path &) {}
|
||||||
@ -133,7 +123,8 @@ namespace MenuTable {
|
|||||||
|
|
||||||
MenuItem::MenuItem( const wxString &internalName,
|
MenuItem::MenuItem( const wxString &internalName,
|
||||||
const TranslatableString &title_, BaseItemPtrs &&items_ )
|
const TranslatableString &title_, BaseItemPtrs &&items_ )
|
||||||
: GroupItem{ internalName, std::move( items_ ) }, title{ title_ }
|
: ConcreteGroupItem< false, MenuVisitor >{
|
||||||
|
internalName, std::move( items_ ) }, title{ title_ }
|
||||||
{
|
{
|
||||||
wxASSERT( !title.empty() );
|
wxASSERT( !title.empty() );
|
||||||
}
|
}
|
||||||
@ -141,7 +132,8 @@ MenuItem::~MenuItem() {}
|
|||||||
|
|
||||||
ConditionalGroupItem::ConditionalGroupItem(
|
ConditionalGroupItem::ConditionalGroupItem(
|
||||||
const wxString &internalName, Condition condition_, BaseItemPtrs &&items_ )
|
const wxString &internalName, Condition condition_, BaseItemPtrs &&items_ )
|
||||||
: GroupItem{ internalName, std::move( items_ ) }, condition{ condition_ }
|
: ConcreteGroupItem< false, MenuVisitor >{
|
||||||
|
internalName, std::move( items_ ) }, condition{ condition_ }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ConditionalGroupItem::~ConditionalGroupItem() {}
|
ConditionalGroupItem::~ConditionalGroupItem() {}
|
||||||
@ -203,15 +195,15 @@ struct CollectedItems
|
|||||||
// alternate as the entire tree is recursively visited.
|
// alternate as the entire tree is recursively visited.
|
||||||
|
|
||||||
// forward declaration for mutually recursive functions
|
// forward declaration for mutually recursive functions
|
||||||
void CollectItem( AudacityProject &project,
|
void CollectItem( Registry::Visitor &visitor,
|
||||||
CollectedItems &collection, BaseItem *Item );
|
CollectedItems &collection, BaseItem *Item );
|
||||||
void CollectItems( AudacityProject &project,
|
void CollectItems( Registry::Visitor &visitor,
|
||||||
CollectedItems &collection, const BaseItemPtrs &items )
|
CollectedItems &collection, const BaseItemPtrs &items )
|
||||||
{
|
{
|
||||||
for ( auto &item : items )
|
for ( auto &item : items )
|
||||||
CollectItem( project, collection, item.get() );
|
CollectItem( visitor, collection, item.get() );
|
||||||
}
|
}
|
||||||
void CollectItem( AudacityProject &project,
|
void CollectItem( Registry::Visitor &visitor,
|
||||||
CollectedItems &collection, BaseItem *pItem )
|
CollectedItems &collection, BaseItem *pItem )
|
||||||
{
|
{
|
||||||
if (!pItem)
|
if (!pItem)
|
||||||
@ -222,25 +214,25 @@ void CollectItem( AudacityProject &project,
|
|||||||
dynamic_cast<SharedItem*>( pItem )) {
|
dynamic_cast<SharedItem*>( pItem )) {
|
||||||
auto &delegate = pShared->ptr;
|
auto &delegate = pShared->ptr;
|
||||||
// recursion
|
// recursion
|
||||||
CollectItem( project, collection, delegate.get() );
|
CollectItem( visitor, collection, delegate.get() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (const auto pComputed =
|
if (const auto pComputed =
|
||||||
dynamic_cast<ComputedItem*>( pItem )) {
|
dynamic_cast<ComputedItem*>( pItem )) {
|
||||||
auto result = pComputed->factory( project );
|
auto result = pComputed->factory( visitor );
|
||||||
if (result) {
|
if (result) {
|
||||||
// Guarantee long enough lifetime of the result
|
// Guarantee long enough lifetime of the result
|
||||||
collection.computedItems.push_back( result );
|
collection.computedItems.push_back( result );
|
||||||
// recursion
|
// recursion
|
||||||
CollectItem( project, collection, result.get() );
|
CollectItem( visitor, collection, result.get() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (auto pGroup = dynamic_cast<GroupItem*>(pItem)) {
|
if (auto pGroup = dynamic_cast<GroupItem*>(pItem)) {
|
||||||
if (dynamic_cast<TransparentGroupItem*>(pItem) && pItem->name.empty())
|
if (pGroup->Transparent() && pItem->name.empty())
|
||||||
// nameless grouping item is transparent to path calculations
|
// nameless grouping item is transparent to path calculations
|
||||||
// recursion
|
// recursion
|
||||||
CollectItems( project, collection, pGroup->items );
|
CollectItems( visitor, collection, pGroup->items );
|
||||||
else
|
else
|
||||||
// all other group items
|
// all other group items
|
||||||
collection.items.push_back( pItem );
|
collection.items.push_back( pItem );
|
||||||
@ -256,29 +248,26 @@ using Path = std::vector< Identifier >;
|
|||||||
|
|
||||||
// forward declaration for mutually recursive functions
|
// forward declaration for mutually recursive functions
|
||||||
void VisitItem(
|
void VisitItem(
|
||||||
Registry::Visitor &visitor,
|
Registry::Visitor &visitor, CollectedItems &collection,
|
||||||
AudacityProject &project, CollectedItems &collection,
|
|
||||||
Path &path, BaseItem *pItem );
|
Path &path, BaseItem *pItem );
|
||||||
void VisitItems(
|
void VisitItems(
|
||||||
Registry::Visitor &visitor,
|
Registry::Visitor &visitor, CollectedItems &collection,
|
||||||
AudacityProject &project, CollectedItems &collection,
|
|
||||||
Path &path, GroupItem *pGroup )
|
Path &path, GroupItem *pGroup )
|
||||||
{
|
{
|
||||||
// Make a new collection for this subtree, sharing the memo cache
|
// Make a new collection for this subtree, sharing the memo cache
|
||||||
CollectedItems newCollection{ {}, collection.computedItems };
|
CollectedItems newCollection{ {}, collection.computedItems };
|
||||||
|
|
||||||
// Gather items at this level
|
// Gather items at this level
|
||||||
CollectItems( project, newCollection, pGroup->items );
|
CollectItems( visitor, newCollection, pGroup->items );
|
||||||
|
|
||||||
// Now visit them
|
// Now visit them
|
||||||
path.push_back( pGroup->name );
|
path.push_back( pGroup->name );
|
||||||
for ( const auto &pSubItem : newCollection.items )
|
for ( const auto &pSubItem : newCollection.items )
|
||||||
VisitItem( visitor, project, collection, path, pSubItem );
|
VisitItem( visitor, collection, path, pSubItem );
|
||||||
path.pop_back();
|
path.pop_back();
|
||||||
}
|
}
|
||||||
void VisitItem(
|
void VisitItem(
|
||||||
Registry::Visitor &visitor,
|
Registry::Visitor &visitor, CollectedItems &collection,
|
||||||
AudacityProject &project, CollectedItems &collection,
|
|
||||||
Path &path, BaseItem *pItem )
|
Path &path, BaseItem *pItem )
|
||||||
{
|
{
|
||||||
if (!pItem)
|
if (!pItem)
|
||||||
@ -293,7 +282,7 @@ void VisitItem(
|
|||||||
dynamic_cast<GroupItem*>( pItem )) {
|
dynamic_cast<GroupItem*>( pItem )) {
|
||||||
visitor.BeginGroup( *pGroup, path );
|
visitor.BeginGroup( *pGroup, path );
|
||||||
// recursion
|
// recursion
|
||||||
VisitItems( visitor, project, collection, path, pGroup );
|
VisitItems( visitor, collection, path, pGroup );
|
||||||
visitor.EndGroup( *pGroup, path );
|
visitor.EndGroup( *pGroup, path );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -304,14 +293,12 @@ void VisitItem(
|
|||||||
|
|
||||||
namespace Registry {
|
namespace Registry {
|
||||||
|
|
||||||
void Visit(
|
void Visit( Visitor &visitor, BaseItem *pTopItem )
|
||||||
Visitor &visitor, AudacityProject &project,
|
|
||||||
BaseItem *pTopItem )
|
|
||||||
{
|
{
|
||||||
std::vector< BaseItemSharedPtr > computedItems;
|
std::vector< BaseItemSharedPtr > computedItems;
|
||||||
CollectedItems collection{ {}, computedItems };
|
CollectedItems collection{ {}, computedItems };
|
||||||
Path emptyPath;
|
Path emptyPath;
|
||||||
VisitItem( visitor, project, collection, emptyPath, pTopItem );
|
VisitItem( visitor, collection, emptyPath, pTopItem );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -362,10 +349,10 @@ static const auto menuTree = MenuTable::Items( MenuPathStart
|
|||||||
);
|
);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct MenuItemVisitor : Registry::Visitor
|
struct MenuItemVisitor : MenuVisitor
|
||||||
{
|
{
|
||||||
MenuItemVisitor( AudacityProject &proj, CommandManager &man )
|
MenuItemVisitor( AudacityProject &proj, CommandManager &man )
|
||||||
: project(proj), manager( man ) {}
|
: MenuVisitor(proj), manager( man ) {}
|
||||||
|
|
||||||
void BeginGroup( GroupItem &item, const Path& ) override
|
void BeginGroup( GroupItem &item, const Path& ) override
|
||||||
{
|
{
|
||||||
@ -384,8 +371,8 @@ struct MenuItemVisitor : Registry::Visitor
|
|||||||
flags.push_back(flag);
|
flags.push_back(flag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (const auto pGroup =
|
if (const auto pGroup = dynamic_cast<GroupItem*>( pItem )) {
|
||||||
dynamic_cast<TransparentGroupItem*>( pItem )) {
|
wxASSERT( pGroup->Transparent() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wxASSERT( false );
|
wxASSERT( false );
|
||||||
@ -407,8 +394,8 @@ struct MenuItemVisitor : Registry::Visitor
|
|||||||
flags.pop_back();
|
flags.pop_back();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (const auto pGroup =
|
if (const auto pGroup = dynamic_cast<GroupItem*>( pItem )) {
|
||||||
dynamic_cast<TransparentGroupItem*>( pItem )) {
|
wxASSERT( pGroup->Transparent() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wxASSERT( false );
|
wxASSERT( false );
|
||||||
@ -448,7 +435,6 @@ struct MenuItemVisitor : Registry::Visitor
|
|||||||
wxASSERT( false );
|
wxASSERT( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
AudacityProject &project;
|
|
||||||
CommandManager &manager;
|
CommandManager &manager;
|
||||||
std::vector<bool> flags;
|
std::vector<bool> flags;
|
||||||
};
|
};
|
||||||
@ -466,7 +452,7 @@ void MenuCreator::CreateMenusAndCommands(AudacityProject &project)
|
|||||||
wxASSERT(menubar);
|
wxASSERT(menubar);
|
||||||
|
|
||||||
MenuItemVisitor visitor{ project, commandManager };
|
MenuItemVisitor visitor{ project, commandManager };
|
||||||
MenuManager::Visit( visitor, project );
|
MenuManager::Visit( visitor );
|
||||||
|
|
||||||
GetProjectFrame( project ).SetMenuBar(menubar.release());
|
GetProjectFrame( project ).SetMenuBar(menubar.release());
|
||||||
|
|
||||||
@ -477,9 +463,9 @@ void MenuCreator::CreateMenusAndCommands(AudacityProject &project)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuManager::Visit( Registry::Visitor &visitor, AudacityProject &project )
|
void MenuManager::Visit( MenuVisitor &visitor )
|
||||||
{
|
{
|
||||||
Registry::Visit( visitor, project, menuTree.get() );
|
Registry::Visit( visitor, menuTree.get() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This surely belongs in CommandManager?
|
// TODO: This surely belongs in CommandManager?
|
||||||
|
@ -54,6 +54,8 @@ public:
|
|||||||
PluginID mLastEffect{};
|
PluginID mLastEffect{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MenuVisitor;
|
||||||
|
|
||||||
class MenuManager final
|
class MenuManager final
|
||||||
: public MenuCreator
|
: public MenuCreator
|
||||||
, public ClientData::Base
|
, public ClientData::Base
|
||||||
@ -70,8 +72,7 @@ public:
|
|||||||
MenuManager &operator=( const MenuManager & ) PROHIBITED;
|
MenuManager &operator=( const MenuManager & ) PROHIBITED;
|
||||||
~MenuManager();
|
~MenuManager();
|
||||||
|
|
||||||
static void Visit(
|
static void Visit( MenuVisitor &visitor );
|
||||||
Registry::Visitor &visitor, AudacityProject &project );
|
|
||||||
|
|
||||||
static void ModifyUndoMenuItems(AudacityProject &project);
|
static void ModifyUndoMenuItems(AudacityProject &project);
|
||||||
static void ModifyToolbarMenus(AudacityProject &project);
|
static void ModifyToolbarMenus(AudacityProject &project);
|
||||||
|
@ -427,6 +427,8 @@ namespace Registry {
|
|||||||
using BaseItemPtr = std::unique_ptr<BaseItem>;
|
using BaseItemPtr = std::unique_ptr<BaseItem>;
|
||||||
using BaseItemSharedPtr = std::shared_ptr<BaseItem>;
|
using BaseItemSharedPtr = std::shared_ptr<BaseItem>;
|
||||||
using BaseItemPtrs = std::vector<BaseItemPtr>;
|
using BaseItemPtrs = std::vector<BaseItemPtr>;
|
||||||
|
|
||||||
|
struct Visitor;
|
||||||
|
|
||||||
|
|
||||||
// An item that delegates to another held in a shared pointer; this allows
|
// An item that delegates to another held in a shared pointer; this allows
|
||||||
@ -454,15 +456,18 @@ namespace Registry {
|
|||||||
// Return type is a shared_ptr to let the function decide whether to
|
// Return type is a shared_ptr to let the function decide whether to
|
||||||
// recycle the object or rebuild it on demand each time.
|
// recycle the object or rebuild it on demand each time.
|
||||||
// Return value from the factory may be null
|
// Return value from the factory may be null
|
||||||
using Factory = std::function< BaseItemSharedPtr( AudacityProject & ) >;
|
template< typename VisitorType >
|
||||||
|
using Factory = std::function< BaseItemSharedPtr( VisitorType & ) >;
|
||||||
|
|
||||||
explicit ComputedItem( const Factory &factory_ )
|
using DefaultVisitor = Visitor;
|
||||||
|
|
||||||
|
explicit ComputedItem( const Factory< DefaultVisitor > &factory_ )
|
||||||
: BaseItem( wxEmptyString )
|
: BaseItem( wxEmptyString )
|
||||||
, factory{ factory_ }
|
, factory{ factory_ }
|
||||||
{}
|
{}
|
||||||
~ComputedItem() override;
|
~ComputedItem() override;
|
||||||
|
|
||||||
Factory factory;
|
Factory< DefaultVisitor > factory;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Common abstract base class for items that are not groups
|
// Common abstract base class for items that are not groups
|
||||||
@ -473,17 +478,31 @@ namespace Registry {
|
|||||||
|
|
||||||
// Common abstract base class for items that group other items
|
// Common abstract base class for items that group other items
|
||||||
struct GroupItem : BaseItem {
|
struct GroupItem : BaseItem {
|
||||||
|
using BaseItem::BaseItem;
|
||||||
|
|
||||||
// Construction from an internal name and a previously built-up
|
// Construction from an internal name and a previously built-up
|
||||||
// vector of pointers
|
// vector of pointers
|
||||||
GroupItem( const wxString &internalName, BaseItemPtrs &&items_ );
|
GroupItem( const wxString &internalName, BaseItemPtrs &&items_ )
|
||||||
// In-line, variadic constructor that doesn't require building a vector
|
: BaseItem{ internalName }, items{ std::move( items_ ) }
|
||||||
template< typename... Args >
|
{}
|
||||||
GroupItem( const wxString &internalName, Args&&... args )
|
|
||||||
: BaseItem( internalName )
|
|
||||||
{ Append( std::forward< Args >( args )... ); }
|
|
||||||
~GroupItem() override = 0;
|
~GroupItem() override = 0;
|
||||||
|
|
||||||
|
// Whether the item is non-significant for path naming
|
||||||
|
// when it also has an empty name
|
||||||
|
virtual bool Transparent() const = 0;
|
||||||
|
|
||||||
BaseItemPtrs items;
|
BaseItemPtrs items;
|
||||||
|
};
|
||||||
|
|
||||||
|
// GroupItem adding variadic constructor conveniences
|
||||||
|
template< typename VisitorType = ComputedItem::DefaultVisitor >
|
||||||
|
struct InlineGroupItem : GroupItem {
|
||||||
|
using GroupItem::GroupItem;
|
||||||
|
// In-line, variadic constructor that doesn't require building a vector
|
||||||
|
template< typename... Args >
|
||||||
|
InlineGroupItem( const wxString &internalName, Args&&... args )
|
||||||
|
: GroupItem( internalName )
|
||||||
|
{ Append( std::forward< Args >( args )... ); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// nullary overload grounds the recursion
|
// nullary overload grounds the recursion
|
||||||
@ -502,27 +521,46 @@ namespace Registry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Move one unique_ptr to an item into our array
|
// Move one unique_ptr to an item into our array
|
||||||
void AppendOne( BaseItemPtr&& ptr );
|
void AppendOne( BaseItemPtr&& ptr )
|
||||||
|
{
|
||||||
|
items.push_back( std::move( ptr ) );
|
||||||
|
}
|
||||||
// This overload allows a lambda or function pointer in the variadic
|
// This overload allows a lambda or function pointer in the variadic
|
||||||
// argument lists without any other syntactic wrapping, and also
|
// argument lists without any other syntactic wrapping, and also
|
||||||
// allows implicit conversions to type Factory.
|
// allows implicit conversions to type Factory.
|
||||||
// (Thus, a lambda can return a unique_ptr<BaseItem> rvalue even though
|
// (Thus, a lambda can return a unique_ptr<BaseItem> rvalue even though
|
||||||
// Factory's return type is shared_ptr, and the needed conversion is
|
// Factory's return type is shared_ptr, and the needed conversion is
|
||||||
// appled implicitly.)
|
// appled implicitly.)
|
||||||
void AppendOne( const ComputedItem::Factory &factory )
|
void AppendOne( const ComputedItem::Factory<VisitorType> &factory )
|
||||||
{ AppendOne( std::make_unique<ComputedItem>( factory ) ); }
|
{
|
||||||
|
auto adaptedFactory = [factory]( Registry::Visitor &visitor ){
|
||||||
|
return factory( dynamic_cast< VisitorType& >( visitor ) );
|
||||||
|
};
|
||||||
|
AppendOne( std::make_unique<ComputedItem>( adaptedFactory ) );
|
||||||
|
}
|
||||||
// This overload lets you supply a shared pointer to an item, directly
|
// This overload lets you supply a shared pointer to an item, directly
|
||||||
template<typename Subtype>
|
template<typename Subtype>
|
||||||
void AppendOne( const std::shared_ptr<Subtype> &ptr )
|
void AppendOne( const std::shared_ptr<Subtype> &ptr )
|
||||||
{ AppendOne( std::make_unique<SharedItem>(ptr) ); }
|
{ AppendOne( std::make_unique<SharedItem>(ptr) ); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Inline group item also specifying transparency
|
||||||
|
template< bool transparent,
|
||||||
|
typename VisitorType = ComputedItem::DefaultVisitor >
|
||||||
|
struct ConcreteGroupItem : InlineGroupItem< VisitorType >
|
||||||
|
{
|
||||||
|
using InlineGroupItem< VisitorType >::InlineGroupItem;
|
||||||
|
~ConcreteGroupItem() {}
|
||||||
|
bool Transparent() const override { return transparent; }
|
||||||
|
};
|
||||||
|
|
||||||
// Concrete subclass of GroupItem that adds nothing else
|
// Concrete subclass of GroupItem that adds nothing else
|
||||||
// TransparentGroupItem with an empty name is transparent to item path calculations
|
// TransparentGroupItem with an empty name is transparent to item path calculations
|
||||||
struct TransparentGroupItem final : GroupItem
|
template< typename VisitorType = ComputedItem::DefaultVisitor >
|
||||||
|
struct TransparentGroupItem final : ConcreteGroupItem< true, VisitorType >
|
||||||
{
|
{
|
||||||
using GroupItem::GroupItem;
|
using ConcreteGroupItem< true, VisitorType >::ConcreteGroupItem;
|
||||||
~TransparentGroupItem() override;
|
~TransparentGroupItem() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define actions to be done in Visit.
|
// Define actions to be done in Visit.
|
||||||
@ -539,16 +577,23 @@ namespace Registry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Top-down visitation of all items and groups in a tree
|
// Top-down visitation of all items and groups in a tree
|
||||||
void Visit(
|
void Visit( Visitor &visitor, BaseItem *pTopItem );
|
||||||
Visitor &visitor, AudacityProject &project, BaseItem *pTopItem );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MenuVisitor : Registry::Visitor
|
||||||
|
{
|
||||||
|
explicit MenuVisitor( AudacityProject &p ) : project{ p } {}
|
||||||
|
operator AudacityProject & () const { return project; }
|
||||||
|
|
||||||
|
AudacityProject &project;
|
||||||
|
};
|
||||||
|
|
||||||
// Define items that populate tables that specifically describe menu trees
|
// Define items that populate tables that specifically describe menu trees
|
||||||
namespace MenuTable {
|
namespace MenuTable {
|
||||||
using namespace Registry;
|
using namespace Registry;
|
||||||
|
|
||||||
// Describes a main menu in the toolbar, or a sub-menu
|
// Describes a main menu in the toolbar, or a sub-menu
|
||||||
struct MenuItem final : GroupItem {
|
struct MenuItem final : ConcreteGroupItem< false, MenuVisitor > {
|
||||||
// Construction from an internal name and a previously built-up
|
// Construction from an internal name and a previously built-up
|
||||||
// vector of pointers
|
// vector of pointers
|
||||||
MenuItem( const wxString &internalName,
|
MenuItem( const wxString &internalName,
|
||||||
@ -557,7 +602,8 @@ namespace MenuTable {
|
|||||||
template< typename... Args >
|
template< typename... Args >
|
||||||
MenuItem( const wxString &internalName,
|
MenuItem( const wxString &internalName,
|
||||||
const TranslatableString &title_, Args&&... args )
|
const TranslatableString &title_, Args&&... args )
|
||||||
: GroupItem{ internalName, std::forward<Args>(args)... }
|
: ConcreteGroupItem< false, MenuVisitor >{
|
||||||
|
internalName, std::forward<Args>(args)... }
|
||||||
, title{ title_ }
|
, title{ title_ }
|
||||||
{}
|
{}
|
||||||
~MenuItem() override;
|
~MenuItem() override;
|
||||||
@ -567,7 +613,7 @@ namespace MenuTable {
|
|||||||
|
|
||||||
// Collects other items that are conditionally shown or hidden, but are
|
// Collects other items that are conditionally shown or hidden, but are
|
||||||
// always available to macro programming
|
// always available to macro programming
|
||||||
struct ConditionalGroupItem final : GroupItem {
|
struct ConditionalGroupItem final : ConcreteGroupItem< false, MenuVisitor > {
|
||||||
using Condition = std::function< bool() >;
|
using Condition = std::function< bool() >;
|
||||||
|
|
||||||
// Construction from an internal name and a previously built-up
|
// Construction from an internal name and a previously built-up
|
||||||
@ -578,7 +624,8 @@ namespace MenuTable {
|
|||||||
template< typename... Args >
|
template< typename... Args >
|
||||||
ConditionalGroupItem( const wxString &internalName,
|
ConditionalGroupItem( const wxString &internalName,
|
||||||
Condition condition_, Args&&... args )
|
Condition condition_, Args&&... args )
|
||||||
: GroupItem{ internalName, std::forward<Args>(args)... }
|
: ConcreteGroupItem< false, MenuVisitor >{
|
||||||
|
internalName, std::forward<Args>(args)... }
|
||||||
, condition{ condition_ }
|
, condition{ condition_ }
|
||||||
{}
|
{}
|
||||||
~ConditionalGroupItem() override;
|
~ConditionalGroupItem() override;
|
||||||
@ -713,10 +760,10 @@ namespace MenuTable {
|
|||||||
// in identification of items by path. Otherwise try to keep the name
|
// in identification of items by path. Otherwise try to keep the name
|
||||||
// stable across Audacity versions.
|
// stable across Audacity versions.
|
||||||
template< typename... Args >
|
template< typename... Args >
|
||||||
inline std::unique_ptr<TransparentGroupItem> Items(
|
inline std::unique_ptr<TransparentGroupItem< MenuVisitor > > Items(
|
||||||
const wxString &internalName, Args&&... args )
|
const wxString &internalName, Args&&... args )
|
||||||
{ return std::make_unique<TransparentGroupItem>( internalName,
|
{ return std::make_unique<TransparentGroupItem< MenuVisitor > >(
|
||||||
std::forward<Args>(args)... ); }
|
internalName, std::forward<Args>(args)... ); }
|
||||||
|
|
||||||
// Menu items can be constructed two ways, as for group items
|
// Menu items can be constructed two ways, as for group items
|
||||||
// Items will appear in a main toolbar menu or in a sub-menu.
|
// Items will appear in a main toolbar menu or in a sub-menu.
|
||||||
|
@ -380,8 +380,10 @@ void OnMenuTree(const CommandContext &context)
|
|||||||
auto &project = context.project;
|
auto &project = context.project;
|
||||||
|
|
||||||
using namespace MenuTable;
|
using namespace MenuTable;
|
||||||
struct MyVisitor : Visitor
|
struct MyVisitor : MenuVisitor
|
||||||
{
|
{
|
||||||
|
using MenuVisitor::MenuVisitor;
|
||||||
|
|
||||||
enum : unsigned { TAB = 3 };
|
enum : unsigned { TAB = 3 };
|
||||||
void BeginGroup( GroupItem &item, const Path& ) override
|
void BeginGroup( GroupItem &item, const Path& ) override
|
||||||
{
|
{
|
||||||
@ -415,9 +417,9 @@ void OnMenuTree(const CommandContext &context)
|
|||||||
unsigned level{};
|
unsigned level{};
|
||||||
wxString indentation;
|
wxString indentation;
|
||||||
wxString info;
|
wxString info;
|
||||||
} visitor;
|
} visitor{ project };
|
||||||
|
|
||||||
MenuManager::Visit( visitor, project );
|
MenuManager::Visit( visitor );
|
||||||
|
|
||||||
ShowDiagnostics( project, visitor.info,
|
ShowDiagnostics( project, visitor.info,
|
||||||
XO("Menu Tree"), wxT("menutree.txt"), true );
|
XO("Menu Tree"), wxT("menutree.txt"), true );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user