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