Audacity 3.2.0
CommandManager.h
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 CommandManager.h
6
7 Brian Gunlogson
8 Dominic Mazzoni
9
10**********************************************************************/
11
12#ifndef __AUDACITY_COMMAND_MANAGER__
13#define __AUDACITY_COMMAND_MANAGER__
14
15#include "Identifier.h"
16
17#include "Callable.h"
18#include "ClientData.h"
19#include "CommandFunctors.h"
20#include "CommandFlag.h"
21#include "GlobalVariable.h"
22
23#include "Keyboard.h"
24#include "MenuRegistry.h"
25
26#include "Observer.h"
27#include "Prefs.h"
28#include "Project.h"
29
30#include <functional>
31#include <vector>
32
33#include "XMLTagHandler.h"
34
35#include <unordered_map>
36
37class wxEvent;
38
39class BoolSetting;
40
41using PluginID = wxString;
42
43class AudacityProject;
44class CommandContext;
45
48
49class MENUS_API CommandManager /* not final */
50 : public XMLTagHandler
51 , public ClientData::Base
52 , public Observer::Publisher<MenuUpdateMessage>
53 , private PrefsListener
54{
55protected:
57
58public:
59 struct CommandListEntry;
60
61 struct MENUS_API Factory : DefaultedGlobalHook<Factory,
62 Callable::SharedPtrFactory<CommandManager, AudacityProject &>::Function
63 >{};
64
66 static const CommandManager &Get( const AudacityProject &project );
67
68 // Interception of menu item handling.
69 // If it returns true, bypass the usual dispatch of commands.
70 struct MENUS_API GlobalMenuHook : GlobalHook<GlobalMenuHook,
71 bool(const CommandID&)
72 >{};
73
75 CommandManager(const CommandManager &) = delete;
77 ~CommandManager() override;
78
79 // If quick, skip some needlessly expensive checks.
80 CommandFlag GetUpdateFlags(bool quick = false) const;
81 void UpdatePrefs() override;
82
83 // Command Handling
84 bool ReportIfActionNotAllowed(
85 const TranslatableString & Name, CommandFlag & flags, CommandFlag flagsRqd );
86 bool TryToMakeActionAllowed(
87 CommandFlag & flags, CommandFlag flagsRqd );
88
90
91 // Last effect applied to this project
92 PluginID mLastGenerator{};
93 PluginID mLastEffect{};
94 PluginID mLastAnalyzer{};
95 int mLastAnalyzerRegistration = repeattypenone;
96 int mLastAnalyzerRegisteredId = -1;
97 PluginID mLastTool{};
98 int mLastToolRegistration = repeattypenone;
99 int mLastToolRegisteredId = -1;
100 enum {
101 repeattypenone = 0,
102 repeattypeplugin = 1,
103 repeattypeunique = 2,
104 repeattypeapplymacro = 3
105 };
106 unsigned mRepeatGeneratorFlags = 0;
107 unsigned mRepeatEffectFlags = 0;
108 unsigned mRepeatAnalyzerFlags = 0;
109 unsigned mRepeatToolFlags = 0;
110
111 // 0 is grey out, 1 is Autoselect, 2 is Give warnings.
113
114 // not configurable for now, but could be later.
115 bool mStopIfWasPaused{ true };
116
117 AudacityProject &GetProject() { return mProject; }
118 size_t NCommands() const { return mCommandList.size(); }
119
120 void PurgeData();
121
122 struct MENUS_API Populator
123 : MenuRegistry::Visitor<MenuRegistry::Traits>
124 {
125 using LeafVisitor = std::function<
126 void(const Registry::SingleItem &, const Registry::Path&)>;
128 LeafVisitor leafVisitor,
129 std::function<void()> doSeparator);
130 virtual ~Populator();
131
132 protected:
133 void DoBeginGroup(
135 void DoVisit(const Registry::SingleItem &item);
136 void DoEndGroup(
138
141 virtual void BeginMenu(const TranslatableString & tName);
142
145 virtual void BeginOccultCommands();
146
149 virtual void EndMenu();
150
153 virtual void EndOccultCommands();
154
158
161 virtual std::unique_ptr<CommandListEntry>
162 AllocateEntry(const MenuRegistry::Options &options);
166
169 virtual void VisitEntry(CommandListEntry &entry,
170 const MenuRegistry::Options *options);
171
172 void DoSeparator();
173
175 const TranslatableStrings &MenuNames() const { return mMenuNames; }
176
177 private:
178 void AddItemList(const CommandID & name,
179 const ComponentInterfaceSymbol items[],
180 size_t nItems,
182 CommandFunctorPointer callback,
183 CommandFlag flags,
184 bool bIsEffect = false);
185 void AddItem(const CommandID & name,
186 const TranslatableString &label_in,
188 CommandFunctorPointer callback,
189 CommandFlag flags,
190 const MenuRegistry::Options &options = {});
191 CommandListEntry *NewIdentifier(const CommandID & name,
194 CommandFunctorPointer callback,
195 const CommandID &nameSuffix,
196 int index,
197 int count,
198 const MenuRegistry::Options &options);
199 void AddGlobalCommand(const CommandID &name,
202 CommandFunctorPointer callback,
203 const MenuRegistry::Options &options = {});
204 void SetMaxList();
205
206 protected:
208
209 // false at the start of a menu and immediately after a separator.
210 bool mbSeparatorAllowed{ false };
211
212 private:
213 // mMaxList only holds shortcuts that should not be added (by default)
214 // and is sorted.
215 std::vector<NormalizedKeyString> mMaxListOnly;
217 std::vector<bool> mFlags;
218 int mCurrentID{ 17000 };
219 bool bMakingOccultCommands{ false };
220 };
221
222public:
223 void SetCommandFlags(const CommandID &name, CommandFlag flags);
224
225 void EnableUsingFlags(
226 CommandFlag flags, CommandFlag strictFlags);
227 void Enable(const wxString &name, bool enabled);
228 void Check(const CommandID &name, bool checked);
229 void Modify(const wxString &name, const TranslatableString &newLabel);
230
231 //
232 // Modifying accelerators
233 //
234
235 void SetKeyFromName(const CommandID &name, const NormalizedKeyString &key);
237 void SetKeyFromIndex(int i, const NormalizedKeyString &key);
238
239 bool HandleMenuID(int id, CommandFlag flags, bool alwaysEnabled);
240 void RegisterLastAnalyzer(const CommandContext& context);
241 void RegisterLastTool(const CommandContext& context);
242 void DoRepeatProcess(const CommandContext& context, int);
243
247 CommandNotFound
248 };
249
253 TextualCommandResult
255 const CommandContext & context, CommandFlag flags, bool alwaysEnabled);
256
257 //
258 // Accessing
259 //
260
261 TranslatableStrings GetCategories();
262 void GetAllCommandNames(CommandIDs &names, bool includeMultis) const;
263 void GetAllCommandLabels(
264 TranslatableStrings &labels, std::vector<bool> &vExcludeFromMacros,
265 bool includeMultis) const;
266 void GetAllCommandData(
268 std::vector<NormalizedKeyString> &keys,
269 std::vector<NormalizedKeyString> &default_keys,
270 TranslatableStrings &labels, TranslatableStrings &categories,
271#if defined(EXPERIMENTAL_KEY_VIEW)
272 TranslatableStrings &prefixes,
273#endif
274 bool includeMultis);
275
276 // Each command is assigned a numerical ID for use in wxMenu and wxEvent,
277 // which need not be the same across platforms or sessions
278 CommandID GetNameFromNumericID(int id) const;
279
280 TranslatableString GetLabelFromName(const CommandID &name) const;
281 TranslatableString GetPrefixedLabelFromName(const CommandID &name) const;
282 TranslatableString GetCategoryFromName(const CommandID &name) const;
283 NormalizedKeyString GetKeyFromName(const CommandID &name) const;
284 NormalizedKeyString GetDefaultKeyFromName(const CommandID &name) const;
285
286 bool GetEnabled(const CommandID &name) const;
287 int GetNumberOfKeysRead() const;
288
289#if defined(_DEBUG)
290 void CheckDups();
291#endif
292 // May have side-effect on the config file
293 TranslatableString ReportDuplicateShortcuts();
294
295 //
296 // Loading/Saving
297 //
298
299 void WriteXML(XMLWriter &xmlFile) const /* not override */;
300
304 TranslatableString DescribeCommandsAndShortcuts(
305 // If a shortcut key is defined for the command, then it is appended,
306 // parenthesized, after the translated name.
307 const ComponentInterfaceSymbol commands[], size_t nCommands) const;
308
309 // Sorted list of the shortcut keys to be excluded from the standard defaults
310 static const std::vector<NormalizedKeyString> &ExcludedList();
311
312private:
313
314 static int NextIdentifier(int ID);
315
316protected:
317 bool HandleCommandEntry(
318 const CommandListEntry * entry, CommandFlag flags,
319 bool alwaysEnabled, const wxEvent * evt = nullptr,
320 const CommandContext *pGivenContext = nullptr );
321
322 virtual void ExecuteCommand(const CommandContext &context,
323 const wxEvent *evt, const CommandListEntry &entry);
324
325 //
326 // Modifying
327 //
328
329private:
330 void Enable(CommandListEntry &entry, bool enabled);
331
332 //
333 // Accessing
334 //
335
336public:
337 void UpdateCheckmarks();
338
340
344 wxString FormatLabelForMenu(
345 const CommandID &id, const TranslatableString *pLabel) const;
346
347 void ModifyUndoMenuItems();
348
349 // checkActive is a temporary hack that should be removed as soon as we
350 // get multiple effect preview working
351 void UpdateMenus(bool checkActive = true);
352
353protected:
355 virtual bool ReallyDoQuickCheck();
356
357private:
358
359 //
360 // Loading/Saving
361 //
362
363 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override;
364 void HandleXMLEndTag(const std::string_view& tag) override;
365 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override;
366
367 void TellUserWhyDisallowed(const TranslatableString & Name, CommandFlag flagsGot,
368 CommandFlag flagsRequired);
369
370 void OnUndoRedo(struct UndoRedoMessage);
371
372protected:
374
375public:
376 struct MENUS_API CommandListEntry
377 {
378 static wxString FormatLabelForMenu(
379 const TranslatableString &translatableLabel,
380 const NormalizedKeyString &keyStr);
381
383
385 virtual void UpdateCheckmark(AudacityProject &project);
387 virtual void Modify(const TranslatableString &newLabel);
389 virtual bool GetEnabled() const;
391 virtual void Check(bool checked);
393 virtual void Enable(bool enabled);
395 virtual void EnableMultiItem(bool enabled);
396
397 wxString FormatLabelForMenu() const {
398 return FormatLabelForMenu(label, key);
399 }
400
401 int id;
412
413 // type of a function that determines checkmark state
414 using CheckFn = std::function< bool(AudacityProject&) >;
416
417 bool multi;
418 int index;
419 int count;
429 bool useStrictFlags{ false };
430 };
431
432protected:
434 std::unordered_map<NormalizedKeyString, CommandListEntry*>;
438
439private:
440 // This is an array of pointers, not structures, because the hash maps also
441 // point to them,
442 // so we don't want the structures to relocate with vector operations.
443 using CommandList = std::vector<std::unique_ptr<CommandListEntry>>;
446
447 using CommandNameHash = std::unordered_map<CommandID, CommandListEntry*>;
451
452 using CommandNumericIDHash = std::unordered_map<int, CommandListEntry*>;
457
460
462};
463#endif
Functions and classes that generate callable objects.
Utility ClientData::Site to register hooks into a host class that attach client data.
wxString PluginID
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:34
std::bitset< NCommandFlags > CommandFlag
Definition: CommandFlag.h:30
std::function< CommandHandlerObject &(AudacityProject &) > CommandHandlerFinder
const TranslatableString name
Definition: Distortion.cpp:76
std::vector< CommandID > CommandIDs
Definition: Identifier.h:233
static ProjectFileIORegistry::AttributeWriterEntry entry
static const AudacityProject::AttachedObjects::RegisteredFactory key
TranslatableString label
Definition: TagsEditor.cpp:165
static TranslatableStrings names
Definition: TagsEditor.cpp:153
const auto project
std::vector< TranslatableString > TranslatableStrings
std::vector< Attribute > AttributesList
Definition: XMLTagHandler.h:40
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:346
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
CommandListEntry is a structure used by CommandManager.
CommandManager implements a system for organizing all user-callable commands.
CommandList mCommandList
CommandManager & operator=(const CommandManager &)=delete
CommandNameHash mCommandNameHash
AudacityProject & mProject
std::unordered_map< int, CommandListEntry * > CommandNumericIDHash
static const TranslatableString COMMAND
std::unordered_map< CommandID, CommandListEntry * > CommandNameHash
CommandKeyHash mCommandKeyHash
size_t NCommands() const
std::unordered_map< NormalizedKeyString, CommandListEntry * > CommandKeyHash
std::vector< std::unique_ptr< CommandListEntry > > CommandList
AudacityProject & GetProject()
CommandManager(const CommandManager &)=delete
const Observer::Subscription mUndoSubscription
TranslatableString mNiceName
CommandNumericIDHash mCommandNumericIDHash
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Global function-valued variable, adding a convenient Call()
An object that sends messages to an open-ended list of subscribed callbacks.
Definition: Observer.h:108
A move-only handle representing a connection to a Publisher.
Definition: Observer.h:70
A listener notified of changes in preferences.
Definition: Prefs.h:652
virtual void UpdatePrefs()=0
Definition: Prefs.cpp:154
Holds a msgid for the translation catalog; may also bind format arguments.
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:42
virtual XMLTagHandler * HandleXMLChild(const std::string_view &tag)=0
virtual void HandleXMLEndTag(const std::string_view &WXUNUSED(tag))
Definition: XMLTagHandler.h:59
virtual bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs)=0
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:25
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:196
AUDACITY_DLL_API bool HandleTextualCommand(const CommandID &Str, const CommandContext &context, CommandFlag flags, bool alwaysEnabled)
std::vector< Identifier > Path
Definition: Registry.h:71
auto finder(TrackId id, int &distance)
A convenient default parameter for class template Site.
Definition: ClientData.h:28
bool skipKeydown
TranslatableString labelTop
std::function< bool(AudacityProject &) > CheckFn
bool allowDup
CommandFunctorPointer callback
NormalizedKeyString defaultKey
virtual ~CommandListEntry()
bool enabled
bool excludeFromMacros
CommandID name
TranslatableString longLabel
bool isGlobal
int count
bool isEffect
TranslatableString labelPrefix
CommandHandlerFinder finder
NormalizedKeyString key
bool multi
wxString FormatLabelForMenu() const
int id
bool isOccult
CheckFn checkmarkFn
int index
CommandFlag flags
CommandParameter parameter
bool wantKeyup
TranslatableString label
std::vector< bool > mFlags
const TranslatableStrings & MenuNames() const
Stack of names of menus that were begun and not yet ended.
std::vector< NormalizedKeyString > mMaxListOnly
std::function< void(const Registry::SingleItem &, const Registry::Path &)> LeafVisitor
AudacityProject & mProject
TranslatableStrings mMenuNames
Sent when menus update (such as for changing enablement of items)
Has variadic and range constructors that check types.
Definition: Registry.h:292
Common abstract base class for items that are not groups.
Definition: Registry.h:224
Type of message published by UndoManager.
Definition: UndoManager.h:55