mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-16 08:09:32 +02:00
Define AttachedItem registration struct for menu items
This commit is contained in:
parent
c5495b3300
commit
baada94567
@ -178,6 +178,78 @@ CommandHandlerFinder FinderScope::sFinder =
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace Registry {
|
||||
|
||||
void RegisterItem( GroupItem ®istry, const Placement &placement,
|
||||
BaseItemPtr pItem )
|
||||
{
|
||||
// Since registration determines only an unordered tree of menu items,
|
||||
// we can sort children of each node lexicographically for our convenience.
|
||||
BaseItemPtrs *pItems;
|
||||
struct Comparator {
|
||||
bool operator()
|
||||
( const Identifier &component, const BaseItemPtr& pItem ) const {
|
||||
return component < pItem->name; }
|
||||
bool operator()
|
||||
( const BaseItemPtr& pItem, const Identifier &component ) const {
|
||||
return pItem->name < component; }
|
||||
};
|
||||
auto find = [&pItems]( const Identifier &component ){ return std::equal_range(
|
||||
pItems->begin(), pItems->end(), component, Comparator() ); };
|
||||
|
||||
auto pNode = ®istry;
|
||||
pItems = &pNode->items;
|
||||
|
||||
auto pathComponents = ::wxSplit( placement.path, '/' );
|
||||
auto pComponent = pathComponents.begin(), end = pathComponents.end();
|
||||
|
||||
// Descend the registry hierarchy, while groups matching the path components
|
||||
// can be found
|
||||
auto debugPath = wxString{'/'} + registry.name.GET();
|
||||
while ( pComponent != end ) {
|
||||
const auto &pathComponent = *pComponent;
|
||||
|
||||
// Try to find an item already present that is a group item with the
|
||||
// same name; we don't care which if there is more than one.
|
||||
const auto range = find( pathComponent );
|
||||
const auto iter2 = std::find_if( range.first, range.second,
|
||||
[](const BaseItemPtr &pItem){
|
||||
return dynamic_cast< GroupItem* >( pItem.get() ); } );
|
||||
|
||||
if ( iter2 != range.second ) {
|
||||
// A matching group in the registry, so descend
|
||||
pNode = static_cast< GroupItem* >( iter2->get() );
|
||||
pItems = &pNode->items;
|
||||
debugPath += '/' + pathComponent;
|
||||
++pComponent;
|
||||
}
|
||||
else
|
||||
// Insert at this level;
|
||||
// If there are no more path components, and a name collision of
|
||||
// the added item with something already in the registry, don't resolve
|
||||
// it yet in this function, but see MergeItems().
|
||||
break;
|
||||
}
|
||||
|
||||
// Create path group items for remaining components
|
||||
while ( pComponent != end ) {
|
||||
auto newNode = std::make_unique<TransparentGroupItem<>>( *pComponent );
|
||||
pNode = newNode.get();
|
||||
pItems->insert( find( newNode->name ).second, std::move( newNode ) );
|
||||
pItems = &pNode->items;
|
||||
++pComponent;
|
||||
}
|
||||
|
||||
// Remember the hint, to be used later in merging.
|
||||
pItem->orderingHint = placement.hint;
|
||||
|
||||
// Now insert the item.
|
||||
pItems->insert( find( pItem->name ).second, std::move( pItem ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const auto MenuPathStart = wxT("MenuBar");
|
||||
@ -301,7 +373,6 @@ void CollectItem( Registry::Visitor &visitor,
|
||||
|
||||
using Path = std::vector< Identifier >;
|
||||
|
||||
namespace {
|
||||
std::unordered_set< wxString > sBadPaths;
|
||||
void BadPath(
|
||||
const TranslatableString &format, const wxString &key, const Identifier &name )
|
||||
@ -339,7 +410,6 @@ XO("Plug-in item at %s conflicts with a previously defined item and was discarde
|
||||
XO("Plug-in items at %s specify conflicting placements"),
|
||||
key, name);
|
||||
}
|
||||
}
|
||||
|
||||
struct ItemOrdering {
|
||||
wxString key;
|
||||
@ -763,6 +833,12 @@ static Registry::GroupItem &sRegistry()
|
||||
}
|
||||
}
|
||||
|
||||
MenuTable::AttachedItem::AttachedItem(
|
||||
const Placement &placement, BaseItemPtr pItem )
|
||||
{
|
||||
Registry::RegisterItem( sRegistry(), placement, std::move( pItem ) );
|
||||
}
|
||||
|
||||
// Table of menu factories.
|
||||
// TODO: devise a registration system instead.
|
||||
static const auto menuTree = MenuTable::Items( MenuPathStart
|
||||
|
@ -602,6 +602,25 @@ namespace Registry {
|
||||
~TransparentGroupItem() override {}
|
||||
};
|
||||
|
||||
// The /-separated path is relative to the GroupItem supplied to
|
||||
// RegisterItem.
|
||||
// For instance, wxT("Transport/Cursor") to locate an item under a sub-menu
|
||||
// of a main menu
|
||||
struct Placement {
|
||||
wxString path;
|
||||
OrderingHint hint;
|
||||
|
||||
Placement( const wxString &path_, const OrderingHint &hint_ = {} )
|
||||
: path( path_ ), hint( hint_ )
|
||||
{}
|
||||
};
|
||||
|
||||
// registry collects items, before consulting preferences and ordering
|
||||
// hints, and applying the merge procedure to them.
|
||||
// This function puts one more item into the registry.
|
||||
void RegisterItem( GroupItem ®istry, const Placement &placement,
|
||||
BaseItemPtr pItem );
|
||||
|
||||
// Define actions to be done in Visit.
|
||||
// Default implementations do nothing
|
||||
// The supplied path does not include the name of the item
|
||||
@ -800,7 +819,8 @@ namespace MenuTable {
|
||||
using MenuItems = MenuPart< true >;
|
||||
using MenuSection = MenuPart< false >;
|
||||
|
||||
// Following are the functions to use directly in writing table definitions.
|
||||
// The following, and Shared(), are the functions to use directly
|
||||
// in writing table definitions.
|
||||
|
||||
// Group items can be constructed two ways.
|
||||
// Pointers to subordinate items are moved into the result.
|
||||
@ -825,7 +845,7 @@ namespace MenuTable {
|
||||
const wxString &internalName, Args&&... args )
|
||||
{ return std::make_unique< MenuSection >(
|
||||
internalName, std::forward<Args>(args)... ); }
|
||||
|
||||
|
||||
// Menu items can be constructed two ways, as for group items
|
||||
// Items will appear in a main toolbar menu or in a sub-menu.
|
||||
// The name is untranslated. Try to keep the name stable across Audacity
|
||||
@ -913,6 +933,20 @@ namespace MenuTable {
|
||||
inline std::unique_ptr<SpecialItem> Special(
|
||||
const wxString &name, const SpecialItem::Appender &fn )
|
||||
{ return std::make_unique<SpecialItem>( name, fn ); }
|
||||
|
||||
// Typically you make a static object of this type in the .cpp file that
|
||||
// also defines the added menu actions.
|
||||
// pItem can be specified by an expression using the inline functions above.
|
||||
struct AttachedItem final
|
||||
{
|
||||
AttachedItem( const Placement &placement, BaseItemPtr pItem );
|
||||
|
||||
AttachedItem( const wxString &path, BaseItemPtr pItem )
|
||||
// Delegating constructor
|
||||
: AttachedItem( Placement{ path }, std::move( pItem ) )
|
||||
{}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user