llundo.cpp

Go to the documentation of this file.
00001 
00031 #include "linden_common.h"
00032 #include "llundo.h"
00033 
00034 
00035 // TODO:
00036 // implement doubly linked circular list for ring buffer
00037 // this will allow us to easily change the size of an undo buffer on the fly
00038 
00039 //-----------------------------------------------------------------------------
00040 // LLUndoBuffer()
00041 //-----------------------------------------------------------------------------
00042 LLUndoBuffer::LLUndoBuffer( LLUndoAction (*create_func()), S32 initial_count )
00043 {
00044         mNextAction = 0;
00045         mLastAction = 0;
00046         mFirstAction = 0;
00047         mOperationID = 0;
00048 
00049         mNumActions = initial_count;    
00050 
00051         mActions = new LLUndoAction *[initial_count];
00052 
00053         //initialize buffer with actions
00054         for (S32 i = 0; i < initial_count; i++)
00055         {
00056                 mActions[i] = create_func();
00057                 if (!mActions[i])
00058                 {
00059                         llerrs << "Unable to create action for undo buffer" << llendl;
00060                 }
00061         }
00062 }
00063 
00064 //-----------------------------------------------------------------------------
00065 // ~LLUndoBuffer()
00066 //-----------------------------------------------------------------------------
00067 LLUndoBuffer::~LLUndoBuffer()
00068 {
00069         for (S32 i = 0; i < mNumActions; i++)
00070         {
00071                 delete mActions[i];
00072         }
00073 
00074         delete [] mActions;
00075 }
00076 
00077 //-----------------------------------------------------------------------------
00078 // getNextAction()
00079 //-----------------------------------------------------------------------------
00080 LLUndoBuffer::LLUndoAction* LLUndoBuffer::getNextAction(BOOL setClusterBegin)
00081 {
00082         LLUndoAction *nextAction = mActions[mNextAction];
00083 
00084         if (setClusterBegin)
00085         {
00086                 mOperationID++;
00087         }
00088         mActions[mNextAction]->mClusterID = mOperationID;
00089 
00090         mNextAction = (mNextAction + 1) % mNumActions;
00091         mLastAction = mNextAction;
00092 
00093         if (mNextAction == mFirstAction)
00094         {
00095                 mActions[mFirstAction]->cleanup();
00096                 mFirstAction = (mFirstAction + 1) % mNumActions;
00097         }
00098 
00099         return nextAction;
00100 }
00101 
00102 //-----------------------------------------------------------------------------
00103 // undoAction()
00104 //-----------------------------------------------------------------------------
00105 BOOL LLUndoBuffer::undoAction()
00106 {
00107         if (!canUndo())
00108         {
00109                 return FALSE;
00110         }
00111 
00112         S32 prevAction = (mNextAction + mNumActions - 1) % mNumActions;
00113 
00114         while(mActions[prevAction]->mClusterID == mOperationID)
00115         {
00116                 // go ahead and decrement action index
00117                 mNextAction = prevAction;
00118 
00119                 // undo this action
00120                 mActions[mNextAction]->undo();
00121 
00122                 // we're at the first action, so we don't know if we've actually undid everything
00123                 if (mNextAction == mFirstAction)
00124                 {
00125                         mOperationID--;
00126                         return FALSE;
00127                 }
00128 
00129                 // do wrap-around of index, but avoid negative numbers for modulo operator
00130                 prevAction = (mNextAction + mNumActions - 1) % mNumActions;
00131         }
00132 
00133         mOperationID--;
00134 
00135         return TRUE;
00136 }
00137 
00138 //-----------------------------------------------------------------------------
00139 // redoAction()
00140 //-----------------------------------------------------------------------------
00141 BOOL LLUndoBuffer::redoAction()
00142 {
00143         if (!canRedo())
00144         {
00145                 return FALSE;
00146         }
00147 
00148         mOperationID++;
00149 
00150         while(mActions[mNextAction]->mClusterID == mOperationID)
00151         {
00152                 if (mNextAction == mLastAction)
00153                 {
00154                         return FALSE;
00155                 }
00156 
00157                 mActions[mNextAction]->redo();
00158 
00159                 // do wrap-around of index
00160                 mNextAction = (mNextAction + 1) % mNumActions;
00161         }
00162 
00163         return TRUE;
00164 }
00165 
00166 //-----------------------------------------------------------------------------
00167 // flushActions()
00168 //-----------------------------------------------------------------------------
00169 void LLUndoBuffer::flushActions()
00170 {
00171         for (S32 i = 0; i < mNumActions; i++)
00172         {
00173                 mActions[i]->cleanup();
00174         }
00175         mNextAction = 0;
00176         mLastAction = 0;
00177         mFirstAction = 0;
00178         mOperationID = 0;
00179 }

Generated on Fri May 16 08:33:00 2008 for SecondLife by  doxygen 1.5.5