Audacity  2.2.2
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 "../Experimental.h"
16 
17 #include "CommandFunctors.h"
18 #include "CommandFlag.h"
19 
20 #include "../MemoryX.h"
21 #include "Keyboard.h"
22 #include <vector>
23 #include <wx/string.h>
24 #include <wx/menu.h>
25 #include <wx/hashmap.h>
26 
27 #include "../xml/XMLTagHandler.h"
28 
29 #include "audacity/Types.h"
30 
31 #include <unordered_map>
32 
33 using CommandParameter = wxString;
35 
37 {
38  MenuBarListEntry(const wxString &name_, wxMenuBar *menubar_)
39  : name(name_), menubar(menubar_)
40  {}
41 
42  wxString name;
43  wxMenuBar *menubar; // This structure does not assume memory ownership!
44 };
45 
47 {
48  SubMenuListEntry(const wxString &name_, std::unique_ptr<wxMenu> &&menu_)
49  : name(name_), menu( std::move(menu_) )
50  {}
51 
53  : name(std::move(that.name))
54  , menu(std::move(that.menu))
55  {
56  }
57 
58  wxString name;
59  std::unique_ptr<wxMenu> menu;
60 };
61 
63 {
64  int id;
65  wxString name;
66  wxString longLabel;
69  wxString label;
70  wxString labelPrefix;
71  wxString labelTop;
72  wxMenu *menu;
76  bool multi;
77  int index;
78  int count;
79  bool enabled;
81  bool wantKeyup;
82  bool isGlobal;
83  bool isOccult;
84  bool isEffect;
85  bool hasDialog;
88 };
89 
90 using MenuBarList = std::vector < MenuBarListEntry >;
91 
92 // to do: remove the extra indirection when Mac compiler moves to newer version
93 using SubMenuList = std::vector < std::unique_ptr<SubMenuListEntry> >;
94 
95 // This is an array of pointers, not structures, because the hash maps also point to them,
96 // so we don't want the structures to relocate with vector operations.
97 using CommandList = std::vector<std::unique_ptr<CommandListEntry>>;
98 
99 namespace std
100 {
101  template<> struct hash< NormalizedKeyString > {
102  size_t operator () (const NormalizedKeyString &str) const // noexcept
103  {
104  auto &stdstr = str.Raw(); // no allocations, a cheap fetch
105  using Hasher = std::hash< wxString >;
106  return Hasher{}( stdstr );
107  }
108  };
109 }
110 
111 using CommandKeyHash = std::unordered_map<NormalizedKeyString, CommandListEntry*>;
112 using CommandNameHash = std::unordered_map<wxString, CommandListEntry*>;
113 using CommandIDHash = std::unordered_map<int, CommandListEntry*>;
114 
115 class AudacityProject;
116 class CommandContext;
117 
118 class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
119 {
120  public:
121 
122  //
123  // Constructor / Destructor
124  //
125 
126  CommandManager();
127  virtual ~CommandManager();
128 
130  CommandManager &operator= (const CommandManager&) PROHIBITED;
131 
132  void SetMaxList();
133  void PurgeData();
134 
135  //
136  // Creating menus and adding commands
137  //
138 
139  std::unique_ptr<wxMenuBar> AddMenuBar(const wxString & sMenu);
140 
141  // You may either called SetCurrentMenu later followed by ClearCurrentMenu,
142  // or else BeginMenu followed by EndMenu. Don't mix them.
143  void BeginMenu(const wxString & tName);
144  void EndMenu();
145 
146  wxMenu* BeginSubMenu(const wxString & tName);
147  void EndSubMenu();
148 
149  /*
150  void InsertItem(const wxString & name,
151  const wxString & label,
152  CommandHandlerFinder finder,
153  CommandFunctorPointer callback,
154  const wxString & after,
155  int checkmark = -1);
156  */
157 
158  void AddItemList(const wxString & name,
159  const TranslatedInternalString items[],
160  size_t nItems,
161  CommandHandlerFinder finder,
162  CommandFunctorPointer callback,
163  bool bIsEffect = false);
164 
165  void AddCheck(const wxChar *name,
166  const wxChar *label,
167  bool hasDialog,
168  CommandHandlerFinder finder,
169  CommandFunctorPointer callback,
170  int checkmark = 0);
171 
172  void AddCheck(const wxChar *name,
173  const wxChar *label,
174  bool hasDialog,
175  CommandHandlerFinder finder,
176  CommandFunctorPointer callback,
177  int checkmark,
178  CommandFlag flags,
179  CommandMask mask);
180 
181  void AddItem(const wxChar *name,
182  const wxChar *label,
183  bool hasDialog,
184  CommandHandlerFinder finder,
185  CommandFunctorPointer callback,
188  bool bIsEffect = false,
189  const CommandParameter &parameter = CommandParameter{});
190 
191  void AddItem(const wxChar *name,
192  const wxChar *label_in,
193  bool hasDialog,
194  CommandHandlerFinder finder,
195  CommandFunctorPointer callback,
196  const wxChar *accel,
199  int checkmark = -1,
200  bool bIsEffect = false,
201  const CommandParameter &parameter = CommandParameter{});
202 
203  void AddSeparator();
204 
205  // A command doesn't actually appear in a menu but might have a
206  // keyboard shortcut.
207  void AddCommand(const wxChar *name,
208  const wxChar *label,
209  CommandHandlerFinder finder,
210  CommandFunctorPointer callback,
213 
214  void AddCommand(const wxChar *name,
215  const wxChar *label,
216  CommandHandlerFinder finder,
217  CommandFunctorPointer callback,
218  const wxChar *accel,
221 
222  void AddGlobalCommand(const wxChar *name,
223  const wxChar *label,
224  bool hasDialog,
225  CommandHandlerFinder finder,
226  CommandFunctorPointer callback,
227  const wxChar *accel);
228  //
229  // Command masks
230  //
231 
232  // For NEW items/commands
233  void SetDefaultFlags(CommandFlag flags, CommandMask mask);
234  CommandFlag GetDefaultFlags() const { return mDefaultFlags; }
235  CommandMask GetDefaultMask() const { return mDefaultMask; }
236 
237  void SetOccultCommands( bool bOccult);
238  CommandManager * SetLongName( const wxString & name ){
239  mLongNameForItem = name;
240  return this;
241  }
242 
243 
244  void SetCommandFlags(const wxString &name, CommandFlag flags, CommandMask mask);
245  void SetCommandFlags(const wxChar **names,
246  CommandFlag flags, CommandMask mask);
247  // Pass multiple command names as const wxChar *, terminated by NULL
248  void SetCommandFlags(CommandFlag flags, CommandMask mask, ...);
249 
250  //
251  // Modifying menus
252  //
253 
254  void EnableUsingFlags(CommandFlag flags, CommandMask mask);
255  void Enable(const wxString &name, bool enabled);
256  void Check(const wxString &name, bool checked);
257  void Modify(const wxString &name, const wxString &newLabel);
258 
259  // You may either called SetCurrentMenu later followed by ClearCurrentMenu,
260  // or else BeginMenu followed by EndMenu. Don't mix them.
261  void SetCurrentMenu(wxMenu * menu);
262  void ClearCurrentMenu();
263 
264  //
265  // Modifying accelerators
266  //
267 
268  void SetKeyFromName(const wxString &name, const NormalizedKeyString &key);
269  void SetKeyFromIndex(int i, const NormalizedKeyString &key);
270 
271  //
272  // Executing commands
273  //
274 
275  // "permit" allows filtering even if the active window isn't a child of the project.
276  // Lyrics and MixerTrackCluster classes use it.
277  bool FilterKeyEvent(AudacityProject *project, const wxKeyEvent & evt, bool permit = false);
278  bool HandleMenuID(int id, CommandFlag flags, CommandMask mask);
279  bool HandleTextualCommand(const wxString & Str, const CommandContext & context, CommandFlag flags, CommandMask mask);
280 
281  //
282  // Accessing
283  //
284 
285  void GetCategories(wxArrayString &cats);
286  void GetAllCommandNames(wxArrayString &names, bool includeMultis) const;
287  void GetAllCommandLabels(
288  wxArrayString &labels, std::vector<bool> &vHasDialog,
289  bool includeMultis) const;
290  void GetAllCommandData(
291  wxArrayString &names,
292  std::vector<NormalizedKeyString> &keys,
293  std::vector<NormalizedKeyString> &default_keys,
294  wxArrayString &labels, wxArrayString &categories,
295 #if defined(EXPERIMENTAL_KEY_VIEW)
296  wxArrayString &prefixes,
297 #endif
298  bool includeMultis);
299 
300  wxString GetNameFromID( int id );
301  wxString GetLabelFromName(const wxString &name);
302  wxString GetPrefixedLabelFromName(const wxString &name);
303  wxString GetCategoryFromName(const wxString &name);
304  NormalizedKeyString GetKeyFromName(const wxString &name) const;
305  NormalizedKeyString GetDefaultKeyFromName(const wxString &name);
306 
307  bool GetEnabled(const wxString &name);
308 
309 #if defined(__WXDEBUG__)
310  void CheckDups();
311 #endif
312 
313  //
314  // Loading/Saving
315  //
316 
317  void WriteXML(XMLWriter &xmlFile) const /* not override */;
318  void TellUserWhyDisallowed(const wxString & Name, CommandFlag flagsGot, CommandFlag flagsRequired);
319 
323  wxString DescribeCommandsAndShortcuts
324  (
325  // If a shortcut key is defined for the command, then it is appended,
326  // parenthesized, after the translated name.
327  const TranslatedInternalString commands[], size_t nCommands) const;
328 
329  // Sorted list of the shortcut keys to be exluded from the standard defaults
330  static const std::vector<NormalizedKeyString> &ExcludedList();
331 
332 protected:
333 
334  //
335  // Creating menus and adding commands
336  //
337 
338  int NextIdentifier(int ID);
339  CommandListEntry *NewIdentifier(const wxString & name,
340  const wxString & label,
341  const wxString & longLabel,
342  bool hasDialog,
343  wxMenu *menu,
344  CommandHandlerFinder finder,
345  CommandFunctorPointer callback,
346  const wxString &nameSuffix,
347  int index,
348  int count,
349  bool bIsEffect);
350  CommandListEntry *NewIdentifier(const wxString & name,
351  const wxString & label,
352  const wxString & longLabel,
353  bool hasDialog,
354  const wxString & accel,
355  wxMenu *menu,
356  CommandHandlerFinder finder,
357  CommandFunctorPointer callback,
358  const wxString &nameSuffix,
359  int index,
360  int count,
361  bool bIsEffect,
362  const CommandParameter &parameter);
363 
364  //
365  // Executing commands
366  //
367 
368  bool HandleCommandEntry(const CommandListEntry * entry, CommandFlag flags, CommandMask mask, const wxEvent * evt = NULL);
369 
370  //
371  // Modifying
372  //
373 
374  void Enable(CommandListEntry *entry, bool enabled);
375 
376  //
377  // Accessing
378  //
379 
380  wxMenuBar * CurrentMenuBar() const;
381  wxMenuBar * GetMenuBar(const wxString & sMenu) const;
382  wxMenu * CurrentSubMenu() const;
383  wxMenu * CurrentMenu() const;
384  wxString GetLabel(const CommandListEntry *entry) const;
385  wxString GetLabelWithDisabledAccel(const CommandListEntry *entry) const;
386 
387  //
388  // Loading/Saving
389  //
390 
391  bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
392  void HandleXMLEndTag(const wxChar *tag) override;
393  XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
394 
395 private:
396  // mMaxList only holds shortcuts that should not be added (by default)
397  // and is sorted.
398  std::vector<NormalizedKeyString> mMaxListOnly;
399 
408 
409  bool mbSeparatorAllowed; // false at the start of a menu and immediately after a separator.
410 
412  std::unique_ptr<wxMenu> uCurrentMenu;
413  wxMenu *mCurrentMenu {};
414 
416 
420 };
421 
422 #endif
wxString labelPrefix
static wxArrayString names()
Definition: Tags.cpp:697
List of SubMenuListEntry.
bool bMakingOccultCommands
int id
#define PROHIBITED
Definition: Audacity.h:224
List of CommandListEntry.
CommandMask mask
wxString label
CommandList mCommandList
virtual XMLTagHandler * HandleXMLChild(const wxChar *tag)=0
int count
wxString label
Definition: Tags.cpp:727
std::unique_ptr< wxMenu > uCurrentMenu
bool enabled
List of MenuBarListEntry.
SubMenuList mSubMenuList
wxMenuBar * menubar
CommandContext provides addiitonal information to an 'Apply()' command. It provides the project...
wxString name
CommandKeyHash mCommandKeyHash
wxString mCurrentMenuName
std::vector< NormalizedKeyString > mMaxListOnly
void(CommandHandlerObject::*)(const CommandContext &context) CommandFunctorPointer
int index
wxMenu * menu
std::unordered_map< NormalizedKeyString, CommandListEntry * > CommandKeyHash
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:176
CommandParameter parameter
SubMenuListEntry(SubMenuListEntry &&that)
CommandNameHash mCommandNameHash
CommandFunctorPointer callback
CommandListEntry is a structure used by CommandManager.
CommandManager * SetLongName(const wxString &name)
bool skipKeydown
virtual bool HandleXMLTag(const wxChar *tag, const wxChar **attrs)=0
CommandManager implements a system for organizing all user-callable commands.
CommandHandlerFinder finder
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:70
bool isEffect
bool isGlobal
bool multi
bool wantKeyup
#define EXPERIMENTAL_KEY_VIEW
Definition: Project.h:47
wxString name
CommandMask mDefaultMask
CommandFlag GetDefaultFlags() const
MenuBarList mMenuBarList
CommandMask GetDefaultMask() const
CommandFlag
Definition: CommandFlag.h:16
SubMenuListEntry(const wxString &name_, std::unique_ptr< wxMenu > &&menu_)
std::unique_ptr< wxMenu > menu
const wxChar * name
Definition: Distortion.cpp:94
NormalizedKeyString defaultKey
CommandFlag mDefaultFlags
std::unordered_map< wxString, CommandListEntry * > CommandNameHash
MenuBarListEntry(const wxString &name_, wxMenuBar *menubar_)
wxString labelTop
virtual void HandleXMLEndTag(const wxChar *WXUNUSED(tag))
Definition: XMLTagHandler.h:87
wxString longLabel
wxString mLongNameForItem
NormalizedKeyString key
CommandHandlerObject &(*)(AudacityProject &) CommandHandlerFinder
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:22
const wxString & Raw() const
Definition: Keyboard.h:27
CommandIDHash mCommandIDHash
CommandFlag flags
bool hasDialog
SubMenuListEntry is a structure used by CommandManager.
MenuBarListEntry is a structure used by CommandManager.
std::unordered_map< int, CommandListEntry * > CommandIDHash
bool isOccult
wxString name
wxString CommandParameter