diff -r 1fc85118c3ae -r 870918037e16 landmarksui/uicontrols/src/lmkiconmap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/landmarksui/uicontrols/src/lmkiconmap.cpp Wed Sep 01 12:31:27 2010 +0100 @@ -0,0 +1,2137 @@ +/* + * Copyright (c) 2002-2010 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: LandmarksUi Content File - Landmarks icon selector map + * + */ + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef RD_TACTILE_FEEDBACK +#include +#endif //RD_TACTILE_FEEDBACK +// For the TEikScrollBarModelType +#include + +#include +#include + +#include + +#include + +#include "lmkiconmap.h" +#include "CLmkUiUtils.h" +#include + +// The offset because of CEikDialogPage +const TInt KHorizontalDialogMargin = 0; +const TInt KVerticalDialogMargin = 0; +const TInt KAknSctCBaButtonDirections = 3; // bottom, right and left + + +/// Unnamed namespace for local definitions +namespace + { + const TInt KNumOfIcons(16); + _LIT( KPanicMsg, "CLmkIconMap" ); + + void Panic(TPanicCode aReason) + { + User::Panic(KPanicMsg, aReason); + } + } // namespace + +// ============================ EXTENSION CLASS =============================== +//Class Declaration +NONSHARABLE_CLASS(CLmkIconMapExtension) : public CBase, +public MObjectProvider + { +public: + CLmkIconMapExtension(); + ~CLmkIconMapExtension(); + +protected: + TTypeUid::Ptr MopSupplyObject(TTypeUid aId); + MObjectProvider* MopNext(); + +public: + // data + MCoeControlObserver *iObserver; + + TUint iFlags; + MObjectProvider* iIconMap; + TInt iMaxVisibleRows; + CAknsFrameBackgroundControlContext* iBgContext; + }; + +// ============================ MEMBER FUNCTIONS OF CLmkIconMapExtension =============================== + +// ----------------------------------------------------------------------------- +// CLmkIconMapExtension::CLmkIconMapExtension +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CLmkIconMapExtension::CLmkIconMapExtension() : + iMaxVisibleRows(0) + { + iObserver = NULL; + } + +// ----------------------------------------------------------------------------- +// CLmkIconMapExtension::MopSupplyObject() +// ----------------------------------------------------------------------------- +// +TTypeUid::Ptr CLmkIconMapExtension::MopSupplyObject(TTypeUid aId) + { + return MAknsControlContext::SupplyMopObject(aId, iBgContext); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMapExtension::MopNext() +// ----------------------------------------------------------------------------- +// +MObjectProvider* CLmkIconMapExtension::MopNext() + { + return iIconMap; + } + +// ----------------------------------------------------------------------------- +// CLmkIconMapExtension::~CLmkIconMapExtension() +// ----------------------------------------------------------------------------- +// +CLmkIconMapExtension::~CLmkIconMapExtension() + { + + delete iBgContext; + } + +// ============================ MEMBER FUNCTIONS OF CLmkIconMap =============================== + +// ----------------------------------------------------------------------------- +// CLmkIconMap::CLmkIconMap +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CLmkIconMap::CLmkIconMap() : + iCursorPos(TPoint(0, 0)), iOldCursorPos(TPoint(0, 0)), iMaxColumns(-1), + iCurrentPage(0), iNumPages(0) + { + iConsArray = (CArrayPtr*) NULL; + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CLmkIconMap* CLmkIconMap::NewL() + { + CLmkIconMap* self = new (ELeave) CLmkIconMap(); + + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); //self + return self; + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::ConstructL() + { + // Must be created here to get the member variables available + iExtension = new (ELeave) CLmkIconMapExtension; + iExtension->iIconMap = this; + + iConsArray = new (ELeave) CAknIconArray(KNumOfIcons); + + iExtension->iFlags = 0x00; + + DoLayout(); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::~CLmkIconMap() +// ----------------------------------------------------------------------------- +// +CLmkIconMap::~CLmkIconMap() + { + delete iSBFrame; + iSBFrame = (CEikScrollBarFrame*) NULL; + + delete iOffscreenBg; + delete iBitmapDevice; + delete iBitmapGc; + + delete iExtension; + iExtension = (CLmkIconMapExtension*) NULL; + + if (iConsArray) + { + iConsArray->ResetAndDestroy(); + delete iConsArray; + iConsArray = (CArrayPtr*) NULL; + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::DoLayout() +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::DoLayout() + { + TRAPD(err, LoadIconL()); + if (err) + return; + + iIsMirrored = AknLayoutUtils::LayoutMirrored(); + iDrawnBefore = EFalse; + CountMaxColumnsAndCellSizes(); + SizeChanged(); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::ConstructFromResourceL() +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::ConstructFromResourceL(TResourceReader& /*aReader*/) + { + LoadIconL(); + CreateScrollBarAndIconRowL(); + + Extension()->iBgContext = CAknsFrameBackgroundControlContext::NewL( + KAknsIIDQsnFrPopup, TRect(0, 0, 1, 1), TRect(0, 0, 1, 1), EFalse); + + if (DrawableWindow() && AknLayoutUtils::PenEnabled()) + { + EnableDragEvents(); + SetGloballyCapturing( ETrue); + SetPointerCapture(ETrue); + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::LoadIcons() +// This actually load the all icons to be shown on dialog from icon file +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::LoadIconL() + { + if (iConsArray) + { + iConsArray->ResetAndDestroy(); + } + // Draw all the Icons. + TFileName* iconFile = CLmkUiUtils::LmkUiIconFileLC(); + + // Create icon bitmap and mask. + for (TInt i(0); i < (KNumOfIcons * 2); i++) + { + CFbsBitmap* bitmap = NULL; + CFbsBitmap* bitmapMask = NULL; + AknIconUtils::CreateIconLC(bitmap, bitmapMask, *iconFile, + EMbmLmkuiQgn_prop_lm_transport + i, + EMbmLmkuiQgn_prop_lm_transport + i + 1); + i++; + AknIconUtils::SetSize(bitmap, TSize(iGridItemWidth, iGridItemHeight)); //fix + AknIconUtils::SetSize(bitmapMask, TSize(iGridItemWidth, + iGridItemHeight)); //fix + CGulIcon* icon = CGulIcon::NewL(bitmap, bitmapMask); + CleanupStack::PushL(icon); + if (iConsArray) + iConsArray->AppendL(icon); + CleanupStack::Pop(icon); // icon + CleanupStack::Pop(bitmapMask); // mask + CleanupStack::Pop(bitmap); // bitmap + } + CleanupStack::PopAndDestroy();// iconFile + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::HeightInRows() +// This actually returns the no of rows to be shown on a page +// Depends upon the Layout size +// ----------------------------------------------------------------------------- +// +TInt CLmkIconMap::HeightInRows() + { + return (iRows); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::CreateScrollBarAndIconRowL() +// This actually creates the scroll bar sets the number of +// pages and rows on a page to be shown +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::CreateScrollBarAndIconRowL() + { + __ASSERT_DEBUG(iExtension, Panic(KLmkPanicInvalidResourceData)); + + __ASSERT_ALWAYS(iConsArray, Panic(KLmkPanicInvalidResourceData)); + + iRows = ((iConsArray->Count() - 1) / iMaxColumns) + 1; + iFirstVisibleRow = 0; + iAnimated = EFalse; + iCursorPos = TPoint(0, 0); + iNumPages = (iRows / iExtension->iMaxVisibleRows) + (iRows + % iExtension->iMaxVisibleRows ? 1 : 0); + iCurrentPage = 1; + + // Create and set the scb visible even though there is nothing to scroll + delete iSBFrame; + iSBFrame = NULL; + + if (AknLayoutUtils::PenEnabled()) + { + iSBFrame = new (ELeave) CEikScrollBarFrame(this, this, ETrue); + } + else + { + iSBFrame = new (ELeave) CEikScrollBarFrame(this, NULL, ETrue); + } + // Decide which type of scrollbar is shown + CAknAppUi* appUi = iAvkonAppUi; + if (AknLayoutUtils::DefaultScrollBarType(appUi) + == CEikScrollBarFrame::EDoubleSpan) + { + // For EDoubleSpan type scrollbar + if (AknLayoutUtils::PenEnabled()) + { + iSBFrame->CreateDoubleSpanScrollBarsL(ETrue, EFalse, ETrue, + EFalse); // window owning scrollbar + } + else + { + iSBFrame->CreateDoubleSpanScrollBarsL(EFalse, EFalse, ETrue, + EFalse); // non-window owning scrollbar + } + iSBFrame->SetTypeOfVScrollBar(CEikScrollBarFrame::EDoubleSpan); + } + else + { + // For EArrowHead type scrollbar + iSBFrame->SetTypeOfVScrollBar(CEikScrollBarFrame::EArrowHead); + } + + iSBFrame->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, + CEikScrollBarFrame::EAuto); + iSBFrame->VerticalScrollBar()->SetMopParent(iExtension); + UpdateScrollIndicatorL(); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::SetIndex +// set the reference of the selected icon index from the table +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::SetIndex(TInt& aIconIndex) + { + iIconIndex = &aIconIndex; + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::MinimumSize +// +// ----------------------------------------------------------------------------- +// +TSize CLmkIconMap::MinimumSize() + { + iIsMirrored = AknLayoutUtils::LayoutMirrored(); + CountMaxColumnsAndCellSizes(); + + TRect rect; + // Used the set rect, but resolution changes cannot be handled when it is used + + TAknLayoutRect dialogLayRect; + + // Main pane without softkeys + TRect mainPaneRect; + if (!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, + mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + // Dialog layout, check variety first + TAknLayoutScalableParameterLimits iconMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + // Calc the variety + TInt maxVariety = iconMapDialogVariety.LastVariety(); + + // Check the CBA, if the orientation is not landscape + // there is not so much varieties + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; // the offset for the certain cba location variety + TInt varietyOffset = maxVariety + 1; // the number of varieties + + // landscape variety number must be calculated offset == number of varieties + // same applies to the variety number for the biggest sized layout for the variety + if (Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; // the offset for one variety + } + + // for right and left cba buttons the max variety is not zero + // the varities are ordered by the location of the cba and the descending order + // e.g the biggest sized layout first, the smallest last + if (location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if (location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; // 2* + } + + TInt varietyNumber = varietyOffset - iRows - 1; + + // if more lines than possible to show, use the default + // (the biggest grid) variety + if (varietyNumber < 0) + varietyNumber = 0; + // if zero rows, use the minimum + else if (iRows <= 0) + varietyNumber -= 1; + + //add the varietyoffset + varietyNumber += maxVarietyOffset; + + if (Layout_Meta_Data::IsLandscapeOrientation() && (location + == AknLayoutUtils::EAknCbaLocationRight)) + { + varietyNumber = 10; + } + else + { + if (iRows == 0) + { + varietyNumber = 5; + } + else + { + varietyNumber = 3; + } + } + // Layout the dialog size + dialogLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber)); + + // Layout the grid + TAknLayoutRect gridWithScrollLayRect; + gridWithScrollLayRect.LayoutRect(dialogLayRect.Rect(), + AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + return TSize(dialogLayRect.Rect().Width(), + gridWithScrollLayRect.Rect().Height()); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::ActivateL() +// This method is needed to set correct initial value to scroll indicator. +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::ActivateL() + { + CCoeControl::ActivateL(); + if (iRows > Extension()->iMaxVisibleRows) + { + UpdateScrollIndicatorL(); + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::OfferKeyEventL +// Handles all the Keypad events +// ----------------------------------------------------------------------------- +// +TKeyResponse CLmkIconMap::OfferKeyEventL(const TKeyEvent& aKeyEvent, + TEventCode /*aModifiers*/) + { + TUint code = aKeyEvent.iCode; + + switch (code) + { + case EKeyLeftArrow: + case '4': + MoveCursorL(-1, 0); + break; + case EKeyRightArrow: + case '6': + MoveCursorL(1, 0); + break; + case EKeyUpArrow: + case '2': + MoveCursorL(0, -1); + break; + case EKeyDownArrow: + case '8': + MoveCursorL(0, 1); + break; + case EKeyOK: + case '5': + case EKeySpace: + case EKeyEnter: + { + if (iConsArray) + { + TInt ret = iMaxColumns * (iFirstVisibleRow + iCursorPos.iY) + + iCursorPos.iX; + if (ret <= iConsArray->Count()) + { + *iIconIndex = ret; + } + else + { + *iIconIndex = -1; + } + } + + } + break; + default: + return EKeyWasNotConsumed; + + } + return EKeyWasConsumed; + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::InputCapabilities() +// +// ----------------------------------------------------------------------------- +// +TCoeInputCapabilities CLmkIconMap::InputCapabilities() const + { + return TCoeInputCapabilities(TCoeInputCapabilities::EAllText); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::SizeChanged() +// Control position of this control is registered for skin library when necessary +// in CEikDialogPage::SetDataPosition, so we do not do that in this method. +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::SizeChanged() + { + // Get the layout + + // Main pane without softkeys + TRect mainPaneRect; + + if (!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, + mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + // Dialog layout, check variety first + TAknLayoutScalableParameterLimits iconMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + TInt maxVariety = iconMapDialogVariety.LastVariety(); + + // Check the CBA, if the orientation is not landscape + // there is not so much varieties + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; // the offset for the certain cba location variety + TInt varietyOffset = maxVariety + 1; + + // landscape variety number must be calculated offset == number of varieties + // same applies to the variety number for the biggest sized layout for the variety + if (Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; // the offset for one variety + } + + // for right and left cba buttons the max variety is not zero + // the varities are ordered by the location of the cba and the descending order + // e.g the biggest sized layout first, the smallest last + if (location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if (location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; // 2* + } + + TInt varietyNumber = varietyOffset - iRows - 1; + + // if more lines than possible to show, use the default + // (the biggest grid) variety + if (varietyNumber < 0) + varietyNumber = 0; + // if zero rows, use the minimum + else if (iRows <= 0) + varietyNumber -= 1; + + //add the varietyoffset + varietyNumber += maxVarietyOffset; + + if (Layout_Meta_Data::IsLandscapeOrientation() && (location + == AknLayoutUtils::EAknCbaLocationRight)) + { + varietyNumber = 10; + } + else + { + if (iRows == 0) + { + varietyNumber = 5; + } + else + { + varietyNumber = 3; + } + + } + + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber)); + + // Calculate the size relatively + TRect relativeDialog(TPoint(0, 0), popupGridLayRect.Rect().Size()); + + // Get the layout of the actual icon grid with scrollbar + TAknLayoutRect gridWithScrollLayRect; + gridWithScrollLayRect.LayoutRect(relativeDialog, + AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + // Then the grid area without scrollbar + // NOTE: The grid with scroll bar is used as reference + TAknLayoutRect gridLayRect; + gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic_popup_pane(0)); + + // Different parent if SCT inside editing menu. + TRect contentRect = gridLayRect.Rect(); + + // The x coordinate is 3 pixels to right and y coordinate 3 pixels up + // so substract from x coordinate and add to y coordinate + if (iIsMirrored) + { + iOffset = TPoint(contentRect.iBr.iX - KHorizontalDialogMargin + - iGridItemWidth + 1, contentRect.iTl.iY + - KVerticalDialogMargin + 1); + iGridTopLeft.iX = contentRect.iBr.iX - KHorizontalDialogMargin + - (iMaxColumns * iGridItemWidth); + iGridTopLeft.iY = contentRect.iTl.iY - KVerticalDialogMargin; + } + else // not mirrored + { + iOffset = TPoint(contentRect.iTl.iX - KHorizontalDialogMargin + 1, + contentRect.iTl.iY - KVerticalDialogMargin + 1); + iGridTopLeft.iX = contentRect.iTl.iX - KHorizontalDialogMargin; + iGridTopLeft.iY = contentRect.iTl.iY - KVerticalDialogMargin; + } + + // The last, update background context + if (Extension()->iBgContext) + { + TInt bgVariety = 0; + if (Layout_Meta_Data::IsLandscapeOrientation()) + bgVariety = 1; + + TAknLayoutRect innerRect; + innerRect.LayoutRect(relativeDialog, + AknLayoutScalable_Avkon::bg_popup_window_pane_g1(bgVariety)); + + Extension()->iBgContext->SetFrameRects(relativeDialog, + innerRect.Rect()); + } + TRAPD(err, UpdateScrollIndicatorL()); + if (err) + return; + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::HandleResourceChange() +// +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::HandleResourceChange(TInt aType) + { + if (aType == KEikDynamicLayoutVariantSwitch) + { + // save the old info for the magnitudes of the SCT grid + TInt oldMaxColumns = iMaxColumns; + //TInt oldMaxRows = 0; + //oldMaxRows = iRows; + // calculate the new magnitudes + DoLayout(); + + // then calculate the index position of the cursor in the icon table + // and update the x and y positions for the new grid with it + + TInt oldCursorPosition = (iFirstVisibleRow + iOldCursorPos.iY) + * oldMaxColumns + iOldCursorPos.iX; + + TInt currentCursorPosition = (iFirstVisibleRow + iCursorPos.iY) + * oldMaxColumns + iCursorPos.iX; + + // the new first row is the top row on the page where the new focus is + iFirstVisibleRow = Extension()->iMaxVisibleRows + * (currentCursorPosition / (iMaxColumns + * Extension()->iMaxVisibleRows)); + + // the cursor positions are relative to current page + iCursorPos.iY = (currentCursorPosition - (iMaxColumns + * iFirstVisibleRow)) / iMaxColumns; + iCursorPos.iX = currentCursorPosition - (iMaxColumns + * iFirstVisibleRow) - (iMaxColumns * iCursorPos.iY); + + iOldCursorPos.iY = (oldCursorPosition - (iMaxColumns + * iFirstVisibleRow)) / iMaxColumns; + iOldCursorPos.iX = oldCursorPosition - (iMaxColumns + * iFirstVisibleRow) - (iMaxColumns * iOldCursorPos.iY); + } + + if (aType == KAknsMessageSkinChange) + { + iOffscreenBgDrawn = EFalse; + } + CCoeControl::HandleResourceChange(aType); + + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::Draw() +// +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::Draw(const TRect& /*aRect*/) const + { + + TInt cursorPos = 0; + CWindowGc& gc = SystemGc(); + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext(this); + + TRect rect = Rect(); + + // Main pane without softkeys + TRect mainPaneRect; + if (!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, + mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + // Dialog layout, check variety first + TAknLayoutScalableParameterLimits iconMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + // The variety starts from 0 so add +1 + TInt maxVariety = iconMapDialogVariety.LastVariety(); + + // Check the CBA, if the orientation is not landscape + // there is not so much varieties + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; // the offset for the certain cba location variety + TInt varietyOffset = maxVariety + 1; + + // landscape variety number must be calculated offset == number of varieties + // same applies to the variety number for the biggest sized layout for the variety + if (Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; // the offset for one variety + } + + // for right and left cba buttons the max variety is not zero + // the varities are ordered by the location of the cba and the descending order + // e.g the biggest sized layout first, the smallest last + if (location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if (location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; // 2* + } + + TInt varietyNumber = varietyOffset - iRows - 1; + + // if more lines than possible to show, use the default + // (the biggest grid) variety + if (varietyNumber < 0) + varietyNumber = 0; + // if zero rows, use the minimum + else if (iRows <= 0) + varietyNumber -= 1; + + //add the varietyoffset + varietyNumber += maxVarietyOffset; + + if (Layout_Meta_Data::IsLandscapeOrientation() && (location + == AknLayoutUtils::EAknCbaLocationRight)) + { + varietyNumber = 10; + } + else + { + varietyNumber = 3; + } + // Layout the dialog size + TAknLayoutRect dialogLayRect; + dialogLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber)); + + // Get the missing height for the background + TInt backgroundHeightOffset = dialogLayRect.Rect().Height() - rect.iBr.iY; + + rect.iBr.iY += backgroundHeightOffset; + + // Check if we got an offscreen bitmap allocated for skin background and + // there is bitmap background in the current skin. + if (iOffscreenBg && iHasBitmapBackground) + { + DrawOffscreenBackgroundIfRequired(); + gc.BitBlt(rect.iTl, iOffscreenBg); + } + else + { + AknsDrawUtils::Background(skin, cc, this, gc, rect); + } + + TInt numberOfIconsToBeDrawn = iConsArray->Count(); + numberOfIconsToBeDrawn -= (iFirstVisibleRow * iMaxColumns); + if (numberOfIconsToBeDrawn > 0) + { + if (numberOfIconsToBeDrawn > (Extension()->iMaxVisibleRows + * iMaxColumns)) + { + numberOfIconsToBeDrawn = Extension()->iMaxVisibleRows + * iMaxColumns; + } + __ASSERT_DEBUG( numberOfIconsToBeDrawn >= 1, Panic( KLmkPanicOutOfRange ) ); + + gc.SetPenStyle(CGraphicsContext::ESolidPen); + gc.SetBrushStyle(CGraphicsContext::ENullBrush); + gc.SetPenSize(TSize(1, 1)); + + // 2) Draw the grid + const TSize gridItemRectSize(iGridItemWidth + 1, iGridItemHeight + 1); + + TInt numberOfGridCellsToBeDrawn = numberOfIconsToBeDrawn; + + TRgb colorLine = AKN_LAF_COLOR(219); + AknsUtils::GetCachedColor(skin, colorLine, KAknsIIDQsnLineColors, + EAknsCIQsnLineColorsCG5); + TRgb colorRecentLine = AKN_LAF_COLOR(215); + AknsUtils::GetCachedColor(skin, colorRecentLine, + KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG7); + + // default pen color + gc.SetPenColor(colorLine); + + TInt fullRows = numberOfGridCellsToBeDrawn / iMaxColumns; + + // how many left after the full rows + numberOfGridCellsToBeDrawn -= fullRows * iMaxColumns; + + TPoint pos = iGridTopLeft; + + TInt endX = pos.iX + iGridItemWidth * iMaxColumns + 1; + TInt endY = pos.iY + iGridItemHeight * fullRows; + + TInt ii = 0; + + if (fullRows) + { + // Draw full vertical lines + for (ii = 0; ii <= iMaxColumns; ii++) + { + gc.SetPenColor(colorLine); + gc.SetPenSize(TSize(1, 1)); + gc.DrawLine(pos, TPoint(pos.iX, endY)); + pos.iX += iGridItemWidth; + } + + pos = iGridTopLeft; + + // Draw full horizontal lines + for (ii = 0; ii <= fullRows; ii++) + { + gc.SetPenSize(TSize(1, 1)); + gc.SetPenColor(colorLine); + gc.DrawLine(pos, TPoint(endX, pos.iY)); + pos.iY += iGridItemHeight; + } + gc.SetPenColor(colorLine); + gc.SetPenSize(TSize(1, 1)); + } + + if (numberOfGridCellsToBeDrawn) + { + // Remaining cells in the last, non-full row + pos = iOffset; + pos.iX--; // iOffset is cell area topLeft, grid is not included in it + pos.iY--; + + pos.iY += iGridItemHeight * fullRows; + + for (ii = 0; ii < numberOfGridCellsToBeDrawn; ii++) + { + gc.DrawRect(TRect(pos, gridItemRectSize)); + + if (iIsMirrored) + pos.iX -= iGridItemWidth; + else + // not mirrored + pos.iX += iGridItemWidth; + } + } + + TInt iconIndex = (iCurrentPage - 1) * (iMaxColumns + * Extension()->iMaxVisibleRows); + TInt lCnt = iConsArray->Count(); + cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + if (lCnt > 0) + { + TRect cellRect(TPoint(0, 0), TSize(iGridItemWidth - 1, + iGridItemHeight - 1)); + for (TInt j = iconIndex, i = 0; j < lCnt && (i + < numberOfIconsToBeDrawn); j++, i++) + { + DrawItem(gc, CursorRect(i), j, (cursorPos == i), EFalse); + } + } + + } + iDrawnBefore = ETrue; + gc.DiscardFont(); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::DrawItem() +// +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::DrawItem(CWindowGc& aGc, const TRect& aSctPosition, + TInt aIconIndex, TBool aHighlighted, TBool aDrawBackground) const + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext(this); + + TBool skins = AknsDrawUtils::Background(skin, cc, aGc, aSctPosition); + TRgb color; + if (!skins) + aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); + if (aHighlighted) + { + TRgb colorHightLightRect = AKN_LAF_COLOR(215); + AknsUtils::GetCachedColor(skin, colorHightLightRect, + KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG7); + aGc.SetPenColor(colorHightLightRect); + aGc.DrawRect(aSctPosition); + + // Shrink by one pixel in all directions. + TRect innerRect = aSctPosition; + innerRect.Shrink(1, 1); + + color = AKN_LAF_COLOR(210); + AknsUtils::GetCachedColor(skin, color, KAknsIIDQsnHighlightColors, + EAknsCIQsnHighlightColorsCG1); + aGc.SetBrushColor(color); + aGc.Clear(innerRect); + } + else if (aDrawBackground) + { + TRect innerRect = aSctPosition; + aGc.SetBrushColor(AKN_LAF_COLOR(0)); + if (!skins) + aGc.Clear(innerRect); + else + AknsDrawUtils::Background(skin, cc, this, aGc, innerRect); + } + + if (iConsArray) + { + TInt lCnt = iConsArray->Count(); + if (lCnt > 0 && aIconIndex < lCnt && aIconIndex >= 0) + { + TRect cellRect(TPoint(0, 0), TSize(iGridItemWidth - 1, + iGridItemHeight - 1)); + + CGulIcon* bitmap = NULL; + bitmap = iConsArray->At(aIconIndex); + TInt numIconsInaPage = Extension()->iMaxVisibleRows * iMaxColumns; + TInt cellIndex = aIconIndex; + if (aIconIndex >= numIconsInaPage) + { + cellIndex = aIconIndex % numIconsInaPage; + } + aGc.BitBltMasked(CursorPoint(cellIndex), bitmap->Bitmap(), + cellRect, bitmap->Mask(), EFalse); + } + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::DrawCursor() +// Optimizes drawing. Only cursor is drawn. +// ----------------------------------------------------------------------------- +void CLmkIconMap::DrawCursor() const + { + // Whole Icon Map has to be drawn at least once. + // If the user presses arrow key before Icon Map has been drawn, + // only cursor position is drawn without this check. + if (!iDrawnBefore) + { + DrawNow(); + } + // Only redraw old and new cursor position cells + ActivateGc(); + CWindowGc& gc = SystemGc(); + + TInt cursorPos = iOldCursorPos.iX + iOldCursorPos.iY * iMaxColumns; + if (cursorPos >= 0) + { + DrawCell(cursorPos, EFalse); + + cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + DrawCell(cursorPos, ETrue); + } + + gc.DiscardFont(); + DeactivateGc(); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::DrawCell +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::DrawCell(TInt aCursorPos, TBool aHighLighted) const + { + // calculate icon index + TInt iconIndex = aCursorPos + iFirstVisibleRow * iMaxColumns; + + // If we are only redrawing for animations, no need to draw non-animated items. + TRect rect = CursorRect(aCursorPos); + + Window().Invalidate(rect); + Window().BeginRedraw(rect); + DrawItem(SystemGc(), rect, iconIndex, aHighLighted, ETrue); + Window().EndRedraw(); + SystemGc().DiscardFont(); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::CursorRect +// ----------------------------------------------------------------------------- +// +TRect CLmkIconMap::CursorRect(TInt aCursorPos) const + { + TPoint pos = iOffset; + + if (iIsMirrored) + { + pos.iX -= (aCursorPos % iMaxColumns) * iGridItemWidth; + } + else // Not mirrored + { + pos.iX += (aCursorPos % iMaxColumns) * iGridItemWidth; + } + + pos.iY += (aCursorPos / iMaxColumns) * iGridItemHeight; + return TRect(pos, TSize(iGridItemWidth - 1, iGridItemHeight - 1)); + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::CursorPoint +// ----------------------------------------------------------------------------- +// +TPoint CLmkIconMap::CursorPoint(TInt aCursorPos) const + { + TPoint pos = iOffset; + + if (iIsMirrored) + { + pos.iX -= (aCursorPos % iMaxColumns) * iGridItemWidth; + } + else // Not mirrored + { + pos.iX += (aCursorPos % iMaxColumns) * iGridItemWidth; + } + + pos.iY += (aCursorPos / iMaxColumns) * iGridItemHeight; + return pos; + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::MoveCursorL +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::MoveCursorL(TInt aDeltaX, TInt aDeltaY) + { + __ASSERT_DEBUG((aDeltaX <= 1) && (aDeltaX >= -1) && (aDeltaY <= 1) + && (aDeltaY >= -1) && ((aDeltaX * aDeltaY) == 0), Panic( + KLmkPanicOutOfRange)); + + if (iIsMirrored) + aDeltaX = -aDeltaX; + + if ((iConsArray->Count() < 8)) + return; + + iOldCursorPos = iCursorPos; + TInt oldFirstVisibleRow = iFirstVisibleRow; + + TInt globalYPos = iCursorPos.iY + iFirstVisibleRow; + TInt lastColumnOnLastRow = ((iConsArray->Count() - 1) % iMaxColumns); + + TInt skipicon = aDeltaX != 0 ? 1 : 0; + + if (aDeltaX < 0) + { + // Cursor was moved to left. + if (iCursorPos.iX > skipicon - 1) + { + iCursorPos.iX -= skipicon; + } + else + { + if (skipicon > iMaxColumns) + { + globalYPos--; + iCursorPos.iX = iMaxColumns; + } + // Go to previous line + globalYPos--; + if (globalYPos < 0) + { + // Cursor was on the first line - go to last line. + globalYPos = iRows - 1; + // x - position to the last item on the last row. + iCursorPos.iX = lastColumnOnLastRow; + } + else + { + // x - position to last column. + iCursorPos.iX = iMaxColumns - skipicon; + } + } + } + + if (aDeltaX > 0) + { + // Cursor was moved to right. + if (globalYPos < iRows - 1) + { + // Not in the last row. + if (iCursorPos.iX < iMaxColumns - skipicon) + { + // If not on the last columns, move cursor to next column. + iCursorPos.iX += skipicon; + } + else + { + // Cursor was on last column, + // move to first column of the next line. + iCursorPos.iX = 0; + globalYPos++; + } + } + else + { + // Currently on the last row. + if (iCursorPos.iX < lastColumnOnLastRow) + { + // If there are more items on this row, move cursor to next item. + iCursorPos.iX++; + } + else + { + // No more item on the current row. + // Move to first item on the first row. + iCursorPos.iX = 0; + globalYPos = 0; + } + } + } + + if (aDeltaY < 0) + { + iCursorPos.iX -= skipicon; + if (iCursorPos.iX < 0) + { + iCursorPos.iX += (iMaxColumns - 1); + globalYPos--; + } + // Cursor was moved to up. + if (globalYPos > 0) + { + // Cursor was not on the first line - move it to previous row. + globalYPos--; + } + else + { + // Move cursot to last to row. + globalYPos = iRows - 1; + if (iCursorPos.iX > lastColumnOnLastRow) + { + // No items in the current column on the last row - + // move cursor to last item on the row. + iCursorPos.iX = lastColumnOnLastRow; + } + } + } + + if (aDeltaY > 0) + { + iCursorPos.iX = (iCursorPos.iX + skipicon) % iMaxColumns; + globalYPos += (iCursorPos.iX + skipicon) / iMaxColumns; + // Cursor was moved to down. + if (globalYPos < iRows - 1) + { + // Cursor is not on the last row. Move cursor to next row. + globalYPos++; + if (globalYPos == iRows - 1 && iCursorPos.iX + > lastColumnOnLastRow) + { + // No items in the current column on the last row - + // move cursor to last item on the row. + iCursorPos.iX = lastColumnOnLastRow; + } + } + else + { + // Cursor was at the last row - move it to the first row. + globalYPos = 0; + } + } + iCursorPos.iY = globalYPos - iFirstVisibleRow; + + if (globalYPos < iFirstVisibleRow) + { + // Cursor was moved from the top row. + if (globalYPos <= 0) + { + iFirstVisibleRow = 0; + iCursorPos = TPoint(iCursorPos.iX, 0); + } + else + { + // If cursor was moved up out of the visible area - show it again. + iFirstVisibleRow -= Extension()->iMaxVisibleRows; + iCursorPos = TPoint(iCursorPos.iX, Extension()->iMaxVisibleRows + - 1); + } + } + + if (globalYPos > iFirstVisibleRow + Extension()->iMaxVisibleRows - 1) + { + if (globalYPos == iRows - 1) + { + // When cursor has moved from the top line, + // it is adjusted to a page boundary. + iCursorPos = TPoint(iCursorPos.iX, (iRows - 1) + % Extension()->iMaxVisibleRows); + iFirstVisibleRow = ((iRows - 1) / Extension()->iMaxVisibleRows) + * Extension()->iMaxVisibleRows; + } + else + { + // If cursor was moved down out of the visible area - show it again. + iFirstVisibleRow += Extension()->iMaxVisibleRows; + iCursorPos = TPoint(iCursorPos.iX, 0); + } + } + + //TInt increment(1); + //if (aDeltaY < 0 || aDeltaX < 0) + // { + //// increment = -1; + // } + if ((iRows > Extension()->iMaxVisibleRows) && (iOldCursorPos.iY + + oldFirstVisibleRow != iCursorPos.iY + iFirstVisibleRow)) + { + UpdateScrollIndicatorL(); + } + + if (oldFirstVisibleRow == iFirstVisibleRow) + { + // Draw only cursor if the view to the content was not scrolled. + DrawCursor(); + } + else + { + DrawNow(); + } + + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::UpdateScrollIndicatorL() +// +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::UpdateScrollIndicatorL() + { + if (!iSBFrame) + { + return; + } + TEikScrollBarModel hSbarModel; + TEikScrollBarModel vSbarModel; + + TEikScrollBarFrameLayout layout; + + // Main pane without softkeys + TRect mainPaneRect; + if (!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, + mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + // Dialog layout, check variety first + TAknLayoutScalableParameterLimits iconMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + TInt maxVariety = iconMapDialogVariety.LastVariety(); + + // Check the CBA, if the orientation is not landscape + // there is not so much varieties + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; // the offset for the certain cba location variety + TInt varietyOffset = maxVariety + 1; + + // landscape variety number must be calculated offset == number of varieties + // same applies to the variety number for the biggest sized layout for the variety + if (Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; // the offset for one variety + } + + // for right and left cba buttons the max variety is not zero + // the varities are ordered by the location of the cba and the descending order + // e.g the biggest sized layout first, the smallest last + if (location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if (location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; // 2* + } + + TInt varietyNumber = varietyOffset - iRows - 1; + + // if more lines than possible to show, use the default + // (the biggest grid) variety + if (varietyNumber < 0) + varietyNumber = 0; + // if zero rows, use the minimum + else if (iRows <= 0) + varietyNumber -= 1; + + //add the varietyoffset + varietyNumber += maxVarietyOffset; + + if (Layout_Meta_Data::IsLandscapeOrientation() && (location + == AknLayoutUtils::EAknCbaLocationRight)) + { + varietyNumber = 10; + } + else + { + varietyNumber = 3; + } + // Layout the dialog size + TAknLayoutRect dialogLayRect; + dialogLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber)); + + TRect dialogRect = dialogLayRect.Rect(); + + // Get the layout of the actual icon grid with scrollbar + TAknLayoutRect gridWithScrollLayRect; + + gridWithScrollLayRect.LayoutRect(TRect(TPoint(0, 0), TSize( + dialogRect.Size())), + AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + // Calculate the relative rect for the grid + TRect parent = gridWithScrollLayRect.Rect(); + + TAknWindowComponentLayout scrollbarLayout = + AknLayoutScalable_Avkon::scroll_pane_cp5(); + + iCurrentPage = (iFirstVisibleRow / Extension()->iMaxVisibleRows) + 1; + + vSbarModel.iScrollSpan = iNumPages * Extension()->iMaxVisibleRows; + vSbarModel.iThumbSpan = Extension()->iMaxVisibleRows; + + if (iSBFrame && iSBFrame->TypeOfVScrollBar() + == CEikScrollBarFrame::EDoubleSpan) + { + // For EDoubleSpan type scrollbar + vSbarModel.iThumbPosition = (iCurrentPage - 1) + * Extension()->iMaxVisibleRows; + TAknDoubleSpanScrollBarModel hDsSbarModel(hSbarModel); + TAknDoubleSpanScrollBarModel vDsSbarModel(vSbarModel); + + // The y coordinate must be sifted 3 pixels up and x 3 to left + parent.iTl.iY -= KVerticalDialogMargin; + parent.iBr.iY -= KVerticalDialogMargin; + parent.iTl.iX -= KHorizontalDialogMargin; + parent.iBr.iX -= KHorizontalDialogMargin; + + layout.iTilingMode = TEikScrollBarFrameLayout::EInclusiveRectConstant; + iSBFrame->Tile(&vDsSbarModel); + AknLayoutUtils::LayoutVerticalScrollBar(iSBFrame, parent, + scrollbarLayout); + iSBFrame->SetVFocusPosToThumbPos(vDsSbarModel.FocusPosition()); + } + else + { + // For EArrowHead type scrollbar + vSbarModel.iThumbPosition = iCursorPos.iY + iFirstVisibleRow; + iSBFrame->TileL(&hSbarModel, &vSbarModel, parent, parent, layout); + iSBFrame->SetVFocusPosToThumbPos(vSbarModel.iThumbPosition); + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::Reserved_1() +// +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::Reserved_1() + { + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::Reserved_2() +// +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::Reserved_2() + { + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::DrawOffscreenBackgroundIfRequired +// +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::DrawOffscreenBackgroundIfRequired() const + { + if (iOffscreenBg && iHasBitmapBackground) + { + if (!iOffscreenBgDrawn) + { + TRect mainPaneRect; + if (!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, + mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + // Dialog layout, check variety first + TAknLayoutScalableParameterLimits + iconMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + TInt maxVariety = iconMapDialogVariety.LastVariety(); + + // Check the CBA, if the orientation is not landscape + // there is not so much varieties + AknLayoutUtils::TAknCbaLocation location = + AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; // the offset for the certain cba location variety + TInt varietyOffset = maxVariety + 1; + + // landscape variety number must be calculated offset == number of varieties + // same applies to the variety number for the biggest sized layout for the variety + if (Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; // the offset for one variety + } + + // for right and left cba buttons the max variety is not zero + // the varities are ordered by the location of the cba and the descending order + // e.g the biggest sized layout first, the smallest last + if (location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if (location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; // 2* + } + TInt varietyNumber = varietyOffset - iRows - 1; + + // if more lines than possible to show, use the default + // (the biggest grid) variety + if (varietyNumber < 0) + varietyNumber = 0; + // if zero rows, use the minimum + else if (iRows <= 0) + varietyNumber -= 1; + + //add the varietyoffset + varietyNumber += maxVarietyOffset; + + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(5)); + + TRect popupGridRect = popupGridLayRect.Rect(); + + // set the top left height as the control starting point + popupGridRect.iTl.iY = Rect().iTl.iY; + + //if(popupGridRect.iBr.iY < mainPaneRect.iBr.iY) + // popupGridRect.iBr.iY = mainPaneRect.iBr.iY + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext(this); + + // draw to upper left corner, and normalize the retangle to + // fact that the dialog starts from coordinates (0,0), + // so the y-coordinate is correct (heading pane) + // but x must be set to zero + TPoint point = TPoint(0, 0); + popupGridRect.Move(-popupGridRect.iTl.iX, 0); + + AknsDrawUtils::DrawBackground(skin, cc, this, *iBitmapGc, point, + popupGridRect, KAknsDrawParamDefault); + + iOffscreenBgDrawn = ETrue; + } + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::ComponentControl(TInt aIndex) const +// Return the controll pointer +// ----------------------------------------------------------------------------- +// +CCoeControl* CLmkIconMap::ComponentControl(TInt aIndex) const + { + if (aIndex == 0 && iSBFrame && iSBFrame->TypeOfVScrollBar() + == CEikScrollBarFrame::EDoubleSpan) + { + return iSBFrame->VerticalScrollBar(); + } + else + { + return NULL; + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::CountComponentControls() +// Return no of controll to be placed on the container control +// ----------------------------------------------------------------------------- +// +TInt CLmkIconMap::CountComponentControls() const + { + if (iSBFrame && iSBFrame->TypeOfVScrollBar() + == CEikScrollBarFrame::EDoubleSpan) + { + return 1; + } + else + { + return 0; + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::CountMaxColumnsAndCellSizes +// Counts no of columns and the cell size will be displayed in the icon table +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::CountMaxColumnsAndCellSizes() + { + + TRect cellRect; // retangle of one item in grid + TRect gridRect; // retangle of the grid contaning the items + + // 1. Get the layout + + // Get the parent rect + TRect mainPaneRect; + if (!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, + mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + // Calculate the layout of the whole popup with the biggest possible -> 0 + // Dialog layout, check variety first + + // Get the layout rect of the dialog + + // Check variety first + TAknLayoutScalableParameterLimits iconMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + TInt maxVariety = iconMapDialogVariety.LastVariety(); + + // Check the CBA, if the orientation is not landscape + // there is not so much varieties + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; // the offset for the certain cba location variety + TInt varietyOffset = maxVariety + 1; // the number of varieties + + // landscape variety number must be calculated offset == number of varieties + // same applies to the variety number for the biggest sized layout for the variety + if (Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; // the offset for one variety + } + + if (location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if (location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; // 2* + } + + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window( + maxVarietyOffset)); + + // Get the layout of the actual icon grid with scrollbar + TAknLayoutRect gridWithScrollLayRect; + gridWithScrollLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + // Then the grid area without scrollbar + // NOTE: The grid with scroll bar is used as reference + TAknLayoutRect gridLayRect; + gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic_popup_pane(0)); + + // Different parent if SCT inside editing menu. + TRect rect = Rect(); + gridRect = gridLayRect.Rect(); + // cell size, AGAIN 7 item + TAknLayoutRect cellLayRect; + cellLayRect.LayoutRect(gridRect, + AknLayoutScalable_Avkon::cell_graphic_popup_pane(0, 0, 0)); + + cellRect = cellLayRect.Rect(); + + // 2. Calculate width related + // - item width + // - max number of columns + + // Width of the items area + TInt gridWidth = gridRect.Width(); + + // Width of one item + TInt cellWidth = cellRect.Width(); + + // ensure the item width and store it + TAknLayoutRect secondCellLayRect; + secondCellLayRect.LayoutRect(gridRect, + AknLayoutScalable_Avkon::cell_graphic_popup_pane(0, 1, 0)); + + iGridItemWidth = secondCellLayRect.Rect().iTl.iX + - cellLayRect.Rect().iTl.iX; + + if (iGridItemWidth < 0) + { + // The result is negative with lay file data if the layout is mirrored. + iGridItemWidth = -iGridItemWidth; + } + + // Calculate the amount of columns + iMaxColumns = gridWidth / cellWidth; + + // 2. Calculate height related + // - item height + // - max number of rows + + // Get the grid height + // NOTE: in landscape the LAF is wrong so use the main panes height + TInt gridHeight = gridRect.Height(); + + // get the item height + TInt cellHeight = cellRect.Height(); + + // calculate the number of items fitting to grid + Extension()->iMaxVisibleRows = 3;//gridHeight / cellHeight; + + + // Store the item height + TAknLayoutRect secondRowLayRect; + secondRowLayRect.LayoutRect(gridLayRect.Rect(), + AknLayoutScalable_Avkon::cell_graphic_popup_pane(0, 0, 1)); + + iGridItemHeight = secondRowLayRect.Rect().iTl.iY + - cellLayRect.Rect().iTl.iY; + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::HandleScrollEventL +// Handles the different scroll events so that the map reacts accordingly. +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::HandleScrollEventL(CEikScrollBar* aScrollBar, + TEikScrollEvent aEventType) + { + TBool update = EFalse; + + switch (aEventType) + { + case EEikScrollUp: + case EEikScrollPageUp: + { + // nothing done if we are already on the first page. + if (iFirstVisibleRow != 0) + { + iFirstVisibleRow -= Extension()->iMaxVisibleRows; + update = ETrue; + } + UpdateScrollIndicatorL(); + } + break; + case EEikScrollDown: + case EEikScrollPageDown: + { + // nothing done if we are already on the last page. + if (iFirstVisibleRow != (iRows / Extension()->iMaxVisibleRows) + * Extension()->iMaxVisibleRows) + { + iFirstVisibleRow += Extension()->iMaxVisibleRows; + update = ETrue; + } + UpdateScrollIndicatorL(); + } + break; + case EEikScrollThumbDragVert: + { + TInt thumbPosition; + TInt halfPage = Extension()->iMaxVisibleRows / 2; + // Ask which type of scrollbar is shown + //CAknAppUi* appUi = iAvkonAppUi; + TBool isDoubleSpan = CEikScrollBarFrame::EDoubleSpan + == iSBFrame->TypeOfVScrollBar(); + if (isDoubleSpan) + { + thumbPosition + = static_cast (aScrollBar->Model())->FocusPosition(); + } + else + { + thumbPosition = aScrollBar->Model()->iThumbPosition; + } + + // If the slider is in the range of less then a half page from a possible correct thumb position. + // thus 0 <= iFirstVisibleRow - thumbPosition < halfPage. Or in the other direction: + // 0 <= thumbPosition - iFirstVisibleRow < halfPage + if (!((0 <= iFirstVisibleRow - thumbPosition && iFirstVisibleRow + - thumbPosition < halfPage) || (0 <= thumbPosition + - iFirstVisibleRow && thumbPosition - iFirstVisibleRow + < halfPage))) + { + TReal toRound = thumbPosition + / (TReal) Extension()->iMaxVisibleRows; + if (toRound * 2 > (TInt) toRound * 2 + 1) + { + toRound++; + } + iFirstVisibleRow = (TInt) toRound + * Extension()->iMaxVisibleRows; + iCurrentPage = (iFirstVisibleRow + / Extension()->iMaxVisibleRows) + 1; + update = ETrue; + } + } + break; + case EEikScrollThumbReleaseVert: + { + UpdateScrollIndicatorL(); + } + break; + case EEikScrollLeft: // flow through + case EEikScrollRight: // flow through + case EEikScrollPageLeft: // flow through + case EEikScrollPageRight: // flow through + case EEikScrollThumbDragHoriz: // flow through + case EEikScrollThumbReleaseHoriz: // flow through + // do nothing + break; + default: + // do nothing + break; + } + + // If we have moved down to the last page we check that the cursor is in a place where it can be + // drawn. + if (iFirstVisibleRow == (iRows / Extension()->iMaxVisibleRows) + * Extension()->iMaxVisibleRows) + { + // the old cursor is set to a "safe" position where it at least can be. + iOldCursorPos.iX = 0; + iOldCursorPos.iY = 0; + // if the last page has only one line which isn't filled complitely. + if (iConsArray->Count() % iMaxColumns - 1 < iCursorPos.iX && iRows + % Extension()->iMaxVisibleRows == 1) + { + TInt xVal = iConsArray->Count() % iMaxColumns - 1; + if (xVal >= 0) + iCursorPos.iX = xVal; + } + // If the cursor is in a position where it would go unto a spot with out + // a icon when scrolled. + if (iCursorPos.iY + iFirstVisibleRow >= iRows) + { + if (iConsArray->Count() % iMaxColumns > iCursorPos.iX) + { + TInt yVal = iRows - 1 - iFirstVisibleRow; + if (yVal >= 0) + iCursorPos.iY = yVal; + } + else + { + TInt yVal = iRows - 2 - iFirstVisibleRow; + if (yVal >= 0) + iCursorPos.iY = yVal; + } + } + // If the cursor is actually on the last row, but is still in the + // area where there is now icons. (the rest of the last row) + if (iConsArray->Count() <= (iFirstVisibleRow + iCursorPos.iY) + * iMaxColumns + iCursorPos.iX && iCursorPos.iY + + iFirstVisibleRow + 1 == iRows) + { + iCursorPos.iY--; + } + // if the corrections did not help and the cursor is in the area + // where there is a valid row, but no icons anymore + } + + // to avoid flicker we draw only if there really was something new to draw. + if (update) + { + if (Extension()->iObserver) + { + Extension()->iObserver->HandleControlEventL(this, + MCoeControlObserver::EEventRequestFocus); + } + DrawDeferred(); + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::Extension +// Asserts that extension object has been created. +// ----------------------------------------------------------------------------- +// +CLmkIconMapExtension* CLmkIconMap::Extension() const + { + __ASSERT_ALWAYS(iExtension, Panic(KLmkPanicNullPointer)); + return iExtension; + } + +#ifdef RD_SCALABLE_UI_V2 +//-------------------------------------------------------------------------- +// void CLmkIconMap::HandlePointerEventL() +//-------------------------------------------------------------------------- +void CLmkIconMap::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + if (AknLayoutUtils::PenEnabled()) + { + TInt newGridX; // For the whole + TInt newGridY; // For the whole grid. + TInt yInPixels = aPointerEvent.iPosition.iY - iGridTopLeft.iY; + newGridY = yInPixels / iGridItemHeight; + if ((aPointerEvent.iPosition.iX - iGridTopLeft.iX) < 0) + { + newGridX = -1; + } + else + { + newGridX = (aPointerEvent.iPosition.iX - iGridTopLeft.iX) + / iGridItemWidth; + } + TInt previousRows = (iRows / iExtension->iMaxVisibleRows) + * iExtension->iMaxVisibleRows; + TUint lastRowsLength = iConsArray->Count() % iMaxColumns; + + // The pointer has been set down or dragged into the area of the grid. (it might be in + // the "white space" at the end of the grid) + if ((yInPixels >= 0 && yInPixels < iGridItemHeight + * iExtension->iMaxVisibleRows) && + // When the pointer is in rows except the recent icon row + ((((newGridY + iFirstVisibleRow) != 0) && newGridX + < iMaxColumns && newGridX >= 0) || + // When the pointer is in the recent icon row + ((newGridY + iFirstVisibleRow == 0) && (newGridX + < iMaxColumns)))) + { + // For any action to be taken, the pointer event must either be a Button1Down or a drag event + // which has originated from a Button1Down in to the grid. + if (aPointerEvent.iType == TPointerEvent::EButton1Down) + { + TUint globalY = newGridY + iFirstVisibleRow; + // The user tapps a cell which has no icon. it is ignored. + if (iConsArray->Count() > globalY * iMaxColumns + newGridX) + { + //If icon is already selected then on single tap it should change the icon. + if (iCursorPos.iY == newGridY && iCursorPos.iX + == newGridX) + { +#ifdef RD_TACTILE_FEEDBACK + // The user tapps a cell which has icon, selection has been accepted + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if (feedback) + { + feedback->InstantFeedback(this, + ETouchFeedbackBasic); + } +#endif //RD_TACTILE_FEEDBACK + //iIsChangeIcon = ETrue; + } + else if (iCursorPos.iX + (iCursorPos.iY + + iFirstVisibleRow) * iMaxColumns + < iConsArray->Count()) + { +#ifdef RD_TACTILE_FEEDBACK + // The user tapps a cell which has icon, send feedback if position has changed + MTouchFeedback* feedback = MTouchFeedback::Instance(); + const TBool feedbackNeeded = (iCursorPos.iY + != newGridY) || (iCursorPos.iX != newGridX); + if (feedback && feedbackNeeded) + { + feedback->InstantFeedback(this, + ETouchFeedbackBasic); + } +#endif //RD_TACTILE_FEEDBACK + iOldCursorPos = iCursorPos; + iCursorPos.iY = newGridY; + iCursorPos.iX = newGridX; + DrawCursor(); + } + else + { + iOldCursorPos = iCursorPos; + iCursorPos.iY = newGridY; + iCursorPos.iX = newGridX; + DrawCursor(); + } + } + } + else if (aPointerEvent.iType == TPointerEvent::EDrag) + { + //Handle drag event only if the icon is not already selected, if already selected then do nothing for EDrag event + if (iCursorPos.iY != newGridY || iCursorPos.iX != newGridX) + { + //iIsChangeIcon = EFalse; + TUint globalY = newGridY + iFirstVisibleRow; + // The user tapps a cell which has no icon. it is ignored. + if (iConsArray->Count() > globalY * iMaxColumns + + newGridX) + { + if (iCursorPos.iX + + (iCursorPos.iY + iFirstVisibleRow) + * iMaxColumns < iConsArray->Count()) + { +#ifdef RD_TACTILE_FEEDBACK + // While dragging cell is changed, give sensitive feedback + MTouchFeedback* feedback = + MTouchFeedback::Instance(); + const TBool feedbackNeeded = (iCursorPos.iY + != newGridY) || (iCursorPos.iX + != newGridX); + if (feedback && feedbackNeeded) + { + feedback->InstantFeedback(this, + ETouchFeedbackSensitive); + } +#endif //RD_TACTILE_FEEDBACK + iOldCursorPos = iCursorPos; + iCursorPos.iY = newGridY; + iCursorPos.iX = newGridX; + DrawCursor(); + } + else + { + iOldCursorPos.iX = 0; + iOldCursorPos.iY = 0; + } + } + } + + } + else if (aPointerEvent.iType == TPointerEvent::EButton1Up) + { + //if (iIsChangeIcon) + + { + iExtension->iObserver->HandleControlEventL(this, + MCoeControlObserver::EEventStateChanged); + //iIsChangeIcon = EFalse; + } + } + } + // Events: Drag and repeat pointer events which are not on the scrollbar are handled here. + + else if (iConsArray->Count() > iMaxColumns + * iExtension->iMaxVisibleRows && newGridX < iMaxColumns + && newGridX >= 0 && newGridY < iExtension->iMaxVisibleRows + && newGridY >= 0) + { + TRect ignoreUpRect(TPoint(KMinTInt, KMinTInt), TPoint(KMaxTInt, + iGridTopLeft.iY)); + TRect ignoreDownRect(TPoint(KMinTInt, (iGridTopLeft.iY + + iGridItemHeight * iExtension->iMaxVisibleRows)), + TPoint(KMaxTInt, KMaxTInt)); + // Drag events + if (aPointerEvent.iType == TPointerEvent::EDrag + || aPointerEvent.iType == TPointerEvent::EButtonRepeat) + { + // The pointer is dragged upwards from map + if (aPointerEvent.iPosition.iY < iGridTopLeft.iY + && aPointerEvent.iPosition.iX < iGridTopLeft.iX) //scroll up + { + // focus on first page + if (iFirstVisibleRow == 0) + { + iFirstVisibleRow = previousRows; + // if the last page contains only one partial row. + if (lastRowsLength - 1 < iCursorPos.iX && iRows + % iExtension->iMaxVisibleRows == 1) + { + iCursorPos.iX = lastRowsLength - 1; + } + } + // focus on some other page than first + else + { + iFirstVisibleRow -= iExtension->iMaxVisibleRows; + } + // For odd reason the user has been able to induce upward dragging with out moving + // up through the grid. + if (iCursorPos.iY + iExtension->iMaxVisibleRows + != iFirstVisibleRow) + { + iCursorPos.iY = 0; + } + UpdateScrollIndicatorL(); + if (iExtension->iObserver) + { + iExtension->iObserver->HandleControlEventL(this, + MCoeControlObserver::EEventRequestFocus); + } + DrawDeferred(); + } + // the pointer is dragged downwards from the map. + else if (yInPixels >= iGridItemHeight + * iExtension->iMaxVisibleRows) //scroll down + { + // The focus is on the last page + if (iFirstVisibleRow == previousRows) + { + iFirstVisibleRow = 0; + iCursorPos.iY = iExtension->iMaxVisibleRows - 1; + } + // The focus is on some other page than the last one. + else + { + iFirstVisibleRow += iExtension->iMaxVisibleRows; + // if the next page is the last page + if (iFirstVisibleRow == previousRows) + { + // the old cursor is set to a "safe" position where it at least can be. + iOldCursorPos.iX = 0; + iOldCursorPos.iY = 0; + + // if the last page has only one line which isn't filled complitely. + if (lastRowsLength - 1 < iCursorPos.iX && iRows + % iExtension->iMaxVisibleRows == 1) + { + iCursorPos.iX = lastRowsLength - 1; + } + // If the cursor is in a position where it would go unto a spot with out + // a icon when scrolled. + if (lastRowsLength > iCursorPos.iX) + { + // + iCursorPos.iY = iRows - 1 - iFirstVisibleRow; + } + else + { + // + iCursorPos.iY = iRows - 2 - iFirstVisibleRow; + } + } + } + UpdateScrollIndicatorL(); + if (iExtension->iObserver) + { + iExtension->iObserver->HandleControlEventL(this, + MCoeControlObserver::EEventRequestFocus); + } + DrawDeferred(); + } + } + } + + else // For a non window owning scrollbar. + { + CCoeControl::HandlePointerEventL(aPointerEvent); + } + } + } + +// ----------------------------------------------------------------------------- +// CLmkIconMap::SetObserver +// Sets the observer. +// ----------------------------------------------------------------------------- +// +void CLmkIconMap::SetObserver( MCoeControlObserver* aObserver ) + { + if (iExtension) + { + iExtension->iObserver = aObserver; + } + } + +#endif //RD_SCALABLE_UI_V2 +// End of File