taskswitcher/taskswitcherui/taskswitcherapp/src/tsfastswaparea.cpp
branchv5backport
changeset 14 1abc632eb502
parent 13 6205fd287e8a
child 20 636d517f67e6
equal deleted inserted replaced
13:6205fd287e8a 14:1abc632eb502
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Taskswitcher Fast Swap area UI
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 #include <gulicon.h>
       
    20 #include <eikenv.h>
       
    21 #include <AknUtils.h>
       
    22 #include <AknIconUtils.h>
       
    23 #include <AknIconArray.h>
       
    24 #include <aknstyluspopupmenu.h>
       
    25 #include <AknQueryDialog.h>
       
    26 #include <StringLoader.h>
       
    27 #include <tstaskswitcher.rsg>
       
    28 #include <aknlayoutscalable_apps.cdl.h>
       
    29 #include <layoutmetadata.cdl.h>
       
    30 #include <aknlists.h>
       
    31 #include <touchfeedback.h>
       
    32 #include <akntransitionutils.h>
       
    33 #include <akntranseffect.h>
       
    34 
       
    35 #include "tsfastswaparea.h"
       
    36 #include "tsapplogging.h"
       
    37 #include "tsfswclient.h"
       
    38 #include "tsappui.h"
       
    39 #include "tsdatachangeobserver.h"
       
    40 #include "tseventcontroler.h"
       
    41 
       
    42 /** command ids for the fsw popup */
       
    43 enum TPopupCommands
       
    44     {
       
    45     EFswCmdClose = 10000,
       
    46     EFswCmdCloseAll
       
    47     };
       
    48 
       
    49 /** Number of closable applications, to show "close all" option. */
       
    50 const TInt KTsMaxClosableApps = 2;
       
    51 
       
    52 /** Interval until which no change in the fsw content is rendered
       
    53     after starting the closing of an application. */
       
    54 const TInt KRefreshDelayAfterClose = 2; // seconds
       
    55 
       
    56 /** Uid of Active Idle application. 
       
    57     Used when movind Ai to specified position.*/
       
    58 const TUid KAiUid = TUid::Uid( 0x102750F0 );
       
    59     
       
    60 /** Position of Ai in fsw grid.*/
       
    61 const TInt KAiPosition = 0;
       
    62 
       
    63 /** Default grid item to highlight.*/
       
    64 const TInt KItemToHighlight = 3;
       
    65 
       
    66 const TInt KAppKeyTypeShort = 1;
       
    67 const TInt KAppKeyTypeLong = 2;
       
    68 
       
    69 const TInt KLayoutItemCount = 4;
       
    70 
       
    71 const TInt KRedrawTime = 250000; // 0.25 sec
       
    72 const TInt KHighlighActivationTime = 100000; // 100 ms
       
    73 const TInt KUpdateGridTime = 1000000; // 1 s
       
    74 
       
    75 // -----------------------------------------------------------------------------
       
    76 // CTsFastSwapArea::NewL
       
    77 // -----------------------------------------------------------------------------
       
    78 //
       
    79 CTsFastSwapArea* CTsFastSwapArea::NewL( const TRect& aRect,
       
    80     CCoeControl& aParent, CTsDeviceState& aDeviceState, 
       
    81     CTsEventControler& aEventHandler )
       
    82     {
       
    83     CTsFastSwapArea* self = CTsFastSwapArea::NewLC(aRect,
       
    84             aParent, aDeviceState, aEventHandler);
       
    85     CleanupStack::Pop( self );
       
    86     return self;
       
    87     }
       
    88 
       
    89 // -----------------------------------------------------------------------------
       
    90 // CTsFastSwapArea::NewLC
       
    91 // -----------------------------------------------------------------------------
       
    92 //
       
    93 CTsFastSwapArea* CTsFastSwapArea::NewLC( const TRect& aRect,
       
    94     CCoeControl& aParent, CTsDeviceState& aDeviceState,
       
    95     CTsEventControler& aEventHandler)
       
    96     {
       
    97     CTsFastSwapArea* self = new (ELeave) CTsFastSwapArea(
       
    98             aParent, aDeviceState, aEventHandler);
       
    99     CleanupStack::PushL( self );
       
   100     self->ConstructL( aRect );
       
   101     return self;
       
   102     }
       
   103 
       
   104 // -----------------------------------------------------------------------------
       
   105 // CTsFastSwapArea::CTsFastSwapArea
       
   106 // -----------------------------------------------------------------------------
       
   107 //
       
   108 CTsFastSwapArea::CTsFastSwapArea(CCoeControl& aParent,
       
   109     CTsDeviceState& aDeviceState,
       
   110     CTsEventControler& aEventHandler) :
       
   111     iParent(aParent), iDeviceState(aDeviceState), iEvtHandler(aEventHandler),
       
   112     iPreviousNoOfItems(0)
       
   113     {
       
   114     // no implementation required
       
   115     }
       
   116 
       
   117 // -----------------------------------------------------------------------------
       
   118 // CTsFastSwapArea::~CTsFastSwapArea
       
   119 // -----------------------------------------------------------------------------
       
   120 //
       
   121 CTsFastSwapArea::~CTsFastSwapArea()
       
   122     {
       
   123     iArray.ResetAndDestroy();
       
   124     delete iGrid;
       
   125     delete iFSClient;
       
   126     delete iPopup;
       
   127     delete iHighlightTimer;
       
   128     delete iRedrawTimer;
       
   129     delete iUpdateGridTimer;
       
   130     }
       
   131 
       
   132 // -----------------------------------------------------------------------------
       
   133 // CTsFastSwapArea::ConstructL
       
   134 // -----------------------------------------------------------------------------
       
   135 //
       
   136 void CTsFastSwapArea::ConstructL( const TRect& aRect )
       
   137     {
       
   138     SetContainerWindowL( iParent );
       
   139 
       
   140     SetRect( aRect );
       
   141 
       
   142     // setup ganes grid
       
   143     ReCreateGridL();
       
   144 
       
   145     // create stylus popup instance
       
   146     PreCreatePopupL();
       
   147 
       
   148     // connect to fsw server
       
   149     iFSClient = CTsFswClient::NewL();
       
   150     
       
   151     iEvtHandler.ReInitPhysicsL(GridWorldSize(), ViewSize(), ETrue);
       
   152     
       
   153     // add self to device state observer
       
   154     iDeviceState.AddObserverL( *this, EDeviceType );
       
   155     
       
   156     iHighlightTimer = new (ELeave) CTsFastSwapTimer( *this );
       
   157     iHighlightTimer->ConstructL();
       
   158     
       
   159     iRedrawTimer = new (ELeave) CTsFastSwapTimer( *this );
       
   160     iRedrawTimer->ConstructL();
       
   161 
       
   162     iUpdateGridTimer = new (ELeave) CTsFastSwapTimer( *this );
       
   163     iUpdateGridTimer->ConstructL();
       
   164     
       
   165     ActivateL();
       
   166     }
       
   167 
       
   168 // -----------------------------------------------------------------------------
       
   169 // CTsFastSwapArea::ReCreateGridL
       
   170 // -----------------------------------------------------------------------------
       
   171 //
       
   172 void CTsFastSwapArea::ReCreateGridL()
       
   173     {
       
   174     MCoeControlObserver* obs = NULL;
       
   175     TBool wasHighlight = iDeviceState.DeviceType() == 
       
   176                              CTsDeviceState::EHybrid ? ETrue : EFalse;
       
   177     if ( iGrid )
       
   178         {
       
   179         obs = iGrid->Observer();
       
   180         iDeviceState.RemoveObserver(*iGrid);
       
   181         wasHighlight = iGrid->IsHighlightVisible();
       
   182         delete iGrid;
       
   183         iGrid = NULL;
       
   184         }
       
   185     
       
   186     iGrid = new( ELeave ) CTsFastSwapGrid;
       
   187     iGrid->ConstructL( this );
       
   188     iDeviceState.AddObserverL(*iGrid, MTsDeviceStateObserver::ESkin);
       
   189     
       
   190     AknListBoxLayouts::SetupStandardGrid( *iGrid );
       
   191     
       
   192     RArray<TAknLayoutRect> rects;
       
   193     CleanupClosePushL(rects);
       
   194     rects.ReserveL(KLayoutItemCount);
       
   195     GetFastSwapAreaRects(rects);
       
   196     TAknLayoutRect gridAppPane = rects[0];
       
   197     TAknLayoutRect gridItem = rects[1];
       
   198     TAknLayoutRect gridImage = rects[2];
       
   199     TAknLayoutRect gridNextItem = rects[3];
       
   200     CleanupStack::PopAndDestroy(&rects);
       
   201     
       
   202     TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
       
   203     iGrid->SetRect(gridAppPane.Rect());
       
   204     iGrid->SetVisibleViewRect(gridAppPane.Rect());
       
   205     TAknLayoutScalableParameterLimits gridParams = 
       
   206         AknLayoutScalable_Apps::cell_tport_appsw_pane_ParamLimits( variety );
       
   207     TPoint empty( ELayoutEmpty, ELayoutEmpty );
       
   208     
       
   209     AknListBoxLayouts::SetupFormGfxCell( *iGrid, iGrid->ItemDrawer(), 0,
       
   210             AknLayoutScalable_Apps::cell_tport_appsw_pane_g1( variety ).LayoutLine(),
       
   211             empty, empty );
       
   212 
       
   213     // Setup text layout
       
   214     TAknLayoutText textLayout;
       
   215     textLayout.LayoutText(
       
   216             Rect(),
       
   217             AknLayoutScalable_Apps::cell_tport_appsw_pane_t1( variety ).LayoutLine() );
       
   218     
       
   219     // Because textLayout.BaselineOffset() does not work (missing lib entry),
       
   220     // we need to calculate offset ourselves
       
   221     TInt baselineOffset = textLayout.TextRect().iBr.iY - textLayout.TextRect().iTl.iY;
       
   222     AknListBoxLayouts::SetupFormTextCell( *iGrid, iGrid->ItemDrawer(), 1 /*Column index*/,
       
   223                                           textLayout.Font() /*Font type*/,
       
   224                                           NULL /*color*/,
       
   225                                           textLayout.TextRect().iTl.iX /*Left margin*/, 0 /*unused*/,
       
   226                                           baselineOffset /*Baseline*/, 0 /*Text width*/,
       
   227                                           textLayout.Align() /*Text alignment*/,
       
   228                                           TPoint(0,0) /*Start pos*/,
       
   229                                           TPoint(0,0) /*End pos*/);
       
   230     // Text colors
       
   231     TRgb textColor;
       
   232     AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor,
       
   233             KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6 );
       
   234     TRgb highlightTextColor;
       
   235     AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), highlightTextColor,
       
   236             KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG11 );
       
   237     CFormattedCellListBoxData::TColors colors;
       
   238     colors.iText = textColor;
       
   239     colors.iBack = iGrid->ItemDrawer()->BackColor();
       
   240     colors.iHighlightedText = highlightTextColor;
       
   241     colors.iHighlightedBack = iGrid->ItemDrawer()->HighlightedBackColor();
       
   242     iGrid->ItemDrawer()->FormattedCellData()->SetSubCellColorsL(1, colors);
       
   243     
       
   244     // Setup grid observers
       
   245     if ( obs )
       
   246         {
       
   247         iGrid->SetObserver( obs );
       
   248         }
       
   249     iGrid->SetListBoxObserver(this);
       
   250     iGrid->SetFastSwapGridObserver(this);
       
   251     iGrid->SetContainerWindowL(*this);
       
   252     
       
   253     if ( AknLayoutUtils::LayoutMirrored() )
       
   254         {
       
   255         iGridItemGap = gridItem.Rect().iTl.iX - gridNextItem.Rect().iBr.iX;
       
   256         }
       
   257     else
       
   258         {
       
   259         iGridItemGap = gridNextItem.Rect().iTl.iX - gridItem.Rect().iBr.iX;
       
   260         }
       
   261     iMaxItemsOnScreen = Rect().Width() / gridItem.Rect().Width();
       
   262     if ( iMaxItemsOnScreen > 1 )
       
   263         {
       
   264         TInt widthWithGaps =
       
   265             (iMaxItemsOnScreen - 1) * iGridItemGap + iMaxItemsOnScreen * gridItem.Rect().Width();
       
   266         if ( widthWithGaps > Rect().Width() )
       
   267             {
       
   268             iMaxItemsOnScreen--;
       
   269             }
       
   270         }
       
   271     iGridItemWidth = gridItem.Rect().Width();
       
   272     
       
   273     iGrid->ItemDrawer()->ColumnData()->SetDrawBackground(EFalse);
       
   274     
       
   275     // Update state
       
   276     HandleDeviceStateChanged( EDeviceType );
       
   277     if( wasHighlight )
       
   278         {
       
   279         iGrid->ShowHighlight();
       
   280         }
       
   281     else
       
   282         {
       
   283         iGrid->HideHighlight();
       
   284         }
       
   285     
       
   286     // Make sure that there is an ActivateL call even when we are not
       
   287     // called from ConstructL. (in order to have the grid's parent ptr set properly)
       
   288     ActivateL();
       
   289     }
       
   290 
       
   291 
       
   292 // --------------------------------------------------------------------------
       
   293 // CTsFastSwapArea::GetFastSwapAreaRects
       
   294 // --------------------------------------------------------------------------
       
   295 //
       
   296 void CTsFastSwapArea::GetFastSwapAreaRects( RArray<TAknLayoutRect>& aRects )
       
   297     {
       
   298     TAknLayoutRect gridAppPane;
       
   299     TAknLayoutRect gridItem;
       
   300     TAknLayoutRect gridImage;
       
   301     TAknLayoutRect gridNextItem;
       
   302     
       
   303     TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
       
   304     
       
   305     gridAppPane.LayoutRect( Rect(), 
       
   306             AknLayoutScalable_Apps::tport_appsw_pane( variety ) );
       
   307     aRects.Append(gridAppPane);
       
   308     
       
   309     gridItem.LayoutRect( gridAppPane.Rect(),
       
   310             AknLayoutScalable_Apps::cell_tport_appsw_pane( variety, 0, 0 ) );
       
   311     aRects.Append(gridItem);
       
   312     
       
   313     gridImage.LayoutRect( gridItem.Rect(),
       
   314             AknLayoutScalable_Apps::cell_tport_appsw_pane_g1( variety ) ); 
       
   315     aRects.Append(gridImage);
       
   316     gridNextItem.LayoutRect( gridAppPane.Rect(),
       
   317             AknLayoutScalable_Apps::cell_tport_appsw_pane_cp03( variety ) );
       
   318     aRects.Append(gridNextItem);
       
   319     }
       
   320 
       
   321 
       
   322 // --------------------------------------------------------------------------
       
   323 // CTsFastSwapArea::Setup
       
   324 // --------------------------------------------------------------------------
       
   325 //
       
   326 void CTsFastSwapArea::Setup( MCoeControlObserver& aControlObserver )
       
   327     {
       
   328     iGrid->SetObserver( &aControlObserver );
       
   329     }
       
   330 
       
   331 // -----------------------------------------------------------------------------
       
   332 // CTsFastSwapArea::SizeChanged
       
   333 // -----------------------------------------------------------------------------
       
   334 //
       
   335 void CTsFastSwapArea::SizeChanged()
       
   336     {
       
   337     TSLOG_CONTEXT( CTsFastSwapArea::SizeChanged, TSLOG_LOCAL );
       
   338     TSLOG_IN();
       
   339     
       
   340     if ( iGrid )
       
   341         {
       
   342         // Grid needs to be recreated to proper reinitilize
       
   343         // data with new layout values
       
   344         TInt selIdx = SelectedIndex();
       
   345         TRAPD(err, 
       
   346               ReCreateGridL();
       
   347               iEvtHandler.ReInitPhysicsL(GridWorldSize(), ViewSize(), ETrue););
       
   348         if ( err != KErrNone )
       
   349             {
       
   350             TSLOG1( TSLOG_INFO, "ReCreateGridL leaves with %d", err );
       
   351             }
       
   352         HandleFswContentChanged();
       
   353         iGrid->SetCurrentDataIndex(selIdx);
       
   354         UpdateGrid(ETrue, EFalse);
       
   355         DrawDeferred();
       
   356         }
       
   357     TSLOG_OUT();
       
   358     }
       
   359 
       
   360 // -----------------------------------------------------------------------------
       
   361 // CTsFastSwapArea::Draw
       
   362 // -----------------------------------------------------------------------------
       
   363 //
       
   364 void CTsFastSwapArea::Draw( const TRect& /*aRect*/ ) const
       
   365     {
       
   366     CWindowGc& gc = SystemGc();
       
   367     MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
   368     MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
       
   369     AknsDrawUtils::Background( skin,
       
   370            cc,
       
   371            this,
       
   372            gc,
       
   373            Rect() );
       
   374     }
       
   375 
       
   376 // --------------------------------------------------------------------------
       
   377 // CTsFastSwapArea::SwitchToApp
       
   378 // --------------------------------------------------------------------------
       
   379 //
       
   380 void CTsFastSwapArea::SwitchToApp( TInt aIndex )
       
   381     {
       
   382     if ( aIndex >= 0 && aIndex < iArray.Count() )
       
   383         {
       
   384         TInt wgId = iArray[aIndex]->WgId();
       
   385         // Move other app to foreground and then move ourselves to background.
       
   386         // Order is important and cannot be reversed.
       
   387         iFSClient->SwitchToApp( wgId );
       
   388         // We do not want to come back to ts if the activated app is closed.
       
   389         // Therefore ts must be moved to background.
       
   390         CTsAppUi* appui =
       
   391             static_cast<CTsAppUi*>( iEikonEnv->AppUi() );
       
   392         appui->MoveAppToBackground( AknTransEffect::EApplicationStartRect );
       
   393         }
       
   394     }
       
   395 
       
   396 // --------------------------------------------------------------------------
       
   397 // CTsFastSwapArea::TryCloseAppL
       
   398 // --------------------------------------------------------------------------
       
   399 //
       
   400 void CTsFastSwapArea::TryCloseAppL( TInt aIndex,
       
   401         TBool aSuppressRendering )
       
   402     {
       
   403     TSLOG_CONTEXT( TryCloseAppL, TSLOG_LOCAL );
       
   404     TSLOG2_IN( "%d %d", aIndex, aSuppressRendering );
       
   405 
       
   406     if ( aIndex >= 0 && aIndex < iArray.Count() && CanClose( aIndex ) )
       
   407         {
       
   408         TInt wgId = iArray[aIndex]->WgId();
       
   409         iFSClient->CloseApp( wgId );
       
   410         // The fsw content will change sooner or later
       
   411         // but the updated content (without the closed app) will not
       
   412         // come very fast. It looks better to the user if the item
       
   413         // in the grid is removed right here, right now.
       
   414         // If the app does not close for some reason then this is
       
   415         // not fully correct but the app will then reappear on the next
       
   416         // content-changed notification anyway.
       
   417         delete iArray[aIndex];
       
   418         iArray.Remove( aIndex );
       
   419         NotifyChange();
       
   420         if ( !aSuppressRendering )
       
   421             {
       
   422             RenderContentL();
       
   423             }
       
   424         // Update item selection on the screen if last item was deleted
       
   425         TInt newItemCount = GridItemCount();
       
   426         if ( aIndex == newItemCount )
       
   427             {
       
   428             newItemCount--;
       
   429             iGrid->SetCurrentDataIndex(newItemCount);
       
   430             }
       
   431         iTimeOfLastClose.HomeTime();
       
   432         }
       
   433 
       
   434     TSLOG_OUT();
       
   435     }
       
   436 
       
   437 // --------------------------------------------------------------------------
       
   438 // CTsFastSwapArea::TryCloseAllL
       
   439 // --------------------------------------------------------------------------
       
   440 //
       
   441 void CTsFastSwapArea::TryCloseAllL()
       
   442     {
       
   443     // note the direction of the loop, this is needed because
       
   444     // TryCloseAppL may modify the array
       
   445     TBool changed = EFalse;
       
   446     for ( TInt i = iArray.Count() - 1; i >= 0; --i )
       
   447         {
       
   448         if ( CanClose( i ) )
       
   449             {
       
   450             TryCloseAppL( i, ETrue );
       
   451             changed = ETrue;
       
   452             }
       
   453         }
       
   454     if ( changed )
       
   455         {
       
   456         RenderContentL();
       
   457         RestoreSelectedIndex();
       
   458         iGrid->DrawNow();
       
   459         }
       
   460     }
       
   461 
       
   462 // --------------------------------------------------------------------------
       
   463 // CTsFastSwapArea::CanClose
       
   464 // --------------------------------------------------------------------------
       
   465 //
       
   466 TBool CTsFastSwapArea::CanClose( TInt aIndex ) const
       
   467     {
       
   468     CTsFswEntry* e = iArray[aIndex];
       
   469     return !e->AlwaysShown() && !e->SystemApp();
       
   470     }
       
   471 
       
   472 // --------------------------------------------------------------------------
       
   473 // CTsFastSwapArea::CanCloseOthers
       
   474 // --------------------------------------------------------------------------
       
   475 //
       
   476 TBool CTsFastSwapArea::CanCloseAll( TInt aSelectedItem ) const
       
   477     {
       
   478     TInt count( 0 );
       
   479 
       
   480     // Count number of closable applications and if number exceeds 2 finish
       
   481     // counting, because it is already enough to show the option.
       
   482     for ( TInt i = iArray.Count(); --i >= 0 && count < KTsMaxClosableApps; )
       
   483         {
       
   484         if ( CanClose( i ) )
       
   485             {
       
   486             count++;
       
   487             }
       
   488         }
       
   489     return ( count >= KTsMaxClosableApps ) ||
       
   490            ( count && !CanClose( aSelectedItem ) );
       
   491     }
       
   492 
       
   493 // --------------------------------------------------------------------------
       
   494 // CTsFastSwapArea::HandleFswContentChanged
       
   495 // From MTsFswObserver
       
   496 // --------------------------------------------------------------------------
       
   497 //
       
   498 void CTsFastSwapArea::HandleFswContentChanged()
       
   499     {
       
   500     TSLOG_CONTEXT( HandleFswContentChanged, TSLOG_LOCAL );
       
   501     TSLOG_IN();
       
   502 
       
   503     TRAPD( err, HandleFswContentChangedL() );
       
   504     if ( err != KErrNone )
       
   505         {
       
   506         TSLOG1( TSLOG_INFO, "leave occured: %d", err );
       
   507         }
       
   508 
       
   509     TSLOG_OUT();
       
   510     }
       
   511 
       
   512 // --------------------------------------------------------------------------
       
   513 // CTsFastSwapArea::HandleFswContentChangedL
       
   514 // --------------------------------------------------------------------------
       
   515 //
       
   516 void CTsFastSwapArea::HandleFswContentChangedL()
       
   517     {
       
   518     TSLOG_CONTEXT( HandleFswContentChangedL, TSLOG_LOCAL );
       
   519     TSLOG_IN();
       
   520 
       
   521     // If there was an app close operation started during the last
       
   522     // few seconds then stop, to prevent flickering.
       
   523     TTime now;
       
   524     now.HomeTime();
       
   525     TTimeIntervalSeconds iv;
       
   526     if ( now.SecondsFrom( iTimeOfLastClose, iv ) == KErrNone
       
   527             && iv.Int() <= KRefreshDelayAfterClose )
       
   528         {
       
   529         TSLOG1_OUT( "difference since last close is only %d sec, stop", iv.Int() );
       
   530         return;
       
   531         }
       
   532 
       
   533     // get current content from fastswap server
       
   534     iFSClient->GetContentL( iArray );
       
   535     SwapApplicationOrder( iArray );
       
   536 
       
   537 #ifdef _DEBUG
       
   538     for ( TInt i = 0, ie = iArray.Count(); i != ie; ++i )
       
   539         {
       
   540         CTsFswEntry* e = iArray[i];
       
   541         const TDesC& name( e->AppName() );
       
   542         TSLOG4( TSLOG_INFO, "[%d]: %d %d %S", i, e->WgId(), e->AppUid(), &name );
       
   543         }
       
   544 #endif
       
   545 
       
   546     // draw
       
   547     RenderContentL();
       
   548 
       
   549     // notify observer, if present
       
   550     NotifyChange();
       
   551 
       
   552     TSLOG_OUT();
       
   553     }
       
   554 
       
   555 // --------------------------------------------------------------------------
       
   556 // CTsFastSwapArea::RenderContentL
       
   557 // --------------------------------------------------------------------------
       
   558 //
       
   559 void CTsFastSwapArea::RenderContentL()
       
   560     {
       
   561     TSLOG_CONTEXT( RenderContentL, TSLOG_LOCAL );
       
   562     TSLOG_IN();
       
   563 
       
   564     _LIT(KSeparator, "\t");
       
   565     
       
   566     CArrayPtr<CGulIcon>* iconArray = new ( ELeave ) CAknIconArray( iArray.Count() );
       
   567     CleanupStack::PushL( iconArray );
       
   568     CDesCArrayFlat* textArray = new ( ELeave ) CDesCArrayFlat( iArray.Count() );
       
   569     CleanupStack::PushL( textArray );
       
   570     RArray<TInt> closeItemArray;
       
   571     CleanupClosePushL(closeItemArray);
       
   572     
       
   573     TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
       
   574     RArray<TAknLayoutRect> rects;
       
   575     CleanupClosePushL(rects);
       
   576     rects.ReserveL(KLayoutItemCount);
       
   577     GetFastSwapAreaRects(rects);
       
   578     TAknLayoutRect gridItem = rects[1];
       
   579     CleanupStack::PopAndDestroy(&rects);
       
   580     if ( AknLayoutUtils::LayoutMirrored() )
       
   581         {
       
   582         iGrid->SetLayoutL( EFalse, EFalse, ETrue, iArray.Count(), 1, gridItem.Rect().Size(), iGridItemGap );
       
   583         }
       
   584     else
       
   585         {
       
   586         iGrid->SetLayoutL( EFalse, ETrue, ETrue, iArray.Count(), 1, gridItem.Rect().Size(), iGridItemGap );
       
   587         }
       
   588     
       
   589     for ( TInt i = 0, ie = iArray.Count(); i != ie; ++i )
       
   590         {
       
   591         const TDesC& appName( iArray[i]->AppName() );
       
   592         const TInt formatLen = 3 + 2;
       
   593         RBuf formAppName;
       
   594         CleanupClosePushL(formAppName);
       
   595         formAppName.CreateL(appName.Length() + formatLen);
       
   596         formAppName.AppendNum(i);
       
   597         formAppName.Append(KSeparator);
       
   598         formAppName.Append(appName);
       
   599         textArray->AppendL(formAppName);
       
   600         CleanupStack::PopAndDestroy(&formAppName);
       
   601         TSize sz = PreferredImageSize();
       
   602 
       
   603         // take the screenshot or appicon+mask and make a copy and scale
       
   604         CFbsBitmap* bitmap = 0;
       
   605         TInt h = iArray[i]->ScreenshotHandle();
       
   606         TSLOG2( TSLOG_INFO, "'%S' screenshot handle %d", &appName, h );
       
   607         TInt maskh = 0;
       
   608         CFbsBitmap* mask = 0;
       
   609         if ( !h )
       
   610             {
       
   611             h = iArray[i]->AppIconBitmapHandle();
       
   612             maskh = iArray[i]->AppIconMaskHandle();
       
   613             TSLOG1( TSLOG_INFO, "using appicon, handle = %d", h );
       
   614             }
       
   615         __ASSERT_DEBUG( h, User::Invariant() );
       
   616         bitmap = CopyBitmapL( h, sz );
       
   617         CleanupStack::PushL( bitmap );
       
   618         if ( maskh )
       
   619             {
       
   620             mask = CopyBitmapL( maskh, sz );
       
   621             }
       
   622         CleanupStack::PushL( mask );
       
   623 
       
   624         CGulIcon* icon = CGulIcon::NewL( bitmap, mask );
       
   625         CleanupStack::PushL(icon);
       
   626         iconArray->AppendL(icon);
       
   627         CleanupStack::Pop( 3, bitmap ); // mask, bitmap, icon
       
   628         
       
   629         // Check if item can be closed
       
   630         if ( CanClose(i) && AknLayoutUtils::PenEnabled() )
       
   631             {
       
   632             closeItemArray.AppendL(i);
       
   633             }
       
   634         }
       
   635     // Setup grid
       
   636     iGrid->Model()->SetItemTextArray(textArray);
       
   637     CArrayPtr<CGulIcon>* oldIconArray =
       
   638         iGrid->ItemDrawer()->FormattedCellData()->IconArray();
       
   639     if(oldIconArray)
       
   640         {
       
   641         delete oldIconArray;
       
   642         oldIconArray = NULL;
       
   643         }
       
   644     iGrid->ItemDrawer()->FormattedCellData()->SetIconArrayL(iconArray);
       
   645     iGrid->SetCloseItemsL(closeItemArray);
       
   646     
       
   647     // Cleanup
       
   648     CleanupStack::PopAndDestroy(&closeItemArray);
       
   649     CleanupStack::Pop(textArray);
       
   650     CleanupStack::Pop(iconArray);
       
   651     
       
   652     iGrid->ScrollBarFrame()->SetScrollBarVisibilityL(
       
   653                 CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOff);
       
   654     
       
   655     // refresh the items in the grid
       
   656     if(iPreviousNoOfItems < iArray.Count())
       
   657         {
       
   658         iGrid->HandleItemAdditionL();
       
   659         }
       
   660     else if(iPreviousNoOfItems > iArray.Count())
       
   661         {
       
   662         iGrid->HandleItemRemovalL();
       
   663         }
       
   664     iPreviousNoOfItems = iArray.Count();
       
   665     iEvtHandler.ReInitPhysicsL( GridWorldSize(), ViewSize(), ETrue );
       
   666     UpdateGrid( ETrue );
       
   667     
       
   668     TSLOG_OUT();
       
   669     }
       
   670 
       
   671 // --------------------------------------------------------------------------
       
   672 // CTsFastSwapArea::CopyBitmapL
       
   673 // Copy and scale.
       
   674 // --------------------------------------------------------------------------
       
   675 //
       
   676 CFbsBitmap* CTsFastSwapArea::CopyBitmapL( TInt aFbsHandle, TSize aSize )
       
   677     {
       
   678     CFbsBitmap* ret = new (ELeave) CFbsBitmap();
       
   679     CleanupStack::PushL( ret );
       
   680 
       
   681     CFbsBitmap* bmp = new (ELeave) CFbsBitmap();
       
   682     CleanupStack::PushL( bmp );
       
   683     User::LeaveIfError( bmp->Duplicate( aFbsHandle ) );
       
   684 
       
   685     // do not always use aSize, preserving the aspect ratio is quite
       
   686     // important when showing app icons instead of screenshots
       
   687     TSize sz = CalculateSizePreserveRatio( aSize, bmp->SizeInPixels() );
       
   688 
       
   689     User::LeaveIfError( ret->Create( sz, bmp->DisplayMode() ) );
       
   690 
       
   691     AknIconUtils::ScaleBitmapL( sz, ret, bmp );
       
   692 
       
   693     CleanupStack::PopAndDestroy( bmp );
       
   694     CleanupStack::Pop( ret );
       
   695 
       
   696     return ret;
       
   697     }
       
   698 
       
   699 // --------------------------------------------------------------------------
       
   700 // CTsFastSwapArea::CountComponentControls
       
   701 // --------------------------------------------------------------------------
       
   702 //
       
   703 TInt CTsFastSwapArea::CountComponentControls() const
       
   704     {
       
   705     return 1;
       
   706     }
       
   707 
       
   708 // --------------------------------------------------------------------------
       
   709 // CTsFastSwapArea::ComponentControl
       
   710 // --------------------------------------------------------------------------
       
   711 //
       
   712 CCoeControl* CTsFastSwapArea::ComponentControl( TInt aIndex ) const
       
   713     {
       
   714     if ( aIndex == 0 )
       
   715         {
       
   716         return iGrid;
       
   717         }
       
   718     return NULL;
       
   719     }
       
   720 
       
   721 // -----------------------------------------------------------------------------
       
   722 // CTsFastSwapArea::HandleSwitchToBackgroundEvent
       
   723 // -----------------------------------------------------------------------------
       
   724 //
       
   725 void CTsFastSwapArea::HandleSwitchToBackgroundEvent()
       
   726     {
       
   727     // stop listening for changes in fsw content
       
   728     iFSClient->CancelSubscribe();
       
   729     }
       
   730 
       
   731 // -----------------------------------------------------------------------------
       
   732 // CTsFastSwapArea::HandleSwitchToForegroundEvent
       
   733 // -----------------------------------------------------------------------------
       
   734 //
       
   735 void CTsFastSwapArea::HandleSwitchToForegroundEvent()
       
   736     {
       
   737     TSLOG_CONTEXT( CTsFastSwapArea::HandleSwitchToForegroundEvent, TSLOG_LOCAL );
       
   738     TSLOG_IN();
       
   739     
       
   740     // get the current task list
       
   741     HandleFswContentChanged();
       
   742     // and then start listening for changes
       
   743     iFSClient->Subscribe( *this );
       
   744     
       
   745     if ( iDeviceState.DeviceType() == CTsDeviceState::EFullTouch )
       
   746         {
       
   747         iGrid->HideHighlight();
       
   748         }
       
   749     else
       
   750         {
       
   751         iGrid->ShowHighlight();
       
   752         }
       
   753     
       
   754     RestoreSelectedIndex();
       
   755     UpdateGrid(ETrue, EFalse);
       
   756     
       
   757     iRedrawTimer->Cancel();
       
   758     iRedrawTimer->After(KRedrawTime);
       
   759     
       
   760     // give feedback
       
   761     LaunchPopupFeedback();
       
   762 
       
   763     TSLOG_OUT();
       
   764     }
       
   765 
       
   766 // -----------------------------------------------------------------------------
       
   767 // CTsFastSwapArea::FocusChanged
       
   768 // -----------------------------------------------------------------------------
       
   769 //
       
   770 void CTsFastSwapArea::FocusChanged( TDrawNow /*aDrawNow*/ )
       
   771     {
       
   772     if ( IsFocused() )
       
   773         {
       
   774         // if in non-touch mode then select (highlight) some item
       
   775         if ( !AknLayoutUtils::PenEnabled()
       
   776             && SelectedIndex() == KErrNotFound
       
   777             && GridItemCount() )
       
   778             {
       
   779             RestoreSelectedIndex();
       
   780             }
       
   781         }
       
   782     else
       
   783         {
       
   784         // store the currently selected index if there is one
       
   785         SaveSelectedIndex();
       
   786         }
       
   787     iGrid->DrawDeferred();
       
   788     }
       
   789 
       
   790 // -----------------------------------------------------------------------------
       
   791 // CTsFastSwapArea::OfferKeyEventL
       
   792 // -----------------------------------------------------------------------------
       
   793 //
       
   794 TKeyResponse CTsFastSwapArea::OfferKeyEventL(
       
   795         const TKeyEvent& aKeyEvent,
       
   796         TEventCode aType )
       
   797     {
       
   798     iKeyEvent = ETrue;
       
   799     iGrid->SetTactileFeedbackSupport(EFalse);
       
   800     // handle the 'clear' key
       
   801     if ( aType == EEventKey && aKeyEvent.iCode == EKeyBackspace )
       
   802         {
       
   803         TInt idx = SelectedIndex();
       
   804         if ( idx >= 0 )
       
   805             {
       
   806             TryCloseAppL( idx );
       
   807             }
       
   808         return EKeyWasConsumed;
       
   809         }
       
   810     
       
   811     //do not forward the event until item is higlighted
       
   812     TKeyResponse response = ShowHighlightOnKeyEvent(aKeyEvent, aType);
       
   813     if( response == EKeyWasConsumed )
       
   814     	{
       
   815     	return EKeyWasConsumed;
       
   816     	}
       
   817     
       
   818     // pass the event to grid
       
   819     // do not pass down and up arrow key events
       
   820     if ( aKeyEvent.iScanCode != EStdKeyUpArrow &&
       
   821          aKeyEvent.iScanCode != EStdKeyDownArrow )
       
   822         {
       
   823         TBool animate(ETrue);
       
   824         TBool redraw(EFalse);
       
   825         TInt prevItem = SelectedIndex();
       
   826         TKeyResponse response = iGrid->OfferKeyEventL( aKeyEvent, aType );
       
   827         if ( prevItem != SelectedIndex() && // item changed
       
   828              ( ( prevItem == 0 &&
       
   829                  SelectedIndex() == GridItemCount() - 1 &&
       
   830                  GridItemCount() > iMaxItemsOnScreen + 1 ) || // loop from first to last item
       
   831                ( prevItem == GridItemCount() - 1 &&
       
   832                  SelectedIndex() == 0 &&
       
   833                  GridItemCount() > iMaxItemsOnScreen + 1) // loop from last to first item
       
   834               ) // loop
       
   835             )
       
   836             {
       
   837             // Loop occured
       
   838             animate = EFalse;
       
   839             }
       
   840         if ( prevItem != SelectedIndex() )
       
   841             {
       
   842             redraw = ETrue;
       
   843             iGrid->ShowHighlight();
       
   844             }
       
   845         UpdateGrid( redraw, animate );
       
   846         return response;
       
   847         }
       
   848     
       
   849     return EKeyWasNotConsumed;
       
   850     }
       
   851 
       
   852 // -----------------------------------------------------------------------------
       
   853 // CTsFastSwapArea::CatchKeyEvent
       
   854 // -----------------------------------------------------------------------------
       
   855 //
       
   856 TKeyResponse CTsFastSwapArea::ShowHighlightOnKeyEvent(
       
   857 		const TKeyEvent& aKeyEvent, TEventCode aType)
       
   858 	{
       
   859 	TKeyResponse retVal(EKeyWasNotConsumed);
       
   860 	
       
   861 	if (aKeyEvent.iScanCode == EStdKeyLeftArrow ||
       
   862 		aKeyEvent.iScanCode == EStdKeyRightArrow)
       
   863 		{
       
   864 		if (!iGrid->IsHighlightVisible())
       
   865 			{
       
   866 			if (aType == EEventKey)
       
   867 				{
       
   868 				ShowHighlight();
       
   869 				iConsumeEvent = ETrue;
       
   870 				}
       
   871 			retVal = EKeyWasConsumed;
       
   872 			}
       
   873 		else if (iConsumeEvent)
       
   874 			{
       
   875 			if (aType == EEventKeyUp)
       
   876 				{
       
   877 				retVal = EKeyWasConsumed;
       
   878 				}
       
   879 			else
       
   880 				{
       
   881 				iConsumeEvent = EFalse;
       
   882 				}
       
   883 			}
       
   884 		}
       
   885 	return retVal;
       
   886 	}
       
   887 
       
   888 
       
   889 // -----------------------------------------------------------------------------
       
   890 // CTsFastSwapArea::HandlePointerEventL
       
   891 // -----------------------------------------------------------------------------
       
   892 //
       
   893 void CTsFastSwapArea::HandlePointerEventL( const TPointerEvent& aPointerEvent )
       
   894     {
       
   895     iKeyEvent = EFalse;
       
   896     iGrid->SetTactileFeedbackSupport(ETrue);
       
   897     if(aPointerEvent.iType == TPointerEvent::EButton1Down)
       
   898         {
       
   899         iTapEvent = aPointerEvent;
       
   900         }
       
   901     }
       
   902 
       
   903 // -----------------------------------------------------------------------------
       
   904 // CTsFastSwapArea::SelectedIndex
       
   905 // -----------------------------------------------------------------------------
       
   906 //
       
   907 TInt CTsFastSwapArea::SelectedIndex() const
       
   908     {
       
   909     return iGrid->CurrentDataIndex();
       
   910     }
       
   911 
       
   912 // -----------------------------------------------------------------------------
       
   913 // CTsFastSwapArea::SaveSelectedIndex
       
   914 // -----------------------------------------------------------------------------
       
   915 //
       
   916 void CTsFastSwapArea::SaveSelectedIndex()
       
   917     {
       
   918     iSavedSelectedIndex = SelectedIndex();
       
   919     }
       
   920 
       
   921 // -----------------------------------------------------------------------------
       
   922 // CTsFastSwapArea::RestoreSelectedIndex
       
   923 // -----------------------------------------------------------------------------
       
   924 //
       
   925 void CTsFastSwapArea::RestoreSelectedIndex()
       
   926     {
       
   927     iSavedSelectedIndex = KErrNotFound;
       
   928     if ( GridItemCount() )
       
   929         {
       
   930         // highlight second recent item (that has index 2) if possible
       
   931         TInt highlightItem = 0;
       
   932         TInt count = GridItemCount();
       
   933         while( highlightItem < count 
       
   934             && highlightItem < KItemToHighlight )
       
   935             {
       
   936             ++highlightItem;
       
   937             }
       
   938         iSavedSelectedIndex = highlightItem - 1;//count from 0
       
   939         iGrid->SetCurrentDataIndex( iSavedSelectedIndex );
       
   940         TBool forceRedraw(ETrue);
       
   941         UpdateGrid(forceRedraw);
       
   942         }
       
   943     }
       
   944 
       
   945 // -----------------------------------------------------------------------------
       
   946 // CTsFastSwapArea::ProcessCommandL
       
   947 // Handle fsw popup commands
       
   948 // -----------------------------------------------------------------------------
       
   949 //
       
   950 void CTsFastSwapArea::ProcessCommandL( TInt aCommandId )
       
   951     {
       
   952     switch ( aCommandId )
       
   953         {
       
   954         case EFswCmdClose:
       
   955             TryCloseAppL( iAppIndexForPopup );
       
   956             break;
       
   957 
       
   958         case EFswCmdCloseAll:
       
   959             TryCloseAllL();
       
   960             break;
       
   961 
       
   962         case KErrCancel:
       
   963             // popup dismisses automatically when tapping outside or when switching to other app
       
   964             break;
       
   965         }
       
   966     }
       
   967 
       
   968 
       
   969 // -----------------------------------------------------------------------------
       
   970 // CTsFastSwapArea::HandleCloseEventL
       
   971 // -----------------------------------------------------------------------------
       
   972 //
       
   973 void CTsFastSwapArea::HandleCloseEventL(TInt aItemIdx)
       
   974     {
       
   975     TryCloseAppL( aItemIdx );
       
   976     }
       
   977 
       
   978 
       
   979 // -----------------------------------------------------------------------------
       
   980 // CTsFastSwapArea::HandleDeviceStateChanged
       
   981 // -----------------------------------------------------------------------------
       
   982 //
       
   983 void CTsFastSwapArea::HandleDeviceStateChanged( TChangeType aChangeType )
       
   984     {
       
   985     if ( aChangeType == EDeviceType )
       
   986         {
       
   987         CTsDeviceState::TDeviceType state = iDeviceState.DeviceType();
       
   988         switch ( state )
       
   989             {
       
   990             case CTsDeviceState::EHybrid:
       
   991                 {
       
   992                 iGrid->SetGridBehaviour( CTsFastSwapGrid::EHybrid );
       
   993                 }
       
   994                 break;
       
   995             case CTsDeviceState::EFullTouch:
       
   996                 {
       
   997                 iGrid->SetGridBehaviour( CTsFastSwapGrid::ETouchOnly );
       
   998                 }
       
   999                 break;
       
  1000             default:
       
  1001                 break;
       
  1002             }
       
  1003         }
       
  1004     }
       
  1005 
       
  1006 
       
  1007 // -----------------------------------------------------------------------------
       
  1008 // CTsFastSwapArea::TimerCompletedL
       
  1009 // -----------------------------------------------------------------------------
       
  1010 //
       
  1011 void CTsFastSwapArea::TimerCompletedL( CTsFastSwapTimer* aSource )
       
  1012     {
       
  1013     if(aSource == iHighlightTimer)
       
  1014         {
       
  1015         iTapEvent.iType = TPointerEvent::EButton1Up;
       
  1016         iGrid->HandlePointerEventL(iTapEvent);
       
  1017         }
       
  1018     else if(aSource == iRedrawTimer)
       
  1019         {
       
  1020         DrawNow();
       
  1021         }
       
  1022     else if( aSource == iUpdateGridTimer )
       
  1023         {
       
  1024         UpdateGrid(ETrue, ETrue);
       
  1025         }
       
  1026     }
       
  1027 
       
  1028 
       
  1029 // -----------------------------------------------------------------------------
       
  1030 // CTsFastSwapArea::PreCreatePopupL
       
  1031 // -----------------------------------------------------------------------------
       
  1032 //
       
  1033 void CTsFastSwapArea::PreCreatePopupL()
       
  1034     {
       
  1035     if ( !iPopup )
       
  1036         {
       
  1037         iPopup = CAknStylusPopUpMenu::NewL( this, Rect().iTl );
       
  1038         HBufC* text = StringLoader::LoadLC( R_TS_FSW_CLOSE );
       
  1039         iPopup->AddMenuItemL( *text, EFswCmdClose );
       
  1040         CleanupStack::PopAndDestroy( text );
       
  1041         text = StringLoader::LoadLC( R_TS_FSW_CLOSE_ALL );
       
  1042         iPopup->AddMenuItemL( *text, EFswCmdCloseAll );
       
  1043         CleanupStack::PopAndDestroy( text );
       
  1044         }
       
  1045     }
       
  1046 
       
  1047 // -----------------------------------------------------------------------------
       
  1048 // CTsFastSwapArea::ShowPopupL
       
  1049 // -----------------------------------------------------------------------------
       
  1050 //
       
  1051 TBool CTsFastSwapArea::ShowPopupL( TInt aIndex, const TPoint& aPoint )
       
  1052     {
       
  1053     TBool showPopUp(EFalse);
       
  1054     TBool showPopupItem;
       
  1055     // hide 'close' if app cannot be closed
       
  1056     showPopupItem = CanClose( aIndex );
       
  1057     iPopup->SetItemDimmed( EFswCmdClose, !showPopupItem );
       
  1058     showPopUp = showPopUp || showPopupItem;
       
  1059     // hide 'close all' if there are no applications to close.
       
  1060     showPopupItem = CanCloseAll( aIndex );
       
  1061     iPopup->SetItemDimmed( EFswCmdCloseAll, !showPopupItem );
       
  1062     showPopUp = showPopUp || showPopupItem;
       
  1063 
       
  1064     if(showPopUp)
       
  1065         {
       
  1066         // give feedback
       
  1067         LaunchPopupFeedback();
       
  1068         // save index for later use & show popup
       
  1069         iAppIndexForPopup = aIndex;
       
  1070         iPopup->SetPosition( aPoint, CAknStylusPopUpMenu::EPositionTypeLeftBottom );
       
  1071         iPopup->ShowMenu();
       
  1072         }
       
  1073     return showPopUp;
       
  1074     }
       
  1075 
       
  1076 
       
  1077 // -----------------------------------------------------------------------------
       
  1078 // CTsFastSwapArea::Count
       
  1079 // -----------------------------------------------------------------------------
       
  1080 //
       
  1081 TInt CTsFastSwapArea::Count() const
       
  1082     {
       
  1083     return iArray.Count();
       
  1084     }
       
  1085 
       
  1086 // -----------------------------------------------------------------------------
       
  1087 // CTsFastSwapArea::SetDataChangeObserver
       
  1088 // -----------------------------------------------------------------------------
       
  1089 //
       
  1090 void CTsFastSwapArea::SetDataChangeObserver(
       
  1091         MTsDataChangeObserver* aDcObserver )
       
  1092     {
       
  1093     iDcObserver = aDcObserver;
       
  1094     }
       
  1095 
       
  1096 // -----------------------------------------------------------------------------
       
  1097 // CTsFastSwapArea::NotifyChange
       
  1098 // -----------------------------------------------------------------------------
       
  1099 //
       
  1100 void CTsFastSwapArea::NotifyChange()
       
  1101     {
       
  1102     if ( iDcObserver )
       
  1103         {
       
  1104         iDcObserver->DataChanged( this, Count() );
       
  1105         }
       
  1106     }
       
  1107     
       
  1108 // -----------------------------------------------------------------------------
       
  1109 // CTsFastSwapArea::SwapApplicationOrder
       
  1110 // -----------------------------------------------------------------------------
       
  1111 //
       
  1112 void CTsFastSwapArea::SwapApplicationOrder( 
       
  1113     RPointerArray<CTsFswEntry>& aArray )
       
  1114     {
       
  1115     for ( TInt i = 0; i < aArray.Count(); ++i )
       
  1116         {
       
  1117         if( aArray[i]->AppUid() == KAiUid )
       
  1118             {
       
  1119             CTsFswEntry* homescreenEntry(0);
       
  1120             homescreenEntry = aArray[i];
       
  1121             aArray.Remove(i);
       
  1122             aArray.Insert(homescreenEntry, KAiPosition);
       
  1123             break;
       
  1124             }
       
  1125         }
       
  1126     }
       
  1127     
       
  1128 // -----------------------------------------------------------------------------
       
  1129 // CTsFastSwapArea::PreferredImageSize
       
  1130 // -----------------------------------------------------------------------------
       
  1131 //
       
  1132 TSize CTsFastSwapArea::PreferredImageSize()
       
  1133     {
       
  1134     TAknLayoutRect gridImage;
       
  1135     TRAP_IGNORE(
       
  1136         RArray<TAknLayoutRect> rects;
       
  1137         CleanupClosePushL(rects);
       
  1138         rects.ReserveL(KLayoutItemCount);
       
  1139         GetFastSwapAreaRects(rects);
       
  1140         gridImage = rects[2];
       
  1141         CleanupStack::PopAndDestroy(&rects);
       
  1142         );
       
  1143     return gridImage.Rect().Size();
       
  1144     }
       
  1145     
       
  1146 // -----------------------------------------------------------------------------
       
  1147 // CTsFastSwapArea::GridItemCount
       
  1148 // -----------------------------------------------------------------------------
       
  1149 //
       
  1150 TInt CTsFastSwapArea::GridItemCount()
       
  1151     {
       
  1152     return iGrid->Model()->ItemTextArray()->MdcaCount();
       
  1153     }
       
  1154 
       
  1155 // -----------------------------------------------------------------------------
       
  1156 // CTsFastSwapArea::HandleListBoxEventL
       
  1157 // -----------------------------------------------------------------------------
       
  1158 //
       
  1159 void CTsFastSwapArea::HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aEventType)
       
  1160     {
       
  1161     if ( aListBox == iGrid )
       
  1162         {
       
  1163         switch ( aEventType )
       
  1164             {
       
  1165             case EEventEnterKeyPressed:
       
  1166             case EEventItemClicked:
       
  1167                 {
       
  1168                 SwitchToApp(SelectedIndex());
       
  1169                 }
       
  1170                 break;
       
  1171             case EEventPenDownOnItem:
       
  1172                 {
       
  1173                 iGrid->ShowHighlight();
       
  1174                 }
       
  1175                 break;
       
  1176             default:
       
  1177                 break;
       
  1178             }
       
  1179         }
       
  1180     }
       
  1181 
       
  1182 // --------------------------------------------------------------------------
       
  1183 // CTsFastSwapArea::CalculateSizePreserveRatio
       
  1184 // --------------------------------------------------------------------------
       
  1185 //
       
  1186 TSize CTsFastSwapArea::CalculateSizePreserveRatio(
       
  1187         const TSize& aTargetAreaSize,
       
  1188         const TSize& aSourceSize )
       
  1189     {
       
  1190     TSize sz;
       
  1191     if ( aSourceSize.iWidth > aSourceSize.iHeight )
       
  1192         {
       
  1193         sz.iWidth = aTargetAreaSize.iWidth;
       
  1194         TReal ratio = aSourceSize.iWidth / (TReal) aSourceSize.iHeight;
       
  1195         sz.iHeight = sz.iWidth / ratio;
       
  1196         }
       
  1197     else
       
  1198         {
       
  1199         sz.iHeight = aTargetAreaSize.iHeight;
       
  1200         TReal ratio = aSourceSize.iHeight / (TReal) aSourceSize.iWidth;
       
  1201         sz.iWidth = sz.iHeight / ratio;
       
  1202         }
       
  1203     return sz;
       
  1204     }
       
  1205 
       
  1206 // --------------------------------------------------------------------------
       
  1207 // CTsFastSwapArea::SelectNextItem
       
  1208 // --------------------------------------------------------------------------
       
  1209 //
       
  1210 void CTsFastSwapArea::SelectNextItem()
       
  1211     {
       
  1212     iKeyEvent = ETrue;
       
  1213     iGrid->SetTactileFeedbackSupport(EFalse);
       
  1214     TBool forceRedraw(ETrue);
       
  1215     TBool animate(ETrue);
       
  1216     TInt selectedItem = SelectedIndex();
       
  1217     selectedItem++;
       
  1218     if ( selectedItem == GridItemCount() )
       
  1219         {
       
  1220         // Last item is selected, move to first one
       
  1221         selectedItem = 0;
       
  1222         animate = EFalse;
       
  1223         }
       
  1224     iGrid->SetCurrentDataIndex(selectedItem);
       
  1225     UpdateGrid(forceRedraw, animate);
       
  1226     }
       
  1227 
       
  1228 // --------------------------------------------------------------------------
       
  1229 // CTsFastSwapArea::ShowHiglight
       
  1230 // --------------------------------------------------------------------------
       
  1231 //
       
  1232 void CTsFastSwapArea::ShowHighlight()
       
  1233     {
       
  1234     iGrid->ShowHighlight();
       
  1235     UpdateGrid(ETrue, EFalse);
       
  1236     }
       
  1237 
       
  1238 // --------------------------------------------------------------------------
       
  1239 // CTsFastSwapArea::CenterItem
       
  1240 // --------------------------------------------------------------------------
       
  1241 //
       
  1242 void CTsFastSwapArea::CenterItem(TInt aRedrawDelay)
       
  1243     {
       
  1244     if( iMaxItemsOnScreen < GridItemCount() )
       
  1245         {
       
  1246         TInt visibleItem = ViewToVisibleItem( ViewPos() );
       
  1247         if(iKeyEvent)
       
  1248             {
       
  1249             visibleItem = SelectedIndex();
       
  1250             }
       
  1251         if(visibleItem != SelectedIndex())
       
  1252             {
       
  1253             iGrid->SetCurrentDataIndex( visibleItem );
       
  1254             DrawNow();
       
  1255             }
       
  1256         }
       
  1257 
       
  1258     iUpdateGridTimer->Cancel();
       
  1259     iUpdateGridTimer->After(aRedrawDelay);
       
  1260     }
       
  1261 
       
  1262 // --------------------------------------------------------------------------
       
  1263 // CTsFastSwapArea::GridWorldSize
       
  1264 // --------------------------------------------------------------------------
       
  1265 //
       
  1266 TSize CTsFastSwapArea::GridWorldSize()
       
  1267     {
       
  1268     return TSize( GridItemCount() * iGridItemWidth + (GridItemCount() - 1) * iGridItemGap, Rect().Height() );
       
  1269     }
       
  1270 
       
  1271 // --------------------------------------------------------------------------
       
  1272 // CTsFastSwapArea::UpdateGrid
       
  1273 // --------------------------------------------------------------------------
       
  1274 //
       
  1275 void CTsFastSwapArea::UpdateGrid( TBool aForceRedraw, TBool aAnimate )
       
  1276     {
       
  1277     TPoint targetPoint = ItemViewPosition( SelectedIndex() );
       
  1278     if ( aForceRedraw || targetPoint.iX != ViewPos().iX )
       
  1279         {
       
  1280         if ( aAnimate )
       
  1281             {
       
  1282             iEvtHandler.Animate( targetPoint );
       
  1283             }
       
  1284         else
       
  1285             {
       
  1286             MoveOffset(targetPoint);
       
  1287             iEvtHandler.StopAnimation();
       
  1288             }
       
  1289         if ( aForceRedraw )
       
  1290             {
       
  1291             iGrid->DrawNow();
       
  1292             }
       
  1293         }
       
  1294     }
       
  1295 
       
  1296 // --------------------------------------------------------------------------
       
  1297 // CTsFastSwapArea::HandleAppKey
       
  1298 // --------------------------------------------------------------------------
       
  1299 //
       
  1300 void CTsFastSwapArea::HandleAppKey(TInt aType)
       
  1301     {
       
  1302     if( aType == KAppKeyTypeShort )
       
  1303         {
       
  1304         if(iGrid->IsHighlightVisible())
       
  1305             {
       
  1306             SelectNextItem();
       
  1307             }
       
  1308         else
       
  1309             {
       
  1310             ShowHighlight();
       
  1311             }
       
  1312         }
       
  1313     else if( aType == KAppKeyTypeLong )
       
  1314         {
       
  1315         SwitchToApp( SelectedIndex() );
       
  1316         }
       
  1317     }
       
  1318 
       
  1319 // --------------------------------------------------------------------------
       
  1320 // CTsFastSwapArea::MoveOffset
       
  1321 // --------------------------------------------------------------------------
       
  1322 //
       
  1323 void CTsFastSwapArea::MoveOffset(const TPoint& aPoint)
       
  1324     {
       
  1325     TSLOG_CONTEXT( CTsFastSwapArea::MoveOffset, TSLOG_LOCAL );
       
  1326     TSLOG2_IN("Old position x: %d, y:%d", ViewPos().iX, ViewPos().iY);
       
  1327     TSLOG2_IN("New position x: %d, y:%d", aPoint.iX, aPoint.iY);
       
  1328     TSLOG_OUT();
       
  1329     
       
  1330     TInt currentXPos = aPoint.iX;
       
  1331     currentXPos -= Rect().Width() / 2;
       
  1332     TRect gridViewRect = Rect();
       
  1333     gridViewRect.iTl.iX = -currentXPos;
       
  1334     // Take edge offset into account
       
  1335     gridViewRect.iTl.iX += Rect().iTl.iX;
       
  1336     if(GridItemCount() <= iMaxItemsOnScreen)
       
  1337         {
       
  1338         // Center view
       
  1339         gridViewRect.iTl.iX += ( Rect().Width() - GridItemCount() * iGridItemWidth ) / 2;
       
  1340         }
       
  1341     iGrid->SetRect( gridViewRect );
       
  1342     DrawNow();
       
  1343     }
       
  1344 
       
  1345 // --------------------------------------------------------------------------
       
  1346 // CTsFastSwapArea::Tap
       
  1347 // --------------------------------------------------------------------------
       
  1348 //
       
  1349 void CTsFastSwapArea::TapL(const TPoint& aPoint)
       
  1350     {
       
  1351     if(iGrid->Rect().Contains(aPoint))
       
  1352         {
       
  1353         //provide tap pointer event to grid
       
  1354         iGrid->HandlePointerEventL(iTapEvent);
       
  1355         iHighlightTimer->Cancel();
       
  1356         iHighlightTimer->After(KHighlighActivationTime);
       
  1357         }
       
  1358     else
       
  1359         {
       
  1360         //move task switcher to background
       
  1361         iEikonEnv->EikAppUi()->HandleCommandL(EAknSoftkeyExit);
       
  1362         }
       
  1363     }
       
  1364 
       
  1365 // --------------------------------------------------------------------------
       
  1366 // CTsFastSwapArea::LongTap
       
  1367 // --------------------------------------------------------------------------
       
  1368 //
       
  1369 void CTsFastSwapArea::LongTapL(const TPoint& aPoint)
       
  1370     {
       
  1371     TInt index(KErrNotFound);
       
  1372     if( iGrid->GridView()->XYPosToItemIndex(aPoint,index) )
       
  1373         {
       
  1374         iGrid->SetCurrentItemIndex(index);
       
  1375         SaveSelectedIndex();
       
  1376         if ( !ShowPopupL(iSavedSelectedIndex, aPoint) )
       
  1377             {
       
  1378             TapL(aPoint);
       
  1379             }
       
  1380         else
       
  1381             {
       
  1382             iGrid->ShowHighlight();
       
  1383             DrawNow();
       
  1384             }
       
  1385         }
       
  1386     else
       
  1387         {
       
  1388         TapL(aPoint);
       
  1389         }
       
  1390     }
       
  1391 
       
  1392 // --------------------------------------------------------------------------
       
  1393 // CTsFastSwapArea::Drag
       
  1394 // --------------------------------------------------------------------------
       
  1395 //
       
  1396 void CTsFastSwapArea::Drag(
       
  1397     const MAknTouchGestureFwDragEvent& /*aEvent*/)
       
  1398     {
       
  1399     iGrid->SetTactileFeedbackSupport(ETrue);
       
  1400     iGrid->HideHighlight();
       
  1401     CenterItem( KUpdateGridTime );
       
  1402     DrawNow();
       
  1403     }
       
  1404 
       
  1405 // -----------------------------------------------------------------------------
       
  1406 // CTsFastSwapArea::ViewSize
       
  1407 // -----------------------------------------------------------------------------
       
  1408 //
       
  1409 TSize CTsFastSwapArea::ViewSize()
       
  1410     {
       
  1411     return TSize(Rect().Width(), Rect().Height());  
       
  1412     }
       
  1413 
       
  1414 // -----------------------------------------------------------------------------
       
  1415 // CTsFastSwapArea::Stop
       
  1416 // -----------------------------------------------------------------------------
       
  1417 //
       
  1418 void CTsFastSwapArea::Stop()
       
  1419     {    
       
  1420     CenterItem( KUpdateGridTime );
       
  1421     DrawNow();
       
  1422     }
       
  1423 
       
  1424 // -----------------------------------------------------------------------------
       
  1425 // CTsFastSwapArea::ViewSize
       
  1426 // -----------------------------------------------------------------------------
       
  1427 //
       
  1428 TPoint CTsFastSwapArea::ViewPos() const
       
  1429     {
       
  1430     TPoint retVal;
       
  1431     retVal.iY = iGrid->Rect().iTl.iY + Rect().Height() / 2;
       
  1432     retVal.iX = - (iGrid->Rect().iTl.iX - Rect().iTl.iX) + Rect().Width() / 2 ;
       
  1433     TInt gridItemCount = iGrid->Model()->ItemTextArray()->MdcaCount();
       
  1434     if( gridItemCount <= iMaxItemsOnScreen)
       
  1435         {
       
  1436         // View centered
       
  1437         retVal.iX += ( Rect().Width() - gridItemCount * iGridItemWidth ) / 2;
       
  1438         }
       
  1439     return retVal;
       
  1440     }
       
  1441 
       
  1442 // -----------------------------------------------------------------------------
       
  1443 // CTsFastSwapArea::ItemPosition
       
  1444 // -----------------------------------------------------------------------------
       
  1445 //
       
  1446 TPoint CTsFastSwapArea::ItemViewPosition( TInt aItemIdx )
       
  1447     {
       
  1448     TPoint retVal = Rect().iTl;
       
  1449     if ( aItemIdx == 0 )
       
  1450         {
       
  1451         // First item
       
  1452         if( AknLayoutUtils::LayoutMirrored() )
       
  1453             {
       
  1454             if ( GridItemCount() > iMaxItemsOnScreen )
       
  1455                 {
       
  1456                 retVal.iX = GridWorldSize().iWidth - Rect().Width();
       
  1457                 }
       
  1458             else
       
  1459                 {
       
  1460                 retVal.iX = 0;
       
  1461                 }
       
  1462             }
       
  1463         else // normal layout
       
  1464             {
       
  1465             retVal.iX = 0;
       
  1466             }
       
  1467         }
       
  1468     else if ( aItemIdx == GridItemCount() - 1 )
       
  1469         {
       
  1470         // Last item selected
       
  1471         if( AknLayoutUtils::LayoutMirrored() )
       
  1472             {
       
  1473             retVal.iX = 0;
       
  1474             }
       
  1475         else // normal layout
       
  1476             {
       
  1477             if ( GridItemCount() > iMaxItemsOnScreen )
       
  1478                 {
       
  1479                 retVal.iX = GridWorldSize().iWidth - Rect().Width();
       
  1480                 }
       
  1481             else
       
  1482                 {
       
  1483                 retVal.iX = 0;
       
  1484                 }
       
  1485             }
       
  1486         }
       
  1487     else
       
  1488         {
       
  1489         // Middle item
       
  1490         TInt screenMiddleItemOffset = ( Rect().Width() - iGridItemWidth ) / 2;
       
  1491         if( AknLayoutUtils::LayoutMirrored() )
       
  1492             {
       
  1493             retVal.iX = iGridItemWidth * ( GridItemCount() - 1 - aItemIdx ) - screenMiddleItemOffset;
       
  1494             retVal.iX += ( GridItemCount() - 1 - aItemIdx ) * iGridItemGap;
       
  1495             }
       
  1496         else // normal layout
       
  1497             {
       
  1498             retVal.iX = iGridItemWidth * aItemIdx - screenMiddleItemOffset;
       
  1499             retVal.iX += iGridItemGap * aItemIdx;
       
  1500             }
       
  1501         if ( retVal.iX < 0 )
       
  1502             {
       
  1503             retVal.iX = 0;
       
  1504             }
       
  1505         else if ( retVal.iX + Rect().Width() > GridWorldSize().iWidth )
       
  1506             {
       
  1507             retVal.iX = GridWorldSize().iWidth - Rect().Width();
       
  1508             }
       
  1509         }
       
  1510     
       
  1511     // Return middle of the view rectangle
       
  1512     retVal.iX += Rect().Width() / 2;
       
  1513     
       
  1514     return retVal;
       
  1515     }
       
  1516 
       
  1517 // -----------------------------------------------------------------------------
       
  1518 // CTsFastSwapArea::ViewToVisibleItem
       
  1519 // -----------------------------------------------------------------------------
       
  1520 //
       
  1521 TInt CTsFastSwapArea::ViewToVisibleItem( const TPoint aViewPos )
       
  1522     {
       
  1523     TInt retVal(0);
       
  1524     TPoint absViewPos = aViewPos;
       
  1525     absViewPos.iX -= Rect().Width() / 2;
       
  1526     if ( absViewPos.iX < 0 )
       
  1527         {
       
  1528         if ( AknLayoutUtils::LayoutMirrored() )
       
  1529             {
       
  1530             // View crossed left border of grid world rect, last item selected
       
  1531             retVal = GridItemCount() - 1;
       
  1532             }
       
  1533         else // normal layout
       
  1534             {
       
  1535             // View crossed left border of grid world rect, first item selected
       
  1536             retVal = 0;
       
  1537             }
       
  1538         }
       
  1539     else if ( absViewPos.iX + Rect().Width() > GridWorldSize().iWidth )
       
  1540         {
       
  1541         if ( AknLayoutUtils::LayoutMirrored() )
       
  1542             {
       
  1543             // View crossed right border of grid world rect, first item selected
       
  1544             retVal = 0;
       
  1545             }
       
  1546         else // normal layout
       
  1547             {
       
  1548             // View crossed right border of grid world rect, last item selected
       
  1549             retVal = GridItemCount() - 1;
       
  1550             }
       
  1551         }
       
  1552     else
       
  1553         {
       
  1554         TInt offsetCheck = GridWorldSize().iWidth;
       
  1555         // View inside of grid world rect
       
  1556         for ( TInt i = 0 ; i < GridItemCount(); i++ )
       
  1557             {
       
  1558             TInt offset = aViewPos.iX - ItemViewPosition( i ).iX;
       
  1559             if ( Abs( offset ) <= offsetCheck )
       
  1560                 {
       
  1561                 offsetCheck = Abs( offset );
       
  1562                 retVal = i;
       
  1563                 }
       
  1564             else
       
  1565                 {
       
  1566                 break;
       
  1567                 }
       
  1568             }
       
  1569         }
       
  1570     return retVal;
       
  1571     }
       
  1572 
       
  1573 
       
  1574 // -----------------------------------------------------------------------------
       
  1575 // CTsFastSwapArea::LaunchPopupFeedback
       
  1576 // -----------------------------------------------------------------------------
       
  1577 //
       
  1578 void CTsFastSwapArea::LaunchPopupFeedback()
       
  1579     {
       
  1580     if ( AknLayoutUtils::PenEnabled() )
       
  1581         {
       
  1582         MTouchFeedback* feedback = MTouchFeedback::Instance();
       
  1583         if ( feedback )
       
  1584             {
       
  1585             TTouchLogicalFeedback fbLogicalType = ETouchFeedbackPopUp;
       
  1586             if ( CAknTransitionUtils::TransitionsEnabled(
       
  1587                  AknTransEffect::EComponentTransitionsOff ) )
       
  1588                 {
       
  1589                 fbLogicalType = ETouchFeedbackIncreasingPopUp;
       
  1590                 }
       
  1591             feedback->InstantFeedback( this,
       
  1592                                        fbLogicalType,
       
  1593                                        ETouchFeedbackVibra,
       
  1594                                        TPointerEvent() );
       
  1595             }
       
  1596         }
       
  1597     }
       
  1598 
       
  1599 // End of file