OpenShot Audio Library | OpenShotAudio: juce_UndoManager.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.4.0

Loading...
Searching...
No Matches
juce_UndoManager.cpp
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
29struct UndoManager::ActionSet
30{
31 ActionSet (const String& transactionName) : name (transactionName)
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
62 OwnedArray<UndoableAction> actions;
63 String name;
64 Time time { Time::getCurrentTime() };
65};
66
67//==============================================================================
68UndoManager::UndoManager (int maxNumberOfUnitsToKeep, int minimumTransactions)
69{
70 setMaxNumberOfStoredUnits (maxNumberOfUnitsToKeep, minimumTransactions);
71}
72
73UndoManager::~UndoManager()
74{
75}
76
77//==============================================================================
78 void UndoManager::clearUndoHistory()
79{
80 transactions.clear();
81 totalUnitsStored = 0;
82 nextIndex = 0;
83 sendChangeMessage();
84}
85
86 int UndoManager::getNumberOfUnitsTakenUpByStoredCommands() const
87{
88 return totalUnitsStored;
89}
90
91 void UndoManager::setMaxNumberOfStoredUnits (int maxUnits, int minTransactions)
92{
93 maxNumUnitsToKeep = jmax (1, maxUnits);
94 minimumTransactionsToKeep = jmax (1, minTransactions);
95}
96
97//==============================================================================
98 bool UndoManager::perform (UndoableAction* newAction, const String& actionName)
99{
100 if (perform (newAction))
101 {
102 if (actionName.isNotEmpty())
103 setCurrentTransactionName (actionName);
104
105 return true;
106 }
107
108 return false;
109}
110
111 bool UndoManager::perform (UndoableAction* newAction)
112{
113 if (newAction != nullptr)
114 {
115 std::unique_ptr<UndoableAction> action (newAction);
116
117 if (isPerformingUndoRedo())
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();
153 sendChangeMessage();
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
209 void UndoManager::beginNewTransaction()
210{
211 beginNewTransaction ({});
212}
213
214 void UndoManager::beginNewTransaction (const String& actionName)
215{
216 newTransaction = true;
217 newTransactionName = actionName;
218}
219
220 void UndoManager::setCurrentTransactionName (const String& newName)
221{
222 if (newTransaction)
223 newTransactionName = newName;
224 else if (auto* action = getCurrentSet())
225 action->name = newName;
226}
227
228 String UndoManager::getCurrentTransactionName() const
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
240 bool UndoManager::isPerformingUndoRedo() const { return isInsideUndoRedoCall; }
241
242 bool UndoManager::canUndo() const { return getCurrentSet() != nullptr; }
243 bool UndoManager::canRedo() const { return getNextSet() != nullptr; }
244
245 bool UndoManager::undo()
246{
247 if (auto* s = getCurrentSet())
248 {
249 const ScopedValueSetter<bool> setter (isInsideUndoRedoCall, true);
250
251 if (s->undo())
252 --nextIndex;
253 else
254 clearUndoHistory();
255
256 beginNewTransaction();
257 sendChangeMessage();
258 return true;
259 }
260
261 return false;
262}
263
264 bool UndoManager::redo()
265{
266 if (auto* s = getNextSet())
267 {
268 const ScopedValueSetter<bool> setter (isInsideUndoRedoCall, true);
269
270 if (s->perform())
271 ++nextIndex;
272 else
273 clearUndoHistory();
274
275 beginNewTransaction();
276 sendChangeMessage();
277 return true;
278 }
279
280 return false;
281}
282
283 String UndoManager::getUndoDescription() const
284{
285 if (auto* s = getCurrentSet())
286 return s->name;
287
288 return {};
289}
290
291 String UndoManager::getRedoDescription() const
292{
293 if (auto* s = getNextSet())
294 return s->name;
295
296 return {};
297}
298
299 StringArray UndoManager::getUndoDescriptions() const
300{
301 StringArray descriptions;
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
312 StringArray UndoManager::getRedoDescriptions() const
313{
314 StringArray descriptions;
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
325 Time UndoManager::getTimeOfUndoTransaction() const
326{
327 if (auto* s = getCurrentSet())
328 return s->time;
329
330 return {};
331}
332
333 Time UndoManager::getTimeOfRedoTransaction() const
334{
335 if (auto* s = getNextSet())
336 return s->time;
337
338 return Time::getCurrentTime();
339}
340
341 bool UndoManager::undoCurrentTransactionOnly()
342{
343 if ((! newTransaction) && undo())
344 {
345 restoreStashedFutureTransactions();
346 return true;
347 }
348
349 return false;
350}
351
352 void UndoManager::getActionsInCurrentTransaction (Array<const UndoableAction*>& actionsFound) const
353{
354 if (! newTransaction)
355 if (auto* s = getCurrentSet())
356 for (auto* a : s->actions)
357 actionsFound.add (a);
358}
359
360 int UndoManager::getNumActionsInCurrentTransaction() const
361{
362 if (! newTransaction)
363 if (auto* s = getCurrentSet())
364 return s->actions.size();
365
366 return 0;
367}
368
369} // namespace juce
juce::Array
Definition juce_Array.h:56
juce::Array::add
void add(const ElementType &newElement)
Definition juce_Array.h:418
juce::ChangeBroadcaster::sendChangeMessage
void sendChangeMessage()
Definition juce_ChangeBroadcaster.cpp:65
juce::OwnedArray::size
int size() const noexcept
Definition juce_OwnedArray.h:129
juce::OwnedArray::getUnchecked
ObjectClass * getUnchecked(int index) const noexcept
Definition juce_OwnedArray.h:159
juce::OwnedArray::removeAndReturn
ObjectClass * removeAndReturn(int indexToRemove)
Definition juce_OwnedArray.h:592
juce::OwnedArray::remove
void remove(int indexToRemove, bool deleteObject=true)
Definition juce_OwnedArray.h:561
juce::OwnedArray::getFirst
ObjectClass * getFirst() const noexcept
Definition juce_OwnedArray.h:170
juce::OwnedArray::clear
void clear(bool deleteObjects=true)
Definition juce_OwnedArray.h:106
juce::OwnedArray::add
ObjectClass * add(ObjectClass *newObject)
Definition juce_OwnedArray.h:293
juce::OwnedArray::insert
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
Definition juce_OwnedArray.h:335
juce::ScopedValueSetter
Definition juce_ScopedValueSetter.h:55
juce::StringArray
Definition juce_StringArray.h:35
juce::StringArray::add
void add(String stringToAdd)
Definition juce_StringArray.cpp:136
juce::String
Definition juce_String.h:53
juce::String::isNotEmpty
bool isNotEmpty() const noexcept
Definition juce_String.h:316
juce::Time
Definition juce_Time.h:37
juce::Time::getCurrentTime
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition juce_Time.cpp:233
juce::UndoManager::beginNewTransaction
void beginNewTransaction()
Definition juce_UndoManager.cpp:209
juce::UndoManager::getTimeOfUndoTransaction
Time getTimeOfUndoTransaction() const
Definition juce_UndoManager.cpp:325
juce::UndoManager::getCurrentTransactionName
String getCurrentTransactionName() const
Definition juce_UndoManager.cpp:228
juce::UndoManager::setMaxNumberOfStoredUnits
void setMaxNumberOfStoredUnits(int maxNumberOfUnitsToKeep, int minimumTransactionsToKeep)
Definition juce_UndoManager.cpp:91
juce::UndoManager::redo
bool redo()
Definition juce_UndoManager.cpp:264
juce::UndoManager::getRedoDescription
String getRedoDescription() const
Definition juce_UndoManager.cpp:291
juce::UndoManager::getRedoDescriptions
StringArray getRedoDescriptions() const
Definition juce_UndoManager.cpp:312
juce::UndoManager::undo
bool undo()
Definition juce_UndoManager.cpp:245
juce::UndoManager::~UndoManager
~UndoManager() override
Definition juce_UndoManager.cpp:73
juce::UndoManager::isPerformingUndoRedo
bool isPerformingUndoRedo() const
Definition juce_UndoManager.cpp:240
juce::UndoManager::clearUndoHistory
void clearUndoHistory()
Definition juce_UndoManager.cpp:78
juce::UndoManager::canUndo
bool canUndo() const
Definition juce_UndoManager.cpp:242
juce::UndoManager::undoCurrentTransactionOnly
bool undoCurrentTransactionOnly()
Definition juce_UndoManager.cpp:341
juce::UndoManager::getNumberOfUnitsTakenUpByStoredCommands
int getNumberOfUnitsTakenUpByStoredCommands() const
Definition juce_UndoManager.cpp:86
juce::UndoManager::perform
bool perform(UndoableAction *action)
Definition juce_UndoManager.cpp:111
juce::UndoManager::getTimeOfRedoTransaction
Time getTimeOfRedoTransaction() const
Definition juce_UndoManager.cpp:333
juce::UndoManager::canRedo
bool canRedo() const
Definition juce_UndoManager.cpp:243
juce::UndoManager::getUndoDescriptions
StringArray getUndoDescriptions() const
Definition juce_UndoManager.cpp:299
juce::UndoManager::getUndoDescription
String getUndoDescription() const
Definition juce_UndoManager.cpp:283
juce::UndoManager::UndoManager
UndoManager(int maxNumberOfUnitsToKeep=30000, int minimumTransactionsToKeep=30)
Definition juce_UndoManager.cpp:68
juce::UndoManager::getActionsInCurrentTransaction
void getActionsInCurrentTransaction(Array< const UndoableAction * > &actionsFound) const
Definition juce_UndoManager.cpp:352
juce::UndoManager::getNumActionsInCurrentTransaction
int getNumActionsInCurrentTransaction() const
Definition juce_UndoManager.cpp:360
juce::UndoManager::setCurrentTransactionName
void setCurrentTransactionName(const String &newName)
Definition juce_UndoManager.cpp:220
juce::UndoableAction
Definition juce_UndoableAction.h:39