1 // Copyright (c) 2010, Amar Takhar <verm@aegisub.org> 2 // 3 // Permission to use, copy, modify, and distribute this software for any 4 // purpose with or without fee is hereby granted, provided that the above 5 // copyright notice and this permission notice appear in all copies. 6 // 7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15 /// @file command.h 16 /// @brief Command base class and main header. 17 /// @ingroup command 18 19 #include <map> 20 #include <memory> 21 #include <string> 22 #include <vector> 23 24 #include <wx/bitmap.h> 25 #include <wx/intl.h> 26 #include <wx/string.h> 27 28 #include <libaegisub/exception.h> 29 30 namespace agi { struct Context; } 31 32 #define CMD_NAME(a) const char* name() const { return a; } 33 #define STR_MENU(a) wxString StrMenu(const agi::Context *) const { return _(a); } 34 #define STR_DISP(a) wxString StrDisplay(const agi::Context *) const { return _(a); } 35 #define STR_HELP(a) wxString StrHelp() const { return _(a); } 36 #define CMD_TYPE(a) int Type() const { using namespace cmd; return a; } 37 38 #define CMD_ICON(icon) wxBitmap Icon(int size, wxLayoutDirection dir = wxLayout_LeftToRight) const override { \ 39 if (size == 64) return GETIMAGEDIR(icon##_64, dir); \ 40 if (size == 48) return GETIMAGEDIR(icon##_48, dir); \ 41 if (size == 32) return GETIMAGEDIR(icon##_32, dir); \ 42 if (size == 24) return GETIMAGEDIR(icon##_24, dir); \ 43 return GETIMAGEDIR(icon##_16, dir); \ 44 } 45 46 #define COMMAND_GROUP(cname, cmdname, menu, disp, help) \ 47 struct cname final : public Command { \ 48 CMD_NAME(cmdname) \ 49 STR_MENU(menu) \ 50 STR_DISP(disp) \ 51 STR_HELP(help) \ 52 void operator()(agi::Context *) { } \ 53 } 54 55 /// Commands 56 namespace cmd { 57 DEFINE_EXCEPTION(CommandError, agi::Exception); 58 DEFINE_EXCEPTION(CommandNotFound, CommandError); 59 60 enum CommandFlags { 61 /// Default command type 62 COMMAND_NORMAL = 0, 63 64 /// Invoking this command toggles a setting of some sort. Any command 65 /// of this type should have IsActive implemented to signal the 66 /// current state of the thing being toggled, and invoking the command 67 /// twice should be a no-op 68 /// 69 /// This is mutually exclusive with COMMAND_RADIO 70 COMMAND_TOGGLE = 1, 71 72 /// Invoking this command sets a setting to a specific value. Any 73 /// command of this type should have IsActive implemented, and if 74 /// IsActive returns true, invoking the command should have no effect 75 /// 76 /// This is mutually exclusive with COMMAND_TOGGLE 77 COMMAND_RADIO = 2, 78 79 /// This command has an overridden Validate method 80 COMMAND_VALIDATE = 4, 81 82 /// This command's name may change based on the state of the project 83 COMMAND_DYNAMIC_NAME = 8, 84 85 /// This command's help string may change 86 COMMAND_DYNAMIC_HELP = 16, 87 88 /// This command's icon may change based on the state of the project 89 COMMAND_DYNAMIC_ICON = 32 90 }; 91 92 /// Holds an individual Command 93 class Command { 94 public: 95 /// Command name 96 virtual const char* name() const=0; 97 /// String for menu purposes including accelerators, but not hotkeys 98 virtual wxString StrMenu(const agi::Context *) const=0; 99 /// Plain string for display purposes; should normally be the same as StrMenu 100 /// but without accelerators 101 virtual wxString StrDisplay(const agi::Context *) const=0; 102 /// Short help string describing what the command does 103 virtual wxString StrHelp() const=0; 104 105 /// Get this command's type flags 106 /// @return Bitmask of CommandFlags Type()107 virtual int Type() const { return COMMAND_NORMAL; } 108 109 /// Request icon. 110 /// @param size Icon size. 111 virtual wxBitmap Icon(int size, wxLayoutDirection = wxLayout_LeftToRight) const { return wxBitmap{}; } 112 113 /// Command function 114 virtual void operator()(agi::Context *c)=0; 115 116 /// Check whether or not it makes sense to call this command at this time 117 /// @param c Project context 118 /// 119 /// This function should be very fast, as it is called whenever a menu 120 /// containing this command is opened and is called periodically for 121 /// any commands used in a toolbar 122 /// 123 /// Note that it is still legal to call commands when this returns 124 /// false. In this situation, commands should do nothing. 125 /// 126 /// This function should be overridden iff the command's type flags 127 /// include COMMAND_VALIDATE Validate(const agi::Context * c)128 virtual bool Validate(const agi::Context *c) { return true; } 129 130 /// Is the selectable value represented by this command currently selected? 131 /// @param c Project context 132 /// 133 /// As with Validate, this function should be very fast. 134 /// 135 /// This function should be overridden iff the command's type flags 136 /// include COMMAND_TOGGLE or COMMAND_RADIO IsActive(const agi::Context * c)137 virtual bool IsActive(const agi::Context *c) { return false; } 138 139 /// Destructor 140 virtual ~Command() = default; 141 }; 142 143 /// Init all builtin commands. 144 void init_builtin_commands(); 145 146 /// Register a command. 147 /// @param cmd Command object to register. 148 void reg(std::unique_ptr<Command> cmd); 149 150 /// Unregister a command. 151 /// @param cmd Command name to unregister. The associated command object is deleted. 152 void unreg(std::string const& name); 153 154 /// Call a command. 155 /// @param name Name of the command to call. 156 /// @param c Current Context. 157 void call(std::string const& name, agi::Context *c); 158 159 /// Retrieve a Command object. 160 /// @param Command object. 161 Command* get(std::string const& name); 162 163 /// Get a list of registered command names 164 std::vector<std::string> get_registered_commands(); 165 166 /// Unregister and deletes all commands 167 void clear(); 168 } // namespace cmd 169