/*
* 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 <eikenv.h>
#include <eiksbfrm.h>
#include <eikscrlb.h>
#include <bidivisual.h>
#include <avkon.rsg>
#include <AknPanic.h>
#include <avkon.hrh>
#include <AknUtils.h>
#include <aknlayoutscalable_avkon.cdl.h>
#include <layoutmetadata.cdl.h>
#include <AknLayout.lag>
#include <aknappui.h>
#include <aknconsts.h>
#include <AknDef.h>
#include <PUAcodes.hrh>
#include <s32file.h>
#ifdef RD_TACTILE_FEEDBACK
#include <touchfeedback.h>
#endif //RD_TACTILE_FEEDBACK
// For the TEikScrollBarModelType
#include <eikscrlb.h>
#include <AknsDrawUtils.h>
#include <featmgr.h>
#include <AknsFrameBackgroundControlContext.h>
#include <lmkui.mbg>
#include "lmkiconmap.h"
#include "CLmkUiUtils.h"
#include <lmkerrors.h>
// 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<CGulIcon>*) 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<CGulIcon>*) 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<const TAknDoubleSpanScrollBarModel*> (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