diff -r 000000000000 -r 5a93021fdf25 cmmanager/cmmgr/Framework/Src/cmdesticonmap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmmanager/cmmgr/Framework/Src/cmdesticonmap.cpp Thu Dec 17 08:55:21 2009 +0200 @@ -0,0 +1,2061 @@ +/* +* Copyright (c) 2006 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: Implementation of CCmDestinationIconMap +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // TEikScrollBarModelType +#include +#include +#include +#include +#include +#include +#include "cmdesticonmap.h" +#include "cmmanagerimpl.h" + +// The offset because of CEikDialogPage +const TInt KHorizontalDialogMargin = 0; +const TInt KVerticalDialogMargin = 0; +const TInt KAknSctCBaButtonDirections = 3; // bottom, right and left + +/** + * Extension class to CCmDestinationIconMap + * + * @since S60 v3.2 + */ +NONSHARABLE_CLASS( CCmDestinationIconMapExtension ) : public CBase, + public MObjectProvider + { + public: + + CCmDestinationIconMapExtension(); + ~CCmDestinationIconMapExtension(); + + protected: + + TTypeUid::Ptr MopSupplyObject( TTypeUid aId ); + MObjectProvider* MopNext(); + + public: // data + + MCoeControlObserver *iObserver; + + TUint iFlags; + MObjectProvider* iIconMap; + TInt iMaxVisibleRows; + CAknsFrameBackgroundControlContext* iBgContext; + }; + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMapExtension::CCmDestinationIconMapExtension +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CCmDestinationIconMapExtension::CCmDestinationIconMapExtension() + : iMaxVisibleRows( 0 ) + { + iObserver = NULL; + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMapExtension::MopSupplyObject() +// ----------------------------------------------------------------------------- +// +TTypeUid::Ptr CCmDestinationIconMapExtension::MopSupplyObject( TTypeUid aId ) + { + return MAknsControlContext::SupplyMopObject( aId, iBgContext ); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMapExtension::MopNext() +// ----------------------------------------------------------------------------- +// +MObjectProvider* CCmDestinationIconMapExtension::MopNext() + { + return iIconMap; + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMapExtension::~CCmDestinationIconMapExtension() +// ----------------------------------------------------------------------------- +// +CCmDestinationIconMapExtension::~CCmDestinationIconMapExtension() + { + delete iBgContext; + iBgContext = NULL; + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::CCmDestinationIconMap +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CCmDestinationIconMap::CCmDestinationIconMap() + : iCursorPos( TPoint( 0,0 ) ) + , iOldCursorPos( TPoint( 0,0 ) ) + , iMaxColumns( -1 ) + , iDragAlreadyActive( EFalse ) + { + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CCmDestinationIconMap* CCmDestinationIconMap::NewL() + { + CCmDestinationIconMap* self = new( ELeave ) CCmDestinationIconMap(); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); //self + return self; + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::ConstructL() + { + // Must be created here to get the member variables available + iExtension = new ( ELeave ) CCmDestinationIconMapExtension; + iExtension->iIconMap = this; + + iConsArray = new( ELeave ) CAknIconArray( KNumOfIcons ); + + iExtension->iFlags = 0x00; + + DoLayout(); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::~CCmDestinationIconMap() +// ----------------------------------------------------------------------------- +// +CCmDestinationIconMap::~CCmDestinationIconMap() + { + delete iSBFrame; iSBFrame = NULL; + + delete iOffscreenBg; + delete iBitmapDevice; + delete iBitmapGc; + + delete iExtension; + iExtension = ( CCmDestinationIconMapExtension* )NULL; + + if ( iConsArray ) + { + iConsArray->ResetAndDestroy(); + delete iConsArray; + iConsArray = NULL; + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::DoLayout() +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::DoLayout() + { + TRAPD( err,LoadIconL() ); + if ( err ) + { + return; + } + + iIsMirrored = AknLayoutUtils::LayoutMirrored(); + iDrawnBefore = EFalse; + CountMaxColumnsAndCellSizes(); + SizeChanged(); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::ConstructFromResourceL() +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::ConstructFromResourceL( + TResourceReader& /*aReader*/ ) + { + LoadIconL(); + CreateScrollBarAndIconRowL(); + + iExtension->iBgContext = CAknsFrameBackgroundControlContext::NewL( + KAknsIIDQsnFrPopup, + TRect( 0, 0, 1, 1 ), + TRect( 0, 0, 1, 1 ), + EFalse ); + + if ( DrawableWindow() && AknLayoutUtils::PenEnabled() ) + { + EnableDragEvents(); + SetGloballyCapturing( ETrue ); + SetPointerCapture( ETrue ); + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::LoadIcons() +// This actually load the all icons to be shown on dialog from icon file +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::LoadIconL() + { + if ( iConsArray ) + { + iConsArray->ResetAndDestroy(); + } + // Draw all the Icons. + TParse mbmFile; + User::LeaveIfError( mbmFile.Set( KManagerIconFilename, + &KDC_APP_BITMAP_DIR, NULL ) ); + + // Create icon bitmap and mask. + for ( TInt i( 0 ); i < ( KNumOfIcons * 2 ); i++ ) + { + CFbsBitmap* bitmap = NULL; + CFbsBitmap* bitmapMask = NULL; + AknIconUtils::CreateIconLC( + bitmap, + bitmapMask, mbmFile.FullName(), + EMbmCmmanagerQgn_prop_set_conn_dest_internet_small + i, + EMbmCmmanagerQgn_prop_set_conn_dest_internet_small + i + 1 ); + i++; + AknIconUtils::SetSize( bitmap, + TSize( iGridItemWidth, iGridItemHeight ) ); + AknIconUtils::SetSize( bitmapMask, + TSize( iGridItemWidth, iGridItemHeight ) ); + CGulIcon* icon = CGulIcon::NewL( bitmap, bitmapMask ); + CleanupStack::PushL( icon ); + iConsArray->AppendL( icon ); + CleanupStack::Pop( 3, bitmap ); + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::HeightInRows() +// This actually returns the no of rows to be shown on a page +// Depends upon the Layout size +// ----------------------------------------------------------------------------- +// +TInt CCmDestinationIconMap::HeightInRows() + { + return ( iRows ); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::CreateScrollBarAndIconRowL() +// This actually creates the scroll bar sets the number of +// pages and rows on a page to be shown +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::CreateScrollBarAndIconRowL() + { + 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() ) + { + // window owning scrollbar + iSBFrame->CreateDoubleSpanScrollBarsL( ETrue, + EFalse, + ETrue, + EFalse ); + } + else + { + // non-window owning scrollbar + iSBFrame->CreateDoubleSpanScrollBarsL( EFalse, + EFalse, + ETrue, + EFalse ); + } + iSBFrame->SetTypeOfVScrollBar( CEikScrollBarFrame::EDoubleSpan ); + } + else + { + // For EArrowHead type scrollbar + iSBFrame->SetTypeOfVScrollBar( CEikScrollBarFrame::EArrowHead ); + } + + iSBFrame->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, + CEikScrollBarFrame::EAuto ); + iSBFrame->VerticalScrollBar()->SetMopParent( iExtension ); + UpdateScrollIndicatorL(); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::SetIndex +// set the reference of the selected icon index from the table +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::SetIndex( TInt& aIconIndex ) + { + iIconIndex = &aIconIndex; + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::MinimumSize +// +// ----------------------------------------------------------------------------- +// +TSize CCmDestinationIconMap::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(); + // the offset for the certain cba location variety + TInt maxVarietyOffset = 0; + // the number of varieties + 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() ) + { + // the offset for one variety + varietyOffset = ( maxVariety + 1 ) / KAknSctCBaButtonDirections; + } + + // 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() ); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::ActivateL() +// This method is needed to set correct initial value to scroll indicator. +// ----------------------------------------------------------------------------- +// + void CCmDestinationIconMap::ActivateL() + { + CCoeControl::ActivateL(); + if ( iRows > iExtension->iMaxVisibleRows ) + { + UpdateScrollIndicatorL(); + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::OfferKeyEventL +// Handles all the Keypad events +// ----------------------------------------------------------------------------- +// +TKeyResponse CCmDestinationIconMap::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: + { + 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; + } + +#ifdef RD_SCALABLE_UI_V2 + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::HandlePointerEventL +// Handles all the Keypad events +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::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; + } + + // 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 ) ) ) ) + { + TUint globalY = newGridY + iFirstVisibleRow; + // 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 || + aPointerEvent.iType == TPointerEvent::EDrag ) + { + if ( aPointerEvent.iType == TPointerEvent::EDrag ) + { + iDragAlreadyActive = ETrue; + } + + // 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 select the icon. + if( iCursorPos.iY == newGridY && + iCursorPos.iX == newGridX && + aPointerEvent.iType != TPointerEvent::EDrag ) + { + if ( iExtension->iObserver ) + { + iExtension->iObserver->HandleControlEventL( + this, + MCoeControlObserver::EEventStateChanged ); + } + } + else if ( iCursorPos.iX + ( iCursorPos.iY + + iFirstVisibleRow ) * iMaxColumns < + iConsArray->Count() ) + { + iOldCursorPos = iCursorPos; + iCursorPos.iY = newGridY; + iCursorPos.iX = newGridX; + DrawCursor(); + } + else + { + iOldCursorPos.iX = 0; + iOldCursorPos.iY = 0; + } + } + } + else if ( aPointerEvent.iType == TPointerEvent::EButton1Up ) + { + // The pointer has been set and dragged into the area of + // the grid. + if ( yInPixels >= 0 && yInPixels < iGridItemHeight * + iExtension->iMaxVisibleRows && + iDragAlreadyActive && + iOldCursorPos == iCursorPos && + (iConsArray->Count() > (globalY * iMaxColumns + newGridX))) + { + if ( iExtension->iObserver ) + { + iExtension->iObserver->HandleControlEventL( + this, + MCoeControlObserver::EEventStateChanged ); + } + iDragAlreadyActive = EFalse; + } + } + + MTouchFeedback* feedback = MTouchFeedback::Instance(); + + if ( feedback ) + { + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + feedback->InstantFeedback( this, ETouchFeedbackBasic ); + } + else if ( aPointerEvent.iType == TPointerEvent::EDrag && iCursorPos != iOldCursorPos ) + { + feedback->InstantFeedback( this, ETouchFeedbackSensitive ); + } + } + } + else // For a non window owning scrollbar. + { + if ( aPointerEvent.iType == TPointerEvent::EButton1Up ) + { + iDragAlreadyActive = EFalse; + } + } + + CCoeControl::HandlePointerEventL( aPointerEvent ); + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::SetObserver +// Sets the observer. +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::SetObserver( MCoeControlObserver* aObserver ) + { + if ( iExtension ) + { + iExtension->iObserver = aObserver; + } + } + +#endif //RD_SCALABLE_UI_V2 + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::InputCapabilities() +// +// ----------------------------------------------------------------------------- +// +TCoeInputCapabilities CCmDestinationIconMap::InputCapabilities() const + { + return TCoeInputCapabilities( TCoeInputCapabilities::EAllText ); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::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 CCmDestinationIconMap::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(); + // the offset for the certain cba location variety + TInt maxVarietyOffset = 0; + 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() ) + { + // the offset for one variety + varietyOffset = ( maxVariety + 1 ) / KAknSctCBaButtonDirections; + } + + // 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 ( iExtension->iBgContext ) + { + TInt bgVariety = 0; + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + bgVariety = 1; + } + + TAknLayoutRect innerRect; + innerRect.LayoutRect( + relativeDialog, + AknLayoutScalable_Avkon::bg_popup_window_pane_g1( bgVariety ) ); + + iExtension->iBgContext->SetFrameRects( relativeDialog, + innerRect.Rect() ); + } + + TRAPD( err,UpdateScrollIndicatorL() ); + if ( err ) + { + return; + } + } + + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::HandleResourceChange() +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::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 = iExtension->iMaxVisibleRows * + ( currentCursorPosition / + ( iMaxColumns * iExtension->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 ); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::Draw() +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::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(); + // the offset for the certain cba location variety + TInt maxVarietyOffset = 0; + 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() ) + { + // the offset for one variety + varietyOffset = ( maxVariety + 1 )/KAknSctCBaButtonDirections; + } + + // 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 > + ( iExtension->iMaxVisibleRows * iMaxColumns ) ) + { + numberOfIconsToBeDrawn = iExtension->iMaxVisibleRows * iMaxColumns; + } + + 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; + // iOffset is cell area topLeft, grid is not included in it + pos.iX--; + 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 * iExtension->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(); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::DrawItem() +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::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 = iExtension->iMaxVisibleRows * iMaxColumns; + TInt cellIndex = aIconIndex; + if ( aIconIndex >= numIconsInaPage ) + { + cellIndex = aIconIndex % numIconsInaPage; + } + aGc.BitBltMasked( CursorPoint( cellIndex ), + bitmap->Bitmap(), + cellRect, + bitmap->Mask(), + EFalse ); + } + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::DrawCursor() +// Optimizes drawing. Only cursor is drawn. +// ----------------------------------------------------------------------------- +void CCmDestinationIconMap::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; + DrawCell( cursorPos, EFalse ); + + cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + DrawCell( cursorPos, ETrue ); + + gc.DiscardFont(); + DeactivateGc(); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::DrawCell +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::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(); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::CursorRect +// ----------------------------------------------------------------------------- +// +TRect CCmDestinationIconMap::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 ) ); + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::CursorPoint +// ----------------------------------------------------------------------------- +// +TPoint CCmDestinationIconMap::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; + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::MoveCursorL +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::MoveCursorL( TInt aDeltaX, TInt aDeltaY ) + { + 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 -= iExtension->iMaxVisibleRows; + iCursorPos = TPoint( iCursorPos.iX, + iExtension->iMaxVisibleRows - 1 ); + } + } + + if ( globalYPos > iFirstVisibleRow + iExtension->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 ) % iExtension->iMaxVisibleRows + ); + iFirstVisibleRow = ( ( iRows - 1 ) / iExtension->iMaxVisibleRows ) * + iExtension->iMaxVisibleRows; + } + else + { + // If cursor was moved down out of the visible area - show it again. + iFirstVisibleRow += iExtension->iMaxVisibleRows; + iCursorPos = TPoint( iCursorPos.iX, 0 ); + } + } + + //TInt increment( 1 ); + //if ( aDeltaY < 0 || aDeltaX < 0 ) + // { + //// increment = -1; + // } + if ( iRows > iExtension->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(); + } + + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::UpdateScrollIndicatorL() +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::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(); + // the offset for the certain cba location variety + TInt maxVarietyOffset = 0; + 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() ) + { + // the offset for one variety + varietyOffset = ( maxVariety + 1 )/KAknSctCBaButtonDirections; + } + + // 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 / iExtension->iMaxVisibleRows ) + 1; + + vSbarModel.iScrollSpan = iNumPages * iExtension->iMaxVisibleRows; + vSbarModel.iThumbSpan = iExtension->iMaxVisibleRows; + + if ( iSBFrame && iSBFrame->TypeOfVScrollBar() == + CEikScrollBarFrame::EDoubleSpan ) + { + // For EDoubleSpan type scrollbar + vSbarModel.iThumbPosition = ( iCurrentPage - 1 ) * + iExtension->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 ); + } + } + + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::Reserved_1() +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::Reserved_1() + { + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::Reserved_2() +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::Reserved_2() + { + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::DrawOffscreenBackgroundIfRequired +// +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::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(); + // the offset for the certain cba location variety + TInt maxVarietyOffset = 0; + 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() ) + { + // the offset for one variety + varietyOffset = ( maxVariety + 1 )/KAknSctCBaButtonDirections; + } + + // 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; + } + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::ComponentControl( TInt aIndex ) const +// Return the controll pointer +// ----------------------------------------------------------------------------- +// +CCoeControl* CCmDestinationIconMap::ComponentControl( TInt aIndex ) const + { + if ( aIndex == 0 && + iSBFrame && + iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan ) + { + return iSBFrame->VerticalScrollBar(); + } + else + { + return NULL; + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::CountComponentControls() +// Return no of controll to be placed on the container control +// ----------------------------------------------------------------------------- +// +TInt CCmDestinationIconMap::CountComponentControls() const + { + if ( iSBFrame && + iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan ) + { + return 1; + } + else + { + return 0; + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::CountMaxColumnsAndCellSizes +// Counts no of columns and the cell size will be displayed in the icon table +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::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(); + // the offset for the certain cba location variety + TInt maxVarietyOffset = 0; + 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() ) + { + // the offset for one variety + varietyOffset = ( maxVariety + 1 ) / KAknSctCBaButtonDirections; + } + + 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 + iExtension->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; + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::HandleScrollEventL +// Handles the different scroll events so that the map reacts accordingly. +// ----------------------------------------------------------------------------- +// +void CCmDestinationIconMap::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 -= iExtension->iMaxVisibleRows; + update = ETrue; + } + UpdateScrollIndicatorL(); + } + break; + + case EEikScrollDown: + case EEikScrollPageDown: + { + // nothing done if we are already on the last page. + if ( iFirstVisibleRow != iRows/iExtension->iMaxVisibleRows * + iExtension->iMaxVisibleRows ) + { + iFirstVisibleRow += iExtension->iMaxVisibleRows; + update = ETrue; + } + UpdateScrollIndicatorL(); + } + break; + + case EEikScrollThumbDragVert: + { + TInt thumbPosition; + TInt halfPage = iExtension->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 )iExtension->iMaxVisibleRows; + if ( toRound * 2 > ( TInt )toRound * 2 + 1 ) + { + toRound++; + } + iFirstVisibleRow = ( TInt )toRound * + iExtension->iMaxVisibleRows; + 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/iExtension->iMaxVisibleRows * iExtension->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 % iExtension->iMaxVisibleRows ) == 1 ) + { + iCursorPos.iX = iConsArray->Count()%iMaxColumns - 1; + } + // If the cursor is in a position where it would go unto a spot without + // a icon when scrolled. + if ( iCursorPos.iY + iFirstVisibleRow >= iRows ) + { + if ( iConsArray->Count() % iMaxColumns > iCursorPos.iX ) + { + iCursorPos.iY = iRows - 1 - iFirstVisibleRow; + } + else + { + iCursorPos.iY = iRows - 2 - iFirstVisibleRow; + } + } + // 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 ( iExtension->iObserver ) + { + iExtension->iObserver->HandleControlEventL( + this, + MCoeControlObserver::EEventRequestFocus ); + } + DrawDeferred(); + } + } + +// ----------------------------------------------------------------------------- +// CCmDestinationIconMap::Extension +// ----------------------------------------------------------------------------- +// +CCmDestinationIconMapExtension* CCmDestinationIconMap::Extension() const + { + return iExtension; + }