diff --git a/src/Menus.cpp b/src/Menus.cpp index 49d29e576..df9904e0e 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -42,7 +42,6 @@ #include "widgets/AudacityMessageBox.h" #include "widgets/ErrorDialog.h" -#include #include #include @@ -941,6 +940,22 @@ void Visit( Visitor &visitor, BaseItem *pTopItem, GroupItem *pRegistry ) gPrefs->Flush(); } +OrderingPreferenceInitializer::OrderingPreferenceInitializer( + Literal root, const Pairs &pairs ) +{ + bool doFlush = false; + for (const auto &pair : pairs) { + const auto key = wxString{'/'} + root + pair.first; + if ( gPrefs->Read(key).empty() ) { + gPrefs->Write( key, pair.second ); + doFlush = true; + } + } + + if (doFlush) + gPrefs->Flush(); +} + } /// CreateMenusAndCommands builds the menus, and also rebuilds them after @@ -963,45 +978,6 @@ MenuTable::AttachedItem::AttachedItem( namespace { -// Once only, cause initial population of preferences for the ordering -// of some menu items that used to be given in tables but are now separately -// registered in several .cpp files; the sequence of registration depends -// on unspecified accidents of static initialization order across -// compilation units, so we need something specific here to preserve old -// default appearance of menus. -// But this needs only to mention some strings -- there is no compilation or -// link dependency of this source file on those other implementation files. -void InitializeMenuOrdering() -{ - using Pair = std::pair; - static const Pair pairs [] = { - {wxT(""), wxT( -"File,Edit,Select,View,Transport,Tracks,Generate,Effect,Analyze,Tools,Window,Optional,Help" - )}, - {wxT("/Optional/Extra/Part1"), wxT( -"Transport,Tools,Mixer,Edit,PlayAtSpeed,Seek,Device,Select" - )}, - {wxT("/Optional/Extra/Part2"), wxT( -"Navigation,Focus,Cursor,Track,Scriptables1,Scriptables2" - )}, - {wxT("/View/Windows"), wxT("UndoHistory,Karaoke,MixerBoard")}, - {wxT("/Analyze/Analyzers/Windows"), wxT("ContrastAnalyser,PlotSpectrum")}, - {wxT("/Transport/Basic"),wxT("Play,Record,Scrubbing,Cursor")}, - }; - - bool doFlush = false; - for (auto pair : pairs) { - const auto key = wxString{'/'} + MenuPathStart + pair.first; - if ( gPrefs->Read(key).empty() ) { - gPrefs->Write( key, pair.second ); - doFlush = true; - } - } - - if (doFlush) - gPrefs->Flush(); -} - using namespace MenuTable; struct MenuItemVisitor : MenuVisitor @@ -1105,8 +1081,31 @@ struct MenuItemVisitor : MenuVisitor void MenuCreator::CreateMenusAndCommands(AudacityProject &project) { - static std::once_flag flag; - std::call_once( flag, InitializeMenuOrdering ); + // Once only, cause initial population of preferences for the ordering + // of some menu items that used to be given in tables but are now separately + // registered in several .cpp files; the sequence of registration depends + // on unspecified accidents of static initialization order across + // compilation units, so we need something specific here to preserve old + // default appearance of menus. + // But this needs only to mention some strings -- there is no compilation or + // link dependency of this source file on those other implementation files. + static Registry::OrderingPreferenceInitializer init{ + MenuPathStart, + { + {wxT(""), wxT( + "File,Edit,Select,View,Transport,Tracks,Generate,Effect,Analyze,Tools,Window,Optional,Help" + )}, + {wxT("/Optional/Extra/Part1"), wxT( + "Transport,Tools,Mixer,Edit,PlayAtSpeed,Seek,Device,Select" + )}, + {wxT("/Optional/Extra/Part2"), wxT( + "Navigation,Focus,Cursor,Track,Scriptables1,Scriptables2" + )}, + {wxT("/View/Windows"), wxT("UndoHistory,Karaoke,MixerBoard")}, + {wxT("/Analyze/Analyzers/Windows"), wxT("ContrastAnalyser,PlotSpectrum")}, + {wxT("/Transport/Basic"),wxT("Play,Record,Scrubbing,Cursor")}, + } + }; auto &commandManager = CommandManager::Get( project ); diff --git a/src/commands/CommandManager.h b/src/commands/CommandManager.h index 5e30cb466..60159366f 100644 --- a/src/commands/CommandManager.h +++ b/src/commands/CommandManager.h @@ -645,6 +645,27 @@ namespace Registry { Visitor &visitor, BaseItem *pTopItem, GroupItem *pRegistry = nullptr ); + + // Typically a static object. Constructor initializes certain preferences + // if they are not present. These preferences determine an extrinsic + // visitation ordering for registered items. This is needed in some + // places that have migrated from a system of exhaustive listings, to a + // registry of plug-ins, and something must be done to preserve old + // behavior. It can be done in the central place using string literal + // identifiers only, not requiring static compilation or linkage dependency. + struct OrderingPreferenceInitializer { + using Literal = const wxChar *; + using Pair = std::pair< Literal, Literal >; + using Pairs = std::vector< Pair >; + OrderingPreferenceInitializer( + // Specifies the topmost preference section: + Literal root, + // Specifies /-separated Registry paths relative to root + // (these should be blank or start with / and not end with /), + // each with a ,-separated sequence of identifiers, which specify a + // desired ordering at one node of the tree: + const Pairs &pairs ); + }; } struct MenuVisitor : Registry::Visitor