--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/taskswitcher/taskswitcherui/taskswitcherapp/src/tsfastswaparea.cpp Tue Jan 26 11:48:23 2010 +0200
@@ -0,0 +1,1605 @@
+/*
+* Copyright (c) 2008 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: Taskswitcher Fast Swap area UI
+ *
+*/
+
+
+#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 <tstaskswitcher.rsg>
+#include <aknlayoutscalable_apps.cdl.h>
+#include <layoutmetadata.cdl.h>
+#include <aknlists.h>
+#include <touchfeedback.h>
+#include <akntransitionutils.h>
+#include <akntranseffect.h>
+
+#include "tsfastswaparea.h"
+#include "tsapplogging.h"
+#include "tsfswclient.h"
+#include "tsappui.h"
+#include "tsdatachangeobserver.h"
+#include "tseventcontroler.h"
+
+/** command ids for the fsw popup */
+enum TPopupCommands
+ {
+ EFswCmdClose = 10000,
+ EFswCmdCloseAll
+ };
+
+/** Number of closable applications, to show "close all" option. */
+const TInt KTsMaxClosableApps = 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 = 4;
+
+const TInt KRedrawTime = 250000; // 0.25 sec
+const TInt KHighlighActivationTime = 100000; // 100 ms
+const TInt KUpdateGridTime = 1000000; // 1 s
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::NewL
+// -----------------------------------------------------------------------------
+//
+CTsFastSwapArea* CTsFastSwapArea::NewL( const TRect& aRect,
+ CCoeControl& aParent, CTsDeviceState& aDeviceState,
+ CTsEventControler& aEventHandler )
+ {
+ CTsFastSwapArea* self = CTsFastSwapArea::NewLC(aRect,
+ aParent, aDeviceState, aEventHandler);
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::NewLC
+// -----------------------------------------------------------------------------
+//
+CTsFastSwapArea* CTsFastSwapArea::NewLC( const TRect& aRect,
+ CCoeControl& aParent, CTsDeviceState& aDeviceState,
+ CTsEventControler& aEventHandler)
+ {
+ CTsFastSwapArea* self = new (ELeave) CTsFastSwapArea(
+ aParent, aDeviceState, aEventHandler);
+ CleanupStack::PushL( self );
+ self->ConstructL( aRect );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::CTsFastSwapArea
+// -----------------------------------------------------------------------------
+//
+CTsFastSwapArea::CTsFastSwapArea(CCoeControl& aParent,
+ CTsDeviceState& aDeviceState,
+ CTsEventControler& aEventHandler) :
+ iParent(aParent), iDeviceState(aDeviceState), iEvtHandler(aEventHandler),
+ iPreviousNoOfItems(0)
+ {
+ // no implementation required
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::~CTsFastSwapArea
+// -----------------------------------------------------------------------------
+//
+CTsFastSwapArea::~CTsFastSwapArea()
+ {
+ iArray.ResetAndDestroy();
+ delete iGrid;
+ delete iFSClient;
+ delete iPopup;
+ delete iConfirmCloseQuery;
+ delete iHighlightTimer;
+ delete iRedrawTimer;
+ delete iUpdateGridTimer;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::ConstructL( const TRect& aRect )
+ {
+ SetContainerWindowL( iParent );
+
+ SetRect( aRect );
+
+ // setup ganes grid
+ ReCreateGridL();
+
+ // create stylus popup instance
+ PreCreatePopupL();
+
+ // connect to fsw server
+ iFSClient = CTsFswClient::NewL();
+
+ iEvtHandler.ReInitPhysicsL(GridWorldSize(), ViewSize(), ETrue);
+
+ // add self to device state observer
+ iDeviceState.AddObserverL( *this, EDeviceType );
+
+ iHighlightTimer = new (ELeave) CTsFastSwapTimer( *this );
+ iHighlightTimer->ConstructL();
+
+ iRedrawTimer = new (ELeave) CTsFastSwapTimer( *this );
+ iRedrawTimer->ConstructL();
+
+ iUpdateGridTimer = new (ELeave) CTsFastSwapTimer( *this );
+ iUpdateGridTimer->ConstructL();
+
+ ActivateL();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ReCreateGridL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::ReCreateGridL()
+ {
+ MCoeControlObserver* obs = NULL;
+ TBool wasHighlight = iDeviceState.DeviceType() ==
+ CTsDeviceState::EHybrid ? ETrue : EFalse;
+ if ( iGrid )
+ {
+ obs = iGrid->Observer();
+ iDeviceState.RemoveObserver(*iGrid);
+ wasHighlight = iGrid->IsHighlightVisible();
+ delete iGrid;
+ iGrid = NULL;
+ }
+
+ iGrid = new( ELeave ) CTsFastSwapGrid;
+ iGrid->ConstructL( this );
+ iDeviceState.AddObserverL(*iGrid, MTsDeviceStateObserver::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];
+ TAknLayoutRect gridNextItem = rects[3];
+ 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 );
+
+ AknListBoxLayouts::SetupFormGfxCell( *iGrid, iGrid->ItemDrawer(), 0,
+ AknLayoutScalable_Apps::cell_tport_appsw_pane_g1( variety ).LayoutLine(),
+ empty, empty );
+
+ // 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
+ 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*/);
+
+ // Setup grid observers
+ if ( obs )
+ {
+ iGrid->SetObserver( obs );
+ }
+ iGrid->SetListBoxObserver(this);
+ iGrid->SetFastSwapGridObserver(this);
+ iGrid->SetContainerWindowL(*this);
+
+ if ( AknLayoutUtils::LayoutMirrored() )
+ {
+ iGridItemGap = gridItem.Rect().iTl.iX - gridNextItem.Rect().iBr.iX;
+ }
+ else
+ {
+ iGridItemGap = gridNextItem.Rect().iTl.iX - gridItem.Rect().iBr.iX;
+ }
+ iMaxItemsOnScreen = Rect().Width() / gridItem.Rect().Width();
+ if ( iMaxItemsOnScreen > 1 )
+ {
+ TInt widthWithGaps =
+ (iMaxItemsOnScreen - 1) * iGridItemGap + iMaxItemsOnScreen * gridItem.Rect().Width();
+ if ( widthWithGaps > Rect().Width() )
+ {
+ iMaxItemsOnScreen--;
+ }
+ }
+ iGridItemWidth = gridItem.Rect().Width();
+
+ 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();
+ }
+
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::GetFastSwapAreaRects
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::GetFastSwapAreaRects( RArray<TAknLayoutRect>& aRects )
+ {
+ TAknLayoutRect gridAppPane;
+ TAknLayoutRect gridItem;
+ TAknLayoutRect gridImage;
+ TAknLayoutRect gridNextItem;
+
+ 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);
+ gridNextItem.LayoutRect( gridAppPane.Rect(),
+ AknLayoutScalable_Apps::cell_tport_appsw_pane_cp03( variety ) );
+ aRects.Append(gridNextItem);
+ }
+
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::Setup
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::Setup( MCoeControlObserver& aControlObserver )
+ {
+ iGrid->SetObserver( &aControlObserver );
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::SizeChanged
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SizeChanged()
+ {
+ TSLOG_CONTEXT( CTsFastSwapArea::SizeChanged, TSLOG_LOCAL );
+ TSLOG_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 )
+ {
+ TSLOG1( TSLOG_INFO, "ReCreateGridL leaves with %d", err );
+ }
+ HandleFswContentChanged();
+ iGrid->SetCurrentDataIndex(selIdx);
+ UpdateGrid(ETrue, EFalse);
+ DrawDeferred();
+ }
+ TSLOG_OUT();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::Draw
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::Draw( const TRect& /*aRect*/ ) const
+ {
+ CWindowGc& gc = SystemGc();
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
+ AknsDrawUtils::Background( skin,
+ cc,
+ this,
+ gc,
+ Rect() );
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::SwitchToApp
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::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 ts if the activated app is closed.
+ // Therefore ts must be moved to background.
+ CTsAppUi* appui =
+ static_cast<CTsAppUi*>( iEikonEnv->AppUi() );
+ appui->MoveAppToBackground( AknTransEffect::EApplicationStartRect );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::TryCloseAppL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::TryCloseAppL( TInt aIndex,
+ TBool aSuppressRendering )
+ {
+ TSLOG_CONTEXT( TryCloseAppL, TSLOG_LOCAL );
+ TSLOG2_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();
+ }
+
+ TSLOG_OUT();
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::TryCloseAppWithQueryL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::TryCloseAppWithQueryL( TInt aIndex )
+ {
+ if ( aIndex >= 0 && aIndex < iArray.Count()
+ && CanClose( aIndex )
+ && ConfirmCloseL( aIndex ) )
+ {
+ TryCloseAppL( aIndex );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::TryCloseAllL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::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();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CanClose
+// --------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::CanClose( TInt aIndex ) const
+ {
+ CTsFswEntry* e = iArray[aIndex];
+ return !e->AlwaysShown() && !e->SystemApp();
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CanCloseOthers
+// --------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::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 < KTsMaxClosableApps; )
+ {
+ if ( CanClose( i ) )
+ {
+ count++;
+ }
+ }
+ return ( count >= KTsMaxClosableApps ) ||
+ ( count && !CanClose( aSelectedItem ) );
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::HandleFswContentChanged
+// From MTsFswObserver
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleFswContentChanged()
+ {
+ TSLOG_CONTEXT( HandleFswContentChanged, TSLOG_LOCAL );
+ TSLOG_IN();
+
+ TRAPD( err, HandleFswContentChangedL() );
+ if ( err != KErrNone )
+ {
+ TSLOG1( TSLOG_INFO, "leave occured: %d", err );
+ }
+
+ TSLOG_OUT();
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::HandleFswContentChangedL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleFswContentChangedL()
+ {
+ TSLOG_CONTEXT( HandleFswContentChangedL, TSLOG_LOCAL );
+ TSLOG_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 )
+ {
+ TSLOG1_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 )
+ {
+ CTsFswEntry* e = iArray[i];
+ const TDesC& name( e->AppName() );
+ TSLOG4( TSLOG_INFO, "[%d]: %d %d %S", i, e->WgId(), e->AppUid(), &name );
+ }
+#endif
+
+ // draw
+ RenderContentL();
+
+ // notify observer, if present
+ NotifyChange();
+
+ TSLOG_OUT();
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::RenderContentL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::RenderContentL()
+ {
+ TSLOG_CONTEXT( RenderContentL, TSLOG_LOCAL );
+ TSLOG_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() )
+ {
+ iGrid->SetLayoutL( EFalse, EFalse, ETrue, iArray.Count(), 1, gridItem.Rect().Size(), iGridItemGap );
+ }
+ else
+ {
+ iGrid->SetLayoutL( EFalse, ETrue, ETrue, iArray.Count(), 1, gridItem.Rect().Size(), iGridItemGap );
+ }
+
+ 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();
+ TSLOG2( TSLOG_INFO, "'%S' screenshot handle %d", &appName, h );
+ TInt maskh = 0;
+ CFbsBitmap* mask = 0;
+ if ( !h )
+ {
+ h = iArray[i]->AppIconBitmapHandle();
+ maskh = iArray[i]->AppIconMaskHandle();
+ TSLOG1( TSLOG_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 );
+
+ TSLOG_OUT();
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CopyBitmapL
+// Copy and scale.
+// --------------------------------------------------------------------------
+//
+CFbsBitmap* CTsFastSwapArea::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;
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CountComponentControls
+// --------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::CountComponentControls() const
+ {
+ return 1;
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::ComponentControl
+// --------------------------------------------------------------------------
+//
+CCoeControl* CTsFastSwapArea::ComponentControl( TInt aIndex ) const
+ {
+ if ( aIndex == 0 )
+ {
+ return iGrid;
+ }
+ return NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleSwitchToBackgroundEvent
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::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;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleSwitchToForegroundEvent
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleSwitchToForegroundEvent()
+ {
+ TSLOG_CONTEXT( CTsFastSwapArea::HandleSwitchToForegroundEvent, TSLOG_LOCAL );
+ TSLOG_IN();
+
+ // get the current task list
+ HandleFswContentChanged();
+ // and then start listening for changes
+ iFSClient->Subscribe( *this );
+
+ if ( iDeviceState.DeviceType() == CTsDeviceState::EFullTouch )
+ {
+ iGrid->HideHighlight();
+ }
+ else
+ {
+ iGrid->ShowHighlight();
+ }
+
+ RestoreSelectedIndex();
+ UpdateGrid(ETrue, EFalse);
+
+ iRedrawTimer->Cancel();
+ iRedrawTimer->After(KRedrawTime);
+
+ // give feedback
+ LaunchPopupFeedback();
+
+ TSLOG_OUT();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::FocusChanged
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::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();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::OfferKeyEventL
+// -----------------------------------------------------------------------------
+//
+TKeyResponse CTsFastSwapArea::OfferKeyEventL(
+ const TKeyEvent& aKeyEvent,
+ TEventCode aType )
+ {
+ iKeyEvent = ETrue;
+ iGrid->SetTactileFeedbackSupport(EFalse);
+ // 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;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandlePointerEventL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandlePointerEventL( const TPointerEvent& aPointerEvent )
+ {
+ iKeyEvent = EFalse;
+ iGrid->SetTactileFeedbackSupport(ETrue);
+ if(aPointerEvent.iType == TPointerEvent::EButton1Down)
+ {
+ iTapEvent = aPointerEvent;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ConfirmCloseL
+// -----------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::ConfirmCloseL( TInt aIndex )
+ {
+ HBufC* msg = StringLoader::LoadLC( R_TS_FSW_CONFIRM_CLOSE,
+ iArray[aIndex]->AppName() );
+ iConfirmCloseQuery = CAknQueryDialog::NewL(
+ CAknQueryDialog::EConfirmationTone );
+ iConfirmCloseQuery->SetPromptL( *msg );
+ CleanupStack::PopAndDestroy( msg );
+ TBool ok = iConfirmCloseQuery->ExecuteLD(
+ R_TS_FSW_CONFIRM_CLOSE_QUERY );
+ iConfirmCloseQuery = 0;
+ return ok;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::SelectedIndex
+// -----------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::SelectedIndex() const
+ {
+ return iGrid->CurrentDataIndex();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::SaveSelectedIndex
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SaveSelectedIndex()
+ {
+ iSavedSelectedIndex = SelectedIndex();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::RestoreSelectedIndex
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::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->SetCurrentDataIndex( iSavedSelectedIndex );
+ TBool forceRedraw(ETrue);
+ UpdateGrid(forceRedraw);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ProcessCommandL
+// Handle fsw popup commands
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::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;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleCloseEventL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleCloseEventL(TInt aItemIdx)
+ {
+ TryCloseAppWithQueryL( aItemIdx );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleDeviceStateChanged
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleDeviceStateChanged( TChangeType aChangeType )
+ {
+ if ( aChangeType == EDeviceType )
+ {
+ CTsDeviceState::TDeviceType state = iDeviceState.DeviceType();
+ switch ( state )
+ {
+ case CTsDeviceState::EHybrid:
+ {
+ iGrid->SetGridBehaviour( CTsFastSwapGrid::EHybrid );
+ }
+ break;
+ case CTsDeviceState::EFullTouch:
+ {
+ iGrid->SetGridBehaviour( CTsFastSwapGrid::ETouchOnly );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::TimerCompletedL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::TimerCompletedL( CTsFastSwapTimer* aSource )
+ {
+ if(aSource == iHighlightTimer)
+ {
+ iTapEvent.iType = TPointerEvent::EButton1Up;
+ iGrid->HandlePointerEventL(iTapEvent);
+ }
+ else if(aSource == iRedrawTimer)
+ {
+ DrawNow();
+ }
+ else if( aSource == iUpdateGridTimer )
+ {
+ UpdateGrid(ETrue, ETrue);
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::PreCreatePopupL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::PreCreatePopupL()
+ {
+ if ( !iPopup )
+ {
+ iPopup = CAknStylusPopUpMenu::NewL( this, Rect().iTl );
+ HBufC* text = StringLoader::LoadLC( R_TS_FSW_CLOSE );
+ iPopup->AddMenuItemL( *text, EFswCmdClose );
+ CleanupStack::PopAndDestroy( text );
+ text = StringLoader::LoadLC( R_TS_FSW_CLOSE_ALL );
+ iPopup->AddMenuItemL( *text, EFswCmdCloseAll );
+ CleanupStack::PopAndDestroy( text );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ShowPopupL
+// -----------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::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;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::Count
+// -----------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::Count() const
+ {
+ return iArray.Count();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::SetDataChangeObserver
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SetDataChangeObserver(
+ MTsDataChangeObserver* aDcObserver )
+ {
+ iDcObserver = aDcObserver;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::NotifyChange
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::NotifyChange()
+ {
+ if ( iDcObserver )
+ {
+ iDcObserver->DataChanged( this, Count() );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::SwapApplicationOrder
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SwapApplicationOrder(
+ RPointerArray<CTsFswEntry>& aArray )
+ {
+ for ( TInt i = 0; i < aArray.Count(); ++i )
+ {
+ if( aArray[i]->AppUid() == KAiUid )
+ {
+ CTsFswEntry* homescreenEntry(0);
+ homescreenEntry = aArray[i];
+ aArray.Remove(i);
+ aArray.Insert(homescreenEntry, KAiPosition);
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::PreferredImageSize
+// -----------------------------------------------------------------------------
+//
+TSize CTsFastSwapArea::PreferredImageSize()
+ {
+ TAknLayoutRect gridImage;
+ TRAP_IGNORE(
+ RArray<TAknLayoutRect> rects;
+ CleanupClosePushL(rects);
+ rects.ReserveL(KLayoutItemCount);
+ GetFastSwapAreaRects(rects);
+ gridImage = rects[2];
+ CleanupStack::PopAndDestroy(&rects);
+ );
+ return gridImage.Rect().Size();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::GridItemCount
+// -----------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::GridItemCount()
+ {
+ return iGrid->Model()->ItemTextArray()->MdcaCount();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleListBoxEventL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aEventType)
+ {
+ if ( aListBox == iGrid )
+ {
+ switch ( aEventType )
+ {
+ case EEventEnterKeyPressed:
+ case EEventItemClicked:
+ {
+ SwitchToApp(SelectedIndex());
+ }
+ break;
+ case EEventPenDownOnItem:
+ {
+ iGrid->ShowHighlight();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CalculateSizePreserveRatio
+// --------------------------------------------------------------------------
+//
+TSize CTsFastSwapArea::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;
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::SelectNextItem
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SelectNextItem()
+ {
+ iKeyEvent = ETrue;
+ iGrid->SetTactileFeedbackSupport(EFalse);
+ 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->SetCurrentDataIndex(selectedItem);
+ UpdateGrid(forceRedraw, animate);
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::ShowHiglight
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::ShowHighlight()
+ {
+ iGrid->ShowHighlight();
+ UpdateGrid(ETrue, EFalse);
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CenterItem
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::CenterItem(TInt aRedrawDelay)
+ {
+ if( iMaxItemsOnScreen < GridItemCount() )
+ {
+ TInt visibleItem = ViewToVisibleItem( ViewPos() );
+ if(iKeyEvent)
+ {
+ visibleItem = SelectedIndex();
+ }
+ if(visibleItem != SelectedIndex())
+ {
+ iGrid->SetCurrentDataIndex( visibleItem );
+ DrawNow();
+ }
+ }
+
+ iUpdateGridTimer->Cancel();
+ iUpdateGridTimer->After(aRedrawDelay);
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::GridWorldSize
+// --------------------------------------------------------------------------
+//
+TSize CTsFastSwapArea::GridWorldSize()
+ {
+ return TSize( GridItemCount() * iGridItemWidth + (GridItemCount() - 1) * iGridItemGap, Rect().Height() );
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::UpdateGrid
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::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();
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::HandleAppKey
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleAppKey(TInt aType)
+ {
+ if( aType == KAppKeyTypeShort )
+ {
+ if(iGrid->IsHighlightVisible())
+ {
+ SelectNextItem();
+ }
+ else
+ {
+ ShowHighlight();
+ }
+ }
+ else if( aType == KAppKeyTypeLong )
+ {
+ SwitchToApp( SelectedIndex() );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::MoveOffset
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::MoveOffset(const TPoint& aPoint)
+ {
+ TSLOG_CONTEXT( CTsFastSwapArea::MoveOffset, TSLOG_LOCAL );
+ TSLOG2_IN("Old position x: %d, y:%d", ViewPos().iX, ViewPos().iY);
+ TSLOG2_IN("New position x: %d, y:%d", aPoint.iX, aPoint.iY);
+ TSLOG_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();
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::Tap
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::TapL(const TPoint& aPoint)
+ {
+ if(iGrid->Rect().Contains(aPoint))
+ {
+ //provide tap pointer event to grid
+ iGrid->HandlePointerEventL(iTapEvent);
+ iHighlightTimer->Cancel();
+ iHighlightTimer->After(KHighlighActivationTime);
+ }
+ else
+ {
+ //move task switcher to background
+ iEikonEnv->EikAppUi()->HandleCommandL(EAknSoftkeyExit);
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::LongTap
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::LongTapL(const TPoint& aPoint)
+ {
+ TInt index(KErrNotFound);
+ if( iGrid->GridView()->XYPosToItemIndex(aPoint,index) )
+ {
+ iGrid->SetCurrentItemIndex(index);
+ SaveSelectedIndex();
+ if ( !ShowPopupL(iSavedSelectedIndex, aPoint) )
+ {
+ TapL(aPoint);
+ }
+ else
+ {
+ iGrid->ShowHighlight();
+ DrawNow();
+ }
+ }
+ else
+ {
+ TapL(aPoint);
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::Drag
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::Drag(
+ const MAknTouchGestureFwDragEvent& /*aEvent*/)
+ {
+ iGrid->SetTactileFeedbackSupport(ETrue);
+ iGrid->HideHighlight();
+ CenterItem( KUpdateGridTime );
+ DrawNow();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ViewSize
+// -----------------------------------------------------------------------------
+//
+TSize CTsFastSwapArea::ViewSize()
+ {
+ return TSize(Rect().Width(), Rect().Height());
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::Stop
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::Stop()
+ {
+ CenterItem( KUpdateGridTime );
+ DrawNow();
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ViewSize
+// -----------------------------------------------------------------------------
+//
+TPoint CTsFastSwapArea::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;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ItemPosition
+// -----------------------------------------------------------------------------
+//
+TPoint CTsFastSwapArea::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;
+ retVal.iX += ( GridItemCount() - 1 - aItemIdx ) * iGridItemGap;
+ }
+ else // normal layout
+ {
+ retVal.iX = iGridItemWidth * aItemIdx - screenMiddleItemOffset;
+ retVal.iX += iGridItemGap * aItemIdx;
+ }
+ 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;
+ }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ViewToVisibleItem
+// -----------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::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;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::LaunchPopupFeedback
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::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