/*
* 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_106 % << Don't touch! Updated by Synergy at check-out.
*
*/
#include <AknsDrawUtils.h>
#include <layoutmetadata.cdl.h>
#include "mmgrid.h"
#include "mmgridmodel.h"
#include "mmlistboxitemdrawer.h"
#include "mmgridview.h"
#include "mmtemplatelibrary.h"
#include "mmlistboxmodel.h"
#include "mmmarqueeadapter.h"
#include "mmwidgetsconstants.h"
#include "mmwidgetcontainer.h"
#include "hnsuitemodel.h"
#include "mmdraweranimator.h"
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
#include <aknlistloadertfx.h>
#include <aknlistboxtfxinternal.h>
#endif
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
CMmGrid::CMmGrid()
{
// No implementation required
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
CMmGrid::~CMmGrid()
{
delete iRedrawTimer;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
CMmGrid* CMmGrid::NewLC( const CCoeControl* aParent, TInt aFlags,
CMmTemplateLibrary* aTemplateLibrary)
{
CMmGrid* self = new (ELeave)CMmGrid();
CleanupStack::PushL(self);
self->ConstructL( aParent, aFlags, aTemplateLibrary );
return self;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
CMmGrid* CMmGrid::NewL( const CCoeControl* aParent, TInt aFlags,
CMmTemplateLibrary* aTemplateLibrary )
{
CMmGrid* self = CMmGrid::NewLC( aParent, aFlags, aTemplateLibrary );
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// 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 CMmGrid::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 CMmGrid::Draw(const TRect& aRect) const
{
if ( View()->RedrawDisabled () || !IsVisible () )
{
return;
}
iMmDrawer->SetNumberOfColsInView(
static_cast<CMmGridView*>(iView)->NumberOfColsInView() );
// If a parent has a custom gc, draw listbox using that gc
CWindowGc* replacedGc = ReplaceGcWithCustomGc( this );
CWindowGc* gc = iItemDrawer->Gc();
TGulBorder::TColors borderColors;
iBorder.Draw(*gc, Rect(), borderColors);
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal(
static_cast<CMmGridView*>(iView)->Gc() );
TBool effects = transApi && !transApi->EffectsDisabled();
if ( effects )
{
// 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 );
transApi->StartDrawing( MAknListBoxTfxInternal::EListView );
}
#endif // RD_UI_TRANSITION_EFFECTS_LIST
ClearMargins();
RedrawScrollbarBackground();
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
if ( effects )
{
transApi->StopDrawing();
}
#endif // RD_UI_TRANSITION_EFFECTS_LIST
iView->Draw(&aRect);
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
if ( effects )
{
transApi->EndViewRedraw( aRect );
}
#endif // RD_UI_TRANSITION_EFFECTS_LIST
if ( replacedGc )
{
// Stop using the custom gc
iItemDrawer->SetGc( replacedGc );
}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::DrawView()
{
iDisableChildComponentDrawing = ETrue;
DrawNow(Rect());
iDisableChildComponentDrawing = EFalse;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::CreateItemDrawerL()
{
iItemDrawer = iMmDrawer;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::CreateItemDrawerL( CMmTemplateLibrary* aTemplateLibrary )
{
CFormattedCellListBoxData* data=CFormattedCellGridData::NewL();
CleanupStack::PushL(data);
iMmDrawer = CMmListBoxItemDrawer::NewL(
MmModel()->MmListBoxModel(), iEikonEnv->NormalFont(), data, EGrid,
aTemplateLibrary );
iItemDrawer = iMmDrawer;
data->SetControl( this );
CleanupStack::Pop( data );
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::HandleScrollEventL( CEikScrollBar* aScrollBar,
TEikScrollEvent aEventType )
{
if ( aEventType == EEikScrollThumbDragVert && !iScrollbarThumbIsBeingDragged )
{
iScrollbarThumbIsBeingDragged = ETrue;
static_cast<CMmListBoxItemDrawer*>(
View()->ItemDrawer() )->EnableCachedDataUse( ETrue );
iRedrawTimer->Start( KScrollingRedrawInterval, KScrollingRedrawInterval,
TCallBack( &CMmGrid::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;
}
}
// -----------------------------------------------------------------------------
// 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 CMmGrid::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();
CAknGrid::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 ) )
{
if ( CurrentItemIndex() != itemUnderPointerIndex )
{
CMmWidgetContainer* parent = static_cast<CMmWidgetContainer*>( Parent() );
if ( parent->IsNoItemDragged() )
{
if ( ItemDrawer()->Flags() & CListItemDrawer::EPressedDownState )
{
ItemDrawer()->ClearFlags( CListItemDrawer::EPressedDownState );
iView->DrawItem( CurrentItemIndex() );
}
}
else
{
iView->SetCurrentItemIndex( itemUnderPointerIndex );
iView->DrawItem(itemUnderPointerIndex);
}
}
}
HandleScrollingInEditMode( aPointerEvent );
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::HandlePointerEventInNormalModeL( const TPointerEvent& aPointerEvent )
{
CAknGrid::HandlePointerEventL(aPointerEvent);
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::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 CMmGrid::IsPointerInTopScrollingThreshold(
const TPointerEvent& aPointerEvent ) const
{
TInt topScrollingTreshold = Rect().iTl.iY
+ ( MmGrid::KFocusScrollingThreshold
* TReal( View()->ItemSize().iHeight ) );
return ( aPointerEvent.iPosition.iY < topScrollingTreshold );
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
TBool CMmGrid::IsPointerInBottomScrollingThreshold(
const TPointerEvent& aPointerEvent ) const
{
TInt bottomScrollingTreshold = Rect().iBr.iY
- ( MmGrid::KFocusScrollingThreshold
* TReal( View()->ItemSize().iHeight ) );
return ( aPointerEvent.iPosition.iY > bottomScrollingTreshold );
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::ScrollWithoutRedraw( TInt distanceInPixels )
{
CAknGridView* view = static_cast<CAknGridView*>( iView );
const TInt rowHeight = ItemHeight();
const TInt numOfCols = view->NumberOfColsInView();
const TInt itemCount = iModel->NumberOfItems();
TInt totalNumberOfRows = itemCount / numOfCols;
if ( itemCount % numOfCols )
{
++totalNumberOfRows;
}
const TInt topItemRowIndex = TopItemIndex() / numOfCols;
// desired view position relative to the first item in grid (always positive)
TInt desiredViewPosition = rowHeight * topItemRowIndex - VerticalItemOffset();
desiredViewPosition += distanceInPixels;
const TInt viewPositionMin = 0;
const TInt viewPositionMax =
Max( 0, ( totalNumberOfRows * rowHeight ) - view->ViewRect().Height() );
desiredViewPosition = Min( desiredViewPosition, viewPositionMax );
desiredViewPosition = Max( desiredViewPosition, viewPositionMin );
ASSERT( desiredViewPosition >= 0 );
TInt newTopItemIndex = ( desiredViewPosition / rowHeight ) * numOfCols;
TInt newVerticalOffset = -( desiredViewPosition % rowHeight );
SetTopItemIndex( newTopItemIndex );
SetVerticalItemOffset( newVerticalOffset );
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
TInt CMmGrid::ScrollIfNeeded( const TPointerEvent& aPointerEvent )
{
CAknGridView* view = static_cast<CAknGridView*>( View() );
TInt nextScrollDelay = 0;
TBool readyForScrolling = iMmDrawer->GetAnimator()->IsReadyForNewAnimation()
&& iMmDrawer->GetFloatingItemCount() != 0;
if ( IsPointerInTopScrollingThreshold( aPointerEvent ) )
{
// scroll up by one row
TInt newCurrentItemIndex = CurrentItemIndex() - view->NumberOfColsInView();
if ( newCurrentItemIndex < 0 )
{
newCurrentItemIndex = CurrentItemIndex();
}
nextScrollDelay = MmEffects::KEditModeScrollingDelayFactor *
Max( 1, aPointerEvent.iPosition.iY - Rect().iTl.iY );
if ( readyForScrolling )
{
ScrollWithoutRedraw( -iItemHeight );
View()->SetCurrentItemIndex( newCurrentItemIndex );
}
}
else if ( IsPointerInBottomScrollingThreshold( aPointerEvent) )
{
TInt newCurrentItemIndex = CurrentItemIndex() + view->NumberOfColsInView();
if ( newCurrentItemIndex > iModel->NumberOfItems() - 1 )
{
newCurrentItemIndex = CurrentItemIndex();
}
nextScrollDelay = MmEffects::KEditModeScrollingDelayFactor *
Max( 1, Rect().iBr.iY - aPointerEvent.iPosition.iY );
if ( readyForScrolling )
{
ScrollWithoutRedraw( iItemHeight );
View()->SetCurrentItemIndex( newCurrentItemIndex );
}
}
return nextScrollDelay;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::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
{
HandlePointerEventInNormalModeL( aPointerEvent );
}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::HandleOverridenHighlightDrawing( const TPointerEvent& aPointerEvent,
TInt aIndexBefore, TInt aIndexAfter )
{
// In grid our behaviour is a little different than defalt avkon.
// It is required to clean the highlight after the finger has been raised,
// and simulate the tap effect, when an item that has an invisible
// highlight is tapped again.
TBool effects (EFalse);
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal(
iMmDrawer->Gc() );
effects = transApi && !transApi->EffectsDisabled();
#endif
if (effects)
{
CMmWidgetContainer* parent = static_cast< CMmWidgetContainer* > ( Parent() );
if ( aIndexBefore == aIndexAfter
&& !parent->IsEditMode()
&& aPointerEvent.iType == TPointerEvent::EButton1Down )
{
DrawItem( aIndexAfter );
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal(
iMmDrawer->Gc() );
if ( transApi )
{
transApi->SetMoveType( MAknListBoxTfxInternal::EListTap);
transApi->Draw( Rect() );
}
#endif
}
else if ( aIndexBefore == aIndexAfter
&& aPointerEvent.iType == TPointerEvent::EButton1Up
&& !parent->IsHighlightVisible())
{
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal(
iMmDrawer->Gc() );
if ( transApi )
{
transApi->Draw( Rect() );
}
#endif
}
}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::FixViewForMirroredLayout()
{
TInt scrollbarWidth = ScrollBarOffset() +
ScrollBarFrame()->VerticalScrollBar()->Rect().Width();
TRect r( View()->ViewRect() );
TInt currentShift = r.iTl.iX;
TBool scrollbarVisible = ScrollBarFrame()->VerticalScrollBar()->IsVisible();
TBool layoutMirrored = AknLayoutUtils::LayoutMirrored();
if ( layoutMirrored )
{
// Extra width, which results from the fact that it is not always
// possible to divide screen width by the number of columns without
// a non-zero remainder. This makes the distance of grid items from
// scrollbar in mirrored layout exactly the same as in normal layout.
scrollbarWidth += ( r.Width() - scrollbarWidth ) %
( (CAknGridView*) View() )->NumberOfColsInView();
}
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 CMmGrid::ConstructL( const CCoeControl* aParent, TInt aFlags,
CMmTemplateLibrary* aTemplateLibrary )
{
iDisableChildComponentDrawing = EFalse;
iModel = iMmModel = CMmGridModel::NewL();
CreateItemDrawerL(aTemplateLibrary);
CAknGrid::ConstructL( aParent, aFlags );
iMmDrawer->SetView( this );
//set initial value so avkon does not panic
if ( Layout_Meta_Data::IsLandscapeOrientation() )
{
iViewLayout = TSize( MmGrid::K4By3LayoutX, MmGrid::K4By3LayoutY );
}
else
{
iViewLayout = TSize( MmGrid::K3By4LayoutX, MmGrid::K3By4LayoutY );
}
DoSetupLayoutL();
iRedrawTimer = CPeriodic::NewL( EPriorityRealTime );
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
CListBoxView* CMmGrid::MakeViewClassInstanceL()
{
return CMmGridView::NewL();
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
CMmGridModel* CMmGrid::MmModel()
{
return iMmModel;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
TKeyResponse CMmGrid::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
TKeyEvent eventCopy( aKeyEvent );
if ( AknLayoutUtils::LayoutMirrored() )
{
if ( eventCopy.iCode == EKeyLeftArrow )
{
eventCopy.iCode = EKeyRightArrow;
}
else if ( eventCopy.iCode == EKeyRightArrow )
{
eventCopy.iCode = EKeyLeftArrow;
}
}
return CAknGrid::OfferKeyEventL( eventCopy, aType );
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::HandleViewRectSizeChangeL()
{
if ( !AknLayoutUtils::LayoutMirrored() )
{
CAknGrid::HandleViewRectSizeChangeL();
}
else
{
// for mirrored layout this function should do
// exactly the same things as CAknGrid::HandleViewRectSizeChangeL
// would do for normal layout
iView->CalcBottomItemIndex();
if ( CurrentItemIndex() >= 0 )
{
AdjustTopItemIndex();
iView->CalcDataWidth();
UpdateScrollBarsL();
iView->CalcBottomItemIndex();
}
}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::AdjustTopItemIndex() const
{
CAknGridView* view = static_cast<CAknGridView*>( iView );
const TInt numOfCols = view->NumberOfColsInView();
const TInt numOfRows = view->NumberOfRowsInView();
const TInt itemCount = iModel->NumberOfItems();
ASSERT( numOfCols > 0 );
TInt lastRow = 0;
if ( itemCount > 0 )
{
lastRow = ( itemCount - 1 ) / numOfCols;
}
TInt maxPossibleTopRow = Max( 0, lastRow - numOfRows + 1 );
TInt topRow = TopItemIndex() / numOfCols;
if( !( TopItemIndex() % numOfCols == 0
&& topRow <= maxPossibleTopRow ) )
{
topRow = Min( topRow, maxPossibleTopRow );
SetTopItemIndex( topRow * numOfCols );
}
// prevent problems with view being scrolled up beyond limits
if ( topRow == maxPossibleTopRow && VerticalItemOffset() < 0 )
{
TRAP_IGNORE(
( ( CMmWidgetContainer* ) Parent() )->AlignBottomOfViewL() );
}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::DoHandleResourceChangeL( TSize& aCellSize,
TSize& aViewLayout )
{
TBool cond = Layout_Meta_Data::IsLandscapeOrientation();
TRAPD( err, DoHandleResourceChangeL( cond, aCellSize, aViewLayout ) );
if ( err == KErrNotFound )
{
aViewLayout = iViewLayout;
aCellSize = TSize (1,1);
}
else if ( err == KErrNoMemory )
{
User::Leave( KErrNoMemory );
}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::DoHandleResourceChangeL( TBool aIsLandscape, TSize& aCellSize,
TSize& aViewLayout )
{
CHnSuiteModel* model = iMmModel->MmListBoxModel()->GetSuiteModel();
const TDesC8& templ = (model) ? model->GetTemplate() : KNullDesC8();
aCellSize = iMmDrawer->TemplateLibrary()->GetSize(
EGrid, templ, aIsLandscape, EFalse, iView->ViewRect() );
aViewLayout = iMmDrawer->TemplateLibrary()->GetLayoutSizeL(
EGrid, templ, aIsLandscape );
iViewLayout = aViewLayout;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::SetItemDrawerAndViewBgContext(
CAknsBasicBackgroundControlContext * aBgContext )
{
iMmDrawer->SetBgContext (aBgContext);
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
TBool CMmGrid::HandleScrollbarVisibilityChangeL()
{
TBool ret = EFalse;
if ( AllItemsFitInViewRect() )
{
if ( ScrollBarFrame()->VerticalScrollBar()->IsVisible()
|| iMmDrawer->TemplateLibrary()->GetScrollbarVisibility() )
{
ScrollBarFrame()->VerticalScrollBar()->MakeVisible( EFalse );
iMmDrawer->SetScrollbarVisibilityL( EFalse );
SetTopItemIndex( 0 );
iCurrentTopItemIndex = 0;
ret = ETrue;
}
}
else if ( !ScrollBarFrame()->VerticalScrollBar()->IsVisible()
|| !iMmDrawer->TemplateLibrary()->GetScrollbarVisibility() )
{
ScrollBarFrame()->VerticalScrollBar()->MakeVisible( ETrue );
iMmDrawer->SetScrollbarVisibilityL( ETrue );
ret = ETrue;
}
return ret;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
TBool CMmGrid::AllItemsFitInViewRect()
{
if ( iMmModel->NumberOfItems() <= iViewLayout.iWidth * iViewLayout.iHeight
|| iViewLayout == TSize(0,0) )
{
return ETrue;
}
else
{
return EFalse;
}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::UpdateScrollBarsL()
{
TBool visibilityChanged = HandleScrollbarVisibilityChangeL();
if (ScrollBarFrame()->VerticalScrollBar()->IsVisible())
{
CMmWidgetContainer* widget = static_cast< CMmWidgetContainer* >(Parent());
if( widget->IsEditMode() && widget->WidgetPositionCache().iValid )
{
static_cast<CMmGridView*> ( View() )->SetItemOffsetInPixels(
widget->WidgetPositionCache().iVerticalItemOffset );
}
CAknGrid::UpdateScrollBarsL();
}
iCurrentTopItemIndex = TopItemIndex();
iMmDrawer->TemplateLibrary()->SetScrollbarWidthL(
ScrollBarFrame()->VerticalScrollBar()->Rect().Width() + ScrollBarOffset() );
FixViewForMirroredLayout();
if ( visibilityChanged )
{
CMmGridView* view = static_cast<CMmGridView*>( iView );
view->UpdateItemHeightAndWidth();
}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::SetMarqueeAdapter( CMmMarqueeAdapter* aAdapter )
{
iMarqueeAdapter = aAdapter;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::SetupLayout()
{
TRAP_IGNORE( DoSetupLayoutL() );
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::DoSetupLayoutL()
{
TSize cellSize;
TSize viewLayout;
DoHandleResourceChangeL( cellSize, viewLayout );
// The mirrored layout arabic item lineout ( right to left )
// is handled by CMmGridView::ItemPos( TInt aItemIndex )
// and CMmGridView::XYPosToItemIndex( TPoint aPosition, TInt& aItemIndex )
SetLayoutL( EFalse, ETrue /*!AknLayoutUtils::LayoutMirrored()*/, ETrue, viewLayout.iWidth,
viewLayout.iHeight, cellSize, 0, 0 );
iMmDrawer->SetNumberOfColsInView(
static_cast<CMmGridView*>(iView)->NumberOfColsInView() );
// setting the top item index when changing orientation
TInt cols( static_cast<CMmGridView*>(iView)->NumberOfColsInView() );
SetTopItemIndex( ( (TInt) ( iCurrentTopItemIndex / cols ) ) * cols );
UpdateScrollBarsL();
AknsUtils::RegisterControlPosition( iMmDrawer->FormattedCellData()->Control() );
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
TInt CMmGrid::ScrollBarOffset()
{
TInt offset = 0;
if ( ScrollBarFrame()->ScrollBarExists( CEikScrollBar::EVertical ) )
{
if ( AknLayoutUtils::LayoutMirrored() )
{
offset = ScrollBarFrame()->VerticalScrollBar()->Position().iX;
}
else
{
offset = View()->ViewRect().Width()
- ( ScrollBarFrame()->VerticalScrollBar()->Position().iX
+ ScrollBarFrame()->VerticalScrollBar()->Rect().Width() );
}
}
return offset;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::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 CMmGrid::ProcessScrollEventL( CEikScrollBar* aScrollBar,
TEikScrollEvent aEventType )
{
CAknGrid::HandleScrollEventL( aScrollBar, aEventType );
iCurrentTopItemIndex = TopItemIndex();
// setting default highlight in order not to overwrite the top item index
// set before in the SetLayout method
CMmWidgetContainer* parent = static_cast< CMmWidgetContainer* > ( Parent() );
if (!parent->IsHighlightVisible())
{
parent->SetDefaultHighlightL( EFalse );
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal(
static_cast<CMmGridView*>(iView)->Gc() );
TBool effects = transApi && !transApi->EffectsDisabled();
if ( effects && aEventType == EEikScrollPageUp ||
aEventType == EEikScrollPageDown )
{
DrawNow();
}
#endif
}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::HandleRedrawTimerEventL()
{
if ( iSkippedScrollbarEventsCount )
{
ProcessScrollEventL( ScrollBarFrame()->VerticalScrollBar(),
EEikScrollThumbDragVert );
}
iSkippedScrollbarEventsCount = 0;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
TInt CMmGrid::RedrawTimerCallback( TAny* aPtr )
{
CMmGrid* self = static_cast<CMmGrid*>( aPtr );
TRAP_IGNORE( self->HandleRedrawTimerEventL() );
// Do not bother returning a meaningful error code, CPeriodic will ignore it
// anyway.
return 0;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::SetVerticalItemOffset(TInt aOffset)
{
static_cast<CMmGridView*> (View())->SetItemOffsetInPixels(aOffset);
UpdateScrollBarThumbs();
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
TInt CMmGrid::VerticalItemOffset() const
{
return static_cast<CMmGridView*> (View())->VerticalItemOffset();
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::SetItemHeight( TInt aItemHeight )
{
iItemHeight = aItemHeight;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::UpdateScrollBarThumbs()
{
CAknGrid::UpdateScrollBarThumbs();
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
TInt CMmGrid::CountComponentControls() const
{
TInt componentControls(0);
if ( !iDisableChildComponentDrawing )
{
componentControls = CAknGrid::CountComponentControls();
}
return componentControls;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
//
void CMmGrid::SetDisableChildComponentDrawing( TBool aDisable )
{
iDisableChildComponentDrawing = aDisable;
}
//End of file