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