llundo.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /**
  2. * @file llundo.cpp
  3. *
  4. * $LicenseInfo:firstyear=2001&license=viewergpl$
  5. *
  6. * Copyright (c) 2001-2009, Linden Research, Inc.
  7. *
  8. * Second Life Viewer Source Code
  9. * The source code in this file ("Source Code") is provided by Linden Lab
  10. * to you under the terms of the GNU General Public License, version 2.0
  11. * ("GPL"), unless you have obtained a separate licensing agreement
  12. * ("Other License"), formally executed by you and Linden Lab. Terms of
  13. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15. *
  16. * There are special exceptions to the terms and conditions of the GPL as
  17. * it is applied to this Source Code. View the full text of the exception
  18. * in the file doc/FLOSS-exception.txt in this software distribution, or
  19. * online at
  20. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21. *
  22. * By copying, modifying or distributing this software, you acknowledge
  23. * that you have read and understood your obligations described above,
  24. * and agree to abide by those obligations.
  25. *
  26. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28. * COMPLETENESS OR PERFORMANCE.
  29. * $/LicenseInfo$
  30. */
  31. #include "linden_common.h"
  32. #include "llundo.h"
  33. // *TODO: implement doubly linked circular list for ring buffer this will allow
  34. // us to easily change the size of an undo buffer on the fly
  35. //-----------------------------------------------------------------------------
  36. // LLUndoBuffer()
  37. //-----------------------------------------------------------------------------
  38. LLUndoBuffer::LLUndoBuffer(LLUndoAction (*create_func()), S32 initial_count)
  39. {
  40. mNextAction = 0;
  41. mLastAction = 0;
  42. mFirstAction = 0;
  43. mOperationID = 0;
  44. mNumActions = initial_count;
  45. mActions = new LLUndoAction *[initial_count];
  46. //initialize buffer with actions
  47. for (S32 i = 0; i < initial_count; ++i)
  48. {
  49. mActions[i] = create_func();
  50. if (!mActions[i])
  51. {
  52. llerrs << "Unable to create action for undo buffer" << llendl;
  53. }
  54. }
  55. }
  56. //-----------------------------------------------------------------------------
  57. // ~LLUndoBuffer()
  58. //-----------------------------------------------------------------------------
  59. LLUndoBuffer::~LLUndoBuffer()
  60. {
  61. for (S32 i = 0; i < mNumActions; ++i)
  62. {
  63. delete mActions[i];
  64. }
  65. delete [] mActions;
  66. }
  67. //-----------------------------------------------------------------------------
  68. // getNextAction()
  69. //-----------------------------------------------------------------------------
  70. LLUndoBuffer::LLUndoAction* LLUndoBuffer::getNextAction(bool setClusterBegin)
  71. {
  72. LLUndoAction* nextAction = mActions[mNextAction];
  73. if (setClusterBegin)
  74. {
  75. ++mOperationID;
  76. }
  77. mActions[mNextAction]->mClusterID = mOperationID;
  78. mNextAction = (mNextAction + 1) % mNumActions;
  79. mLastAction = mNextAction;
  80. if (mNextAction == mFirstAction)
  81. {
  82. mActions[mFirstAction]->cleanup();
  83. mFirstAction = (mFirstAction + 1) % mNumActions;
  84. }
  85. return nextAction;
  86. }
  87. //-----------------------------------------------------------------------------
  88. // undoAction()
  89. //-----------------------------------------------------------------------------
  90. bool LLUndoBuffer::undoAction()
  91. {
  92. if (!canUndo())
  93. {
  94. return false;
  95. }
  96. S32 prevAction = (mNextAction + mNumActions - 1) % mNumActions;
  97. while(mActions[prevAction]->mClusterID == mOperationID)
  98. {
  99. // go ahead and decrement action index
  100. mNextAction = prevAction;
  101. // undo this action
  102. mActions[mNextAction]->undo();
  103. // we're at the first action, so we don't know if we've actually undid
  104. // everything
  105. if (mNextAction == mFirstAction)
  106. {
  107. --mOperationID;
  108. return false;
  109. }
  110. // do wrap-around of index, but avoid negative numbers for modulo
  111. // operator
  112. prevAction = (mNextAction + mNumActions - 1) % mNumActions;
  113. }
  114. mOperationID--;
  115. return true;
  116. }
  117. //-----------------------------------------------------------------------------
  118. // redoAction()
  119. //-----------------------------------------------------------------------------
  120. bool LLUndoBuffer::redoAction()
  121. {
  122. if (!canRedo())
  123. {
  124. return false;
  125. }
  126. ++mOperationID;
  127. while(mActions[mNextAction]->mClusterID == mOperationID)
  128. {
  129. if (mNextAction == mLastAction)
  130. {
  131. return false;
  132. }
  133. mActions[mNextAction]->redo();
  134. // do wrap-around of index
  135. mNextAction = (mNextAction + 1) % mNumActions;
  136. }
  137. return true;
  138. }
  139. //-----------------------------------------------------------------------------
  140. // flushActions()
  141. //-----------------------------------------------------------------------------
  142. void LLUndoBuffer::flushActions()
  143. {
  144. for (S32 i = 0; i < mNumActions; ++i)
  145. {
  146. mActions[i]->cleanup();
  147. }
  148. mNextAction = 0;
  149. mLastAction = 0;
  150. mFirstAction = 0;
  151. mOperationID = 0;
  152. }