OpenShot Audio Library | OpenShotAudio: juce_UndoManager.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.3.2

Loading...
Searching...
No Matches
juce_UndoManager.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
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 5 End-User License
11 Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12 27th April 2017).
13
14 End User License Agreement: www.juce.com/juce-5-licence
15 Privacy Policy: www.juce.com/juce-5-privacy-policy
16
17 Or: You may also use this code under the terms of the GPL v3 (see
18 www.gnu.org/licenses).
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29
30struct UndoManager::ActionSet
31{
32 ActionSet (const String& transactionName) : name (transactionName)
33 {}
34
35 bool perform() const
36 {
37 for (auto* a : actions)
38 if (! a->perform())
39 return false;
40
41 return true;
42 }
43
44 bool undo() const
45 {
46 for (int i = actions.size(); --i >= 0;)
47 if (! actions.getUnchecked(i)->undo())
48 return false;
49
50 return true;
51 }
52
53 int getTotalSize() const
54 {
55 int total = 0;
56
57 for (auto* a : actions)
58 total += a->getSizeInUnits();
59
60 return total;
61 }
62
63 OwnedArray<UndoableAction> actions;
64 String name;
65 Time time { Time::getCurrentTime() };
66};
67
68//==============================================================================
69UndoManager::UndoManager (int maxNumberOfUnitsToKeep, int minimumTransactions)
70{
71 setMaxNumberOfStoredUnits (maxNumberOfUnitsToKeep, minimumTransactions);
72}
73
74UndoManager::~UndoManager()
75{
76}
77
78//==============================================================================
79 void UndoManager::clearUndoHistory()
80{
81 transactions.clear();
82 totalUnitsStored = 0;
83 nextIndex = 0;
84 sendChangeMessage();
85}
86
87 int UndoManager::getNumberOfUnitsTakenUpByStoredCommands() const
88{
89 return totalUnitsStored;
90}
91
92 void UndoManager::setMaxNumberOfStoredUnits (int maxUnits, int minTransactions)
93{
94 maxNumUnitsToKeep = jmax (1, maxUnits);
95 minimumTransactionsToKeep = jmax (1, minTransactions);
96}
97
98//==============================================================================
99 bool UndoManager::perform (UndoableAction* newAction, const String& actionName)
100{
101 if (perform (newAction))
102 {
103 if (actionName.isNotEmpty())
104 setCurrentTransactionName (actionName);
105
106 return true;
107 }
108
109 return false;
110}
111
112 bool UndoManager::perform (UndoableAction* newAction)
113{
114 if (newAction != nullptr)
115 {
116 std::unique_ptr<UndoableAction> action (newAction);
117
118 if (isPerformingUndoRedo())
119 {
120 jassertfalse; // Don't call perform() recursively from the UndoableAction::perform()
121 // or undo() methods, or else these actions will be discarded!
122 return false;
123 }
124
125 if (action->perform())
126 {
127 auto* actionSet = getCurrentSet();
128
129 if (actionSet != nullptr && ! newTransaction)
130 {
131 if (auto* lastAction = actionSet->actions.getLast())
132 {
133 if (auto coalescedAction = lastAction->createCoalescedAction (action.get()))
134 {
135 action.reset (coalescedAction);
136 totalUnitsStored -= lastAction->getSizeInUnits();
137 actionSet->actions.removeLast();
138 }
139 }
140 }
141 else
142 {
143 actionSet = new ActionSet (newTransactionName);
144 transactions.insert (nextIndex, actionSet);
145 ++nextIndex;
146 }
147
148 totalUnitsStored += action->getSizeInUnits();
149 actionSet->actions.add (std::move (action));
150 newTransaction = false;
151
152 moveFutureTransactionsToStash();
153 dropOldTransactionsIfTooLarge();
154 sendChangeMessage();
155 return true;
156 }
157 }
158
159 return false;
160}
161
162void UndoManager::moveFutureTransactionsToStash()
163{
164 if (nextIndex < transactions.size())
165 {
166 stashedFutureTransactions.clear();
167
168 while (nextIndex < transactions.size())
169 {
170 auto* removed = transactions.removeAndReturn (nextIndex);
171 stashedFutureTransactions.add (removed);
172 totalUnitsStored -= removed->getTotalSize();
173 }
174 }
175}
176
177void UndoManager::restoreStashedFutureTransactions()
178{
179 while (nextIndex < transactions.size())
180 {
181 totalUnitsStored -= transactions.getUnchecked (nextIndex)->getTotalSize();
182 transactions.remove (nextIndex);
183 }
184
185 for (auto* stashed : stashedFutureTransactions)
186 {
187 transactions.add (stashed);
188 totalUnitsStored += stashed->getTotalSize();
189 }
190
191 stashedFutureTransactions.clearQuick (false);
192}
193
194void UndoManager::dropOldTransactionsIfTooLarge()
195{
196 while (nextIndex > 0
197 && totalUnitsStored > maxNumUnitsToKeep
198 && transactions.size() > minimumTransactionsToKeep)
199 {
200 totalUnitsStored -= transactions.getFirst()->getTotalSize();
201 transactions.remove (0);
202 --nextIndex;
203
204 // if this fails, then some actions may not be returning
205 // consistent results from their getSizeInUnits() method
206 jassert (totalUnitsStored >= 0);
207 }
208}
209
210 void UndoManager::beginNewTransaction()
211{
212 beginNewTransaction ({});
213}
214
215 void UndoManager::beginNewTransaction (const String& actionName)
216{
217 newTransaction = true;
218 newTransactionName = actionName;
219}
220
221 void UndoManager::setCurrentTransactionName (const String& newName)
222{
223 if (newTransaction)
224 newTransactionName = newName;
225 else if (auto* action = getCurrentSet())
226 action->name = newName;
227}
228
229 String UndoManager::getCurrentTransactionName() const
230{
231 if (auto* action = getCurrentSet())
232 return action->name;
233
234 return newTransactionName;
235}
236
237//==============================================================================
238UndoManager::ActionSet* UndoManager::getCurrentSet() const { return transactions[nextIndex - 1]; }
239UndoManager::ActionSet* UndoManager::getNextSet() const { return transactions[nextIndex]; }
240
241 bool UndoManager::isPerformingUndoRedo() const { return isInsideUndoRedoCall; }
242
243 bool UndoManager::canUndo() const { return getCurrentSet() != nullptr; }
244 bool UndoManager::canRedo() const { return getNextSet() != nullptr; }
245
246 bool UndoManager::undo()
247{
248 if (auto* s = getCurrentSet())
249 {
250 const ScopedValueSetter<bool> setter (isInsideUndoRedoCall, true);
251
252 if (s->undo())
253 --nextIndex;
254 else
255 clearUndoHistory();
256
257 beginNewTransaction();
258 sendChangeMessage();
259 return true;
260 }
261
262 return false;
263}
264
265 bool UndoManager::redo()
266{
267 if (auto* s = getNextSet())
268 {
269 const ScopedValueSetter<bool> setter (isInsideUndoRedoCall, true);
270
271 if (s->perform())
272 ++nextIndex;
273 else
274 clearUndoHistory();
275
276 beginNewTransaction();
277 sendChangeMessage();
278 return true;
279 }
280
281 return false;
282}
283
284 String UndoManager::getUndoDescription() const
285{
286 if (auto* s = getCurrentSet())
287 return s->name;
288
289 return {};
290}
291
292 String UndoManager::getRedoDescription() const
293{
294 if (auto* s = getNextSet())
295 return s->name;
296
297 return {};
298}
299
300 StringArray UndoManager::getUndoDescriptions() const
301{
302 StringArray descriptions;
303
304 for (int i = nextIndex;;)
305 {
306 if (auto* t = transactions[--i])
307 descriptions.add (t->name);
308 else
309 return descriptions;
310 }
311}
312
313 StringArray UndoManager::getRedoDescriptions() const
314{
315 StringArray descriptions;
316
317 for (int i = nextIndex;;)
318 {
319 if (auto* t = transactions[i++])
320 descriptions.add (t->name);
321 else
322 return descriptions;
323 }
324}
325
326 Time UndoManager::getTimeOfUndoTransaction() const
327{
328 if (auto* s = getCurrentSet())
329 return s->time;
330
331 return {};
332}
333
334 Time UndoManager::getTimeOfRedoTransaction() const
335{
336 if (auto* s = getNextSet())
337 return s->time;
338
339 return Time::getCurrentTime();
340}
341
342 bool UndoManager::undoCurrentTransactionOnly()
343{
344 if ((! newTransaction) && undo())
345 {
346 restoreStashedFutureTransactions();
347 return true;
348 }
349
350 return false;
351}
352
353 void UndoManager::getActionsInCurrentTransaction (Array<const UndoableAction*>& actionsFound) const
354{
355 if (! newTransaction)
356 if (auto* s = getCurrentSet())
357 for (auto* a : s->actions)
358 actionsFound.add (a);
359}
360
361 int UndoManager::getNumActionsInCurrentTransaction() const
362{
363 if (! newTransaction)
364 if (auto* s = getCurrentSet())
365 return s->actions.size();
366
367 return 0;
368}
369
370} // 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:130
juce::OwnedArray::getUnchecked
ObjectClass * getUnchecked(int index) const noexcept
Definition: juce_OwnedArray.h:160
juce::OwnedArray::removeAndReturn
ObjectClass * removeAndReturn(int indexToRemove)
Definition: juce_OwnedArray.h:629
juce::OwnedArray::remove
void remove(int indexToRemove, bool deleteObject=true)
Definition: juce_OwnedArray.h:598
juce::OwnedArray::getFirst
ObjectClass * getFirst() const noexcept
Definition: juce_OwnedArray.h:171
juce::OwnedArray::clear
void clear(bool deleteObjects=true)
Definition: juce_OwnedArray.h:107
juce::OwnedArray::add
ObjectClass * add(ObjectClass *newObject)
Definition: juce_OwnedArray.h:294
juce::OwnedArray::insert
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
Definition: juce_OwnedArray.h:336
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:135
juce::String
Definition: juce_String.h:39
juce::String::isNotEmpty
bool isNotEmpty() const noexcept
Definition: juce_String.h:302
juce::Time
Definition: juce_Time.h:37
juce::Time::getCurrentTime
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition: juce_Time.cpp:218
juce::UndoManager::beginNewTransaction
void beginNewTransaction()
Definition: juce_UndoManager.cpp:210
juce::UndoManager::getTimeOfUndoTransaction
Time getTimeOfUndoTransaction() const
Definition: juce_UndoManager.cpp:326
juce::UndoManager::getCurrentTransactionName
String getCurrentTransactionName() const
Definition: juce_UndoManager.cpp:229
juce::UndoManager::setMaxNumberOfStoredUnits
void setMaxNumberOfStoredUnits(int maxNumberOfUnitsToKeep, int minimumTransactionsToKeep)
Definition: juce_UndoManager.cpp:92
juce::UndoManager::redo
bool redo()
Definition: juce_UndoManager.cpp:265
juce::UndoManager::getRedoDescription
String getRedoDescription() const
Definition: juce_UndoManager.cpp:292
juce::UndoManager::getRedoDescriptions
StringArray getRedoDescriptions() const
Definition: juce_UndoManager.cpp:313
juce::UndoManager::undo
bool undo()
Definition: juce_UndoManager.cpp:246
juce::UndoManager::~UndoManager
~UndoManager() override
Definition: juce_UndoManager.cpp:74
juce::UndoManager::isPerformingUndoRedo
bool isPerformingUndoRedo() const
Definition: juce_UndoManager.cpp:241
juce::UndoManager::clearUndoHistory
void clearUndoHistory()
Definition: juce_UndoManager.cpp:79
juce::UndoManager::canUndo
bool canUndo() const
Definition: juce_UndoManager.cpp:243
juce::UndoManager::undoCurrentTransactionOnly
bool undoCurrentTransactionOnly()
Definition: juce_UndoManager.cpp:342
juce::UndoManager::getNumberOfUnitsTakenUpByStoredCommands
int getNumberOfUnitsTakenUpByStoredCommands() const
Definition: juce_UndoManager.cpp:87
juce::UndoManager::perform
bool perform(UndoableAction *action)
Definition: juce_UndoManager.cpp:112
juce::UndoManager::getTimeOfRedoTransaction
Time getTimeOfRedoTransaction() const
Definition: juce_UndoManager.cpp:334
juce::UndoManager::canRedo
bool canRedo() const
Definition: juce_UndoManager.cpp:244
juce::UndoManager::getUndoDescriptions
StringArray getUndoDescriptions() const
Definition: juce_UndoManager.cpp:300
juce::UndoManager::getUndoDescription
String getUndoDescription() const
Definition: juce_UndoManager.cpp:284
juce::UndoManager::UndoManager
UndoManager(int maxNumberOfUnitsToKeep=30000, int minimumTransactionsToKeep=30)
Definition: juce_UndoManager.cpp:69
juce::UndoManager::getActionsInCurrentTransaction
void getActionsInCurrentTransaction(Array< const UndoableAction * > &actionsFound) const
Definition: juce_UndoManager.cpp:353
juce::UndoManager::getNumActionsInCurrentTransaction
int getNumActionsInCurrentTransaction() const
Definition: juce_UndoManager.cpp:361
juce::UndoManager::setCurrentTransactionName
void setCurrentTransactionName(const String &newName)
Definition: juce_UndoManager.cpp:221
juce::UndoableAction
Definition: juce_UndoableAction.h:40