menufw/menufwui/mmwidgets/src/mmlistbox.cpp
branchRCL_3
changeset 83 5456b4e8b3a8
child 88 3321d3e205b6
equal deleted inserted replaced
82:5f0182e07bfb 83:5456b4e8b3a8
       
     1 /*
       
     2 * Copyright (c) 2007 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:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <aknlists.h>
       
    20 #include <eikspmod.h>
       
    21 #include <eikclb.h>
       
    22 #include <eikfrlb.h>
       
    23 #include <eikslb.h>
       
    24 #include <AknUtils.h>
       
    25 #include <aknlayoutscalable_avkon.cdl.h>
       
    26 #include <aknlayoutscalable_apps.cdl.h>
       
    27 #include <layoutmetadata.cdl.h>
       
    28 
       
    29 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
    30 #include <aknlistboxtfxinternal.h>
       
    31 #include <akntransitionutils.h>
       
    32 #include <aknlistloadertfx.h>
       
    33 #endif
       
    34 
       
    35 #include "mmlistboxmodel.h"
       
    36 #include "mmlistbox.h"
       
    37 #include "mmlistboxview.h"
       
    38 #include "mmlistboxitemdrawer.h"
       
    39 #include "mmmarqueeadapter.h"
       
    40 #include "mmwidgetcontainer.h"
       
    41 #include "mmwidgetsconstants.h"
       
    42 #include "mmdraweranimator.h"
       
    43 #include "mmtemplatelibrary.h"
       
    44 
       
    45 
       
    46 // -----------------------------------------------------------------------------
       
    47 //
       
    48 // -----------------------------------------------------------------------------
       
    49 //
       
    50 CMmListBox::CMmListBox() : AKNDOUBLELISTBOXNAME(R_LIST_PANE_LINES_AB_COLUMN)
       
    51   {
       
    52   // No implementation required
       
    53   }
       
    54 
       
    55 // -----------------------------------------------------------------------------
       
    56 //
       
    57 // -----------------------------------------------------------------------------
       
    58 //
       
    59 CMmListBox::~CMmListBox()
       
    60   {
       
    61   delete iRedrawTimer;
       
    62   }
       
    63 
       
    64 // -----------------------------------------------------------------------------
       
    65 //
       
    66 // -----------------------------------------------------------------------------
       
    67 //
       
    68 CMmListBox* CMmListBox::NewLC( const CCoeControl* aParent, TInt aFlags,
       
    69     CMmTemplateLibrary* aTemplateLibrary )
       
    70   {
       
    71   CMmListBox* self = new (ELeave)CMmListBox();
       
    72   CleanupStack::PushL(self);
       
    73   self->ConstructL( aParent, aFlags, aTemplateLibrary );
       
    74   return self;
       
    75   }
       
    76 
       
    77 // -----------------------------------------------------------------------------
       
    78 //
       
    79 // -----------------------------------------------------------------------------
       
    80 //
       
    81 void CMmListBox::SetListFlag( TInt aFlag )
       
    82   {
       
    83   iListBoxFlags = iListBoxFlags | aFlag;
       
    84   }
       
    85 
       
    86 // -----------------------------------------------------------------------------
       
    87 //
       
    88 // -----------------------------------------------------------------------------
       
    89 //
       
    90 void CMmListBox::ClearListFlag( TInt aFlag )
       
    91   {
       
    92   iListBoxFlags = iListBoxFlags & !aFlag;
       
    93   }
       
    94 
       
    95 // -----------------------------------------------------------------------------
       
    96 //
       
    97 // -----------------------------------------------------------------------------
       
    98 //
       
    99 CMmListBox* CMmListBox::NewL( const CCoeControl* aParent, TInt aFlags,
       
   100     CMmTemplateLibrary* aTemplateLibrary )
       
   101   {
       
   102   CMmListBox* self = CMmListBox::NewLC( aParent, aFlags, aTemplateLibrary );
       
   103   CleanupStack::Pop( self );
       
   104   return self;
       
   105   }
       
   106 
       
   107 // -----------------------------------------------------------------------------
       
   108 //
       
   109 // -----------------------------------------------------------------------------
       
   110 //
       
   111 void CMmListBox::ConstructL( const CCoeControl* aParent, TInt aFlags,
       
   112     CMmTemplateLibrary* aTemplateLibrary )
       
   113   {
       
   114   iDisableChildComponentDrawing = EFalse;
       
   115   iModel = iMmModel = CMmListBoxModel::NewL();
       
   116     CreateItemDrawerL( aTemplateLibrary );
       
   117 
       
   118     EnableExtendedDrawingL();
       
   119 
       
   120     iItemDrawer->SetDrawMark(EFalse);
       
   121     CEikListBox::ConstructL(aParent,aFlags);
       
   122     iMmDrawer->SetView( this );
       
   123     iRedrawTimer = CPeriodic::NewL( EPriorityRealTime );
       
   124   }
       
   125 
       
   126 // -----------------------------------------------------------------------------
       
   127 // Clearing ELeftDownInViewRect flag before invoking the base class
       
   128 // HandlePointerEventL method effectively prevents that method from doing most
       
   129 // of the things it would normally do in response to EButton1Down event.
       
   130 // This flag is explicitly cleared to achieve two things:
       
   131 // 1. Prevent kinetic scrolling (flick) in edit mode.
       
   132 // 2. Prevent highlight removal when popup menu is displayed.
       
   133 // -----------------------------------------------------------------------------
       
   134 //
       
   135 void CMmListBox::HandlePointerEventInEditModeL(
       
   136         const TPointerEvent& aPointerEvent )
       
   137     {
       
   138     CMmWidgetContainer* parent = static_cast<CMmWidgetContainer*>( Parent() );
       
   139     if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
       
   140         {
       
   141         iButton1DownPos = aPointerEvent.iPosition;
       
   142         }
       
   143     else if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
       
   144         {
       
   145         TPoint dragDelta = iButton1DownPos - aPointerEvent.iPosition;
       
   146         if ( Abs( dragDelta.iY ) > KDragTreshold || parent->LongTapInProgress() )
       
   147             {
       
   148             iListBoxFlags &= ~ELeftDownInViewRect;
       
   149             }
       
   150         }
       
   151 
       
   152     TInt itemUnderPointerIndex = KErrNotFound;
       
   153     if ( aPointerEvent.iType == TPointerEvent::EButton1Up ||
       
   154             aPointerEvent.iType == TPointerEvent::EButton1Down )
       
   155         {
       
   156         TBool highlightWasVisible = parent->IsHighlightVisible();
       
   157         CEikFormattedCellListBoxTypedef::HandlePointerEventL( aPointerEvent );
       
   158         // Tricky: Do not allow the base class implementation of HandlePointerEventL
       
   159         //         to remove the highlight on EButton1Up event when context menu
       
   160         //         is displayed for an item
       
   161         if ( aPointerEvent.iType == TPointerEvent::EButton1Up &&
       
   162                 highlightWasVisible && parent->LongTapInProgress()
       
   163                 && !parent->IsHighlightVisible() )
       
   164             {
       
   165             ItemDrawer()->ClearFlags( CListItemDrawer::ESingleClickDisabledHighlight );
       
   166             }
       
   167         }
       
   168     else if ( View()->XYPosToItemIndex(
       
   169             aPointerEvent.iPosition, itemUnderPointerIndex ) )
       
   170         {
       
   171         TInt currentItemIndex = CurrentItemIndex();
       
   172         if ( currentItemIndex != itemUnderPointerIndex )
       
   173             {
       
   174             View()->SetCurrentItemIndex( itemUnderPointerIndex );
       
   175             // remove hightlight from the previously highlighted item
       
   176             }
       
   177         }
       
   178     HandleScrollingInEditMode( aPointerEvent );
       
   179     }
       
   180 
       
   181 // -----------------------------------------------------------------------------
       
   182 //
       
   183 // -----------------------------------------------------------------------------
       
   184 //
       
   185 void CMmListBox::HandleScrollingInEditMode( const TPointerEvent& aPointerEvent )
       
   186     {
       
   187     if ( aPointerEvent.iType == TPointerEvent::EDrag
       
   188             || aPointerEvent.iType == TPointerEvent::EButtonRepeat )
       
   189         {
       
   190         TInt nextScrollDelay = ScrollIfNeeded( aPointerEvent );
       
   191         if ( nextScrollDelay )
       
   192             {
       
   193             TRect ignoreDragRect(
       
   194                 TPoint(aPointerEvent.iParentPosition.iX - MmEffects::KDragIgnoreRectValue,
       
   195                     aPointerEvent.iParentPosition.iY - MmEffects::KDragIgnoreRectValue),
       
   196                 TPoint(aPointerEvent.iParentPosition.iX + MmEffects::KDragIgnoreRectValue,
       
   197                     aPointerEvent.iParentPosition.iY + MmEffects::KDragIgnoreRectValue));
       
   198 
       
   199             Window().CancelPointerRepeatEventRequest();
       
   200             Window().RequestPointerRepeatEvent( nextScrollDelay, ignoreDragRect );
       
   201             }
       
   202         }
       
   203     }
       
   204 
       
   205 // -----------------------------------------------------------------------------
       
   206 //
       
   207 // -----------------------------------------------------------------------------
       
   208 //
       
   209 TBool CMmListBox::IsPointerInTopScrollingThreshold(
       
   210             const TPointerEvent& aPointerEvent ) const
       
   211     {
       
   212     TInt topScrollingTreshold = Rect().iTl.iY
       
   213         + ( MmListBox::KFocusScrollingThreshold
       
   214             * TReal( View()->ItemSize().iHeight ) );
       
   215 
       
   216     return ( aPointerEvent.iPosition.iY < topScrollingTreshold );
       
   217     }
       
   218 
       
   219 // -----------------------------------------------------------------------------
       
   220 //
       
   221 // -----------------------------------------------------------------------------
       
   222 //
       
   223 TBool CMmListBox::IsPointerInBottomScrollingThreshold(
       
   224             const TPointerEvent& aPointerEvent ) const
       
   225     {
       
   226     TInt bottomScrollingTreshold = Rect().iBr.iY
       
   227         - ( MmListBox::KFocusScrollingThreshold
       
   228             * TReal( View()->ItemSize().iHeight ) );
       
   229 
       
   230     return ( aPointerEvent.iPosition.iY > bottomScrollingTreshold );
       
   231     }
       
   232 
       
   233 // -----------------------------------------------------------------------------
       
   234 //
       
   235 // -----------------------------------------------------------------------------
       
   236 //
       
   237 TInt CMmListBox::ScrollIfNeeded( const TPointerEvent& aPointerEvent )
       
   238     {
       
   239     TInt nextScrollDelay = 0;
       
   240 
       
   241   TBool readyForScrolling =
       
   242       iMmDrawer->GetAnimator()->IsReadyForNewAnimation()
       
   243           && iMmDrawer->GetFloatingItemCount() != 0;
       
   244 
       
   245   if ( IsPointerInTopScrollingThreshold( aPointerEvent ) )
       
   246     {
       
   247     // scroll up by one row
       
   248     TInt newCurrentItemIndex = CurrentItemIndex() - 1;
       
   249 
       
   250     if ( newCurrentItemIndex >= 0 )
       
   251       {
       
   252       nextScrollDelay = MmEffects::KEditModeScrollingDelayFactor *
       
   253         Max( 1, aPointerEvent.iPosition.iY - Rect().iTl.iY );
       
   254       if (readyForScrolling)
       
   255         {
       
   256         View()->VScrollTo( View()->CalcNewTopItemIndexSoItemIsVisible(
       
   257                         newCurrentItemIndex ) );
       
   258                 View()->SetCurrentItemIndex( newCurrentItemIndex );
       
   259                 UpdateScrollBarThumbs();
       
   260         }
       
   261       }
       
   262     }
       
   263   else if ( IsPointerInBottomScrollingThreshold( aPointerEvent) )
       
   264     {
       
   265     // scroll down by one row
       
   266     TInt lastItemIndex = iModel->NumberOfItems() - 1;
       
   267     TInt newCurrentItemIndex = CurrentItemIndex() + 1;
       
   268 
       
   269 
       
   270     if ( newCurrentItemIndex <= lastItemIndex )
       
   271       {
       
   272       nextScrollDelay = MmEffects::KEditModeScrollingDelayFactor *
       
   273         Max( 1, Rect().iBr.iY - aPointerEvent.iPosition.iY );
       
   274 
       
   275       if (readyForScrolling)
       
   276         {
       
   277         View()->VScrollTo( View()->CalcNewTopItemIndexSoItemIsVisible(
       
   278             newCurrentItemIndex ) );
       
   279         View()->SetCurrentItemIndex( newCurrentItemIndex );
       
   280                 UpdateScrollBarThumbs();
       
   281         }
       
   282       }
       
   283     }
       
   284 
       
   285     return nextScrollDelay;
       
   286     }
       
   287 
       
   288 // -----------------------------------------------------------------------------
       
   289 //
       
   290 // -----------------------------------------------------------------------------
       
   291 //
       
   292 void CMmListBox::HandlePointerEventL(const TPointerEvent& aPointerEvent)
       
   293     {
       
   294 //    if ( aPointerEvent.iType == TPointerEvent::EButton1Down &&
       
   295 //            iMmDrawer->CachedDataUseIsEnabled() )
       
   296 //        {
       
   297 //        // Touching the screen stops flick but avkon does not send us
       
   298 //        // MEikListBoxObserver::EEventFlickStopped event in such case.
       
   299 //        // Thus this little hack:
       
   300 //        iMmDrawer->EnableCachedDataUse( EFalse );
       
   301 //        DrawView();
       
   302 //        }
       
   303 
       
   304     CMmWidgetContainer* parent = static_cast<CMmWidgetContainer*>( Parent() );
       
   305 
       
   306     if ( parent->IsEditMode() )
       
   307         {
       
   308         HandlePointerEventInEditModeL( aPointerEvent );
       
   309         }
       
   310     else
       
   311       {
       
   312         CEikFormattedCellListBoxTypedef::HandlePointerEventL( aPointerEvent );
       
   313       }
       
   314 
       
   315     }
       
   316 
       
   317 // -----------------------------------------------------------------------------
       
   318 //
       
   319 // -----------------------------------------------------------------------------
       
   320 //
       
   321 void CMmListBox::FixViewForMirroredLayout()
       
   322     {
       
   323     TInt scrollbarWidth =
       
   324             ScrollBarFrame()->VerticalScrollBar()->Rect().Width();
       
   325     TRect r( View()->ViewRect() );
       
   326     TInt currentShift = r.iTl.iX;
       
   327     TBool scrollbarVisible = ScrollBarFrame()->VerticalScrollBar()->IsVisible();
       
   328     TBool layoutMirrored = AknLayoutUtils::LayoutMirrored();
       
   329 
       
   330     if ( layoutMirrored && scrollbarVisible && currentShift != scrollbarWidth )
       
   331         {
       
   332         // shift view rect to the right
       
   333         r.Move( scrollbarWidth - currentShift, 0 );
       
   334         View()->SetViewRect( r );
       
   335         }
       
   336     else if ( ( !layoutMirrored || !scrollbarVisible ) && currentShift != 0 )
       
   337         {
       
   338         // restore view rect to its normal position
       
   339         r.Move( -currentShift, 0 );
       
   340         View()->SetViewRect( r );
       
   341         }
       
   342     }
       
   343 
       
   344 // -----------------------------------------------------------------------------
       
   345 //
       
   346 // -----------------------------------------------------------------------------
       
   347 //
       
   348 void CMmListBox::RedrawScrollbarBackground() const
       
   349     {
       
   350     TRect viewRect( View()->ViewRect() );
       
   351     if ( viewRect.iTl.iX > 0 )
       
   352         {
       
   353         TRect scrollbarRect( TPoint( 0, 0 ),
       
   354                 TSize( viewRect.iTl.iX, viewRect.Height() ) );
       
   355 
       
   356         CWindowGc* gc = iItemDrawer->Gc();
       
   357         CMmListBoxItemDrawer* itemDrawer =
       
   358                 static_cast<CMmListBoxItemDrawer*>( iItemDrawer );
       
   359         MAknsSkinInstance *skin = AknsUtils::SkinInstance();
       
   360         CCoeControl* control = itemDrawer->FormattedCellData()->Control();
       
   361         MAknsControlContext *cc = AknsDrawUtils::ControlContext( control );
       
   362         if( gc )
       
   363             {
       
   364             if ( control )
       
   365                 {
       
   366                 AknsDrawUtils::Background( skin, cc, control, *gc, scrollbarRect );
       
   367                 }
       
   368             else
       
   369                 {
       
   370                 gc->SetBrushColor( BackColor() );
       
   371                 gc->Clear( scrollbarRect );
       
   372                 }
       
   373             }
       
   374         }
       
   375     }
       
   376 
       
   377 // -----------------------------------------------------------------------------
       
   378 //
       
   379 // -----------------------------------------------------------------------------
       
   380 //
       
   381 void CMmListBox::ProcessScrollEventL( CEikScrollBar* aScrollBar,
       
   382             TEikScrollEvent aEventType )
       
   383     {
       
   384     CEikFormattedCellListBoxTypedef::HandleScrollEventL(
       
   385             aScrollBar, aEventType );
       
   386     }
       
   387 
       
   388 // -----------------------------------------------------------------------------
       
   389 //
       
   390 // -----------------------------------------------------------------------------
       
   391 //
       
   392 void CMmListBox::HandleRedrawTimerEventL()
       
   393     {
       
   394     if ( iSkippedScrollbarEventsCount )
       
   395         {
       
   396         ProcessScrollEventL( ScrollBarFrame()->VerticalScrollBar(),
       
   397                 EEikScrollThumbDragVert );
       
   398         }
       
   399     iSkippedScrollbarEventsCount = 0;
       
   400     }
       
   401 
       
   402 // -----------------------------------------------------------------------------
       
   403 //
       
   404 // -----------------------------------------------------------------------------
       
   405 //
       
   406 TInt CMmListBox::RedrawTimerCallback( TAny* aPtr )
       
   407     {
       
   408     CMmListBox* self = static_cast<CMmListBox*>( aPtr );
       
   409     TRAP_IGNORE( self->HandleRedrawTimerEventL() );
       
   410     // Do not bother returning a meaningful error code, CPeriodic will ignore it
       
   411     // anyway.
       
   412     return 0;
       
   413     }
       
   414 
       
   415 // -----------------------------------------------------------------------------
       
   416 //
       
   417 // -----------------------------------------------------------------------------
       
   418 //
       
   419 TKeyResponse CMmListBox::OfferKeyEventL(
       
   420         const TKeyEvent& aKeyEvent,TEventCode aType )
       
   421     {
       
   422     TInt itemIndex = CurrentItemIndex();
       
   423     TInt previousItemIndex = CurrentItemIndex();
       
   424     TKeyResponse ret = CEikFormattedCellListBoxTypedef::OfferKeyEventL(
       
   425         aKeyEvent, aType );
       
   426     TInt currentItemIndex = CurrentItemIndex();
       
   427 
       
   428     TInt itemY = View()->ItemPos( currentItemIndex ).iY
       
   429                + View()->ItemSize( currentItemIndex ).iHeight;
       
   430 
       
   431     if ( currentItemIndex == BottomItemIndex()
       
   432         && currentItemIndex != previousItemIndex
       
   433         && itemY > View()->ViewRect().iBr.iY )
       
   434       {
       
   435       if( aType == EEventKey )
       
   436         {
       
   437 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   438         MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal(
       
   439             View()->ItemDrawer()->Gc() );
       
   440         TBool effects = transApi && !transApi->EffectsDisabled();
       
   441         if ( effects )
       
   442           {
       
   443           transApi->SetMoveType( MAknListBoxTfxInternal::EListScrollDown );
       
   444           }
       
   445 #endif
       
   446       iView->VScrollTo(
       
   447         iView->CalcNewTopItemIndexSoItemIsVisible( currentItemIndex ) );
       
   448 
       
   449 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   450       if ( effects )
       
   451         {
       
   452         transApi->Draw( Rect() );
       
   453         }
       
   454 #endif
       
   455       }
       
   456       SetCurrentItemIndex( currentItemIndex );
       
   457       }
       
   458 
       
   459     RedrawIfNecessary( itemIndex, CurrentItemIndex());
       
   460     return ret;
       
   461     }
       
   462 
       
   463 // -----------------------------------------------------------------------------
       
   464 //
       
   465 // -----------------------------------------------------------------------------
       
   466 //
       
   467 TBool CMmListBox::RedrawIfNecessary( TInt aPreviousCurrent, TInt aCurrent )
       
   468     {
       
   469     TBool redrawConsumed( EFalse );
       
   470     if( aCurrent == KErrNotFound )
       
   471         {
       
   472         return redrawConsumed;
       
   473         }
       
   474 
       
   475     CMmListBoxView * view = static_cast<CMmListBoxView *>(iView);
       
   476     TInt differenceIndex = Abs( aPreviousCurrent - aCurrent );
       
   477     if ( aPreviousCurrent == KErrNotFound  || differenceIndex == 0 )
       
   478         {
       
   479         //TODO: It should be checked if this is really necessary
       
   480         view->RedrawBackground();
       
   481         return redrawConsumed;
       
   482         }
       
   483 
       
   484     TInt sizePrevBefore = iMmDrawer->GetItemHeight(aPreviousCurrent, ETrue);
       
   485     TInt sizeCurBefore = iMmDrawer->GetItemHeight(aCurrent, EFalse);
       
   486     TInt sizePrevAfter = iMmDrawer->GetItemHeight(aPreviousCurrent, EFalse);
       
   487     TInt sizeCurAfter = iMmDrawer->GetItemHeight(aCurrent, ETrue);
       
   488 
       
   489     if ( ( sizePrevBefore == sizePrevAfter ) && (sizeCurBefore == sizeCurAfter) )
       
   490         {
       
   491         return redrawConsumed;
       
   492         }
       
   493      else
       
   494         {
       
   495         TInt sizeAllBefore = sizePrevBefore + sizePrevAfter;
       
   496         TInt sizeAllAfter = sizeCurBefore + sizeCurAfter;
       
   497 
       
   498         TInt lastPotentialItemIndex = Min( iModel->NumberOfItems(),
       
   499                 iView->TopItemIndex() + iView->NumberOfItemsThatFitInRect(
       
   500                         iView->ViewRect() ) );
       
   501         TInt redrawIndex = lastPotentialItemIndex;
       
   502 
       
   503         if ( differenceIndex == 1 )
       
   504             {
       
   505             if( sizeAllBefore != sizeAllAfter )
       
   506               {
       
   507                 redrawIndex = Min( aPreviousCurrent, aCurrent );
       
   508               }
       
   509             else
       
   510               {
       
   511               return redrawConsumed;
       
   512               }
       
   513             }
       
   514         else if ( differenceIndex > 1 && sizeAllBefore == sizeAllAfter  )
       
   515             {
       
   516             redrawIndex = Min( aPreviousCurrent, aCurrent );
       
   517             lastPotentialItemIndex = Max( aPreviousCurrent, aCurrent );
       
   518             }
       
   519         else if ( differenceIndex > 1 )
       
   520             {
       
   521             redrawIndex = Min( aPreviousCurrent, aCurrent );
       
   522             }
       
   523 
       
   524         if (redrawIndex < iView->TopItemIndex())
       
   525             redrawIndex = iView->TopItemIndex();
       
   526 
       
   527         if (lastPotentialItemIndex > iView->BottomItemIndex())
       
   528             lastPotentialItemIndex = iView->BottomItemIndex();
       
   529 
       
   530         if ( aPreviousCurrent < TopItemIndex() )
       
   531           {
       
   532           lastPotentialItemIndex = BottomItemIndex() ;
       
   533           }
       
   534         else if ( BottomItemIndex() < aPreviousCurrent )
       
   535           {
       
   536           lastPotentialItemIndex = BottomItemIndex() + 1;
       
   537           }
       
   538 
       
   539         while ( redrawIndex < lastPotentialItemIndex +1 )
       
   540             {
       
   541             view->DrawSingleItem( redrawIndex++ );
       
   542             redrawConsumed = ETrue;
       
   543             }
       
   544 
       
   545         view->RedrawBackground();
       
   546         }
       
   547     return redrawConsumed;
       
   548     }
       
   549 
       
   550 // -----------------------------------------------------------------------------
       
   551 //
       
   552 // -----------------------------------------------------------------------------
       
   553 //
       
   554 void CMmListBox::CreateItemDrawerL( CMmTemplateLibrary* aTemplateLibrary )
       
   555     {
       
   556     CFormattedCellListBoxData* cellData=CFormattedCellListBoxData::NewL();
       
   557     CleanupStack::PushL( cellData );
       
   558     iItemDrawer = iMmDrawer = CMmListBoxItemDrawer::NewL( MmModel(),
       
   559             iEikonEnv->NormalFont(), cellData, EListbox, aTemplateLibrary );
       
   560     CleanupStack::Pop( cellData );
       
   561     }
       
   562 
       
   563 // -----------------------------------------------------------------------------
       
   564 //
       
   565 // -----------------------------------------------------------------------------
       
   566 //
       
   567 CMmListBoxModel* CMmListBox::MmModel()
       
   568   {
       
   569   return iMmModel;
       
   570   }
       
   571 
       
   572 // -----------------------------------------------------------------------------
       
   573 //
       
   574 // -----------------------------------------------------------------------------
       
   575 //
       
   576 void CMmListBox::SetMmModel( CMmListBoxModel* aMmModel )
       
   577   {
       
   578   if ( iMmModel != aMmModel )
       
   579     {
       
   580     delete iMmModel;
       
   581     iMmModel = aMmModel;
       
   582     }
       
   583   }
       
   584 
       
   585 // -----------------------------------------------------------------------------
       
   586 //
       
   587 // -----------------------------------------------------------------------------
       
   588 //
       
   589 CListBoxView* CMmListBox::MakeViewClassInstanceL()
       
   590     {
       
   591     return CMmListBoxView::NewL();
       
   592     }
       
   593 
       
   594 // -----------------------------------------------------------------------------
       
   595 //
       
   596 // -----------------------------------------------------------------------------
       
   597 //
       
   598 TInt CMmListBox::AdjustRectHeightToWholeNumberOfItems(TRect& /*aRect*/) const
       
   599     {
       
   600     return KErrNone;
       
   601     }
       
   602 
       
   603 // -----------------------------------------------------------------------------
       
   604 //
       
   605 // -----------------------------------------------------------------------------
       
   606 //
       
   607 void CMmListBox::SetItemDrawerAndViewBgContext (CAknsBasicBackgroundControlContext * aBgContext)
       
   608   {
       
   609   iMmDrawer->SetBgContext (aBgContext);
       
   610   }
       
   611 
       
   612 // -----------------------------------------------------------------------------
       
   613 //
       
   614 // -----------------------------------------------------------------------------
       
   615 //
       
   616 TBool CMmListBox::HandleScrollbarVisibilityChangeL()
       
   617   {
       
   618   TBool ret = EFalse;
       
   619   if ( AllItemsFitInViewRect() )
       
   620     {
       
   621     if ( ScrollBarFrame()->VerticalScrollBar()->IsVisible()
       
   622             || iMmDrawer->TemplateLibrary()->GetScrollbarVisibility() )
       
   623       {
       
   624       ScrollBarFrame()->VerticalScrollBar()->MakeVisible( EFalse );
       
   625       iMmDrawer->SetScrollbarVisibilityL( EFalse );
       
   626 
       
   627 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   628       MAknListBoxTfxInternal *trans = CAknListLoader::TfxApiInternal( ItemDrawer()->Gc() );
       
   629         if ( trans )
       
   630           {
       
   631           trans->Remove( MAknListBoxTfxInternal::EListEverything );
       
   632           }
       
   633 #endif
       
   634 
       
   635       ret = ETrue; //redraw is needed
       
   636       }
       
   637     }
       
   638   else if ( !ScrollBarFrame()->VerticalScrollBar()->IsVisible()
       
   639             || !iMmDrawer->TemplateLibrary()->GetScrollbarVisibility() )
       
   640     {
       
   641     ScrollBarFrame()->VerticalScrollBar()->MakeVisible( ETrue );
       
   642     iMmDrawer->SetScrollbarVisibilityL( ETrue );
       
   643     ret = ETrue; //redraw is needed
       
   644     }
       
   645   return ret;
       
   646   }
       
   647 
       
   648 
       
   649 // -----------------------------------------------------------------------------
       
   650 //
       
   651 // -----------------------------------------------------------------------------
       
   652 //
       
   653 TBool CMmListBox::AllItemsFitInViewRect()
       
   654   {
       
   655   CMmListBoxView* view = static_cast< CMmListBoxView* >(iView);
       
   656   TInt totalHeight = view->GetTotalHeight( view->TopItemIndex(), view->BottomItemIndex());
       
   657   if ( view->TopItemIndex() == 0 && iMmModel->NumberOfItems() <= view->BottomItemIndex() + 1
       
   658           && totalHeight <= iView->ViewRect().Height() )
       
   659     {
       
   660     return ETrue;
       
   661     }
       
   662   else
       
   663     {
       
   664     return EFalse;
       
   665     }
       
   666   }
       
   667 
       
   668 /**
       
   669  * Helper class whose only purpose is to ensure that
       
   670  * ScrollToItem method will be always re-enabled.
       
   671  */
       
   672 struct TScrollToItemEnabler
       
   673     {
       
   674     CMmListBoxView* iV;
       
   675     void Close() { iV->DisableScrollToItem( EFalse ); }
       
   676     };
       
   677 
       
   678 // -----------------------------------------------------------------------------
       
   679 //
       
   680 // -----------------------------------------------------------------------------
       
   681 //
       
   682 void CMmListBox::UpdateScrollBarsL()
       
   683     {
       
   684     TBool redrawNeeded = HandleScrollbarVisibilityChangeL();
       
   685     if (ScrollBarFrame()->VerticalScrollBar()->IsVisible())
       
   686         {
       
   687         CMmListBoxView* view = static_cast<CMmListBoxView*>( View() );
       
   688         view->DisableScrollToItem( ETrue );
       
   689         TScrollToItemEnabler reverter = { view };
       
   690         CleanupClosePushL( reverter );
       
   691         CEikFormattedCellListBoxTypedef::UpdateScrollBarsL();
       
   692         CleanupStack::PopAndDestroy( &reverter );
       
   693         }
       
   694     iMmDrawer->TemplateLibrary()->SetScrollbarWidthL(
       
   695         ScrollBarFrame()->VerticalScrollBar()->Rect().Width() );
       
   696     FixViewForMirroredLayout();
       
   697     if ( redrawNeeded )
       
   698         {
       
   699         DrawNow();
       
   700         }
       
   701     }
       
   702 
       
   703 // -----------------------------------------------------------------------------
       
   704 //
       
   705 // -----------------------------------------------------------------------------
       
   706 //
       
   707 void CMmListBox::UpdateScrollBarsNoRedrawL()
       
   708     {
       
   709     HandleScrollbarVisibilityChangeL();
       
   710     if ( ScrollBarFrame()->VerticalScrollBar()->IsVisible() )
       
   711         {
       
   712         CMmListBoxView* view = static_cast<CMmListBoxView*>( View() );
       
   713         view->DisableScrollToItem( ETrue );
       
   714         TScrollToItemEnabler reverter = { view };
       
   715         CleanupClosePushL( reverter );
       
   716         CEikFormattedCellListBoxTypedef::UpdateScrollBarsL();
       
   717         CleanupStack::PopAndDestroy( &reverter );
       
   718         iMmDrawer->TemplateLibrary()->SetScrollbarWidthL(
       
   719                 ScrollBarFrame()->VerticalScrollBar()->Rect().Width() );
       
   720         }
       
   721     }
       
   722 
       
   723 // -----------------------------------------------------------------------------
       
   724 //
       
   725 // -----------------------------------------------------------------------------
       
   726 //
       
   727 void CMmListBox::SetMarqueeAdapter( CMmMarqueeAdapter* aAdapter )
       
   728   {
       
   729   iMarqueeAdapter = aAdapter;
       
   730   iMarqueeAdapter->SetControl( const_cast< CMmListBox *>(this) );
       
   731   }
       
   732 
       
   733 // -----------------------------------------------------------------------------
       
   734 //
       
   735 // -----------------------------------------------------------------------------
       
   736 //
       
   737 void CMmListBox::SetMarqueeDrawing( TBool aIsMarqueeBeingDrawn )
       
   738   {
       
   739   iMmDrawer->SetMarqueeDrawing( aIsMarqueeBeingDrawn );
       
   740   }
       
   741 
       
   742 // -----------------------------------------------------------------------------
       
   743 //
       
   744 // -----------------------------------------------------------------------------
       
   745 //
       
   746 void CMmListBox::HandleItemRemovalL()
       
   747   {
       
   748   CEikFormattedCellListBoxTypedef::HandleItemRemovalL();
       
   749     DrawNow();
       
   750     //avkon does not redraw the items for listbox when item is
       
   751     //removed. This needs to be forced here.
       
   752     UpdateScrollBarsL();
       
   753   }
       
   754 
       
   755 // -----------------------------------------------------------------------------
       
   756 // If a parent to the supplied control has its Gc set, this function will find
       
   757 // it and return it. (Copied from EIKLBX.CPP, needed by CMmListBox::Draw)
       
   758 // -----------------------------------------------------------------------------
       
   759 //
       
   760 LOCAL_C CWindowGc* ReplaceGcWithCustomGc( const CEikListBox* aListBox )
       
   761     {
       
   762     const CCoeControl* parent = aListBox;
       
   763     CWindowGc* customGc;
       
   764     while(parent)
       
   765         {
       
   766         customGc = parent->GetGc();
       
   767         if ( customGc )
       
   768             {
       
   769             CListItemDrawer* itemDrawer = aListBox->View()->ItemDrawer();
       
   770             CWindowGc* originalGc = itemDrawer->Gc();
       
   771             if ( customGc == originalGc )
       
   772             {
       
   773                 return NULL;
       
   774                 }
       
   775             else
       
   776                 {
       
   777                 itemDrawer->SetGc( customGc );
       
   778                 return originalGc;
       
   779                 }
       
   780             }
       
   781         parent = parent->Parent();
       
   782         }
       
   783     return NULL;
       
   784     }
       
   785 
       
   786 // -----------------------------------------------------------------------------
       
   787 //
       
   788 // -----------------------------------------------------------------------------
       
   789 //
       
   790 void CMmListBox::Draw(const TRect& aRect) const
       
   791     {
       
   792 //    if (!iResized)
       
   793 //        {
       
   794 //        return;
       
   795 //        }
       
   796 
       
   797     CWindowGc* gc = this->iItemDrawer->Gc();
       
   798 
       
   799     // If a parent has a custom gc, draw listbox using that gc
       
   800     CWindowGc* replacedGc = ReplaceGcWithCustomGc(
       
   801                                     static_cast<const CEikListBox*>( this ) );
       
   802 
       
   803     if (this->iModel->NumberOfItems() == 0)
       
   804         {
       
   805         this->iView->DrawEmptyList(this->Rect());
       
   806 
       
   807         if ( replacedGc )
       
   808             {
       
   809             // Stop using the custom gc
       
   810             this->iItemDrawer->SetGc( replacedGc );
       
   811             }
       
   812         return;
       
   813         }
       
   814 
       
   815 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   816     MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( gc );
       
   817 
       
   818     if ( transApi )
       
   819         {
       
   820         transApi->SetListType( MAknListBoxTfxInternal::EListBoxTypeMainPane );
       
   821         // ViewRect might have been moved to the right to prevent grid items
       
   822         // from overlapping the scrollbar in mirrored layout.
       
   823         // However, we still have to draw scrollbar background, thus the
       
   824         // rectangle object passed to MAknListBoxTfxInternal::BeginRedraw must
       
   825         // be placed at (0, 0) so that it covers the area where scrollbar is
       
   826         // drawn.
       
   827         TRect r( View()->ViewRect().Size() );
       
   828         transApi->BeginRedraw( MAknListBoxTfxInternal::EListView, r );
       
   829         }
       
   830 #endif //RD_UI_TRANSITION_EFFECTS_LIST
       
   831     if (!this->iView->RedrawDisabled())
       
   832         {
       
   833         MAknsControlContext *cc = AknsDrawUtils::ControlContext( this );
       
   834         if (!cc) cc = ItemDrawer()->FormattedCellData()->SkinBackgroundContext();
       
   835 
       
   836         if (gc)
       
   837             {
       
   838             TRect clientRect;
       
   839             this->RestoreClientRectFromViewRect(clientRect);
       
   840 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   841             if ( transApi )
       
   842                 {
       
   843                 transApi->StartDrawing( MAknListBoxTfxInternal::EListView );
       
   844                 }
       
   845 #endif //RD_UI_TRANSITION_EFFECTS_LIST
       
   846             gc->SetBrushColor(this->BackColor());
       
   847             AknsDrawUtils::BackgroundBetweenRects( AknsUtils::SkinInstance(), cc, this, *gc, clientRect, this->iView->ViewRect() );
       
   848             RedrawScrollbarBackground();
       
   849 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   850             if ( transApi )
       
   851                 {
       
   852                 transApi->StopDrawing();
       
   853         }
       
   854 #endif //RD_UI_TRANSITION_EFFECTS_LIST
       
   855             }
       
   856         }
       
   857     if ( this->iModel->NumberOfItems() )
       
   858         {
       
   859         // finally, draw the actual list
       
   860         this->iView->Draw(&aRect);
       
   861         }
       
   862 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   863     if ( transApi )
       
   864         {
       
   865         CMmListBoxView* view = static_cast<CMmListBoxView*>( View() );
       
   866         view->DisableScrollToItem( ETrue );
       
   867         transApi->EndViewRedraw( aRect );
       
   868         view->DisableScrollToItem( EFalse );
       
   869         }
       
   870 #endif //RD_UI_TRANSITION_EFFECTS_LIST
       
   871     if ( replacedGc )
       
   872         {
       
   873         // Stop using the custom gc
       
   874         this->iItemDrawer->SetGc( replacedGc );
       
   875         }
       
   876     }
       
   877 
       
   878 // -----------------------------------------------------------------------------
       
   879 //
       
   880 // -----------------------------------------------------------------------------
       
   881 //
       
   882 void CMmListBox::DrawView()
       
   883     {
       
   884     iDisableChildComponentDrawing = ETrue;
       
   885     DrawNow(Rect());
       
   886     iDisableChildComponentDrawing = EFalse;
       
   887     }
       
   888 
       
   889 // -----------------------------------------------------------------------------
       
   890 //
       
   891 // -----------------------------------------------------------------------------
       
   892 //
       
   893 void CMmListBox::SetVerticalItemOffset( TInt aOffset )
       
   894   {
       
   895   static_cast<CMmListBoxView*>( View() )->SetItemOffsetInPixels( aOffset );
       
   896   UpdateScrollBarThumbs();
       
   897   }
       
   898 
       
   899 // -----------------------------------------------------------------------------
       
   900 //
       
   901 // -----------------------------------------------------------------------------
       
   902 //
       
   903 TInt CMmListBox::VerticalItemOffset() const
       
   904   {
       
   905   return static_cast<CMmListBoxView*>( View() )->VerticalItemOffset();
       
   906   }
       
   907 
       
   908 // -----------------------------------------------------------------------------
       
   909 //
       
   910 // -----------------------------------------------------------------------------
       
   911 //
       
   912 void CMmListBox::SetItemHeight( TInt aItemHeight )
       
   913   {
       
   914   if ( aItemHeight != iItemHeight )
       
   915       {
       
   916       iItemHeight = aItemHeight;
       
   917       TRAP_IGNORE( UpdateScrollBarsNoRedrawL() );
       
   918       }
       
   919   }
       
   920 
       
   921 // -----------------------------------------------------------------------------
       
   922 //
       
   923 // -----------------------------------------------------------------------------
       
   924 //
       
   925 void CMmListBox::UpdateScrollBarThumbs()
       
   926   {
       
   927   CEikFormattedCellListBox::UpdateScrollBarThumbs();
       
   928   }
       
   929 
       
   930 // -----------------------------------------------------------------------------
       
   931 //
       
   932 // -----------------------------------------------------------------------------
       
   933 //
       
   934 TInt CMmListBox::CountComponentControls() const
       
   935     {
       
   936     TInt componentControls(0);
       
   937     if ( !iDisableChildComponentDrawing )
       
   938     {
       
   939         componentControls = CEikFormattedCellListBoxTypedef::CountComponentControls();
       
   940       }
       
   941     return componentControls;
       
   942     }
       
   943 // -----------------------------------------------------------------------------
       
   944 //
       
   945 // -----------------------------------------------------------------------------
       
   946 //
       
   947 void CMmListBox::SetDisableChildComponentDrawing( TBool aDisable )
       
   948     {
       
   949     iDisableChildComponentDrawing = aDisable;
       
   950     }
       
   951 
       
   952 // -----------------------------------------------------------------------------
       
   953 //
       
   954 // -----------------------------------------------------------------------------
       
   955 //
       
   956 void CMmListBox::HandleScrollEventL( CEikScrollBar* aScrollBar,
       
   957             TEikScrollEvent aEventType )
       
   958     {
       
   959     if ( aEventType == EEikScrollThumbDragVert && !iScrollbarThumbIsBeingDragged )
       
   960         {
       
   961         iScrollbarThumbIsBeingDragged = ETrue;
       
   962         static_cast<CMmListBoxItemDrawer*>(
       
   963                 View()->ItemDrawer() )->EnableCachedDataUse( ETrue );
       
   964         iRedrawTimer->Start( KScrollingRedrawInterval, KScrollingRedrawInterval,
       
   965                 TCallBack( &CMmListBox::RedrawTimerCallback, static_cast<TAny*>( this ) ) );
       
   966         }
       
   967     else if ( aEventType == EEikScrollThumbReleaseVert )
       
   968         {
       
   969         iScrollbarThumbIsBeingDragged = EFalse;
       
   970         static_cast<CMmListBoxItemDrawer*>(
       
   971                 View()->ItemDrawer() )->EnableCachedDataUse( EFalse );
       
   972         // The view will be redrawn with cache disabled when ProcessScrollEventL
       
   973         // calls the base class's HandleScrollEventL method -- no need to
       
   974         // explicitly redraw the view.
       
   975         iRedrawTimer->Cancel();
       
   976         }
       
   977 
       
   978     if ( !iScrollbarThumbIsBeingDragged )
       
   979         {
       
   980         ProcessScrollEventL( aScrollBar, aEventType );
       
   981         }
       
   982     else
       
   983         {
       
   984         __ASSERT_DEBUG( aEventType == EEikScrollThumbDragVert, User::Invariant() );
       
   985         ++iSkippedScrollbarEventsCount;
       
   986         }
       
   987     }
       
   988 
       
   989 // End of file