llundo.cpp

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

Generated on Thu Jul 1 06:09:24 2010 for Second Life Viewer by  doxygen 1.4.7