PageRenderTime 55ms CodeModel.GetById 47ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llui/llundo.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 174 lines | 94 code | 29 blank | 51 comment | 15 complexity | d2647941bd8bd979b3ccc22f8b5d2580 MD5 | raw file
  1/** 
  2 * @file llundo.cpp
  3 *
  4 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  5 * Second Life Viewer Source Code
  6 * Copyright (C) 2010, Linden Research, Inc.
  7 * 
  8 * This library is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU Lesser General Public
 10 * License as published by the Free Software Foundation;
 11 * version 2.1 of the License only.
 12 * 
 13 * This library is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16 * Lesser General Public License for more details.
 17 * 
 18 * You should have received a copy of the GNU Lesser General Public
 19 * License along with this library; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 21 * 
 22 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 23 * $/LicenseInfo$
 24 */
 25
 26#include "linden_common.h"
 27#include "llundo.h"
 28
 29
 30// TODO:
 31// implement doubly linked circular list for ring buffer
 32// this will allow us to easily change the size of an undo buffer on the fly
 33
 34//-----------------------------------------------------------------------------
 35// LLUndoBuffer()
 36//-----------------------------------------------------------------------------
 37LLUndoBuffer::LLUndoBuffer( LLUndoAction (*create_func()), S32 initial_count )
 38{
 39	mNextAction = 0;
 40	mLastAction = 0;
 41	mFirstAction = 0;
 42	mOperationID = 0;
 43
 44	mNumActions = initial_count;	
 45
 46	mActions = new LLUndoAction *[initial_count];
 47
 48	//initialize buffer with actions
 49	for (S32 i = 0; i < initial_count; i++)
 50	{
 51		mActions[i] = create_func();
 52		if (!mActions[i])
 53		{
 54			llerrs << "Unable to create action for undo buffer" << llendl;
 55		}
 56	}
 57}
 58
 59//-----------------------------------------------------------------------------
 60// ~LLUndoBuffer()
 61//-----------------------------------------------------------------------------
 62LLUndoBuffer::~LLUndoBuffer()
 63{
 64	for (S32 i = 0; i < mNumActions; i++)
 65	{
 66		delete mActions[i];
 67	}
 68
 69	delete [] mActions;
 70}
 71
 72//-----------------------------------------------------------------------------
 73// getNextAction()
 74//-----------------------------------------------------------------------------
 75LLUndoBuffer::LLUndoAction* LLUndoBuffer::getNextAction(BOOL setClusterBegin)
 76{
 77	LLUndoAction *nextAction = mActions[mNextAction];
 78
 79	if (setClusterBegin)
 80	{
 81		mOperationID++;
 82	}
 83	mActions[mNextAction]->mClusterID = mOperationID;
 84
 85	mNextAction = (mNextAction + 1) % mNumActions;
 86	mLastAction = mNextAction;
 87
 88	if (mNextAction == mFirstAction)
 89	{
 90		mActions[mFirstAction]->cleanup();
 91		mFirstAction = (mFirstAction + 1) % mNumActions;
 92	}
 93
 94	return nextAction;
 95}
 96
 97//-----------------------------------------------------------------------------
 98// undoAction()
 99//-----------------------------------------------------------------------------
100BOOL LLUndoBuffer::undoAction()
101{
102	if (!canUndo())
103	{
104		return FALSE;
105	}
106
107	S32 prevAction = (mNextAction + mNumActions - 1) % mNumActions;
108
109	while(mActions[prevAction]->mClusterID == mOperationID)
110	{
111		// go ahead and decrement action index
112		mNextAction = prevAction;
113
114		// undo this action
115		mActions[mNextAction]->undo();
116
117		// we're at the first action, so we don't know if we've actually undid everything
118		if (mNextAction == mFirstAction)
119		{
120			mOperationID--;
121			return FALSE;
122		}
123
124		// do wrap-around of index, but avoid negative numbers for modulo operator
125		prevAction = (mNextAction + mNumActions - 1) % mNumActions;
126	}
127
128	mOperationID--;
129
130	return TRUE;
131}
132
133//-----------------------------------------------------------------------------
134// redoAction()
135//-----------------------------------------------------------------------------
136BOOL LLUndoBuffer::redoAction()
137{
138	if (!canRedo())
139	{
140		return FALSE;
141	}
142
143	mOperationID++;
144
145	while(mActions[mNextAction]->mClusterID == mOperationID)
146	{
147		if (mNextAction == mLastAction)
148		{
149			return FALSE;
150		}
151
152		mActions[mNextAction]->redo();
153
154		// do wrap-around of index
155		mNextAction = (mNextAction + 1) % mNumActions;
156	}
157
158	return TRUE;
159}
160
161//-----------------------------------------------------------------------------
162// flushActions()
163//-----------------------------------------------------------------------------
164void LLUndoBuffer::flushActions()
165{
166	for (S32 i = 0; i < mNumActions; i++)
167	{
168		mActions[i]->cleanup();
169	}
170	mNextAction = 0;
171	mLastAction = 0;
172	mFirstAction = 0;
173	mOperationID = 0;
174}