45#include <unordered_set>
48#include <wx/windowptr.h>
68 return std::make_shared< MenuManager >( project ); }
95 bool bSelectAllIfNone;
96 gPrefs->Read(wxT(
"/GUI/SelectAllOnNone"), &bSelectAllIfNone,
false);
111 bool isExtension =
false;
113 if ( pItem->Transparent() ) {
121 isExtension = pWhole->extension;
136 if ( pItem->Transparent() ) {
158 bool separate =
false;
190 internalName, std::move( items_ ) },
title{ title_ }
192 wxASSERT( !
title.empty() );
199 internalName, std::move( items_ ) }, condition{ condition_ }
211, finder{ finder_ }, callback{ callback_ }
212, flags{ flags_ }, options{ options_ }
217 std::vector< ComponentInterfaceSymbol > items_,
223, finder{ finder_ }, callback{ callback_ }
224, flags{ flags_ }, isEffect{ isEffect_ }
284 if (
const auto pMenu =
286 manager.BeginMenu( pMenu->title );
289 if (
const auto pConditionalGroup =
291 const auto flag = pConditionalGroup->condition();
295 flags.push_back(
flag);
298 if ( pItem->Transparent() ) {
301 if (
const auto pGroup =
dynamic_cast<MenuSection*
>( pItem ) ) {
310 if (
const auto pMenu =
315 if (
const auto pConditionalGroup =
317 const bool flag = flags.back();
323 if ( pItem->Transparent() ) {
326 if (
const auto pGroup =
dynamic_cast<MenuSection*
>( pItem ) ) {
334 const auto pCurrentMenu =
manager.CurrentMenu();
335 if ( !pCurrentMenu ) {
342 if (
const auto pCommand =
345 pCommand->name, pCommand->label_in,
346 pCommand->finder, pCommand->callback,
347 pCommand->flags, pCommand->options
351 if (
const auto pCommandList =
353 manager.AddItemList(pCommandList->name,
354 pCommandList->items.data(), pCommandList->items.size(),
355 pCommandList->finder, pCommandList->callback,
356 pCommandList->flags, pCommandList->isEffect);
359 if (
const auto pSpecial =
361 wxASSERT( pCurrentMenu );
362 pSpecial->fn( project, *pCurrentMenu );
392 "File,Edit,Select,View,Transport,Tracks,Generate,Effect,Analyze,Tools,Window,Optional,Help"
394 {wxT(
"/Optional/Extra/Part1"), wxT(
395 "Transport,Tools,Mixer,Edit,PlayAtSpeed,Seek,Device,Select"
397 {wxT(
"/Optional/Extra/Part2"), wxT(
398 "Navigation,Focus,Cursor,Track,Scriptables1,Scriptables2"
400 {wxT(
"/View/Windows"), wxT(
"UndoHistory,Karaoke,MixerBoard")},
401 {wxT(
"/Analyze/Analyzers/Windows"), wxT(
"ContrastAnalyser,PlotSpectrum")},
402 {wxT(
"/Transport/Basic"), wxT(
"Play,Record,Scrubbing,Cursor")},
403 {wxT(
"/View/Other/Toolbars/Toolbars/Other"), wxT(
404"ShowTransportTB,ShowToolsTB,ShowRecordMeterTB,ShowPlayMeterTB,"
407"ShowEditTB,ShowTranscriptionTB,ShowScrubbingTB,ShowDeviceTB,ShowSelectionTB,"
408"ShowSpectralSelectionTB") },
409 {wxT(
"/Tracks/Add/Add"), wxT(
410 "NewMonoTrack,NewStereoTrack,NewLabelTrack,NewTimeTrack")},
418 commandManager.SetMaxList();
420 auto menubar = commandManager.AddMenuBar(wxT(
"appmenu"));
423 MenuItemVisitor visitor{ project, commandManager };
449 int cur = undoManager.GetCurrentState();
451 if (undoManager.UndoAvailable()) {
452 undoManager.GetShortDescription(cur, &
desc);
453 commandManager.Modify(wxT(
"Undo"),
456 commandManager.Enable(wxT(
"Undo"),
460 commandManager.Modify(wxT(
"Undo"),
464 if (undoManager.RedoAvailable()) {
465 undoManager.GetShortDescription(cur+1, &
desc);
466 commandManager.Modify(wxT(
"Redo"),
469 commandManager.Enable(wxT(
"Redo"),
473 commandManager.Modify(wxT(
"Redo"),
475 commandManager.Enable(wxT(
"Redo"),
false);
483 using wxFrame::DetachMenuBar;
491#if defined(__WXMAC__) && defined(_DEBUG)
494 wxDynamicCast(wxGetTopLevelParent(wxWindow::FindFocus()), wxDialog);
495 wxASSERT((!dlg || !dlg->IsModal()));
503 wxWindowPtr<wxMenuBar> menuBar{ window.GetMenuBar() };
504 window.DetachMenuBar();
510 CreateMenusAndCommands(project);
515 switch (message.
type) {
524 ModifyUndoMenuItems( mProject );
529 using Predicates = std::vector< ReservedCommandFlag::Predicate >;
533 return thePredicates;
537 static std::vector< CommandFlagOptions > options;
545 static size_t sNextReservedFlag = 0;
548 set( sNextReservedFlag++ );
550 Options().emplace_back( options );
565 const auto &options =
Options();
568 if ( options[ii].quickTest ) {
569 quickFlags[ii] =
true;
570 if( predicate( mProject ) )
578 flags = (lastFlags & ~quickFlags) | flags;
582 if ( !options[ii].quickTest && predicate( mProject ) )
595 auto &project = *pProject;
610 auto bar = toolManager.GetToolBar(i);
612 bar->EnableDisableButtons();
619 gPrefs->Read(wxT(
"/GUI/SyncLockTracks"), &active,
false);
645 auto &project = mProject;
647 auto flags = GetUpdateFlags(checkActive);
650 if (flags == mLastFlags)
662 for (
const auto &enabler :
Enablers() ) {
663 auto actual = enabler.actualFlags();
665 enabler.applicable( project ) && (flags & actual) == actual
667 flags2 |= enabler.possibleFlags();
675 commandManager.EnableUsingFlags(
677 (mWhatIfNoSelection == 0 ? flags2 : flags)
691#if defined(__WXGTK__)
698 wxRect r = window.GetRect();
699 window.SetSize(wxSize(1,1));
700 window.SetSize(r.GetSize());
708 auto &project = mProject;
709 bool bAllowed = TryToMakeActionAllowed( flags, flagsRqd );
713 TellUserWhyDisallowed( Name, flags & flagsRqd, flagsRqd);
723 auto &project = mProject;
726 flags = GetUpdateFlags();
730 auto iter = enablers.begin(),
end = enablers.end();
731 while ((flags & flagsRqd) != flagsRqd && iter !=
end) {
732 const auto &enabler = *iter;
733 auto actual = enabler.actualFlags();
734 auto MissingFlags = (~flags & flagsRqd);
737 (flags & actual) == actual
740 (MissingFlags & enabler.possibleFlags()).any()
743 enabler.tryEnable( project, flagsRqd );
744 flags = GetUpdateFlags();
748 return (flags & flagsRqd) == flagsRqd;
756 auto reason =
XO(
"There was a problem with your last action. If you think\nthis is a bug, please tell us exactly where it occurred.");
758 auto untranslatedTitle =
XO(
"Disallowed");
761 bool enableDefaultMessage =
true;
762 bool defaultMessage =
true;
765 if ( options.message ) {
766 reason = options.message( Name );
767 defaultMessage =
false;
768 if ( !options.title.empty() )
769 untranslatedTitle = options.title;
770 helpPage = options.helpPage;
774 enableDefaultMessage =
775 enableDefaultMessage && options.enableDefaultMessage;
780 const auto &alloptions =
Options();
781 auto missingFlags = flagsRequired & ~flagsGot;
784 unsigned priority = 0;
785 for (
const auto &options : alloptions )
786 priority = std::max( priority, options.priority );
791 while( priority-- ) {
793 for (
const auto &options : alloptions ) {
795 priority == options.priority
799 doOption( options ) )
812 !enableDefaultMessage
Toolkit-neutral facade for basic user interface services.
constexpr CommandFlag AlwaysEnabledFlag
std::bitset< NCommandFlags > CommandFlag
void(CommandHandlerObject::*)(const CommandContext &context) CommandFunctorPointer
std::function< CommandHandlerObject &(AudacityProject &) > CommandHandlerFinder
wxEvtHandler CommandHandlerObject
const TranslatableString desc
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
accessors for certain important windows associated with each project
static const AttachedProjectObjects::RegisteredFactory manager
static Settings & settings()
static const auto MenuPathStart
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
CommandManager implements a system for organizing all user-callable commands.
void UpdateCheckmarks(AudacityProject &project)
static CommandManager & Get(AudacityProject &project)
An explicitly nonlocalized string, not meant for the user to see.
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
static ProjectHistory & Get(AudacityProject &project)
static ProjectSettings & Get(AudacityProject &project)
std::vector< Identifier > Path
std::function< bool(const AudacityProject &) > Predicate
ReservedCommandFlag(const Predicate &predicate, const CommandFlagOptions &options={})
Holds a msgid for the translation catalog; may also bind format arguments.
static UndoManager & Get(AudacityProject &project)
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItem *pRegistry)
std::unique_ptr< BaseItem > BaseItemPtr
std::vector< BaseItemPtr > BaseItemPtrs
void RegisterItem(GroupItem ®istry, const Placement &placement, BaseItemPtr pItem)
~CommandGroupItem() override
CommandGroupItem(const Identifier &name_, std::vector< ComponentInterfaceSymbol > items_, CommandFunctorPointer callback_, CommandFlag flags_, bool isEffect_, CommandHandlerFinder finder_)
CommandItem(const CommandID &name_, const TranslatableString &label_in_, CommandFunctorPointer callback_, CommandFlag flags_, const CommandManager::Options &options_, CommandHandlerFinder finder_)
Type of message published by UndoManager.
enum UndoRedoMessage::Type type