--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/aknhlist/src/akntreelistphysicshandler.cpp Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1151 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: AknTreeListView physics handler
+*
+*/
+
+#include <aknphysics.h>
+#include <aknphysicsobserveriface.h>
+#include <babitflags.h>
+#include <eiksbobs.h>
+#include <eikon.hrh> // EKeyOK
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+#include <aknlistloadertfx.h>
+#include <aknlistboxtfx.h>
+#endif // RD_UI_TRANSITION_EFFECTS_LIST
+
+#include <touchfeedback.h>
+
+#include "akntree.h"
+#include "akntreelistview.h"
+#include "akntreelistphysicshandler.h"
+#include "akntreelist.h"
+#include "akntrace.h" // trace
+
+// Tree list view physics handler flag definitions.
+enum TAknTreeListPhysicsHandlerFlags
+ {
+ // pressed-down highlight should be drawn to focused item
+ EFlagPDHighlightToFocusedItem,
+ // pressed-down highlight should be drawn to nonfocused item
+ EFlagPDHighlightToNonFocusedItem,
+ EFlagButtonUpReceived,
+ EFlagUpdatingView
+ };
+
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::NewL
+// ---------------------------------------------------------------------------
+//
+CAknTreeListPhysicsHandler* CAknTreeListPhysicsHandler::NewL(
+ CAknTreeListView* aTreeListView,
+ CAknTree* aTree,
+ RArray<TAknTreeListViewItem>* aItems )
+ {
+ CAknTreeListPhysicsHandler* self =
+ CAknTreeListPhysicsHandler::NewLC( aTreeListView, aTree, aItems );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::NewLC
+// ---------------------------------------------------------------------------
+//
+CAknTreeListPhysicsHandler* CAknTreeListPhysicsHandler::NewLC(
+ CAknTreeListView* aTreeListView,
+ CAknTree* aTree,
+ RArray<TAknTreeListViewItem>* aItems )
+ {
+ CAknTreeListPhysicsHandler* self
+ = new ( ELeave ) CAknTreeListPhysicsHandler(
+ aTreeListView, aTree, aItems );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::~CAknTreeListPhysicsHandler
+// ---------------------------------------------------------------------------
+//
+CAknTreeListPhysicsHandler::~CAknTreeListPhysicsHandler()
+ {
+ delete iHighlightTimer;
+ delete iPhysics;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::HandlePointerEventL
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::HandlePointerEventL(
+ const TPointerEvent& aPointerEvent, const TInt& aViewLevel,
+ TBool aMarking, TBool aShiftPressed, TBool aCtrlPressed )
+ {
+ _AKNTRACE_FUNC_ENTER;
+ if ( aPointerEvent.iType == TPointerEvent::EButton1Down && iEnableEvents )
+ {
+ iEventsBlocked = EFalse;
+ iEnableEvents = EFalse;
+ }
+ if ( iEventsBlocked )
+ {
+ _AKNTRACE("CAknTreeListPhysicsHandler::%s Return due to event blocked", __FUNCTION__);
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+
+ // Panning/flicking logic
+
+ // EButton1Down
+
+ TBool wasFlicking( EFalse );
+ TBool wasScrolling = ( iPhysics->OngoingPhysicsAction() !=
+ CAknPhysics::EAknPhysicsActionNone );
+
+ if ( aPointerEvent.iType == TPointerEvent::EButton1Down &&
+ iViewRect.Contains( aPointerEvent.iPosition ) )
+ {
+ iPenDown = ETrue;
+ if ( iPhysics->OngoingPhysicsAction() == CAknPhysics::EAknPhysicsActionFlicking )
+ {
+ // flicking was ongoing when content stopped
+ if ( iFeedback )
+ {
+ iFeedback->InstantFeedback( ETouchFeedbackBasic );
+ }
+ wasFlicking = ETrue;
+ }
+
+ iFlags.Clear( EFlagButtonUpReceived );
+ iPosition = aPointerEvent.iPosition;
+ iStartPosition = aPointerEvent.iPosition;
+
+ iPhysics->StopPhysics();
+ iPhysics->ResetFriction();
+
+ iStartTime.HomeTime();
+ iHighlightTimer->Cancel();
+
+ iItemToBeFocused = NULL;
+ iIndexToBeFocused = -1;
+ iItemToBeSelected = NULL;
+
+ iPanningActivated = EFalse;
+
+ iPlayFeedbackOnUp = EFalse;
+
+ // Check if marquee needs to be disabled
+ if ( iTreeListView->SingleClickEnabled()
+ && iTree->IsMarqueeOn() )
+ {
+ iTree->EnableMarquee( EFalse );
+ }
+
+ iEmptyAreaClicked = EmptyAreaClicked( aPointerEvent.iPosition );
+ }
+
+ // EDrag
+
+ if ( aPointerEvent.iType == TPointerEvent::EDrag )
+ {
+ TInt distanceFromStart( iStartPosition.iY - aPointerEvent.iPosition.iY );
+
+ if ( !iPanningActivated && Abs( distanceFromStart ) > DragThreshold() )
+ {
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ MAknListBoxTfx* tfxApi = CAknListLoader::TfxApi( iTfxGc );
+
+ if ( tfxApi )
+ {
+ tfxApi->EnableEffects( EFalse );
+ }
+#endif // RD_UI_TRANSITION_EFFECTS_LIST
+
+ iPanningActivated = ETrue;
+ iEmptyAreaClicked = EFalse;
+
+ iHighlightTimer->Cancel();
+ iItemToBeFocused = NULL;
+ iItemToBeSelected = NULL;
+ iIndexToBeFocused = -1;
+ iTreeListView->SetPressedDownState( EFalse );
+ iPosition = aPointerEvent.iPosition;
+
+ _AKNTRACE(
+ "CAknTreeListPhysicsHandler::[%s] Report EEventPanningStarted",
+ __FUNCTION__);
+
+ if ( iTreeListView->SingleClickEnabled() )
+ {
+ iTreeListView->EnableHighlight( EFalse );
+ iTreeListView->CancelLongTapDetectorL();
+ }
+
+ iTreeListView->ReportTreeListEvent(
+ MAknTreeListObserver::EEventPanningStarted,
+ KAknTreeIIDNone );
+ }
+
+ if ( iPanningActivated )
+ {
+ TInt deltaY( iPosition.iY - aPointerEvent.iPosition.iY );
+ iPosition = aPointerEvent.iPosition;
+
+ TPoint deltaPoint( 0, deltaY );
+ _AKNTRACE(
+ "CAknTreeListPhysicsHandler::[%s] Panning deltaPoint.iY = %d",
+ __FUNCTION__, deltaY );
+ iPhysics->RegisterPanningPosition( deltaPoint );
+ }
+ else if ( iTreeListView->SingleClickEnabled() )
+ {
+ iTreeListView->LongTapPointerEventL( aPointerEvent );
+ }
+ }
+
+ // EButton1Up
+
+ if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
+ {
+ iTreeListView->SetPressedDownState( EFalse );
+ if ( iTreeListView->SingleClickEnabled() && !aMarking )
+ {
+ iHighlightTimer->Cancel();
+ iTreeListView->EnableHighlight( EFalse );
+ iTreeListView->LongTapPointerEventL( aPointerEvent );
+ }
+ iFlags.Set( EFlagButtonUpReceived );
+ iTreeListView->DrawDeferred();
+
+ TInt distance = iStartPosition.iY - aPointerEvent.iPosition.iY;
+ TPoint drag( 0, distance );
+
+ if ( iPhysics->StartPhysics( drag, iStartTime ) )
+ {
+ if ( iPanningActivated )
+ {
+ _AKNTRACE(
+ "CAknTreeListPhysicsHandler::[%s] Report EEventPanningStopped",
+ __FUNCTION__);
+ iTreeListView->ReportTreeListEvent(
+ MAknTreeListObserver::EEventPanningStopped,
+ KAknTreeIIDNone );
+ }
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ // Transitions are already suspended if listbox was panned.
+ if ( !iPanningActivated )
+ {
+ MAknListBoxTfx* tfxApi = CAknListLoader::TfxApi( iTfxGc );
+
+ if ( tfxApi )
+ {
+ tfxApi->EnableEffects( EFalse );
+ }
+ }
+#endif // RD_UI_TRANSITION_EFFECTS_LIST
+
+ if ( iPhysics->OngoingPhysicsAction() == CAknPhysics::EAknPhysicsActionFlicking )
+ {
+ iItemToBeFocused = NULL;
+ iItemToBeSelected = NULL;
+ iIndexToBeFocused = -1;
+ iHighlightTimer->Cancel();
+ }
+
+ if ( iItemToBeSelected != NULL )
+ {
+ iTreeListView->SelectItem( iItemToBeSelected );
+ iItemToBeSelected = NULL;
+ }
+ _AKNTRACE(
+ "CAknTreeListPhysicsHandler::[%s] Report EEventFlickStarted",
+ __FUNCTION__);
+ iTreeListView->ReportTreeListEvent(
+ MAknTreeListObserver::EEventFlickStarted,
+ KAknTreeIIDNone );
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+
+ if ( iPlayFeedbackOnUp )
+ {
+ // touch down has occured on an item, which requires feedback
+ // also on up event -> play basic list feedback
+ if ( iFeedback )
+ {
+ TTouchLogicalFeedback fbType = ETouchFeedbackList;
+ if ( iItemToBeSelected != NULL )
+ {
+ if ( iItemToBeSelected->IsLeaf() && iItemToBeSelected->IsMarkable() )
+ {
+ fbType = ETouchFeedbackCheckbox;
+ }
+ else if ( iItemToBeSelected->Node() != NULL )
+ {
+ if ( iItemToBeSelected->Node()->ChildCount() == 0 &&
+ iItemToBeSelected->Node()->IsMarkable() )
+ {
+ fbType = ETouchFeedbackCheckbox;
+ }
+ }
+ iFeedback->InstantFeedback( iTreeListView,
+ fbType,
+ ETouchFeedbackVibra,
+ aPointerEvent );
+ }
+
+ }
+ }
+
+ if ( iItemToBeSelected != NULL && !aMarking)
+ {
+ iTreeListView->SelectItem( iItemToBeSelected );
+ iItemToBeSelected = NULL;
+ }
+
+ if ( iItemToBeSelected == NULL && iEmptyAreaClicked )
+ {
+ if ( iTree->VisibleItemCount() > 0 )
+ {
+ iTreeListView->ReportTreeListEvent(
+ MAknTreeListObserver::EEmptyAreaClicked,
+ KAknTreeIIDNone );
+ }
+ else
+ {
+ iTreeListView->ReportTreeListEvent(
+ MAknTreeListObserver::EEmptyListClicked,
+ KAknTreeIIDNone );
+ }
+ }
+ }
+
+ // Item handling logic
+
+ TPoint adjustedPosition( aPointerEvent.iPosition );
+ adjustedPosition.iY += Offset();
+
+ for ( TInt ii = 0; ii < iItems->Count(); ++ii )
+ {
+ CAknTreeItem* item = (*iItems)[ii].Item();
+
+ if ( item && (*iItems)[ii].Rect().Contains( adjustedPosition ) )
+ {
+ if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
+ {
+ // Marking mode
+ if ( aMarking )
+ {
+ TBool drawNow = ( item == iTreeListView->FocusedItem() );
+ if ( aShiftPressed )
+ {
+ iTreeListView->MarkItems( iTreeListView->FocusedItem(), item,
+ !item->IsMarked(), drawNow );
+ }
+ else if ( aCtrlPressed )
+ {
+ iTreeListView->MarkItem( item, !item->IsMarked(), drawNow );
+ }
+ }
+ else if ( iTreeListView->SingleClickEnabled()
+ && !wasFlicking )
+ {
+ iItemToBeSelected = item;
+ iTreeListView->SetFocusedItem( item, ii, EFalse );
+ // Start long tap detector
+ if ( !iTreeListView->HasMarkedItemsL() )
+ {
+ iTreeListView->LongTapPointerEventL( aPointerEvent );
+ }
+ }
+ if ( ii != iTreeListView->FocusedItemIndex() )
+ {
+ iItemToBeFocused = item;
+ iIndexToBeFocused = ii;
+ // node will be collapsed/expanded only if flicking was not ongoing
+ if ( item->Node() && !wasFlicking )
+ {
+ iItemToBeSelected = item;
+ // Pressed down highlight to nonfocused item
+ iFlags.Set( EFlagPDHighlightToNonFocusedItem );
+ }
+ // touch down on non-focused item, while not flicking
+ if ( iFeedback && !wasFlicking )
+ {
+ if ( item->Node() )
+ {
+ // item is a non-focused node, play basic list
+ // feedback
+ iFeedback->InstantFeedback( iTreeListView,
+ ETouchFeedbackList );
+
+ // next up event causes for the node to collapse,
+ // play feedback on up event
+ iPlayFeedbackOnUp = ETrue;
+ }
+ else
+ {
+ // item is a non-focused leaf, play sensitive
+ // feedback
+ iFeedback->InstantFeedback( iTreeListView,
+ ETouchFeedbackSensitiveList );
+ }
+ }
+ }
+ // item will be selected only if flicking was not ongoing
+ else if ( !wasFlicking )
+ {
+ iItemToBeSelected = item;
+ // Pressed down highlight to focused item
+ iFlags.Set( EFlagPDHighlightToFocusedItem );
+ // touch down on focused item, while not flicking
+ if ( iFeedback )
+ {
+ iFeedback->InstantFeedback( iTreeListView,
+ ETouchFeedbackList );
+
+ // next up event cause an action on the screen,
+ // play feedback on up event
+ iPlayFeedbackOnUp = ETrue;
+ }
+ }
+ if ( !aMarking )
+ {
+ // timer will be launched everytime, but not
+ // if flicking was ongoing AND it was stopped by tapping
+ // to highlighted item or to folder (=node)
+ if ( !( wasFlicking && iItemToBeSelected != NULL ) )
+ {
+ LaunchHighlightTimer( wasScrolling );
+ }
+ }
+ else
+ {
+ // Pressed down highlight or highlight timer
+ // are not used in marking mode.
+ SetHighlight();
+ }
+ }
+ (*iItems)[ii].HandlePointerEventL( aPointerEvent, aViewLevel,
+ iTreeListView->Indention(), iTreeListView->IndentionWidth() );
+ }
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::HandleScrollEventL
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::HandleScrollEventL(
+ TEikScrollEvent aEventType, const TInt& aThumbPosition )
+ {
+ switch ( aEventType )
+ {
+ case EEikScrollUp:
+ case EEikScrollDown:
+ case EEikScrollPageUp:
+ case EEikScrollPageDown:
+ case EEikScrollThumbDragVert:
+ {
+ iScrollIndex = aThumbPosition;
+ ScrollView( ETrue );
+ }
+ // fall through
+ default:
+ {
+ StopPhysics();
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::HandleKeyEvent
+// -----------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::HandleKeyEvent( TInt aKeyCode )
+ {
+
+ if ( aKeyCode != EKeyLeftArrow && aKeyCode != EKeyRightArrow &&
+ aKeyCode != EKeyUpArrow && aKeyCode != EKeyDownArrow &&
+ aKeyCode != EKeyEnter && aKeyCode != EKeyOK )
+ {
+ return;
+ }
+
+ TInt lastItem = LastVisibleItemIndex();
+ TInt firstItem = FirstVisibleItemIndex();
+ TInt focusedItem = iTreeListView->FocusedItemIndex();
+
+ // Offset used in drawing
+ TInt panningOffset = Offset();
+ // When physics is activated view contains partial items
+ TInt viewOffset(
+ iItemHeight * ( lastItem - firstItem + 1 ) - iViewRect.Height() + iListTopOffset );
+
+ // Handle list top item
+ if ( panningOffset != 0 && ( firstItem == focusedItem ||
+ firstItem == focusedItem + 1 ) )
+ {
+ iScrollIndex -= panningOffset;
+ ScrollView( EFalse );
+ }
+ // Handle list bottom item
+ else if ( panningOffset != viewOffset && ( lastItem == focusedItem ||
+ lastItem == focusedItem - 1 ) )
+ {
+ iScrollIndex -= panningOffset - viewOffset;
+ ScrollView( EFalse );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::SetViewRect
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::SetViewRect( const TRect& aRect )
+ {
+ iViewRect = aRect;
+
+ // Calculate list top offset
+ TRect firstItemRect( ( *iItems )[ 0 ].Rect() );
+ if ( iViewRect.iTl.iY < firstItemRect.iTl.iY )
+ {
+ iListTopOffset = firstItemRect.iTl.iY - iViewRect.iTl.iY;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::ViewRect
+// ---------------------------------------------------------------------------
+//
+TRect CAknTreeListPhysicsHandler::ViewRect() const
+ {
+ return iViewRect;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::SetItemHeight
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::SetItemHeight( const TInt& aHeight )
+ {
+ if( iScrollIndex > 0 && iItemHeight > 0 && aHeight != iItemHeight )
+ {
+ iScrollIndex = ( iScrollIndex / iItemHeight ) * aHeight;
+ }
+ iItemHeight = aHeight;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Offset
+// ---------------------------------------------------------------------------
+//
+TInt CAknTreeListPhysicsHandler::Offset() const
+ {
+ if ( iItemHeight == 0)
+ {
+ return 0;
+ }
+
+ TInt currentLine = iScrollIndex / iItemHeight;
+
+ if ( currentLine < 0)
+ {
+ return iScrollIndex % iItemHeight + iItemHeight * currentLine;
+ }
+ else if ( currentLine >= iTree->VisibleItemCount() )
+ {
+ return iScrollIndex - ( iItemHeight * ( iTree->VisibleItemCount() - 1 ) );
+ }
+ return iScrollIndex % iItemHeight;
+ }
+
+
+// ---------------------------------------------------------------------------
+// InitPhysicsL
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::InitPhysicsL()
+ {
+ TSize totalSize( iViewRect.Width(), WorldHeight() );
+ TSize viewSize( iViewRect.Width(), iViewRect.Height() );
+
+ iPhysics->InitPhysicsL( totalSize, viewSize, EFalse );
+
+ if ( iScrollIndex < 0 )
+ {
+ iScrollIndex = 0;
+ ScrollView( EFalse );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::ResetEventBlockingStatus
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::ResetEventBlockingStatus()
+ {
+ iEventsBlocked = EFalse;
+ iEnableEvents = EFalse;
+ }
+
+
+// ---------------------------------------------------------------------------
+// GetVScrollbarParams
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::GetVScrollbarParams( TInt& aThumbSpan,
+ TInt& aThumbPos,
+ TInt& aScrollSpan )
+ {
+ aThumbSpan = iViewRect.Height() - iViewRect.Height() % 2;
+ aThumbPos = iScrollIndex;
+
+ TInt span1( aThumbPos + aThumbSpan );
+ TInt totalHeight( iTree->VisibleItemCount() * iItemHeight );
+ TInt span2( totalHeight - aThumbSpan );
+
+ aScrollSpan = Max( Min( span1, span2 ), totalHeight );
+ }
+
+
+// ---------------------------------------------------------------------------
+// FocusedItemVisible
+// ---------------------------------------------------------------------------
+//
+TBool CAknTreeListPhysicsHandler::FocusedItemVisible(
+ const TInt& aFocusedIndex ) const
+ {
+ TBool visible( EFalse );
+ if ( aFocusedIndex > -1 && aFocusedIndex < iItems->Count() )
+ {
+ visible = ETrue;
+ TInt topY( ( *iItems )[ aFocusedIndex ].Rect().iTl.iY - Offset() );
+ TInt bottomY( ( *iItems )[ aFocusedIndex ].Rect().iBr.iY - Offset() );
+ if ( bottomY < iViewRect.iTl.iY || topY > iViewRect.iBr.iY )
+ {
+ visible = EFalse;
+ }
+ }
+ return visible;
+ }
+
+
+// ---------------------------------------------------------------------------
+// FirstVisibleItemIndex
+// ---------------------------------------------------------------------------
+//
+TInt CAknTreeListPhysicsHandler::FirstVisibleItemIndex() const
+ {
+ TInt firstItemIndex( -1 );
+ if ( iItems->Count() )
+ {
+ firstItemIndex = 0;
+ TBool firstItemFound( EFalse );
+ while ( firstItemIndex < iItems->Count() && !firstItemFound )
+ {
+ TInt bottomY(
+ ( *iItems )[ firstItemIndex ].Rect().iBr.iY - Offset() );
+ if ( bottomY < iViewRect.iTl.iY )
+ {
+ firstItemIndex++;
+ }
+ else
+ {
+ firstItemFound = ETrue;
+ break;
+ }
+ }
+ if ( !firstItemFound )
+ {
+ firstItemIndex = 0;
+ }
+ }
+ return firstItemIndex;
+ }
+
+
+// ---------------------------------------------------------------------------
+// LastVisibleItemIndex
+// ---------------------------------------------------------------------------
+//
+TInt CAknTreeListPhysicsHandler::LastVisibleItemIndex() const
+ {
+ TInt lastItemIndex( -1 );
+ if ( iItems->Count() )
+ {
+ lastItemIndex = iItems->Count() - 1;
+ TBool lastItemFound( EFalse );
+ while ( lastItemIndex > -1 && !lastItemFound )
+ {
+ TInt topY( ( *iItems )[ lastItemIndex ].Rect().iTl.iY - Offset() );
+ if ( topY > iViewRect.iBr.iY )
+ {
+ lastItemIndex--;
+ }
+ else
+ {
+ lastItemFound = ETrue;
+ break;
+ }
+ }
+ }
+ return lastItemIndex;
+ }
+
+
+// ---------------------------------------------------------------------------
+// UpdateScrollIndex
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::UpdateScrollIndex( const TBool& aScrollTop )
+ {
+ // Do nothing if handler itself is updating the view
+ if ( iFlags.IsSet( EFlagUpdatingView ) )
+ {
+ return;
+ }
+
+ TInt first( 0 );
+ TInt scrollOffset( 0 );
+ TInt previousScrollIndex( iScrollIndex );
+
+ // Check that scroll index is within worldSizeLimit
+ TInt worldSizeLimit( WorldHeight() - iViewRect.Height() );
+ if ( worldSizeLimit < iScrollIndex && worldSizeLimit > 0 )
+ {
+ iScrollIndex = worldSizeLimit;
+ }
+
+ // Adjusting scroll index according to first visible item
+ if ( aScrollTop )
+ {
+ first = FirstVisibleItemIndex();
+ }
+
+ // Adjusting scroll index according to last visible item
+ else
+ {
+ scrollOffset = iViewRect.Height();
+ first = iItems->Count() - 1;
+ while ( scrollOffset > iItemHeight && first >= 0 )
+ {
+ scrollOffset -= iItemHeight;
+ first--;
+ }
+ }
+
+ if ( first >= 0 && first < iItems->Count() )
+ {
+ // First visible item index of the whole item list
+ TInt topIndex( iTree->VisibleItemIndex( (*iItems)[ first ].Item() ) );
+ TInt currentIndex( iScrollIndex / iItemHeight );
+
+ // Scrollindex needs updating
+ if ( topIndex != currentIndex || scrollOffset != 0 )
+ {
+ iScrollIndex = topIndex * iItemHeight + scrollOffset;
+
+ // Check that scroll index is within boundaries.
+ if ( iScrollIndex < 0 )
+ {
+ iScrollIndex = 0;
+ }
+ else if ( iScrollIndex > worldSizeLimit )
+ {
+ if ( worldSizeLimit < 0 )
+ {
+ // if worldSizeLimit<0, means the world height is less than view rect, no scroll needed,
+ // it is safe to set iScrollIndex to 0
+ iScrollIndex = 0;
+ }
+ else
+ {
+ iScrollIndex = worldSizeLimit;
+ }
+ }
+
+ // Update view if needed
+ if ( previousScrollIndex != iScrollIndex )
+ {
+ ScrollView( EFalse );
+ }
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// ViewPositionChanged
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::ViewPositionChanged(
+ const TPoint& aNewPosition,
+ TBool aDrawNow,
+ TUint /*aFlags*/ )
+ {
+ iScrollIndex = aNewPosition.iY - iViewRect.Height() / 2;
+ TTouchFeedbackType feedbackType = ETouchFeedbackVibra;
+ if ( iPhysics->OngoingPhysicsAction()
+ == CAknPhysics::EAknPhysicsActionDragging )
+ {
+ feedbackType = static_cast<TTouchFeedbackType>(ETouchFeedbackAudio | ETouchFeedbackVibra);
+ }
+ if ( iPhysics->OngoingPhysicsAction()
+ == CAknPhysics::EAknPhysicsActionBouncing )
+ {
+ iEventsBlocked = ETrue;
+ iEnableEvents = EFalse;
+ }
+ else
+ {
+ ResetEventBlockingStatus();
+ }
+
+ TInt viewBottom = aNewPosition.iY + iViewRect.Height() - iViewRect.Height() / 2;
+ if ( iPenDown )
+ {
+ iPenDown = EFalse;
+ if ( iScrollIndex <= iListTopOffset - iItemHeight )
+ {
+ iOldTopItem = -1;
+ }
+ else
+ {
+ iOldTopItem = ( iScrollIndex - iListTopOffset ) / iItemHeight;
+ if ( iOldTopItem >= iTree->VisibleItemCount() )
+ {
+ iOldTopItem = iTree->VisibleItemCount();
+ }
+ }
+
+ if ( viewBottom < iListTopOffset )
+ {
+ iOldBottomItem = -1;
+ }
+ else
+ {
+ iOldBottomItem = ( viewBottom - iListTopOffset ) / iItemHeight;
+ if ( iOldBottomItem >= iTree->VisibleItemCount() )
+ {
+ iOldBottomItem = iTree->VisibleItemCount();
+ }
+ }
+ }
+ else
+ {
+ TInt bottomItem, upperItem;
+ if ( iScrollIndex <= iListTopOffset - iItemHeight )
+ {
+ upperItem = -1;
+ }
+ else
+ {
+ upperItem = ( iScrollIndex - iListTopOffset ) / iItemHeight;
+ if ( upperItem >= iTree->VisibleItemCount() )
+ {
+ upperItem = iTree->VisibleItemCount();
+ }
+ }
+ if ( viewBottom < iListTopOffset )
+ {
+ bottomItem = -1;
+ }
+ else
+ {
+ bottomItem = ( viewBottom - iListTopOffset ) / iItemHeight;
+ if ( bottomItem >= iTree->VisibleItemCount() )
+ {
+ bottomItem = iTree->VisibleItemCount();
+ }
+ }
+ if ( upperItem == -1 )
+ {
+ if ( bottomItem != iOldBottomItem )
+ {
+ if ( bottomItem != iTree->VisibleItemCount() - 1 )
+ iFeedback->InstantFeedback( iTreeListView,
+ ETouchFeedbackSensitiveList,
+ feedbackType,
+ TPointerEvent() );
+ }
+ }
+ else if ( bottomItem == iTree->VisibleItemCount() )
+ {
+ if ( upperItem != iOldTopItem )
+ {
+ iFeedback->InstantFeedback( iTreeListView,
+ ETouchFeedbackSensitiveList,
+ feedbackType,
+ TPointerEvent() );
+ }
+ }
+ else if ( upperItem >= 0 || bottomItem < iTree->VisibleItemCount() )
+ {
+ if ( upperItem < iOldTopItem || bottomItem > iOldBottomItem )
+ {
+ iFeedback->InstantFeedback( iTreeListView,
+ ETouchFeedbackSensitiveList,
+ feedbackType,
+ TPointerEvent() );
+ }
+ }
+ iOldTopItem = upperItem;
+ iOldBottomItem = bottomItem;
+ }
+ ScrollView( aDrawNow );
+ }
+
+
+// ---------------------------------------------------------------------------
+// PhysicEmulationEnded
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::PhysicEmulationEnded()
+ {
+ iEnableEvents = ETrue;
+ _AKNTRACE("CAknTreeListPhysicsHandler::%s Report EEventFlickStopped",
+ __FUNCTION__);
+ iTreeListView->ReportTreeListEvent(
+ MAknTreeListObserver::EEventFlickStopped,
+ KAknTreeIIDNone );
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ MAknListBoxTfx* tfxApi = CAknListLoader::TfxApi( iTfxGc );
+
+ if ( tfxApi )
+ {
+ tfxApi->EnableEffects( ETrue );
+ }
+#endif // RD_UI_TRANSITION_EFFECTS_LIST
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::ViewPosition
+// ---------------------------------------------------------------------------
+//
+TPoint CAknTreeListPhysicsHandler::ViewPosition() const
+ {
+ TPoint viewPosition( iViewRect.Width() / 2,
+ iScrollIndex + iViewRect.Height() / 2 );
+ return viewPosition;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::SetGc
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::SetGc( CWindowGc* aGc )
+ {
+ iTfxGc = aGc;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::CAknTreeListPhysicsHandler
+// ---------------------------------------------------------------------------
+//
+CAknTreeListPhysicsHandler::CAknTreeListPhysicsHandler(
+ CAknTreeListView* aTreeListView,
+ CAknTree* aTree,
+ RArray<TAknTreeListViewItem>* aItems )
+ :
+ iPhysics( NULL ),
+ iHighlightTimer( NULL ),
+ iTree( aTree ),
+ iTreeListView( aTreeListView ),
+ iItems( aItems ),
+ iPlayFeedbackOnUp( EFalse )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::ConstructL()
+ {
+ iPhysics = CAknPhysics::NewL( *this, iTreeListView );
+ iHighlightTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+ iFeedback = MTouchFeedback::Instance();
+ }
+
+
+// ---------------------------------------------------------------------------
+// DragThreshold
+// ---------------------------------------------------------------------------
+//
+TInt CAknTreeListPhysicsHandler::DragThreshold()
+ {
+ return iPhysics->DragThreshold();
+ }
+
+
+// ---------------------------------------------------------------------------
+// LaunchHighlightTimer
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::LaunchHighlightTimer( TBool aWasScrolling )
+ {
+ if ( !aWasScrolling )
+ {
+ HighlightTimerCallback( this );
+ CCoeEnv::Static()->WsSession().Finish();
+ }
+ else
+ {
+ TInt highlightTimeout = iPhysics->HighlightTimeout() * 1000;
+
+ iHighlightTimer->Start(
+ TTimeIntervalMicroSeconds32( highlightTimeout ),
+ TTimeIntervalMicroSeconds32( highlightTimeout ),
+ TCallBack( HighlightTimerCallback, this ) );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// HighlightTimerCallback
+// ---------------------------------------------------------------------------
+//
+TInt CAknTreeListPhysicsHandler::HighlightTimerCallback( TAny* aPtr )
+ {
+ CAknTreeListPhysicsHandler* handler =
+ static_cast<CAknTreeListPhysicsHandler*>( aPtr );
+ if ( handler && handler->iTreeListView )
+ {
+ if ( handler->iTreeListView->SingleClickEnabled()
+ && !handler->iEnableEvents )
+ {
+ handler->iTreeListView->EnableHighlight(ETrue);
+ }
+ // Pressed down highlight if item still pressed down
+ if ( !handler->iFlags.IsSet( EFlagButtonUpReceived )
+ && handler->iFlags.IsSet( EFlagPDHighlightToFocusedItem ) )
+ {
+ handler->iTreeListView->SetPressedDownState( ETrue );
+ handler->iTreeListView->DrawNow();
+ }
+ else
+ {
+ // Pressed down highlight if item still pressed down
+ if ( !handler->iFlags.IsSet( EFlagButtonUpReceived )
+ && handler->iFlags.IsSet( EFlagPDHighlightToNonFocusedItem ) )
+ {
+ handler->iTreeListView->SetPressedDownState( ETrue );
+ }
+ handler->SetHighlight();
+ }
+ handler->iFlags.Clear( EFlagPDHighlightToFocusedItem );
+ handler->iFlags.Clear( EFlagPDHighlightToNonFocusedItem );
+ }
+ return NULL;
+ }
+
+
+// ---------------------------------------------------------------------------
+// SetHighlight
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::SetHighlight()
+ {
+ iHighlightTimer->Cancel();
+ if ( iItemToBeFocused )
+ {
+ iTreeListView->SetHighlight( iItemToBeFocused, iIndexToBeFocused );
+ iItemToBeFocused = NULL;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// ScrollView
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::ScrollView( TBool aDrawNow )
+ {
+ iFlags.Set( EFlagUpdatingView );
+ if ( iPreviousIndex != iScrollIndex )
+ {
+ iPreviousIndex = iScrollIndex;
+ TInt currentLine = iScrollIndex / iItemHeight;
+
+ TInt line = currentLine;
+ if ( currentLine < 0 )
+ {
+ line = 0;
+ }
+ else if ( currentLine >= iTree->VisibleItemCount() )
+ {
+ line = iTree->VisibleItemCount() - 1;
+ }
+
+ iTreeListView->UpdateTreeListView( line, aDrawNow );
+ }
+ iFlags.Clear( EFlagUpdatingView );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::StopPhysics
+// ---------------------------------------------------------------------------
+//
+void CAknTreeListPhysicsHandler::StopPhysics()
+ {
+ iPhysics->StopPhysics();
+ iPhysics->ResetFriction();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::WorldHeight
+// ---------------------------------------------------------------------------
+//
+TInt CAknTreeListPhysicsHandler::WorldHeight()
+ {
+ return iTree->VisibleItemCount() * iItemHeight + iListTopOffset;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknTreeListPhysicsHandler::EmptyAreaClicked
+// ---------------------------------------------------------------------------
+//
+TBool CAknTreeListPhysicsHandler::EmptyAreaClicked( TPoint aPosition )
+ {
+ if ( aPosition.iY <= WorldHeight() )
+ {
+ return EFalse;
+ }
+ return ETrue;
+ }
+
+