--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/menufw/menufwui/mmwidgets/src/mmlistboxview.cpp Thu Dec 17 08:40:49 2009 +0200
@@ -0,0 +1,660 @@
+/*
+* 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:
+ * Version : %version: MM_49 % << Don't touch! Updated by Synergy at check-out.
+ *
+*/
+
+
+
+#include "mmlistboxview.h"
+#include "mmlistbox.h"
+#include "mmlistboxitemdrawer.h"
+#include "mmlistboxmodel.h"
+#include "hnsuitemodel.h"
+#include "hnitemsorder.h"
+#include <eikfrlb.h>
+#include <AknUtils.h>
+#include <eikfrlbd.h>
+#include <eikspmod.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <AknsDrawUtils.h>
+
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+#include <aknlistboxtfx.h>
+#include <aknlistboxtfxinternal.h>
+#include <akntransitionutils.h>
+#include <aknlistloadertfx.h>
+#endif
+
+CMmListBoxView::CMmListBoxView ()
+ {
+ // No implementation required
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMmListBoxView::~CMmListBoxView ()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMmListBoxView* CMmListBoxView::NewLC ()
+ {
+ CMmListBoxView* self = new (ELeave)CMmListBoxView();
+ CleanupStack::PushL (self);
+ self->ConstructL ();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMmListBoxView* CMmListBoxView::NewL ()
+ {
+ CMmListBoxView* self=CMmListBoxView::NewLC ();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::ConstructL ()
+ {
+ iScrollbarIsVisible = ETrue;
+ iPreviouslyDrawnCurrentItemIndex = KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::UpdateAverageItemHeight ()
+ {
+ TInt count( iModel->NumberOfItems() );
+ if ( !count )
+ {
+ SetItemHeight( 2 );
+ }
+ else
+ {
+ TInt totalHeight = GetTotalHeight( 0, count - 1 );
+ TInt averageItemHeight = totalHeight / count;
+ if ( totalHeight % count )
+ {
+ ++averageItemHeight;
+ // this ensures that it is always possible to
+ // scroll to the very bottom of the view by
+ // using scrollbar.
+ }
+ SetItemHeight( averageItemHeight );
+ }
+ }
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBoxView::GetTotalHeight (const TInt aStartIndex, TInt aEndIndex) const
+ {
+ TInt totalHeight = 0;
+
+ if ( aEndIndex >= 0)
+ {
+ TInt itemCount = iModel->NumberOfItems ();
+ aEndIndex = (aEndIndex >= itemCount ) ? itemCount-1 : aEndIndex;
+ CMmListBoxItemDrawer* drawer= STATIC_CAST( CMmListBoxItemDrawer*, iItemDrawer);
+ for (TInt i(aStartIndex); i <= aEndIndex; i++)
+ {
+ totalHeight += drawer->GetItemHeight (i, CurrentItemIndex () == i);
+ }
+ }
+
+ return totalHeight;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBoxView::GetLastIndexInHeight (const TInt aStartIndex, TInt aHeight) const
+ {
+ TInt i = aStartIndex;
+ TInt totalHeight = 0;
+
+ TInt itemCount(iModel->NumberOfItems () );
+ CMmListBoxItemDrawer* drawer= STATIC_CAST( CMmListBoxItemDrawer*, iItemDrawer);
+
+ for (; (i > -1) && (i < itemCount); i++)
+ {
+ totalHeight += drawer->GetItemHeight (i, CurrentItemIndex () == i);
+ if ( totalHeight > aHeight)
+ break;
+ }
+
+ TInt ret(i - aStartIndex);
+
+ if ( !AknLayoutUtils::PenEnabled() && totalHeight > aHeight )
+ {
+ ret--; // exclude partial item
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBoxView::NumberOfItemsThatFitInRect(const TRect& aRect) const
+ {
+ return GetNumberOfItemsThatFitInRect( aRect, EFalse );
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBoxView::GetNumberOfItemsThatFitInRect (const TRect& aRect,
+ TBool aIncludePartialItem ) const
+ {
+ TInt i = iTopItemIndex;
+ TInt totalHeight = iVerticalOffset;
+
+ TInt itemCount( iModel->NumberOfItems () );
+ CMmListBoxItemDrawer* drawer= STATIC_CAST( CMmListBoxItemDrawer*, iItemDrawer);
+ while (totalHeight < aRect.Height ())
+ {
+ totalHeight += ((i > -1) && (i < itemCount )) ? drawer->GetItemHeight (
+ i, CurrentItemIndex () == i) : iItemHeight;
+ ++i;
+ }
+
+ TInt ret(i - iTopItemIndex);
+
+ if ( !AknLayoutUtils::PenEnabled() && !aIncludePartialItem && totalHeight > aRect.Height() )
+ {
+ ret--; // exclude partial item
+ }
+
+ return ret;
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::CalcBottomItemIndex ()
+ {
+
+ TInt numberOfVisibleItems = NumberOfItemsThatFitInRect( iViewRect );
+ iBottomItemIndex = Min( iTopItemIndex + numberOfVisibleItems - 1,
+ iModel->NumberOfItems() );
+
+ // The next piece of code removes filtering from find box when
+ // new list items are added.
+ if ( Flags () & CListBoxView::EItemCountModified)
+ {
+ CAknFilteredTextListBoxModel *model= STATIC_CAST(CAknFilteredTextListBoxModel*,iModel);
+ CAknListBoxFilterItems *filter = model ? model->Filter () : 0;
+ if ( filter)
+ {
+ TRAP_IGNORE(filter->ResetFilteringL());
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::Draw (const TRect* aClipRect) const
+ {
+ TBool drawingInitiated(EFalse);
+ if ( CAknEnv::Static()->TransparencyEnabled() &&
+ iWin && iWin->GetDrawRect() == TRect::EUninitialized )
+ {
+ TRect a(ViewRect());
+ if (!aClipRect || *aClipRect == TRect(0,0,0,0) )
+ {
+ aClipRect = &a;
+ }
+ drawingInitiated=ETrue;
+ iWin->Invalidate( *aClipRect );
+ iWin->BeginRedraw( *aClipRect );
+ }
+
+ DoDraw(aClipRect);
+
+ CMmListBoxItemDrawer* itemDrawer =
+ static_cast<CMmListBoxItemDrawer*>(iItemDrawer );
+ if (aClipRect)
+ {
+ TRect rect(*aClipRect);
+ rect.iTl.iY = ItemPos( BottomItemIndex() ).iY + ItemSize( BottomItemIndex() ).iHeight;
+
+// iGc->SetClippingRect( rect );
+// removed to prevent non-redraw drawing. Was present to prevent out of view drawing when effects are on.
+// could be removed because effects were disabled at some point in edit mode to enhance performance.
+ itemDrawer->DrawFloatingItems( rect );
+// iGc->CancelClippingRect();
+ }
+
+ if ( CAknEnv::Static()->TransparencyEnabled() &&
+ iWin && drawingInitiated )
+ {
+ drawingInitiated = EFalse;
+ iWin->EndRedraw( );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::DoDraw(const TRect* aClipRect) const
+ {
+ CMmListBoxView* view= CONST_CAST( CMmListBoxView*, this );
+ view->UpdateAverageItemHeight ();
+
+ CMmListBoxModel* model = static_cast< CMmListBoxModel* > ( iModel );
+ if ( model && model->GetSuiteModel()
+ && !model->GetSuiteModel()->GetItemsOrder()->IsSuiteReadyToShow() )
+ {
+ return;
+ }
+
+ if ( RedrawDisabled () || !IsVisible () )
+ {
+ return;
+ }
+
+ TInt i = iTopItemIndex;
+ CMmListBoxItemDrawer* itemDrawer =
+ static_cast<CMmListBoxItemDrawer*>(iItemDrawer );
+ MAknsSkinInstance *skin = AknsUtils::SkinInstance ();
+ CCoeControl* control = itemDrawer->FormattedCellData()->Control ();
+ MAknsControlContext *cc = AknsDrawUtils::ControlContext (control);
+
+ if ( !cc)
+ {
+ cc = itemDrawer->FormattedCellData()->SkinBackgroundContext ();
+ }
+
+ itemDrawer->SetTopItemIndex (iTopItemIndex);
+
+ if ( iModel->NumberOfItems () > 0)
+ {
+ TBool drawingInitiated = ETrue;
+ if ( CAknEnv::Static()->TransparencyEnabled () )
+ {
+ if ( iWin && iWin->GetDrawRect () == TRect::EUninitialized)
+ {
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ MAknListBoxTfxInternal* transApi =
+ CAknListLoader::TfxApiInternal( iGc );
+ drawingInitiated = transApi && !transApi->EffectsDisabled();
+#else
+ drawingInitiated = EFalse;
+#endif
+ }
+
+ if ( !drawingInitiated)
+ {
+ iWin->Invalidate ( *aClipRect);
+ iWin->BeginRedraw ( *aClipRect);
+ }
+ }
+
+ TInt lastPotentialItemIndex = Min (iModel->NumberOfItems (),
+ iTopItemIndex + GetNumberOfItemsThatFitInRect( ViewRect (), ETrue ) );
+ while (i < lastPotentialItemIndex)
+ {
+ DrawItem(i++);
+ }
+
+ RedrawBackground();
+
+ if ( CAknEnv::Static()->TransparencyEnabled () && !drawingInitiated)
+ {
+ iWin->EndRedraw ();
+ }
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::DrawItem (TInt aItemIndex) const
+ {
+ CMmListBoxItemDrawer* itemDrawer= STATIC_CAST( CMmListBoxItemDrawer*, iItemDrawer );
+ TBool currentChanged( CurrentItemIndex() != iPreviouslyDrawnCurrentItemIndex );
+ TBool redrawConsumed(EFalse);
+ if ( currentChanged )
+ {
+ CMmListBoxView* view= CONST_CAST( CMmListBoxView*, this );
+ redrawConsumed =
+ static_cast<CMmListBox*> (itemDrawer->Widget())->RedrawIfNecessary(
+ iPreviouslyDrawnCurrentItemIndex,
+ CurrentItemIndex());
+ view->SetPreviouslyDrawnCurrentItemIndex( CurrentItemIndex() );
+ }
+
+ if ( !redrawConsumed )
+ {
+ DrawSingleItem ( aItemIndex );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TSize CMmListBoxView::ItemSize (TInt aItemIndex) const
+ {
+ CMmListBoxView* view= CONST_CAST( CMmListBoxView*, this );
+ view->UpdateAverageItemHeight ();
+
+ CMmListBoxItemDrawer* itemDrawer= STATIC_CAST( CMmListBoxItemDrawer*, iItemDrawer );
+ TSize size(CFormattedCellListBoxView::ItemSize(aItemIndex).iWidth, itemDrawer->GetItemHeight (aItemIndex,
+ CurrentItemIndex () == aItemIndex) );
+
+ if ( size.iHeight < 2)
+ size.iHeight = 2;
+
+ return size;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TPoint CMmListBoxView::ItemPos (TInt aItemIndex) const
+ {
+ TInt vRealPos = CFormattedCellListBoxView::ItemPos(TopItemIndex()).iY;
+ TInt totalHeight = 0;
+ if ( aItemIndex > iTopItemIndex )
+ {
+ totalHeight = GetTotalHeight( iTopItemIndex, aItemIndex - 1 );
+ }
+ else if ( aItemIndex < iTopItemIndex )
+ {
+ totalHeight = -GetTotalHeight( aItemIndex, iTopItemIndex - 1 );
+ }
+
+ return TPoint (-iHScrollOffset + iViewRect.iTl.iX, iViewRect.iTl.iY
+ + totalHeight + vRealPos);
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool CMmListBoxView::XYPosToItemIndex (TPoint aPosition, TInt& aItemIndex) const
+ {
+ // returns ETrue and sets aItemIndex to the index of the item whose bounding box contains aPosition
+ // returns EFalse if no such item exists
+ TBool itemFound = EFalse;
+ if ( iViewRect.Contains (aPosition))
+ {
+ TInt vRealPos = CFormattedCellListBoxView::ItemPos(TopItemIndex()).iY;
+ // aPosition is inside the display area
+ TInt numberOfVisibleItems = GetLastIndexInHeight (iTopItemIndex,
+ aPosition.iY - iViewRect.iTl.iY - vRealPos );
+ TInt itemAtSpecifiedPos = iTopItemIndex + numberOfVisibleItems;
+ aItemIndex = itemAtSpecifiedPos;
+ itemFound = ( GetTotalHeight( iTopItemIndex, iBottomItemIndex )
+ >= aPosition.iY ) && ( iModel->NumberOfItems() > itemAtSpecifiedPos );
+// if ( itemFound )
+// {
+// // aPosition is inside the display area
+// TInt numberOfVisibleItems = GetLastIndexInHeight (iTopItemIndex,
+// aPosition.iY - iViewRect.iTl.iY);
+// TInt itemAtSpecifiedPos = iTopItemIndex + numberOfVisibleItems;
+// aItemIndex = itemAtSpecifiedPos;
+// }
+ }
+ return itemFound;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::SetItemHeight (TInt aItemHeight)
+ {
+ // we need to update the iItemHeight member in widget also (there are two different item height value holders - in widget and here in widget view)
+ iItemHeight = aItemHeight;
+
+ CMmListBoxItemDrawer* itemDrawer =
+ STATIC_CAST( CMmListBoxItemDrawer*, ItemDrawer() );
+ static_cast<CMmListBox*>(itemDrawer->Widget())->SetItemHeight( aItemHeight );
+
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBoxView::CalcNewTopItemIndexSoItemIsVisible (TInt aItemIndex) const
+ {
+ CMmListBoxItemDrawer* itemDrawer =
+ static_cast<CMmListBoxItemDrawer*>( iItemDrawer );
+
+ TInt newTopItemIndex = iTopItemIndex;
+
+ TInt itemHeight = itemDrawer->
+ GetItemHeight( aItemIndex, aItemIndex == CurrentItemIndex() );
+
+ // ItemIsPartiallyVisible uses fixed iItemHeight, but we have to support
+ // variable item height in lists, unfortunately ItemIsPartiallyVisible
+ // is not virtual
+ TPoint itemPosition( ItemPos( aItemIndex ) );
+ TBool itemPartiallyVisible =
+ ( itemPosition.iY < iViewRect.iTl.iY &&
+ itemPosition.iY + itemHeight >= iViewRect.iTl.iY ) ||
+ ( itemPosition.iY <= iViewRect.iBr.iY &&
+ itemPosition.iY + itemHeight > iViewRect.iBr.iY );
+
+ TBool itemIsFullyVisible = ItemIsVisible( aItemIndex ) &&
+ !itemPartiallyVisible;
+
+ TBool itemIsAboveVisibleArea = !itemIsFullyVisible &&
+ ItemPos( aItemIndex ).iY < ViewRect().iTl.iY;
+
+ TBool itemIsBeneathVisibleArea = !itemIsFullyVisible &&
+ !itemIsAboveVisibleArea && ItemPos( aItemIndex ).iY + itemDrawer->
+ GetItemHeight( aItemIndex, aItemIndex == CurrentItemIndex() ) >
+ ViewRect().iBr.iY;
+
+ if ( itemIsAboveVisibleArea )
+ {
+ newTopItemIndex = aItemIndex;
+ const_cast<CMmListBoxView*>( this )->SetItemOffsetInPixels( 0 );
+ }
+
+ if ( itemIsBeneathVisibleArea )
+ {
+ const TInt viewHeight = ViewRect().Height();
+ newTopItemIndex = aItemIndex;
+ for ( ;; )
+ {
+ TInt totalHeight = GetTotalHeight( newTopItemIndex, aItemIndex );
+ if ( totalHeight >= viewHeight || newTopItemIndex == 0 )
+ {
+ const_cast<CMmListBoxView*>( this )->SetItemOffsetInPixels(
+ viewHeight - totalHeight );
+ break;
+ }
+ --newTopItemIndex;
+ }
+ }
+
+ return newTopItemIndex;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::RedrawBackground (TRect aUsedPortionOfViewRect,
+ TRect aSmallerViewRect) const
+ {
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal(iGc);
+ if (transApi)
+ {
+ transApi->StartDrawing(MAknListBoxTfxInternal::EListView);
+ }
+#endif
+
+ CMmListBoxItemDrawer* itemDrawer = STATIC_CAST( CMmListBoxItemDrawer*, iItemDrawer );
+ MAknsSkinInstance *skin = AknsUtils::SkinInstance();
+ CCoeControl* control = itemDrawer->FormattedCellData()->Control();
+ MAknsControlContext *cc = AknsDrawUtils::ControlContext(control);
+
+ if (control)
+ {
+ AknsDrawUtils::BackgroundBetweenRects(skin, cc, control, *iGc,
+ aSmallerViewRect, aUsedPortionOfViewRect);
+ }
+ else
+ {
+ iGc->SetBrushColor(BackColor());
+ DrawUtils::ClearBetweenRects(*iGc, aSmallerViewRect,
+ aUsedPortionOfViewRect);
+ }
+
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ if (transApi)
+ {
+ transApi->StopDrawing();
+ }
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::RedrawBackground () const
+ {
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ CMmListBoxItemDrawer* drawer =
+ static_cast<CMmListBoxItemDrawer*>( iItemDrawer );
+ CMmTemplateLibrary* templateLib = drawer->TemplateLibrary();
+
+ TInt usedPortionHeight = GetTotalHeight(iTopItemIndex, iBottomItemIndex );
+ TInt usedPortionWidth = iViewRect.Width();
+ if (templateLib->GetScrollbarVisibility())
+ {
+ usedPortionWidth -= templateLib->ScrollbarWidth();
+ }
+
+ TRect usedPortionOfViewRect(iViewRect.iTl, TSize(usedPortionWidth,
+ usedPortionHeight));
+ usedPortionOfViewRect.Move(0,
+ CFormattedCellListBoxView::ItemPos(iTopItemIndex).iY);
+
+ RedrawBackground(usedPortionOfViewRect, iViewRect);
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::SetPreviouslyDrawnCurrentItemIndex( TBool aIndex )
+ {
+ iPreviouslyDrawnCurrentItemIndex = aIndex;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::DrawSingleItem (TInt aItemIndex) const
+ {
+ CMmListBoxItemDrawer* itemDrawer= STATIC_CAST( CMmListBoxItemDrawer*, iItemDrawer );
+ TSize size = itemDrawer->GetItemSize( aItemIndex, CurrentItemIndex ()
+ == aItemIndex);
+ itemDrawer->SetItemCellSize (size);
+
+ // CMmListBoxView* view= CONST_CAST( CMmListBoxView*, this );
+ // view->SetItemHeight( size.iHeight );
+ // The above line (currently commented-out) was originaly needed to correct
+ // some drawing-related error which used to occur when moving highlight with
+ // rocker keys. It seems that this is no longer needed. If anything should
+ // change, please note that now the SetItemHeight method does much more than
+ // it used to, so simply uncommenting this line would be a bad idea (consider
+ // setting the iItemHeight member variable directly).
+
+ CFormattedCellListBoxView::DrawItem (aItemIndex);
+
+ //To eliminate the effect of undrawn fragment of background, when the last
+ //is drawn, background is refreshed
+ if ( aItemIndex == ( iModel->NumberOfItems()-1 ) && ItemIsVisible( iModel->NumberOfItems()-1 ) )
+ {
+ CMmListBoxItemDrawer* itemDrawer= STATIC_CAST( CMmListBoxItemDrawer*, iItemDrawer );
+ if ( !itemDrawer->IsEditMode() )
+ {
+ RedrawBackground();
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TInt CMmListBoxView::VerticalItemOffset() const
+ {
+ return iVerticalOffset;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool CMmListBoxView::ScrollToMakeItemVisible(TInt aItemIndex)
+ {
+ TBool scrollConsumed(EFalse);
+ if ( !iScrollToItemDisabled )
+ {
+ scrollConsumed = CFormattedCellListBoxView::ScrollToMakeItemVisible(
+ aItemIndex);
+ }
+ return scrollConsumed;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMmListBoxView::DisableScrollToItem( TBool aDisable )
+ {
+ iScrollToItemDisabled = aDisable;
+ }
+
+// End of file