Update contrib.
1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "LogViewWindow.h"
19 #include "logclientop.h"
20 #include "logclipanic.h"
21 #include "LogViewWindowChangeObserver.h"
24 const TInt KWindowSlideSize = 2;
27 /////////////////////////////////////////////////////////////////////////////////////////
28 // -----> CLogViewWindow (source)
29 /////////////////////////////////////////////////////////////////////////////////////////
31 CLogViewWindow::CLogViewWindow(RLogSession& aSession, TLogViewId aViewId, TInt aWindowSize, MLogViewChangeObserver* aCascadeObserver, TInt aPriority)
32 : CLogActive(aPriority), iSession(aSession), iViewId(aViewId), iWindowSize(aWindowSize), iCascadeObserver(aCascadeObserver), iEvents(aWindowSize)
37 CLogViewWindow::~CLogViewWindow()
41 delete iWindowChangeObserver;
42 delete iWindowPreparer;
43 delete iWindowFetcher;
44 delete iWindowLockObserver;
46 iEvents.ResetAndDestroy();
50 void CLogViewWindow::ConstructL(CLogPackage& aPackage)
52 iWindowPreparer = new(ELeave) CLogViewSetupClientOp(iSession, aPackage, CActive::EPriorityStandard);
54 iWindowFetcher = new(ELeave) CLogViewWindowFetcher(iSession, iViewId, *this, CActive::EPriorityIdle + 1);
55 iWindowFetcher->ConstructL();
57 iWindowLockObserver = new(ELeave) CLogViewWindowLockObserver(iSession, iViewId, *this, CActive::EPriorityHigh);
58 iWindowLockObserver->ConstructL();
60 iWindowChangeObserver = new(ELeave) CLogViewWindowChangeObserver(*this);
63 /////////////////////////////////////////////////////////////////////////////////////////
64 /////////////////////////////////////////////////////////////////////////////////////////
65 /////////////////////////////////////////////////////////////////////////////////////////
67 TInt CLogViewWindow::Setup(const CLogFilterList& aFilterList, TInt aParam, TLogFilterConstructionType aFilterConstructionType)
70 iViewRecordCount = iWindowPreparer->Start(iViewId, aFilterList, aParam, aFilterConstructionType);
71 return iViewRecordCount;
74 TBool CLogViewWindow::NavigateL(TLogNavigation aNavigate, TRequestStatus& aStatus)
76 // Check why we're already active
81 __ASSERT_DEBUG(!IsActive(), Panic(ELogWindowStateMachineNavigationError1));
83 case EStateFetchingWindow:
84 case EStateProcessingWindow:
85 case EStateNavigateWithinWindow:
86 // We're trying to catch up with some changes.. use the requested
87 // window as the new window, but refetch everything.
88 __ASSERT_DEBUG(IsActive(), Panic(ELogWindowStateMachineNavigationError2));
90 iWindow = iWindowFetcher->RequestedWindow();
96 // Perform boundary checks
97 TInt cursorPos = CalculateCursorPosition(aNavigate);
98 if (cursorPos < 0 || cursorPos >= iViewRecordCount)
100 // Can't navigate to the specified position
104 // Check whether the cursor position falls within the view window
105 if (iWindow.iValid && iWindow.Contains(cursorPos))
107 // Can return event from window
108 CompleteRequest(cursorPos);
109 ChangeState(EStateNavigateWithinWindow);
113 // Have to fetch a new window. Work it out...
114 TLogWindowAndCursor window;
115 CalculateWindowForCursorPosition(cursorPos, window);
116 window.iCursorPosition = cursorPos;
117 iWindowFetcher->PrepareToFetchWindowL(window);
119 CompleteRequest(KErrNone);
120 ChangeState(EStateFetchingWindow);
123 // Okay to (try to) navigate here
128 void CLogViewWindow::RemoveFromWindowIfPresentL(TLogId aId)
130 TInt index = FindEvent(aId);
133 // Ignore next window removal event (since we're proactively removing
134 // the event from the client side without server prompting).
135 iWindowChangeObserver->IgnoreNextEventL(aId, CLogViewWindowChangeObserver::ELogEventTypeDelete);
140 // Map onto full view position
141 index += iWindow.iLower;
143 // Update window - when removing the last event from the window, we must
144 // ensure we mark the window as invalid.
145 if (iWindow.AdjustForItemDeletion(index) == TLogWindowAndCursor::EWindowAffected && iEvents.Count() == 0)
154 MLogViewChangeObserverInternal& CLogViewWindow::ChangeObserver()
156 __ASSERT_ALWAYS(iWindowChangeObserver, Panic(ELogWindowNoChangeObserver));
157 return *iWindowChangeObserver;
160 const CLogEvent& CLogViewWindow::CurrsorEvent() const
162 // Map the cursor position to fall within the window
163 const TInt mappedIndex = iWindow.WindowIndexFromCursorPosition();
164 const TInt count = iEvents.Count();
165 __ASSERT_ALWAYS(mappedIndex >= 0 && mappedIndex < count, Panic(ELogWindowCursorCalculationOutOfBounds));
166 return *iEvents[mappedIndex];
169 /////////////////////////////////////////////////////////////////////////////////////////
170 /////////////////////////////////////////////////////////////////////////////////////////
171 /////////////////////////////////////////////////////////////////////////////////////////
173 void CLogViewWindow::HandleWindowLockStatusChangeL(TLogViewLockStatus aStatus)
177 case ELogViewWindowLocked:
179 iState = EStateLocked;
181 case ELogViewWindowOpen:
182 if (iState == EStateLocked)
189 // The window is never valid after a change in lock status
190 iWindow.iValid = EFalse;
193 /////////////////////////////////////////////////////////////////////////////////////////
194 /////////////////////////////////////////////////////////////////////////////////////////
195 /////////////////////////////////////////////////////////////////////////////////////////
197 void CLogViewWindow::HandleFetchedWindowItemL(TInt /*aItemIndex*/, CLogEvent* aEvent)
199 // IMPROVEMENT: could use aItemIndex as the insertion point?
200 User::LeaveIfError(iEvents.Append(aEvent));
203 /////////////////////////////////////////////////////////////////////////////////////////
204 /////////////////////////////////////////////////////////////////////////////////////////
205 /////////////////////////////////////////////////////////////////////////////////////////
207 void CLogViewWindow::HandleLogViewChangeEventAddedL(TLogId aId, TInt aViewIndex, TInt aChangeIndex, TInt aTotalChangeCount)
209 ///////////////////////////////////////
211 ///////////////////////////////////////
212 // Cursor position: *
213 // View Index: 0 1 2 3 4 5 6
214 // View Contents: A B C D E F G
216 // Then, item X is added =>
218 // Cursor position: *
219 // View Index: 0 1 2 3 4 5 6 7
220 // View Contents: X A B C D E F G
222 ///////////////////////////////////////
224 ///////////////////////////////////////
225 // Cursor position: *
226 // View Index: 0 1 2 3 4 5 6
227 // View Contents: A B C D E F G
229 // Then, item X is added =>
231 // Cursor position: *
232 // View Index: 0 1 2 3 4 5 6 7
233 // View Contents: X A B C D E F G
235 ///////////////////////////////////////
237 ///////////////////////////////////////
238 // Cursor position: *
239 // View Index: 0 1 2 3 4 5 6
240 // View Contents: A B C D E F G
242 // Then, item X is added =>
244 // Cursor position: *
245 // View Index: 0 1 2 3 4 5 6 7
246 // View Contents: X A B C D E F G
248 ///////////////////////////////////////
250 ///////////////////////////////////////
251 // Cursor position: *
252 // View Index: 0 1 2 3 4 5 6
253 // View Contents: A B C D E F G
255 // Then, change item Z so that it now appears in the view
257 // Cursor position: *
258 // View Index: 0 1 2 3 4 5 6 7
259 // View Contents: A B C Z D E F G
261 ///////////////////////////////////////
263 ///////////////////////////////////////
264 // Cursor position: *
265 // View Index: 0 1 2 3 4 5 6
266 // View Contents: A B C D E F G
268 // Then, change item Z so that it now appears in the view
270 // Cursor position: *
271 // View Index: 0 1 2 3 4 5 6 7
272 // View Contents: A B C Z D E F G
274 ///////////////////////////////////////
275 //RDebug::Print(_L("CLogViewWindow::HandleLogViewChangeEventAddedL() - aId: %3d, aViewIndex: %3d, aChangeIndex: %3d, aTotalChangeCount: %d, cursorPos: %3d, window: (%3d, %3d), viewCount: %3d, iState: %d"), aId, aViewIndex, aChangeIndex, aTotalChangeCount, iWindow.iCursorPosition, iWindow.iLower, iWindow.iUpper, iViewRecordCount, iState);
277 // Must compare against the current window (if this object is idle) or against
278 // the window fetcher's window if it is in the process of making a fetch
279 TLogWindowAndCursor currentWindow;
282 case EStateFetchingWindow:
283 case EStateProcessingWindow:
284 currentWindow = iWindowFetcher->RequestedWindow();
286 case EStateNavigateWithinWindow:
289 currentWindow = iWindow;
293 // If the addition took place after the window, then we do nothing (except update the
294 // total view record count)
295 if (aViewIndex <= currentWindow.iUpper)
297 // If the addition took place before our window, or at the very start, then we simply need to adjust
298 // the window & cursor position. If the window fetcher was active then this will affect the window
299 // being fetched - in this case, we MUST refetch the whole window.
300 if (iState == EStateIdle && aViewIndex <= currentWindow.iLower)
302 iWindow.AdjustForItemAddition(aViewIndex);
306 // If the addition took place within the window, then we have to refetch the window
307 TBool refetch = ETrue;
308 TLogWindowAndCursor newWindow;
315 case EStateNavigateWithinWindow:
316 // Since we complete our own request status with the new cursor position,
317 // we can use that here as the desired cursor position after the fetch
319 newWindow.iCursorPosition = iStatus.Int();
321 case EStateFetchingWindow:
322 case EStateProcessingWindow:
323 newWindow = iWindowFetcher->RequestedWindow();
326 // Don't need to do anything. When the view is unlocked, we refetch anyway
335 newWindow.AdjustForItemAddition(aViewIndex);
336 RefetchL(newWindow, newWindow.iCursorPosition);
341 // Increase the total view size
344 if (iCascadeObserver)
345 iCascadeObserver->HandleLogViewChangeEventAddedL(aId, aViewIndex, aChangeIndex, aTotalChangeCount);
348 void CLogViewWindow::HandleLogViewChangeEventChangedL(TLogId aId, TInt aViewIndex, TInt aChangeIndex, TInt aTotalChangeCount)
350 //RDebug::Print(_L("CLogViewWindow::HandleLogViewChangeEventChangedL() - aId: %3d, aViewIndex: %3d, aChangeIndex: %3d, aTotalChangeCount: %d, cursorPos: %3d, window: (%3d, %3d), viewCount: %3d, iState: %d"), aId, aViewIndex, aChangeIndex, aTotalChangeCount, iWindow.iCursorPosition, iWindow.iLower, iWindow.iUpper, iViewRecordCount, iState);
352 // Must compare against the current window (if this object is idle) or against
353 // the window fetcher's window if it is in the process of making a fetch
354 TLogWindowAndCursor currentWindow;
357 case EStateFetchingWindow:
358 case EStateProcessingWindow:
359 currentWindow = iWindowFetcher->RequestedWindow();
361 case EStateNavigateWithinWindow:
364 currentWindow = iWindow;
370 // If the event that changed was within the view, then we have to refetch it
371 if (currentWindow.Contains(aViewIndex))
376 RefetchL(iWindow, iWindow.iCursorPosition);
378 case EStateNavigateWithinWindow:
379 // Since we complete our own request status with the new cursor position,
380 // we can use that here as the desired cursor position after the fetch
381 RefetchL(iWindow, iStatus.Int());
383 case EStateFetchingWindow:
384 case EStateProcessingWindow:
385 RefetchL(iWindowFetcher->RequestedWindow(), iWindowFetcher->RequestedWindow().iCursorPosition);
388 // Don't need to do anything. When the view is unlocked, we refetch anyway
395 if (iCascadeObserver)
396 iCascadeObserver->HandleLogViewChangeEventChangedL(aId, aViewIndex, aChangeIndex, aTotalChangeCount);
399 void CLogViewWindow::HandleLogViewChangeEventDeletedL(TLogId aId, TInt aViewIndex, TInt aChangeIndex, TInt aTotalChangeCount)
401 ///////////////////////////////////////
403 ///////////////////////////////////////
404 // Cursor position: *
405 // View Index: 0 1 2 3 4 5 6
406 // View Contents: A B C D E F G
408 // Then, item 5 is deleted =>
410 // Cursor position: *
411 // View Index: 0 1 2 3 4 5
412 // View Contents: A B C D E G
414 ///////////////////////////////////////
416 ///////////////////////////////////////
417 // Cursor position: *
418 // View Index: 0 1 2 3 4 5 6
419 // View Contents: A B C D E F G
421 // Then, item 4 is deleted =>
423 // Cursor position: *
424 // View Index: 0 1 2 3 4 5
425 // View Contents: A B C D F G
427 ///////////////////////////////////////
429 ///////////////////////////////////////
430 // Cursor position: *
431 // View Index: 0 1 2 3 4 5 6
432 // View Contents: A B C D E F G
434 // Then, item 6 is deleted =>
436 // Cursor position: *
437 // View Index: 0 1 2 3 4 5
438 // View Contents: A B C D E F
440 ///////////////////////////////////////
442 ///////////////////////////////////////
443 // Cursor position: *
444 // View Index: 0 1 2 3 4 5 6
445 // View Contents: A B C D E F G
447 // Then, item 6 is deleted =>
449 // Cursor position: *
450 // View Index: 0 1 2 3 4 5
451 // View Contents: B C D E F G
453 ///////////////////////////////////////
454 //RDebug::Print(_L("CLogViewWindow::HandleLogViewChangeEventDeletedL() - aId: %3d, aViewIndex: %3d, aChangeIndex: %3d, aTotalChangeCount: %d, cursorPos: %3d, window: (%3d, %3d), viewCount: %3d, iState: %d"), aId, aViewIndex, aChangeIndex, aTotalChangeCount, iWindow.iCursorPosition, iWindow.iLower, iWindow.iUpper, iViewRecordCount, iState);
456 // Must compare against the current window (if this object is idle) or against
457 // the window fetcher's window if it is in the process of making a fetch
458 TLogWindowAndCursor currentWindow;
461 case EStateFetchingWindow:
462 case EStateProcessingWindow:
463 currentWindow = iWindowFetcher->RequestedWindow();
465 case EStateNavigateWithinWindow:
468 currentWindow = iWindow;
474 // Does the change alter our current window in any way?
475 if (aViewIndex <= currentWindow.iUpper)
477 TBool refetch = ETrue;
478 TLogWindowAndCursor newWindow;
483 FindAndRemoveEvent(aId);
485 // When removing the last event from the window, we must ensure we mark
486 // the window as invalid.
487 if (iWindow.AdjustForItemDeletion(aViewIndex) == TLogWindowAndCursor::EWindowAffected && iEvents.Count() == 0)
494 case EStateNavigateWithinWindow:
496 newWindow.iCursorPosition = iStatus.Int();
498 case EStateFetchingWindow:
499 case EStateProcessingWindow:
500 newWindow = iWindowFetcher->RequestedWindow();
503 // Don't need to do anything. When the view is unlocked, we refetch anyway
512 newWindow.AdjustForItemDeletion(aViewIndex);
513 RefetchL(newWindow, newWindow.iCursorPosition);
517 // Reduce the total view size
520 if (iCascadeObserver)
521 iCascadeObserver->HandleLogViewChangeEventDeletedL(aId, aViewIndex, aChangeIndex, aTotalChangeCount);
524 /////////////////////////////////////////////////////////////////////////////////////////
525 /////////////////////////////////////////////////////////////////////////////////////////
526 /////////////////////////////////////////////////////////////////////////////////////////
528 void CLogViewWindow::HandleLogViewChangeEventLogClearedL()
533 // This event type is not cascaded to the client of the log engine
536 /////////////////////////////////////////////////////////////////////////////////////////
537 /////////////////////////////////////////////////////////////////////////////////////////
538 /////////////////////////////////////////////////////////////////////////////////////////
540 void CLogViewWindow::DoRunL()
544 case EStateFetchingWindow:
545 StateHandleWindowFetchStarting();
547 case EStateProcessingWindow:
548 StateHandleWindowFetchedL();
550 case EStateNavigateWithinWindow:
551 StateHandleNavigation();
560 void CLogViewWindow::DoCancel()
562 if(iState == EStateProcessingWindow)
564 iWindowFetcher->Cancel();
566 CLogActive::DoCancel();
569 void CLogViewWindow::DoComplete(TInt& aComplete)
576 case EStateNavigateWithinWindow:
577 if (aComplete < KErrNone)
579 // Reset to known state
583 case EStateFetchingWindow:
584 case EStateProcessingWindow:
585 if (aComplete < KErrNone)
587 // Reset to known state
589 iWindow = iWindowFetcher->RequestedWindow();
593 aComplete = KErrAccessDenied;
598 /////////////////////////////////////////////////////////////////////////////////////////
599 /////////////////////////////////////////////////////////////////////////////////////////
600 /////////////////////////////////////////////////////////////////////////////////////////
602 void CLogViewWindow::StateHandleWindowFetchStarting()
604 iEvents.ResetAndDestroy();
605 iWindowFetcher->Start(iStatus);
606 ChangeState(EStateProcessingWindow);
610 void CLogViewWindow::StateHandleWindowFetchedL()
612 const TInt count = iEvents.Count();
613 const TInt expected = iWindowFetcher->RequestedWindow().Range();
614 if (expected != count)
615 User::Leave(KErrGeneral);
617 iWindow = iWindowFetcher->RequestedWindow();
618 CompleteRequest(iWindow.iCursorPosition);
619 ChangeState(EStateNavigateWithinWindow);
622 void CLogViewWindow::StateHandleNavigation()
624 const TInt cursorPos = iStatus.Int();
625 __ASSERT_ALWAYS(iWindow.Contains(cursorPos), Panic(ELogWindowNavigationOutsideWindow));
626 iWindow.iCursorPosition = cursorPos;
627 ChangeState(EStateIdle);
630 /////////////////////////////////////////////////////////////////////////////////////////
631 /////////////////////////////////////////////////////////////////////////////////////////
632 /////////////////////////////////////////////////////////////////////////////////////////
634 void CLogViewWindow::CompleteRequest(TInt aCompletionCode)
636 if (!IsActive() || (IsActive() && iStatus == KRequestPending))
638 TRequestStatus* status = &iStatus;
639 User::RequestComplete(status, aCompletionCode);
645 void CLogViewWindow::CalculateWindowForCursorPosition(TInt aCursorPosition, TLogWindow& aWindow) const
647 aWindow.iLower = Max(0, aCursorPosition - KWindowSlideSize - 1);
648 aWindow.iUpper = Min(iViewRecordCount - 1, aWindow.iLower + iWindowSize - 1);
651 void CLogViewWindow::Reset()
655 iViewRecordCount = 0;
657 iEvents.ResetAndDestroy();
661 void CLogViewWindow::SilentCancel()
663 iWindowFetcher->SilentCancel();
666 void CLogViewWindow::RefetchL(const TLogWindow& aWindow, TInt aCursor)
670 TLogWindowAndCursor newWindow(aWindow, aCursor);
671 iWindowFetcher->PrepareToFetchWindowL(newWindow);
672 CompleteRequest(KErrNone);
673 ChangeState(EStateFetchingWindow);
676 void CLogViewWindow::ChangeState(TWindowState aNewState)
681 void CLogViewWindow::RemoveEvent(TInt aIndex)
683 CLogEvent* event = iEvents[aIndex];
685 iEvents.Remove(aIndex);
688 TInt CLogViewWindow::CalculateCursorPosition(TLogNavigation aNavigate) const
693 case ELogNavigateForwards:
694 position = iWindow.iCursorPosition + 1;
696 case ELogNavigateBackwards:
697 position = iWindow.iCursorPosition - 1;
699 case ELogNavigateFirst:
702 case ELogNavigateLast:
703 position = iViewRecordCount - 1;
711 TInt CLogViewWindow::FindEvent(TLogId aId)
713 const TInt count = iEvents.Count();
714 for(TInt i=0; i<count; i++)
716 CLogEvent* event = iEvents[i];
717 if (event->Id() == aId)
723 TInt CLogViewWindow::FindAndRemoveEvent(TLogId aId)
725 TInt index = FindEvent(aId);
729 index += iWindow.iLower;