File indexing completed on 2024-05-19 04:24:18

0001 #ifndef KISCHANGEVALUECOMMAND_H
0002 #define KISCHANGEVALUECOMMAND_H
0003 
0004 #include "kundo2command.h"
0005 
0006 /**
0007  * A simple command that flips the state of a member variable in a
0008  * contained structure.
0009  *
0010  * For example, to change the variable `m_d->fooBar` to the value `newValue`
0011  * in an undoable fashion, just create a command like that:
0012  *
0013  *        \code{.cpp}
0014  *
0015  *        KUndo2Command *cmd =
0016  *            makeChangeValueCommand<&Private::fooBar>(m_d.data(), newValue);
0017  *
0018  *        \endcode
0019  *
0020  * It is not strictly necessary that `newValue` had the same type as the type
0021  * of the member variable. They may differ, given the types are convertible.
0022  */
0023 
0024 template <auto mem_ptr, typename ValueType>
0025 struct KisChangeValueCommand {};
0026 
0027 template <typename Base, typename Member, Member Base::* mem_ptr, typename ValueType>
0028 struct KisChangeValueCommand<mem_ptr, ValueType> : KUndo2Command
0029 {
0030     KisChangeValueCommand(Base *base, const ValueType &newValue, KUndo2Command *parent = nullptr)
0031         : KUndo2Command(parent)
0032         , m_base(base)
0033         , m_oldValue(m_base->*mem_ptr)
0034         , m_newValue(newValue)
0035     {
0036     }
0037 
0038     void redo() {
0039         KUndo2Command::redo();
0040         m_base->*mem_ptr = m_newValue;
0041     }
0042 
0043     void undo() {
0044         m_base->*mem_ptr = m_oldValue;
0045         KUndo2Command::undo();
0046     }
0047 
0048 protected:
0049     Base *m_base;
0050     ValueType m_oldValue;
0051     ValueType m_newValue;
0052 };
0053 
0054 
0055 /**
0056  * Creates KisChangeValueCommand on heap, automatically deducing the
0057  * type of `newValue`.
0058  */
0059 template <auto mem_ptr, typename Base, typename ValueType>
0060 KisChangeValueCommand<mem_ptr, ValueType> *makeChangeValueCommand(Base *base, const ValueType &newValue, KUndo2Command *parent = nullptr)
0061 {
0062     return new KisChangeValueCommand<mem_ptr, ValueType>(base, newValue, parent);
0063 }
0064 
0065 
0066 /**
0067  * KisChangeIndirectValueCommand has the same purpose as KisChangeValueCommand, but
0068  * changes the value of variable stored **inside** a pointer. Basically, it
0069  * dereferences the variable on every assignment operation.
0070  */
0071 
0072 template <auto mem_ptr, typename ValueType>
0073 struct KisChangeIndirectValueCommand {};
0074 
0075 template <typename Base, typename Member, Member Base::* mem_ptr, typename ValueType>
0076 struct KisChangeIndirectValueCommand<mem_ptr, ValueType> : KUndo2Command
0077 {
0078     KisChangeIndirectValueCommand(Base *base, const ValueType &newValue, KUndo2Command *parent = nullptr)
0079         : KUndo2Command(parent)
0080         , m_base(base)
0081         , m_oldValue(*(m_base->*mem_ptr))
0082         , m_newValue(newValue)
0083     {
0084     }
0085 
0086     void redo() {
0087         KUndo2Command::redo();
0088         *(m_base->*mem_ptr) = m_newValue;
0089     }
0090 
0091     void undo() {
0092         *(m_base->*mem_ptr) = m_oldValue;
0093         KUndo2Command::undo();
0094     }
0095 private:
0096     Base *m_base;
0097     ValueType m_oldValue;
0098     ValueType m_newValue;
0099 };
0100 
0101 /**
0102  * Creates KisChangeIndirectValueCommand on heap, automatically deducing the
0103  * type of `newValue`.
0104  */
0105 template <auto mem_ptr, typename Base, typename ValueType>
0106 KisChangeIndirectValueCommand<mem_ptr, ValueType>* makeChangeIndirectValueCommand(Base *base, const ValueType &newValue, KUndo2Command *parent = nullptr)
0107 {
0108     return new KisChangeIndirectValueCommand<mem_ptr, ValueType>(base, newValue, parent);
0109 }
0110 
0111 #endif // KISCHANGEVALUECOMMAND_H