JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_UndoManager.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
30{
32 {}
33
34 bool perform() const
35 {
36 for (auto* a : actions)
37 if (! a->perform())
38 return false;
39
40 return true;
41 }
42
43 bool undo() const
44 {
45 for (int i = actions.size(); --i >= 0;)
46 if (! actions.getUnchecked (i)->undo())
47 return false;
48
49 return true;
50 }
51
52 int getTotalSize() const
53 {
54 int total = 0;
55
56 for (auto* a : actions)
57 total += a->getSizeInUnits();
58
59 return total;
60 }
61
63 String name;
64 Time time { Time::getCurrentTime() };
65};
66
67//==============================================================================
72
76
77//==============================================================================
79{
80 transactions.clear();
81 totalUnitsStored = 0;
82 nextIndex = 0;
84}
85
87{
88 return totalUnitsStored;
89}
90
92{
93 maxNumUnitsToKeep = jmax (1, maxUnits);
94 minimumTransactionsToKeep = jmax (1, minTransactions);
95}
96
97//==============================================================================
99{
100 if (perform (newAction))
101 {
102 if (actionName.isNotEmpty())
104
105 return true;
106 }
107
108 return false;
109}
110
112{
113 if (newAction != nullptr)
114 {
116
118 {
119 jassertfalse; // Don't call perform() recursively from the UndoableAction::perform()
120 // or undo() methods, or else these actions will be discarded!
121 return false;
122 }
123
124 if (action->perform())
125 {
126 auto* actionSet = getCurrentSet();
127
128 if (actionSet != nullptr && ! newTransaction)
129 {
130 if (auto* lastAction = actionSet->actions.getLast())
131 {
132 if (auto coalescedAction = lastAction->createCoalescedAction (action.get()))
133 {
134 action.reset (coalescedAction);
135 totalUnitsStored -= lastAction->getSizeInUnits();
136 actionSet->actions.removeLast();
137 }
138 }
139 }
140 else
141 {
142 actionSet = new ActionSet (newTransactionName);
143 transactions.insert (nextIndex, actionSet);
144 ++nextIndex;
145 }
146
147 totalUnitsStored += action->getSizeInUnits();
148 actionSet->actions.add (std::move (action));
149 newTransaction = false;
150
151 moveFutureTransactionsToStash();
152 dropOldTransactionsIfTooLarge();
154 return true;
155 }
156 }
157
158 return false;
159}
160
161void UndoManager::moveFutureTransactionsToStash()
162{
163 if (nextIndex < transactions.size())
164 {
165 stashedFutureTransactions.clear();
166
167 while (nextIndex < transactions.size())
168 {
169 auto* removed = transactions.removeAndReturn (nextIndex);
170 stashedFutureTransactions.add (removed);
171 totalUnitsStored -= removed->getTotalSize();
172 }
173 }
174}
175
176void UndoManager::restoreStashedFutureTransactions()
177{
178 while (nextIndex < transactions.size())
179 {
180 totalUnitsStored -= transactions.getUnchecked (nextIndex)->getTotalSize();
181 transactions.remove (nextIndex);
182 }
183
184 for (auto* stashed : stashedFutureTransactions)
185 {
186 transactions.add (stashed);
187 totalUnitsStored += stashed->getTotalSize();
188 }
189
190 stashedFutureTransactions.clearQuick (false);
191}
192
193void UndoManager::dropOldTransactionsIfTooLarge()
194{
195 while (nextIndex > 0
196 && totalUnitsStored > maxNumUnitsToKeep
197 && transactions.size() > minimumTransactionsToKeep)
198 {
199 totalUnitsStored -= transactions.getFirst()->getTotalSize();
200 transactions.remove (0);
201 --nextIndex;
202
203 // if this fails, then some actions may not be returning
204 // consistent results from their getSizeInUnits() method
205 jassert (totalUnitsStored >= 0);
206 }
207}
208
213
215{
216 newTransaction = true;
217 newTransactionName = actionName;
218}
219
221{
222 if (newTransaction)
223 newTransactionName = newName;
224 else if (auto* action = getCurrentSet())
225 action->name = newName;
226}
227
229{
230 if (auto* action = getCurrentSet())
231 return action->name;
232
233 return newTransactionName;
234}
235
236//==============================================================================
237UndoManager::ActionSet* UndoManager::getCurrentSet() const { return transactions[nextIndex - 1]; }
238UndoManager::ActionSet* UndoManager::getNextSet() const { return transactions[nextIndex]; }
239
240bool UndoManager::isPerformingUndoRedo() const { return isInsideUndoRedoCall; }
241
242bool UndoManager::canUndo() const { return getCurrentSet() != nullptr; }
243bool UndoManager::canRedo() const { return getNextSet() != nullptr; }
244
246{
247 if (auto* s = getCurrentSet())
248 {
249 const ScopedValueSetter<bool> setter (isInsideUndoRedoCall, true);
250
251 if (s->undo())
252 --nextIndex;
253 else
255
258 return true;
259 }
260
261 return false;
262}
263
265{
266 if (auto* s = getNextSet())
267 {
268 const ScopedValueSetter<bool> setter (isInsideUndoRedoCall, true);
269
270 if (s->perform())
271 ++nextIndex;
272 else
274
277 return true;
278 }
279
280 return false;
281}
282
284{
285 if (auto* s = getCurrentSet())
286 return s->name;
287
288 return {};
289}
290
292{
293 if (auto* s = getNextSet())
294 return s->name;
295
296 return {};
297}
298
300{
302
303 for (int i = nextIndex;;)
304 {
305 if (auto* t = transactions[--i])
306 descriptions.add (t->name);
307 else
308 return descriptions;
309 }
310}
311
313{
315
316 for (int i = nextIndex;;)
317 {
318 if (auto* t = transactions[i++])
319 descriptions.add (t->name);
320 else
321 return descriptions;
322 }
323}
324
326{
327 if (auto* s = getCurrentSet())
328 return s->time;
329
330 return {};
331}
332
334{
335 if (auto* s = getNextSet())
336 return s->time;
337
338 return Time::getCurrentTime();
339}
340
342{
343 if ((! newTransaction) && undo())
344 {
345 restoreStashedFutureTransactions();
346 return true;
347 }
348
349 return false;
350}
351
353{
354 if (! newTransaction)
355 if (auto* s = getCurrentSet())
356 for (auto* a : s->actions)
357 actionsFound.add (a);
358}
359
361{
362 if (! newTransaction)
363 if (auto* s = getCurrentSet())
364 return s->actions.size();
365
366 return 0;
367}
368
369} // namespace juce
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:56
void sendChangeMessage()
Causes an asynchronous change message to be sent to all the registered listeners.
An array designed for holding objects.
Helper class providing an RAII-based mechanism for temporarily setting and then re-setting a value.
A special array for holding a list of strings.
void add(String stringToAdd)
Appends a string at the end of the array.
The JUCE String class!
Definition juce_String.h:53
Holds an absolute date and time.
Definition juce_Time.h:37
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
void beginNewTransaction()
Starts a new group of actions that together will be treated as a single transaction.
Time getTimeOfUndoTransaction() const
Returns the time to which the state would be restored if undo() was to be called.
String getCurrentTransactionName() const
Returns the name of the current transaction.
void setMaxNumberOfStoredUnits(int maxNumberOfUnitsToKeep, int minimumTransactionsToKeep)
Sets the amount of space that can be used for storing UndoableAction objects.
bool redo()
Tries to redo the last transaction that was undone.
String getRedoDescription() const
Returns the name of the transaction that will be redone when redo() is called.
StringArray getRedoDescriptions() const
Returns the names of the sequence of transactions that will be performed if redo() is repeatedly call...
bool undo()
Tries to roll-back the last transaction.
~UndoManager() override
Destructor.
bool isPerformingUndoRedo() const
Returns true if the caller code is in the middle of an undo or redo action.
void clearUndoHistory()
Deletes all stored actions in the list.
bool canUndo() const
Returns true if there's at least one action in the list to undo.
bool undoCurrentTransactionOnly()
Tries to roll-back any actions that were added to the current transaction.
int getNumberOfUnitsTakenUpByStoredCommands() const
Returns the current amount of space to use for storing UndoableAction objects.
bool perform(UndoableAction *action)
Performs an action and adds it to the undo history list.
Time getTimeOfRedoTransaction() const
Returns the time to which the state would be restored if redo() was to be called.
bool canRedo() const
Returns true if there's at least one action in the list to redo.
StringArray getUndoDescriptions() const
Returns the names of the sequence of transactions that will be performed if undo() is repeatedly call...
String getUndoDescription() const
Returns the name of the transaction that will be rolled-back when undo() is called.
UndoManager(int maxNumberOfUnitsToKeep=30000, int minimumTransactionsToKeep=30)
Creates an UndoManager.
void getActionsInCurrentTransaction(Array< const UndoableAction * > &actionsFound) const
Returns a list of the UndoableAction objects that have been performed during the transaction that is ...
int getNumActionsInCurrentTransaction() const
Returns the number of UndoableAction objects that have been performed during the transaction that is ...
void setCurrentTransactionName(const String &newName)
Changes the name stored for the current transaction.
Used by the UndoManager class to store an action which can be done and undone.
T get(T... args)
#define jassert(expression)
Platform-independent assertion macro.
#define jassertfalse
This will always cause an assertion failure.
JUCE Namespace.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
T reset(T... args)