taskswitcher/teleportui/hgteleportapp/src/hgteleportfastswaparea.cpp
changeset 2 08c6ee43b396
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/taskswitcher/teleportui/hgteleportapp/src/hgteleportfastswaparea.cpp	Mon Jan 18 20:10:36 2010 +0200
@@ -0,0 +1,1642 @@
+/*
+ * ============================================================================
+ *  Name        : hgteleportfastswaparea.cpp
+ *  Part of     : Hg Teleport
+ *  Description : Teleport Fast Swap area UI
+ *  Version     : %version: sa1spcx1#74 %
+ *
+ *  Copyright © 2008 Nokia.  All rights reserved.
+ *  This material, including documentation and any related computer
+ *  programs, is protected by copyright controlled by Nokia.  All
+ *  rights are reserved.  Copying, including reproducing, storing,
+ *  adapting or translating, any or all of this material requires the
+ *  prior written consent of Nokia.  This material also contains
+ *  confidential information which may not be disclosed to others
+ *  without the prior written consent of Nokia.
+ * ============================================================================
+ *
+ */
+
+#include <gulicon.h>
+#include <eikenv.h>
+#include <AknUtils.h>
+#include <AknIconUtils.h>
+#include <AknIconArray.h>
+#include <aknstyluspopupmenu.h>
+#include <AknQueryDialog.h>
+#include <StringLoader.h>
+#include <hgteleport.rsg>
+#include <aknlayoutscalable_apps.cdl.h>
+#include <layoutmetadata.cdl.h>
+#include <aknlists.h>
+#include <touchfeedback.h>
+#include <akntransitionutils.h>
+#include <akntranseffect.h>
+
+#include "hgteleportfastswaparea.h"
+#include "hgteleportapplogging.h"
+#include "hgfswclient.h"
+#include "hgteleportappui.h"
+#include "hgteleportdatachangeobserver.h"
+#include "hgteleporteventcontroler.h"
+
+/** command ids for the fsw popup */
+enum TPopupCommands
+    {
+    EFswCmdClose = 10000,
+    EFswCmdCloseAll
+    };
+
+/** Number of closable applications, to show "close all" option. */
+const TInt KHgMaxClosableApps = 2;
+
+/** Interval until which no change in the fsw content is rendered
+    after starting the closing of an application. */
+const TInt KRefreshDelayAfterClose = 2; // seconds
+
+/** Uid of Active Idle application. 
+    Used when movind Ai to specified position.*/
+const TUid KAiUid = TUid::Uid( 0x102750F0 );
+    
+/** Position of Ai in fsw grid.*/
+const TInt KAiPosition = 0;
+
+/** Default grid item to highlight.*/
+const TInt KItemToHighlight = 3;
+
+const TInt KAppKeyTypeShort = 1;
+const TInt KAppKeyTypeLong = 2;
+
+const TInt KLayoutItemCount = 3;
+
+const TInt KRedrawTime = 250000; // 0.25 sec
+const TInt KHighlighActivationTime = 100000; // 100 ms
+const TInt KUpdateGridTime = 1000000; // 1 s
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::NewL
+// -----------------------------------------------------------------------------
+//
+CHgTeleportFastSwapArea* CHgTeleportFastSwapArea::NewL( const TRect& aRect,
+    CCoeControl& aParent, CHgTeleportDeviceState& aDeviceState, 
+    CHgTeleportEventControler& aEventHandler )
+    {
+    CHgTeleportFastSwapArea* self = CHgTeleportFastSwapArea::NewLC(aRect,
+            aParent, aDeviceState, aEventHandler);
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::NewLC
+// -----------------------------------------------------------------------------
+//
+CHgTeleportFastSwapArea* CHgTeleportFastSwapArea::NewLC( const TRect& aRect,
+    CCoeControl& aParent, CHgTeleportDeviceState& aDeviceState,
+    CHgTeleportEventControler& aEventHandler)
+    {
+    CHgTeleportFastSwapArea* self = new (ELeave) CHgTeleportFastSwapArea(
+            aParent, aDeviceState, aEventHandler);
+    CleanupStack::PushL( self );
+    self->ConstructL( aRect );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::CHgTeleportFastSwapArea
+// -----------------------------------------------------------------------------
+//
+CHgTeleportFastSwapArea::CHgTeleportFastSwapArea(CCoeControl& aParent,
+    CHgTeleportDeviceState& aDeviceState,
+    CHgTeleportEventControler& aEventHandler) :
+    iParent(aParent), iDeviceState(aDeviceState), iEvtHandler(aEventHandler),
+    iPreviousNoOfItems(0)
+    {
+    // no implementation required
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::~CHgTeleportFastSwapArea
+// -----------------------------------------------------------------------------
+//
+CHgTeleportFastSwapArea::~CHgTeleportFastSwapArea()
+    {
+    iArray.ResetAndDestroy();
+    delete iGrid;
+    delete iFSClient;
+    delete iPopup;
+    delete iConfirmCloseQuery;
+    delete iHighlightTimer;
+    delete iRedrawTimer;
+    delete iUpdateGridTimer;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::ConstructL( const TRect& aRect )
+    {
+    SetContainerWindowL( iParent );
+
+    SetRect( aRect );
+
+    // setup ganes grid
+    ReCreateGridL();
+
+    // create stylus popup instance
+    PreCreatePopupL();
+
+    // connect to fsw server
+    iFSClient = CHgFswClient::NewL();
+    
+    iEvtHandler.ReInitPhysicsL(GridWorldSize(), ViewSize(), ETrue);
+    
+    // add self to device state observer
+    iDeviceState.AddObserverL( *this, EDeviceType );
+    
+    iHighlightTimer = new (ELeave) CHgTeleportFastSwapTimer( *this );
+    iHighlightTimer->ConstructL();
+    
+    iRedrawTimer = new (ELeave) CHgTeleportFastSwapTimer( *this );
+    iRedrawTimer->ConstructL();
+
+    iUpdateGridTimer = new (ELeave) CHgTeleportFastSwapTimer( *this );
+    iUpdateGridTimer->ConstructL();
+    
+    ActivateL();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ReCreateGridL
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::ReCreateGridL()
+    {
+    MCoeControlObserver* obs = NULL;
+    TBool wasHighlight = iDeviceState.DeviceType() == 
+                             CHgTeleportDeviceState::EHybrid ? ETrue : EFalse;
+    if ( iGrid )
+        {
+        obs = iGrid->Observer();
+        iDeviceState.RemoveObserver(*iGrid);
+        wasHighlight = iGrid->IsHighlightVisible();
+        delete iGrid;
+        iGrid = NULL;
+        }
+    
+    iGrid = new( ELeave ) CHgTeleportFastSwapGrid;
+    iGrid->ConstructL( this );
+    iDeviceState.AddObserverL(*iGrid, MHgDeviceStateObserver::ESkin);
+    
+    AknListBoxLayouts::SetupStandardGrid( *iGrid );
+    
+    RArray<TAknLayoutRect> rects;
+    CleanupClosePushL(rects);
+    rects.ReserveL(KLayoutItemCount);
+    GetFastSwapAreaRects(rects);
+    TAknLayoutRect gridAppPane = rects[0];
+    TAknLayoutRect gridItem = rects[1];
+    TAknLayoutRect gridImage = rects[2];
+    CleanupStack::PopAndDestroy(&rects);
+    
+    TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
+    iGrid->SetRect(gridAppPane.Rect());
+    iGrid->SetVisibleViewRect(gridAppPane.Rect());
+    TAknLayoutScalableParameterLimits gridParams = 
+        AknLayoutScalable_Apps::cell_tport_appsw_pane_ParamLimits( variety );
+    TPoint empty( ELayoutEmpty, ELayoutEmpty );
+    
+#ifndef TASKSWITCHER_USE_CUSTOM_LAYOUT
+    AknListBoxLayouts::SetupFormGfxCell( *iGrid, iGrid->ItemDrawer(), 0,
+            AknLayoutScalable_Apps::cell_tport_appsw_pane_g1( variety ).LayoutLine(),
+            empty, empty );
+#else
+    TRect imageRect;
+    TRect textRect;
+    TInt leftMargin = ( KFswItemWidth - KFswImageSize ) / 2;
+    TInt topMargin = ( KFswItemHeight - KFswImageSize - KFswTextHeight ) / 3;
+    textRect.iTl = TPoint( leftMargin, topMargin );
+    textRect.iBr = TPoint( leftMargin + KFswImageSize, topMargin + KFswTextHeight );
+    imageRect.iTl = TPoint( leftMargin, topMargin * 2 + KFswTextHeight );
+    imageRect.iBr = TPoint( leftMargin + KFswImageSize, topMargin * 2 + KFswTextHeight + KFswImageSize );
+    
+    AknListBoxLayouts::SetupFormGfxCell( *iGrid, iGrid->ItemDrawer(), 0 /*Column index*/,
+                                         imageRect.iTl.iX  /*Left pos*/, imageRect.iTl.iY /*Top pos*/,
+                                         0 /*unused*/, 0 /*unused*/,
+                                         imageRect.Width() /*Icon width*/,
+                                         imageRect.Height() /*Icon height*/,
+                                         imageRect.iTl /*Start pos*/,
+                                         imageRect.iBr /*End pos*/ );
+#endif
+
+    // Setup text layout
+    TRgb textColor;
+    AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor,
+            KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG9 );
+    
+    TAknLayoutText textLayout;
+    textLayout.LayoutText(
+            Rect(),
+            AknLayoutScalable_Apps::cell_tport_appsw_pane_t1( variety ).LayoutLine() );
+    
+    // Because textLayout.BaselineOffset() does not work (missing lib entry),
+    // we need to calculate offset ourselves
+#ifndef TASKSWITCHER_USE_CUSTOM_LAYOUT
+    TInt baselineOffset = textLayout.TextRect().iBr.iY - textLayout.TextRect().iTl.iY;
+    AknListBoxLayouts::SetupFormTextCell( *iGrid, iGrid->ItemDrawer(), 1 /*Column index*/,
+                                          textLayout.Font() /*Font type*/,
+                                          textColor.Color16() /*color*/,
+                                          textLayout.TextRect().iTl.iX /*Left margin*/, 0 /*unused*/,
+                                          baselineOffset /*Baseline*/, 0 /*Text width*/,
+                                          textLayout.Align() /*Text alignment*/,
+                                          TPoint(0,0) /*Start pos*/,
+                                          TPoint(0,0) /*End pos*/);
+#else    
+    TInt baselineOffset = textRect.iBr.iY - textRect.iTl.iY;
+    AknListBoxLayouts::SetupFormTextCell( *iGrid, iGrid->ItemDrawer(), 1 /*Column index*/,
+                                          textLayout.Font() /*Font type*/,
+                                          textColor.Color16() /*color*/,
+                                          textRect.iTl.iX /*Left margin*/, 0 /*unused*/,
+                                          baselineOffset /*Baseline*/, 0 /*Text width*/,
+                                          CGraphicsContext::ECenter /*Text alignment*/,
+                                          TPoint(0,0) /*Start pos*/,
+                                          TPoint(0,0) /*End pos*/);
+#endif
+    
+    // Setup grid observers
+    if ( obs )
+        {
+        iGrid->SetObserver( obs );
+        }
+    iGrid->SetListBoxObserver(this);
+    iGrid->SetFastSwapGridObserver(this);
+    iGrid->SetContainerWindowL(*this);
+    
+#ifndef TASKSWITCHER_USE_CUSTOM_LAYOUT
+    iMaxItemsOnScreen = Rect().Width() / gridItem.Rect().Width();
+    iGridItemWidth = gridItem.Rect().Width();
+#else
+    iMaxItemsOnScreen = Rect().Width() / KFswItemWidth;
+    iGridItemWidth = KFswItemWidth;
+#endif
+    
+    iGrid->ItemDrawer()->ColumnData()->SetDrawBackground(EFalse);
+    
+    // Update state
+    HandleDeviceStateChanged( EDeviceType );
+    if( wasHighlight )
+        {
+        iGrid->ShowHighlight();
+        }
+    else
+        {
+        iGrid->HideHighlight();
+        }
+    
+    // Make sure that there is an ActivateL call even when we are not
+    // called from ConstructL. (in order to have the grid's parent ptr set properly)
+    ActivateL();
+    }
+
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::GetFastSwapAreaRects
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::GetFastSwapAreaRects( RArray<TAknLayoutRect>& aRects )
+    {
+    TAknLayoutRect gridAppPane;
+    TAknLayoutRect gridItem;
+    TAknLayoutRect gridImage;
+    
+    TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
+    
+    gridAppPane.LayoutRect( Rect(), 
+            AknLayoutScalable_Apps::tport_appsw_pane( variety ) );
+    aRects.Append(gridAppPane);
+    
+    gridItem.LayoutRect( gridAppPane.Rect(),
+            AknLayoutScalable_Apps::cell_tport_appsw_pane( variety, 0, 0 ) );
+    aRects.Append(gridItem);
+    
+    gridImage.LayoutRect( gridItem.Rect(),
+            AknLayoutScalable_Apps::cell_tport_appsw_pane_g1( variety ) ); 
+    aRects.Append(gridImage);
+    }
+
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::Setup
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::Setup( MCoeControlObserver& aControlObserver )
+    {
+    iGrid->SetObserver( &aControlObserver );
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::SizeChanged
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::SizeChanged()
+    {
+    HGLOG_CONTEXT( CHgTeleportFastSwapArea::SizeChanged, HGLOG_LOCAL );
+    HGLOG_IN();
+    
+    if ( iGrid )
+        {
+        // Grid needs to be recreated to proper reinitilize
+        // data with new layout values
+        TInt selIdx = SelectedIndex();
+        TRAPD(err, 
+              ReCreateGridL();
+              iEvtHandler.ReInitPhysicsL(GridWorldSize(), ViewSize(), ETrue););
+        if ( err != KErrNone )
+            {
+            HGLOG1( HGLOG_INFO, "ReCreateGridL leaves with %d", err );
+            }
+        HandleFswContentChanged();
+        iGrid->SetCurrentDataIndex(selIdx);
+        UpdateGrid(ETrue, EFalse);
+        DrawDeferred();
+        }
+    HGLOG_OUT();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::Draw
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::Draw( const TRect& /*aRect*/ ) const
+    {
+    CWindowGc& gc = SystemGc();
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
+    AknsDrawUtils::Background( skin,
+           cc,
+           this,
+           gc,
+           Rect() );
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::SwitchToApp
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::SwitchToApp( TInt aIndex )
+    {
+    if ( aIndex >= 0 && aIndex < iArray.Count() )
+        {
+        TInt wgId = iArray[aIndex]->WgId();
+        // Move other app to foreground and then move ourselves to background.
+        // Order is important and cannot be reversed.
+        iFSClient->SwitchToApp( wgId );
+        // We do not want to come back to teleport if the activated app is closed.
+        // Therefore teleport must be moved to background.
+        CHgTeleportAppUi* appui =
+            static_cast<CHgTeleportAppUi*>( iEikonEnv->AppUi() );
+        appui->MoveAppToBackground( AknTransEffect::EApplicationStartRect );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::TryCloseAppL
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::TryCloseAppL( TInt aIndex,
+        TBool aSuppressRendering )
+    {
+    HGLOG_CONTEXT( TryCloseAppL, HGLOG_LOCAL );
+    HGLOG2_IN( "%d %d", aIndex, aSuppressRendering );
+
+    if ( aIndex >= 0 && aIndex < iArray.Count() && CanClose( aIndex ) )
+        {
+        TInt wgId = iArray[aIndex]->WgId();
+        iFSClient->CloseApp( wgId );
+        // The fsw content will change sooner or later
+        // but the updated content (without the closed app) will not
+        // come very fast. It looks better to the user if the item
+        // in the grid is removed right here, right now.
+        // If the app does not close for some reason then this is
+        // not fully correct but the app will then reappear on the next
+        // content-changed notification anyway.
+        delete iArray[aIndex];
+        iArray.Remove( aIndex );
+        NotifyChange();
+        if ( !aSuppressRendering )
+            {
+            RenderContentL();
+            }
+        // Update item selection on the screen if last item was deleted
+        TInt newItemCount = GridItemCount();
+        if ( aIndex == newItemCount )
+            {
+            newItemCount--;
+            iGrid->SetCurrentDataIndex(newItemCount);
+            }
+        iTimeOfLastClose.HomeTime();
+        }
+
+    HGLOG_OUT();
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::TryCloseAppWithQueryL
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::TryCloseAppWithQueryL( TInt aIndex )
+    {
+    if ( aIndex >= 0 && aIndex < iArray.Count()
+            && CanClose( aIndex )
+            && ConfirmCloseL( aIndex ) )
+        {
+        TryCloseAppL( aIndex );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::TryCloseAllL
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::TryCloseAllL()
+    {
+    // note the direction of the loop, this is needed because
+    // TryCloseAppL may modify the array
+    TBool changed = EFalse;
+    for ( TInt i = iArray.Count() - 1; i >= 0; --i )
+        {
+        if ( CanClose( i ) )
+            {
+            TryCloseAppL( i, ETrue );
+            changed = ETrue;
+            }
+        }
+    if ( changed )
+        {
+        RenderContentL();
+        RestoreSelectedIndex();
+        iGrid->DrawNow();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::CanClose
+// --------------------------------------------------------------------------
+//
+TBool CHgTeleportFastSwapArea::CanClose( TInt aIndex ) const
+    {
+    CHgFswEntry* e = iArray[aIndex];
+    return !e->AlwaysShown() && !e->SystemApp();
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::CanCloseOthers
+// --------------------------------------------------------------------------
+//
+TBool CHgTeleportFastSwapArea::CanCloseAll( TInt aSelectedItem ) const
+    {
+    TInt count( 0 );
+
+    // Count number of closable applications and if number exceeds 2 finish
+    // counting, because it is already enough to show the option.
+    for ( TInt i = iArray.Count(); --i >= 0 && count < KHgMaxClosableApps; )
+        {
+        if ( CanClose( i ) )
+            {
+            count++;
+            }
+        }
+    return ( count >= KHgMaxClosableApps ) ||
+           ( count && !CanClose( aSelectedItem ) );
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::HandleFswContentChanged
+// From MHgFswObserver
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::HandleFswContentChanged()
+    {
+    HGLOG_CONTEXT( HandleFswContentChanged, HGLOG_LOCAL );
+    HGLOG_IN();
+
+    TRAPD( err, HandleFswContentChangedL() );
+    if ( err != KErrNone )
+        {
+        HGLOG1( HGLOG_INFO, "leave occured: %d", err );
+        }
+
+    HGLOG_OUT();
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::HandleFswContentChangedL
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::HandleFswContentChangedL()
+    {
+    HGLOG_CONTEXT( HandleFswContentChangedL, HGLOG_LOCAL );
+    HGLOG_IN();
+
+    // If there was an app close operation started during the last
+    // few seconds then stop, to prevent flickering.
+    TTime now;
+    now.HomeTime();
+    TTimeIntervalSeconds iv;
+    if ( now.SecondsFrom( iTimeOfLastClose, iv ) == KErrNone
+            && iv.Int() <= KRefreshDelayAfterClose )
+        {
+        HGLOG1_OUT( "difference since last close is only %d sec, stop", iv.Int() );
+        return;
+        }
+
+    // get current content from fastswap server
+    iFSClient->GetContentL( iArray );
+    SwapApplicationOrder( iArray );
+
+#ifdef _DEBUG
+    for ( TInt i = 0, ie = iArray.Count(); i != ie; ++i )
+        {
+        CHgFswEntry* e = iArray[i];
+        const TDesC& name( e->AppName() );
+        HGLOG4( HGLOG_INFO, "[%d]: %d %d %S", i, e->WgId(), e->AppUid(), &name );
+        }
+#endif
+
+    // draw
+    RenderContentL();
+
+    // notify observer, if present
+    NotifyChange();
+
+    HGLOG_OUT();
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::RenderContentL
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::RenderContentL()
+    {
+    HGLOG_CONTEXT( RenderContentL, HGLOG_LOCAL );
+    HGLOG_IN();
+
+    _LIT(KSeparator, "\t");
+    
+    CArrayPtr<CGulIcon>* iconArray = new ( ELeave ) CAknIconArray( iArray.Count() );
+    CleanupStack::PushL( iconArray );
+    CDesCArrayFlat* textArray = new ( ELeave ) CDesCArrayFlat( iArray.Count() );
+    CleanupStack::PushL( textArray );
+    RArray<TInt> closeItemArray;
+    CleanupClosePushL(closeItemArray);
+    
+    TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
+    RArray<TAknLayoutRect> rects;
+    CleanupClosePushL(rects);
+    rects.ReserveL(KLayoutItemCount);
+    GetFastSwapAreaRects(rects);
+    TAknLayoutRect gridItem = rects[1];
+    CleanupStack::PopAndDestroy(&rects);
+    if ( AknLayoutUtils::LayoutMirrored() )
+        {
+#ifndef TASKSWITCHER_USE_CUSTOM_LAYOUT
+        iGrid->SetLayoutL( EFalse, EFalse, ETrue, iArray.Count(), 1, gridItem.Rect().Size() );
+#else
+        TSize itemSize( KFswItemWidth, KFswItemHeight );
+        iGrid->SetLayoutL( EFalse, EFalse, ETrue, iArray.Count(), 1, itemSize );
+#endif
+        }
+    else
+        {
+#ifndef TASKSWITCHER_USE_CUSTOM_LAYOUT
+        iGrid->SetLayoutL( EFalse, ETrue, ETrue, iArray.Count(), 1, gridItem.Rect().Size() );
+#else
+        TSize itemSize( KFswItemWidth, KFswItemHeight );
+        iGrid->SetLayoutL( EFalse, ETrue, ETrue, iArray.Count(), 1, itemSize );
+#endif
+        }
+    
+    for ( TInt i = 0, ie = iArray.Count(); i != ie; ++i )
+        {
+        const TDesC& appName( iArray[i]->AppName() );
+        const TInt formatLen = 3 + 2;
+        RBuf formAppName;
+        CleanupClosePushL(formAppName);
+        formAppName.CreateL(appName.Length() + formatLen);
+        formAppName.AppendNum(i);
+        formAppName.Append(KSeparator);
+        formAppName.Append(appName);
+        textArray->AppendL(formAppName);
+        CleanupStack::PopAndDestroy(&formAppName);
+        TSize sz = PreferredImageSize();
+
+        // take the screenshot or appicon+mask and make a copy and scale
+        CFbsBitmap* bitmap = 0;
+        TInt h = iArray[i]->ScreenshotHandle();
+        HGLOG2( HGLOG_INFO, "'%S' screenshot handle %d", &appName, h );
+        TInt maskh = 0;
+        CFbsBitmap* mask = 0;
+        if ( !h )
+            {
+            h = iArray[i]->AppIconBitmapHandle();
+            maskh = iArray[i]->AppIconMaskHandle();
+            HGLOG1( HGLOG_INFO, "using appicon, handle = %d", h );
+            }
+        __ASSERT_DEBUG( h, User::Invariant() );
+        bitmap = CopyBitmapL( h, sz );
+        CleanupStack::PushL( bitmap );
+        if ( maskh )
+            {
+            mask = CopyBitmapL( maskh, sz );
+            }
+        CleanupStack::PushL( mask );
+
+        CGulIcon* icon = CGulIcon::NewL( bitmap, mask );
+        CleanupStack::PushL(icon);
+        iconArray->AppendL(icon);
+        CleanupStack::Pop( 3, bitmap ); // mask, bitmap, icon
+        
+        // Check if item can be closed
+        if ( CanClose(i) && AknLayoutUtils::PenEnabled() )
+            {
+            closeItemArray.AppendL(i);
+            }
+        }
+    // Setup grid
+    iGrid->Model()->SetItemTextArray(textArray);
+    CArrayPtr<CGulIcon>* oldIconArray =
+        iGrid->ItemDrawer()->FormattedCellData()->IconArray();
+    if(oldIconArray)
+        {
+        delete oldIconArray;
+        oldIconArray = NULL;
+        }
+    iGrid->ItemDrawer()->FormattedCellData()->SetIconArrayL(iconArray);
+    iGrid->SetCloseItemsL(closeItemArray);
+    
+    // Cleanup
+    CleanupStack::PopAndDestroy(&closeItemArray);
+    CleanupStack::Pop(textArray);
+    CleanupStack::Pop(iconArray);
+    
+    iGrid->ScrollBarFrame()->SetScrollBarVisibilityL(
+                CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOff);
+    
+    // refresh the items in the grid
+    if(iPreviousNoOfItems < iArray.Count())
+        {
+        iGrid->HandleItemAdditionL();
+        }
+    else if(iPreviousNoOfItems > iArray.Count())
+        {
+        iGrid->HandleItemRemovalL();
+        }
+    iPreviousNoOfItems = iArray.Count();
+    iEvtHandler.ReInitPhysicsL( GridWorldSize(), ViewSize(), ETrue );
+    UpdateGrid( ETrue );
+    
+    HGLOG_OUT();
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::CopyBitmapL
+// Copy and scale.
+// --------------------------------------------------------------------------
+//
+CFbsBitmap* CHgTeleportFastSwapArea::CopyBitmapL( TInt aFbsHandle, TSize aSize )
+    {
+    CFbsBitmap* ret = new (ELeave) CFbsBitmap();
+    CleanupStack::PushL( ret );
+
+    CFbsBitmap* bmp = new (ELeave) CFbsBitmap();
+    CleanupStack::PushL( bmp );
+    User::LeaveIfError( bmp->Duplicate( aFbsHandle ) );
+
+    // do not always use aSize, preserving the aspect ratio is quite
+    // important when showing app icons instead of screenshots
+    TSize sz = CalculateSizePreserveRatio( aSize, bmp->SizeInPixels() );
+
+    User::LeaveIfError( ret->Create( sz, bmp->DisplayMode() ) );
+
+    AknIconUtils::ScaleBitmapL( sz, ret, bmp );
+
+    CleanupStack::PopAndDestroy( bmp );
+    CleanupStack::Pop( ret );
+
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::CountComponentControls
+// --------------------------------------------------------------------------
+//
+TInt CHgTeleportFastSwapArea::CountComponentControls() const
+    {
+    return 1;
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ComponentControl
+// --------------------------------------------------------------------------
+//
+CCoeControl* CHgTeleportFastSwapArea::ComponentControl( TInt aIndex ) const
+    {
+    if ( aIndex == 0 )
+        {
+        return iGrid;
+        }
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::HandleSwitchToBackgroundEvent
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::HandleSwitchToBackgroundEvent()
+    {
+    // stop listening for changes in fsw content
+    iFSClient->CancelSubscribe();
+    // get rid of the close confirmation query if shown
+    delete iConfirmCloseQuery; // this will cause ExecuteLD to return with 0
+    iConfirmCloseQuery = 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::HandleSwitchToForegroundEvent
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::HandleSwitchToForegroundEvent()
+    {
+    HGLOG_CONTEXT( CHgTeleportFastSwapArea::HandleSwitchToForegroundEvent, HGLOG_LOCAL );
+    HGLOG_IN();
+    
+    // get the current task list
+    HandleFswContentChanged();
+    // and then start listening for changes
+    iFSClient->Subscribe( *this );
+    
+    if ( iDeviceState.DeviceType() == CHgTeleportDeviceState::EFullTouch )
+        {
+        iGrid->HideHighlight();
+        }
+    else
+        {
+        iGrid->ShowHighlight();
+        }
+    
+    RestoreSelectedIndex();
+    UpdateGrid(ETrue, EFalse);
+    
+    iRedrawTimer->Cancel();
+    iRedrawTimer->After(KRedrawTime);
+    
+    // give feedback
+    LaunchPopupFeedback();
+
+    HGLOG_OUT();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::FocusChanged
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::FocusChanged( TDrawNow /*aDrawNow*/ )
+    {
+    if ( IsFocused() )
+        {
+        // if in non-touch mode then select (highlight) some item
+        if ( !AknLayoutUtils::PenEnabled()
+            && SelectedIndex() == KErrNotFound
+            && GridItemCount() )
+            {
+            RestoreSelectedIndex();
+            }
+        }
+    else
+        {
+        // store the currently selected index if there is one
+        SaveSelectedIndex();
+        }
+    iGrid->DrawDeferred();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::OfferKeyEventL
+// -----------------------------------------------------------------------------
+//
+TKeyResponse CHgTeleportFastSwapArea::OfferKeyEventL(
+        const TKeyEvent& aKeyEvent,
+        TEventCode aType )
+    {
+    iKeyEvent = ETrue;
+    // handle the 'clear' key
+    if ( aType == EEventKey && aKeyEvent.iCode == EKeyBackspace )
+        {
+        TInt idx = SelectedIndex();
+        if ( idx >= 0 )
+            {
+            TryCloseAppWithQueryL( idx );
+            }
+        return EKeyWasConsumed;
+        }
+    
+    //do not forward the event until item is higlighted
+    if( aKeyEvent.iScanCode == EStdKeyLeftArrow ||
+        aKeyEvent.iScanCode == EStdKeyRightArrow )
+        {
+        if ( !iGrid->IsHighlightVisible() )
+            {
+            if ( aType == EEventKey )
+                {
+                ShowHighlight();
+                iConsumeEvent = ETrue;
+                }
+            return EKeyWasConsumed;
+            }
+        else if(iConsumeEvent)
+            {
+            if (aType == EEventKeyUp)
+                {
+                return EKeyWasConsumed;
+                }
+            iConsumeEvent = EFalse;
+            }
+        }
+    
+    // pass the event to grid
+    // do not pass down and up arrow key events
+    if ( aKeyEvent.iScanCode != EStdKeyUpArrow &&
+         aKeyEvent.iScanCode != EStdKeyDownArrow )
+        {
+        TBool animate(ETrue);
+        TBool redraw(EFalse);
+        TInt prevItem = SelectedIndex();
+        TKeyResponse response = iGrid->OfferKeyEventL( aKeyEvent, aType );
+        if ( prevItem != SelectedIndex() && // item changed
+             ( ( prevItem == 0 &&
+                 SelectedIndex() == GridItemCount() - 1 &&
+                 GridItemCount() > iMaxItemsOnScreen + 1 ) || // loop from first to last item
+               ( prevItem == GridItemCount() - 1 &&
+                 SelectedIndex() == 0 &&
+                 GridItemCount() > iMaxItemsOnScreen + 1) // loop from last to first item
+              ) // loop
+            )
+            {
+            // Loop occured
+            animate = EFalse;
+            }
+        if ( prevItem != SelectedIndex() )
+            {
+            redraw = ETrue;
+            iGrid->ShowHighlight();
+            }
+        UpdateGrid( redraw, animate );
+        return response;
+        }
+    
+    return EKeyWasNotConsumed;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::HandlePointerEventL
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::HandlePointerEventL( const TPointerEvent& aPointerEvent )
+    {
+    iKeyEvent = EFalse;
+    if(aPointerEvent.iType == TPointerEvent::EButton1Down)
+        {
+        iTapEvent = aPointerEvent;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ConfirmCloseL
+// -----------------------------------------------------------------------------
+//
+TBool CHgTeleportFastSwapArea::ConfirmCloseL( TInt aIndex )
+    {
+    HBufC* msg = StringLoader::LoadLC( R_TELEPORT_FSW_CONFIRM_CLOSE,
+        iArray[aIndex]->AppName() );
+    iConfirmCloseQuery = CAknQueryDialog::NewL(
+        CAknQueryDialog::EConfirmationTone );
+    iConfirmCloseQuery->SetPromptL( *msg );
+    CleanupStack::PopAndDestroy( msg );
+    TBool ok = iConfirmCloseQuery->ExecuteLD(
+        R_HG_TELEPORT_FSW_CONFIRM_CLOSE_QUERY );
+    iConfirmCloseQuery = 0;
+    return ok;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::SelectedIndex
+// -----------------------------------------------------------------------------
+//
+TInt CHgTeleportFastSwapArea::SelectedIndex() const
+    {
+    return iGrid->CurrentDataIndex();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::SaveSelectedIndex
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::SaveSelectedIndex()
+    {
+    iSavedSelectedIndex = SelectedIndex();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::RestoreSelectedIndex
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::RestoreSelectedIndex()
+    {
+    iSavedSelectedIndex = KErrNotFound;
+    if ( GridItemCount() )
+        {
+        // highlight second recent item (that has index 2) if possible
+        TInt highlightItem = 0;
+        TInt count = GridItemCount();
+        while( highlightItem < count 
+            && highlightItem < KItemToHighlight )
+            {
+            ++highlightItem;
+            }
+        iSavedSelectedIndex = highlightItem - 1;//count from 0
+        iGrid->SetCurrentItemIndex( iSavedSelectedIndex );
+        TBool forceRedraw(ETrue);
+        UpdateGrid(forceRedraw);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ProcessCommandL
+// Handle fsw popup commands
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::ProcessCommandL( TInt aCommandId )
+    {
+    switch ( aCommandId )
+        {
+        case EFswCmdClose:
+            TryCloseAppL( iAppIndexForPopup );
+            break;
+
+        case EFswCmdCloseAll:
+            TryCloseAllL();
+            break;
+
+        case KErrCancel:
+            // popup dismisses automatically when tapping outside or when switching to other app
+            break;
+        }
+    iTapEvent.iType = TPointerEvent::EButton1Up;
+    iGrid->HandlePointerEventL(iTapEvent);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::HandleCloseEventL
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::HandleCloseEventL(TInt aItemIdx)
+    {
+    if ( !iLongTap )
+        {
+        TryCloseAppWithQueryL( aItemIdx );
+        }
+    // Simulate long tap to prevent item activation
+    iLongTap = ETrue;
+    iTapEvent.iType = TPointerEvent::EButton1Up;
+    iGrid->HandlePointerEventL(iTapEvent);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::HandleDeviceStateChanged
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::HandleDeviceStateChanged( TChangeType aChangeType )
+    {
+    if ( aChangeType == EDeviceType )
+        {
+        CHgTeleportDeviceState::TDeviceType state = iDeviceState.DeviceType();
+        switch ( state )
+            {
+            case CHgTeleportDeviceState::EHybrid:
+                {
+                iGrid->SetGridBehaviour( CHgTeleportFastSwapGrid::EHybrid );
+                }
+                break;
+            case CHgTeleportDeviceState::EFullTouch:
+                {
+                iGrid->SetGridBehaviour( CHgTeleportFastSwapGrid::ETouchOnly );
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::TimerCompletedL
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::TimerCompletedL( CHgTeleportFastSwapTimer* aSource )
+    {
+    if(aSource == iHighlightTimer)
+        {
+        iTapEvent.iType = TPointerEvent::EButton1Up;
+        iGrid->HandlePointerEventL(iTapEvent);
+        }
+    else if(aSource == iRedrawTimer)
+        {
+        DrawNow();
+        }
+    else if( aSource == iUpdateGridTimer )
+        {
+        UpdateGrid(ETrue, ETrue);
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::PreCreatePopupL
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::PreCreatePopupL()
+    {
+    if ( !iPopup )
+        {
+        iPopup = CAknStylusPopUpMenu::NewL( this, Rect().iTl );
+        HBufC* text = StringLoader::LoadLC( R_TELEPORT_FSW_CLOSE );
+        iPopup->AddMenuItemL( *text, EFswCmdClose );
+        CleanupStack::PopAndDestroy( text );
+        text = StringLoader::LoadLC( R_TELEPORT_FSW_CLOSE_ALL );
+        iPopup->AddMenuItemL( *text, EFswCmdCloseAll );
+        CleanupStack::PopAndDestroy( text );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ShowPopupL
+// -----------------------------------------------------------------------------
+//
+TBool CHgTeleportFastSwapArea::ShowPopupL( TInt aIndex, const TPoint& aPoint )
+    {
+    TBool showPopUp(EFalse);
+    TBool showPopupItem;
+    // hide 'close' if app cannot be closed
+    showPopupItem = CanClose( aIndex );
+    iPopup->SetItemDimmed( EFswCmdClose, !showPopupItem );
+    showPopUp = showPopUp || showPopupItem;
+    // hide 'close all' if there are no applications to close.
+    showPopupItem = CanCloseAll( aIndex );
+    iPopup->SetItemDimmed( EFswCmdCloseAll, !showPopupItem );
+    showPopUp = showPopUp || showPopupItem;
+
+    if(showPopUp)
+        {
+        // give feedback
+        LaunchPopupFeedback();
+        // save index for later use & show popup
+        iAppIndexForPopup = aIndex;
+        iPopup->SetPosition( aPoint, CAknStylusPopUpMenu::EPositionTypeLeftBottom );
+        iPopup->ShowMenu();
+        }
+    return showPopUp;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::Count
+// -----------------------------------------------------------------------------
+//
+TInt CHgTeleportFastSwapArea::Count() const
+    {
+    return iArray.Count();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::SetDataChangeObserver
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::SetDataChangeObserver(
+        MHgTeleportDataChangeObserver* aDcObserver )
+    {
+    iDcObserver = aDcObserver;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::NotifyChange
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::NotifyChange()
+    {
+    if ( iDcObserver )
+        {
+        iDcObserver->DataChanged( this, Count() );
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::SwapApplicationOrder
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::SwapApplicationOrder( 
+    RPointerArray<CHgFswEntry>& aArray )
+    {
+    for ( TInt i = 0; i < aArray.Count(); ++i )
+        {
+        if( aArray[i]->AppUid() == KAiUid )
+            {
+            CHgFswEntry* homescreenEntry(0);
+            homescreenEntry = aArray[i];
+            aArray.Remove(i);
+            aArray.Insert(homescreenEntry, KAiPosition);
+            break;
+            }
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::PreferredImageSize
+// -----------------------------------------------------------------------------
+//
+TSize CHgTeleportFastSwapArea::PreferredImageSize()
+    {
+#ifndef TASKSWITCHER_USE_CUSTOM_LAYOUT
+    TAknLayoutRect gridImage;
+    TRAP_IGNORE(
+        RArray<TAknLayoutRect> rects;
+        CleanupClosePushL(rects);
+        rects.ReserveL(KLayoutItemCount);
+        GetFastSwapAreaRects(rects);
+        gridImage = rects[2];
+        CleanupStack::PopAndDestroy(&rects);
+        );
+    return gridImage.Rect().Size();
+#else
+    return TSize( KFswImageSize, KFswImageSize );
+#endif
+    }
+    
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::GridItemCount
+// -----------------------------------------------------------------------------
+//
+TInt CHgTeleportFastSwapArea::GridItemCount()
+    {
+    return iGrid->Model()->ItemTextArray()->MdcaCount();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::HandleListBoxEventL
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aEventType)
+    {
+    if ( aListBox == iGrid )
+        {
+        switch ( aEventType )
+            {
+            case EEventEnterKeyPressed:
+            case EEventItemClicked:
+                {
+                if (!iLongTap)
+                    {
+                    SwitchToApp(SelectedIndex());
+                    }
+                }
+                break;
+            case EEventPenDownOnItem:
+                {
+                iGrid->HideHighlight();
+                iGrid->ShowHighlight();
+                if (!iLongTap )
+                    {
+                    iHighlightTimer->Cancel();
+                    iHighlightTimer->After(KHighlighActivationTime);
+                    }
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::CalculateSizePreserveRatio
+// --------------------------------------------------------------------------
+//
+TSize CHgTeleportFastSwapArea::CalculateSizePreserveRatio(
+        const TSize& aTargetAreaSize,
+        const TSize& aSourceSize )
+    {
+    TSize sz;
+    if ( aSourceSize.iWidth > aSourceSize.iHeight )
+        {
+        sz.iWidth = aTargetAreaSize.iWidth;
+        TReal ratio = aSourceSize.iWidth / (TReal) aSourceSize.iHeight;
+        sz.iHeight = sz.iWidth / ratio;
+        }
+    else
+        {
+        sz.iHeight = aTargetAreaSize.iHeight;
+        TReal ratio = aSourceSize.iHeight / (TReal) aSourceSize.iWidth;
+        sz.iWidth = sz.iHeight / ratio;
+        }
+    return sz;
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::SelectNextItem
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::SelectNextItem()
+    {
+    iKeyEvent = ETrue;
+    TBool forceRedraw(ETrue);
+    TBool animate(ETrue);
+    TInt selectedItem = SelectedIndex();
+    selectedItem++;
+    if ( selectedItem == GridItemCount() )
+        {
+        // Last item is selected, move to first one
+        selectedItem = 0;
+        animate = EFalse;
+        }
+    iGrid->SetCurrentItemIndex(selectedItem);
+    UpdateGrid(forceRedraw, animate);
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ShowHiglight
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::ShowHighlight()
+    {
+    iGrid->ShowHighlight();
+    UpdateGrid(ETrue, EFalse);
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::CenterItem
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::CenterItem(TInt aRedrawDelay)
+    {
+    if( iMaxItemsOnScreen < GridItemCount() )
+        {
+        TInt visibleItem = ViewToVisibleItem( ViewPos() );
+        if(iKeyEvent)
+            {
+            visibleItem = SelectedIndex();
+            }
+        iGrid->SetCurrentDataIndex( visibleItem );
+        }
+
+    iUpdateGridTimer->Cancel();
+    iUpdateGridTimer->After(aRedrawDelay);
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::GridWorldSize
+// --------------------------------------------------------------------------
+//
+TSize CHgTeleportFastSwapArea::GridWorldSize()
+    {
+    return TSize( GridItemCount() * iGridItemWidth, Rect().Height() );
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::UpdateGrid
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::UpdateGrid( TBool aForceRedraw, TBool aAnimate )
+    {
+    TPoint targetPoint = ItemViewPosition( SelectedIndex() );
+    if ( aForceRedraw || targetPoint.iX != ViewPos().iX )
+        {
+        if ( aAnimate )
+            {
+            iEvtHandler.Animate( targetPoint );
+            }
+        else
+            {
+            MoveOffset(targetPoint);
+            iEvtHandler.StopAnimation();
+            }
+        if ( aForceRedraw )
+            {
+            iGrid->DrawNow();
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::HandleAppKey
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::HandleAppKey(TInt aType)
+    {
+    if( aType == KAppKeyTypeShort )
+        {
+        if(iGrid->IsHighlightVisible())
+            {
+            SelectNextItem();
+            }
+        else
+            {
+            ShowHighlight();
+            }
+        }
+    else if( aType == KAppKeyTypeLong )
+        {
+        SwitchToApp( SelectedIndex() );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::MoveOffset
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::MoveOffset(const TPoint& aPoint)
+    {
+    HGLOG_CONTEXT( CHgTeleportFastSwapArea::MoveOffset, HGLOG_LOCAL );
+    HGLOG2_IN("Old position x: %d, y:%d", ViewPos().iX, ViewPos().iY);
+    HGLOG2_IN("New position x: %d, y:%d", aPoint.iX, aPoint.iY);
+    HGLOG_OUT();
+    
+    TInt currentXPos = aPoint.iX;
+    currentXPos -= Rect().Width() / 2;
+    TRect gridViewRect = Rect();
+    gridViewRect.iTl.iX = -currentXPos;
+    // Take edge offset into account
+    gridViewRect.iTl.iX += Rect().iTl.iX;
+    if(GridItemCount() <= iMaxItemsOnScreen)
+        {
+        // Center view
+        gridViewRect.iTl.iX += ( Rect().Width() - GridItemCount() * iGridItemWidth ) / 2;
+        }
+    iGrid->SetRect( gridViewRect );
+    DrawNow();
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::Tap
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::TapL(const TPoint& aPoint)
+    {
+    iLongTap = EFalse;
+    if(iGrid->Rect().Contains(aPoint))
+        {
+        //provide tap pointer event to grid
+        iGrid->HandlePointerEventL(iTapEvent);
+        }
+    else
+        {
+        //move task switcher to background
+        iEikonEnv->EikAppUi()->HandleCommandL(EAknSoftkeyExit);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::LongTap
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::LongTapL(const TPoint& aPoint)
+    {
+    iLongTap = ETrue;
+    TInt index(KErrNotFound);
+    if( iGrid->GridView()->XYPosToItemIndex(aPoint,index) )
+        {
+        if ( AknLayoutUtils::LayoutMirrored() )
+            {
+            // Calculate logical item index
+            index = GridItemCount() - 1 - index;
+            }
+        SaveSelectedIndex();
+        iGrid->HandlePointerEventL(iTapEvent);
+        if ( !ShowPopupL(index, aPoint) )
+            {
+            TapL(aPoint);
+            }
+        }
+    else
+        {
+        TapL(aPoint);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::Drag
+// --------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::Drag(
+    const MAknTouchGestureFwDragEvent& /*aEvent*/)
+    {
+    iGrid->HideHighlight();
+    CenterItem( KUpdateGridTime );
+    DrawNow();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ViewSize
+// -----------------------------------------------------------------------------
+//
+TSize CHgTeleportFastSwapArea::ViewSize()
+    {
+    return TSize(Rect().Width(), Rect().Height());  
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::Stop
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::Stop()
+    {    
+    CenterItem( KUpdateGridTime );
+    DrawNow();
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ViewSize
+// -----------------------------------------------------------------------------
+//
+TPoint CHgTeleportFastSwapArea::ViewPos() const
+    {
+    TPoint retVal;
+    retVal.iY = iGrid->Rect().iTl.iY + Rect().Height() / 2;
+    retVal.iX = - (iGrid->Rect().iTl.iX - Rect().iTl.iX) + Rect().Width() / 2 ;
+    TInt gridItemCount = iGrid->Model()->ItemTextArray()->MdcaCount();
+    if( gridItemCount <= iMaxItemsOnScreen)
+        {
+        // View centered
+        retVal.iX += ( Rect().Width() - gridItemCount * iGridItemWidth ) / 2;
+        }
+    return retVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ItemPosition
+// -----------------------------------------------------------------------------
+//
+TPoint CHgTeleportFastSwapArea::ItemViewPosition( TInt aItemIdx )
+    {
+    TPoint retVal = Rect().iTl;
+    if ( aItemIdx == 0 )
+        {
+        // First item
+        if( AknLayoutUtils::LayoutMirrored() )
+            {
+            if ( GridItemCount() > iMaxItemsOnScreen )
+                {
+                retVal.iX = GridWorldSize().iWidth - Rect().Width();
+                }
+            else
+                {
+                retVal.iX = 0;
+                }
+            }
+        else // normal layout
+            {
+            retVal.iX = 0;
+            }
+        }
+    else if ( aItemIdx == GridItemCount() - 1 )
+        {
+        // Last item selected
+        if( AknLayoutUtils::LayoutMirrored() )
+            {
+            retVal.iX = 0;
+            }
+        else // normal layout
+            {
+            if ( GridItemCount() > iMaxItemsOnScreen )
+                {
+                retVal.iX = GridWorldSize().iWidth - Rect().Width();
+                }
+            else
+                {
+                retVal.iX = 0;
+                }
+            }
+        }
+    else
+        {
+        // Middle item
+        TInt screenMiddleItemOffset = ( Rect().Width() - iGridItemWidth ) / 2;
+        if( AknLayoutUtils::LayoutMirrored() )
+            {
+            retVal.iX = iGridItemWidth * ( GridItemCount() - 1 - aItemIdx ) - screenMiddleItemOffset;
+            }
+        else // normal layout
+            {
+            retVal.iX = iGridItemWidth * aItemIdx - screenMiddleItemOffset;
+            }
+        if ( retVal.iX < 0 )
+            {
+            retVal.iX = 0;
+            }
+        else if ( retVal.iX + Rect().Width() > GridWorldSize().iWidth )
+            {
+            retVal.iX = GridWorldSize().iWidth - Rect().Width();
+            }
+        }
+    
+    // Return middle of the view rectangle
+    retVal.iX += Rect().Width() / 2;
+    
+    return retVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::ViewToVisibleItem
+// -----------------------------------------------------------------------------
+//
+TInt CHgTeleportFastSwapArea::ViewToVisibleItem( const TPoint aViewPos )
+    {
+    TInt retVal(0);
+    TPoint absViewPos = aViewPos;
+    absViewPos.iX -= Rect().Width() / 2;
+    if ( absViewPos.iX < 0 )
+        {
+        if ( AknLayoutUtils::LayoutMirrored() )
+            {
+            // View crossed left border of grid world rect, last item selected
+            retVal = GridItemCount() - 1;
+            }
+        else // normal layout
+            {
+            // View crossed left border of grid world rect, first item selected
+            retVal = 0;
+            }
+        }
+    else if ( absViewPos.iX + Rect().Width() > GridWorldSize().iWidth )
+        {
+        if ( AknLayoutUtils::LayoutMirrored() )
+            {
+            // View crossed right border of grid world rect, first item selected
+            retVal = 0;
+            }
+        else // normal layout
+            {
+            // View crossed right border of grid world rect, last item selected
+            retVal = GridItemCount() - 1;
+            }
+        }
+    else
+        {
+        TInt offsetCheck = GridWorldSize().iWidth;
+        // View inside of grid world rect
+        for ( TInt i = 0 ; i < GridItemCount(); i++ )
+            {
+            TInt offset = aViewPos.iX - ItemViewPosition( i ).iX;
+            if ( Abs( offset ) <= offsetCheck )
+                {
+                offsetCheck = Abs( offset );
+                retVal = i;
+                }
+            else
+                {
+                break;
+                }
+            }
+        }
+    return retVal;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHgTeleportFastSwapArea::LaunchPopupFeedback
+// -----------------------------------------------------------------------------
+//
+void CHgTeleportFastSwapArea::LaunchPopupFeedback()
+    {
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        MTouchFeedback* feedback = MTouchFeedback::Instance();
+        if ( feedback )
+            {
+            TTouchLogicalFeedback fbLogicalType = ETouchFeedbackPopUp;
+            if ( CAknTransitionUtils::TransitionsEnabled(
+                 AknTransEffect::EComponentTransitionsOff ) )
+                {
+                fbLogicalType = ETouchFeedbackIncreasingPopUp;
+                }
+            feedback->InstantFeedback( this,
+                                       fbLogicalType,
+                                       ETouchFeedbackVibra,
+                                       TPointerEvent() );
+            }
+        }
+    }
+
+// End of file