Update contrib.
2 * Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
19 #include "UndoSystemImpl.h"
20 #include "AssertFileAndLine.h"
22 using namespace UndoSystem;
24 namespace UndoSystemImpl
26 const TInt KCommandStackGranularity = 10;
27 _LIT(KUndoPanic, "Undo System");
30 using namespace UndoSystemImpl;
33 void UndoSystem::Panic(TPanicCode aCode)
35 User::Panic(KUndoPanic, aCode);
44 CCommandStack::CCommandStack() : iEnd(0), iBookmark(0) {}
46 CCommandStack::~CCommandStack()
55 void CCommandStack::ConstructL()
57 iStack = new(ELeave) CArrayFixSeg<CCommand*>(KCommandStackGranularity);
60 CCommandStack* CCommandStack::NewL()
62 CCommandStack* r = new(ELeave) CCommandStack();
63 CleanupStack::PushL(r);
69 TInt CCommandStack::Count() const
71 ASSERT(iEnd <= iStack->Count());
75 void CCommandStack::Reset()
81 CCommand* CCommandStack::Top() const
84 ASSERT(iEnd <= iStack->Count());
85 return iEnd == 0? 0 : iStack->At(iEnd - 1);
88 CCommand* CCommandStack::Pop()
90 ASSERT(iEnd <= iStack->Count());
91 CCommand* top = Top();
92 __ASSERT_ALWAYS(top, UndoSystem::Panic(KCommandStackUnderflow));
93 TInt numSlots = iStack->Count() - iEnd + 1;
94 ASSERT(numSlots <= iStack->Count());
95 iStack->Delete(iStack->Count() - numSlots, numSlots);
96 iEnd = iStack->Count();
102 void CCommandStack::PruneTo(TInt aNumberOfItems)
104 ASSERT(iEnd <= iStack->Count());
105 iStack->Delete(iEnd, iStack->Count() - iEnd);
106 iEnd = iStack->Count();
107 if (aNumberOfItems < iEnd)
109 TInt numberToDestroy = iEnd - aNumberOfItems;
110 for (TInt i = 0; i != numberToDestroy; ++i)
112 delete iStack->At(i);
114 iStack->Delete(0, numberToDestroy);
116 iEnd = aNumberOfItems;
117 iBookmark -= aNumberOfItems;
121 void CCommandStack::PrepareToPushL(TInt aNumberOfItems)
123 iStack->ResizeL(iEnd + aNumberOfItems);
126 void CCommandStack::Push(CCommand* aCommand)
129 __ASSERT_ALWAYS(iEnd < iStack->Count(), UndoSystem::Panic(KCommandStackPushNotPrepared));
130 iStack->At(iEnd) = aCommand;
134 void CCommandStack::Concatenate(CCommandStack& aStack)
136 TInt thisCount = iEnd;
138 __ASSERT_DEBUG(iEnd <= iStack->Count(),
139 UndoSystem::Panic(KCommandStackPushNotPrepared));
140 for (TInt i = 0; i != aStack.iEnd; ++i, ++thisCount)
141 iStack->At(thisCount) = (aStack.iStack->At(i));
143 aStack.iStack->Reset();
146 void CCommandStack::SetBookmark()
151 TBool CCommandStack::IsAtBookmark() const
153 return iBookmark == iEnd? ETrue : EFalse;
156 CSingleCommandStack* CSingleCommandStack::NewL()
158 CSingleCommandStack* r = new(ELeave) CSingleCommandStack;
159 CleanupStack::PushL(r);
160 r->iStack.ConstructL();
161 CleanupStack::Pop(r);
165 ///////////////////////
167 // CCommandHistory //
169 ///////////////////////
171 CCommandHistory::CCommandHistory()
172 : iMaxItems(KMaxTInt >> 1)
176 CCommandHistory::~CCommandHistory()
181 void CCommandHistory::ConstructL()
183 iStack = CCommandStack::NewL();
187 CCommandHistory* CCommandHistory::NewL()
189 CCommandHistory* r = new(ELeave) CCommandHistory();
190 CleanupStack::PushL(r);
192 CleanupStack::Pop(r);
196 void CCommandHistory::Prune()
198 if (iMaxItems < iStack->Count())
199 iStack->PruneTo(iMaxItems);
202 void CCommandHistory::SetMaxItems(TInt aMaxItems)
204 ASSERT(0 < aMaxItems);
205 iMaxItems = aMaxItems;
209 void CCommandHistory::CloseBatch(void* a)
211 CCommandHistory* aThat = reinterpret_cast<CCommandHistory*>(a);
213 if (aThat->iBatchUndoHasBeenWaived)
217 void CCommandHistory::DownBatchLevel(void*) {}
219 TBool CCommandHistory::IsWithinBatch() const
221 return iCurrent? ETrue : EFalse;
224 void CCommandHistory::BeginBatchLC()
228 CleanupStack::PushL(TCleanupItem(DownBatchLevel, this));
232 iStack->PrepareToPushL(1);
233 iBatchUndoHasBeenWaived = EFalse;
234 CleanupStack::PushL(TCleanupItem(CloseBatch, this));
235 CBatchCommand* batch = CBatchCommand::NewL();
241 TBool CCommandHistory::UndoHasBeenWaived() const
243 return iCurrent? iBatchUndoHasBeenWaived : EFalse;
246 void CCommandHistory::SetUndoWaived()
248 iBatchUndoHasBeenWaived = ETrue;
251 void CCommandHistory::Reset()
257 void CCommandHistory::PrepareToAddCommandL(CCommand* aCommand)
260 iCurrent->PrepareToPushL(aCommand);
262 iStack->PrepareToPushL(1);
265 void CCommandHistory::AddCommand(CCommand* aCommand)
268 iCurrent->Push(aCommand);
270 iStack->Push(aCommand);
275 CSingleCommand* CCommandHistory::TopSingleCommand() const
277 CCommand* top = Top();
282 // if the top of the undo stack is an empty batch, then we are starting a new
283 // batch command and so do not want to combine. Otherwise, if the top is a batch
284 // with elements, we want to see if we can combine with the top one.
285 CBatchCommand* batch = top->Batch();
286 return batch? batch->Top() : top->Single();
289 CCommand* CCommandHistory::Top() const
291 return iStack->Top();
294 CCommand* CCommandHistory::Pop()
297 return iStack->Pop();
300 void CCommandHistory::Clean()
303 CCommand* command = Top();
306 CBatchCommand* batch = command->Batch();
309 if (batch->IsEmpty())
315 void CCommandHistory::SetBookmark()
317 iStack->SetBookmark();
320 TBool CCommandHistory::IsAtBookmark()
322 return iStack->IsAtBookmark();