1 // 2 // CommandFlag.h 3 // Audacity 4 // 5 // Created by Paul Licameli on 11/22/16. 6 // 7 // 8 9 #ifndef __AUDACITY_COMMAND_FLAG__ 10 #define __AUDACITY_COMMAND_FLAG__ 11 12 // Flags used in command handling. 13 14 #include <bitset> 15 #include <functional> 16 #include <utility> 17 #include <wx/string.h> 18 19 #include "audacity/Types.h" 20 21 class AudacityProject; 22 23 // Increase the template parameter as needed to allow more flags 24 constexpr size_t NCommandFlags = 64; 25 static_assert( 26 NCommandFlags <= 8 * sizeof( unsigned long long ), 27 "NoFlagsSpecified may have incorrect value" 28 ); 29 30 // Type to specify conditions for enabling of a menu item 31 using CommandFlag = std::bitset<NCommandFlags>; 32 33 // Special constant values 34 constexpr CommandFlag 35 AlwaysEnabledFlag{}, // all zeroes 36 NoFlagsSpecified{ ~0ULL }; // all ones 37 38 struct CommandFlagOptions{ 39 // Supplied the translated name of the command, returns a translated 40 // error message 41 using MessageFormatter = 42 std::function< TranslatableString( const TranslatableString& ) >; 43 44 CommandFlagOptions() = default; 45 CommandFlagOptions( 46 const MessageFormatter &message_, 47 const wxString &helpPage_ = {}, 48 const TranslatableString &title_ = {} 49 ) : message{ message_ }, helpPage{ helpPage_ }, title{ title_ } 50 {} 51 QuickTestCommandFlagOptions52 CommandFlagOptions && QuickTest() && 53 { quickTest = true; return std::move( *this ); } DisableDefaultMessageCommandFlagOptions54 CommandFlagOptions && DisableDefaultMessage() && 55 { enableDefaultMessage = false; return std::move( *this ); } PriorityCommandFlagOptions56 CommandFlagOptions && Priority( unsigned priority_ ) && 57 { priority = priority_; return std::move( *this ); } 58 59 // null, or else computes non-default message for the dialog box when the 60 // condition is not satisfied for the selected command 61 MessageFormatter message; 62 63 // Title and help page are used only if a message function is given 64 wxString helpPage; 65 66 // Empty, or non-default title for the dialog box when the 67 // condition is not satisfied for the selected command 68 // This string must be given UN-translated. 69 TranslatableString title; 70 71 // Conditions with higher "priority" are preferred over others in choosing 72 // the help message 73 unsigned priority = 0; 74 75 // If false, and no other condition with a message is unsatisfied, then 76 // display no dialog box at all when this condition is not satisfied 77 bool enableDefaultMessage = true; 78 79 // If true, assume this is a cheap test to be done always. If false, the 80 // test may be skipped and the condition assumed to be unchanged since the 81 // last more comprehensive testing 82 bool quickTest = false; 83 }; 84 85 // Construct one statically to register (and reserve) a bit position in the set 86 // an associate it with a test function; those with quickTest = true are cheap 87 // to compute and always checked 88 class AUDACITY_DLL_API ReservedCommandFlag : public CommandFlag 89 { 90 public: 91 using Predicate = std::function< bool( const AudacityProject& ) >; 92 ReservedCommandFlag( const Predicate &predicate, 93 const CommandFlagOptions &options = {} ); 94 }; 95 96 // To describe auto-selection, stop-if-paused, etc.: 97 // A structure describing a set of conditions, another set that might be 98 // made true given the first, and the function that may make them true. 99 // If a menu item requires the second set, while the first set is true, 100 // then the enabler will be invoked (unless the menu item is constructed with 101 // the useStrictFlags option, or the applicability test first returns false). 102 // The item's full set of required flags is passed to the function. 103 104 // Computation of the flags is delayed inside a function -- because often you 105 // need to name a statically allocated CommandFlag, or a bitwise OR of some, 106 // while they may not have been initialized yet, during static initialization. 107 struct MenuItemEnabler { 108 using Flags = std::function< CommandFlag() >; 109 using Test = std::function< bool( const AudacityProject& ) >; 110 using Action = std::function< void( AudacityProject&, CommandFlag ) >; 111 112 const Flags actualFlags; 113 const Flags possibleFlags; 114 Test applicable; 115 Action tryEnable; 116 }; 117 118 // Typically this is statically constructed: 119 struct AUDACITY_DLL_API RegisteredMenuItemEnabler{ 120 RegisteredMenuItemEnabler( const MenuItemEnabler &enabler ); 121 }; 122 123 // Unnecessary #include to indicate otherwise hidden link dependencies 124 #include "Menus.h" 125 126 #endif 127