idlehomescreen/xmluirendering/uiengine/src/xnviewswitcher.cpp
branchRCL_3
changeset 88 3321d3e205b6
child 93 b01126ce0bec
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idlehomescreen/xmluirendering/uiengine/src/xnviewswitcher.cpp	Tue Sep 14 20:58:58 2010 +0300
@@ -0,0 +1,986 @@
+/*
+ * Copyright (c) 2002-2004 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:  Implementation for wrapper for a box
+ *
+ */
+
+// System includes
+#include <akntouchgesturefwevents.h>
+#include <centralrepository.h>
+
+#include <activeidle2domaincrkeys.h>
+#include <gfxtranseffect/gfxtranseffect.h>  
+
+#ifdef RD_TACTILE_FEEDBACK
+#include <touchfeedback.h>
+#endif // RD_TACTILE_FEEDBACK
+
+// User includes
+#include "xnappuiadapter.h"
+#include "xnuiengine.h"
+#include "xnproperty.h"
+#include "xnviewmanager.h"
+#include "xnviewdata.h"
+#include "xndomnode.h"
+#include "xnnode.h"
+#include "xnviewcontroladapter.h"
+#include "xneffectmanager.h"
+#include "xnrootdata.h"
+#include "xnviewadapter.h"
+#include "xnbackgroundmanager.h"
+
+#include "xnviewswitcher.h"
+
+// Constants
+const TInt KDrawDelay( 25000 ); // 16100 = 62 fps
+const TInt KDragTreshold( 30 );
+const TInt KMaxScrollSpeed( 150 );
+const TInt KMinScrollSpeed( 20 );
+const TInt KAnimationDuration( 500000 );
+const TInt KDragOffsetForBackground( 100 );
+const TInt KDragOffsetForPageSwitch( 50 );
+
+enum TViewPosition
+    {
+    KCurrentView, KNextView, KPreviousView
+    };
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void HideAdapter( CXnControlAdapter* aAdapter )
+    {
+    if( aAdapter )
+        {
+        aAdapter->Window().SetOrdinalPosition( -1 );
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void ShowAdapter( CXnControlAdapter* aAdapter )
+    {
+    if( aAdapter )
+        {
+        aAdapter->Window().SetOrdinalPosition( 1 );
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// Changes window position
+// -----------------------------------------------------------------------------
+//
+void SetWindowPosition( CXnControlAdapter* aAdapter, const TPoint& aPos )
+    {
+    if( aAdapter )
+        {
+        aAdapter->Window().SetPosition( aPos );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Hide/Show control
+// -----------------------------------------------------------------------------
+//
+void SetVisible( CCoeControl* aControl, TBool aVisible )
+    {
+    if( aControl )
+        {
+        aControl->MakeVisible( aVisible );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// ShowNodes
+// -----------------------------------------------------------------------------
+//
+void ShowNodesL( CXnNode& aNode, TBool aShow )
+    {    
+    CXnDomStringPool* sp( aNode.DomNode()->StringPool() );
+    
+    CXnProperty* prop( NULL );
+    if( aShow )
+        {
+        prop = CXnProperty::NewL(
+            XnPropertyNames::style::common::KDisplay, 
+            XnPropertyNames::style::common::display::KBlock,
+            CXnDomPropertyValue::EString, *sp );    
+        } 
+    else
+        {
+        prop = CXnProperty::NewL(
+            XnPropertyNames::style::common::KDisplay, 
+            XnPropertyNames::style::common::display::KNone,
+            CXnDomPropertyValue::EString, *sp );
+        }
+    CleanupStack::PushL( prop );    
+    
+    aNode.SetPropertyWithoutNotificationL( prop );
+    CleanupStack::Pop( prop );
+    }
+
+// -----------------------------------------------------------------------------
+// IsNodeVisible
+// -----------------------------------------------------------------------------
+//
+TBool IsNodeVisibleL( CXnNode& aNode )
+    {
+    CXnProperty* displayProp( aNode.DisplayL() );
+
+    if ( displayProp )
+        {
+        const TDesC8& display( displayProp->StringValue() );
+
+        if ( display == XnPropertyNames::style::common::display::KBlock )
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+    
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CXnViewSwitcher::NewL
+// Symbian static 1st phase constructor
+// -----------------------------------------------------------------------------
+//
+CXnViewSwitcher* CXnViewSwitcher::NewL()
+    {
+    CXnViewSwitcher* self = new (ELeave) CXnViewSwitcher();
+
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CXnViewSwitcher::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::ConstructL()
+    {
+    iFingerFollowSupported = IsFingerFollowSupportedL();
+    iTimer = CPeriodic::NewL( CActive::EPriorityUserInput );
+    iViewSwitchState = KViewSwitchIdle;
+    }
+
+// -----------------------------------------------------------------------------
+// CXnViewSwitcher::CXnViewSwitcher
+// C++ default constructor
+// -----------------------------------------------------------------------------
+//
+CXnViewSwitcher::CXnViewSwitcher() :
+    iAppUi(static_cast<CXnAppUiAdapter&> (*iAvkonAppUi))
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CXnViewSwitcher::~CXnViewSwitcher
+// C++ destructor
+// -----------------------------------------------------------------------------
+//
+CXnViewSwitcher::~CXnViewSwitcher()
+    {    
+    if (iTimer->IsActive())
+        {
+        iTimer->Cancel();
+        }
+    delete iTimer;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+TBool CXnViewSwitcher::FingerFollowSupported() const
+    {
+    return iFingerFollowSupported;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+TBool CXnViewSwitcher::ProcessPointerEventL(const TPointerEvent& aPointerEvent )
+    {
+    TBool consumed(EFalse);
+    
+    if ( FingerFollowSupported() )
+        {
+        TPoint parentPos = aPointerEvent.iParentPosition;
+
+        switch (aPointerEvent.iType)
+            {
+            case TPointerEvent::EButton1Down:
+                {
+                if ( iViewSwitchState == KViewSwitchBegin || iViewSwitchState
+                        == KViewSwitchIdle )
+                    {
+                    if (iTimer->IsActive())
+                        {
+                        iTimer->Cancel();
+                        }
+                    if( SetupViewsL() )
+                        {
+                        iViewSwitchState = KViewSwitchBegin;
+                        iStartPosition = parentPos;
+                        iScrollSpeed = KMaxScrollSpeed;
+                        iTickAmount = 0;
+                        iDirection = KCurrentView;
+                        iScrollDistance = 0;
+                        iScrollDirectionDistance = 0;
+                        }
+                    }
+                else if( iViewSwitchState == KViewSwitchDragOngoing )
+                    {
+                    consumed = ETrue;
+                    }
+                else if( iViewSwitchState == KViewSwitchScroll )
+                    {
+                    consumed = ETrue;
+
+                    if( iActivateView == KCurrentView )
+                        {
+                        if (iTimer->IsActive())
+                            {
+                            iTimer->Cancel();
+                            }                    
+
+                        iViewSwitchState = KViewSwitchDragOngoing;
+                        consumed = ETrue;    
+                        iViewStartPosition = iViewPosition;
+                        iScrollDistance = 0;
+                        iScrollDirectionDistance = 0;
+                        iStartPosition = parentPos;
+
+                        iTimer->Start( 0, KDrawDelay, TCallBack(
+                                TimerCallback, this ) );
+                        }
+                    else if( iActivateView == KNextView )
+                        {
+                        if( iCurrentView.iAdapter && iNextView.iAdapter && 
+                            iPreviousView.iAdapter )
+                            {
+                            if (iTimer->IsActive())
+                                {
+                                iTimer->Cancel();
+                                }
+                            
+                            iViewSwitchState = KViewSwitchDragOngoing;
+                            iActivateView = KCurrentView;
+                            
+                            if( iPreviousView.iAdapter == iNextView.iAdapter )
+                                {
+                                iPreviousView = iCurrentView;
+                                iCurrentView = iNextView;
+                                iNextView = iPreviousView;
+                                }
+                            else
+                                {
+                                iPreviousView = iCurrentView;
+    
+                                iCurrentView = iNextView;
+                                
+                                iNextView.iReadyToDraw = EFalse;
+                                CXnViewData* nextViewData( 
+                                    ViewData( *iCurrentView.iViewData, KNextView ) );
+                                CXnNode* nextViewNode( nextViewData->ViewNode() );
+                                if( nextViewNode )
+                                    {
+                                    iNextView.iAdapter = nextViewNode->Control();
+                                    iNextView.iViewData = nextViewData;
+                                    iNextView.iBgDrawn = EFalse;
+                                    }                            
+                                }
+                            
+                            iViewStartPosition = iCurrentView.iAdapter->Window().Position();
+                            iScrollDistance = 0;
+                            iScrollDirectionDistance = 0;
+                            iStartPosition = parentPos;
+                        
+                            iScrollSpeed = KMaxScrollSpeed;
+                            iTickAmount = 0;
+                            iTimer->Start( 0, KDrawDelay, TCallBack(
+                                    TimerCallback, this ) );
+                            }
+                        consumed = ETrue;
+                        }
+                    else if( iActivateView == KPreviousView )
+                        {
+                        if( iCurrentView.iAdapter && iNextView.iAdapter && 
+                            iPreviousView.iAdapter )
+                            {
+                            if (iTimer->IsActive())
+                                {
+                                iTimer->Cancel();
+                                }
+                            
+                            iViewSwitchState = KViewSwitchDragOngoing;
+                            iActivateView = KCurrentView;
+
+                            if( iPreviousView.iAdapter == iNextView.iAdapter )
+                                {
+                                iNextView = iCurrentView;
+                                iCurrentView = iPreviousView;
+                                iPreviousView = iNextView;
+                                }
+                            else
+                                {
+                                iNextView = iCurrentView;
+    
+                                iCurrentView = iPreviousView;
+                                
+                                iPreviousView.iReadyToDraw = EFalse;
+                                CXnViewData* prevViewData( 
+                                    ViewData( *iCurrentView.iViewData, KPreviousView ) );
+                                CXnNode* prevViewNode( prevViewData->ViewNode() );
+                                if( prevViewNode )
+                                    {
+                                    iPreviousView.iAdapter = prevViewNode->Control();
+                                    iPreviousView.iViewData = prevViewData;
+                                    iPreviousView.iBgDrawn = EFalse;
+                                    }                            
+                                }
+
+                            iViewStartPosition = iCurrentView.iAdapter->Window().Position();
+                            iScrollDistance = 0;
+                            iScrollDirectionDistance = 0;
+                            iStartPosition = parentPos;
+                        
+                            iScrollSpeed = KMaxScrollSpeed;
+                            iTickAmount = 0;
+                            iTimer->Start( 0, KDrawDelay, TCallBack(
+                                TimerCallback, this ) );
+                            }
+                        consumed = ETrue;
+                        }
+                    }
+                }
+                break;
+            case TPointerEvent::EDrag:
+                {
+                if( iViewSwitchState == KViewSwitchIdle )
+                    {
+                    consumed = EFalse;
+                    }
+                else if( iViewSwitchState == KViewSwitchBegin )
+                    {
+                    TPoint delta = parentPos - iStartPosition;
+
+                    if( Abs(delta.iX) > KDragTreshold || Abs(delta.iY) > KDragTreshold )
+                        {
+#ifdef RD_TACTILE_FEEDBACK            
+                        MTouchFeedback* feedback( MTouchFeedback::Instance() );
+                        
+                        if ( feedback )
+                            {
+                            feedback->InstantFeedback( ETouchFeedbackBasic );
+                            }
+#endif                           
+
+                        iViewSwitchState = KViewSwitchDragOngoing;
+                        iActivateView = KCurrentView;
+                        iViewPosition.iY = iCurrentView.iAdapter->Position().iY;
+                        iViewPosition.iX = 0;
+                        iStartPosition = parentPos;
+
+                        StartViewDraggingL();
+
+                        iTimer->Start( 0, KDrawDelay, TCallBack(
+                                TimerCallback, this ) );
+                        }
+                    consumed = ETrue;
+                    }
+                else if( iViewSwitchState == KViewSwitchDragOngoing )
+                    {
+                    iScrollDistance = parentPos.iX - iStartPosition.iX;
+                    consumed = ETrue;
+                    }
+                else
+                    {
+                    consumed = EFalse;                
+                    }
+                }
+                break;
+            case TPointerEvent::EButton1Up:
+                {
+                if( iViewSwitchState == KViewSwitchBegin )
+                    {
+                    iViewSwitchState = KViewSwitchIdle;
+                    }
+                else if( iViewSwitchState == KViewSwitchDragOngoing )
+                    {
+                    if (iTimer->IsActive())
+                        {
+                        iTimer->Cancel();
+                        }                    
+
+#ifdef RD_TACTILE_FEEDBACK            
+/*
+                    MTouchFeedback* feedback( MTouchFeedback::Instance() );
+                    
+                    if ( feedback )
+                        {
+                        feedback->InstantFeedback( ETouchFeedbackBasic );
+                        }
+*/
+#endif                           
+
+                    consumed = ETrue;
+                    
+                    StartViewScrolling();
+                    iViewSwitchState = KViewSwitchScroll;
+                    }
+                else if( iViewSwitchState == KViewSwitchScroll )
+                    {
+                    consumed = ETrue;
+                    }
+                }
+                break;
+            default:
+                break;
+            }
+        }
+
+    return consumed;
+    }
+    
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::TouchGesture( TAknTouchGestureFwType& /*aTouchGesture*/ )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CXnViewSwitcher::SizeChanged
+// -----------------------------------------------------------------------------
+// 
+void CXnViewSwitcher::SizeChanged( TRect aRect )
+    {
+    iRect = aRect;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+TBool CXnViewSwitcher::SetupViewsL()
+    {
+    TBool ret = EFalse;
+    
+    CXnViewManager& wManager = iAppUi.ViewManager();
+    iCurrentView.iViewData = &wManager.ActiveViewData();
+    iCurrentView.iAdapter = iCurrentView.iViewData->ViewNode()->Control();
+    iCurrentView.iReadyToDraw = ETrue;
+    iCurrentView.iBgDrawn = ETrue;
+
+    iViewStartPosition = TPoint( 0, iCurrentView.iAdapter->Window().Position().iY );
+
+    if ( wManager.ViewAmount() > 1 )
+        {
+        ret = ETrue;
+        
+        CXnNode* nextViewNode( wManager.NextViewData().ViewNode() );
+        if( nextViewNode )
+            {
+            iNextView.iAdapter = nextViewNode->Control();
+            iNextView.iViewData = &wManager.NextViewData();
+            }
+
+        CXnNode* prevViewNode( wManager.PreviousViewData().ViewNode() );
+        if( prevViewNode && prevViewNode == nextViewNode )
+            {
+            // Only 2 views in Homesceern -> previous = next
+            iPreviousView = iNextView;
+            }
+        else if( prevViewNode )
+            {
+            iPreviousView.iAdapter = prevViewNode->Control();
+            iPreviousView.iViewData = &wManager.PreviousViewData();
+            }
+        }
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::PrepareViewL( CXnViewSwitcher::TViewInformation& aView )
+    {
+    if( !aView.iAdapter || !aView.iViewData )
+        {
+        return;
+        }
+    
+    CXnControlAdapter& adapter = *aView.iAdapter;
+    RWindow& win( adapter.Window() );
+    win.SetOrdinalPosition( -1 );
+    adapter.MakeVisible( ETrue );
+
+    CXnNode* viewNode( aView.iViewData->ViewNode() );
+    TBool nodesVisible( IsNodeVisibleL( *viewNode ) );
+    if( !nodesVisible )
+        {
+        // Set visible temporarily
+        ShowNodesL( *viewNode, ETrue );
+        }
+    
+    iAppUi.ViewAdapter().EnterEditStateL( *aView.iViewData, EFalse );
+        
+    viewNode->UiEngine()->RenderFromNodeL( *viewNode );
+    aView.iReadyToDraw = ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::StartViewDraggingL()
+    {
+    // Remove focused node, in order to prevent activate triggers
+    CXnNode* currentViewNode =
+            iAppUi.ViewManager().ActiveViewData(). Node()->LayoutNode();
+    CXnUiEngine* engine(currentViewNode->UiEngine());
+
+    CXnNode* focusedNode = engine->FocusedNode();
+    if (focusedNode)
+        {
+        focusedNode->UnsetStateL(XnPropertyNames::style::common::KPressedDown);
+        focusedNode->UnsetStateL(XnPropertyNames::style::common::KFocus);
+        }
+
+    // Send button up to prevent long tapping 
+    TPointerEvent pointerEvent;
+    pointerEvent.iType = TPointerEvent::EButton1Up;
+    if ( iCurrentView.iAdapter )
+        {
+        iCurrentView.iAdapter->CXnControlAdapter::HandlePointerEventL(
+                pointerEvent);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::StartViewScrolling()
+    {
+    TInt screenWidth = iCurrentView.iAdapter->Window().Size().iWidth;
+
+    UpdateViewToBeActivated( KDragOffsetForPageSwitch );
+
+    switch (iActivateView)
+        {
+        case KPreviousView:
+            {
+            iScrollDistance = screenWidth - iViewPosition.iX;
+            }
+            break;
+        case KNextView:
+            {
+            iScrollDistance = -screenWidth - iViewPosition.iX;
+            }
+            break;
+        default: // KCurrentView
+            {
+            iScrollDistance = -iViewPosition.iX;
+            }
+            break;
+        }
+
+    TInt minSpeed = Abs( iScrollDistance / ( KAnimationDuration / KDrawDelay ) );
+    iScrollSpeed = Abs( iScrollSpeed );
+    if( iScrollSpeed < minSpeed )
+        {
+        iScrollSpeed = minSpeed;
+        }
+    if( iScrollSpeed < KMinScrollSpeed )
+        {
+        iScrollSpeed = KMinScrollSpeed;
+        }
+    if (iTimer->IsActive())
+        {
+        iTimer->Cancel();
+        }
+    
+    iTimer->Start(KDrawDelay, KDrawDelay, TCallBack(
+            TimerCallback, this));
+    }
+
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::ViewSwitchEndedL()
+    {
+    iViewSwitchState = KViewSwitchIdle;
+
+    if (iTimer->IsActive())
+        {
+        iTimer->Cancel();
+        }
+
+    iViewPosition.iX = 0;
+
+    if ( iCurrentView.iAdapter )
+        {
+        CXnViewManager& wManager( iAppUi.ViewManager() );
+        CXnViewData* activeViewData( &wManager.ActiveViewData() ); 
+        
+        switch( iActivateView )
+            {
+            case KCurrentView:
+                SetVisible( iNextView.iAdapter, EFalse );
+                SetVisible( iPreviousView.iAdapter, EFalse );    
+                
+                if( iCurrentView.iViewData && activeViewData != iCurrentView.iViewData )
+                    {
+                    wManager.ActivateViewL( *iCurrentView.iViewData, TUid::Null(), EFalse );            
+                    }
+                break;
+            case KPreviousView:
+                if ( iPreviousView.iAdapter )
+                    {
+                    SetVisible( iCurrentView.iAdapter, EFalse );
+                    if( iPreviousView.iAdapter != iNextView.iAdapter )
+                        {
+                        SetVisible( iNextView.iAdapter, EFalse );
+                        }
+
+                    CXnViewData* prevViewData( ViewData( *iCurrentView.iViewData, KPreviousView ) );
+                    if( prevViewData && activeViewData != prevViewData )
+                        {
+                        wManager.ActivateViewL( *prevViewData, TUid::Null(), EFalse );            
+                        }
+                    }
+                break;
+            case KNextView:
+                if ( iNextView.iAdapter )
+                    {
+                    SetVisible( iCurrentView.iAdapter, EFalse );
+                    if( iPreviousView.iAdapter != iNextView.iAdapter )
+                        {
+                        SetVisible( iPreviousView.iAdapter, EFalse );                
+                        }
+
+                    CXnViewData* nextViewData( ViewData( *iCurrentView.iViewData, KNextView ) );
+                    if( nextViewData && activeViewData != nextViewData )
+                        {
+                        wManager.ActivateViewL( *nextViewData, TUid::Null(), EFalse );            
+                        }                    
+                    }
+                break;
+            }
+
+        ClearViews();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::Scroll()
+    {
+    TInt scrollStep = iScrollDistance / 1.5;
+
+    if( Abs( scrollStep ) > Abs( iScrollSpeed ) )
+        {
+        scrollStep = ( scrollStep > 0 ) ? iScrollSpeed : -iScrollSpeed;
+        }
+
+    iViewPosition.iX += scrollStep;
+    iScrollDistance -= scrollStep;
+    }
+        
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::DoScroll()
+    {
+    SetWindowPosition( iCurrentView.iAdapter, iViewPosition );
+
+    if( iViewPosition.iX < 0 && iNextView.iAdapter )
+        {
+        // next view shown
+        if( !iNextView.iReadyToDraw )
+            {
+            TRAP_IGNORE( PrepareViewL( iNextView ) );
+            if( iPreviousView.iAdapter == iNextView.iAdapter )
+                {
+                iPreviousView.iReadyToDraw = ETrue;          
+                }
+            }
+        
+        ShowAdapter( iNextView.iAdapter );
+        if( iPreviousView.iAdapter != iNextView.iAdapter )
+            {
+            HideAdapter( iPreviousView.iAdapter );
+            }
+        
+        TPoint pos( TPoint( iViewPosition.iX + iRect.Width(), iViewPosition.iY ) );
+        SetWindowPosition( iNextView.iAdapter, pos );
+        }
+
+    else if( iViewPosition.iX > 0 && iPreviousView.iAdapter )
+        {
+        // previous view shown
+        if( !iPreviousView.iReadyToDraw )
+            {
+            TRAP_IGNORE( PrepareViewL( iPreviousView ) );
+            }
+
+        ShowAdapter( iPreviousView.iAdapter );
+        if( iPreviousView.iAdapter != iNextView.iAdapter )
+            {
+            HideAdapter( iNextView.iAdapter );
+            }
+        TPoint pos( TPoint( iViewPosition.iX - iRect.Width(), iViewPosition.iY ) );
+        SetWindowPosition( iPreviousView.iAdapter, pos );
+        }
+    
+    else
+        {
+        HideAdapter( iPreviousView.iAdapter );
+        HideAdapter( iNextView.iAdapter );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+TInt CXnViewSwitcher::TimerCallback(TAny *aPtr)
+    {
+    CXnViewSwitcher* self = reinterpret_cast<CXnViewSwitcher*> (aPtr);
+
+    if( self->iViewSwitchState == KViewSwitchDragOngoing )
+        {
+        TInt prevViewPos( self->iViewPosition.iX );
+        self->iViewPosition.iX = self->iViewStartPosition.iX + self->iScrollDistance;
+        self->DoScroll();
+        
+        self->UpdateViewToBeActivated( KDragOffsetForBackground );
+        
+        // Hack for informing NGA to draw. 
+        self->iAppUi.ViewAdapter().BgManager().DrawNow(TRect(0,0,1,1));
+        
+        // Scroll speed is average drag delta between timer callbacks.
+        self->iTickAmount++;
+
+        TInt scrollDistance = self->iViewPosition.iX - prevViewPos;
+        
+        if( ( scrollDistance < 0 && self->iScrollDirectionDistance > 0 ) || 
+            ( scrollDistance > 0 && self->iScrollDirectionDistance < 0 ) )
+            {
+            // Scroll direction has been changed
+            self->iScrollDirectionDistance = scrollDistance;
+            self->iScrollSpeed = scrollDistance;
+            self->iTickAmount = 1;            
+            }
+        else
+            {
+            self->iScrollDirectionDistance += scrollDistance;
+            self->iScrollSpeed = self->iScrollDistance / self->iTickAmount;    
+            }
+        
+        if( scrollDistance < 0 )
+            {
+            self->iDirection = KNextView;
+            }
+        else if( scrollDistance > 0 )
+            {
+            self->iDirection = KPreviousView;
+            }
+
+        return 0;
+        }
+
+    if ( Abs( self->iScrollDistance ) <= 2 )
+        {
+        TRAP_IGNORE( self->ViewSwitchEndedL() );
+        }
+    else
+        {
+        self->Scroll();
+        self->DoScroll();
+        
+        // Hack for inforing NGA to draw. 
+        self->iAppUi.ViewAdapter().BgManager().DrawNow(TRect(0,0,1,1));
+        }
+    return 0;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+TBool CXnViewSwitcher::IsFingerFollowSupportedL() const
+    {    
+    CRepository* repository =
+            CRepository::NewL(TUid::Uid(KCRUidActiveIdleLV));
+    TBool value(EFalse);
+    TInt err(repository->Get(KAIFingerFollowSupport, value));
+    delete repository;
+
+    return value && (KErrNone == err);
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+CXnViewData* CXnViewSwitcher::ViewData( CXnViewData& aCurrentViewData, 
+    TInt aView )
+    {
+    CXnRootData& rootData = iAppUi.ViewManager().ActiveAppData();
+    RPointerArray<CXnPluginData>& rootDataArr = rootData.PluginData();
+
+    CXnViewData* ret( NULL );
+    
+    TInt viewAmount( rootDataArr.Count() );
+    for( TInt i = 0; i < viewAmount; i++ )
+        {
+        CXnViewData* viewData = static_cast<CXnViewData*>( rootDataArr[i] );
+        if( &aCurrentViewData == viewData )
+            {
+            if( aView == KNextView )
+                {
+                if( i < viewAmount - 1 )
+                    {
+                    ret = static_cast<CXnViewData*>( rootDataArr[i + 1] );
+                    }
+                else
+                    {
+                    ret = static_cast<CXnViewData*>( rootDataArr[0] );            
+                    }
+                break;
+                }
+            else if( aView == KPreviousView )
+                {
+                if( i == 0 )
+                    {
+                    ret = static_cast<CXnViewData*>( rootDataArr[viewAmount - 1] );
+                    }
+                else
+                    {
+                    ret = static_cast<CXnViewData*>( rootDataArr[i - 1] );            
+                    }            
+                break;
+                }
+            }
+        }
+    
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::ClearViews()
+    {
+    TPoint p( 0, iCurrentView.iAdapter->Window().Position().iY );
+    SetWindowPosition( iCurrentView.iAdapter, p );
+    SetWindowPosition( iPreviousView.iAdapter, p );
+    SetWindowPosition( iNextView.iAdapter, p );
+    ShowAdapter( iPreviousView.iAdapter );
+    ShowAdapter( iNextView.iAdapter );
+    ShowAdapter( iCurrentView.iAdapter );
+    iCurrentView.iAdapter = NULL;
+    iCurrentView.iViewData = NULL;
+    iCurrentView.iReadyToDraw = EFalse;
+    iCurrentView.iBgDrawn = EFalse;
+    iNextView.iAdapter = NULL;
+    iNextView.iViewData = NULL;
+    iNextView.iReadyToDraw = EFalse;
+    iNextView.iBgDrawn = EFalse;
+    iPreviousView.iAdapter = NULL;
+    iPreviousView.iViewData = NULL;
+    iPreviousView.iReadyToDraw = EFalse;
+    iPreviousView.iBgDrawn = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::UpdateViewToBeActivated( TInt aOffset )
+    {
+    if ( iViewPosition.iX > aOffset && iDirection == KPreviousView && 
+        iScrollDirectionDistance > aOffset / 2)
+        {
+        if( iActivateView != KPreviousView &&
+            iPreviousView.iViewData && iCurrentView.iViewData )
+            {
+            iActivateView = KPreviousView;
+            if( !iPreviousView.iBgDrawn )
+                {
+                ChangeBackground( *iCurrentView.iViewData, 
+                    *iPreviousView.iViewData );
+                iPreviousView.iBgDrawn = ETrue; 
+                iNextView.iBgDrawn = EFalse;
+                iCurrentView.iBgDrawn = EFalse;
+                }
+            }
+        }
+    else if ( iViewPosition.iX < -aOffset && iDirection == KNextView && 
+        iScrollDirectionDistance < -aOffset / 2 )
+        {
+        if( iActivateView != KNextView && 
+            iNextView.iViewData && iCurrentView.iViewData )
+            {
+            iActivateView = KNextView;
+            if( !iNextView.iBgDrawn )
+                {
+                ChangeBackground( *iCurrentView.iViewData, 
+                    *iNextView.iViewData );
+                iPreviousView.iBgDrawn = EFalse; 
+                iNextView.iBgDrawn = ETrue;
+                iCurrentView.iBgDrawn = EFalse;                            
+                }
+            }
+        }
+    else if( iActivateView != KCurrentView && 
+        iPreviousView.iViewData && iNextView.iViewData && iCurrentView.iViewData )
+        {
+        if( Abs( iScrollDirectionDistance ) > aOffset / 2 )
+            {
+            iActivateView = KCurrentView;
+            if( !iCurrentView.iBgDrawn )
+                {    
+                ChangeBackground( ( iPreviousView.iBgDrawn ) ? *iPreviousView.iViewData :
+                    *iNextView.iViewData, *iCurrentView.iViewData );                                
+                iPreviousView.iBgDrawn = EFalse; 
+                iNextView.iBgDrawn = EFalse;
+                iCurrentView.iBgDrawn = ETrue;                            
+                }        
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CXnViewSwitcher::ChangeBackground( CXnViewData& aCurrent, CXnViewData& aNext )
+    {
+    CXnBackgroundManager& bg( iAppUi.ViewAdapter().BgManager() );
+
+    GfxTransEffect::Begin( &bg, KGfxControlActionBgImgToImgAppear );
+    
+    bg.ChangeWallpaper( aCurrent, aNext, EFalse );
+
+    GfxTransEffect::SetDemarcation( &bg, bg.Position() );
+    GfxTransEffect::End( &bg ); 
+    }
+            
+// End of file