--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/akngrid.cpp Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,2200 @@
+/*
+* Copyright (c) 2002-2009 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: This is a concrete class for the handling of a grid.
+* The class handles a rectangular grid arrangement of items
+* held in any linear ordering i.e. cells ordered top to
+* bottom and left, left to right and down etc.
+*
+*/
+
+
+#include <AknGrid.h>
+#include <avkon.hrh>
+#include <avkon.rsg>
+
+#include <barsread.h>
+
+#include <AknGridView.h>
+#include <AknGridM.h>
+#include <eiklbm.h>
+#include <eiklbi.h>
+#include <eiklbx.h>
+
+#include <eikenv.h>
+#include <eiklbx.pan>
+#include <eikkeys.h>
+
+#include <AknsUtils.h>
+
+//formatted listbox
+#include <eikfrlbd.h>
+#include <eikfrlb.h>
+
+#include <AknDef.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <AknsControlContext.h>
+#include "layoutmetadata.cdl.h"
+#include <aknphysics.h>
+
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ #include <aknlistloadertfx.h>
+ #include <aknlistboxtfxinternal.h>
+#endif //RD_UI_TRANSITION_EFFECTS_LIST
+
+#include <touchfeedback.h>
+#include "akntrace.h"
+
+const TInt KDefaultLineHeightForHorizontalGrid = 10;
+
+const TInt KEikListBoxPointerRepeatInterval = 100000; // 0.1 seconds in micro seconds
+
+const TInt KEikListBoxInvalidIndex = -1;
+
+enum TGridOrientation
+ {
+ EGridOrientationHorizontal,
+ EGridOrientationVertical
+ };
+enum TGridHorizontal
+ {
+ EGridHorizontalRightToLeft,
+ EGridHorizontalLeftToRight,
+ EGridHorizontalWritingDirection,
+ EGridHorizontalAntiWritingDirection
+ };
+enum TGridVertical
+ {
+ EGridVerticalBottomToTop,
+ EGridVerticalTopToBottom
+ };
+
+
+/**
+* Local Panic Function and Panic Codes
+*/
+enum TAknGridPanicCodes
+ {
+ EAknPanicGridGeneralPanic,
+ EAknPanicGridModelAlreadyExists,
+ EAknPanicGridInvalidNumberOfPrimaryItems,
+ EAknPanicGridNoView
+ };
+
+
+enum TAknGridStateFlags
+ {
+ EAknGridStateButton1DownInGrid = 0x01
+ };
+
+// ================= Extension class ========================
+NONSHARABLE_CLASS(CAknGridExtension) : public CBase
+ {
+ public:
+ CAknGridExtension();
+ ~CAknGridExtension();
+ TInt GetScrollingSpeed( TBool aIsOverItem, TInt aItemIndex, CAknGridView& aView,
+ const TPoint& aPoint ) const;
+
+
+ public: // data
+ TInt iFlags;
+ // EMMA-7A8B9F.Ugly hack. Prevent MopSupplyObject being invoked
+ // from CEikListBox::MopGetObject()
+ TBool iIsFromBaseClass;
+ TPoint iLastPoint;
+ TBool iKineticScrolling;
+ TBool iSingleClickEnabled;
+ };
+
+CAknGridExtension::CAknGridExtension()
+ :
+ iFlags(0),
+ iIsFromBaseClass( EFalse ),
+ iLastPoint( 0, 0 ),
+ iKineticScrolling( CAknPhysics::FeatureEnabled() ),
+ iSingleClickEnabled( iAvkonAppUi->IsSingleClickCompatible() )
+ {
+ }
+
+CAknGridExtension::~CAknGridExtension()
+ {
+ }
+
+TInt CAknGridExtension::GetScrollingSpeed( TBool aIsOverItem, TInt aItemIndex,
+ CAknGridView& aView, const TPoint& aPoint ) const
+ {
+ TInt itemCountInRow = aView.NumberOfColsInView();
+ TInt speed = 0;
+ TInt y = aPoint.iY - iLastPoint.iY;
+ if ( aIsOverItem )
+ {
+ if ( aView.BottomItemIndex() - aItemIndex < itemCountInRow
+ && y> 0 )
+ {
+ speed = 1;
+ }
+ else if ( aItemIndex - aView.TopItemIndex() < itemCountInRow
+ && y < 0 )
+ {
+ speed = -1;
+ }
+ }
+ else
+ {
+ speed = 0;
+ }
+ return speed;
+ }
+
+
+// ================= CAknGrid class ========================
+
+GLDEF_C void Panic(TAknGridPanicCodes aPanic)
+ {
+ _LIT(KPanicCat,"AknGrid");
+ User::Panic(KPanicCat, aPanic);
+ }
+
+
+EXPORT_C CAknGrid::CAknGrid()
+ {
+ }
+
+EXPORT_C CAknGrid::~CAknGrid()
+ {
+ delete iExtension;
+ }
+
+/**
+* This function must only be called before ConstructL()
+*/
+EXPORT_C void CAknGrid::SetModel(CAknGridM* aModel)
+ {
+ __ASSERT_ALWAYS(!iModel, Panic(EAknPanicGridModelAlreadyExists));
+ iModel = aModel;
+ }
+
+EXPORT_C void CAknGrid::ConstructL(const CCoeControl* aParent, TInt aFlags)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ if (!iModel)
+ {
+ iModel = new(ELeave) CAknGridM;
+ }
+
+ GridModel()->ConstructL();
+
+ CreateItemDrawerL();
+ ItemDrawer()->FormattedCellData()->SetControl(this);
+ CEikListBox::ConstructL(aParent, aFlags);
+
+ if ( !iExtension )
+ {
+ iExtension = new (ELeave) CAknGridExtension;
+ }
+
+ // the default scrolling method is follows items
+ SetPrimaryScrollingType( CAknGridView::EScrollFollowsItemsAndLoops );
+ SetSecondaryScrollingType( CAknGridView::EScrollFollowsItemsAndLoops );
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C void CAknGrid::ConstructFromResourceL(TResourceReader& aReader)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ RestoreCommonListBoxPropertiesL(aReader);
+ TInt requiredCellCharWidth=aReader.ReadInt16();
+
+ if (!iModel)
+ iModel = new(ELeave) CAknGridM;
+
+ TInt items=aReader.ReadInt32();
+ if (!items)
+ {
+ STATIC_CAST(CAknGridM*,iModel)->ConstructL();
+ }
+ else
+ {
+ CDesCArray* desArray=iCoeEnv->ReadDesCArrayResourceL(items);
+ CleanupStack::PushL(desArray);
+
+ STATIC_CAST(CAknGridM*,iModel)->ConstructL(desArray);
+ CleanupStack::Pop( desArray );
+ }
+
+ CreateItemDrawerL();
+ iItemDrawer->SetDrawMark(EFalse);
+ ItemDrawer()->FormattedCellData()->SetControl(this);
+ STATIC_CAST(CFormattedCellListBoxItemDrawer*,iItemDrawer)->SetCellWidthInChars(requiredCellCharWidth);
+ CreateViewL();
+
+ // empty text
+ HBufC* emptyGridText = aReader.ReadHBufCL();
+ if (emptyGridText)
+ {
+ CleanupStack::PushL(emptyGridText);
+ SetEmptyGridTextL(*emptyGridText);
+ CleanupStack::PopAndDestroy( emptyGridText );
+ }
+
+ TInt gridStyle=aReader.ReadInt32();
+
+ TResourceReader reader;
+ if (!gridStyle)
+ {
+ iEikonEnv->CreateResourceReaderLC(reader,R_AVKON_GRID_STYLE_DEFAULT);
+ }
+ else
+ {
+ iEikonEnv->CreateResourceReaderLC(reader,gridStyle);
+ }
+
+ SetLayoutFromResourceL(reader);
+ CleanupStack::PopAndDestroy(); // reader
+
+ if ( !iExtension )
+ {
+ iExtension = new (ELeave) CAknGridExtension;
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* This routine assumes that SetLayoutL has been called to set
+* up the grid.
+*/
+EXPORT_C void CAknGrid::SizeChanged()
+ {
+ _AKNTRACE_FUNC_ENTER;
+ TRect clientRect = iBorder.InnerRect(Rect());
+
+ TInt currentDataIndex = 0;
+ CAknGridView* gridView = GridView();
+
+ // reset item offset
+ gridView->SetItemOffsetInPixels( 0 );
+
+ if (iCurrentIsValid) // appshell does not call HandleItemAddition!
+ { // so this is never called. See CAknAppStyleGrid::SizeChanged()
+ // remember current position
+ currentDataIndex = gridView->CurrentDataIndex();
+ }
+
+ TRect rect(clientRect);
+ rect.SetRect(rect.iTl.iX + ListBoxMargins().iLeft, rect.iTl.iY + ListBoxMargins().iTop,
+ rect.iBr.iX - ListBoxMargins().iRight, rect.iBr.iY - ListBoxMargins().iBottom);
+ iView->SetViewRect(rect);
+ _AKNTRACE( "The rect of grid are ( %d, %d ) ( %d, %d )",
+ rect.iTl.iX, rect.iTl.iY,
+ rect.iBr.iX, rect.iBr.iY );
+ TRAPD(err1, HandleViewRectSizeChangeL());
+ if (err1)
+ {
+ if (iSBFrameOwned == ENotOwnedExternally)
+ {
+ delete iSBFrame;
+ iSBFrame = 0;
+ }
+ }
+
+ // check grid orientated to show current focus (item height
+ // change may have moved the focus to a new page)
+ if (iCurrentIsValid)
+ {
+ gridView->SetCurrentDataIndex(currentDataIndex);
+ }
+
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ TRgb color;
+
+ TInt error = AknsUtils::GetCachedColor( skin,
+ color,
+ KAknsIIDQsnTextColors,
+ EAknsCIQsnTextColorsCG11 );
+ if (!error)
+ {
+ ItemDrawer()->SetHighlightedTextColor( color );
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* Protected routine used by functions to check/alter the dimensions
+* of the grid as data items are added or removed or the
+* size of the items are altered.
+* This routine assumes that SetLayoutL has been called.
+* This will not leave if scrollbars have both been turned off.
+*/
+EXPORT_C void CAknGrid::CalcGridSizeL()
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+
+ CAknGridView* gridView = GridView();
+ TSize gridSize = gridView->GridCellDimensions();
+
+ TInt definedItems = GridModel()->IndexOfLastDataItem() + 1;
+
+ if (definedItems > 0)
+ {
+ // item height determines iHeight
+ if (iItemHeight < 1)
+ {
+ // item height must exist - so set to default value
+ // for now
+ CEikListBox::SetItemHeightL(KDefaultLineHeightForHorizontalGrid);
+ }
+
+ if(iOrientationFlags.IsSet(EGridOrientationVertical))
+ {
+ gridSize.iHeight = iNumOfRowsInView;
+ gridSize.iWidth = definedItems / gridSize.iHeight;
+ if (definedItems % gridSize.iHeight)
+ gridSize.iWidth++;
+ }
+ else
+ {
+ gridSize.iWidth = iNumOfColsInView;
+ gridSize.iHeight = definedItems / gridSize.iWidth;
+ if (definedItems % gridSize.iWidth)
+ gridSize.iHeight++;
+ }
+ }
+ else
+ {
+ //no defined items so grid empty
+ gridSize.iWidth = 1;
+ gridSize.iHeight = 1;
+ if (iOrientationFlags.IsSet(EGridOrientationVertical))
+ gridSize.iHeight = iNumOfRowsInView;
+ else
+ gridSize.iWidth = iNumOfColsInView;
+ }
+ // set number of cells in grid
+ gridView->SetGridCellDimensions(gridSize);
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+
+/**
+* Creates a formatted list item drawer.
+*/
+EXPORT_C void CAknGrid::CreateItemDrawerL()
+ {
+ CFormattedCellListBoxData* data=CFormattedCellGridData::NewL();
+ CleanupStack::PushL(data);
+
+ data->SetControl( this );
+ data->CreatePictographInterfaceL();
+
+ iItemDrawer=new(ELeave) CFormattedCellListBoxItemDrawer(Model(), iEikonEnv->NormalFont(), data);
+ CleanupStack::Pop( data );
+ }
+
+/**
+* Gives the formatted list item drawer being used by the grid.
+*/
+EXPORT_C CFormattedCellListBoxItemDrawer* CAknGrid::ItemDrawer() const
+ {
+ return STATIC_CAST(CFormattedCellListBoxItemDrawer*,iItemDrawer);
+ }
+
+/**
+* Informs the grid that the data in the model has altered.
+* It is assumed that the grid has been initialised by a call to SetLayoutL
+* before this function is called for the first time.
+*/
+EXPORT_C void CAknGrid::HandleItemAdditionL()
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+
+ if (GridModel()->NumberOfData() <= 0)
+ return;
+
+ TInt currentDataIndex = 0;
+
+ CAknGridView* gridView = GridView();
+
+ if (iCurrentIsValid)
+ {
+ // remember current position
+ currentDataIndex = gridView->CurrentDataIndex();
+ }
+
+ CalcGridSizeL();
+
+ CEikListBox::HandleItemAdditionL();
+
+ // check the current marker is set to the first item in the
+ // grid if it hasn't been set yet otherwise ensure current marker still
+ // on cell item before new items were added.
+ if (!iCurrentIsValid)
+ SetStartPositionL(PositionAtIndex(0));
+ else
+ gridView->SetCurrentDataIndex(currentDataIndex);
+
+ iCurrentIsValid = ETrue;
+
+ // redraw everything visible since all/most will have been affected
+ DrawNow();
+ UpdateScrollBarsL();
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* Informs the grid that the data in the model has altered.
+* It is assumed that the grid has been initialised by a call to SetLayoutL
+* before this function is called for the first time.
+*/
+EXPORT_C void CAknGrid::HandleItemRemovalL()
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+
+ if (!iCurrentIsValid)
+ return;
+
+ CAknGridView* gridView = GridView();
+
+ TInt currentDataIndex = gridView->CurrentDataIndex();
+
+ CalcGridSizeL();
+
+ CEikListBox::HandleItemRemovalL();
+
+ // check if need to reposition current index since may have been
+ // on one of those just deleted.
+ CAknGridM* gridModel = GridModel();
+ if (!gridModel->IndexContainsData(currentDataIndex))
+ currentDataIndex = gridModel->IndexOfLastDataItem();
+
+ gridView->SetCurrentDataIndex(currentDataIndex);
+
+ // redraw everything visible since all/most will have been affected
+ DrawNow();
+ UpdateScrollBarsL();
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* Sets the orientation of the grid, either vertical or horizontal, the
+* ordering of the data and the size of the primary dimension of the
+* grid.
+* Note: The value for the parameter aNumOfItemsInPrimaryOrient must be
+* greater than zero since this determines the number of items (be it rows
+* or columns) in the primary orientation of the grid.
+*/
+EXPORT_C void CAknGrid::SetLayoutL(TBool aVerticalOrientation,
+ TBool aLeftToRight,
+ TBool aTopToBottom,
+ TInt aNumOfItemsInPrimaryOrient,
+ TInt aNumOfItemsInSecondaryOrient,
+ TSize aSizeOfItems,
+ TInt aWidthOfSpaceBetweenItems,
+ TInt aHeightOfSpaceBetweenItems)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ TGridOrientation gridOrientation = EGridOrientationHorizontal;
+ if (aVerticalOrientation)
+ gridOrientation = EGridOrientationVertical;
+
+ TGridHorizontal gridHorizontal = EGridHorizontalWritingDirection;
+ if (aLeftToRight)
+ gridHorizontal = EGridHorizontalLeftToRight;
+ else
+ gridHorizontal = EGridHorizontalRightToLeft;
+
+ TGridVertical gridVertical = EGridVerticalBottomToTop;
+ if (aTopToBottom)
+ gridVertical = EGridVerticalTopToBottom;
+
+ DoSetLayoutL(gridOrientation,
+ gridHorizontal,
+ gridVertical,
+ aNumOfItemsInPrimaryOrient,
+ aNumOfItemsInSecondaryOrient,
+ aSizeOfItems,
+ aWidthOfSpaceBetweenItems,
+ aHeightOfSpaceBetweenItems);
+ _AKNTRACE_FUNC_EXIT;
+
+ }
+
+void CAknGrid::DoSetLayoutL(TInt aOrientation,
+ TInt aHorizontal,
+ TInt aVertical,
+ TInt aNumOfItemsInPrimaryOrient,
+ TInt aNumOfItemsInSecondaryOrient,
+ TSize aSizeOfItems,
+ TInt aWidthOfSpaceBetweenItems,
+ TInt aHeightOfSpaceBetweenItems)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ // this must be the first method called after the construction of
+ // the grid
+ __TEST_INVARIANT;
+
+ // number of primary items must be > 0
+ __ASSERT_ALWAYS((aNumOfItemsInPrimaryOrient > 0), Panic(EAknPanicGridInvalidNumberOfPrimaryItems));
+
+ // store number of items in primary in case of SizeChange
+ // never used iNumOfItemsInPrimaryOrient = aNumOfItemsInPrimaryOrient;
+
+ iSpaceBetweenItems.iWidth = aWidthOfSpaceBetweenItems;
+ iSpaceBetweenItems.iHeight = aHeightOfSpaceBetweenItems;
+
+ iOrientationFlags.ClearAll();
+ iHorizontalFlags.ClearAll();
+ iVerticalFlags.ClearAll();
+ TInt gridFlags = 0;
+
+ switch(aOrientation)
+ {
+ case EGridOrientationHorizontal:
+ iOrientationFlags.Set(EGridOrientationHorizontal);
+ iNumOfRowsInView = aNumOfItemsInSecondaryOrient;
+ iNumOfColsInView = aNumOfItemsInPrimaryOrient;
+ break;
+ case EGridOrientationVertical: // drop through to default
+ default: // use default to keep BC with old code
+ iOrientationFlags.Set(EGridOrientationVertical);
+ gridFlags |= CAknGridView::EPrimaryIsVertical;
+ iNumOfRowsInView = aNumOfItemsInPrimaryOrient;
+ iNumOfColsInView = aNumOfItemsInSecondaryOrient;
+ break;
+ }
+
+ switch(aHorizontal)
+ {
+ case EGridHorizontalRightToLeft: // drop through
+ case EGridHorizontalLeftToRight: // drop through
+ case EGridHorizontalWritingDirection: // drop through
+ case EGridHorizontalAntiWritingDirection:
+ iHorizontalFlags.Set(aHorizontal);
+ break;
+ default: // use default to keep BC with old code
+ iHorizontalFlags.Set(EGridHorizontalWritingDirection);
+ break;
+ }
+
+ TBool isMirrored = AknLayoutUtils::LayoutMirrored();
+ if (isMirrored)
+ {
+ if (iHorizontalFlags.IsSet(EGridHorizontalAntiWritingDirection)
+ || iHorizontalFlags.IsSet(EGridHorizontalLeftToRight))
+ gridFlags |= CAknGridView::ELeftToRight;
+ }
+ else
+ {
+ if (iHorizontalFlags.IsSet(EGridHorizontalWritingDirection)
+ || iHorizontalFlags.IsSet(EGridHorizontalLeftToRight))
+ gridFlags |= CAknGridView::ELeftToRight;
+ }
+
+ switch(aVertical)
+ {
+ case EGridVerticalBottomToTop:
+ iVerticalFlags.Set(EGridVerticalBottomToTop);
+ break;
+ case EGridVerticalTopToBottom: // drop through to default
+ default: // use default to keep BC with old code
+ iVerticalFlags.Set(EGridVerticalTopToBottom);
+ gridFlags |= CAknGridView::ETopToBottom;
+ break;
+ }
+
+ CAknGridView* gridView = GridView();
+
+ gridView->SetSpacesBetweenItems(iSpaceBetweenItems);
+ CAknGridView::SGrid gridDetails;
+ // define a single cell grid size to start with - the grid will only become
+ // real after we've added some data and called HandleItemAdditionL. Because
+ // this method is being called when dynamic layout switch is handled we
+ // cannot set gridDetails.iGridDimensions = TSize(1,1). Instead, we use the
+ // grid view's value -> a fully populated grid no longer loses its
+ // dimension information. Default value TSize(1,1) is now set in grid
+ // view's constructor.
+ gridDetails.iGridDimensions = gridView->GridCellDimensions();
+ gridDetails.iGridFlags = gridFlags;
+ gridDetails.iPageSize = iNumOfColsInView*iNumOfRowsInView;
+ gridDetails.iColsInView = iNumOfColsInView;
+ gridDetails.iRowsInView = iNumOfRowsInView;
+ gridDetails.iSizeBetweenItems = iSpaceBetweenItems;
+ gridDetails.iSizeOfItems = aSizeOfItems;
+ CalcGridSizeL();
+ gridView->SetGridDetails(gridDetails);
+
+ gridView->SetColumnWidth(aSizeOfItems.iWidth);
+ SetItemHeightL(aSizeOfItems.iHeight);
+ SetItemsInSingleLine(gridDetails.iColsInView);
+
+ // Create the scroll bars
+ _AKNTRACE( "Create scroll bar" );
+ CreateScrollBarFrameL(ETrue, EFalse, ETrue);
+ ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);
+ UpdateScrollBarsL();
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C void CAknGrid::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ if ( AknLayoutUtils::PenEnabled() )
+ {
+ // Scroll bar
+ // Do not use iSBFrame->VerticalScrollBar()->Rect() to test,
+ // because of iSBFrame->VerticalScrollBar owning window.
+ if( iSBFrame && TRect(iSBFrame->VerticalScrollBar()->Position(),
+ iSBFrame->VerticalScrollBar()->Size()).Contains ( aPointerEvent.iPosition ))
+ {
+ if ( !ScrollingDisabled()
+ && iExtension->iFlags & EAknGridStateButton1DownInGrid )
+ {
+ if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
+ {
+ iExtension->iFlags &= ~EAknGridStateButton1DownInGrid;
+ }
+ CEikListBox::HandlePointerEventL( aPointerEvent );
+ }
+ else
+ {
+ CCoeControl::HandlePointerEventL( aPointerEvent );
+ }
+ return;
+ }
+ else
+ {
+ CAknGridView* gridView = GridView();
+ TInt itemIndex = 0;
+
+ TRect visibleItemsRect(gridView->ViewRect().iTl,
+ TSize(gridView->ItemSize(itemIndex).iWidth * iNumOfColsInView,
+ gridView->ItemSize(itemIndex).iHeight * iNumOfRowsInView));
+
+ // switch pointer event type and set button 1 down in grid flag on and off depending where event happened.
+ switch (aPointerEvent.iType)
+ {
+ case TPointerEvent::EButton1Down:
+ iExtension->iLastPoint = aPointerEvent.iPosition;
+ if ( visibleItemsRect.Contains(aPointerEvent.iPosition) )
+ {
+ iExtension->iFlags |= EAknGridStateButton1DownInGrid;
+ }
+ _AKNTRACE( "TPointerEvent::EButton1Down" );
+ break;
+
+ case TPointerEvent::EButton1Up:
+ {
+ iExtension->iFlags &= ~EAknGridStateButton1DownInGrid;
+ _AKNTRACE( "TPointerEvent::EButton1Up" );
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ CEikListBox::HandlePointerEventL( aPointerEvent ); // eventually will call CAknGrid::HandleDragEventL if dragged
+ }
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C void* CAknGrid::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+/**
+* Sets the layout from a resource. Layout includes orientation
+* (either vertical or horizontal), horizontal and vertical direction
+* of numbering, the number of items in the primary and secondary
+* orientation, and the primary and secondary scrolling types.
+*/
+EXPORT_C void CAknGrid::SetLayoutFromResourceL(TResourceReader& aReader)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ TInt layoutFlags = aReader.ReadInt16();
+ TInt primaryScroll=aReader.ReadInt16();
+ TInt secondaryScroll=aReader.ReadInt16();
+ TInt numItemsInPrimaryOrient=aReader.ReadInt16();
+ TInt numItemsInSecondaryOrient=aReader.ReadInt16();
+ TInt height = aReader.ReadInt16();
+ TInt width = aReader.ReadInt16();
+ TInt gapWidth = aReader.ReadInt16();
+ TInt gapHeight = aReader.ReadInt16();
+
+ TGridOrientation gridOrientation = EGridOrientationHorizontal;
+ if (layoutFlags & EAknGridVerticalOrientation)
+ gridOrientation = EGridOrientationVertical;
+
+ TGridHorizontal gridHorizontal = EGridHorizontalWritingDirection;
+ if (layoutFlags & EAknGridLeftToRight)
+ gridHorizontal = EGridHorizontalLeftToRight;
+ else if (layoutFlags & EAknGridRightToLeft)
+ gridHorizontal = EGridHorizontalRightToLeft;
+// else if (layoutFlags & EAknGridHorizontalAntiWritingDirection)
+// gridHorizontal = EGridHorizontalAntiWritingDirection;
+ else if (layoutFlags & EAknGridLanguageSpecificHorizontalDirection)
+ gridHorizontal = EGridHorizontalWritingDirection;
+
+ TGridVertical gridVertical = EGridVerticalTopToBottom;
+ if (layoutFlags & EAknGridBottomToTop)
+ gridVertical = EGridVerticalBottomToTop;
+
+ CAknGridView::TScrollingType prime = CAknGridView::EScrollFollowsItemsAndLoops;
+ CAknGridView::TScrollingType second = CAknGridView::EScrollFollowsItemsAndLoops;
+
+ switch(primaryScroll)
+ {
+ case EAknGridFollowsItemsAndStops:
+ prime = CAknGridView::EScrollFollowsItemsAndStops;
+ break;
+ case EAknGridFollowsItemsAndLoops:
+ prime = CAknGridView::EScrollFollowsItemsAndLoops;
+ break;
+ case EAknGridFollowsGrid:
+ prime = CAknGridView::EScrollFollowsGrid;
+ break;
+ case EAknGridStops:
+ prime = CAknGridView::EScrollStops;
+ break;
+ case EAknGridIncrementLineAndStops:
+ prime = CAknGridView::EScrollIncrementLineAndStops;
+ break;
+ case EAknGridIncrementLineAndLoops:
+ prime = CAknGridView::EScrollIncrementLineAndLoops;
+ break;
+ default:
+ break;
+ }
+
+ switch(secondaryScroll)
+ {
+ case EAknGridFollowsItemsAndStops:
+ second = CAknGridView::EScrollFollowsItemsAndStops;
+ break;
+ case EAknGridFollowsItemsAndLoops:
+ second = CAknGridView::EScrollFollowsItemsAndLoops;
+ break;
+ case EAknGridFollowsGrid:
+ second = CAknGridView::EScrollFollowsGrid;
+ break;
+ case EAknGridStops:
+ second = CAknGridView::EScrollStops;
+ break;
+ case EAknGridIncrementLineAndStops:
+ second = CAknGridView::EScrollIncrementLineAndStops;
+ break;
+ case EAknGridIncrementLineAndLoops:
+ second = CAknGridView::EScrollIncrementLineAndLoops;
+ break;
+ default:
+ break;
+ }
+ TSize itemSize(width,height);
+ DoSetLayoutL(gridOrientation, gridHorizontal, gridVertical, numItemsInPrimaryOrient, numItemsInSecondaryOrient, itemSize, gapWidth, gapHeight);
+ SetPrimaryScrollingType(prime);
+ SetSecondaryScrollingType(second);
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+
+/**
+* Sets the movement of the cursor with respect to scrolling when the
+* end item in the current row or column, whichever is the primary
+* orientation of the data items, is encountered. The movement maybe
+* either stop, loop back to same row or column or move onto the
+* next logical data item in the sequence.
+*/
+EXPORT_C void CAknGrid::SetPrimaryScrollingType(CAknGridView::TScrollingType aScrollingType)
+ {
+ __TEST_INVARIANT;
+ GridView()->SetPrimaryScrollingType(aScrollingType);
+ }
+
+/**
+* Sets the movement of the cursor with respect to scrolling when the
+* end item in the secondary dimension of the grid is encountered.
+* The movement maybe either stop, loop back back to same row or column
+* or move onto the next logical data item in the sequence.
+*/
+EXPORT_C void CAknGrid::SetSecondaryScrollingType(CAknGridView::TScrollingType aSecondaryScrolling)
+ {
+ __TEST_INVARIANT;
+ GridView()->SetSecondaryScrollingType(aSecondaryScrolling);
+ }
+
+/**
+* Returns the current grid data index.
+* Returns -1 if the grid is empty.
+*/
+EXPORT_C TInt CAknGrid::CurrentDataIndex() const
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+ if (GridModel()->NumberOfData() < 1)
+ {
+ _AKNTRACE( "no data in model, return -1" );
+ _AKNTRACE_FUNC_EXIT;
+ return -1;
+ }
+ TInt startOffset = GridModel()->IndexOfFirstDataItem();
+ _AKNTRACE_FUNC_EXIT;
+ return (GridView()->CurrentDataIndex() - startOffset);
+ }
+
+/**
+* Moves the cursor to the required grid data index.
+*/
+EXPORT_C void CAknGrid::SetCurrentDataIndex(TInt aDataIndex)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+ _AKNTRACE( "[%s] aDataIndex = %d",
+ __FUNCTION__, aDataIndex );
+ TInt startOffset = GridModel()->IndexOfFirstDataItem();
+
+ if (startOffset == -1)
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return; // there is no data yet
+ }
+ TInt newIndex = aDataIndex + startOffset;
+
+ GridView()->SetCurrentDataIndex(newIndex);
+ UpdateScrollBarThumbs();
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* Sets the starting position of the data within the grid.
+* <p>
+* Note: a blank page cannot be accessed (since cannot move into empty cells)
+* so a totally blank page is the same as if the page never existed since
+* the user cannot scroll into it. For this reason it is suggested that
+* the start position be no more than one page into the grid.
+*/
+EXPORT_C void CAknGrid::SetStartPositionL(TPoint aGridStartPosition)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+
+ TInt dataIndex;
+ CAknGridView* gridView = GridView();
+ gridView->DataIndexFromLogicalPos(dataIndex,aGridStartPosition.iY,aGridStartPosition.iX);
+
+ // set the number of blank start cells
+ GridModel()->SetStartCells(dataIndex);
+
+ // need to check grid size
+ CalcGridSizeL();
+
+ // check current item position
+ gridView->SetCurrentDataIndex(dataIndex);
+ iCurrentIsValid = ETrue;
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* Gives the data index at the grid position given.
+* The position must be given with respect to the top left corner
+* of the grid.
+* An index value of -1 is given if the grid position given is
+* invalid.
+*/
+EXPORT_C TInt CAknGrid::IndexOfPosition(TPoint aGridPosition) const
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+
+ TInt indexValue = -1;
+
+
+ CAknGridView* gridView = GridView();
+ TSize gridSize = gridView->GridCellDimensions();
+
+ if ((aGridPosition.iY >= 0)&&
+ (aGridPosition.iX >= 0)&&
+ (aGridPosition.iX < gridSize.iWidth)&&
+ (aGridPosition.iY < gridSize.iHeight))
+ {
+ // grid position is valid
+ gridView->DataIndexFromLogicalPos(indexValue, aGridPosition.iY, aGridPosition.iX);
+
+ indexValue -= GridModel()->IndexOfFirstDataItem();
+ }
+
+ _AKNTRACE_FUNC_EXIT;
+ return indexValue;
+ }
+
+/**
+* Gives the position of the data item required.
+* The logical position is given with respect to the top left
+* hand corner of the grid.
+* A position of (-1,-1) is given if the data item is not valid.
+*/
+EXPORT_C TPoint CAknGrid::PositionAtIndex(TInt aItemIndex) const
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+ _AKNTRACE(" [%s] aItemIndex = %d",
+ __FUNCTION__, aItemIndex );
+
+ TPoint gridPosition(-1,-1);
+
+ CAknGridM* gridModel = GridModel();
+
+ TInt startOffset = gridModel->IndexOfFirstDataItem();
+ TInt newIndex = aItemIndex + startOffset;
+
+ if (ItemExists(newIndex))
+ {
+ if (gridModel->IndexContainsData(newIndex))
+ {
+ GridView()->
+ LogicalPosFromDataIndex(newIndex, gridPosition.iY, gridPosition.iX);
+ }
+ }
+
+ _AKNTRACE_FUNC_EXIT;
+ return gridPosition;
+ }
+
+
+EXPORT_C CListBoxView* CAknGrid::MakeViewClassInstanceL()
+ {
+ return (new(ELeave) CAknGridView);
+ }
+
+/**
+* Sets the column width of the grid.
+* Column width cannot be set in a horizontal grid since the number
+* of columns in the grid is defined by the initialising call to
+* SetLayoutL.
+* The column width cannot be larger than the width of the viewing
+* rectangle.
+*/
+EXPORT_C void CAknGrid::SetColumnWidth(TInt aColumnWidth)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+ _AKNTRACE(" [%s] aColumnWidth = %d",
+ __FUNCTION__, aColumnWidth );
+
+ if (aColumnWidth < 1)
+ return;
+
+ TInt currentDataIndex = 0;
+
+ CAknGridView* gridView = GridView();
+ if (iCurrentIsValid)
+ {
+ // remember current position
+ currentDataIndex = gridView->CurrentDataIndex();
+ }
+
+ // hold the users value in case needed in the method
+ // HandleItemAdditionL
+ iMinColWidth = aColumnWidth;
+
+ gridView->SetColumnWidth(aColumnWidth);
+
+ // check grid orientated to show current focus (item height
+ // change may have moved the focus to a new page)
+ if (iCurrentIsValid)
+ gridView->SetCurrentDataIndex(currentDataIndex);
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* Sets the row height of the grid.
+* Row height cannot be set in a vertical grid since the number
+* of rows in the grid is defined by the initialising call to
+* SetLayoutL.
+* The row height cannot be larger than the height of the viewing
+* rectangle.
+*/
+EXPORT_C void CAknGrid::SetItemHeightL(TInt aHeight)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ __TEST_INVARIANT;
+ _AKNTRACE(" [%s] aHeight = %d",
+ __FUNCTION__, aHeight );
+
+ if (aHeight < 1)
+ return;
+
+ TInt currentDataIndex = 0;
+
+ CAknGridView* gridView = GridView();
+ if (iCurrentIsValid)
+ {
+ // remember current position
+ currentDataIndex = gridView->CurrentDataIndex();
+ }
+
+ // this ensures that if user changes the item height then the
+ // grid details will change in line as well
+ iItemHeight = aHeight;
+
+ gridView->SetItemHeight(aHeight);
+
+ CalcGridSizeL();
+
+ // check grid orientated to show current focus (item height
+ // change may have moved the focus to a new page)
+ if (iCurrentIsValid)
+ gridView->SetCurrentDataIndex(currentDataIndex);
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* Processes the user key events or passes them onto the underlying
+* listbox code.
+*/
+EXPORT_C TKeyResponse CAknGrid::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ // SERIES60 LAF
+ CListBoxView::TSelectionMode selectionMode = CListBoxView::ENoSelection;
+
+ TBool shiftKeyPressed = (aKeyEvent.iModifiers & EModifierShift);
+ if (iListBoxFlags & EMultipleSelection)
+ {
+ if (shiftKeyPressed && iListBoxFlags & EShiftEnterMarks)
+ {
+ View()->SetAnchor(View()->CurrentItemIndex());
+ selectionMode = CListBoxView::EDisjointMarkSelection;
+ }
+ else
+ selectionMode = CListBoxView::ENoSelection;
+ }
+
+ // With single click first key event enables highlight
+ if ( iExtension->iSingleClickEnabled
+ && ItemDrawer()->Flags()
+ & CListItemDrawer::ESingleClickDisabledHighlight )
+ {
+ if ( aKeyEvent.iCode == EKeyUpArrow ||
+ aKeyEvent.iCode == EKeyDownArrow ||
+ aKeyEvent.iCode == EKeyLeftArrow ||
+ aKeyEvent.iCode == EKeyRightArrow ||
+ aKeyEvent.iCode == EKeyEnter ||
+ aKeyEvent.iCode == EKeyOK )
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return CEikListBox::OfferKeyEventL( aKeyEvent, aType );
+ }
+ }
+
+ switch (aKeyEvent.iCode)
+ {
+ case EKeyUpArrow:
+ iView->MoveCursorL(CListBoxView::ECursorPreviousItem, selectionMode);
+ ClearMatchBuffer();
+ _AKNTRACE( "EKeyUpArrow" );
+ break;
+ case EKeyDownArrow:
+ iView->MoveCursorL(CListBoxView::ECursorNextItem, selectionMode);
+ ClearMatchBuffer();
+ _AKNTRACE( "EKeyDownArrow" );
+ break;
+
+ case EKeyPrevious:
+ {
+ const TBool disableRedraw = aKeyEvent.iRepeats;
+ TBool redrawDisabled = iView->RedrawDisabled();
+ if ( disableRedraw )
+ {
+ iView->SetDisableRedraw(ETrue);
+ }
+
+ ((CAknGridView*)iView)->
+ MoveCursorWithRepeatsL( EFalse, selectionMode, 1 + aKeyEvent.iRepeats );
+ ClearMatchBuffer();
+
+ if ( disableRedraw )
+ {
+ iView->SetDisableRedraw(redrawDisabled);
+ if ( !redrawDisabled )
+ {
+ DrawNow();
+ }
+ }
+ }
+ _AKNTRACE( "EKeyPrevious" );
+ break;
+
+ case EKeyLeftArrow:
+ iView->MoveCursorL(CListBoxView::ECursorPreviousColumn, selectionMode);
+ ClearMatchBuffer();
+ _AKNTRACE( "EKeyLeftArrow" );
+ break;
+
+ case EKeyNext:
+ {
+ const TBool disableRedraw = aKeyEvent.iRepeats;
+ TBool redrawDisabled = iView->RedrawDisabled();
+ if ( disableRedraw )
+ {
+ iView->SetDisableRedraw(ETrue);
+ }
+
+ ((CAknGridView*)iView)->
+ MoveCursorWithRepeatsL( ETrue, selectionMode, 1 + aKeyEvent.iRepeats );
+ ClearMatchBuffer();
+
+ if ( disableRedraw )
+ {
+ iView->SetDisableRedraw(redrawDisabled);
+ if ( !redrawDisabled )
+ {
+ DrawNow();
+ }
+ }
+ }
+ _AKNTRACE( "EKeyNext" );
+ break;
+
+ case EKeyRightArrow:
+ iView->MoveCursorL(CListBoxView::ECursorNextColumn, selectionMode);
+ ClearMatchBuffer();
+ _AKNTRACE( "EKeyRightArrow" );
+ break;
+
+#if defined(_DEBUG) // only needed when debuging
+ case EKeyPageUp:
+ iView->MoveCursorL(CListBoxView::ECursorPreviousPage, selectionMode);
+ ClearMatchBuffer();
+ break;
+ case EKeyPageDown:
+ iView->MoveCursorL(CListBoxView::ECursorNextPage, selectionMode);
+ ClearMatchBuffer();
+ break;
+ case EKeyHome:
+ iView->MoveCursorL(CListBoxView::ECursorFirstItem, selectionMode);
+ ClearMatchBuffer();
+ break;
+ case EKeyEnd:
+ iView->MoveCursorL(CListBoxView::ECursorLastItem, selectionMode);
+ ClearMatchBuffer();
+ break;
+#endif// end of debug code
+ default:
+ _AKNTRACE_FUNC_EXIT;
+ return CEikListBox::OfferKeyEventL(aKeyEvent,aType);
+ }
+
+ UpdateScrollBarThumbs();
+
+ // matcher cursor code maybe needed here if matcher cursors
+ // supported in future versions, refer to CEikListBox::OfferKeyEventL
+
+ if (iListBoxFlags & EStateChanged)
+ {
+ ReportEventL(MCoeControlObserver::EEventStateChanged);
+ iListBoxFlags &= (~EStateChanged);
+ }
+
+ _AKNTRACE_FUNC_EXIT;
+ return EKeyWasConsumed;
+ }
+/**
+* @return Model
+*/
+EXPORT_C CTextListBoxModel* CAknGrid::Model() const
+ {
+ return STATIC_CAST(CTextListBoxModel*,iModel);
+ }
+
+/**
+* Sets the viewable rect
+*/
+EXPORT_C void CAknGrid::SetRect(const TRect& aRect)
+ {
+ _AKNTRACE_FUNC_ENTER;
+
+ CCoeControl::SetRect(aRect);
+
+ TRect rect(aRect);
+ rect.SetRect(rect.iTl.iX + ListBoxMargins().iLeft, rect.iTl.iY + ListBoxMargins().iTop,
+ rect.iBr.iX - ListBoxMargins().iRight, rect.iBr.iY - ListBoxMargins().iBottom);
+ _AKNTRACE( "The rect of grid are ( %d, %d ) ( %d, %d )",
+ rect.iTl.iX, rect.iTl.iY,
+ rect.iBr.iX, rect.iBr.iY );
+ iView->SetViewRect(rect);
+
+ // basically, this is redundant call, but leaving it out breaks at
+ // least camcorder's colorburstgrid, because SizeChanged() trusts
+ // margin values
+ TRAP_IGNORE( HandleViewRectSizeChangeL() );
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* Called when the view rect changes size
+*/
+EXPORT_C void CAknGrid::HandleViewRectSizeChangeL()
+ {
+ _AKNTRACE_FUNC_ENTER;
+ iView->CalcBottomItemIndex();
+ TInt oldTopItemIndex = TopItemIndex();// store old top item index
+ TInt newTopItemIndex = oldTopItemIndex;// set new same as old
+
+ TInt currentItemIndex = CurrentItemIndex();// get the current item index
+
+ if (currentItemIndex < 0)// check valid
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+
+ iNumOfRowsInView = Max(1, iNumOfRowsInView);// make iNumOfRowsInView > 1
+ iNumOfColsInView = Max(1, iNumOfColsInView);// make iNumOfColsInView > 1
+
+ if ( iOrientationFlags.IsClear( EGridOrientationVertical )&&
+ ( AknLayoutUtils::LayoutMirrored()
+ ? iHorizontalFlags.IsClear( EGridHorizontalLeftToRight )
+ : iHorizontalFlags.IsSet( EGridHorizontalLeftToRight ) ) &&
+ iVerticalFlags.IsSet(EGridVerticalTopToBottom) )
+ {
+ // CAknAppStyleGrid uses this combination of flags
+ AdjustTopItemIndex();
+ }
+ else
+ {
+ // this version is likely to contain bugs.
+ if (currentItemIndex != oldTopItemIndex)
+ {
+ TInt colIndexOfTargetItem = currentItemIndex / iNumOfRowsInView;// iNumOfRowsInView != 0
+ TInt adjustment = newTopItemIndex % iNumOfRowsInView;// iNumOfRowsInView != 0
+ if (adjustment != 0)
+ {
+ // adjust newTopItemIndex till it refers to the index of an item at the top of a column
+ newTopItemIndex -= adjustment;
+ }
+ TInt newBottomItemIndex = newTopItemIndex + (iNumOfColsInView * iNumOfRowsInView) - 1;
+ if (currentItemIndex < newTopItemIndex)
+ newTopItemIndex = colIndexOfTargetItem * iNumOfRowsInView;
+ else if (currentItemIndex > newBottomItemIndex)
+ {
+ TInt colIndexOfNewBottomItem = colIndexOfTargetItem;
+ TInt colIndexOfNewTopItem = colIndexOfNewBottomItem - (iNumOfColsInView - 1);
+ newTopItemIndex = colIndexOfNewTopItem * iNumOfRowsInView;
+ }
+ }
+ else if ((newTopItemIndex != 0) && (iNumOfRowsInView != 0))
+ {
+ TInt adjustment = newTopItemIndex % iNumOfRowsInView;// iNumOfRowsInView != 0
+ if (adjustment != 0)
+ {// adjust newTopItemIndex till it refers to the index of an item at the top of a column
+ newTopItemIndex -= adjustment;
+ }
+ }
+ SetTopItemIndex(newTopItemIndex);
+ }
+
+ iView->CalcDataWidth();
+ UpdateScrollBarsL();
+ iView->CalcBottomItemIndex();
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+/**
+* Set the empty grid text
+*/
+EXPORT_C void CAknGrid::SetEmptyGridTextL(const TDesC& aText)
+ {
+ GridView()->SetListEmptyTextL(aText);
+ }
+
+/////////////////////////////////////////////////////
+/////////////////////////////////////////////////////
+
+EXPORT_C void CAknGrid::SetTopItemIndex(TInt aItemIndex) const
+ {
+ __ASSERT_DEBUG(iView, Panic(EAknPanicGridNoView));
+ iView->SetTopItemIndex(aItemIndex);
+ }
+
+EXPORT_C void CAknGrid::HandleResourceChange(TInt aType)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ // Need to do this to set up the scroll bar model
+ TRAP_IGNORE( UpdateScrollBarsL() );
+
+ if (aType==KEikDynamicLayoutVariantSwitch)
+ {
+ CAknGridView* gridView = GridView();
+
+ gridView->SetItemOffsetInPixels( 0 );
+
+ TSize sizeOfItems;
+ sizeOfItems.iWidth = ( Rect().iBr.iX - Rect().iTl.iX ) / iNumOfColsInView;
+ sizeOfItems.iHeight = ( Rect().iBr.iY - Rect().iTl.iY ) / iNumOfRowsInView;
+
+ CAknGridView::SGrid gridDetails;
+ gridDetails.iGridDimensions = gridView->GridCellDimensions();
+ gridDetails.iPageSize = iNumOfColsInView*iNumOfRowsInView;
+
+ gridDetails.iColsInView = iNumOfColsInView;
+ gridDetails.iRowsInView = iNumOfRowsInView;
+ gridDetails.iSizeBetweenItems = iSpaceBetweenItems;
+ //gridDetails.iSizeOfItems = gridView->ItemSize();
+ gridDetails.iSizeOfItems = sizeOfItems;
+
+ gridView->SetColumnWidth(gridDetails.iSizeOfItems.iWidth);
+ TRAP_IGNORE( SetItemHeightL(gridDetails.iSizeOfItems.iHeight) );
+
+ gridDetails.iGridFlags = 0;
+ if (iOrientationFlags.IsSet(EGridOrientationVertical))
+ gridDetails.iGridFlags |= CAknGridView::EPrimaryIsVertical;
+ if (iVerticalFlags.IsSet(EGridVerticalTopToBottom))
+ gridDetails.iGridFlags |= CAknGridView::ETopToBottom;
+
+ TBool isMirrored = AknLayoutUtils::LayoutMirrored();
+ if (isMirrored)
+ {
+ if (iHorizontalFlags.IsSet(EGridHorizontalAntiWritingDirection)
+ || iHorizontalFlags.IsSet(EGridHorizontalLeftToRight))
+ gridDetails.iGridFlags |= CAknGridView::ELeftToRight;
+ }
+ else
+ {
+ if (iHorizontalFlags.IsSet(EGridHorizontalWritingDirection)
+ || iHorizontalFlags.IsSet(EGridHorizontalLeftToRight))
+ gridDetails.iGridFlags |= CAknGridView::ELeftToRight;
+ }
+ gridView->SetGridDetails(gridDetails);
+
+ SetItemsInSingleLine( gridDetails.iColsInView );
+ }
+
+ CEikListBox::HandleResourceChange(aType);
+
+ TRAP_IGNORE( ItemDrawer()->FormattedCellData()->SetupSkinContextL());
+ // Data extension has animations which will change when skin changes.
+ ItemDrawer()->FormattedCellData()->HandleResourceChange( aType );
+
+ // Need to do this to set up the scroll bar model
+ TRAP_IGNORE( UpdateScrollBarsL() );
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+
+EXPORT_C void CAknGrid::FocusChanged( TDrawNow aDrawNow )
+ {
+ _AKNTRACE_FUNC_ENTER;
+ CEikListBox::FocusChanged( aDrawNow );
+
+ // Grid data needs focus change information to control animations.
+ if( IsFocused() )
+ {
+ ItemDrawer()->FormattedCellData()->FocusGained();
+ }
+ else
+ {
+ ItemDrawer()->FormattedCellData()->FocusLost();
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C TInt CAknGrid::ColumnWidth() const
+ {
+ __ASSERT_DEBUG(iView, Panic(EAknPanicGridNoView));
+ return ((CAknGridView*)iView)->ColumnWidth();
+ }
+
+EXPORT_C TInt CAknGrid::HorizontalNudgeValue() const
+ {
+ return 1; // scroll horizontal by one column when the left/right scroll arrows (i.e. the nudge buttons) are tapped
+ }
+
+EXPORT_C TInt CAknGrid::HorizScrollGranularityInPixels() const
+ {
+ return ColumnWidth(); // horiz scrollbar model set in columns for snaking list box
+ }
+
+EXPORT_C void CAknGrid::AdjustTopItemIndex() const
+ {
+
+ _AKNTRACE_FUNC_ENTER;
+ /*
+ * make sure, that topitemindex points to topmost leftmost visible item
+ * This hackish solution is only valid for appstyle grid & similar grids
+ */
+ if ( iOrientationFlags.IsClear( EGridOrientationVertical )&&
+ ( AknLayoutUtils::LayoutMirrored()
+ ? iHorizontalFlags.IsClear( EGridHorizontalLeftToRight )
+ : iHorizontalFlags.IsSet( EGridHorizontalLeftToRight ) ) &&
+ iVerticalFlags.IsSet(EGridVerticalTopToBottom) )
+ {
+ if ( !iNumOfColsInView )
+ { // just in case
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+
+ TPoint topIndexPoint = iView->ItemPos( TopItemIndex() );
+ TInt bottomOrdinate = topIndexPoint.iY + iItemHeight;
+ if ( TopItemIndex() % iNumOfColsInView == 0
+ && ( bottomOrdinate > 0
+ && bottomOrdinate <= ( iView->ViewRect().iTl.iY + iItemHeight ) )
+ && iView->ViewRect().Contains( iView->ItemPos( CurrentItemIndex() ) ) )
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+
+ // get row of topmost item relative to the whole grid - 0 based indexing
+ TInt topRow = TopItemIndex() / iNumOfColsInView;
+
+ // get row of current item relative to the whole grid - 0 based indexing
+ TInt currRow = CurrentItemIndex() / iNumOfColsInView;
+
+ // top item will be col 0 in topmost row - find out new top item's row
+ TInt newTopRow( topRow ); // prefer minimum adjustment
+ TInt reminder = iView->ViewRect().Height() % ( iItemHeight + iSpaceBetweenItems.iHeight );
+ TInt rowsFitInView = iNumOfRowsInView;
+ if ( reminder > 0 )
+ {
+ rowsFitInView ++;
+ }
+ newTopRow = currRow - rowsFitInView + 1;
+ newTopRow = Max( 0, newTopRow );
+
+ // and calculate new top item index
+ TInt topItemIndex = newTopRow * iNumOfColsInView ;
+ iView->SetItemOffsetInPixels(0);
+ SetTopItemIndex(topItemIndex);
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C void CAknGrid::HandleDragEventL(TPoint aPointerPos)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ // No drag event handling if kinetic scrolling is enabled
+ if ( !ScrollingDisabled() )
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+
+ if ( AknLayoutUtils::PenEnabled() )
+ {
+ if ( !(iExtension->iFlags & EAknGridStateButton1DownInGrid) )
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+
+ CAknGridView* gridView = GridView();
+ TRect maxRect(TPoint( KMinTInt, KMinTInt ), TPoint(KMaxTInt, KMaxTInt));
+ TRect ignoreDragRect;
+ TRect viewRect(gridView->ViewRect());
+ TInt itemIndex = KEikListBoxInvalidIndex ;
+ TBool pointerIsOverAnItem = gridView->XYPosToItemIndex(aPointerPos, itemIndex);
+ // SERIES60 LAF
+ CListBoxView::TSelectionMode selectionMode = CListBoxView::ENoSelection;
+ // CListBoxView::TSelectionMode selectionMode = (iListBoxFlags & EMultipleSelection) ? CListBoxView::EContiguousSelection : CListBoxView::ESingleSelection;
+ // END OF SERIES60 LAF
+ TInt speed = iExtension->GetScrollingSpeed( pointerIsOverAnItem, itemIndex,
+ *gridView, aPointerPos );
+
+ TInt oldCurrentItemIndex = CurrentItemIndex();
+ TRect currentItemRect(gridView->ItemPos(oldCurrentItemIndex), gridView->ItemSize(oldCurrentItemIndex));
+ TInt numOfRows = Max(GridView()->GridCellDimensions().iHeight,1);
+ const TInt placesInGrid = numOfRows * iNumOfColsInView;
+ TBool currItemIsInLastRow = ((placesInGrid - iNumOfColsInView) <= itemIndex) && (placesInGrid > itemIndex);
+ TBool currItemIsInFirstRow = itemIndex >= iNumOfColsInView;
+
+ TRect visibleItemsRect(viewRect.iTl,
+ TPoint(gridView->ItemSize(itemIndex).iWidth * iNumOfColsInView,
+ gridView->ItemSize(itemIndex).iHeight * iNumOfRowsInView));
+
+ if ( speed != 0 )
+ {
+ TInt itemCountInRow = iNumOfColsInView;
+ TInt dest = itemIndex + speed * itemCountInRow;
+ TInt offset = 0;
+ TInt newTopIndex = dest / itemCountInRow * itemCountInRow;
+ TInt upperBound = iModel->NumberOfItems() - 1;
+
+ if ( speed > 0 )
+ {
+
+ if ( gridView->ActualDataIndex( dest ) <= upperBound )
+ {
+ offset = -itemCountInRow;
+ }
+ else
+ {
+ dest = gridView->ListBoxIndex( upperBound );
+ offset = itemIndex - dest; // Don't make focus jump.
+ }
+ newTopIndex -= ( iNumOfRowsInView - 1) * itemCountInRow ;
+ }
+ else if ( speed < 0 )
+ {
+ if ( dest > 0 )
+ {
+ offset = itemCountInRow;
+ }
+ else
+ {
+ offset = itemIndex - dest;
+ newTopIndex = 0;
+ }
+ }
+
+ if ((iListBoxFlags & ES60StyleMarkable) &&
+ ( (EventModifiers() & EModifierShift) ||
+ (EventModifiers() & EModifierCtrl) ))
+ {
+ selectionMode = CListBoxView::EPenMultiselection;
+ iListBoxFlags |= EStateChanged;
+ }
+ TInt oldtop = gridView->TopItemIndex();
+ if ( !gridView->ItemIsVisible( dest ))
+ {
+ gridView->VScrollTo( newTopIndex );
+ UpdateScrollBarThumbs();
+ if ( pointerIsOverAnItem )
+ {
+ Window().RequestPointerRepeatEvent(
+ KEikListBoxPointerRepeatInterval, viewRect );
+ }
+ }
+ itemIndex = dest + offset;
+ }
+
+
+ // if pointer is over some new item.
+ if ( pointerIsOverAnItem )
+ {
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal(
+ iView->ItemDrawer()->Gc() );
+ if ( transApi && !transApi->EffectsDisabled() )
+ {
+ transApi->SetMoveType( itemIndex < oldCurrentItemIndex ?
+ MAknListBoxTfxInternal::EListMoveUp :
+ MAknListBoxTfxInternal::EListMoveDown );
+ }
+#endif
+ if ((iListBoxFlags & ES60StyleMarkable) &&
+ ( (EventModifiers() & EModifierShift) ||
+ (EventModifiers() & EModifierCtrl) ))
+ {
+ selectionMode = CListBoxView::EPenMultiselection;
+ iListBoxFlags |= EStateChanged;
+ }
+
+ gridView->MoveToItemIndexL(itemIndex, selectionMode);
+ }
+ else if ((aPointerPos.iY < visibleItemsRect.iTl.iY) &&
+ (aPointerPos.iX > visibleItemsRect.iTl.iX) &&
+ (aPointerPos.iX < visibleItemsRect.iBr.iX) &&
+ !currItemIsInFirstRow) // Dragged upwards from the grid.
+ {
+ ignoreDragRect = TRect(maxRect.iTl, TPoint(maxRect.iBr.iX, visibleItemsRect.iTl.iY));
+
+ MoveToNextOrPreviousItemL(aPointerPos);
+
+ if ( (iListBoxFlags & ES60StyleMarkable) &&
+ ( (EventModifiers() & EModifierShift) ||
+ (EventModifiers() & EModifierCtrl) ))
+ {
+ iView->UpdateSelectionL(CListBoxView::EPenMultiselection);
+ iListBoxFlags |= EStateChanged;
+ }
+
+ UpdateScrollBarThumbs();
+
+ Window().RequestPointerRepeatEvent(KEikListBoxPointerRepeatInterval, ignoreDragRect);
+ }
+ else if (aPointerPos.iY > visibleItemsRect.iBr.iY &&
+ (aPointerPos.iX > visibleItemsRect.iTl.iX) &&
+ (aPointerPos.iX < visibleItemsRect.iBr.iX) &&
+ !currItemIsInLastRow) // Dragged downwards from the grid.
+ {
+ ignoreDragRect = TRect(TPoint( maxRect.iTl.iX, visibleItemsRect.iBr.iY), maxRect.iBr );
+
+ MoveToNextOrPreviousItemL(aPointerPos);
+
+ if ( (iListBoxFlags & ES60StyleMarkable) &&
+ ( (EventModifiers() & EModifierShift) ||
+ (EventModifiers() & EModifierCtrl) ))
+ {
+ iView->UpdateSelectionL(CListBoxView::EPenMultiselection);
+ iListBoxFlags |= EStateChanged;
+ }
+
+ UpdateScrollBarThumbs();
+
+ Window().RequestPointerRepeatEvent(KEikListBoxPointerRepeatInterval, ignoreDragRect);
+ }
+
+ if (CurrentItemIndex() != oldCurrentItemIndex)
+ {
+ ReportListBoxEventL(MEikListBoxObserver::EEventItemDraggingActioned);
+ iListBoxFlags |= EStateChanged;
+ if (IsMatchBuffer())
+ {
+ ClearMatchBuffer();
+ DrawMatcherCursor();
+ }
+ }
+ }
+ else
+ {
+ if (!(iListBoxFlags & ELeftDownInViewRect))
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+
+ CAknGridView* gridView = GridView();
+ const TInt clickableBorder = 20; // distance in pixels of area around grid that can see pointer events.
+ TRect ignoreDragRect(TPoint(aPointerPos.iX-clickableBorder, aPointerPos.iY-clickableBorder), TPoint(aPointerPos.iX+clickableBorder, aPointerPos.iY+clickableBorder));
+ TRect viewRect(gridView->ViewRect());
+ TInt itemIndex;
+ TBool pointerIsOverAnItem = gridView->XYPosToItemIndex(aPointerPos, itemIndex);
+ // SERIES60 LAF
+ CListBoxView::TSelectionMode selectionMode = CListBoxView::ENoSelection;
+ // CListBoxView::TSelectionMode selectionMode = (iListBoxFlags & EMultipleSelection) ? CListBoxView::EContiguousSelection : CListBoxView::ESingleSelection;
+ // END OF SERIES60 LAF
+
+ TInt oldCurrentItemIndex = CurrentItemIndex();
+ TRect currentItemRect(gridView->ItemPos(oldCurrentItemIndex), gridView->ItemSize(oldCurrentItemIndex));
+ if (pointerIsOverAnItem)
+ {
+ gridView->MoveToItemIndexL(itemIndex, selectionMode);
+ }
+ else if ((aPointerPos.iX < viewRect.iTl.iX) || (aPointerPos.iX > viewRect.iBr.iX))
+ {
+ // drag event occurred outside the listbox's viewRect
+ if (aPointerPos.iX < viewRect.iTl.iX)
+ gridView->MoveCursorL(CListBoxView::ECursorPreviousColumn, selectionMode);
+ else if (aPointerPos.iX > viewRect.iBr.iX)
+ gridView->MoveCursorL(CListBoxView::ECursorNextColumn, selectionMode);
+ MoveToNextOrPreviousItemL(aPointerPos);
+ UpdateScrollBarThumbs();
+ Window().RequestPointerRepeatEvent(KEikListBoxPointerRepeatInterval, ignoreDragRect);
+ }
+ else
+ {
+ // find item nearest to the pointer pos and make that the current item
+ if (viewRect.Contains(aPointerPos))
+ {
+ }
+ else
+ {
+ if (aPointerPos.iX > currentItemRect.iBr.iX)
+ gridView->MoveCursorL(CListBoxView::ECursorNextColumn, selectionMode);
+ else if (aPointerPos.iX < currentItemRect.iTl.iX)
+ gridView->MoveCursorL(CListBoxView::ECursorPreviousColumn, selectionMode);
+ MoveToNextOrPreviousItemL(aPointerPos);
+ UpdateScrollBarThumbs();
+ Window().RequestPointerRepeatEvent(KEikListBoxPointerRepeatInterval, ignoreDragRect);
+ }
+ }
+ if (CurrentItemIndex() != oldCurrentItemIndex)
+ {
+ iListBoxFlags |= EStateChanged;
+ if (IsMatchBuffer())
+ {
+ ClearMatchBuffer();
+ DrawMatcherCursor();
+ }
+ }
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C void CAknGrid::RestoreClientRectFromViewRect(TRect& aClientRect) const
+ {
+ _AKNTRACE_FUNC_ENTER;
+ aClientRect=iView->ViewRect();
+ aClientRect.SetRect(aClientRect.iTl.iX - ListBoxMargins().iLeft, aClientRect.iTl.iY - ListBoxMargins().iTop,
+ aClientRect.iBr.iX + ListBoxMargins().iRight, aClientRect.iBr.iY + ListBoxMargins().iBottom);
+ if (!ViewRectHeightAdjustment())
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+ aClientRect.iBr.iY += ViewRectHeightAdjustment();
+ _AKNTRACE( "The rect of grid are ( %d, %d ) ( %d, %d )",
+ aClientRect.iTl.iX, aClientRect.iTl.iY,
+ aClientRect.iBr.iX, aClientRect.iBr.iY );
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C TInt CAknGrid::AdjustRectHeightToWholeNumberOfItems(TRect& aRect) const
+ {
+ _AKNTRACE_FUNC_ENTER;
+ TInt remainder = aRect.Height() % (iItemHeight + iSpaceBetweenItems.iHeight);
+ if (remainder >= iItemHeight)
+ remainder -= iItemHeight;
+ if (remainder != 0)
+ aRect.iBr.iY -= remainder;
+ _AKNTRACE_FUNC_EXIT;
+ return remainder;
+ }
+
+EXPORT_C void CAknGrid::MoveToNextOrPreviousItemL(TPoint aPointerPos)
+ {
+ _AKNTRACE_FUNC_ENTER;
+ // SERIES60 LAF
+ CListBoxView::TSelectionMode selectionMode = CListBoxView::ENoSelection;
+// CListBoxView::TSelectionMode selectionMode = (iListBoxFlags & EMultipleSelection) ? CListBoxView::EContiguousSelection : CListBoxView::ESingleSelection;
+ // END OF SERIES60 LAF
+
+ TInt cix = CurrentItemIndex();
+ TRect currentItemRect(iView->ItemPos(cix), iView->ItemSize(cix));
+ TInt numOfRows = Max(GridView()->GridCellDimensions().iHeight,1);
+
+ TBool currItemIsInLastRow;
+ TBool currItemIsInFirstRow;
+
+ if ( AknLayoutUtils::PenEnabled() )
+ {
+ const TInt placesInGrid = numOfRows * iNumOfColsInView;
+
+ // calculate is the item in first or last row.
+ currItemIsInLastRow = ((placesInGrid - iNumOfColsInView) <= cix) && (placesInGrid > cix);
+ currItemIsInFirstRow = (cix >= 0 && cix < iNumOfColsInView);
+ }
+ else
+ {
+ currItemIsInLastRow = ((cix % numOfRows) == (numOfRows-1));
+ currItemIsInFirstRow = ((cix % numOfRows) == 0);
+ }
+
+ TBool currItemIsLastItem = (cix == (iModel->NumberOfItems()-1));
+
+ if ((aPointerPos.iY > currentItemRect.iBr.iY) && (! (currItemIsInLastRow || currItemIsLastItem)))
+ {
+ iView->MoveCursorL(CListBoxView::ECursorNextItem, selectionMode);
+ }
+ else if ((aPointerPos.iY < currentItemRect.iTl.iY) && (! currItemIsInFirstRow))
+ {
+ iView->MoveCursorL(CListBoxView::ECursorPreviousItem, selectionMode);
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C void CAknGrid::UpdateScrollBarsL()
+ {
+ _AKNTRACE_FUNC_ENTER;
+ if (!iSBFrame)
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+ TEikScrollBarModel hSbarModel;
+ TEikScrollBarModel vSbarModel;
+ CAknGridView* gridView = GridView();
+ TRect rect=gridView->ViewRect();
+ if (!(iListBoxFlags & EScrollBarSizeExcluded))
+ {
+ // Ignore scrollbars presence to set the model, Scrollbar Frame will change it as required
+ rect = iBorder.InnerRect(Rect());
+ rect.SetRect(rect.iTl.iX + ListBoxMargins().iLeft, rect.iTl.iY + ListBoxMargins().iTop,
+ rect.iBr.iX - ListBoxMargins().iRight, rect.iBr.iY - ListBoxMargins().iBottom);
+ AdjustRectHeightToWholeNumberOfItems(rect);
+ // rect is now viewRect when ignoring scrollbars
+ }
+ if (iSBFrame->VScrollBarVisibility()!=CEikScrollBarFrame::EOff)
+ {
+ TInt currentIndex = CurrentItemIndex();
+ if (currentIndex < 0)
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return; // current item is not defined
+ }
+ TInt row = 0;
+ TInt col = 0;
+ gridView->LogicalPosFromListBoxIndex(currentIndex, row, col);
+ row *= iView->ItemHeight();
+ row -= iView->ItemOffsetInPixels();
+
+ TSize gridSize = gridView->GridCellDimensions();
+ gridSize.iHeight = Max(gridSize.iHeight,1);//check gridSize != 0
+
+ vSbarModel.iThumbPosition = row;
+ // EHXA-7AQ8N4. Only set it to 0 can make scrollbar empty.
+ vSbarModel.iScrollSpan = GridModel()->NumberOfItems() >0 ?
+ gridSize.iHeight : 0;
+ vSbarModel.iThumbSpan = gridView->NumberOfRowsInView();
+ vSbarModel.iScrollSpan = GridModel()->NumberOfItems() >0 ?
+ gridSize.iHeight*iView->ItemHeight() : 0;
+ vSbarModel.iThumbSpan = rect.Height();
+
+ if (iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan)
+ {
+ TInt topRow = 0;
+ TInt topCol = 0;
+ gridView->LogicalPosFromListBoxIndex(TopItemIndex(), topRow, topCol);
+ topRow *= iView->ItemHeight();
+ topRow -= iView->ItemOffsetInPixels();
+ vSbarModel.iThumbPosition = topRow;
+ }
+ if (vSbarModel.iScrollSpan-vSbarModel.iThumbPosition<vSbarModel.iThumbSpan)
+ {
+ vSbarModel.iThumbPosition=Max(0,vSbarModel.iScrollSpan-vSbarModel.iThumbSpan);
+ gridView->MoveToItemIndexL(currentIndex,CListBoxView::ENoSelection); // force a scroll if neccessary
+ }
+ }
+ if (iSBFrame->ScrollBarVisibility(CEikScrollBar::EHorizontal)!=CEikScrollBarFrame::EOff)
+ {
+ GridView()->CalcDataWidth();
+ hSbarModel.iThumbPosition = gridView->HScrollOffset();
+ hSbarModel.iScrollSpan = gridView->DataWidth();
+ }
+
+ if (iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan)
+ {
+ //same scrollbar data within landscape & portraid
+ TInt varietyIndex = Layout_Meta_Data::IsLandscapeOrientation() ? 1: 0;
+ TAknWindowComponentLayout layout = TAknWindowComponentLayout::Compose(
+ AknLayoutScalable_Avkon::listscroll_app_pane(0),
+ AknLayoutScalable_Avkon::scroll_pane_cp15(varietyIndex));
+
+ CEikAppUi* appUi = iEikonEnv->EikAppUi();
+ TRect clientRect = appUi->ClientRect();
+ TRect mainPaneRect;
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
+
+ TRect scrollBarParent = TRect( TPoint(0, 0), mainPaneRect.Size());
+ AknLayoutUtils::LayoutVerticalScrollBar(iSBFrame, scrollBarParent, layout.LayoutLine());
+
+
+ TRect inclusiveRect=Rect();
+
+ TEikScrollBarFrameLayout layoutSB;
+ layoutSB.SetClientMargin(0);
+ layoutSB.SetInclusiveMargin(0);
+ layoutSB.iTilingMode=TEikScrollBarFrameLayout::EInclusiveRectConstant;
+
+ iSBFrame->Tile(&hSbarModel, &vSbarModel );
+ }
+ else
+ {
+ TRect clientRect;
+ RestoreClientRectFromViewRect(clientRect);
+ TRect inclusiveRect=Rect();
+ TEikScrollBarFrameLayout layout;
+ CreateScrollBarFrameLayout(layout);
+ TBool sizeChanged=iSBFrame->TileL(&hSbarModel, &vSbarModel, clientRect, inclusiveRect, layout);
+ if (!sizeChanged)
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+ // else size of client/inclusive rect has changed
+ if (layout.iTilingMode==TEikScrollBarFrameLayout::EClientRectConstant)
+ SetSizeWithoutNotification(inclusiveRect.Size());
+ else
+ {
+ SetViewRectFromClientRect(clientRect);
+ ClearMargins();
+ }
+ }
+ AdjustTopItemIndex();
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C void CAknGrid::UpdateScrollBarThumbs() const
+ {
+ _AKNTRACE_FUNC_ENTER;
+ if (!iSBFrame)
+ {
+ _AKNTRACE_FUNC_EXIT;
+ return;
+ }
+ CAknGridView* gridView = GridView();
+ TInt currentDataIndex = gridView->CurrentDataIndex();
+ TInt row = 0;
+ TInt col = 0;
+ gridView->LogicalPosFromDataIndex(currentDataIndex, row, col);
+ iSBFrame->MoveHorizThumbTo(col);
+ if (iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EArrowHead)
+ {
+ iSBFrame->MoveVertThumbTo(row);
+ iSBFrame->DrawScrollBarsNow();
+ }
+ else
+ {
+ TInt topRow = 0;
+ TInt topCol = 0;
+ gridView->LogicalPosFromListBoxIndex(TopItemIndex(), topRow, topCol);
+ topRow *= iView->ItemHeight();
+ topRow -= iView->ItemOffsetInPixels();
+ iSBFrame->MoveVertThumbTo(topRow);
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+EXPORT_C TInt CAknGrid::CountComponentControls() const
+ {
+ if (GridModel()->NumberOfItems()<=0) return 0;
+ return CEikListBox::CountComponentControls();
+ }
+
+
+// debug only invariant function
+EXPORT_C void CAknGrid::__DbgTestInvariant() const
+ {
+#if defined(_DEBUG)
+ TBool invalid = EFalse;
+
+ if ( !iModel )
+ {
+ invalid = ETrue;
+ }
+
+ if ( !iView )
+ {
+ invalid = ETrue;
+ }
+
+ if ( invalid )
+ {
+ User::Invariant();
+ }
+#endif
+ }
+
+EXPORT_C TAny* CAknGrid::MListBoxModel_Reserved()
+ {
+ return NULL;
+ }
+
+
+//----------------------------------------------------------------------------
+// Handles scroll events received from the scroll bar.
+// Function reads thumb position from model and updates view by these values.
+// One thumb step is actually one row in list, not item in list.
+//----------------------------------------------------------------------------
+//
+EXPORT_C void CAknGrid::HandleScrollEventL( CEikScrollBar* aScrollBar,
+ TEikScrollEvent aEventType )
+ {
+ _AKNTRACE_FUNC_ENTER;
+ if ( AknLayoutUtils::PenEnabled() )
+ {
+ // Read values from model.
+ TInt oldThumbPos = iView->TopItemIndex() / iNumOfColsInView * iView->ItemHeight() - iView->ItemOffsetInPixels();
+ TInt newThumbPos = aScrollBar->ThumbPosition();
+ TInt pageSize = aScrollBar->Model()->iThumbSpan;
+ TInt maxThumbPos = aScrollBar->Model()->MaxThumbPos();
+ TBool update = EFalse;
+
+ switch ( aEventType & KEikScrollEventBarMask )
+ {
+ case KEikScrollEventFromHBar:
+ {
+ switch ( aEventType )
+ {
+ case EEikScrollLeft:
+ {
+ newThumbPos -= HorizontalNudgeValue();
+ break;
+ }
+
+ case EEikScrollRight:
+ {
+ newThumbPos += HorizontalNudgeValue();
+ break;
+ }
+
+ case EEikScrollPageLeft:
+ {
+ newThumbPos -= pageSize;
+ break;
+ }
+
+ case EEikScrollPageRight:
+ {
+ newThumbPos += pageSize;
+ break;
+ }
+
+ case EEikScrollThumbDragVert:
+ {
+ // In the case of drag events, the scrollbar
+ // automatically updates its thumb pos...
+ SuspendEffects( ETrue );
+ break;
+ }
+
+ case EEikScrollThumbReleaseVert:
+ {
+ // In the case of drag events, the scrollbar
+ // automatically updates its thumb pos...
+ SuspendEffects( EFalse );
+ break;
+ }
+
+ default:
+ {
+ // Do nothing
+ break;
+ }
+ }
+
+ newThumbPos = Max( 0, Min( newThumbPos, maxThumbPos ) );
+
+ if ( aEventType != EEikScrollThumbDragHoriz )
+ {
+ iView->HScroll( newThumbPos - oldThumbPos );
+ aScrollBar->SetModelThumbPosition( iView->HScrollOffset() );
+ }
+ break;
+ }
+
+ case KEikScrollEventFromVBar:
+ {
+ switch ( aEventType )
+ {
+ case EEikScrollUp:
+ {
+ if ( oldThumbPos == 0 && (iListBoxFlags & ELoopScrolling) )
+ {
+ // move thumb to downmost site if current is upmost
+ newThumbPos = maxThumbPos;
+ update = ETrue;
+ }
+ break;
+ }
+
+ case EEikScrollDown:
+ {
+ if ( oldThumbPos == maxThumbPos && (iListBoxFlags & ELoopScrolling) )
+ {
+ // move thumb to upmost site if current is downmost
+ newThumbPos = 0;
+ update = ETrue;
+ }
+ break;
+ }
+
+ case EEikScrollThumbDragVert:
+ {
+ SuspendEffects( ETrue );
+ break;
+ }
+
+ case EEikScrollThumbReleaseVert:
+ {
+ SuspendEffects( EFalse );
+ break;
+ }
+
+ default:
+ {
+ // Do nothing
+ break;
+ }
+ }
+
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ MAknListBoxTfxInternal* transApi =
+ CAknListLoader::TfxApiInternal(
+ iView->ItemDrawer()->Gc() );
+ TBool effects = newThumbPos != oldThumbPos &&
+ transApi && !transApi->EffectsDisabled();
+ if ( effects )
+ {
+ transApi->SetMoveType( newThumbPos < oldThumbPos ?
+ MAknListBoxTfxInternal::EListScrollUp :
+ MAknListBoxTfxInternal::EListScrollDown );
+ }
+#endif // RD_UI_TRANSITION_EFFECTS_LIST
+
+ if ( iExtension && !ScrollingDisabled() )
+ {
+ HandlePhysicsScrollEventL( newThumbPos - oldThumbPos );
+ }
+ else
+ {
+ // Do normal scrolling if physics are not enabled.
+ iView->VScrollTo( newThumbPos/iView->ItemHeight() * iNumOfColsInView );
+ }
+
+#ifdef RD_UI_TRANSITION_EFFECTS_LIST
+ if ( effects )
+ {
+ transApi->Draw( Rect() );
+ }
+#endif // RD_UI_TRANSITION_EFFECTS_LIST
+
+ // If event has changed thumb position to different than in
+ // model do by default, then update scroll bar to
+ // correct values.
+ if ( update )
+ {
+ aScrollBar->SetModelThumbPosition(
+ iView->TopItemIndex() / iNumOfColsInView*iView->ItemHeight() - iView->ItemOffsetInPixels() );
+
+ UpdateScrollBarThumbs();
+ }
+ else
+ {
+ aScrollBar->DrawNow();
+ }
+ }
+
+ default:
+ {
+ // Do nothing
+ break;
+ }
+ }
+ }
+ else
+ {
+ CEikListBox::HandleScrollEventL( aScrollBar, aEventType );
+ }
+ _AKNTRACE_FUNC_EXIT;
+ }
+
+
+EXPORT_C TTypeUid::Ptr CAknGrid::MopSupplyObject(TTypeUid aId)
+ {
+ if ( iExtension && iExtension->iIsFromBaseClass )
+ {
+ iExtension->iIsFromBaseClass = EFalse;
+ return CEikListBox::MopSupplyObject( aId );
+ }
+
+ if ( iExtension && aId.iUid == MAknsControlContext::ETypeId )
+ {
+ MAknsControlContext* cc = NULL;
+ iExtension->iIsFromBaseClass = ETrue;
+ if ( !CEikListBox::MopGetObject( cc ))
+ {
+ cc = ItemDrawer()->FormattedCellData()->SkinBackgroundContext();
+ }
+ return MAknsControlContext::SupplyMopObject( aId, cc);
+ }
+ return CEikListBox::MopSupplyObject( aId );
+ }