Pioneer
Loading...
Searching...
No Matches
UndoStepType.h
Go to the documentation of this file.
1// Copyright © 2008-2024 Pioneer Developers. See AUTHORS.txt for details
2// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3
4#pragma once
5
6#include "editor/UndoSystem.h"
7
8namespace Editor {
9
10 // ========================================================================
11 // UndoClosure Helper
12 // ========================================================================
13
14 // UndoClosure wraps an UndoStep with a closure to be executed after an
15 // Undo() or Redo() operation.
16
17 template<typename ClosureType, typename T>
18 class UndoClosure : public T {
19 public:
20 template<typename ...Args>
21 UndoClosure(ClosureType &&closure, Args ...args) :
22 m_onUpdate(closure),
23 T(args...)
24 {}
25
26 void Swap() override {
27 T::Swap();
28 m_onUpdate();
29 }
30
31 private:
32 ClosureType m_onUpdate;
33 };
34
35 // ========================================================================
36 // UndoSingleValue Helper
37 // ========================================================================
38
39 // UndoSingleValueStep implements an UndoStep that allows tracking mutation
40 // of a single public member variable in any class.
41 //
42 // The only requirements are that the value type be Move-Constructible or
43 // Copy-Constructible, and that the value's memory location will not change
44 // between creation of the UndoStep and when it is undone/redone.
45
46 template<typename ValueType>
48 {
49 public:
50 // Simple copy-state constructor to clone the given value
51 UndoSingleValueStep(ValueType *data) :
52 m_dataRef(data),
53 m_state(*m_dataRef)
54 {
55 }
56
57 // Convenience constructor overload to allow updating a data value in a single call
58 // (allows UndoSingleValueStep to work for move-only values like std::unique_ptr)
59 UndoSingleValueStep(ValueType *data, const ValueType &newValue) :
60 m_dataRef(data),
61 m_state(newValue)
62 {
63 std::swap(m_state, *m_dataRef);
64 }
65
66 void Swap() override { std::swap(*m_dataRef, m_state); }
67
68 // Implement HasChanged as !(a == b) to reduce the number of operator overloads required
69 bool HasChanged() const override { return !(*m_dataRef == m_state); }
70
71 private:
72 ValueType *m_dataRef;
73 ValueType m_state;
74 };
75
76 // Helper functions to construct the above UndoStep helpers
77
78 template<typename T>
79 inline void AddUndoSingleValue(UndoSystem *s, T *dataRef)
80 {
82 }
83
84 template<typename T>
85 inline void AddUndoSingleValue(UndoSystem *s, T *dataRef, const T &newValue)
86 {
87 s->AddUndoStep<UndoSingleValueStep<T>>(dataRef, newValue);
88 }
89
90 template<typename T, typename UpdateClosure>
91 inline void AddUndoSingleValueClosure(UndoSystem *s, T *dataRef, UpdateClosure closure)
92 {
93 s->AddUndoStep<UndoClosure<UpdateClosure, UndoSingleValueStep<T>>>(std::move(closure), dataRef);
94 }
95
96 template<typename T, typename UpdateClosure>
97 inline void AddUndoSingleValueClosure(UndoSystem *s, T *dataRef, const T &newValue, UpdateClosure closure)
98 {
99 s->AddUndoStep<UndoClosure<UpdateClosure, UndoSingleValueStep<T>>>(std::move(closure), dataRef, newValue);
100 }
101
102 // ========================================================================
103 // UndoGetSetValue Helper
104 // ========================================================================
105
106 // UndoGetSetValueStep implements an UndoStep that allows tracking mutation
107 // of a single private member variable exposed by a GetX() / SetX() pair.
108 //
109 // The value type must be Copy-Constructible, and the object containing the
110 // variable must not be reallocated or destroyed during the lifetime of the
111 // UndoStep.
112
113 template<auto GetterFn, auto SetterFn, typename ValueType, typename Obj>
115 {
116 public:
118 m_dataRef(data),
119 m_state((m_dataRef->*GetterFn)())
120 {
121 }
122
123 UndoGetSetValueStep(Obj *data, const ValueType &newValue) :
124 m_dataRef(data),
125 m_state(newValue)
126 {
127 Swap();
128 }
129
130 // two-way swap with opaque setter/getter functions
131 void Swap() override {
132 ValueType t = (m_dataRef->*GetterFn)();
133 std::swap(t, m_state);
134 (m_dataRef->*SetterFn)(std::move(t));
135 }
136
137 bool HasChanged() const override { return !((m_dataRef->*GetterFn)() == m_state); }
138
139 private:
140 Obj *m_dataRef;
141 ValueType m_state;
142 };
143
144 // Helper functions to construct the above UndoStep helpers
145
146 template<auto GetterFn, auto SetterFn, typename Obj>
147 inline void AddUndoGetSetValue(UndoSystem *s, Obj *dataRef)
148 {
149 using ValueType = decltype((dataRef->*GetterFn)());
151 }
152
153 template<auto GetterFn, auto SetterFn, typename Obj, typename T>
154 inline void AddUndoGetSetValue(UndoSystem *s, Obj *dataRef, const T &newValue)
155 {
156 using ValueType = decltype((dataRef->*GetterFn)());
158 }
159
160 template<auto GetterFn, auto SetterFn, typename Obj, typename UpdateClosure>
161 inline void AddUndoGetSetValueClosure(UndoSystem *s, Obj *dataRef, UpdateClosure &&closure)
162 {
163 using ValueType = decltype((dataRef->*GetterFn)());
165 }
166
167 template<auto GetterFn, auto SetterFn, typename Obj, typename T, typename UpdateClosure>
168 inline void AddUndoGetSetValueClosure(UndoSystem *s, Obj *dataRef, const T &newValue, UpdateClosure &&closure)
169 {
170 using ValueType = decltype((dataRef->*GetterFn)());
172 }
173
174 // ========================================================================
175 // UndoVectorStep Helper
176 // ========================================================================
177
178 // UndoVectorStep implements an UndoStep that expresses mutation of a
179 // std::vector or similar container variable providing insert(), erase(),
180 // begin(), and size().
181 //
182 // The only requirements are that the value type be Move-Constructible or
183 // Copy-Constructible, and that the container's memory location will not
184 // change between creation of the UndoStep and when it is undone/redone.
185
186 template<typename Container>
188 {
189 public:
190 using ValueType = typename Container::value_type;
191
192 UndoVectorStep(Container *container, const ValueType &newValue, size_t insertIdx) :
193 m_container(*container),
194 m_value {},
195 m_idx(insertIdx),
196 m_insert(true)
197 {
198 Swap();
199 }
200
201 UndoVectorStep(Container *container, size_t removeIdx) :
202 m_container(*container),
203 m_value {},
204 m_idx(removeIdx),
205 m_insert(false)
206 {
207 Swap();
208 }
209
210 void Swap() override
211 {
212 if (m_insert) {
213 m_container.insert(m_container.begin() + m_idx, std::move(m_value));
214 } else {
215 m_value = std::move(m_container[m_idx]);
216 m_container.erase(m_container.begin() + m_idx);
217 }
218
219 m_insert = !m_insert;
220 }
221
222 private:
223 Container &m_container;
224 ValueType m_value;
225 size_t m_idx;
226 bool m_insert;
227 };
228
229 // ========================================================================
230 // UndoVectorSingleValue Helper
231 // ========================================================================
232
233 // UndoVectorSingleValue implements an UndoStep that expresses mutation of
234 // a value contained in a std::vector or similar container variable
235 // providing operator[](size_t) and size()
236 //
237 // The only requirements are that the value type be Move-Constructible or
238 // Copy-Constructible, and that the container's memory location will not
239 // change between creation of the UndoStep and when it is undone/redone.
240 //
241 // For containers that reallocate memory on mutation (e.g. std::vector)
242 // this UndoStep is a replacement for UndoSingleValueStep.
243
244 template<typename Container>
246 {
247 public:
248 using ValueType = typename Container::value_type;
249
250 UndoVectorSingleValueStep(Container *container, size_t idx) :
251 m_container(*container),
252 m_index(idx),
253 m_state(m_container[idx])
254 {
255 }
256
257 void Swap() override { std::swap(m_container[m_index], m_state); }
258
259 bool HasChanged() const override { return !(m_container[m_index] == m_state); }
260
261 private:
262 Container &m_container;
263 size_t m_index;
264 ValueType m_state;
265 };
266
267 // Helper functions to construct the above UndoStep helpers
268
269 template<typename T, typename Value = typename T::value_type>
270 inline void AddUndoVectorInsert(UndoSystem *s, T *containerRef, const Value &value, size_t idx = -1)
271 {
272 if (idx == size_t(-1))
273 idx = containerRef->size();
274
275 s->AddUndoStep<UndoVectorStep<T>>(containerRef, value, idx);
276 }
277
278 template<typename T>
279 inline void AddUndoVectorErase(UndoSystem *s, T *containerRef, size_t idx = -1)
280 {
281 if (idx == size_t(-1))
282 idx = containerRef->size() - 1;
283
284 s->AddUndoStep<UndoVectorStep<T>>(containerRef, idx);
285 }
286
287 template<typename T>
288 inline void AddUndoVectorSingleValue(UndoSystem *s, T *containerRef, size_t idx = -1)
289 {
290 if (idx == size_t(-1))
291 idx = containerRef->size() - 1;
292
293 s->AddUndoStep<UndoVectorSingleValueStep<T>>(containerRef, idx);
294 }
295
296 template<typename T, typename UpdateClosure, typename Value = typename T::value_type>
297 inline void AddUndoVectorInsertClosure(UndoSystem *s, T *containerRef, const Value &value, size_t idx, UpdateClosure closure)
298 {
299 s->AddUndoStep<UndoClosure<UpdateClosure, UndoVectorStep<T>>>(std::move(closure), containerRef, value, idx);
300 }
301
302 template<typename T, typename UpdateClosure>
303 inline void AddUndoVectorEraseClosure(UndoSystem *s, T *containerRef, size_t idx, UpdateClosure closure)
304 {
305 s->AddUndoStep<UndoClosure<UpdateClosure, UndoVectorStep<T>>>(std::move(closure), containerRef, idx);
306 }
307
308 template<typename T, typename UpdateClosure>
309 inline void AddUndoVectorSingleValue(UndoSystem *s, T *containerRef, size_t idx, UpdateClosure closure)
310 {
311 if (idx == size_t(-1))
312 idx = containerRef->size() - 1;
313
314 s->AddUndoStep<UndoClosure<UpdateClosure, UndoVectorSingleValueStep<T>>>(std::move(closure), containerRef, idx);
315 }
316
317} // namespace Editor
Definition: UndoStepType.h:18
void Swap() override
Definition: UndoStepType.h:26
UndoClosure(ClosureType &&closure, Args ...args)
Definition: UndoStepType.h:21
Definition: UndoStepType.h:115
void Swap() override
Definition: UndoStepType.h:131
UndoGetSetValueStep(Obj *data)
Definition: UndoStepType.h:117
UndoGetSetValueStep(Obj *data, const ValueType &newValue)
Definition: UndoStepType.h:123
bool HasChanged() const override
Definition: UndoStepType.h:137
Definition: UndoStepType.h:48
UndoSingleValueStep(ValueType *data)
Definition: UndoStepType.h:51
bool HasChanged() const override
Definition: UndoStepType.h:69
UndoSingleValueStep(ValueType *data, const ValueType &newValue)
Definition: UndoStepType.h:59
void Swap() override
Definition: UndoStepType.h:66
Definition: UndoSystem.h:31
Definition: UndoSystem.h:112
void AddUndoStep(Args &&...args)
Definition: UndoSystem.h:153
Definition: UndoStepType.h:246
bool HasChanged() const override
Definition: UndoStepType.h:259
void Swap() override
Definition: UndoStepType.h:257
UndoVectorSingleValueStep(Container *container, size_t idx)
Definition: UndoStepType.h:250
typename Container::value_type ValueType
Definition: UndoStepType.h:248
Definition: UndoStepType.h:188
typename Container::value_type ValueType
Definition: UndoStepType.h:190
UndoVectorStep(Container *container, size_t removeIdx)
Definition: UndoStepType.h:201
UndoVectorStep(Container *container, const ValueType &newValue, size_t insertIdx)
Definition: UndoStepType.h:192
void Swap() override
Definition: UndoStepType.h:210
Definition: ActionBinder.h:14
void AddUndoVectorInsertClosure(UndoSystem *s, T *containerRef, const Value &value, size_t idx, UpdateClosure closure)
Definition: UndoStepType.h:297
void AddUndoSingleValueClosure(UndoSystem *s, T *dataRef, UpdateClosure closure)
Definition: UndoStepType.h:91
void AddUndoGetSetValue(UndoSystem *s, Obj *dataRef)
Definition: UndoStepType.h:147
void AddUndoSingleValue(UndoSystem *s, T *dataRef)
Definition: UndoStepType.h:79
void AddUndoVectorErase(UndoSystem *s, T *containerRef, size_t idx=-1)
Definition: UndoStepType.h:279
void AddUndoVectorSingleValue(UndoSystem *s, T *containerRef, size_t idx=-1)
Definition: UndoStepType.h:288
void AddUndoVectorInsert(UndoSystem *s, T *containerRef, const Value &value, size_t idx=-1)
Definition: UndoStepType.h:270
void AddUndoVectorEraseClosure(UndoSystem *s, T *containerRef, size_t idx, UpdateClosure closure)
Definition: UndoStepType.h:303
void AddUndoGetSetValueClosure(UndoSystem *s, Obj *dataRef, UpdateClosure &&closure)
Definition: UndoStepType.h:161