mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-01 16:19:43 +02:00
Change class hierarchy of MenuTable::BaseItem...
... There are now four immediate subclasses (SharedItem and Computed Item, which are final, and SingleItem and GroupItem, which are abstract), which may serve future purposes more general than menu items. There are further subclasses specific to menu management. The former concrete class GroupItem is renamed TransparentGroupItem. Also allows direct construction of items in lists from shared pointers.
This commit is contained in:
parent
93c2bb9322
commit
33b4b409e8
@ -104,8 +104,12 @@ namespace MenuTable {
|
||||
|
||||
BaseItem::~BaseItem() {}
|
||||
|
||||
SharedItem::~SharedItem() {}
|
||||
|
||||
ComputedItem::~ComputedItem() {}
|
||||
|
||||
SingleItem::~SingleItem() {}
|
||||
|
||||
GroupItem::GroupItem( BaseItemPtrs &&items_ )
|
||||
: items{ std::move( items_ ) }
|
||||
{
|
||||
@ -116,6 +120,11 @@ void GroupItem::AppendOne( BaseItemPtr&& ptr )
|
||||
}
|
||||
GroupItem::~GroupItem() {}
|
||||
|
||||
TransparentGroupItem::~TransparentGroupItem() {}
|
||||
}
|
||||
|
||||
namespace MenuTable {
|
||||
|
||||
MenuItem::MenuItem( const TranslatableString &title_, BaseItemPtrs &&items_ )
|
||||
: GroupItem{ std::move( items_ ) }, title{ title_ }
|
||||
{
|
||||
@ -188,6 +197,12 @@ void VisitItem( AudacityProject &project, MenuTable::BaseItem *pItem )
|
||||
auto &manager = CommandManager::Get( project );
|
||||
|
||||
using namespace MenuTable;
|
||||
if (const auto pShared =
|
||||
dynamic_cast<SharedItem*>( pItem )) {
|
||||
auto delegate = pShared->ptr;
|
||||
VisitItem( project, delegate.get() );
|
||||
}
|
||||
else
|
||||
if (const auto pComputed =
|
||||
dynamic_cast<ComputedItem*>( pItem )) {
|
||||
// TODO maybe? memo-ize the results of the function, but that requires
|
||||
@ -235,7 +250,7 @@ void VisitItem( AudacityProject &project, MenuTable::BaseItem *pItem )
|
||||
}
|
||||
else
|
||||
if (const auto pGroup =
|
||||
dynamic_cast<GroupItem*>( pItem )) {
|
||||
dynamic_cast<TransparentGroupItem*>( pItem )) {
|
||||
// recursion
|
||||
VisitItems( project, pGroup->items );
|
||||
}
|
||||
|
@ -405,7 +405,8 @@ private:
|
||||
std::unique_ptr< wxMenuBar > mTempMenuBar;
|
||||
};
|
||||
|
||||
// Define items that populate tables that describe menu trees
|
||||
// Define classes and functions that associate parts of the user interface
|
||||
// with path names
|
||||
namespace MenuTable {
|
||||
// TODO C++17: maybe use std::variant (discriminated unions) to achieve
|
||||
// polymorphism by other means, not needing unique_ptr and dynamic_cast
|
||||
@ -418,18 +419,34 @@ namespace MenuTable {
|
||||
virtual ~BaseItem();
|
||||
};
|
||||
using BaseItemPtr = std::unique_ptr<BaseItem>;
|
||||
using BaseItemSharedPtr = std::shared_ptr<BaseItem>;
|
||||
using BaseItemPtrs = std::vector<BaseItemPtr>;
|
||||
|
||||
|
||||
// The type of functions that generate menu table descriptions.
|
||||
// Return type is a shared_ptr to let the function decide whether to recycle
|
||||
// the object or rebuild it on demand each time.
|
||||
// Return value from the factory may be null.
|
||||
using Factory = std::function<
|
||||
std::shared_ptr< MenuTable::BaseItem >( AudacityProject & )
|
||||
>;
|
||||
// An item that delegates to another held in a shared pointer; this allows
|
||||
// static tables of items to be computed once and reused
|
||||
struct SharedItem final : BaseItem {
|
||||
explicit SharedItem( const BaseItemSharedPtr &ptr_ )
|
||||
: ptr{ ptr_ }
|
||||
{}
|
||||
~SharedItem() override;
|
||||
|
||||
BaseItemSharedPtr ptr;
|
||||
};
|
||||
|
||||
// A convenience function
|
||||
inline std::unique_ptr<SharedItem> Shared( const BaseItemSharedPtr &ptr )
|
||||
{ return std::make_unique<SharedItem>( ptr ); }
|
||||
|
||||
// An item that computes some other item to substitute for it, each time
|
||||
// the ComputedItem is visited
|
||||
struct ComputedItem final : BaseItem {
|
||||
// The type of functions that generate descriptions of items.
|
||||
// Return type is a shared_ptr to let the function decide whether to
|
||||
// recycle the object or rebuild it on demand each time.
|
||||
// Return value from the factory may be null
|
||||
using Factory = std::function< BaseItemSharedPtr( AudacityProject & ) >;
|
||||
|
||||
struct ComputedItem : BaseItem {
|
||||
explicit ComputedItem( const Factory &factory_ )
|
||||
: factory{ factory_ }
|
||||
{}
|
||||
@ -438,6 +455,13 @@ namespace MenuTable {
|
||||
Factory factory;
|
||||
};
|
||||
|
||||
// Common abstract base class for items that are not groups
|
||||
struct SingleItem : BaseItem {
|
||||
using BaseItem::BaseItem;
|
||||
~SingleItem() override = 0;
|
||||
};
|
||||
|
||||
// Common abstract base class for items that group other items
|
||||
struct GroupItem : BaseItem {
|
||||
// Construction from a previously built-up vector of pointers
|
||||
GroupItem( BaseItemPtrs &&items_ );
|
||||
@ -445,7 +469,7 @@ namespace MenuTable {
|
||||
template< typename... Args >
|
||||
GroupItem( Args&&... args )
|
||||
{ Append( std::forward< Args >( args )... ); }
|
||||
~GroupItem() override;
|
||||
~GroupItem() override = 0;
|
||||
|
||||
BaseItemPtrs items;
|
||||
|
||||
@ -473,10 +497,24 @@ namespace MenuTable {
|
||||
// (Thus, a lambda can return a unique_ptr<BaseItem> rvalue even though
|
||||
// Factory's return type is shared_ptr, and the needed conversion is
|
||||
// appled implicitly.)
|
||||
void AppendOne( const Factory &factory )
|
||||
void AppendOne( const ComputedItem::Factory &factory )
|
||||
{ AppendOne( std::make_unique<ComputedItem>( factory ) ); }
|
||||
// This overload lets you supply a shared pointer to an item, directly
|
||||
template<typename Subtype>
|
||||
void AppendOne( const std::shared_ptr<Subtype> &ptr )
|
||||
{ AppendOne( std::make_unique<SharedItem>(ptr) ); }
|
||||
};
|
||||
|
||||
// Concrete subclass of GroupItem that adds nothing else
|
||||
struct TransparentGroupItem final : GroupItem
|
||||
{
|
||||
using GroupItem::GroupItem;
|
||||
~TransparentGroupItem() override;
|
||||
};
|
||||
|
||||
// Define items that populate tables that specifically describe menu trees
|
||||
|
||||
// Describes a main menu in the toolbar, or a sub-menu
|
||||
struct MenuItem final : GroupItem {
|
||||
// Construction from a previously built-up vector of pointers
|
||||
MenuItem( const TranslatableString &title_, BaseItemPtrs &&items_ );
|
||||
@ -492,6 +530,8 @@ namespace MenuTable {
|
||||
TranslatableString title;
|
||||
};
|
||||
|
||||
// Collects other items that are conditionally shown or hidden, but are
|
||||
// always available to macro programming
|
||||
struct ConditionalGroupItem final : GroupItem {
|
||||
using Condition = std::function< bool() >;
|
||||
|
||||
@ -508,7 +548,8 @@ namespace MenuTable {
|
||||
Condition condition;
|
||||
};
|
||||
|
||||
struct SeparatorItem final : BaseItem
|
||||
// Describes a separator between menu items
|
||||
struct SeparatorItem final : SingleItem
|
||||
{
|
||||
~SeparatorItem() override;
|
||||
};
|
||||
@ -542,7 +583,8 @@ namespace MenuTable {
|
||||
{ return std::forward<Value>(value); }
|
||||
};
|
||||
|
||||
struct CommandItem final : BaseItem {
|
||||
// Describes one command in a menu
|
||||
struct CommandItem final : SingleItem {
|
||||
CommandItem(const CommandID &name_,
|
||||
const TranslatableString &label_in_,
|
||||
CommandFunctorPointer callback_,
|
||||
@ -574,7 +616,10 @@ namespace MenuTable {
|
||||
CommandManager::Options options;
|
||||
};
|
||||
|
||||
struct CommandGroupItem final : BaseItem {
|
||||
// Describes several successive commands in a menu that are closely related
|
||||
// and dispatch to one common callback, which will be passed a number
|
||||
// in the CommandContext identifying the command
|
||||
struct CommandGroupItem final : SingleItem {
|
||||
CommandGroupItem(const wxString &name_,
|
||||
std::initializer_list< ComponentInterfaceSymbol > items_,
|
||||
CommandFunctorPointer callback_,
|
||||
@ -608,7 +653,7 @@ namespace MenuTable {
|
||||
|
||||
// For manipulating the enclosing menu or sub-menu directly,
|
||||
// adding any number of items, not using the CommandManager
|
||||
struct SpecialItem final : BaseItem
|
||||
struct SpecialItem final : SingleItem
|
||||
{
|
||||
using Appender = std::function< void( AudacityProject&, wxMenu& ) >;
|
||||
|
||||
@ -627,8 +672,8 @@ namespace MenuTable {
|
||||
// Null pointers are permitted, and ignored when building the menu.
|
||||
// Items are spliced into the enclosing menu
|
||||
template< typename... Args >
|
||||
inline std::unique_ptr<GroupItem> Items( Args&&... args )
|
||||
{ return std::make_unique<GroupItem>(
|
||||
inline std::unique_ptr<TransparentGroupItem> Items( Args&&... args )
|
||||
{ return std::make_unique<TransparentGroupItem>(
|
||||
std::forward<Args>(args)... ); }
|
||||
|
||||
// Menu items can be constructed two ways, as for group items
|
||||
|
Loading…
x
Reference in New Issue
Block a user