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 TranslatableStrings &prefixes,
272 bool includeMultis);
273
274 // Each command is assigned a numerical ID for use in wxMenu and wxEvent,
275 // which need not be the same across platforms or sessions
276 CommandID GetNameFromNumericID(int id) const;
277
278 TranslatableString GetLabelFromName(const CommandID &name) const;
279 TranslatableString GetPrefixedLabelFromName(const CommandID &name) const;
280 TranslatableString GetCategoryFromName(const CommandID &name) const;
281 NormalizedKeyString GetKeyFromName(const CommandID &name) const;
282 NormalizedKeyString GetDefaultKeyFromName(const CommandID &name) const;
283
284 bool GetEnabled(const CommandID &name) const;
285 int GetNumberOfKeysRead() const;
286
287#if defined(_DEBUG)
288 void CheckDups();
289#endif
290 // May have side-effect on the config file
291 TranslatableString ReportDuplicateShortcuts();
292
293 //
294 // Loading/Saving
295 //
296
297 void WriteXML(XMLWriter &xmlFile) const /* not override */;
298
302 TranslatableString DescribeCommandsAndShortcuts(
303 // If a shortcut key is defined for the command, then it is appended,
304 // parenthesized, after the translated name.
305 const ComponentInterfaceSymbol commands[], size_t nCommands) const;
306
307 // Sorted list of the shortcut keys to be excluded from the standard defaults
308 static const std::vector<NormalizedKeyString> &ExcludedList();
309
310private:
311
312 static int NextIdentifier(int ID);
313
314protected:
315 bool HandleCommandEntry(
316 const CommandListEntry * entry, CommandFlag flags,
317 bool alwaysEnabled, const wxEvent * evt = nullptr,
318 const CommandContext *pGivenContext = nullptr );
319
320 virtual void ExecuteCommand(const CommandContext &context,
321 const wxEvent *evt, const CommandListEntry &entry);
322
323 //
324 // Modifying
325 //
326
327private:
328 void Enable(CommandListEntry &entry, bool enabled);
329
330 //
331 // Accessing
332 //
333
334public:
335 void UpdateCheckmarks();
336
338
342 wxString FormatLabelForMenu(
343 const CommandID &id, const TranslatableString *pLabel) const;
344
345 void ModifyUndoMenuItems();
346
347 // checkActive is a temporary hack that should be removed as soon as we
348 // get multiple effect preview working
349 void UpdateMenus(bool checkActive = true);
350
351protected:
353 virtual bool ReallyDoQuickCheck();
354
355private:
356
357 //
358 // Loading/Saving
359 //
360
361 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override;
362 void HandleXMLEndTag(const std::string_view& tag) override;
363 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override;
364
365 void TellUserWhyDisallowed(const TranslatableString & Name, CommandFlag flagsGot,
366 CommandFlag flagsRequired);
367
368 void OnUndoRedo(struct UndoRedoMessage);
369
370protected:
372
373public:
374 struct MENUS_API CommandListEntry
375 {
376 static wxString FormatLabelForMenu(
377 const TranslatableString &translatableLabel,
378 const NormalizedKeyString &keyStr);
379
381
383 virtual void UpdateCheckmark(AudacityProject &project);
385 virtual void Modify(const TranslatableString &newLabel);
387 virtual bool GetEnabled() const;
389 virtual void Check(bool checked);
391 virtual void Enable(bool enabled);
393 virtual void EnableMultiItem(bool enabled);
394
395 wxString FormatLabelForMenu() const {
396 return FormatLabelForMenu(label, key);
397 }
398
399 int id;
410
411 // type of a function that determines checkmark state
412 using CheckFn = std::function< bool(AudacityProject&) >;
414
415 bool multi;
416 int index;
417 int count;
427 bool useStrictFlags{ false };
428 };
429
430protected:
432 std::unordered_map<NormalizedKeyString, CommandListEntry*>;
436
437private:
438 // This is an array of pointers, not structures, because the hash maps also
439 // point to them,
440 // so we don't want the structures to relocate with vector operations.
441 using CommandList = std::vector<std::unique_ptr<CommandListEntry>>;
444
445 using CommandNameHash = std::unordered_map<CommandID, CommandListEntry*>;
449
450 using CommandNumericIDHash = std::unordered_map<int, CommandListEntry*>;
455
458
460};
461#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
std::vector< CommandID > CommandIDs
Definition: Identifier.h:233
static ProjectFileIORegistry::AttributeWriterEntry entry
static const AudacityProject::AttachedObjects::RegisteredFactory key
wxString name
Definition: TagsEditor.cpp:166
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:202
AUDACITY_DLL_API bool HandleTextualCommand(const CommandID &Str, const CommandContext &context, CommandFlag flags, bool alwaysEnabled)
std::vector< Identifier > Path
Definition: Registry.h:71
A convenient default parameter for class template Site.
Definition: ClientData.h:29
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