menufw/menufwui/mmwidgets/src/mmlistbox.cpp
branchRCL_3
changeset 34 5456b4e8b3a8
child 35 3321d3e205b6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/menufw/menufwui/mmwidgets/src/mmlistbox.cpp	Wed Sep 01 12:32:46 2010 +0100
@@ -0,0 +1,989 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <aknlists.h>
+#include <eikspmod.h>
+#include <eikclb.h>
+#include <eikfrlb.h>
+#include <eikslb.h>
+#include <AknUtils.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <aknlayoutscalable_apps.cdl.h>
+#include <layoutmetadata.cdl.h>
+
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+#include <aknlistboxtfxinternal.h>
+#include <akntransitionutils.h>
+#include <aknlistloadertfx.h>
+#endif
+
+#include "mmlistboxmodel.h"
+#include "mmlistbox.h"
+#include "mmlistboxview.h"
+#include "mmlistboxitemdrawer.h"
+#include "mmmarqueeadapter.h"
+#include "mmwidgetcontainer.h"
+#include "mmwidgetsconstants.h"
+#include "mmdraweranimator.h"
+#include "mmtemplatelibrary.h"
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMmListBox::CMmListBox() : AKNDOUBLELISTBOXNAME(R_LIST_PANE_LINES_AB_COLUMN)
+  {
+  // No implementation required
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMmListBox::~CMmListBox()
+  {
+  delete iRedrawTimer;
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMmListBox* CMmListBox::NewLC( const CCoeControl* aParent, TInt aFlags,
+    CMmTemplateLibrary* aTemplateLibrary )
+  {
+  CMmListBox* self = new (ELeave)CMmListBox();
+  CleanupStack::PushL(self);
+  self->ConstructL( aParent, aFlags, aTemplateLibrary );
+  return self;
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::SetListFlag( TInt aFlag )
+  {
+  iListBoxFlags = iListBoxFlags | aFlag;
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::ClearListFlag( TInt aFlag )
+  {
+  iListBoxFlags = iListBoxFlags & !aFlag;
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMmListBox* CMmListBox::NewL( const CCoeControl* aParent, TInt aFlags,
+    CMmTemplateLibrary* aTemplateLibrary )
+  {
+  CMmListBox* self = CMmListBox::NewLC( aParent, aFlags, aTemplateLibrary );
+  CleanupStack::Pop( self );
+  return self;
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::ConstructL( const CCoeControl* aParent, TInt aFlags,
+    CMmTemplateLibrary* aTemplateLibrary )
+  {
+  iDisableChildComponentDrawing = EFalse;
+  iModel = iMmModel = CMmListBoxModel::NewL();
+    CreateItemDrawerL( aTemplateLibrary );
+
+    EnableExtendedDrawingL();
+
+    iItemDrawer->SetDrawMark(EFalse);
+    CEikListBox::ConstructL(aParent,aFlags);
+    iMmDrawer->SetView( this );
+    iRedrawTimer = CPeriodic::NewL( EPriorityRealTime );
+  }
+
+// -----------------------------------------------------------------------------
+// Clearing ELeftDownInViewRect flag before invoking the base class
+// HandlePointerEventL method effectively prevents that method from doing most
+// of the things it would normally do in response to EButton1Down event.
+// This flag is explicitly cleared to achieve two things:
+// 1. Prevent kinetic scrolling (flick) in edit mode.
+// 2. Prevent highlight removal when popup menu is displayed.
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::HandlePointerEventInEditModeL(
+        const TPointerEvent& aPointerEvent )
+    {
+    CMmWidgetContainer* parent = static_cast<CMmWidgetContainer*>( Parent() );
+    if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
+        {
+        iButton1DownPos = aPointerEvent.iPosition;
+        }
+    else if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
+        {
+        TPoint dragDelta = iButton1DownPos - aPointerEvent.iPosition;
+        if ( Abs( dragDelta.iY ) > KDragTreshold || parent->LongTapInProgress() )
+            {
+            iListBoxFlags &= ~ELeftDownInViewRect;
+            }
+        }
+
+    TInt itemUnderPointerIndex = KErrNotFound;
+    if ( aPointerEvent.iType == TPointerEvent::EButton1Up ||
+            aPointerEvent.iType == TPointerEvent::EButton1Down )
+        {
+        TBool highlightWasVisible = parent->IsHighlightVisible();
+        CEikFormattedCellListBoxTypedef::HandlePointerEventL( aPointerEvent );
+        // Tricky: Do not allow the base class implementation of HandlePointerEventL
+        //         to remove the highlight on EButton1Up event when context menu
+        //         is displayed for an item
+        if ( aPointerEvent.iType == TPointerEvent::EButton1Up &&
+                highlightWasVisible && parent->LongTapInProgress()
+                && !parent->IsHighlightVisible() )
+            {
+            ItemDrawer()->ClearFlags( CListItemDrawer::ESingleClickDisabledHighlight );
+            }
+        }
+    else if ( View()->XYPosToItemIndex(
+            aPointerEvent.iPosition, itemUnderPointerIndex ) )
+        {
+        TInt currentItemIndex = CurrentItemIndex();
+        if ( currentItemIndex != itemUnderPointerIndex )
+            {
+            View()->SetCurrentItemIndex( itemUnderPointerIndex );
+            // remove hightlight from the previously highlighted item
+            }
+        }
+    HandleScrollingInEditMode( aPointerEvent );
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::HandleScrollingInEditMode( const TPointerEvent& aPointerEvent )
+    {
+    if ( aPointerEvent.iType == TPointerEvent::EDrag
+            || aPointerEvent.iType == TPointerEvent::EButtonRepeat )
+        {
+        TInt nextScrollDelay = ScrollIfNeeded( aPointerEvent );
+        if ( nextScrollDelay )
+            {
+            TRect ignoreDragRect(
+                TPoint(aPointerEvent.iParentPosition.iX - MmEffects::KDragIgnoreRectValue,
+                    aPointerEvent.iParentPosition.iY - MmEffects::KDragIgnoreRectValue),
+                TPoint(aPointerEvent.iParentPosition.iX + MmEffects::KDragIgnoreRectValue,
+                    aPointerEvent.iParentPosition.iY + MmEffects::KDragIgnoreRectValue));
+
+            Window().CancelPointerRepeatEventRequest();
+            Window().RequestPointerRepeatEvent( nextScrollDelay, ignoreDragRect );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool CMmListBox::IsPointerInTopScrollingThreshold(
+            const TPointerEvent& aPointerEvent ) const
+    {
+    TInt topScrollingTreshold = Rect().iTl.iY
+        + ( MmListBox::KFocusScrollingThreshold
+            * TReal( View()->ItemSize().iHeight ) );
+
+    return ( aPointerEvent.iPosition.iY < topScrollingTreshold );
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool CMmListBox::IsPointerInBottomScrollingThreshold(
+            const TPointerEvent& aPointerEvent ) const
+    {
+    TInt bottomScrollingTreshold = Rect().iBr.iY
+        - ( MmListBox::KFocusScrollingThreshold
+            * TReal( View()->ItemSize().iHeight ) );
+
+    return ( aPointerEvent.iPosition.iY > bottomScrollingTreshold );
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBox::ScrollIfNeeded( const TPointerEvent& aPointerEvent )
+    {
+    TInt nextScrollDelay = 0;
+
+  TBool readyForScrolling =
+      iMmDrawer->GetAnimator()->IsReadyForNewAnimation()
+          && iMmDrawer->GetFloatingItemCount() != 0;
+
+  if ( IsPointerInTopScrollingThreshold( aPointerEvent ) )
+    {
+    // scroll up by one row
+    TInt newCurrentItemIndex = CurrentItemIndex() - 1;
+
+    if ( newCurrentItemIndex >= 0 )
+      {
+      nextScrollDelay = MmEffects::KEditModeScrollingDelayFactor *
+        Max( 1, aPointerEvent.iPosition.iY - Rect().iTl.iY );
+      if (readyForScrolling)
+        {
+        View()->VScrollTo( View()->CalcNewTopItemIndexSoItemIsVisible(
+                        newCurrentItemIndex ) );
+                View()->SetCurrentItemIndex( newCurrentItemIndex );
+                UpdateScrollBarThumbs();
+        }
+      }
+    }
+  else if ( IsPointerInBottomScrollingThreshold( aPointerEvent) )
+    {
+    // scroll down by one row
+    TInt lastItemIndex = iModel->NumberOfItems() - 1;
+    TInt newCurrentItemIndex = CurrentItemIndex() + 1;
+
+
+    if ( newCurrentItemIndex <= lastItemIndex )
+      {
+      nextScrollDelay = MmEffects::KEditModeScrollingDelayFactor *
+        Max( 1, Rect().iBr.iY - aPointerEvent.iPosition.iY );
+
+      if (readyForScrolling)
+        {
+        View()->VScrollTo( View()->CalcNewTopItemIndexSoItemIsVisible(
+            newCurrentItemIndex ) );
+        View()->SetCurrentItemIndex( newCurrentItemIndex );
+                UpdateScrollBarThumbs();
+        }
+      }
+    }
+
+    return nextScrollDelay;
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+    {
+//    if ( aPointerEvent.iType == TPointerEvent::EButton1Down &&
+//            iMmDrawer->CachedDataUseIsEnabled() )
+//        {
+//        // Touching the screen stops flick but avkon does not send us
+//        // MEikListBoxObserver::EEventFlickStopped event in such case.
+//        // Thus this little hack:
+//        iMmDrawer->EnableCachedDataUse( EFalse );
+//        DrawView();
+//        }
+
+    CMmWidgetContainer* parent = static_cast<CMmWidgetContainer*>( Parent() );
+
+    if ( parent->IsEditMode() )
+        {
+        HandlePointerEventInEditModeL( aPointerEvent );
+        }
+    else
+      {
+        CEikFormattedCellListBoxTypedef::HandlePointerEventL( aPointerEvent );
+      }
+
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::FixViewForMirroredLayout()
+    {
+    TInt scrollbarWidth =
+            ScrollBarFrame()->VerticalScrollBar()->Rect().Width();
+    TRect r( View()->ViewRect() );
+    TInt currentShift = r.iTl.iX;
+    TBool scrollbarVisible = ScrollBarFrame()->VerticalScrollBar()->IsVisible();
+    TBool layoutMirrored = AknLayoutUtils::LayoutMirrored();
+
+    if ( layoutMirrored && scrollbarVisible && currentShift != scrollbarWidth )
+        {
+        // shift view rect to the right
+        r.Move( scrollbarWidth - currentShift, 0 );
+        View()->SetViewRect( r );
+        }
+    else if ( ( !layoutMirrored || !scrollbarVisible ) && currentShift != 0 )
+        {
+        // restore view rect to its normal position
+        r.Move( -currentShift, 0 );
+        View()->SetViewRect( r );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::RedrawScrollbarBackground() const
+    {
+    TRect viewRect( View()->ViewRect() );
+    if ( viewRect.iTl.iX > 0 )
+        {
+        TRect scrollbarRect( TPoint( 0, 0 ),
+                TSize( viewRect.iTl.iX, viewRect.Height() ) );
+
+        CWindowGc* gc = iItemDrawer->Gc();
+        CMmListBoxItemDrawer* itemDrawer =
+                static_cast<CMmListBoxItemDrawer*>( iItemDrawer );
+        MAknsSkinInstance *skin = AknsUtils::SkinInstance();
+        CCoeControl* control = itemDrawer->FormattedCellData()->Control();
+        MAknsControlContext *cc = AknsDrawUtils::ControlContext( control );
+        if( gc )
+            {
+            if ( control )
+                {
+                AknsDrawUtils::Background( skin, cc, control, *gc, scrollbarRect );
+                }
+            else
+                {
+                gc->SetBrushColor( BackColor() );
+                gc->Clear( scrollbarRect );
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::ProcessScrollEventL( CEikScrollBar* aScrollBar,
+            TEikScrollEvent aEventType )
+    {
+    CEikFormattedCellListBoxTypedef::HandleScrollEventL(
+            aScrollBar, aEventType );
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::HandleRedrawTimerEventL()
+    {
+    if ( iSkippedScrollbarEventsCount )
+        {
+        ProcessScrollEventL( ScrollBarFrame()->VerticalScrollBar(),
+                EEikScrollThumbDragVert );
+        }
+    iSkippedScrollbarEventsCount = 0;
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBox::RedrawTimerCallback( TAny* aPtr )
+    {
+    CMmListBox* self = static_cast<CMmListBox*>( aPtr );
+    TRAP_IGNORE( self->HandleRedrawTimerEventL() );
+    // Do not bother returning a meaningful error code, CPeriodic will ignore it
+    // anyway.
+    return 0;
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TKeyResponse CMmListBox::OfferKeyEventL(
+        const TKeyEvent& aKeyEvent,TEventCode aType )
+    {
+    TInt itemIndex = CurrentItemIndex();
+    TInt previousItemIndex = CurrentItemIndex();
+    TKeyResponse ret = CEikFormattedCellListBoxTypedef::OfferKeyEventL(
+        aKeyEvent, aType );
+    TInt currentItemIndex = CurrentItemIndex();
+
+    TInt itemY = View()->ItemPos( currentItemIndex ).iY
+               + View()->ItemSize( currentItemIndex ).iHeight;
+
+    if ( currentItemIndex == BottomItemIndex()
+        && currentItemIndex != previousItemIndex
+        && itemY > View()->ViewRect().iBr.iY )
+      {
+      if( aType == EEventKey )
+        {
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+        MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal(
+            View()->ItemDrawer()->Gc() );
+        TBool effects = transApi && !transApi->EffectsDisabled();
+        if ( effects )
+          {
+          transApi->SetMoveType( MAknListBoxTfxInternal::EListScrollDown );
+          }
+#endif
+      iView->VScrollTo(
+        iView->CalcNewTopItemIndexSoItemIsVisible( currentItemIndex ) );
+
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+      if ( effects )
+        {
+        transApi->Draw( Rect() );
+        }
+#endif
+      }
+      SetCurrentItemIndex( currentItemIndex );
+      }
+
+    RedrawIfNecessary( itemIndex, CurrentItemIndex());
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool CMmListBox::RedrawIfNecessary( TInt aPreviousCurrent, TInt aCurrent )
+    {
+    TBool redrawConsumed( EFalse );
+    if( aCurrent == KErrNotFound )
+        {
+        return redrawConsumed;
+        }
+
+    CMmListBoxView * view = static_cast<CMmListBoxView *>(iView);
+    TInt differenceIndex = Abs( aPreviousCurrent - aCurrent );
+    if ( aPreviousCurrent == KErrNotFound  || differenceIndex == 0 )
+        {
+        //TODO: It should be checked if this is really necessary
+        view->RedrawBackground();
+        return redrawConsumed;
+        }
+
+    TInt sizePrevBefore = iMmDrawer->GetItemHeight(aPreviousCurrent, ETrue);
+    TInt sizeCurBefore = iMmDrawer->GetItemHeight(aCurrent, EFalse);
+    TInt sizePrevAfter = iMmDrawer->GetItemHeight(aPreviousCurrent, EFalse);
+    TInt sizeCurAfter = iMmDrawer->GetItemHeight(aCurrent, ETrue);
+
+    if ( ( sizePrevBefore == sizePrevAfter ) && (sizeCurBefore == sizeCurAfter) )
+        {
+        return redrawConsumed;
+        }
+     else
+        {
+        TInt sizeAllBefore = sizePrevBefore + sizePrevAfter;
+        TInt sizeAllAfter = sizeCurBefore + sizeCurAfter;
+
+        TInt lastPotentialItemIndex = Min( iModel->NumberOfItems(),
+                iView->TopItemIndex() + iView->NumberOfItemsThatFitInRect(
+                        iView->ViewRect() ) );
+        TInt redrawIndex = lastPotentialItemIndex;
+
+        if ( differenceIndex == 1 )
+            {
+            if( sizeAllBefore != sizeAllAfter )
+              {
+                redrawIndex = Min( aPreviousCurrent, aCurrent );
+              }
+            else
+              {
+              return redrawConsumed;
+              }
+            }
+        else if ( differenceIndex > 1 && sizeAllBefore == sizeAllAfter  )
+            {
+            redrawIndex = Min( aPreviousCurrent, aCurrent );
+            lastPotentialItemIndex = Max( aPreviousCurrent, aCurrent );
+            }
+        else if ( differenceIndex > 1 )
+            {
+            redrawIndex = Min( aPreviousCurrent, aCurrent );
+            }
+
+        if (redrawIndex < iView->TopItemIndex())
+            redrawIndex = iView->TopItemIndex();
+
+        if (lastPotentialItemIndex > iView->BottomItemIndex())
+            lastPotentialItemIndex = iView->BottomItemIndex();
+
+        if ( aPreviousCurrent < TopItemIndex() )
+          {
+          lastPotentialItemIndex = BottomItemIndex() ;
+          }
+        else if ( BottomItemIndex() < aPreviousCurrent )
+          {
+          lastPotentialItemIndex = BottomItemIndex() + 1;
+          }
+
+        while ( redrawIndex < lastPotentialItemIndex +1 )
+            {
+            view->DrawSingleItem( redrawIndex++ );
+            redrawConsumed = ETrue;
+            }
+
+        view->RedrawBackground();
+        }
+    return redrawConsumed;
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::CreateItemDrawerL( CMmTemplateLibrary* aTemplateLibrary )
+    {
+    CFormattedCellListBoxData* cellData=CFormattedCellListBoxData::NewL();
+    CleanupStack::PushL( cellData );
+    iItemDrawer = iMmDrawer = CMmListBoxItemDrawer::NewL( MmModel(),
+            iEikonEnv->NormalFont(), cellData, EListbox, aTemplateLibrary );
+    CleanupStack::Pop( cellData );
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMmListBoxModel* CMmListBox::MmModel()
+  {
+  return iMmModel;
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::SetMmModel( CMmListBoxModel* aMmModel )
+  {
+  if ( iMmModel != aMmModel )
+    {
+    delete iMmModel;
+    iMmModel = aMmModel;
+    }
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CListBoxView* CMmListBox::MakeViewClassInstanceL()
+    {
+    return CMmListBoxView::NewL();
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBox::AdjustRectHeightToWholeNumberOfItems(TRect& /*aRect*/) const
+    {
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::SetItemDrawerAndViewBgContext (CAknsBasicBackgroundControlContext * aBgContext)
+  {
+  iMmDrawer->SetBgContext (aBgContext);
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool CMmListBox::HandleScrollbarVisibilityChangeL()
+  {
+  TBool ret = EFalse;
+  if ( AllItemsFitInViewRect() )
+    {
+    if ( ScrollBarFrame()->VerticalScrollBar()->IsVisible()
+            || iMmDrawer->TemplateLibrary()->GetScrollbarVisibility() )
+      {
+      ScrollBarFrame()->VerticalScrollBar()->MakeVisible( EFalse );
+      iMmDrawer->SetScrollbarVisibilityL( EFalse );
+
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+      MAknListBoxTfxInternal *trans = CAknListLoader::TfxApiInternal( ItemDrawer()->Gc() );
+        if ( trans )
+          {
+          trans->Remove( MAknListBoxTfxInternal::EListEverything );
+          }
+#endif
+
+      ret = ETrue; //redraw is needed
+      }
+    }
+  else if ( !ScrollBarFrame()->VerticalScrollBar()->IsVisible()
+            || !iMmDrawer->TemplateLibrary()->GetScrollbarVisibility() )
+    {
+    ScrollBarFrame()->VerticalScrollBar()->MakeVisible( ETrue );
+    iMmDrawer->SetScrollbarVisibilityL( ETrue );
+    ret = ETrue; //redraw is needed
+    }
+  return ret;
+  }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool CMmListBox::AllItemsFitInViewRect()
+  {
+  CMmListBoxView* view = static_cast< CMmListBoxView* >(iView);
+  TInt totalHeight = view->GetTotalHeight( view->TopItemIndex(), view->BottomItemIndex());
+  if ( view->TopItemIndex() == 0 && iMmModel->NumberOfItems() <= view->BottomItemIndex() + 1
+          && totalHeight <= iView->ViewRect().Height() )
+    {
+    return ETrue;
+    }
+  else
+    {
+    return EFalse;
+    }
+  }
+
+/**
+ * Helper class whose only purpose is to ensure that
+ * ScrollToItem method will be always re-enabled.
+ */
+struct TScrollToItemEnabler
+    {
+    CMmListBoxView* iV;
+    void Close() { iV->DisableScrollToItem( EFalse ); }
+    };
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::UpdateScrollBarsL()
+    {
+    TBool redrawNeeded = HandleScrollbarVisibilityChangeL();
+    if (ScrollBarFrame()->VerticalScrollBar()->IsVisible())
+        {
+        CMmListBoxView* view = static_cast<CMmListBoxView*>( View() );
+        view->DisableScrollToItem( ETrue );
+        TScrollToItemEnabler reverter = { view };
+        CleanupClosePushL( reverter );
+        CEikFormattedCellListBoxTypedef::UpdateScrollBarsL();
+        CleanupStack::PopAndDestroy( &reverter );
+        }
+    iMmDrawer->TemplateLibrary()->SetScrollbarWidthL(
+        ScrollBarFrame()->VerticalScrollBar()->Rect().Width() );
+    FixViewForMirroredLayout();
+    if ( redrawNeeded )
+        {
+        DrawNow();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::UpdateScrollBarsNoRedrawL()
+    {
+    HandleScrollbarVisibilityChangeL();
+    if ( ScrollBarFrame()->VerticalScrollBar()->IsVisible() )
+        {
+        CMmListBoxView* view = static_cast<CMmListBoxView*>( View() );
+        view->DisableScrollToItem( ETrue );
+        TScrollToItemEnabler reverter = { view };
+        CleanupClosePushL( reverter );
+        CEikFormattedCellListBoxTypedef::UpdateScrollBarsL();
+        CleanupStack::PopAndDestroy( &reverter );
+        iMmDrawer->TemplateLibrary()->SetScrollbarWidthL(
+                ScrollBarFrame()->VerticalScrollBar()->Rect().Width() );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::SetMarqueeAdapter( CMmMarqueeAdapter* aAdapter )
+  {
+  iMarqueeAdapter = aAdapter;
+  iMarqueeAdapter->SetControl( const_cast< CMmListBox *>(this) );
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::SetMarqueeDrawing( TBool aIsMarqueeBeingDrawn )
+  {
+  iMmDrawer->SetMarqueeDrawing( aIsMarqueeBeingDrawn );
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::HandleItemRemovalL()
+  {
+  CEikFormattedCellListBoxTypedef::HandleItemRemovalL();
+    DrawNow();
+    //avkon does not redraw the items for listbox when item is
+    //removed. This needs to be forced here.
+    UpdateScrollBarsL();
+  }
+
+// -----------------------------------------------------------------------------
+// If a parent to the supplied control has its Gc set, this function will find
+// it and return it. (Copied from EIKLBX.CPP, needed by CMmListBox::Draw)
+// -----------------------------------------------------------------------------
+//
+LOCAL_C CWindowGc* ReplaceGcWithCustomGc( const CEikListBox* aListBox )
+    {
+    const CCoeControl* parent = aListBox;
+    CWindowGc* customGc;
+    while(parent)
+        {
+        customGc = parent->GetGc();
+        if ( customGc )
+            {
+            CListItemDrawer* itemDrawer = aListBox->View()->ItemDrawer();
+            CWindowGc* originalGc = itemDrawer->Gc();
+            if ( customGc == originalGc )
+            {
+                return NULL;
+                }
+            else
+                {
+                itemDrawer->SetGc( customGc );
+                return originalGc;
+                }
+            }
+        parent = parent->Parent();
+        }
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::Draw(const TRect& aRect) const
+    {
+//    if (!iResized)
+//        {
+//        return;
+//        }
+
+    CWindowGc* gc = this->iItemDrawer->Gc();
+
+    // If a parent has a custom gc, draw listbox using that gc
+    CWindowGc* replacedGc = ReplaceGcWithCustomGc(
+                                    static_cast<const CEikListBox*>( this ) );
+
+    if (this->iModel->NumberOfItems() == 0)
+        {
+        this->iView->DrawEmptyList(this->Rect());
+
+        if ( replacedGc )
+            {
+            // Stop using the custom gc
+            this->iItemDrawer->SetGc( replacedGc );
+            }
+        return;
+        }
+
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+    MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( gc );
+
+    if ( transApi )
+        {
+        transApi->SetListType( MAknListBoxTfxInternal::EListBoxTypeMainPane );
+        // ViewRect might have been moved to the right to prevent grid items
+        // from overlapping the scrollbar in mirrored layout.
+        // However, we still have to draw scrollbar background, thus the
+        // rectangle object passed to MAknListBoxTfxInternal::BeginRedraw must
+        // be placed at (0, 0) so that it covers the area where scrollbar is
+        // drawn.
+        TRect r( View()->ViewRect().Size() );
+        transApi->BeginRedraw( MAknListBoxTfxInternal::EListView, r );
+        }
+#endif //RD_UI_TRANSITION_EFFECTS_LIST
+    if (!this->iView->RedrawDisabled())
+        {
+        MAknsControlContext *cc = AknsDrawUtils::ControlContext( this );
+        if (!cc) cc = ItemDrawer()->FormattedCellData()->SkinBackgroundContext();
+
+        if (gc)
+            {
+            TRect clientRect;
+            this->RestoreClientRectFromViewRect(clientRect);
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+            if ( transApi )
+                {
+                transApi->StartDrawing( MAknListBoxTfxInternal::EListView );
+                }
+#endif //RD_UI_TRANSITION_EFFECTS_LIST
+            gc->SetBrushColor(this->BackColor());
+            AknsDrawUtils::BackgroundBetweenRects( AknsUtils::SkinInstance(), cc, this, *gc, clientRect, this->iView->ViewRect() );
+            RedrawScrollbarBackground();
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+            if ( transApi )
+                {
+                transApi->StopDrawing();
+        }
+#endif //RD_UI_TRANSITION_EFFECTS_LIST
+            }
+        }
+    if ( this->iModel->NumberOfItems() )
+        {
+        // finally, draw the actual list
+        this->iView->Draw(&aRect);
+        }
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+    if ( transApi )
+        {
+        CMmListBoxView* view = static_cast<CMmListBoxView*>( View() );
+        view->DisableScrollToItem( ETrue );
+        transApi->EndViewRedraw( aRect );
+        view->DisableScrollToItem( EFalse );
+        }
+#endif //RD_UI_TRANSITION_EFFECTS_LIST
+    if ( replacedGc )
+        {
+        // Stop using the custom gc
+        this->iItemDrawer->SetGc( replacedGc );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::DrawView()
+    {
+    iDisableChildComponentDrawing = ETrue;
+    DrawNow(Rect());
+    iDisableChildComponentDrawing = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::SetVerticalItemOffset( TInt aOffset )
+  {
+  static_cast<CMmListBoxView*>( View() )->SetItemOffsetInPixels( aOffset );
+  UpdateScrollBarThumbs();
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBox::VerticalItemOffset() const
+  {
+  return static_cast<CMmListBoxView*>( View() )->VerticalItemOffset();
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::SetItemHeight( TInt aItemHeight )
+  {
+  if ( aItemHeight != iItemHeight )
+      {
+      iItemHeight = aItemHeight;
+      TRAP_IGNORE( UpdateScrollBarsNoRedrawL() );
+      }
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::UpdateScrollBarThumbs()
+  {
+  CEikFormattedCellListBox::UpdateScrollBarThumbs();
+  }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBox::CountComponentControls() const
+    {
+    TInt componentControls(0);
+    if ( !iDisableChildComponentDrawing )
+    {
+        componentControls = CEikFormattedCellListBoxTypedef::CountComponentControls();
+      }
+    return componentControls;
+    }
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::SetDisableChildComponentDrawing( TBool aDisable )
+    {
+    iDisableChildComponentDrawing = aDisable;
+    }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBox::HandleScrollEventL( CEikScrollBar* aScrollBar,
+            TEikScrollEvent aEventType )
+    {
+    if ( aEventType == EEikScrollThumbDragVert && !iScrollbarThumbIsBeingDragged )
+        {
+        iScrollbarThumbIsBeingDragged = ETrue;
+        static_cast<CMmListBoxItemDrawer*>(
+                View()->ItemDrawer() )->EnableCachedDataUse( ETrue );
+        iRedrawTimer->Start( KScrollingRedrawInterval, KScrollingRedrawInterval,
+                TCallBack( &CMmListBox::RedrawTimerCallback, static_cast<TAny*>( this ) ) );
+        }
+    else if ( aEventType == EEikScrollThumbReleaseVert )
+        {
+        iScrollbarThumbIsBeingDragged = EFalse;
+        static_cast<CMmListBoxItemDrawer*>(
+                View()->ItemDrawer() )->EnableCachedDataUse( EFalse );
+        // The view will be redrawn with cache disabled when ProcessScrollEventL
+        // calls the base class's HandleScrollEventL method -- no need to
+        // explicitly redraw the view.
+        iRedrawTimer->Cancel();
+        }
+
+    if ( !iScrollbarThumbIsBeingDragged )
+        {
+        ProcessScrollEventL( aScrollBar, aEventType );
+        }
+    else
+        {
+        __ASSERT_DEBUG( aEventType == EEikScrollThumbDragVert, User::Invariant() );
+        ++iSkippedScrollbarEventsCount;
+        }
+    }
+
+// End of file