File indexing completed on 2024-05-12 16:23:28
0001 /*************************************************************************** 0002 * Copyright (C) 2013 by Linuxstopmotion contributors; * 0003 * see the AUTHORS file for details. * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 0021 #ifndef EXECUTOR_H_ 0022 #define EXECUTOR_H_ 0023 0024 #include <exception> 0025 #include <memory> 0026 0027 /** 0028 * Thrown if a command factory attempts to read a parameter from the log files 0029 * that is of the wrong type, is not present or otherwise does not parse. 0030 */ 0031 class IncorrectParameterException : public std::exception { 0032 const char* what() const throw(); 0033 }; 0034 0035 /** 0036 * Thrown if a line from the log parses correctly but has extra unexpected 0037 * characters at its end. 0038 */ 0039 class MalformedLineException : public std::exception { 0040 const char* what() const throw(); 0041 }; 0042 0043 /** 0044 * Thrown if the parameters for a command (from the log or from a caller) are 0045 * inappropriate for the current state of the model. 0046 */ 0047 class ParametersOutOfRangeException : public std::exception { 0048 public: 0049 ParametersOutOfRangeException() { 0050 } 0051 const char* what() const throw(); 0052 }; 0053 0054 class CommandFactory; 0055 class CommandLogger; 0056 class ErrorHandler; 0057 class Parameters; 0058 class RandomSource; 0059 class UndoRedoObserver; 0060 0061 /** 0062 * Thrown if @ref CommandFactory::Execute is called with a name for which no 0063 * command has been added, or if @ref CommandFactory::executeRandomCommands is 0064 * called on a @ref CommandFactory which has had no commands added, or if 0065 * @ref CommandFactory::executeRandomConstructiveCommands is called 0066 * on a @ref CommandFactory which has had no constructive commands set. 0067 */ 0068 class UnknownCommandException : public std::exception { 0069 const char* what() const throw(); 0070 }; 0071 0072 class CommandNameAlreadyUsedException : public std::exception { 0073 const char* what() const throw(); 0074 }; 0075 0076 class Executor { 0077 public: 0078 virtual ~Executor() = 0; 0079 /** 0080 * Executes a command, logging it and putting its inverse onto the undo 0081 * stack. Be careful that the argument list exactly matches what the 0082 * command expects; in particular, all integers should be @c int32_t. If 0083 * you supply a command factory, you should also supply a wrapper for this 0084 * Execute function to make sure this is done correctly, for example: 0085 * @code{.cpp} 0086 * void ExecuteAddFrame(Executor& e, const char* filename, int32_t sceneNo, 0087 * int32_t frameNo) { 0088 * e.Execute("addf", filename, sceneNo, frameNo); 0089 * } 0090 * @endcode 0091 * @param name The name with which the command's factory was registered. 0092 */ 0093 virtual void execute(const char* name, ...) = 0; 0094 /** 0095 * Executes a command, logging it and putting its inverse onto the undo 0096 * stack. 0097 * @param name The name with which the command's factory was registered. 0098 * @param params Supplier of the parameters to the command. 0099 */ 0100 virtual void execute(const char* name, Parameters& params) = 0; 0101 /** 0102 * Executes the command described by (the first line of) @a line, a line 0103 * from a command log previously written by a call to @ref execute. 0104 * @param line Null- or line-ending-terminated string; a line from the log. 0105 * @return true if a command was executed, false if the line was empty or 0106 * contained only undo and redo instructions. 0107 * @throws MalformedLineException if the line is neither empty nor starts 0108 * with a command name. 0109 */ 0110 virtual bool executeFromLog(const char* line, ErrorHandler& e) = 0; 0111 /** 0112 * Executes a random set of commands. Used for testing. 0113 * @param rng The random number generator. 0114 * @param min The minimum number of commands that should be generated. 0115 * @param max The maximum number of commands that should be generated. 0116 * @param [out] commandCount Returns the number of commands actually 0117 * executed, even if an exception is thrown. 0118 */ 0119 virtual void executeRandomCommands(int& commandCount, RandomSource& rng, 0120 int min, int max) = 0; 0121 /** 0122 * Executes a random set of commands. Used for testing for constructing 0123 * fresh models from empty models. Only commands that were added with the 0124 * @a constructive parameter of @ref addCommand set to @c true are used. 0125 * @param rng The random number generator. 0126 */ 0127 virtual void executeRandomConstructiveCommands(RandomSource& rng) = 0; 0128 /** 0129 * Make a command available for execution. It is assumed that @a name 0130 * endures for the lifetime of the Executor. Ideally name should be a 0131 * static constant, not heap allocated; for example 0132 * @code{.cpp} 0133 * executor.addCommand("addf", addFactory, true); 0134 * @endcode 0135 * @throws CommandNameAlreadyUsedException if a factory has already 0136 * been registered under @a name. 0137 * @param name The name of the command. Will need to be supplied in a 0138 * call to @ref Execute in order to use @a factory. 0139 * @param factory The factory that makes these sort of commands. 0140 * @param constructive If true is passed, test code will use this 0141 * factory to construct initial model states from empty models. Therefore 0142 * @c true should be passed whenever the command is useful in constructing 0143 * an initial state. For example, an add operation is constructive, but a 0144 * delete or a move is not. 0145 * @ref executeRandomConstructiveCommands uses only those factories 0146 * passed here with @a constructive set to @c true. 0147 */ 0148 virtual void addCommand(const char* name, 0149 std::unique_ptr<CommandFactory>factory, 0150 bool constructive = false) = 0; 0151 /** 0152 * Sets the logger to be used to record commands executed. 0153 * @param logger The logger to be set. Ownership is not passed. 0154 * Pass NULL to get no logging. 0155 */ 0156 virtual void setCommandLogger(CommandLogger* logger) = 0; 0157 /** 0158 * Clears the undo and redo stacks. 0159 */ 0160 virtual void clearHistory() = 0; 0161 /** 0162 * Undoes the most recent command. 0163 * @return true on success, false if nothing was on the undo stack. 0164 */ 0165 virtual bool undo() = 0; 0166 /** 0167 * Redoes the most recently undone command. 0168 * @return true on success, false if nothing was on the redo stack. 0169 */ 0170 virtual bool redo() = 0; 0171 /** 0172 * Returns true if and only if there is a command waiting to be undone. 0173 */ 0174 virtual bool canUndo() const = 0; 0175 /** 0176 * Returns true if and only if there is a command waiting to be redone. 0177 */ 0178 virtual bool canRedo() const = 0; 0179 /** 0180 * The number of commands registered. 0181 * @par 0182 * Useful for determining how many randomized tests to run. 0183 */ 0184 virtual int commandCount() const = 0; 0185 /** 0186 * Sets the observer to be notified when {@ref canUndo} or {@ref canRedo} 0187 * change what they would return. 0188 * @param observer The new observer to be set. The old observer is unset. 0189 * A null pointer means no observer. Ownership is not passed. 0190 */ 0191 virtual void setUndoRedoObserver(UndoRedoObserver* observer) = 0; 0192 }; 0193 0194 /** 0195 * Create a new executor. 0196 * @return The new {@ref Executor}; ownership is returned. 0197 */ 0198 Executor* makeExecutor(); 0199 0200 #endif /* EXECUTOR_H_ */