The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. You may use this code under the terms of the GPL v3
  6. (see www.gnu.org/licenses).
  7. For this technical preview, this file is not subject to commercial licensing.
  8. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  9. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  10. DISCLAIMED.
  11. ==============================================================================
  12. */
  13. namespace juce
  14. {
  15. //==============================================================================
  16. /**
  17. Manages a list of undo/redo commands.
  18. An UndoManager object keeps a list of past actions and can use these actions
  19. to move backwards and forwards through an undo history.
  20. To use it, create subclasses of UndoableAction which perform all the
  21. actions you need, then when you need to actually perform an action, create one
  22. and pass it to the UndoManager's perform() method.
  23. The manager also uses the concept of 'transactions' to group the actions
  24. together - all actions performed between calls to beginNewTransaction() are
  25. grouped together and are all undone/redone as a group.
  26. The UndoManager is a ChangeBroadcaster, so listeners can register to be told
  27. when actions are performed or undone.
  28. @see UndoableAction
  29. @tags{DataStructures}
  30. */
  31. class JUCE_API UndoManager : public ChangeBroadcaster
  32. {
  33. public:
  34. //==============================================================================
  35. /** Creates an UndoManager.
  36. @param maxNumberOfUnitsToKeep each UndoableAction object returns a value
  37. to indicate how much storage it takes up
  38. (UndoableAction::getSizeInUnits()), so this
  39. lets you specify the maximum total number of
  40. units that the undomanager is allowed to
  41. keep in memory before letting the older actions
  42. drop off the end of the list.
  43. @param minimumTransactionsToKeep this specifies the minimum number of transactions
  44. that will be kept, even if this involves exceeding
  45. the amount of space specified in maxNumberOfUnitsToKeep
  46. */
  47. UndoManager (int maxNumberOfUnitsToKeep = 30000,
  48. int minimumTransactionsToKeep = 30);
  49. /** Destructor. */
  50. ~UndoManager() override;
  51. //==============================================================================
  52. /** Deletes all stored actions in the list. */
  53. void clearUndoHistory();
  54. /** Returns the current amount of space to use for storing UndoableAction objects.
  55. @see setMaxNumberOfStoredUnits
  56. */
  57. int getNumberOfUnitsTakenUpByStoredCommands() const;
  58. /** Sets the amount of space that can be used for storing UndoableAction objects.
  59. @param maxNumberOfUnitsToKeep each UndoableAction object returns a value
  60. to indicate how much storage it takes up
  61. (UndoableAction::getSizeInUnits()), so this
  62. lets you specify the maximum total number of
  63. units that the undomanager is allowed to
  64. keep in memory before letting the older actions
  65. drop off the end of the list.
  66. @param minimumTransactionsToKeep this specifies the minimum number of transactions
  67. that will be kept, even if this involves exceeding
  68. the amount of space specified in maxNumberOfUnitsToKeep
  69. @see getNumberOfUnitsTakenUpByStoredCommands
  70. */
  71. void setMaxNumberOfStoredUnits (int maxNumberOfUnitsToKeep,
  72. int minimumTransactionsToKeep);
  73. //==============================================================================
  74. /** Performs an action and adds it to the undo history list.
  75. @param action the action to perform - this object will be deleted by
  76. the UndoManager when no longer needed
  77. @returns true if the command succeeds - see UndoableAction::perform
  78. @see beginNewTransaction
  79. */
  80. bool perform (UndoableAction* action);
  81. /** Performs an action and also gives it a name.
  82. @param action the action to perform - this object will be deleted by
  83. the UndoManager when no longer needed
  84. @param actionName if this string is non-empty, the current transaction will be
  85. given this name; if it's empty, the current transaction name will
  86. be left unchanged. See setCurrentTransactionName()
  87. @returns true if the command succeeds - see UndoableAction::perform
  88. @see beginNewTransaction
  89. */
  90. bool perform (UndoableAction* action, const String& actionName);
  91. /** Starts a new group of actions that together will be treated as a single transaction.
  92. All actions that are passed to the perform() method between calls to this
  93. method are grouped together and undone/redone together by a single call to
  94. undo() or redo().
  95. */
  96. void beginNewTransaction();
  97. /** Starts a new group of actions that together will be treated as a single transaction.
  98. All actions that are passed to the perform() method between calls to this
  99. method are grouped together and undone/redone together by a single call to
  100. undo() or redo().
  101. @param actionName a description of the transaction that is about to be
  102. performed
  103. */
  104. void beginNewTransaction (const String& actionName);
  105. /** Changes the name stored for the current transaction.
  106. Each transaction is given a name when the beginNewTransaction() method is
  107. called, but this can be used to change that name without starting a new
  108. transaction.
  109. */
  110. void setCurrentTransactionName (const String& newName);
  111. /** Returns the name of the current transaction.
  112. @see setCurrentTransactionName
  113. */
  114. String getCurrentTransactionName() const;
  115. //==============================================================================
  116. /** Returns true if there's at least one action in the list to undo.
  117. @see getUndoDescription, undo, canRedo
  118. */
  119. bool canUndo() const;
  120. /** Tries to roll-back the last transaction.
  121. @returns true if the transaction can be undone, and false if it fails, or
  122. if there aren't any transactions to undo
  123. @see undoCurrentTransactionOnly
  124. */
  125. bool undo();
  126. /** Tries to roll-back any actions that were added to the current transaction.
  127. This will perform an undo() only if there are some actions in the undo list
  128. that were added after the last call to beginNewTransaction().
  129. This is useful because it lets you call beginNewTransaction(), then
  130. perform an operation which may or may not actually perform some actions, and
  131. then call this method to get rid of any actions that might have been done
  132. without it rolling back the previous transaction if nothing was actually
  133. done.
  134. @returns true if any actions were undone.
  135. */
  136. bool undoCurrentTransactionOnly();
  137. /** Returns the name of the transaction that will be rolled-back when undo() is called.
  138. @see undo, canUndo, getUndoDescriptions
  139. */
  140. String getUndoDescription() const;
  141. /** Returns the names of the sequence of transactions that will be performed if undo()
  142. is repeatedly called. Note that for transactions where no name was provided, the
  143. corresponding string will be empty.
  144. @see undo, canUndo, getUndoDescription
  145. */
  146. StringArray getUndoDescriptions() const;
  147. /** Returns the time to which the state would be restored if undo() was to be called.
  148. If an undo isn't currently possible, it'll return Time().
  149. */
  150. Time getTimeOfUndoTransaction() const;
  151. /** Returns a list of the UndoableAction objects that have been performed during the
  152. transaction that is currently open.
  153. Effectively, this is the list of actions that would be undone if undoCurrentTransactionOnly()
  154. were to be called now.
  155. The first item in the list is the earliest action performed.
  156. */
  157. void getActionsInCurrentTransaction (Array<const UndoableAction*>& actionsFound) const;
  158. /** Returns the number of UndoableAction objects that have been performed during the
  159. transaction that is currently open.
  160. @see getActionsInCurrentTransaction
  161. */
  162. int getNumActionsInCurrentTransaction() const;
  163. //==============================================================================
  164. /** Returns true if there's at least one action in the list to redo.
  165. @see getRedoDescription, redo, canUndo
  166. */
  167. bool canRedo() const;
  168. /** Tries to redo the last transaction that was undone.
  169. @returns true if the transaction can be redone, and false if it fails, or
  170. if there aren't any transactions to redo
  171. */
  172. bool redo();
  173. /** Returns the name of the transaction that will be redone when redo() is called.
  174. @see redo, canRedo, getRedoDescriptions
  175. */
  176. String getRedoDescription() const;
  177. /** Returns the names of the sequence of transactions that will be performed if redo()
  178. is repeatedly called. Note that for transactions where no name was provided, the
  179. corresponding string will be empty.
  180. @see redo, canRedo, getRedoDescription
  181. */
  182. StringArray getRedoDescriptions() const;
  183. /** Returns the time to which the state would be restored if redo() was to be called.
  184. If a redo isn't currently possible, it'll return Time::getCurrentTime().
  185. @see redo, canRedo
  186. */
  187. Time getTimeOfRedoTransaction() const;
  188. /** Returns true if the caller code is in the middle of an undo or redo action. */
  189. bool isPerformingUndoRedo() const;
  190. private:
  191. //==============================================================================
  192. struct ActionSet;
  193. OwnedArray<ActionSet> transactions, stashedFutureTransactions;
  194. String newTransactionName;
  195. int totalUnitsStored = 0, maxNumUnitsToKeep = 0, minimumTransactionsToKeep = 0, nextIndex = 0;
  196. bool newTransaction = true, isInsideUndoRedoCall = false;
  197. ActionSet* getCurrentSet() const;
  198. ActionSet* getNextSet() const;
  199. void moveFutureTransactionsToStash();
  200. void restoreStashedFutureTransactions();
  201. void dropOldTransactionsIfTooLarge();
  202. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UndoManager)
  203. };
  204. } // namespace juce