diff -r 000000000000 -r 2f259fa3e83a uifw/EikStd/coctlsrc/eikcba.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/EikStd/coctlsrc/eikcba.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,8366 @@ +/* +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Command button array implementation. +* +*/ + + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif +#include +#include "eikcba.h" +#include +#include +#include +#include +#include +#include // LayoutUtils +#include +#include +#include +#include +#include +#include +#include +#include +#include // R_ENHANCED_CBA_PRIORITIES +#include +#include +#include +#include +#include // KAknMiddleSoftkeyEnabled +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include "akncollectionobserver.h" +#include "aknitemactionmenuregister.h" + +/** + * Color value for transparent pixel (ARGB format). + */ +const TUint32 KAknCbaColorKey = 0x00000000; + +/** + * Mask for opaque pixel (ARGB format). + */ +const TUint32 KAknCbaOpaqueMask = 0xFF000000; + +/** + * Mask for outline font in font id. + */ +const TUint32 KOutlineFontMask = 0x00000040; +#include + +inline TAknWindowComponentLayout DoCompose(TAknWindowComponentLayout aLine1, + TAknWindowComponentLayout aLine2) + { + return TAknWindowComponentLayout::Compose(aLine1, aLine2); + } + +inline TAknTextComponentLayout DoComposeText(TAknWindowComponentLayout aLine1, + TAknTextComponentLayout aLine2) + { + return TAknWindowComponentLayout::ComposeText(aLine1, aLine2); + } + +/** +* Checks if right side pane is active. +* @return ETrue if right side pane is active, EFalse otherwise. +*/ +static TBool IsAreaSideRightPaneActive() + { + return EFalse; + } + + +/** +* Checks if MSK-enabled layout is in use. +*/ +static TBool IsMskEnabledLayoutActive() + { + TBool result( EFalse ); + + if ( Layout_Meta_Data::IsMSKEnabled() ) + { + // First check if MSK is enabled in the layout metadata. + result = ETrue; + } + else + { + TInt statusPaneLayout( + AVKONENV->StatusPaneResIdForCurrentLayout( + AknStatuspaneUtils::CurrentStatusPaneLayoutResId() ) ); + + if ( statusPaneLayout == + R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT_NO_SOFTKEYS || + ( statusPaneLayout == R_AVKON_STATUS_PANE_LAYOUT_IDLE_FLAT && + AknLayoutUtils::PenEnabled() && + !Layout_Meta_Data::IsLandscapeOrientation() ) ) + { + // MSK is not enabled in the layout metadata, but for + // these status pane layouts an exception is made. + result = ETrue; + } + } + + return result; + } + + +/* + * Checks if bitmap must be updated, i.e. bitmap does not exist or + * expected size does not match with actual size. + */ +static TBool IsBitmapUpdateNeeded( CFbsBitmap* aOldBitmap, const TSize& aSize ) + { + return !aOldBitmap || ( aOldBitmap->SizeInPixels() != aSize ); + } + + +/** + * Implementation of class CEikCba - Control button array. + */ +const TInt KNoResource = 0; +const TInt KMaxSeries60Softkeys = 3; // 3 softkeys for S60 with MSK +const TInt KControlArrayCBAButton1Posn = 0; +const TInt KControlArrayScrollBarPosn = 1; +const TInt KControlArrayCBAButton2Posn = 2; +const TInt KControlArrayCBAButtonMSKPosn = 3; +const TInt KCbaScrollBarButtonWidth = 9; // in pixels + +/** Alpha value used in drawing CBA button contents in pressed down state. */ +const TInt KPressedDownAlphaValue = 127; + + +/** +* Local panic definitions. +*/ +enum TEikPanicCBA + { + EEikPanicCBAControlArraySize, + EEikPanicCBANullButton, + EEikPanicCBACannotConvertToCEikCommandButton, + EEikPanicCBAIsNotEnhancedCba, + EEikPanicCBAButtonCountDiffersFromCommandTableSize + }; + +/** +* Local AknLayout definintions. +*/ +enum TAknLayoutFlags + { + EAknLayoutCbaInControlPane = 0x1, + EAknLayoutCbaInStaconPane = 0x2, + EAknLayoutCbaInStaconPaneRight = 0x4, + EAknLayoutCbaInStaconPaneLeft = 0x8, + EAknLayoutCbaInStaconPaneIdle = 0x10, + EAknLayoutCbaInRightPane = 0x20 + }; + +/** +* Enumeration for CEikCommandTable for fetching commands. +*/ +enum TCommandTableCbaPositions + { + ECommandTableCommand1Posn = 0, + ECommandTableCommand2Posn = 1, + ECommandTableCommand3Posn = 2, + ECommandTableCommand4Posn = 3 + }; + +enum TCbaChangeRecordedFlags + { + ECbaChangeRecordedLayout, + ECbaChangeRecordedSkin, + ECbaChangeRecordedColor, + ECbaInsideDialog, + ECbaEmbedded, // cba is embedded in a parent control (dialog or popup) + ECbaHasContent, // cba has content and should be visible when embedded + ECbaParentAsControl, // cba's parent window group is treated as CCoeControl + ECbaActivationDelayed, // activation delayed + ECbaSingleClickEnabled, // single click enabled in appUi + ECbaItemSoftkeyDisabled, // item specific softkey disabled + ECbaItemSpecificSoftkeyInUse, // item specific softkey is in use + ECbaItemSoftkeyDisabledByClient // client has disabled item specific softkey + }; + +enum TCbaLayers + { + ECbaLayerWallpaper, + ECbaLayerBackground, + ECbaLayerN + }; + +/** +* Local panic routine. +*/ +#if defined(_DEBUG) +LOCAL_C void Panic(TEikPanicCBA aPanic) + { + _LIT(KPanicCat,"CBA"); + User::Panic(KPanicCat, aPanic); + } +#endif + + +/** +* Internal extension class. +*/ +class CEikCbaExtension : public CBase, + public MCenRepNotifyHandlerCallback, + public MAknCollectionObserver + { +public: + + CEikCbaExtension( CEikCba& aOwner ) : iOwner( aOwner ), + iCbaBgIIDSetExt( EFalse ) + ,iLeftFrameMask( NULL ), + iRightFrameMask( NULL ), + iItemActionMenu( NULL ) + { + }; + + static CEikCbaExtension* NewL( CEikCba& aOwner ) + { + CEikCbaExtension* self = new (ELeave) CEikCbaExtension( aOwner ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + + void ConstructL() + { + // Wallpaper is not drawn by embedded CBA. + if ( !iOwner.Flags().IsSet( ECbaEmbedded ) ) + { + iRepository = CRepository::NewL( KCRUidPersonalisation ); + iRepository->Get( KPslnWallpaperType, iWallpaperInUse ); + + iCRListener = CCenRepNotifyHandler::NewL( *this, + *iRepository, + CCenRepNotifyHandler::EIntKey, + KPslnWallpaperType ); + iCRListener->StartListeningL(); + } + + iBackgroundMaskID = KAknsIIDNone; + iCbaRect = TRect( 0,0,0,0 ); + iIfSkinChanged = EFalse; + iIfMskIconSet = EFalse; + iSemiBgID = KAknsIIDNone; + + if ( iOwner.Flags().IsSet( ECbaSingleClickEnabled ) ) + { + AknItemActionMenuRegister::RegisterCollectionObserverL( + *this ); + } + } + + ~CEikCbaExtension() + { + if ( iOwner.Flags().IsSet( ECbaSingleClickEnabled ) ) + { + AknItemActionMenuRegister::UnregisterCollectionObserver( *this ); + } + if ( iCRListener ) + { + iCRListener->StopListening(); + delete iCRListener; + } + + delete iRepository; + delete iPressedMSKFrameBitmap; + delete iLeftFrameMask; + delete iRightFrameMask; + delete iLskPostingOverlayBitmap; + delete iRskPostingOverlayBitmap; + delete iBmpFile; + } + + /** From base class MCenRepNotifyHandlerCallback */ + void HandleNotifyInt( TUint32 /*aId*/, TInt aNewValue ) + { + iWallpaperInUse = aNewValue; + iOwner.SetSkinBackgroundId( KAknsIIDNone ); + } + + void UpdateSoftkeyFrameL( TBool aForcedUpdate ) + { + if ( !AknLayoutUtils::PenEnabled() ) + { + return; + } + TAknLayoutRect cbarect; + + TRect screen; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen ); + + TAknWindowComponentLayout applicationWindow( + AknLayoutScalable_Avkon::application_window( 0 ) ); + + TRect innerRect; + TRect outerRect; + TRect mskOuterRect; + TRect mskInnerRect; + + if ( iOwner.Flags().IsSet( ECbaEmbedded ) ) + { + TRect rect ( iOwner.Rect() ); + if ( rect.Width() > 0 && rect.Height() > 0 ) + { + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::popup_sk_window_g1( 0 ) ); + + TInt margin = layoutRect.Rect().iTl.iX - rect.iTl.iX; + TInt buttonWidth = ( rect.Width() - margin * 2 ) / 2; + outerRect = TRect( 0, 0, buttonWidth, + layoutRect.Rect().Height() ); + + layoutRect.LayoutRect( outerRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + innerRect = layoutRect.Rect(); + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + + const TSize maskSize = outerRect.Size(); + if (skin && ( aForcedUpdate || IsBitmapUpdateNeeded( iLeftFrameMask, maskSize ) + || IsBitmapUpdateNeeded( iRightFrameMask, maskSize ) ) ) + { + delete iLeftFrameMask; + iLeftFrameMask = NULL; + delete iRightFrameMask; + iRightFrameMask = NULL; + } + } + } + else + { + TBool rightPaneActive( IsAreaSideRightPaneActive() ); + + TBool bskLandscape( Layout_Meta_Data::IsLandscapeOrientation() && + !rightPaneActive ); + + if ( rightPaneActive ) + { + cbarect.LayoutRect( + screen, + DoCompose( + applicationWindow, + AknLayoutScalable_Avkon::area_side_right_pane( 0 ) ).LayoutLine() ); + } + else + { + cbarect.LayoutRect( + screen, + DoCompose( + applicationWindow, + DoCompose( + AknLayoutScalable_Avkon::area_bottom_pane( bskLandscape ? 2 : 1 ), + AknLayoutScalable_Avkon::control_pane() ) ).LayoutLine() ); + } + + TRect cbaRect( cbarect.Rect() ); + + TBool mskEnabled( IsMskEnabledLayoutActive() ); + + TAknWindowComponentLayout frameLayout; + if ( rightPaneActive ) + { + frameLayout = AknLayoutScalable_Avkon::sctrl_sk_top_pane(); + } + else if ( bskLandscape || mskEnabled ) + { + frameLayout = AknLayoutScalable_Avkon::control_pane_g6( 0 ); + } + else + { + frameLayout = AknLayoutScalable_Avkon::bg_sctrl_sk_pane_cp1(); + } + + cbarect.LayoutRect( cbaRect, frameLayout ); + + outerRect.SetRect( TPoint( 0, 0 ), cbarect.Rect().Size() ); + + if ( mskEnabled ) + { + cbarect.LayoutRect( + cbaRect, + AknLayoutScalable_Avkon::control_pane_g7( 0 ) ); + + mskOuterRect.SetRect( TPoint( 0, 0 ), cbarect.Rect().Size() ); + } + else + { + + iUpdateMSKFrameOuterRect.SetRect( 0, 0, 0, 0 ); + } + + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( + outerRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1().LayoutLine() ); + innerRect = layoutRect.Rect(); + if ( mskEnabled ) + { + layoutRect.LayoutRect( + mskOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() ); + mskInnerRect = layoutRect.Rect(); + } + } + + + iUpdateFrameOuterRect = outerRect; + iUpdateFrameInnerRect = innerRect; + iUpdateMSKFrameOuterRect = mskOuterRect; + iUpdateMskFrameInnerRect = mskInnerRect; + } + + + + + /** + * Merges mask into color bitmap. + * @internal + * @since S60 v5.0 + * @param aMask mask to be merged. + * @param aDestBitmap bitmap to merge mask with. + */ + static void MergeMaskInto16MA( CFbsBitmap* aMask, CFbsBitmap* aDestBitmap ) + { + // aMask display mode must be EGray256. + // aMask must not be compressed in RAM. + // aDestBitmap display mode must be EColor16MA. + // aDestBitmap must not be compressed in RAM. + // aMask size must equal to aDestBitmap size. + // See UpdatePostingOverlayBitmapL. + + TSize size = aMask->SizeInPixels(); + TUint32 pitch = CFbsBitmap::ScanLineLength( size.iWidth, EGray256 ); + TUint32 destPitch = CFbsBitmap::ScanLineLength( size.iWidth, EColor16MA ) / 4; + aMask->LockHeap(); + aDestBitmap->LockHeap(); + TUint8* dataAddr = + reinterpret_cast( aMask->DataAddress() ); + TUint32* destAddr = + reinterpret_cast( aDestBitmap->DataAddress() ); + + for ( TUint32 y = 0; y < size.iHeight; y++ ) + { + for ( TUint32 x = 0; x < size.iWidth; x++ ) + { + TUint8 value = (TUint8)dataAddr[ y * pitch + x ]; + // Round mask value to fully opaque or transparent + if ( value > 0x7f ) + { + // Opaque pixel. + destAddr[ y * destPitch + x ] |= KAknCbaOpaqueMask; + } + else + { + // Transparent pixel + destAddr[ y * destPitch + x ] = KAknCbaColorKey; + } + } + } + aDestBitmap->UnlockHeap(); + aMask->UnlockHeap(); + } + + /** + * Updates posting overlay bitmap. + * @internal + * @since S60 v5.0 + * @param aBitmap Reference to bitmap pointer to get the new bitmap. + * @param aRect Rectangle for the CBA button. + * @param aControl CEikCba control. + * @param aButton CEikCbaButton control for the button. + */ + void UpdatePostingOverlayBitmapL( + CFbsBitmap*& aBitmap, + const TRect& aRect, + CEikCbaButton* aButton ) + { + delete aBitmap; + aBitmap = NULL; + + // If you modify this method, please make sure that assumptions + // mentioned in MergeMaskInto16MA still hold. + + CFbsBitmap* bitmap = new ( ELeave ) CFbsBitmap(); + CleanupStack::PushL( bitmap ); + User::LeaveIfError( bitmap->Create( aRect.Size(), EColor16MA ) ); + + CFbsBitGc* bitmapContext = NULL; + CFbsBitmapDevice* bitmapDevice = + CFbsBitmapDevice::NewL( bitmap ); + CleanupStack::PushL( bitmapDevice ); + User::LeaveIfError( bitmapDevice->CreateContext( bitmapContext ) ); + CleanupStack::PushL( bitmapContext ); + + // Zero alpha channel to make bitmap fully transparent + bitmapContext->SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha ); + bitmapContext->SetBrushColor( TRgb::Color16MA( 0 ) ); + bitmapContext->Clear(); + + // Draw button text into bitmap + if ( aButton ) + { + CFbsBitmap* textBitmapMask = new ( ELeave ) CFbsBitmap(); + CleanupStack::PushL( textBitmapMask ); + User::LeaveIfError( textBitmapMask->Create( aRect.Size(), EGray256 ) ); + + CFbsBitmapDevice* device = CFbsBitmapDevice::NewL( textBitmapMask ); + CleanupStack::PushL( device ); + CFbsBitGc* gc = NULL; + User::LeaveIfError( device->CreateContext( gc ) ); + CleanupStack::PushL( gc ); + + // Clear bitmap + gc->SetBrushColor( KRgbBlack ); + gc->Clear(); + + aButton->DrawToContext( *bitmapContext, *gc, aRect.iTl ); + + CleanupStack::PopAndDestroy( gc ); + CleanupStack::PopAndDestroy( device ); + + // Merge text mask into the alpha channel to make the text fully opaque + MergeMaskInto16MA( textBitmapMask, bitmap ); + + CleanupStack::PopAndDestroy( textBitmapMask ); + } + + CleanupStack::PopAndDestroy( 2, bitmapDevice ); + CleanupStack::Pop( bitmap ); + aBitmap = bitmap; + } + + /** + * Updates posting overlay bitmaps. + * @param aCbaRect cba rect. + * @param aLeftButton left button. + * @param aRightButton right button. + */ + void UpdatePostingOverlayBitmapsL( + const TRect& aCbaRect, + CEikCbaButton* aLeftButton, + CEikCbaButton* aRightButton, + TInt aAknLayoutFlags ) + { + TRect rightSoftKeyButtonRect; + TRect leftSoftKeyButtonRect; + if( aAknLayoutFlags & EAknLayoutCbaInRightPane ) + { + // Read right (top in landscape) softkey layout. + TAknWindowLineLayout rightSoftkeyLayout( + DoCompose( AknLayoutScalable_Avkon::area_side_right_pane( 0 ), + AknLayoutScalable_Avkon::sctrl_sk_top_pane() ).LayoutLine() ); + + TAknLayoutRect rightSoftkeyLayoutRect; + rightSoftkeyLayoutRect.LayoutRect( aCbaRect, rightSoftkeyLayout ); + rightSoftKeyButtonRect = rightSoftkeyLayoutRect.Rect() ; + + // Read left (bottom in landscape) softkey layout. + TAknWindowLineLayout leftSoftkeyLayout( + DoCompose( AknLayoutScalable_Avkon::area_side_right_pane( 0 ), + AknLayoutScalable_Avkon::sctrl_sk_bottom_pane() ).LayoutLine() ); + + TAknLayoutRect leftSoftkeyLayoutRect; + leftSoftkeyLayoutRect.LayoutRect( aCbaRect, leftSoftkeyLayout ); + leftSoftKeyButtonRect = leftSoftkeyLayoutRect.Rect() ; + } + else if( aAknLayoutFlags & EAknLayoutCbaInControlPane ) + { + TAknLayoutRect layoutRect; + TRect rect( 0,0,0,0 ); + if ( AknLayoutUtils::LayoutMirrored() ) + { + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::aid_touch_ctrl_right().LayoutLine() ); + leftSoftKeyButtonRect = layoutRect.Rect(); + + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::aid_touch_ctrl_left().LayoutLine() ); + rightSoftKeyButtonRect = layoutRect.Rect(); + } + else + { + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::aid_touch_ctrl_left().LayoutLine() ); + leftSoftKeyButtonRect = layoutRect.Rect(); + + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::aid_touch_ctrl_right().LayoutLine() ); + rightSoftKeyButtonRect = layoutRect.Rect(); + } + } + else + { + TInt variety = 0; + if ( aAknLayoutFlags & EAknLayoutCbaInStaconPaneLeft ) + { + variety = 1; + } + + TAknWindowComponentLayout layout0; + TAknWindowComponentLayout layout1; + TAknWindowComponentLayout layout2; + + // Read right (top in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_top_pane( 2 ); + layout1 = AknLayoutScalable_Avkon::stacon_top_pane(); + + // If clock is shown in stacon, cba area is smaller. + TInt topCbaVariety = variety; + if ( AknStatuspaneUtils::ExtendedStaconPaneActive() ) + { + topCbaVariety += 4; + } + + layout2 = AknLayoutScalable_Avkon::control_top_pane_stacon( topCbaVariety ); + + TAknWindowLineLayout rightSoftkeyLayout( + DoCompose( layout0,DoCompose( layout1, layout2 ) ).LayoutLine() ); + + TAknLayoutRect rightSoftkeyLayoutRect; + rightSoftkeyLayoutRect.LayoutRect( aCbaRect, rightSoftkeyLayout ); + rightSoftKeyButtonRect = rightSoftkeyLayoutRect.Rect(); + + // Read left (bottom in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_bottom_pane( 2 ); + layout1 = AknLayoutScalable_Avkon::stacon_bottom_pane(); + + // If clock is shown in stacon, cba area is smaller. + TInt bottomCbaVariety = variety; + if ( AknStatuspaneUtils::ExtendedStaconPaneActive() ) + { + bottomCbaVariety += 2; + } + + layout2 = AknLayoutScalable_Avkon::control_bottom_pane_stacon( + bottomCbaVariety ); + + TAknWindowLineLayout leftSoftkeyLayout( + DoCompose( layout0, DoCompose( layout1, layout2 ) ).LayoutLine() ); + + TAknLayoutRect leftSoftkeyLayoutRect; + leftSoftkeyLayoutRect.LayoutRect( aCbaRect, leftSoftkeyLayout ); + leftSoftKeyButtonRect = leftSoftkeyLayoutRect.Rect(); + } + UpdatePostingOverlayBitmapL( + iLskPostingOverlayBitmap, + leftSoftKeyButtonRect, + aLeftButton ); + UpdatePostingOverlayBitmapL( + iRskPostingOverlayBitmap, + rightSoftKeyButtonRect, + aRightButton ); + } + + /** + * From MAknCollectionObserver. + * This method is used to set the item action menu to observer. + * + * @param aItemActionMenu Item action menu. + */ + void SetItemActionMenu( CAknItemActionMenu* aItemActionMenu ) + { + iItemActionMenu = aItemActionMenu; + } + + /** + * From MAknCollectionObserver. + * This method is called when there are changes in collection state. + * LSK should be hidden when there is no highlight in list. + * + * @param aCollectionVisible ETrue if changed collection is visible. + */ + void CollectionChanged( TBool aCollectionVisible ) + { + // Do not update state if invisible collection tries to enable sk + if ( aCollectionVisible + || iOwner.Flags().IsClear( ECbaItemSoftkeyDisabled ) ) + { + iOwner.UpdateItemSpecificSoftkey(); + } + } + + /** + * From MAknCollectionObserver. + * This method returns ETrue if collection observer is active. + * + * @return ETrue if observer is active. + */ + TBool Active() const + { + return iOwner.IsVisible() && !iOwner.IsEmpty(); + } + + /* + * Using the special theme Id draw background + */ + void DrawSemiTransparencyL(CWindowGc& aGc, + const TRect& aRect) + { + //Temporary inner rectangal value + TRect innerRect = aRect; + innerRect.Shrink( 5, 5 ); + if ( iSemiBgID != KAknsIIDNone ) + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + aGc, aRect, innerRect, iSemiBgID, iSemiBgCenterID ); + } + } + +public: + + CEikCba& iOwner; + CRepository* iRepository; + CCenRepNotifyHandler* iCRListener; + TInt iWallpaperInUse; + CFbsBitmap* iFrameBitmap; + CFbsBitmap* iPressedFrameBitmap; + CFbsBitmap* iMSKFrameBitmap; + CFbsBitmap* iPressedMSKFrameBitmap; + CFbsBitmap* iLskPostingOverlayBitmap; + CFbsBitmap* iRskPostingOverlayBitmap; + TBool iEnablePostingTransparency; + + TBool iCbaBgIIDSetExt; + TBool iIfSkinChanged; + + CFbsBitmap* iLeftFrameMask; + CFbsBitmap* iRightFrameMask; + + TAknsItemID iBackgroundMaskID; + TRect iCbaRect; + TBool iIfMskIconSet; + TAknsItemID iMSKSkinID; + HBufC* iBmpFile; + TInt32 iBmp; + TInt32 iBmpM; + /** + * Pointer to the CBA button which currently has the pointer grab. + * Not own. + */ + CCoeControl* iPointerGrabbingButton; + + /** Rectangle in which the left (or bottom) softkey frame is drawn to. */ + TRect iLeftFrameOuterRect; + TRect iLeftFrameInnerRect; + + /** Rectangle in which the right (or top) softkey frame is drawn to. */ + TRect iRightFrameOuterRect; + TRect iRightFrameInnerRect; + + /** Rectangle in which the middle softkey frame is drawn to if used. */ + TRect iMiddleFrameOuterRect; + TRect iMiddleFrameInnerRect; + + /** + * Content observer. + */ + TCallBack iContentObserver; + + /** + * Outer rect used in UpdateSoftkeyFrameL method. + */ + TRect iUpdateFrameOuterRect; + + /* + * Frame and center theme ID, using for semi-transparent + */ + TAknsItemID iSemiBgID; + TAknsItemID iSemiBgCenterID; + /** + * Inner rect used in UpdateSoftkeyFrameL method. + */ + TRect iUpdateFrameInnerRect; + + /** + * Outer MSK rect used in UpdateSoftkeyFrameL method. + */ + TRect iUpdateMSKFrameOuterRect; + /* + * + */ + TRect iUpdateMskFrameInnerRect; + + /** + * Item action menu. + * Not own. + */ + CAknItemActionMenu* iItemActionMenu; + }; + + +CEikCba* CEikCba::NewL(const CEikCba* aPrevious, MEikCommandObserver* aCommandObserver, + RWindowGroup* aParentWg) + { + CEikCba* self = CEikCba::NewLC(aPrevious, aCommandObserver, aParentWg); // static + CleanupStack::Pop( self ); + return self; + } + +CEikCba* CEikCba::NewL(TInt aResourceId, const CEikCba* aPrevious, + MEikCommandObserver* aCommandObserver, RWindowGroup* aParentWg) + { + CEikCba* self = CEikCba::NewLC(aResourceId, aPrevious, aCommandObserver, aParentWg); // static + CleanupStack::Pop( self ); + return self; + } + +CEikCba* CEikCba::NewLC(const CEikCba* aPrevious, MEikCommandObserver* aCommandObserver, + RWindowGroup* aParentWg) + { + return CEikCba::NewLC(KNoResource, aPrevious, aCommandObserver, aParentWg); // static + } + +CEikCba* CEikCba::NewLC(const CEikCba* aPrevious, + MEikCommandObserver* aCommandObserver, RWindowGroup* aParentWg, + TUint aFlags) + { + return CEikCba::NewLC(KNoResource, aPrevious, aCommandObserver, + aParentWg, aFlags); + } + +CEikCba* CEikCba::NewLC(TInt aResourceId, const CEikCba* aPrevious, + MEikCommandObserver* aCommandObserver, RWindowGroup* aParentWg) + { + CEikCba* self = new(ELeave) CEikCba(aPrevious, aCommandObserver, aParentWg); // static + CleanupStack::PushL(self); + self->ConstructL(aResourceId); + AKNTASHOOK_ADDL( self, "CEikCba" ); + return self; + } + +CEikCba* CEikCba::NewLC(TInt aResourceId, const CEikCba* aPrevious, + MEikCommandObserver* aCommandObserver, RWindowGroup* aParentWg, + TUint aFlags) + { + CEikCba* self = new(ELeave) CEikCba(aPrevious, aCommandObserver, + aParentWg, aFlags); + CleanupStack::PushL(self); + self->ConstructL(aResourceId); + AKNTASHOOK_ADDL( self, "CEikCba" ); + return self; + } + + +/** +* Destructor. +*/ +CEikCba::~CEikCba() + { + AKNTASHOOK_REMOVE(); + // Revert the clock and indicator pane area of status pane + // to use the previous skin background. + CEikStatusPaneBase* sp = CEikStatusPaneBase::Current(); + if ( sp && + iClockIndicBgIID.iMajor && + iClockIndicBgIID.iMinor && + iIsClockIndicBgIIDSet ) + { + sp->SetCbaAreaBackgroundID( iClockIndicBgIID, + CEikStatusPaneBase::EDrawDeferred ); + } + + AknsUtils::DeregisterControlPosition( this ); + + // Remove scroll bar from control array to prevent double deletion + // but only if has been properly constructed. + if (iControlArray) + { + if (iControlArray->Count() > KControlArrayScrollBarPosn) + { + iControlArray->Delete(KControlArrayScrollBarPosn); + } + } + + if(iEikonEnv && iEikonEnv->EikAppUi()) + { + iEikonEnv->EikAppUi()->RemoveFromStack(this); + } + + // Don't release font, as we are using layout utils to use SAME font every time. + + delete iBrushAndPenContext; + delete iSBFrame; + + delete iMLBgContext; + delete iStaconBgContextTop; + delete iStaconBgContextBottom; + +#ifdef RD_ENHANCED_CBA + delete iCommandTable; +#endif // RD_ENHANCED_CBA + + delete iExtension; + } + +/** +* Constructor. +*/ +CEikCba::CEikCba(const CEikCba* aPrevious, + MEikCommandObserver* aCommandObserver, RWindowGroup* aParentWg, + TUint aFlags) + : iLink(aPrevious), iCommandObserver(aCommandObserver), iParentWg(aParentWg) + { + if (aFlags & CEikButtonGroupContainer::EIsEmbedded) + { + // CBA is embedded in another component (eg. dialog/popup/setting page + iFlags.Set(ECbaEmbedded); + } + + if ( aFlags & CEikButtonGroupContainer::EParentIsControl ) + { + iFlags.Set( ECbaParentAsControl ); + } + + if ( aFlags & CEikButtonGroupContainer::EDelayActivation ) + { + iFlags.Set( ECbaActivationDelayed ); + } + + CAknAppUi* appUi = static_cast( iCoeEnv->AppUi() ); + if ( appUi && appUi->IsSingleClickCompatible() ) + { + iFlags.Set( ECbaSingleClickEnabled ); + iFlags.Set( ECbaItemSpecificSoftkeyInUse ); + } + + SetNonFocusing(); + } + + +void CEikCba::SetContainerWindowL( const CCoeControl& aContainer ) + { + // CCoeControl::SetContainerWindowL closes the previously own window and + // deactivates control. Therefore store the activation status and re-set + // it after the container window has been set. + + // Removed to enable drawing of Query Input in one phase + //TBool wasActivated = IsActivated(); + // Check that this method was called from CAknQueryControl. Otherwise just + // bail out so that previous functionality (i.e. the one before SetContainerWindowL + // was overridded) is preserved. + CAknQueryControl* queryControl; + + queryControl = const_cast( aContainer ).MopGetObject( queryControl ); + + if ( queryControl == &aContainer ) + { + CCoeControl::SetContainerWindowL( aContainer ); + + // Convert all CEikCbaButtons to CAknButtons + iFlags.Set( ECbaInsideDialog ); + + TAknTextComponentLayout layout = AknLayoutScalable_Apps::cell_vitu2_itu_pane_t1( 0 ); + TAknLayoutText layoutText; + layoutText.LayoutText(Rect(), layout.LayoutLine() ); + + CCoeControl *leftSoftkey = (*iControlArray)[KControlArrayCBAButton1Posn].iControl; + CCoeControl *rightSoftkey = (*iControlArray)[KControlArrayCBAButton2Posn].iControl; + + TInt leftCommandId( (*iControlArray)[KControlArrayCBAButton1Posn].iId ); + TInt rightCommandId( (*iControlArray)[KControlArrayCBAButton2Posn].iId ); + + TRgb color = layoutText.Color(); + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + + AknsUtils::GetCachedColor( skin, color, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG65 ); + + + CAknButton* button = CAknButton::NewL(); + button->SetObserver( this ); + + + switch ( AknLayoutScalable_Apps::area_vitu2_query_pane_t1( 0 ).J() ) + { + case ELayoutAlignRight: + { + button->SetTextHorizontalAlignment( CGraphicsContext::ERight ); + break; + } + + case ELayoutAlignLeft: + { + button->SetTextHorizontalAlignment( CGraphicsContext::ELeft ); + break; + } + + case ELayoutAlignCenter: + default: + { + button->SetTextHorizontalAlignment( CGraphicsContext::ECenter ); + break; + } + } + + if ( !static_cast( leftSoftkey )->IsImageOn() ) + { + CEikLabel* label = static_cast( leftSoftkey->ComponentControl( 0 ) ); + + const TDesC* text = label->Text(); + button->AddStateL( NULL, NULL, NULL, NULL, *text, KNullDesC, 0, leftCommandId ); + + if ( text->Length() == 0 || !text->Compare( _L(" ") ) ) + { + button->SetDimmed( ETrue ); + } + } + + button->OverrideColorL( EColorButtonText, color ); + button->OverrideColorL( EColorButtonTextPressed, color ); + button->OverrideColorL( EColorButtonTextDimmed, color ); + + button->SetBackgroundIds( KAknsIIDQsnFrFunctionButtonNormal, + KAknsIIDQsnFrFunctionButtonPressed, KAknsIIDQsnFrFunctionButtonInactive, + KAknsIIDQsnFrFunctionButtonPressed, KAknsIIDQsnFrFunctionButtonInactive ); + + + delete leftSoftkey; + (*iControlArray)[KControlArrayCBAButton1Posn].iControl = button; + + button = CAknButton::NewL(); + button->SetObserver( this ); + + + switch ( AknLayoutScalable_Apps::area_vitu2_query_pane_t2( 0 ).J() ) + { + case ELayoutAlignRight: + { + button->SetTextHorizontalAlignment( CGraphicsContext::ERight ); + break; + } + + case ELayoutAlignLeft: + { + button->SetTextHorizontalAlignment( CGraphicsContext::ELeft ); + break; + } + + case ELayoutAlignCenter: + default: + { + button->SetTextHorizontalAlignment( CGraphicsContext::ECenter ); + break; + } + } + + if ( !static_cast( rightSoftkey )->IsImageOn() ) + { + CEikLabel* label = static_cast( rightSoftkey->ComponentControl( 0 ) ); + + const TDesC* text = label->Text(); + button->AddStateL( NULL, NULL, NULL, NULL, *text, KNullDesC, 0, rightCommandId ); + + if ( text->Length() == 0 || !text->Compare( _L(" ") ) ) + { + button->SetDimmed( ETrue ); + } + } + + button->OverrideColorL( EColorButtonText, color ); + button->OverrideColorL( EColorButtonTextPressed, color ); + button->OverrideColorL( EColorButtonTextDimmed, color ); + + button->SetBackgroundIds( KAknsIIDQsnFrFunctionButtonNormal, + KAknsIIDQsnFrFunctionButtonPressed, KAknsIIDQsnFrFunctionButtonInactive, + KAknsIIDQsnFrFunctionButtonPressed, KAknsIIDQsnFrFunctionButtonInactive ); + + delete rightSoftkey; + (*iControlArray)[KControlArrayCBAButton2Posn].iControl = button; + + // CCoeControl::ComponentControl can't be used since base class CEikControlGroup + // doesn't necessarily return all child controls. + for ( TInt i = 0; i < iControlArray->Count(); ++i ) + { + if ( (*iControlArray)[i].iControl ) + { + (*iControlArray)[i].iControl->SetContainerWindowL( *this ); + } + } + } + + else if ( iFlags.IsSet( ECbaEmbedded ) && + !iFlags.IsSet( ECbaParentAsControl ) ) + { + if ( OwnsWindow() ) + { + CloseWindow(); + } + + CreateWindowL( &aContainer ); + EnableWindowTransparency(); + + RWindow& window = Window(); + window.SetPointerGrab(ETrue); + EnableDragEvents(); + window.SetShadowDisabled(ETrue); + + TBool isEmpty = IsEmpty(); + + if ( !isEmpty && !iFlags.IsSet( ECbaHasContent ) ) + { + iFlags.Set( ECbaHasContent ); + } + + for ( TInt i = 0; i < iControlArray->Count(); ++i ) + { + if ( (*iControlArray)[i].iControl ) + { + (*iControlArray)[i].iControl->SetContainerWindowL( *this ); + } + } + } + else + { + CCoeControl::SetContainerWindowL( aContainer ); + } + } + +void CEikCba::ActivateL() + { + CCoeControl::ActivateL(); + } + +void CEikCba::BaseConstructL() + { + if ( iFlags.IsSet( ECbaEmbedded ) && iFlags.IsSet( ECbaParentAsControl ) ) + { + __ASSERT_DEBUG( iParentWg, User::Invariant() ); + CreateWindowL( (CCoeControl*)iParentWg ); + EnableWindowTransparency(); + iParentWg = NULL; + iCbaFlags &= ~EEikCbaFlagTransparent; + } + else + { + CreateWindowL( iParentWg ); + + if ( ( ( iCbaFlags & EEikCbaFlagTransparent ) || + iCbaFlags & EEikCbaFlagSemiTransparent ) && + CAknEnv::Static()->TransparencyEnabled() ) + { + Window().SetRequiredDisplayMode( EColor16MA ); // Without this, ACT does not work in all cases in HW + TInt err = Window().SetTransparencyAlphaChannel(); + + if ( err == KErrNone ) + { + // Set the window initially completely transparent. This needs to be called only once. + Window().SetBackgroundColor(~0); + } + else + { + // SetTransparencyAlphaChannel returned an error. + // Revert back to non-transparent CBA. + iCbaFlags &= ~EEikCbaFlagTransparent; + } + } + else + { + // Transparency not supported or not enabled + iCbaFlags &= ~EEikCbaFlagTransparent; + } + } + + iExtension = CEikCbaExtension::NewL( *this ); + //create bitmap for semi-transparent background + if ( iCbaFlags & EEikCbaFlagSemiTransparent && iExtension ) + { + iExtension->iSemiBgID = KAknsIIDQsnHomeBgWidget; + iExtension->iSemiBgCenterID = KAknsIIDQsnHomeBgWidgetCenter; + } + + // Skin background is not drawn by embedded CBA. + if ( !iFlags.IsSet( ECbaEmbedded ) ) + { + TRect screen; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen ); + + // Construct background control context, SizeChanged will update + // the layout rectangle. + iBgIID = AknStatuspaneUtils::IdleLayoutActive() ? + KAknsIIDQsnBgAreaControlIdle : + KAknsIIDQsnBgAreaControl; + + iMLBgContext = CAknsMaskedLayerBackgroundControlContext::NewL( + KAknsIIDWallpaper, + TRect( 0, 0, 1, 1 ), + ETrue, + 2 ); + + // Other context for staconpane + + // There is a need for two layers in each context: one for wallpaper, + // the other for skin graphics. + iStaconBgContextTop = CAknsMaskedLayerBackgroundControlContext::NewL( + KAknsIIDWallpaper, TRect( 0, 0, 1, 1 ), ETrue, ECbaLayerN ); + iStaconBgContextBottom = CAknsMaskedLayerBackgroundControlContext::NewL( + KAknsIIDWallpaper, TRect( 0, 0, 1, 1 ), ETrue, ECbaLayerN ); + + for ( TInt i = 0; i < ECbaLayerN; i++ ) + { + iStaconBgContextBottom->SetLayerImage( i, KAknsIIDNone ); + } + + TAknWindowLineLayout layout( AknLayoutScalable_Avkon::area_top_pane(2).LayoutLine() ); + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( screen, layout ); + TRect staconTop( layoutRect.Rect() ); + + layout = AknLayoutScalable_Avkon::area_bottom_pane(2).LayoutLine(); + layoutRect.LayoutRect( screen, layout ); + TRect staconBottom( layoutRect.Rect() ); + + // Set layers to stacon contexts. + // Set bottom as parent to top, so that top is re-drawn, if bottom is drawn. + iStaconBgContextTop->SetLayerImage( ECbaLayerWallpaper, KAknsIIDWallpaper ); + iStaconBgContextTop->SetLayerRect( ECbaLayerWallpaper, screen ); + iStaconBgContextTop->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconRt ); + iStaconBgContextTop->SetLayerRect( ECbaLayerBackground, staconTop ); + + iStaconBgContextBottom->SetLayerImage( ECbaLayerWallpaper, KAknsIIDWallpaper ); + iStaconBgContextBottom->SetLayerRect( ECbaLayerWallpaper, screen ); + iStaconBgContextBottom->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconRb ); + iStaconBgContextBottom->SetLayerRect( ECbaLayerBackground, staconBottom ); + iStaconBgContextBottom->SetParentPos( TPoint( 0, 0 ) ); + + iStaconBgContextTop->SetParentContext( iStaconBgContextBottom ); + + TBool idle = AknLayoutFlags() & EAknLayoutCbaInStaconPaneIdle; + if ( idle ) + { + iStaconBgContextTop->SetLayerMaskAndSizeL( KAknsIIDQgnGrafBgLscTopMaskIcon, staconTop ); + iStaconBgContextBottom->SetLayerMaskAndSizeL( KAknsIIDQgnGrafBgLscBottomMaskIcon, staconBottom ); + } + + } + + iExtension->UpdateSoftkeyFrameL( EFalse ); + + CRepository* cenRep = NULL; + TRAPD(err, cenRep = CRepository::NewL( KCRUidAvkon )); + if (!err) + { + err = cenRep->Get( KAknMiddleSoftkeyEnabled, iMSKEnabledInPlatform ); + delete cenRep; + } + + RWindow& window = Window(); + window.SetPointerGrab(ETrue); + EnableDragEvents(); + window.SetShadowDisabled(ETrue); + if ( ! ( iCbaFlags & EEikCbaFlagTransparent ) ) + { + window.SetBackgroundColor(iEikonEnv->ControlColor(EColorToolbarBackground, *this)); + } + CEikControlGroup::ConstructL(CEikControlGroup::EFromBottomLeft, CEikControlGroup::ELayHorizontally); + SetLengthInPixels(iAvkonAppUi->ApplicationRect().Width()); + SetNumberOfLines(1, ETrue); + iBrushAndPenContext = CCoeBrushAndPenContext::NewL(); + CheckSkinAndUpdateContext(); + iBrushAndPenContext->SetBrushColor(iEikonEnv->ControlColor(EColorToolbarBackground, *this)); + iBrushAndPenContext->SetPenColor(iEikonEnv->ControlColor(EColorToolbarText, *this)); + SetControlContext(iBrushAndPenContext); + iEikonEnv->EikAppUi()->AddToStackL(this, ECoeStackPriorityCba, ECoeStackFlagRefusesFocus); + UpdateFonts(); + + SetMSKVisibility( MskAllowed() ); + + if ( !iFlags.IsSet( ECbaEmbedded ) ) + { + if ( AknStatuspaneUtils::ExtendedFlatLayoutActive() ) + { + // Store the current skin background ID of the clock and indicator + // pane area to draw their background correctly if custom CBA + // background is used. + CEikStatusPaneBase* sp = CEikStatusPaneBase::Current(); + if ( sp ) + { + iClockIndicBgIID = sp->CbaAreaBackgroundID(); + if ( iClockIndicBgIID == KAknsIIDQsnBgAreaControlMp ) + { + // Skin background ID needs to be reverted back + // in destructor. + iIsClockIndicBgIIDSet = ETrue; + } + sp->SetCbaAreaBackgroundID( iBgIID, CEikStatusPaneBase::EDrawDeferred ); + } + else + { + // Default value. + iClockIndicBgIID = KAknsIIDQsnBgAreaControl; + } + } + } + } + +void CEikCba::ConstructL(TInt aResourceId) + { + if (aResourceId != KNoResource) + { + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader, aResourceId); + iCbaFlags = reader.ReadInt32(); // flags resource + + // If using enhanced cba. + if ( (iCbaFlags & EEikEnhancedButtonGroup) == EEikEnhancedButtonGroup ) + { +#ifdef RD_ENHANCED_CBA + iCommandTable = CEikCommandTable::NewL(); + BaseConstructL(); + CreateScrollBarFrameL(); + + iSize.iWidth = reader.ReadInt16(); + reader.ReadInt32(); // Skip related buttons resource. + TInt count( reader.ReadInt16() ); // Read the amount of enhanced cba buttons. + + for ( TInt ii = 0; ii < count; ii++ ) + { + TUint8 version( (TUint8)reader.ReadUint8() ); + TInt commandId( 0 ); + TInt longCommandId( 0 ); + CEikEnhancedCbaButton* button = new (ELeave) CEikEnhancedCbaButton; + button->SetTextBitmapMode( iExtension->iEnablePostingTransparency ); + CleanupStack::PushL( button ); + + if( version == EEikCbaButtonLink ) + { + TInt aButtonId( reader.ReadInt32() ); // Read ENHANCED_CBA_BUTTON id from LLINK. + TResourceReader linkReader; // Reader for reading linked resource. + iCoeEnv->CreateResourceReaderLC( linkReader, aButtonId ); + TUint8 ver( linkReader.ReadUint8() ); + if( ver == EEikEnhancedCbaButton ) + { + button->ConstructFromResourceL( linkReader ); + } + CleanupStack::PopAndDestroy( ); // linkReader + } + else if( version == EEikEnhancedCbaButton ) + { + button->ConstructFromResourceL( reader ); + } + else + { + CleanupStack::PopAndDestroy( button ); + continue; // Jump over the rest. + } + + iCommandTable->AddCommandL( button ); // Transfers ownership. + CleanupStack::Pop( button ); + } + + // Set observer and add to control group if placed in the command table. + for ( TInt i = 0; i < KMaxButtonsInCommandTable; i++ ) + { + CEikEnhancedCbaButton* button = iCommandTable->Command( i ); + if( button ) + { + button->SetObserver( Observer() ); + button->SetLabelFont( iLabelFont ); + + TEikGroupControl groupCtrl( + button, + button->CommandId(), + button->Size().iWidth, + TEikGroupControl::ESetLength); + + groupCtrl.iLongId = 0; + AddControlL(groupCtrl); // Transfers ownership. + } + else + { + // Add dummy button if no command for this index. + button = new (ELeave) CEikEnhancedCbaButton; + button->SetTextBitmapMode( iExtension->iEnablePostingTransparency ); + CleanupStack::PushL( button ); + button->ConstructEmptyButtonL(); + CleanupStack::Pop( button ); + + TEikGroupControl groupCtrl( + button, + button->CommandId(), + button->Size().iWidth, + TEikGroupControl::ESetLength); + + AddControlL(groupCtrl); + } + } + + InsertScrollBarL(); + + // This needs to be after all buttons are inserted to control group. + SetBoundingRect(TRect()); + + ActivateL(); +#else // RD_ENHANCED_CBA + User::Leave( KErrNotSupported ); +#endif // RD_ENHANCED_CBA + } + else // Not using enhanced cba. + { + reader.Rewind(4); + ConstructFromResourceL(reader); + } + + CleanupStack::PopAndDestroy(); // reader + } + else // aResourceId == KNoResource + { + BaseConstructL(); + CreateScrollBarFrameL(); + // Alignments for left, right and MSK. + TGulAlignmentValue anAlignment[3] = {EHLeftVCenter, EHRightVCenter, EHCenterVCenter}; + const TInt commands = MaxCommands(); + + for (TInt ii = 0; ii < commands; ii++) + { + CEikCbaButton* button = new(ELeave) CEikCbaButton; + button->SetTextBitmapMode( iExtension->iEnablePostingTransparency ); + button->SetObserver(Observer()); + CleanupStack::PushL(button); + button->ConstructL(anAlignment[ii]); + + // Initialise button size. + if(Orientation() == ELayHorizontally) + { + TSize buttonSize((MinimumSize().iWidth) / commands, button->MinimumSize().iHeight); + button->SetSize(buttonSize); + } + + TEikGroupControl groupCtrl(button, ii, 0, TEikGroupControl::EAllowStretch); + AddControlL(groupCtrl); + button->SetLabelFont(iLabelFont); + CleanupStack::Pop( button ); + } + + InsertScrollBarL(); // into control group + iMSKset = EFalse; + + // This needs to be after all buttons are inserted to control group. + SetBoundingRect(TRect()); + + if ( !iFlags.IsSet( ECbaActivationDelayed ) ) + { + ActivateL(); + } + + // We need to activate MSK in here - it won't be otherwise activated in landscape. + if ( iMSKEnabledInPlatform && AknLayoutUtils::MSKEnabled() && + iControlArray->Count() == (MaxCommands() + 1) ) // scrollbar added + { + if ( (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl ) + { + (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl->ActivateL(); + } + } + } + + // Set CBA faded in case the softkeys are empty. + SetFadeState(); + } + + +void CEikCba::ConstructFromResourceL(TResourceReader& aReader) + { + BaseConstructL(); + CreateScrollBarFrameL(); + TGulAlignmentValue anAlignment[3] = {EHLeftVCenter, EHRightVCenter, EHCenterVCenter}; + iCbaFlags = aReader.ReadInt32(); // flags resource + iSize.iWidth = aReader.ReadInt16(); + aReader.ReadInt32(); // Skip related buttons resource. + + // Ignore any commands that won't fit on screen. + TInt count = Min(aReader.ReadInt16(), MaxCommands()); + __ASSERT_DEBUG(iControlArray->Count() <= count + 2, Panic(EEikPanicCBAControlArraySize)); + + for (TInt ii = 0; ii < count; ii++) + { + TUint8 version = (TUint8)aReader.ReadUint8(); + TInt commandId; + TInt longCommandId; + if (version == KAknCbaVersion) + { + commandId = aReader.ReadInt16(); + longCommandId = aReader.ReadInt16(); + } + else + { + commandId = aReader.ReadInt16(); + longCommandId = 0; + } + CEikCbaButton* button = new(ELeave) CEikCbaButton; + button->SetTextBitmapMode( iExtension->iEnablePostingTransparency ); + button->SetObserver(Observer()); + CleanupStack::PushL(button); + button->ConstructFromResourceL(aReader, anAlignment[ii]); + // Initialise button size. + if(Orientation() == ELayHorizontally) + { + TSize buttonSize((MinimumSize().iWidth)/count, button->MinimumSize().iHeight); + button->SetSize(buttonSize); + } + TEikGroupControl groupCtrl( + button, + commandId, + button->Size().iWidth, + TEikGroupControl::ESetLength); + + groupCtrl.iLongId = longCommandId; + AddControlL(groupCtrl); + button->SetLabelFont(iLabelFont); + CleanupStack::Pop( button ); + } + + InsertScrollBarL(); // into control group + iMSKset = ETrue; + + // MSK is not mandatory, so add empty button if resource not found. + if (iControlArray->Count() < MaxCommands() + 1) // scrollbar added + { + iMSKset = EFalse; + CEikCbaButton* button = new (ELeave) CEikCbaButton; + button->SetTextBitmapMode( iExtension->iEnablePostingTransparency ); + CleanupStack::PushL( button ); + button->ConstructEmptyButtonL(); + CleanupStack::Pop( button ); + TEikGroupControl groupCtrl(button, 0, button->Size().iWidth,TEikGroupControl::ESetLength); + AddControlL(groupCtrl); + } + + // This needs to be after all buttons are inserted to control group. + if (iMSKset) + { + SetMSKIconL(); + } + + SetBoundingRect(TRect()); + + if ( !iFlags.IsSet( ECbaActivationDelayed ) ) + { + ActivateL(); + } + + // We need to activate MSK in here - it won't be otherwise activated in landscape. + if ( iMSKEnabledInPlatform && AknLayoutUtils::MSKEnabled() && + iControlArray->Count() == (MaxCommands() + 1) ) // scrollbar added + { + if ( (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl ) + { + (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl->ActivateL(); + } + } + + // Set CBA faded in case the softkeys are empty. + SetFadeState(); + } + + +TInt CEikCba::MaxCommands() const + { + return KMaxSeries60Softkeys; + } + +TInt CEikCba::MSKEnabledInPlatform() const + { + return iMSKEnabledInPlatform; + } + + +// --------------------------------------------------------------------------- +// Sets the middle softkey icon. +// --------------------------------------------------------------------------- +// +void CEikCba::SetMSKIconL() + { + // MSK is not supported by dialog-embedded CBAs. + if ( iFlags.IsSet( ECbaInsideDialog ) || iFlags.IsSet( ECbaEmbedded ) ) + { + return; + } + + if ( !MskAllowed() ) + { + return; + } + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + if ( !skin ) + { + return; + } + if( iExtension->iIfMskIconSet ) + { + // UpdateIconL(); + return; + } + TEikGroupControl &gCtrl = iControlArray->At( KControlArrayCBAButtonMSKPosn ); + + CEikCbaButton *button = static_cast( gCtrl.iControl ); + if ( !button ) + { + return; + } + + CFbsBitmap *bitmap = NULL; + CFbsBitmap *mask = NULL; + + TAknLayoutRect qgn_graf_sk_msk; + TRect rect; + qgn_graf_sk_msk.LayoutRect( + rect, + AknLayoutScalable_Avkon::control_pane_g4( 0 ).LayoutLine() ); + + TSize iconSize( qgn_graf_sk_msk.Rect().Width(), + qgn_graf_sk_msk.Rect().Height() ); + TInt leftId = (*iControlArray)[KControlArrayCBAButton1Posn].iId; + + TRgb MSKColor; + TInt errorMSK; + + TInt iconColorId(0); + TInt leftCBAColorId(0); + + TBool idleState = AknStatuspaneUtils::IdleLayoutActive(); + if ( idleState ) + { + iconColorId = EAknsCIQsnIconColorsCG28; + leftCBAColorId = EAknsCIQsnTextColorsCG15; + + errorMSK = AknsUtils::GetCachedColor( + skin, + MSKColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG57 ); + } + else if ( iPopupVisible ) + { + iconColorId = EAknsCIQsnIconColorsCG29; + leftCBAColorId = EAknsCIQsnTextColorsCG17; + + errorMSK = AknsUtils::GetCachedColor( + skin, + MSKColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG58 ); + } + else + { + iconColorId = EAknsCIQsnIconColorsCG27; + leftCBAColorId = EAknsCIQsnTextColorsCG13; + + errorMSK = AknsUtils::GetCachedColor( + skin, + MSKColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG56 ); + } + + if ( errorMSK ) + { + // Use black if no color specified for MSK in skin. + MSKColor = KRgbBlack; + AknsUtils::GetCachedColor( skin, + MSKColor, + KAknsIIDQsnTextColors, + leftCBAColorId ); + } + + if ( gCtrl.iId == EAknSoftkeyContextOptions ) + { + // Set context specific options menu icon. + AknsUtils::CreateColorIconL( + skin, + KAknsIIDQgnPropMskMenu, + KAknsIIDQsnIconColors, + iconColorId, // There is no color for icon -> use text color. + bitmap, + mask, + KAvkonBitmapFile, + EMbmAvkonQgn_prop_msk_menu, + EMbmAvkonQgn_prop_msk_menu_mask, + MSKColor ); + } + else if ( gCtrl.iId == EAknSoftkeyDialler ) + { + // Set context specific options menu icon. + AknsUtils::CreateColorIconL( + skin, + KAknsIIDQgnIndiTpDialler, + KAknsIIDQsnIconColors, + iconColorId, // There is no color for icon -> use text color. + bitmap, + mask, + KAvkonBitmapFile, + EMbmAvkonQgn_indi_tp_dialler, + EMbmAvkonQgn_indi_tp_dialler_mask, + MSKColor ); + } + else if ( leftId == gCtrl.iId) + { + if ( leftId != EEikBidBlank && + leftId != EAknSoftkeyEmpty && + leftId != 0 ) + { + // Same as left softkey icon. + AknsUtils::CreateColorIconL( + skin, + KAknsIIDQgnPropMskSelect, + KAknsIIDQsnIconColors, + iconColorId, // There is no color for icon -> use text color. + bitmap, + mask, + KAvkonBitmapFile, + EMbmAvkonQgn_prop_msk_select, + EMbmAvkonQgn_prop_msk_select_mask, + MSKColor ); + } + } + + if ( bitmap ) // Bitmap not set -> do not use image. + { + AknIconUtils::DisableCompression( bitmap ); + AknIconUtils::DisableCompression( mask ); + AknIconUtils::SetSize( bitmap, iconSize ); + + CEikImage* image = new (ELeave) CEikImage; + image->SetPicture( bitmap, mask ); + + // Transfers ownership of the image (image owns bitmap and mask). + button->SetImage( *image ); + } + else + { + button->ReplaceImageByLabel(); // remove old image + } + + button->SetContainerWindowL( *this ); + } + +EXPORT_C TBool CEikCba::UpdateMSKIconL( const TAknsItemID& aId, + const TDesC& aBmpFile, + const TInt32 aBmp, + const TInt32 aBmpM, + TBool aEnable ) + { + iExtension->iIfMskIconSet = EFalse; + + // MSK is not supported by dialog-embedded CBAs. + if (!aEnable) + { + SetMSKIconL(); + return ETrue; + } + + delete iExtension->iBmpFile; + iExtension->iBmpFile = NULL; + iExtension->iBmpFile = aBmpFile.AllocL(); + + iExtension->iIfMskIconSet = ETrue; + iExtension->iMSKSkinID = aId; + + iExtension->iBmp = aBmp; + iExtension->iBmpM = aBmpM; + + return UpdateIconL(); + } + + +// ---------------------------------------------------------------------------- +// CEikCba::EnableItemSpecificSoftkey +// ---------------------------------------------------------------------------- +// +EXPORT_C void CEikCba::EnableItemSpecificSoftkey( TBool aEnable ) + { + if ( iFlags.IsSet( ECbaSingleClickEnabled ) ) + { + iFlags.Assign( ECbaItemSpecificSoftkeyInUse, aEnable ); + + if ( aEnable ) + { + UpdateItemSpecificSoftkey(); + } + else + { + TEikGroupControl& leftSoftkey = + ( *iControlArray )[KControlArrayCBAButton1Posn]; + + if ( !iFlags.IsSet( ECbaInsideDialog ) ) + { + leftSoftkey.iControl->MakeVisible( ETrue ); + } + else + { + leftSoftkey.iControl->SetDimmed( EFalse ); + leftSoftkey.iControl->DrawDeferred(); + } + } + } + } + + +void CEikCba::SetMSKCommandObserver(MEikCommandObserver* aCommandObserver) + { + // aCommandObserver set to NULL when removing observer. + iMSKCommandObserver = aCommandObserver; + } + +void CEikCba::UpdateCbaLabels(TBool aScrollerOn) + { + // This method is called only from scrollbar that has nothing to do with + // dialog-embedded CBAs -> ignore the call. + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + return; + } + + // Communicate change to CBA buttons. + for (TInt ii = 0; ii < iControlArray->Count(); ii++) + { + if (ii != KControlArrayScrollBarPosn) // To avoid tinkering with scrollbar. + { + TEikGroupControl& gCtrl = iControlArray->At(ii); + CEikCbaButton* button = STATIC_CAST(CEikCbaButton*, gCtrl.iControl); + TRAP_IGNORE(button->SwitchToShortTextL(aScrollerOn)); + } + } + // Change of text may affect layout. + SizeChanged(); + DrawDeferred() ; + } + +void CEikCba::SetSBFrameObserver(MEikScrollBarObserver* aObserver) + { + if(iSBFrame) + { + iSBFrame->SetScrollBarFrameObserver(aObserver); + } + } + +void CEikCba::SetScrollBarModelL(TEikScrollBarModel* aModel) + { + if(iSBFrame) + { + VScrollBarAsControl()->SetModelL(aModel); + } + } + +const CEikCbaScrollBarFrame* CEikCba::ScrollBarFrame() const + { + return STATIC_CAST(const CEikCbaScrollBarFrame*, iSBFrame); + } + +CAknScrollBar* CEikCba::VScrollBarAsControl() + { + return STATIC_CAST(CAknScrollBar*, VScrollBarAsGroupControl().iControl); + } + +void CEikCba::InsertControlL(TEikGroupControl& aGroupControl,TInt aIndex) + { + iControlArray->InsertL(aIndex,aGroupControl); // Takes ownership at this point. + } + + +void CEikCba::SetCommandL( TInt aPosition, + TInt aCommandId, + const TDesC* aText, + const CFbsBitmap* /*aBitmap*/, + const CFbsBitmap* /*aMask*/ ) + { + // We need to check if this call changes the softkeys from being + // empty to having a command or vice versa to be able to maintain + // correct fade state. + TBool isEmptyBefore( IsEmpty() ); + + TEikGroupControl& groupCtrl = (*iControlArray)[aPosition]; + groupCtrl.iId = aCommandId; + groupCtrl.iLongId = 0; + if ( !iFlags.IsSet( ECbaInsideDialog ) ) + { + if ( aText ) + { + static_cast( + groupCtrl.iControl )->AddCommandL( *aText ); + } + + if ( aPosition == KControlArrayCBAButtonMSKPosn ) + { + iMSKset = ETrue; + } + SetMSKIconL(); // If MSK or left CBA was changed, this sets MSK icon accordingly. + + // Force labels to be re-formatted... + SizeChanged(); + } + else if ( aPosition != KControlArrayCBAButtonMSKPosn ) + { + CAknButton* button = static_cast( groupCtrl.iControl ); + CAknCommandButtonState* buttonState = + static_cast( button->State() ); + buttonState->SetTextL( *aText ); + buttonState->SetCommand( aCommandId ); + } + + TBool isEmptyAfter( IsEmpty() ); + + if ( !COMPARE_BOOLS( isEmptyBefore, isEmptyAfter ) ) + { + SetFadeState(); + } + + ReportContentChangedEvent(); + } + + +void CEikCba::SetCommandL(TInt aPosition,TInt aResourceId) + { + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader,aResourceId); + TInt version = reader.ReadInt8(); // version + +#ifdef RD_ENHANCED_CBA + if( version == EEikCbaButtonLink ) + { + TInt aButtonId = reader.ReadInt32(); // Read ENHANCED_CBA_BUTTON id from LLINK. + CleanupStack::PopAndDestroy(); // reader + iCoeEnv->CreateResourceReaderLC( reader, aButtonId ); + TUint8 aVersion = reader.ReadUint8(); + + // Panics if linked resource is not enhanced cba button. + __ASSERT_DEBUG( aVersion == EEikEnhancedCbaButton, Panic(EEikPanicCBAIsNotEnhancedCba) ); + + reader.ReadUint8(); // commandType + } + else if( version == EEikEnhancedCbaButton ) + { + reader.ReadUint8(); // commandType + } +#endif // RD_ENHANCED_CBA + TInt commandId(0); + if (version == KAknCbaVersion) + { + commandId = reader.ReadInt16(); + reader.ReadInt16(); + } + else + { + commandId = reader.ReadInt16(); + } + + TPtrC text = reader.ReadTPtrC(); + SetCommandL(aPosition, commandId, &text, NULL, NULL); + CleanupStack::PopAndDestroy(); // reader + + ReportContentChangedEvent(); + } + +/** +* Installs a new set of commands to be associated with the cba buttons. +* The previous command set is restored if there is an error while adding +* the new command set. +*/ +void CEikCba::SetCommandSetL(TInt aResourceId) + { + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader, aResourceId); + + iCbaFlags = reader.ReadInt32(); + + if ( ( iCbaFlags & EEikEnhancedButtonGroup ) == EEikEnhancedButtonGroup ) + { + CleanupStack::PopAndDestroy(); // reader + OfferCommandListL( aResourceId ); + return; + } + + SetButtonGroupFlags( iCbaFlags ); + reader.ReadInt16(); // Skip width resource. + reader.ReadInt32(); // Skip related buttons resource. + const TInt maxCommands = MaxCommands(); + + // Ignore any commands that won't fit on screen. + TInt count = Min(reader.ReadInt16(), maxCommands); + + TInt previousIds[KMaxSeries60Softkeys + 1]; // Uses 16 bytes stack, +1 for scrollbar. + + __ASSERT_DEBUG(iControlArray->Count() <= count + 2, Panic(EEikPanicCBAControlArraySize)); + + // Replace the existing command set. + TInt controlId = 0; + for (controlId = 0; controlId < count + 1; controlId++) // (+1 for scroll bar) + { + if (controlId != KControlArrayScrollBarPosn) // To avoid tinkering with scrollbar. + { + // Store the existing commands. + TEikGroupControl& groupCtrl = (*iControlArray)[controlId]; + previousIds[controlId] = groupCtrl.iId; + TUint8 version = (TUint8)reader.ReadUint8(); + TInt commandId; + TInt errorcode; + + if (version == KAknCbaVersion) + { + commandId = reader.ReadInt16(); + reader.ReadInt16(); // Skip long command id. + } + else + { + commandId = reader.ReadInt16(); + } + TPtrC text=reader.ReadTPtrC(); + reader.ReadTPtrC(); // bmp filename + reader.ReadInt16(); // bmp id + reader.ReadInt16(); // bmp mask id + + // Add the new commands. + TRAP(errorcode, AddCommandToStackWithoutSizeChangedL(controlId, commandId, &text)); + if (errorcode) // In case of error restore previous commands before leave. + { + if (controlId > 0) + { + for (TInt counter = 0; counter < controlId; counter++) + { + // Do not deal with the scroller as a CEikCbaButton; skip its index. + if (counter != KControlArrayScrollBarPosn) + { + RemoveCommandFromStack(counter,previousIds[counter]); + } + } + } + User::Leave(errorcode); + } + } + } + + // Remove the original commands from the temporary store. + for (controlId = 0; controlId < count + 1; controlId++) // +1 for scroll bar + { + if (controlId != KControlArrayScrollBarPosn) + { + TInt controlPosition = controlId; + if (controlId > 1) + { + controlPosition-=1; + } + RemovePreviousCommandWithoutSizeChanged(controlId); + } + } + SetMSKIconL(); + // If MSK was not defined in softkey resources, set MSK command id same as left + // softkey's command id and set label empty. + // We can't restore original commands any more, so if setting MSK fails, + // at least left and right softkeys are set. + if (count < KControlArrayCBAButtonMSKPosn) + { + TRAP_IGNORE( SetCommandL( + KControlArrayCBAButtonMSKPosn, + (*iControlArray)[KControlArrayCBAButton1Posn].iId, + &KNullDesC, + NULL, + NULL) ); + + iMSKset = ETrue; + } + else + { + SetMSKIconL(); // If MSK id was changed, this sets MSK icon accordingly. + } + + CleanupStack::PopAndDestroy(); // reader + + // Force labels to be re-formatted... + SizeChanged(); + ReportContentChangedEvent(); + } + +void CEikCba::AddCommandL(TInt /*aPosition*/, TInt /*aCommandId*/, const TDesC* /*aText*/, + const CFbsBitmap* /*aBitmap*/, const CFbsBitmap* /*aMask*/) + { + User::Leave(KErrNotSupported); + } + + +void CEikCba::AddCommandToStackWithoutSizeChangedL(TInt aPosition, + TInt aCommandId, + const TDesC* aText) + { + // We need to check if this call changes the softkeys from being + // empty to having a command or vice versa to be able to maintain + // correct fade state. + TBool isEmptyBefore( IsEmpty() ); + + TEikGroupControl& groupCtrl = (*iControlArray)[aPosition]; + + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + CAknButton* button = static_cast( groupCtrl.iControl ); + button->AddStateL( NULL, NULL, NULL, NULL, *aText, KNullDesC, 0, aCommandId ); + + if ( aText->Length() == 0 || !aText->Compare( _L(" ") ) ) + { + button->SetDimmed( ETrue ); + } + + TInt state( button->StateIndex() + 1 ); + + // DrawDeferred must be used here to reduce flicker, + // as ECS may cause unnecessary CBA label updates in queries. + button->SetCurrentState( state, EFalse ); + button->DrawDeferred(); + } + else + { + static_cast(groupCtrl.iControl)->PushCommandL(groupCtrl.iId /*aCommandId*/, + *aText); + } + + groupCtrl.iId = aCommandId; + groupCtrl.iLongId = 0; + + if ( aPosition == KControlArrayCBAButtonMSKPosn ) + { + iMSKset = ETrue; + } + SetMSKIconL(); // If MSK id was changed, this sets MSK icon accordingly. + + TBool isEmptyAfter( IsEmpty() ); + + if ( !COMPARE_BOOLS( isEmptyBefore, isEmptyAfter ) ) + { + SetFadeState(); + } + + ReportContentChangedEvent(); + } + +void CEikCba::AddCommandToStackL( TInt aPosition, + TInt aCommandId, + const TDesC* aText, + const CFbsBitmap* /*aBitmap*/, + const CFbsBitmap* /*aMask*/ ) + { + + AddCommandToStackWithoutSizeChangedL( aPosition, aCommandId, aText); + // Force labels to be re-formatted... + SizeChanged(); + } + + +void CEikCba::AddCommandToStackL(TInt aPosition, TInt aResourceId) + { + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader,aResourceId); + TUint8 version = (TUint8)reader.ReadInt8(); + TInt commandId(0); + if (version == KAknCbaVersion) + { + commandId = reader.ReadInt16(); + reader.ReadInt16(); // Skip long command id. + } + else + { + commandId = reader.ReadInt16(); + } + TPtrC text=reader.ReadTPtrC(); + AddCommandToStackL(aPosition, commandId, &text, NULL, NULL); + CleanupStack::PopAndDestroy(); // reader + + ReportContentChangedEvent(); + } + +void CEikCba::AddCommandSetToStackL(TInt aResourceId) + { + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader,aResourceId); + + iCbaFlags = reader.ReadInt32(); // Flags resource. + reader.ReadInt16(); // Skip width resource. + reader.ReadInt32(); // Skip related buttons resource. + + SetButtonGroupFlags( iCbaFlags ); + // Ignore any commands that won't fit on screen. + const TInt maxCommands = MaxCommands(); + const TInt count = Min(reader.ReadInt16(), maxCommands); + + __ASSERT_DEBUG(iControlArray->Count() <= count + 2, Panic(EEikPanicCBAControlArraySize)); + + for (TInt ii = 0; ii < count + 1; ii++) // +1 for scroll bar + { + if (ii != KControlArrayScrollBarPosn) // To avoid tinkering with the scrollbar. + { + TUint8 version = (TUint8)reader.ReadUint8(); + TInt commandId; + + if (version == KAknCbaVersion) + { + commandId = reader.ReadInt16(); + reader.ReadInt16(); // Skip long command id. + } + else + { + commandId = reader.ReadInt16(); + } + TPtrC text = reader.ReadTPtrC(); + reader.ReadTPtrC(); // bmp filename + reader.ReadInt16(); // bmp id + reader.ReadInt16(); // bmp mask id + TInt errorcode; + TRAP(errorcode, AddCommandToStackWithoutSizeChangedL(ii, commandId, &text)); + if (errorcode) // Restore previous commands before leave. + { + if (ii > 0) + { + for (TInt counter = 0; counter < ii; counter++) + { + if (counter != KControlArrayScrollBarPosn) + { + TEikGroupControl& groupCtrl = (*iControlArray)[counter]; + + groupCtrl.iId = + STATIC_CAST(CEikCbaButton*, groupCtrl.iControl)->PopCommand(); + + groupCtrl.iLongId = 0; + } + } + } + User::Leave(errorcode); + } + } + } + + if (count == KControlArrayCBAButtonMSKPosn) + { + iMSKset = ETrue; + } + SetMSKIconL(); // If MSK id was changed, this sets MSK icon accordingly. + + CleanupStack::PopAndDestroy(); // reader + + // Force labels to be re-formatted... + SizeChanged(); + ReportContentChangedEvent(); + } + +void CEikCba::SetDefaultCommand(TInt /*aCommandId*/) + { + } + +TSize CEikCba::CalcMinimumSizeL(TInt /*aResourceId*/) + { + return MinimumSize(); + } + + +void CEikCba::RemoveCommandFromStack( TInt aPosition, TInt aCommandId ) + { + // We need to check if this call changes the softkeys from being + // empty to having a command or vice versa to be able to maintain + // correct fade state. + TBool isEmptyBefore( IsEmpty() ); + + TEikGroupControl& groupCtrl = (*iControlArray)[aPosition]; + if ( groupCtrl.iId == aCommandId ) + { + // Command to be removed is topmost. + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + CAknButton* button = static_cast( groupCtrl.iControl ); + button->RemoveCurrentState(); + + CAknCommandButtonState* buttonState = + static_cast( button->State() ); + + groupCtrl.iId = buttonState->CommandId(); + groupCtrl.iLongId = 0; + + if ( buttonState->Text().Length() == 0 || + !buttonState->Text().Compare( _L(" ") ) ) + { + button->SetDimmed( ETrue ); + } + } + else + { + groupCtrl.iId = static_cast( groupCtrl.iControl )->PopCommand(); + groupCtrl.iLongId = 0; + } + } + else // Command to be removed is not on the top, check the whole stack. + { + STATIC_CAST(CEikCbaButton*, groupCtrl.iControl)->RemoveCommand(aCommandId); + } + + // If MSK or left CBA was changed, this sets MSK icon accordingly. + TRAP_IGNORE( SetMSKIconL() ); + + // Force labels to be re-formatted... + SizeChanged(); + + TBool isEmptyAfter( IsEmpty() ); + + if ( !COMPARE_BOOLS( isEmptyBefore, isEmptyAfter ) ) + { + SetFadeState(); + } + + DrawDeferred(); + ReportContentChangedEvent(); + } + +void CEikCba::RemovePreviousCommandWithoutSizeChanged(TInt aPosition) + { + TEikGroupControl& groupCtrl = (*iControlArray)[aPosition]; + STATIC_CAST(CEikCbaButton*, groupCtrl.iControl)->RemovePreviousCommand(); + } + +void CEikCba::RemovePreviousCommand(TInt aPosition) + { + RemovePreviousCommandWithoutSizeChanged( aPosition ); + // If MSK or left CBA was changed, this sets MSK icon accordingly. + TRAP_IGNORE( SetMSKIconL() ); + + // Force labels to be re-formatted... + SizeChanged(); + ReportContentChangedEvent(); + } + + +TInt CEikCba::CommandPos(TInt aCommandId) const + { + return IndexById(aCommandId); + } + +void CEikCba::DimCommand(TInt aCommandId,TBool aDimmed) + { + CCoeControl* control( ButtonById( aCommandId ) ); + if ( control ) + { + if ( SoftkeyStatusChangeAllowed( IndexById( aCommandId ), aDimmed ) ) + { + control->SetDimmed( aDimmed ); + } + } + } + +TBool CEikCba::IsCommandDimmed(TInt aCommandId) const + { + if( ButtonById(aCommandId) ) + { + return ButtonById(aCommandId)->IsDimmed(); + } + return EFalse; + } + +void CEikCba::MakeCommandVisible(TInt aCommandId, TBool aVisible) + { + CCoeControl* control( ButtonById( aCommandId ) ); + if ( control ) + { + if ( SoftkeyStatusChangeAllowed( IndexById( aCommandId ), !aVisible ) ) + { + control->MakeVisible( aVisible ); + } + } + } + +TBool CEikCba::IsCommandVisible(TInt aCommandId) const + { + if( ButtonById(aCommandId) ) + { + return ButtonById(aCommandId)->IsVisible(); + } + return EFalse; + } + +void CEikCba::AnimateCommand(TInt /*aCommandId*/) + { + } + + +// --------------------------------------------------------------------------- +// Sets the dimming status of a button with the specified position. +// --------------------------------------------------------------------------- +// +void CEikCba::DimCommandByPosition( TInt aPosition, TBool aDimmed ) + { + if ( aPosition >= iControlArray->Count() ) + { + return; + } + + if ( SoftkeyStatusChangeAllowed( aPosition, aDimmed ) ) + { + TEikGroupControl& groupCtrl = ( *iControlArray )[ aPosition ]; + groupCtrl.iControl->SetDimmed( aDimmed ); + } + } + + +// --------------------------------------------------------------------------- +// Returns the dimming status of a button with the specified position. +// --------------------------------------------------------------------------- +// +TBool CEikCba::IsCommandDimmedByPosition( TInt aPosition ) const + { + if ( aPosition >= iControlArray->Count() ) + { + return EFalse; + } + + TEikGroupControl& groupCtrl = (*iControlArray)[aPosition]; + return groupCtrl.iControl->IsDimmed(); + } + + +// --------------------------------------------------------------------------- +// Sets the visibility of a button with the specified position. +// --------------------------------------------------------------------------- +// +void CEikCba::MakeCommandVisibleByPosition( TInt aPosition, TBool aVisible ) + { + if ( aPosition >= iControlArray->Count() ) + { + return; + } + + if ( SoftkeyStatusChangeAllowed( aPosition, !aVisible ) ) + { + TEikGroupControl& groupCtrl = ( *iControlArray )[ aPosition ]; + + if ( !iFlags.IsSet( ECbaInsideDialog ) ) + { + groupCtrl.iControl->MakeVisible( aVisible ); + } + else + { + // Just dim the button, don't hide it. + groupCtrl.iControl->SetDimmed( !aVisible ); + groupCtrl.iControl->DrawDeferred(); + } + } + } + + +TBool CEikCba::IsCommandVisibleByPosition(TInt aPosition) const + { + if (aPosition >= iControlArray->Count()) + { + return EFalse; + } + TEikGroupControl& groupCtrl = (*iControlArray)[aPosition]; + + if ( !iFlags.IsSet( ECbaInsideDialog ) ) + { + return STATIC_CAST(CEikCbaButton*, groupCtrl.iControl)->IsVisible(); + } + + return !groupCtrl.iControl->IsDimmed(); + } + +void CEikCba::AnimateCommandByPosition(TInt /*aPosition*/) + { + } + +/*CCoeControl* CEikCba::GroupControlByPosition(TInt aPosition) const + { + if (aPosition >= iControlArray->Count()) + { + return NULL; + } + TEikGroupControl& groupCtrl = (*iControlArray)[aPosition]; + return groupCtrl.iControl; + }*/ + + +// --------------------------------------------------------------------------- +// CEikCba::ButtonRectByPosition +// Gets a CBA button rectangle. +// --------------------------------------------------------------------------- +// +TRect CEikCba::ButtonRectByPosition( TInt aPosition, TBool aRelativeToScreen ) + { + TRect rect( 0, 0, 0, 0 ); + + if ( aPosition >= iControlArray->Count() || aPosition < 0 ) + { + return rect; + } + + if ( !AknLayoutUtils::PenEnabled() ) + { + // Button rectangle is the actual control rect. + rect = ( *iControlArray )[aPosition].iControl->Rect(); + } + else + { + // In touch layouts the button areas are read from the + // layout data because they are larger than the actual + // control size. + // Also, currently touch layouts do not support MSK, + // so it's ignored. + TRect containerRect( Rect() ); + TAknLayoutRect layoutRect; + TRect button1Rect( 0, 0, 0, 0 ); + TRect button2Rect( 0, 0, 0, 0 ); + TRect buttonMSKRect( 0, 0, 0, 0 ); + + if ( iFlags.IsSet( ECbaEmbedded ) ) + { + TRect rect ( Rect() ); + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::popup_sk_window_g1( 0 ) ); + + // Button widths are calculated based on cba area width + // margin width is taken from layout + TInt margin = layoutRect.Rect().iTl.iX - rect.iTl.iX; + TInt buttonWidth = ( rect.Width() - margin * 2 ) / 2; + TSize buttonSize ( buttonWidth, layoutRect.Rect().Height() ); + + button1Rect = TRect( + TPoint( rect.iTl.iX + margin, layoutRect.Rect().iTl.iY ), + buttonSize ); + button2Rect = TRect( + TPoint( button1Rect.iBr.iX, layoutRect.Rect().iTl.iY ), + TPoint( rect.iBr.iX - margin, + layoutRect.Rect().iBr.iY ) ); + } + else if ( AknLayoutFlags() & EAknLayoutCbaInRightPane ) + { + // Landcsape nHD layout, button parent rectangle + // is the whole screen so aRelativeToScreen parameter + // is not taken into account. + TAknWindowComponentLayout rightAreaLayout( + AknLayoutScalable_Avkon::area_side_right_pane( 0 ) ); + + layoutRect.LayoutRect( + containerRect, + DoCompose( + rightAreaLayout, + AknLayoutScalable_Avkon::sctrl_sk_bottom_pane() ).LayoutLine() ); + TRect bottomSKRect( layoutRect.Rect() ); + + layoutRect.LayoutRect( + containerRect, + DoCompose( + rightAreaLayout, + AknLayoutScalable_Avkon::sctrl_sk_top_pane() ).LayoutLine() ); + TRect topSKRect( layoutRect.Rect() ); + + layoutRect.LayoutRect( + bottomSKRect, + AknLayoutScalable_Avkon::aid_touch_sctrl_bottom().LayoutLine() ); + button1Rect = layoutRect.Rect(); + + layoutRect.LayoutRect( + topSKRect, + AknLayoutScalable_Avkon::aid_touch_sctrl_top().LayoutLine() ); + button2Rect = layoutRect.Rect(); + } + else if ( AknLayoutFlags() & EAknLayoutCbaInControlPane ) + { + TBool mskDisabled( !MskAllowed() ); + + TBool flatLscLayout( + Layout_Meta_Data::IsLandscapeOrientation() && + AknStatuspaneUtils::FlatLayoutActive() ); + + if ( mskDisabled && !flatLscLayout ) + { + if ( aRelativeToScreen ) + { + AknLayoutUtils::LayoutMetricsRect( + AknLayoutUtils::EControlPane, containerRect ); + } + + if ( AknLayoutUtils::LayoutMirrored() ) + { + layoutRect.LayoutRect( + containerRect, + AknLayoutScalable_Avkon::aid_touch_ctrl_right().LayoutLine() ); + button1Rect = layoutRect.Rect(); + + layoutRect.LayoutRect( + containerRect, + AknLayoutScalable_Avkon::aid_touch_ctrl_left().LayoutLine() ); + button2Rect = layoutRect.Rect(); + } + else + { + layoutRect.LayoutRect( + containerRect, + AknLayoutScalable_Avkon::aid_touch_ctrl_left().LayoutLine() ); + button1Rect = layoutRect.Rect(); + + layoutRect.LayoutRect( + containerRect, + AknLayoutScalable_Avkon::aid_touch_ctrl_right().LayoutLine() ); + button2Rect = layoutRect.Rect(); + } + } + else + { + layoutRect.LayoutRect( + containerRect, + AknLayoutScalable_Avkon::control_pane_g6( 0 ).LayoutLine() ); + button1Rect = layoutRect.Rect(); + + layoutRect.LayoutRect( + containerRect, + AknLayoutScalable_Avkon::control_pane_g8( 0 ).LayoutLine() ); + button2Rect = layoutRect.Rect(); + + if ( !mskDisabled ) + { + layoutRect.LayoutRect( + containerRect, + AknLayoutScalable_Avkon::control_pane_g7( 0 ).LayoutLine() ); + buttonMSKRect = layoutRect.Rect(); + } + else + { + buttonMSKRect.SetRect( 0, 0, 0, 0 ); + } + } + } + + switch ( aPosition ) + { + case KControlArrayCBAButton1Posn: + { + rect = button1Rect; + break; + } + + case KControlArrayCBAButton2Posn: + { + rect = button2Rect; + break; + } + + case KControlArrayCBAButtonMSKPosn: + { + rect = buttonMSKRect; + break; + } + + default: + { + break; + } + } + } + + return rect; + } + + +CCoeControl* CEikCba::AsControl() + { + return this; + } + +const CCoeControl* CEikCba::AsControl() const + { + return this; + } + + +void CEikCba::SetBoundingRect( const TRect& /*aBoundingRect*/ ) + { + if ( iFlags.IsSet( ECbaEmbedded ) ) + { + return; + } + + // If background skin id has not been set from outside CBA, + // update it in case status pane layout has changed + if ( !iExtension->iCbaBgIIDSetExt ) + { + iBgIID = AknStatuspaneUtils::IdleLayoutActive() ? + KAknsIIDQsnBgAreaControlIdle : + KAknsIIDQsnBgAreaControl; + } + + // If CBA is inserted into a query dialog then it is positioned by the + // query control. + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + return; + } + + TRect oldRect( Rect() ); + + TRect screen; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen ); + + // Enable the MSK icon if status pane layout is changed from + // MSK disabled to MSK enabled one. + TBool mskDisabled( !MskAllowed() ); + + const TInt aknLayoutFlags = AknLayoutFlags(); + if ( aknLayoutFlags & EAknLayoutCbaInControlPane ) + { + if ( mskDisabled ) + { + SetMSKVisibility( EFalse ); + } + else + { + SetMSKVisibility( ETrue ); + TRAP_IGNORE( SetMSKIconL() ); + } + + // We must check for landscape mode bottom sks + TInt bottomPaneVariety = 1; + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + bottomPaneVariety = 6; + } + + TAknWindowLineLayout controlPane( DoCompose( + AknLayoutScalable_Avkon::application_window( 0 ), + DoCompose( AknLayoutScalable_Avkon::area_bottom_pane( bottomPaneVariety ), + AknLayoutScalable_Avkon::control_pane() ) ).LayoutLine() ); + + TAknLayoutRect cbarect; + cbarect.LayoutRect( screen, controlPane ); + + SetRect( cbarect.Rect() ); + + // Set correct window region incase we have been in stacon mode. + RRegion region; + region.AddRect( Rect() ); + + CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current(); + + // If status indicators and clock are shown in control pane area, + // then remove those areas from cba window region. + // + // NOTE: MSK is not supported in landscape. + // + if ( statusPane && + statusPane->IsVisible() && + AknStatuspaneUtils::ExtendedFlatLayoutActive() && + ( iBgIID == KAknsIIDQsnBgAreaControl || + iBgIID == KAknsIIDQsnBgAreaControlIdle || + iBgIID == KAknsIIDQsnBgAreaControlMp || + ( iBgIID == KAknsIIDWallpaper && + AknStatuspaneUtils::IdleLayoutActive() ) ) ) + { + TRect digitalClockRect( 0,0,0,0 ); + TRect indicatorRect( 0,0,0,0 ); + + if ( iBgIID == KAknsIIDQsnBgAreaControlMp ) + { + if ( !iIsClockIndicBgIIDSet ) + { + statusPane->SetCbaAreaBackgroundID( + iBgIID, + CEikStatusPaneBase::EDrawDeferred ); + iIsClockIndicBgIIDSet = ETrue; + } + } + else + { + if ( statusPane->CbaAreaBackgroundID() != iBgIID ) + { + statusPane->SetCbaAreaBackgroundID( + iBgIID, + CEikStatusPaneBase::EDrawDeferred ); + } + } + + TRAPD( err1, + indicatorRect = statusPane->PaneRectL( TUid::Uid( + EEikStatusPaneUidIndic ) ) ); + + TRAPD( err2, + digitalClockRect = statusPane->PaneRectL( TUid::Uid( + EEikStatusPaneUidDigitalClock ) ) ); + + if ( !err1 && !err2 ) + { + TPoint cbaPositionRelativeToScreen( PositionRelativeToScreen() ); + TRect cbaRectRelativeToScreen( cbaPositionRelativeToScreen, Size() ); + + if ( cbaRectRelativeToScreen.Intersects( indicatorRect ) ) + { + indicatorRect.Move( + -cbaPositionRelativeToScreen.iX, + -cbaPositionRelativeToScreen.iY ); + + region.SubRect( indicatorRect ); + } + + if ( cbaRectRelativeToScreen.Intersects( digitalClockRect ) ) + { + digitalClockRect.Move( + -cbaPositionRelativeToScreen.iX, + -cbaPositionRelativeToScreen.iY ); + + region.SubRect( digitalClockRect ); + } + } + } + + if ( !region.CheckError() ) + { + Window().SetShape( region ); + } + region.Close(); + } + else if ( aknLayoutFlags & EAknLayoutCbaInRightPane ) + { + // Softkeys in right pane. + // + // We set the rect to whole screen and then set window to + // clip other parts than softkey buttons. + + TRect rect( screen ); + SetRect( rect ); + + // Read right (top in landscape) softkey layout. + TAknWindowLineLayout rightSoftkeyLayout( + DoCompose( AknLayoutScalable_Avkon::area_side_right_pane( 0 ), + AknLayoutScalable_Avkon::sctrl_sk_top_pane() ).LayoutLine() ); + + TAknLayoutRect rightSoftkeyLayoutRect; + rightSoftkeyLayoutRect.LayoutRect( rect, rightSoftkeyLayout ); + TRect rightSoftKeyButtonRect( rightSoftkeyLayoutRect.Rect() ); + + // Read left (bottom in landscape) softkey layout. + TAknWindowLineLayout leftSoftkeyLayout( + DoCompose( AknLayoutScalable_Avkon::area_side_right_pane( 0 ), + AknLayoutScalable_Avkon::sctrl_sk_bottom_pane() ).LayoutLine() ); + + TAknLayoutRect leftSoftkeyLayoutRect; + leftSoftkeyLayoutRect.LayoutRect( rect, leftSoftkeyLayout ); + TRect leftSoftKeyButtonRect( leftSoftkeyLayoutRect.Rect() ); + + // Set the window shape. + RRegion region; + region.AddRect( leftSoftKeyButtonRect ); + region.AddRect( rightSoftKeyButtonRect ); + if ( !region.CheckError() ) + { + Window().SetShape( region ); + } + region.Close(); + } + else + { + // Stacon pane (combined status and control pane). + // + // Control pane is splitted. We set the rect to whole screen and then set window to + // clip other parts than softkey buttons. + + TRect rect( screen ); + SetRect( rect ); + + TInt variety = 0; + if ( AknLayoutFlags() & EAknLayoutCbaInStaconPaneLeft ) + { + variety = 1; + } + + TAknWindowComponentLayout layout0; + TAknWindowComponentLayout layout1; + TAknWindowComponentLayout layout2; + + // Read right (top in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_top_pane( 2 ); + layout1 = AknLayoutScalable_Avkon::stacon_top_pane(); + + // If clock is shown in stacon, cba area is smaller. + TInt topCbaVariety = variety; + if ( AknStatuspaneUtils::ExtendedStaconPaneActive() + || AknStatuspaneUtils::ExtendedLayoutActive() ) + { + topCbaVariety += 4; + } + + layout2 = AknLayoutScalable_Avkon::control_top_pane_stacon( topCbaVariety ); + + TAknWindowLineLayout rightSoftkeyLayout( + DoCompose( layout0,DoCompose( layout1, layout2 ) ).LayoutLine() ); + + TAknLayoutRect rightSoftkeyLayoutRect; + rightSoftkeyLayoutRect.LayoutRect( rect, rightSoftkeyLayout ); + TRect rightSoftKeyButtonRect( rightSoftkeyLayoutRect.Rect() ); + + // Read left (bottom in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_bottom_pane( 2 ); + layout1 = AknLayoutScalable_Avkon::stacon_bottom_pane(); + + // If clock is shown in stacon, cba area is smaller. + TInt bottomCbaVariety = variety; + if ( AknStatuspaneUtils::ExtendedStaconPaneActive() + || AknStatuspaneUtils::ExtendedLayoutActive() ) + { + bottomCbaVariety += 2; + } + + layout2 = + AknLayoutScalable_Avkon::control_bottom_pane_stacon( + bottomCbaVariety ); + + TAknWindowLineLayout leftSoftkeyLayout( + DoCompose( layout0, DoCompose( layout1, layout2 ) ).LayoutLine() ); + + TAknLayoutRect leftSoftkeyLayoutRect; + leftSoftkeyLayoutRect.LayoutRect( rect, leftSoftkeyLayout ); + TRect leftSoftKeyButtonRect( leftSoftkeyLayoutRect.Rect() ); + + // Set the window shape. + RRegion region; + region.AddRect( leftSoftKeyButtonRect ); + region.AddRect( rightSoftKeyButtonRect ); + if ( !region.CheckError() ) + { + Window().SetShape( region ); + } + region.Close(); + } + + // The softkey frame needs to be updated if the size or + // position of CBA was changed. + if ( iExtension && Rect() != oldRect ) + { + TRAP_IGNORE( iExtension->UpdateSoftkeyFrameL( EFalse ) ); + + // Finally ensure that MSK drawing is disabled if the status pane + // layout is changed from MSK enabled to MSK disabled one. + if ( mskDisabled ) + { + SetMSKVisibility( EFalse ); + } + + DrawDeferred(); + } + } + + +// --------------------------------------------------------------------------- +// Subtracts the area occupied by the button group from the specified +// bounding rectangle. +// --------------------------------------------------------------------------- +// +void CEikCba::ReduceRect( TRect& aBoundingRect ) const + { + // CBA inside Popup/Query Input does not reduce bounding rect + if ( iFlags.IsSet( ECbaEmbedded ) || iFlags.IsSet( ECbaInsideDialog ) ) + { + return; + } + + if ( !IsVisible() ) + { + return; + } + + const TInt aknLayoutFlags = AknLayoutFlags(); + + if ( aknLayoutFlags & EAknLayoutCbaInControlPane ) + { + // Cba in control pane. + if ( aBoundingRect.Intersects( TRect( iPosition, iSize ) ) ) + { + aBoundingRect.iBr.iY = Position().iY; + } + } + else if ( aknLayoutFlags & EAknLayoutCbaInRightPane ) + { + // Cba in right pane. + + TRect rect; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, rect ); + + const TAknWindowLineLayout rightPaneLayout( + AknLayoutScalable_Avkon::area_side_right_pane( 0 ).LayoutLine() ); + + TAknLayoutRect rightPaneRect; + rightPaneRect.LayoutRect( rect, rightPaneLayout ); + + const TRect rightPane( rightPaneRect.Rect() ); + + if ( aBoundingRect.Intersects( rightPane ) ) + { + // Always on the right side, won't be mirrored. + aBoundingRect.iBr.iX = rightPane.iTl.iX; + } + } + else + { + // CBA in stacon pane. + if ( iControlArray->Count() != 0 ) + { + CCoeControl *leftSoftkey = + (*iControlArray)[KControlArrayCBAButton1Posn].iControl; + CCoeControl *rightSoftkey = + (*iControlArray)[KControlArrayCBAButton2Posn].iControl; + if ( leftSoftkey && rightSoftkey ) + { + RRegion boundingRegion; + TRect originalboundingRect( aBoundingRect ); + boundingRegion.AddRect( originalboundingRect ); + + TRect rect; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, + rect ); + + TInt variety = 0; + if ( aknLayoutFlags & EAknLayoutCbaInStaconPaneLeft ) + { + variety = 1; + } + + TAknWindowComponentLayout layout0; + TAknWindowComponentLayout layout1; + TAknWindowComponentLayout layout2; + + // Read right (top in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_top_pane( 2 ); + layout1 = AknLayoutScalable_Avkon::stacon_top_pane(); + + // If clock is shown in stacon, CBA area is smaller. + TInt topCbaVariety = variety; + TInt bottomCbaVariety = variety; + if ( AknStatuspaneUtils::ExtendedStaconPaneActive() ) + { + topCbaVariety += 4; + bottomCbaVariety += 2; + } + + layout2 = AknLayoutScalable_Avkon::control_top_pane_stacon( topCbaVariety ); + + TAknWindowLineLayout rightSoftkeyLayout( + DoCompose( layout0, + DoCompose( layout1, layout2 ) ).LayoutLine() ); + + TAknLayoutRect rightSoftkeyLayoutRect; + rightSoftkeyLayoutRect.LayoutRect( rect, rightSoftkeyLayout ); + TRect rightSoftKeyRect( rightSoftkeyLayoutRect.Rect() ); + + // Read left (bottom in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_bottom_pane( 2 ); + layout1 = AknLayoutScalable_Avkon::stacon_bottom_pane(); + layout2 = AknLayoutScalable_Avkon::control_bottom_pane_stacon( bottomCbaVariety ); + + TAknWindowLineLayout leftSoftkeyLayout( + DoCompose( layout0, + DoCompose( layout1, layout2 ) ).LayoutLine() ); + + TAknLayoutRect leftSoftkeyLayoutRect; + leftSoftkeyLayoutRect.LayoutRect( rect, leftSoftkeyLayout ); + TRect leftSoftKeyRect( leftSoftkeyLayoutRect.Rect() ); + + boundingRegion.SubRect( leftSoftKeyRect ); + boundingRegion.SubRect( rightSoftKeyRect ); + + TInt count = boundingRegion.Count(); + + TRect largestBoundingRect( 0, 0, 0, 0 ); + TRect boundingRect( 0, 0, 0, 0 ); + for ( TInt j = 0; j < count; j++ ) + { + boundingRect = boundingRegion[j]; + if ( boundingRect.Height() >= largestBoundingRect.Height() ) + { + largestBoundingRect = boundingRect; + } + } + + // Return largest bounding rect. + aBoundingRect = largestBoundingRect; + boundingRegion.Close(); + } + } + } + } + + +CCoeControl* CEikCba::GroupControlById(TInt aCommandId) + { + return ButtonById(aCommandId); + } + + +CCoeControl* CEikCba::GroupControlById(TInt aCommandId) const + { + return ButtonById(aCommandId); + } + +TInt CEikCba::CommandId(TInt aCommandPos) const + { + return (*iControlArray)[aCommandPos].iId; + } + +TInt CEikCba::ButtonCount() const + { + return (iControlArray->Count()-1); // -1 for scroll bar; + } + +CEikCommandButton* CEikCba::GroupControlAsButton(TInt /*aCommandId*/) const + { + // It is not possible to convert a CBA button to a CEikCommandButton. + // Please use an interface that does not use a CEikCommandButton conversion, + // e.g. CEikButtonGroupContainer::SetCommandL(). +#if defined(_DEBUG) + Panic(EEikPanicCBACannotConvertToCEikCommandButton); +#endif + return NULL; + } + +TUint CEikCba::ButtonGroupFlags() const + { + return iCbaFlags ; + } + +EXPORT_C void CEikCba::SetButtonGroupFlags(TInt aFlags) + { + iCbaFlags = aFlags; + if (( iCbaFlags & EEikCbaFlagTransparent || iCbaFlags & EEikCbaFlagSemiTransparent ) && + CAknEnv::Static()->TransparencyEnabled() ) + { + Window().SetRequiredDisplayMode( EColor16MA ); + TInt err = Window().SetTransparencyAlphaChannel(); + if( err == KErrNone ) + { + Window().SetBackgroundColor( ~0 ); + if ( iExtension && iExtension->iEnablePostingTransparency ) + { + iExtension->iEnablePostingTransparency = EFalse; + delete iExtension->iLskPostingOverlayBitmap; + iExtension->iLskPostingOverlayBitmap = NULL; + delete iExtension->iRskPostingOverlayBitmap; + iExtension->iRskPostingOverlayBitmap = NULL; + BroadcastPostingTransparency( EFalse ); + } + } + else + { + iCbaFlags &= ~EEikCbaFlagTransparent; + } + } + else + { + iCbaFlags &= ~EEikCbaFlagTransparent; + } + if ( iCbaFlags & EEikCbaFlagSemiTransparent ) + { + if ( iExtension ) + { + iExtension->iSemiBgID = KAknsIIDQsnHomeBgWidget; + iExtension->iSemiBgCenterID = KAknsIIDQsnHomeBgWidgetCenter; + } + } + else + { + if ( iExtension ) + { + iExtension->iSemiBgID = KAknsIIDNone; + iExtension->iSemiBgCenterID = KAknsIIDNone; + } + } + + UpdateFonts(); + } + +// ----------------------------------------------------------------------------- +// CEikCba::SetSkinBackgroundId +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CEikCba::SetSkinBackgroundId( const TAknsItemID& aIID ) + { + // Skin background is not drawn by embedded CBA. + if ( iFlags.IsSet( ECbaEmbedded ) ) + { + return; + } + + if ( iBgIID != KAknsIIDNone ) + { + if ( iBgIID != aIID ) + { + TRAP_IGNORE( iExtension->UpdateSoftkeyFrameL( EFalse ) ); + } + + iBgIID = aIID; + iExtension->iCbaBgIIDSetExt = ETrue; + } + + if ( iMLBgContext ) + { + DoSetLayers( aIID ); + + if ( aIID.iMajor == KAknsIIDQsnBgAreaControlPopup.iMajor && + aIID.iMinor == KAknsIIDQsnBgAreaControlPopup.iMinor ) + { + iPopupVisible = ETrue; + } + else + { + iPopupVisible = EFalse; + } + + } + + CheckSkinAndUpdateContext(); + + if ( AknStatuspaneUtils::ExtendedFlatLayoutActive() ) + { + // Clock and indicator pane area must be removed from + // this window in extended flat layout. + SetBoundingRect( TRect(0,0,0,0) ); // dummy parameter + } + + CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current(); + + if ( statusPane && + ( iIsClockIndicBgIIDSet && + iBgIID == KAknsIIDQsnBgAreaControlMp && + statusPane->CbaAreaBackgroundID() != iBgIID ) || + ( iBgIID == KAknsIIDQsnBgAreaControlMp && + AknLayoutFlags() & EAknLayoutCbaInRightPane ) ) + { + statusPane->SetCbaAreaBackgroundID( + iBgIID, + CEikStatusPaneBase::EDrawDeferred ); + } + } + +TKeyResponse CEikCba::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) + { + if (aType != EEventKey) + { + return EKeyWasNotConsumed; + } + + // Return immediately if the control is invisible. + if (!IsVisible() && !(iCbaFlags&EAknCBAFlagRespondWhenInvisible)) + { + return EKeyWasNotConsumed; + } + + TBool shiftControlPressed = + (aKeyEvent.iModifiers & EModifierShift) || + (aKeyEvent.iModifiers & EModifierLeftShift) || + (aKeyEvent.iModifiers & EModifierRightShift) || + (aKeyEvent.iModifiers & EModifierCtrl) || + (aKeyEvent.iModifiers & EModifierRightCtrl); + + TKeyResponse response(EKeyWasNotConsumed); + + // AknLaf - changed to use keys defined in AknKeys.h. + // Left soft key will be returned also when MSK is enabled but not defined. + if (aKeyEvent.iCode == EKeyCBA1) + { + if (KControlArrayCBAButton1Posn < iControlArray->Count()) + { + // Return immediately if the button is invisible + if ( (*iControlArray)[KControlArrayCBAButton1Posn].iControl && + !(*iControlArray)[KControlArrayCBAButton1Posn].iControl->IsVisible() && + !(iCbaFlags & EAknCBAFlagRespondWhenInvisible) ) + { + return EKeyWasConsumed; + } + TInt shortCommand = (*iControlArray)[KControlArrayCBAButton1Posn].iId; + TInt longCommand = (*iControlArray)[KControlArrayCBAButton1Posn].iLongId; + + // This will pass key event to application - no softkey command is processed. + if (shortCommand == EAknSoftkeyForwardKeyEvent) + { + return EKeyWasNotConsumed; + } + + if (aKeyEvent.iRepeats == 0 && shortCommand) + { + iCommandObserver->ProcessCommandL((TInt)shortCommand); + } + else if (longCommand) + { + iCommandObserver->ProcessCommandL((TInt)longCommand); + } + response = EKeyWasConsumed; + } + } + else if (aKeyEvent.iCode == EKeyCBA2) + { + if (KControlArrayCBAButton2Posn < iControlArray->Count()) + { + // Return immediately if the button is invisible. + if ( (*iControlArray)[KControlArrayCBAButton2Posn].iControl && + !(*iControlArray)[KControlArrayCBAButton2Posn].iControl->IsVisible() && + !(iCbaFlags&EAknCBAFlagRespondWhenInvisible) ) + { + return EKeyWasConsumed; + } + TInt shortCommand = (*iControlArray)[KControlArrayCBAButton2Posn].iId; + TInt longCommand = (*iControlArray)[KControlArrayCBAButton2Posn].iLongId; + + if (!shortCommand && (aKeyEvent.iModifiers & EModifierKeyboardExtend) + && (aKeyEvent.iScanCode == EStdKeyDevice1)) + { + shortCommand = EEikBidCancel; + } + + // This will pass key event to application - no softkey command is processed. + if (shortCommand == EAknSoftkeyForwardKeyEvent) + { + return EKeyWasNotConsumed; + } + + if (aKeyEvent.iRepeats == 0 && shortCommand) + { + iCommandObserver->ProcessCommandL((TInt)shortCommand); + } + else if (longCommand) + { + iCommandObserver->ProcessCommandL((TInt)longCommand); + } + response=EKeyWasConsumed; + } + } + // Only take care of MSK if there has been something set to MSK (so that this doesn't break old + // cbas with only left and right softkeys set). + + // Do not handle key events with middle softkey if single click is enabled + else if ( iFlags.IsClear( ECbaSingleClickEnabled ) + && AknLayoutUtils::MSKEnabled() + && iMSKset + && aKeyEvent.iCode == EKeyOK + && !Window().IsFaded() ) + { + if (KControlArrayCBAButtonMSKPosn < iControlArray->Count()) + { + // Return immediately if the button is invisible. + if ( (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl && + !(*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl->IsVisible() && + !(iCbaFlags&EAknCBAFlagRespondWhenInvisible) ) + { + return EKeyWasConsumed; + } + + TInt shortCommand = (*iControlArray)[KControlArrayCBAButtonMSKPosn].iId; + TInt longCommand = (*iControlArray)[KControlArrayCBAButtonMSKPosn].iLongId; + + // This will pass key event to application - no softkey command is processed. + if (shortCommand == EAknSoftkeyForwardKeyEvent) + { + return EKeyWasNotConsumed; + } + + if (aKeyEvent.iRepeats == 0 && shortCommand) + { + if (iMSKCommandObserver) + { + iMSKCommandObserver->ProcessCommandL(shiftControlPressed ? + EAknSoftkeyShiftMSK : (TInt)shortCommand); + } + // MSK observer handles shift, no normal MSK after that. + if (!(iMSKCommandObserver && shiftControlPressed)) + { + iCommandObserver->ProcessCommandL((TInt)shortCommand); + } + } + else if (longCommand) + { + if (iMSKCommandObserver) + { + iMSKCommandObserver->ProcessCommandL(shiftControlPressed ? + EAknSoftkeyShiftMSK : (TInt)longCommand); + } + // MSK observer handles shift, no normal MSK after that. + if (!(iMSKCommandObserver && shiftControlPressed)) + { + iCommandObserver->ProcessCommandL((TInt)longCommand); + } + } + response=EKeyWasConsumed; + } + } + // If MSK is enabled but not defined, we return left softkey. + // Do not handle key events with middle softkey if single click is enabled + else if ( iFlags.IsClear( ECbaSingleClickEnabled ) + && AknLayoutUtils::MSKEnabled() + && !iMSKset + && aKeyEvent.iCode == EKeyOK + && !Window().IsFaded() ) + { + if (KControlArrayCBAButton1Posn < iControlArray->Count()) + { + // Return immediately if the button is invisible. + if ( (*iControlArray)[KControlArrayCBAButton1Posn].iControl && + !(*iControlArray)[KControlArrayCBAButton1Posn].iControl->IsVisible() && + !(iCbaFlags&EAknCBAFlagRespondWhenInvisible) ) + { + return EKeyWasConsumed; + } + + TInt shortCommand = (*iControlArray)[KControlArrayCBAButton1Posn].iId; + TInt longCommand = (*iControlArray)[KControlArrayCBAButton1Posn].iLongId; + + // This will pass key event to application - no softkey command is processed. + if (shortCommand == EAknSoftkeyForwardKeyEvent) + { + return EKeyWasNotConsumed; + } + + if (aKeyEvent.iRepeats == 0 && shortCommand) + { + // Send shift + MSK to (listbox) observer even if MSK is not defined. + if (iMSKCommandObserver && shiftControlPressed) + { + iMSKCommandObserver->ProcessCommandL(EAknSoftkeyShiftMSK); + } + else + { + iCommandObserver->ProcessCommandL((TInt)shortCommand); + } + } + else if (longCommand) + { + // Send shift + MSK to (listbox) observer even if MSK is not defined. + if (iMSKCommandObserver && shiftControlPressed) + { + iMSKCommandObserver->ProcessCommandL(EAknSoftkeyShiftMSK); + } + else + { + iCommandObserver->ProcessCommandL((TInt)longCommand); + } + } + response = EKeyWasConsumed; + } + } + + return response; + } + +EXPORT_C void* CEikCba::ExtensionInterface( TUid /*aInterface*/ ) + { + return NULL; + } + + +// --------------------------------------------------------------------------- +// Handles pointer events by passing the event to component controls by using +// the base class functionality. In addition this function notifies the +// command observer if a cba button was tapped. +// --------------------------------------------------------------------------- +// +void CEikCba::HandlePointerEventL( const TPointerEvent& aPointerEvent ) + { + if ( !AknLayoutUtils::PenEnabled() ) + { + return; + } + else if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + CCoeControl::HandlePointerEventL( aPointerEvent ); + return; + } + + // If a child control is grabbing the pointer, we store the object pointer + // before calling base class implementation. This is because the up event + // releases the pointer grab. + CCoeControl* grabber = GrabbingComponent(); + + // Default base class functionality passes event to child controls. + CCoeControl::HandlePointerEventL( aPointerEvent ); + + // If pointer up event occurred in child control which was grabbing + // the pointer, it means that the CBA button was clicked. + + CEikCbaButton* button1 = + static_cast( + (*iControlArray)[KControlArrayCBAButton1Posn].iControl ); + CEikCbaButton* button2 = + static_cast( + (*iControlArray)[KControlArrayCBAButton2Posn].iControl ); + CEikCbaButton* buttonMSK = NULL; + + if ( iMSKset && AknLayoutUtils::MSKEnabled() ) + { + buttonMSK = + static_cast( + (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl ); + } + + TRect button1Rect; + TRect button2Rect; + TRect buttonMSKRect; + + if ( AknLayoutFlags() & EAknLayoutCbaInRightPane ) + { + button1Rect = ButtonRectByPosition( KControlArrayCBAButton1Posn, ETrue ); + button2Rect = ButtonRectByPosition( KControlArrayCBAButton2Posn, ETrue ); + } + else if ( AknLayoutFlags() & EAknLayoutCbaInControlPane ) + { + button1Rect = ButtonRectByPosition( KControlArrayCBAButton1Posn, EFalse ); + button2Rect = ButtonRectByPosition( KControlArrayCBAButton2Posn, EFalse ); + buttonMSKRect = ButtonRectByPosition( KControlArrayCBAButtonMSKPosn, EFalse ); + } + else + { + button1Rect = button1->Rect(); + button2Rect = button2->Rect(); + buttonMSKRect = TRect( 0,0,0,0 ); + } + + // This flag is used to determine whether a pointer hit has + // happened in the grabbing control. It is needed to prevent + // the event from passing from one softkey to another. + TBool noHits = EFalse; + + TBool buttonMSKDown = EFalse; + TBool button1Down = button1->PressedDown(); + TBool button2Down = button2->PressedDown(); + if ( buttonMSK ) + { + buttonMSKDown = buttonMSK->PressedDown(); + } + + TBool button1Empty = EFalse; + if ( !button1->IsImageOn() && button1->IsEmptyText() ) + { + button1Empty = ETrue; + } + + TBool button2Empty = EFalse; + if ( !button2->IsImageOn() && button2->IsEmptyText() ) + { + button2Empty = ETrue; + } + + TBool buttonMSKEmpty = EFalse; + if ( buttonMSK && !buttonMSK->IsImageOn() && buttonMSK->IsEmptyText() ) + { + buttonMSKEmpty = ETrue; + } + + // If hits the left softkey. + if ( button1Rect.Contains( aPointerEvent.iPosition ) && !button1Empty ) + { + if ( button1->IsVisible() ) + { + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + button1->SetPressedDown( ETrue ); + + // Store the pointer of the button control to be + // used as the grabbing control, this is required + // in case the pointer events happens in the extended + // touch area where the button control doesn't receive + // the grab otherwise. + iExtension->iPointerGrabbingButton = button1; + } + else if ( aPointerEvent.iType == TPointerEvent::EButton1Up && + button1->PressedDown() ) + { + // Accept the up event only if the down event has happened + // in the same button. + button1->SetPressedDown( EFalse ); + grabber = iExtension->iPointerGrabbingButton; + + // Clear the grabber pointer at up event. + iExtension->iPointerGrabbingButton = NULL; + } + else if ( aPointerEvent.iType == TPointerEvent::EDrag ) + { + if ( iExtension->iPointerGrabbingButton == button1 ) + { + // Accept the drag event only if the down event has happened + // in the same button. + button1->SetPressedDown( ETrue ); + button2->SetPressedDown( EFalse); + if ( buttonMSK ) + { + buttonMSK->SetPressedDown( EFalse ); + } + } + else + { + // Don't transfer the event to this button. + noHits = ETrue; + } + } + else + { + // The event happened outside the button areas + // or up event happened inside a button which + // didn't get the down event. + noHits = ETrue; + } + } + else + { + // Button is inactive + noHits = ETrue; + } + } + else if ( button2Rect.Contains( aPointerEvent.iPosition ) && !button2Empty ) + { + if ( button2->IsVisible() ) + { + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + button2->SetPressedDown( ETrue ); + + // Store the pointer of the button control to be + // used as the grabbing control, this is required + // in case the pointer events happens in the extended + // touch area where the button control doesn't receive + // the grab otherwise. + iExtension->iPointerGrabbingButton = button2; + } + else if ( aPointerEvent.iType == TPointerEvent::EButton1Up && + button2->PressedDown() ) + { + // Accept the up event only if the down event has happened + // in the same button. + button2->SetPressedDown( EFalse ); + grabber = iExtension->iPointerGrabbingButton; + + // Clear the grabber pointer at up event. + iExtension->iPointerGrabbingButton = NULL; + } + else if ( aPointerEvent.iType == TPointerEvent::EDrag ) + { + if ( iExtension->iPointerGrabbingButton == button2 ) + { + // Accept the drag event only if the down event has happened + // in the same button. + button2->SetPressedDown( ETrue ); + button1->SetPressedDown( EFalse); + if ( buttonMSK ) + { + buttonMSK->SetPressedDown( EFalse ); + } + } + else + { + // Don't transfer the event to this button. + noHits = ETrue; + } + } + else + { + // The event happened outside the button areas + // or up event happened inside a button which + // didn't get the down event. + noHits = ETrue; + } + } + else + { + // Button is inactive + noHits = ETrue; + } + } + else if ( buttonMSK && + !buttonMSKEmpty && + buttonMSKRect.Contains( aPointerEvent.iPosition ) ) + { + if ( buttonMSK->IsVisible() ) + { + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + buttonMSK->SetPressedDown( ETrue ); + + // Store the pointer of the button control to be + // used as the grabbing control, this is required + // in case the pointer events happens in the extended + // touch area where the button control doesn't receive + // the grab otherwise. + iExtension->iPointerGrabbingButton = buttonMSK; + } + else if ( aPointerEvent.iType == TPointerEvent::EButton1Up && + buttonMSK->PressedDown() ) + { + // Accept the up event only if the down event has happened + // in the same button. + buttonMSK->SetPressedDown( EFalse ); + grabber = iExtension->iPointerGrabbingButton; + + // Clear the grabber pointer at up event. + iExtension->iPointerGrabbingButton = NULL; + } + else if ( aPointerEvent.iType == TPointerEvent::EDrag ) + { + if ( iExtension->iPointerGrabbingButton == buttonMSK ) + { + // Accept the drag event only if the down event has happened + // in the same button. + buttonMSK->SetPressedDown( ETrue ); + button2->SetPressedDown( EFalse ); + button1->SetPressedDown( EFalse ); + } + else + { + // Don't transfer the event to this button. + noHits = ETrue; + } + } + else + { + // The event happened outside the button areas + // or up event happened inside a button which + // didn't get the down event. + noHits = ETrue; + } + } + else + { + // Button is inactive + noHits = ETrue; + } + } + else + { + if ( aPointerEvent.iType == TPointerEvent::EButton1Up ) + { + // Clear the grabber pointer at up event. + iExtension->iPointerGrabbingButton = NULL; + } + + noHits = ETrue; + } + + if ( noHits ) + { + button1->SetPressedDown( EFalse ); + button2->SetPressedDown( EFalse ); + if ( buttonMSK ) + { + buttonMSK->SetPressedDown( EFalse ); + } + } + else if ( aPointerEvent.iType != TPointerEvent::EDrag ) + { + // CBA button has been hit with a down or up event, play feedback + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback ) + { + TTouchFeedbackType fbType = TTouchFeedbackType( ETouchFeedbackAudio | + ETouchFeedbackVibra ); + if ( aPointerEvent.iType == TPointerEvent::EButton1Up ) + { + fbType = ETouchFeedbackVibra; + } + feedback->InstantFeedback( this, + ETouchFeedbackBasicButton, + fbType, + aPointerEvent ); + } + } + + if (button1Down != button1->PressedDown() || + button2Down != button2->PressedDown() || + (buttonMSK && (buttonMSKDown != buttonMSK->PressedDown()))) + { + + if ( iFlags.IsSet( ECbaEmbedded ) ) + { + UpdateLabels( EFalse ); + + // Redraw only changed buttons. It's assumed that there's no + // visible MSK if softkeys are embedded. + TRect invalidRect( button1Rect ); + + if ( button2Down != button2->PressedDown() ) + { + invalidRect = button2Rect; + } + + // TODO: whole control is redrawn as a workaround for NGA bug that + // causes incorrect drawing of softkey labels when the second + // button is pressed down after the first one has already been + // pressed. Actually we should just redraw the invalidRect + // calculated above. + DrawNow(); + } + else + { + SizeChanged(); + DrawNow(); + } + } + + if ( !grabber && !noHits ) + { + // Set the correct button to claim the pointer grab if the + // event happened in an extended touch area of the button + // (the button control didn't receive the event). + grabber = iExtension->iPointerGrabbingButton; + } + + if ( aPointerEvent.iType == TPointerEvent::EButton1Up && grabber && !noHits ) + { + // This check also includes the extended touch space for a button. + if ( ( button1Rect.Contains( aPointerEvent.iPosition ) && + button1Rect.Intersects( grabber->Rect() ) ) || + ( button2Rect.Contains( aPointerEvent.iPosition ) && + button2Rect.Intersects( grabber->Rect() ) ) || + ( buttonMSKRect.Contains( aPointerEvent.iPosition ) && + buttonMSKRect.Intersects( grabber->Rect() ) ) ) + { + TInt buttoncount = iControlArray->Count(); + for ( TInt i = 0; i < buttoncount; i++ ) + { + if ( (*iControlArray)[i].iControl == grabber ) + { + if ( !IsVisible() ) + return; + + // Send the button command to command observer. + TInt shortCommand = (*iControlArray)[i].iId; + if ( shortCommand && + i == KControlArrayCBAButtonMSKPosn && + iMSKCommandObserver ) + { + iMSKCommandObserver->ProcessCommandL( shortCommand ); + } + + if( shortCommand ) + { + iCommandObserver->ProcessCommandL( shortCommand ); + } + + break; + } + } + } + } + } + + +TSize CEikCba::MinimumSize() + { + TSize size = CEikControlGroup::MinimumSize(); + size.iWidth = iAvkonAppUi->ApplicationRect().Width(); + const TInt count = iControlArray->Count(); + for (TInt ii = 0; ii < count; ii++) + { + size.iHeight = Max(size.iHeight, (*iControlArray)[ii].iControl->MinimumSize().iHeight); + } + if (iLink) + { + size.iHeight = Max(size.iHeight, iLink->Size().iHeight); + } + // Add a standard margin from the laf. + return size; + } + +/** +* Gets the list of logical colors employed in the drawing of the control, +* paired with an explanation of how they are used. Appends the list to aColorUseList. +* +* @since ER5U +*/ +void CEikCba::GetColorUseListL(CArrayFix& aColorUseList) const + { + CEikControlGroup::GetColorUseListL(aColorUseList); + + TInt commonAttributes = TCoeColorUse::ESurrounds|TCoeColorUse::EActive|TCoeColorUse::ENormal| + TCoeColorUse::ENeutral; + + TCoeColorUse colorUse; + + colorUse.SetLogicalColor(EColorToolbarText); + colorUse.SetUse(TCoeColorUse::EFore|commonAttributes); + aColorUseList.AppendL(colorUse); + + colorUse.SetLogicalColor(EColorToolbarBackground); + colorUse.SetUse(TCoeColorUse::EBack|commonAttributes); + aColorUseList.AppendL(colorUse); + } + + +// --------------------------------------------------------------------------- +// Handles a change to the control's resources of type aType +// which are shared across the environment, e.g. colors or fonts. +// --------------------------------------------------------------------------- +// +void CEikCba::HandleResourceChange( TInt aType ) + { + CEikControlGroup::HandleResourceChange( aType ); + + switch ( aType ) + { + case KAknsMessageSkinChange: + { + if ( IsVisible() ) + { + DoSkinChange(); + if( iExtension->iIfMskIconSet ) + { + TRAP_IGNORE( UpdateIconL() ); + } + } + else + { + iFlags.Set( ECbaChangeRecordedSkin ); + } + break; + } + + case KEikColorResourceChange: + { + if ( IsVisible() ) + { + DoColorChange(); + } + else + { + iFlags.Set( ECbaChangeRecordedColor ); + } + break; + } + + case KEikDynamicLayoutVariantSwitch: + { + if ( IsVisible() ) + { + DoLayoutChange(); + SetBoundingRect( TRect() ); + if ( iFlags.IsSet( ECbaInsideDialog ) + || iFlags.IsSet( ECbaEmbedded ) ) + { + DrawDeferred(); + } + else + { + DrawNow(); + } + } + else + { + iFlags.Set( ECbaChangeRecordedLayout ); + } + break; + } + + case KAknMessageFocusLost: + { + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + return; + } + + + CEikCbaButton* button1 = + static_cast( + (*iControlArray)[KControlArrayCBAButton1Posn].iControl ); + CEikCbaButton* button2 = + static_cast( + (*iControlArray)[KControlArrayCBAButton2Posn].iControl ); + CEikCbaButton* buttonMSK = NULL; + + if ( iMSKset && AknLayoutUtils::MSKEnabled() ) + { + buttonMSK = + static_cast( + (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl ); + } + + TBool redrawNeeded( EFalse ); + + if ( button1 && button1->PressedDown() ) + { + button1->SetPressedDown( EFalse ); + redrawNeeded = ETrue; + } + if ( button2 && button2->PressedDown() ) + { + button2->SetPressedDown( EFalse ); + redrawNeeded = ETrue; + } + if ( buttonMSK && buttonMSK->PressedDown() ) + { + buttonMSK->SetPressedDown( EFalse ); + redrawNeeded = ETrue; + } + + if ( buttonMSK && iExtension ) + { + SetBoundingRect( TRect( 0, 0, 0, 0 ) ); + redrawNeeded = ETrue; + } + if ( redrawNeeded ) + { + SizeChanged(); + DrawDeferred(); + } + + if ( iFlags.IsSet( ECbaItemSpecificSoftkeyInUse ) ) + { + UpdateItemSpecificSoftkey( EFalse ); + } + break; + } + + case KEikMessageUnfadeWindows: + { + DoLayoutChange(); + SetFadeState(); + + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + DrawDeferred(); + } + else + { + //When touch unsupported,it's unnecessary to call DrawNow() + if ( AknLayoutUtils::PenEnabled() ) + { + DrawNow(); + } + else + { + DrawDeferred(); + } + } + + break; + } + + case KEikMessageFadeAllWindows: + { + if ( AknLayoutUtils::PenEnabled() && + AknStatuspaneUtils::IdleLayoutActive() ) + { + SetMSKVisibility( MskAllowed() ); + } + SetFadeState(); + break; + } + + default: + { + break; + } + } + } + + +void CEikCba::DoSkinChange() + { + iExtension->iIfSkinChanged = ETrue; + DoSetLayers( KAknsIIDNone ); + iExtension->iIfSkinChanged = EFalse; + if ( iExtension ) + { + TRAP_IGNORE( iExtension->UpdateSoftkeyFrameL( ETrue ) ); + } + + // This is required for skin resource changes (as well as color resource change). + CheckSkinAndUpdateContext(); + TRAP_IGNORE( SetMSKIconL() ); + SizeChanged(); + + //Skin change uses DrawNow to flus draw cache before layoutchange. + DrawNow(); + iFlags.Clear(ECbaChangeRecordedSkin); + } + +void CEikCba::DoColorChange() + { + iBrushAndPenContext->SetBrushColor(iEikonEnv->ControlColor(EColorToolbarBackground, *this)); + iBrushAndPenContext->SetPenColor(iEikonEnv->ControlColor(EColorToolbarText, *this)); + Window().SetBackgroundColor(iEikonEnv->ControlColor(EColorToolbarBackground, *this)); + // This is required for skin resource changes (as well as color resource change). + CheckSkinAndUpdateContext(); + TRAP_IGNORE( SetMSKIconL() ); + SizeChanged(); + iFlags.Clear(ECbaChangeRecordedColor); + } + + +void CEikCba::DoLayoutChange() + { + SetBoundingRect( TRect() ); + + UpdateFonts(); + + TBool mskAllowed( MskAllowed() ); + if ( !mskAllowed ) + { + SetMSKVisibility( EFalse ); + } + else + { + SetMSKVisibility( ETrue ); + TRAP_IGNORE( SetMSKIconL() ); + } + + if ( iFlags.IsSet( ECbaEmbedded ) ) + { + CEikCbaButton* button1 = + static_cast( + (*iControlArray)[KControlArrayCBAButton1Posn].iControl ); + CEikCbaButton* button2 = + static_cast( + (*iControlArray)[KControlArrayCBAButton2Posn].iControl ); + + if ( button1 ) + { + button1->SetPressedDown( EFalse ); + } + + if ( button2 ) + { + button2->SetPressedDown( EFalse ); + } + } + + SizeChanged(); + + if ( iExtension ) + { + TRAP_IGNORE( iExtension->UpdateSoftkeyFrameL( EFalse ) ); + } + + iFlags.Clear( ECbaChangeRecordedLayout ); + } + + +void CEikCba::HandleScrollEventL(CEikScrollBar* /*aScrollBar*/, TEikScrollEvent /*aEventType*/) + { + User::Leave(KErrNotSupported); + } + +TTypeUid::Ptr CEikCba::MopSupplyObject(TTypeUid aId) + { + if (aId.iUid == MAknsControlContext::ETypeId) + { + if ( AknLayoutFlags() & EAknLayoutCbaInControlPane || + AknLayoutFlags() & EAknLayoutCbaInRightPane ) + { + return MAknsControlContext::SupplyMopObject( aId, iMLBgContext ); + } + else + { + // Always provide top object to mop-chain. + // Bottom is parent of Top, so bottom is re-drawn + // automatically when top is drawn. + return MAknsControlContext::SupplyMopObject( aId, iStaconBgContextTop ); + } + } + + if ( aId.iUid == CEikCba::ETypeId ) + { + return aId.MakePtr( this ); + } + + return CEikControlGroup::MopSupplyObject(aId); + } + + +void CEikCba::Draw( const TRect& aRect ) const + { + // Embedded CBA doesn't draw anything + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + return; + } + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + + const TRect rect( Rect() ); + CWindowGc& gc = SystemGc(); + + TRgb rgb( TRgb::Color16MA( 0 ) ); + gc.SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha ); + gc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + gc.SetBrushColor( rgb ); + gc.Clear(); + + MAknsControlContext* cc = iMLBgContext; + + if ( iFlags.IsSet( ECbaEmbedded ) ) + { + // Embedded CBA is drawn inside dialog + if ( AknLayoutUtils::PenEnabled() && iExtension ) + { + if ( aRect.Intersects( iExtension->iLeftFrameOuterRect ) ) + { + DrawEmbeddedSoftkey( + iControlArray->At( KControlArrayCBAButton1Posn ), + iExtension->iLeftFrameOuterRect, + gc, + iExtension->iLeftFrameMask ); + } + + if ( aRect.Intersects( iExtension->iRightFrameOuterRect ) ) + { + DrawEmbeddedSoftkey( + iControlArray->At( KControlArrayCBAButton2Posn ), + iExtension->iRightFrameOuterRect, + gc, + iExtension->iRightFrameMask ); + } + } + } //ECbaEmbedded + else if ( AknLayoutFlags() & EAknLayoutCbaInControlPane ) + { + if ( AknLayoutUtils::PenEnabled() || ( iCbaFlags & EEikCbaFlagTransparent) + ||iExtension->iEnablePostingTransparency ) + { + TAknLayoutRect layoutRect; + TRect leftSKRect( iExtension->iLeftFrameOuterRect ); + TRect rightSKRect( iExtension->iRightFrameOuterRect ); + TRect middleSKRect( iExtension->iMiddleFrameOuterRect ); + + TSize leftSKSize( leftSKRect.Size() ); + TSize rightSKSize( rightSKRect.Size() ); + TSize middleSKSize( middleSKRect.Size() ); + + if ( iExtension && + iExtension->iLskPostingOverlayBitmap && + iExtension->iRskPostingOverlayBitmap ) + { + // This code may be executed if iExtension->iEnablePostingTransparency + // holds. Draw graphics with mask information alpha channel for + // transparency for posting overlay + gc.SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha ); + gc.BitBlt( rightSKRect.iTl, iExtension->iRskPostingOverlayBitmap, + TRect( rightSKSize ) ); + gc.BitBlt( leftSKRect.iTl, iExtension->iLskPostingOverlayBitmap, + TRect( leftSKSize ) ); + } + else if ( !( ( iCbaFlags & EEikCbaFlagTransparent) || ( iCbaFlags & EEikCbaFlagSemiTransparent)) ) + {// Old way to render + if( !AknsDrawUtils::Background( skin, cc, this, gc, rect ) ) + { + gc.SetPenStyle( CGraphicsContext::ENullPen ); + gc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + gc.SetBrushColor( AKN_LAF_COLOR( KStatusPaneBackgroundGraphicsColorUsual ) ); + gc.DrawRect( rect ); + } + if ( iExtension ) + { + + CEikCbaButton* button1 = static_cast( + (*iControlArray)[KControlArrayCBAButton1Posn].iControl ); + CEikCbaButton* button2 = static_cast( + (*iControlArray)[KControlArrayCBAButton2Posn].iControl ); + + if ( IsMskEnabledLayoutActive() ) + { + CEikCbaButton* buttonMSK = static_cast( + (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl ); + + CFbsBitmap* middleMask = + AknsUtils::GetCachedBitmap( skin, KAknsIIDQgnIndiSctrlSkMaskMiddlePrt ); + AknIconUtils::SetSize( middleMask, middleSKSize, EAspectRatioNotPreserved ); + + if( buttonMSK && buttonMSK->PressedDown() ) + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iMiddleFrameOuterRect, + iExtension->iMiddleFrameInnerRect, + KAknsIIDQgnFrSctrlSkButtonPressed, + KAknsIIDQgnFrSctrlSkButtonCenterPressed ); + } + else + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iMiddleFrameOuterRect, + iExtension->iMiddleFrameInnerRect, + KAknsIIDQgnFrSctrlSkButton, + KAknsIIDQgnFrSctrlSkButtonCenter); + } + + } + + if( button1 && button1->PressedDown() ) + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iLeftFrameOuterRect, + iExtension->iLeftFrameInnerRect, + KAknsIIDQgnFrSctrlSkButtonPressed, + KAknsIIDQgnFrSctrlSkButtonCenterPressed ); + } + else + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iLeftFrameOuterRect, + iExtension->iLeftFrameInnerRect, + KAknsIIDQgnFrSctrlSkButton, + KAknsIIDQgnFrSctrlSkButtonCenter); + } + + if( button2 && button2->PressedDown() ) + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iRightFrameOuterRect, + iExtension->iRightFrameInnerRect, + KAknsIIDQgnFrSctrlSkButtonPressed, + KAknsIIDQgnFrSctrlSkButtonCenterPressed ); + } + else + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iRightFrameOuterRect, + iExtension->iRightFrameInnerRect, + KAknsIIDQgnFrSctrlSkButton, + KAknsIIDQgnFrSctrlSkButtonCenter); + } + + + } + } + } + else + { + if ( !AknsDrawUtils::Background( skin, cc, this, gc, rect ) ) + { + CEikControlGroup::Draw( aRect ); + } + } + } + else if ( AknLayoutFlags() & EAknLayoutCbaInRightPane ) + { + TRect bottomSKRect; + TRect topSKRect; + if ( iExtension ) + { + bottomSKRect = iExtension->iLeftFrameOuterRect; + topSKRect = iExtension->iRightFrameOuterRect; + } + + if ( iExtension && + iExtension->iLskPostingOverlayBitmap && + iExtension->iRskPostingOverlayBitmap ) + { + // This code may be executed if iExtension->iEnablePostingTransparency + // holds. Draw graphics with mask information alpha channel for + // transparency for posting overlay + gc.SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha ); + gc.BitBlt( topSKRect.iTl, iExtension->iRskPostingOverlayBitmap, + TRect( topSKRect.Size() ) ); + gc.BitBlt( bottomSKRect.iTl, iExtension->iLskPostingOverlayBitmap, + TRect( bottomSKRect.Size() ) ); + } + else if ( !( ( iCbaFlags & EEikCbaFlagTransparent) || ( iCbaFlags & EEikCbaFlagSemiTransparent)) ) + { + // Old way to render + if( !AknsDrawUtils::Background( skin, cc, this, gc, rect ) ) + { + gc.SetPenStyle( CGraphicsContext::ENullPen ); + gc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + gc.SetBrushColor( AKN_LAF_COLOR( KStatusPaneBackgroundGraphicsColorUsual ) ); + gc.DrawRect( rect ); + } + + // Draw the softkey frames. + if ( iExtension ) + { + + CEikCbaButton* button1 = static_cast( + (*iControlArray)[KControlArrayCBAButton1Posn].iControl ); + CEikCbaButton* button2 = static_cast( + (*iControlArray)[KControlArrayCBAButton2Posn].iControl ); + + if ( button1 && button1->PressedDown() ) + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iLeftFrameOuterRect, + iExtension->iLeftFrameInnerRect, + KAknsIIDQgnFrSctrlSkButtonPressed, + KAknsIIDQgnFrSctrlSkButtonCenterPressed ); + } + else + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iLeftFrameOuterRect, + iExtension->iLeftFrameInnerRect, + KAknsIIDQgnFrSctrlSkButton, + KAknsIIDQgnFrSctrlSkButtonCenter ); + } + + if ( button2 && button2->PressedDown() ) + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iRightFrameOuterRect, + iExtension->iRightFrameInnerRect, + KAknsIIDQgnFrSctrlSkButtonPressed, + KAknsIIDQgnFrSctrlSkButtonCenterPressed ); + } + else + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iRightFrameOuterRect, + iExtension->iRightFrameInnerRect, + KAknsIIDQgnFrSctrlSkButton, + KAknsIIDQgnFrSctrlSkButtonCenter ); + } + } + } + else if ( ( iCbaFlags & EEikCbaFlagSemiTransparent) && iExtension ) + { + if ( iExtension->iSemiBgID != KAknsIIDNone ) + { + iExtension->DrawSemiTransparencyL( gc, rect ); + } + } + else + { + // No background since EEikCbaFlagTransparent is set. + // Do nothing. + } + } + else + { + // Combined statusp and control pane + + TRect screen( iAvkonAppUi->ApplicationRect() ); + + TInt variety = 0; + if ( AknLayoutFlags() & EAknLayoutCbaInStaconPaneLeft ) + { + variety = 1; + } + + TAknWindowComponentLayout layout0; + TAknWindowComponentLayout layout1; + TAknWindowComponentLayout layout2; + + // Read right (top in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_top_pane( 2 ); + layout1 = AknLayoutScalable_Avkon::stacon_top_pane(); + + // If clock is shown in stacon, cba area is smaller. + TInt topCbaVariety = variety; + if ( AknStatuspaneUtils::ExtendedStaconPaneActive() ) + { + topCbaVariety += 4; + } + + layout2 = AknLayoutScalable_Avkon::control_top_pane_stacon( topCbaVariety ); + + TAknWindowLineLayout rightSoftkeyLayout( + DoCompose( layout0,DoCompose( layout1, layout2 ) ).LayoutLine() ); + + TAknLayoutRect rightSoftkeyLayoutRect; + rightSoftkeyLayoutRect.LayoutRect( screen, rightSoftkeyLayout ); + + // Read left (bottom in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_bottom_pane( 2 ); + layout1 = AknLayoutScalable_Avkon::stacon_bottom_pane(); + + // If clock is shown in stacon, cba area is smaller. + TInt bottomCbaVariety = variety; + if ( AknStatuspaneUtils::ExtendedStaconPaneActive() ) + { + bottomCbaVariety += 2; + } + + layout2 = + AknLayoutScalable_Avkon::control_bottom_pane_stacon( + bottomCbaVariety ); + + TAknWindowLineLayout leftSoftkeyLayout( + DoCompose( layout0, DoCompose( layout1, layout2 ) ).LayoutLine() ); + + TAknLayoutRect leftSoftkeyLayoutRect; + leftSoftkeyLayoutRect.LayoutRect( screen, leftSoftkeyLayout ); + + TRect staconBottom( leftSoftkeyLayoutRect.Rect() ); + + // First draw bottom area. + cc = iStaconBgContextBottom; + + if ( iExtension && iExtension->iLskPostingOverlayBitmap ) + { + // This code may be executed if iExtension->iEnablePostingTransparency + // holds. Draw graphics with mask information alpha channel for + // transparency for posting overlay + gc.SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha ); + + gc.BitBlt( staconBottom.iTl, iExtension->iLskPostingOverlayBitmap, + TRect( staconBottom.Size() ) ); + } + else if ( !( iCbaFlags & EEikCbaFlagTransparent) ) + { + if( !AknsDrawUtils::Background( skin, cc, this, gc, staconBottom ) ) + { + gc.SetPenStyle(CGraphicsContext::ENullPen); + gc.SetBrushStyle(CGraphicsContext::ESolidBrush); + gc.SetBrushColor(AKN_LAF_COLOR(KStatusPaneBackgroundGraphicsColorUsual)); + gc.DrawRect(staconBottom); + } + if ( iExtension ) + { + CEikCbaButton* button1 = static_cast( + (*iControlArray)[KControlArrayCBAButton1Posn].iControl ); + + if ( button1 && button1->PressedDown() ) + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iLeftFrameOuterRect, + iExtension->iLeftFrameInnerRect, + KAknsIIDQgnFrSctrlSkButtonPressed, + KAknsIIDQgnFrSctrlSkButtonCenterPressed ); + } + else + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iLeftFrameOuterRect, + iExtension->iLeftFrameInnerRect, + KAknsIIDQgnFrSctrlSkButton, + KAknsIIDQgnFrSctrlSkButtonCenter ); + } + } + } + // Then top area. + cc = iStaconBgContextTop; + + TRect staconTop( rightSoftkeyLayoutRect.Rect() ); + + if ( iExtension && iExtension->iRskPostingOverlayBitmap ) + { + // This code may be executed if iExtension->iEnablePostingTransparency + // holds. Draw graphics with mask information alpha channel for + // transparency for posting overlay + gc.SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha ); + + gc.BitBlt( staconTop.iTl, iExtension->iRskPostingOverlayBitmap, + TRect( staconTop.Size() ) ); + } + else if ( !( iCbaFlags & EEikCbaFlagTransparent) ) + { + if( !AknsDrawUtils::Background( skin, cc, this, gc, staconTop ) ) + { + gc.SetPenStyle(CGraphicsContext::ENullPen); + gc.SetBrushStyle(CGraphicsContext::ESolidBrush); + gc.SetBrushColor(AKN_LAF_COLOR(KStatusPaneBackgroundGraphicsColorUsual)); + gc.DrawRect(staconTop); + } + if ( iExtension ) + { + + CEikCbaButton* button2 = static_cast( + (*iControlArray)[KControlArrayCBAButton2Posn].iControl ); + + if ( button2 && button2->PressedDown() ) + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iRightFrameOuterRect, + iExtension->iRightFrameInnerRect, + KAknsIIDQgnFrSctrlSkButtonPressed, + KAknsIIDQgnFrSctrlSkButtonCenterPressed ); + } + else + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, + iExtension->iRightFrameOuterRect, + iExtension->iRightFrameInnerRect, + KAknsIIDQgnFrSctrlSkButton, + KAknsIIDQgnFrSctrlSkButtonCenter ); + } + } + } + } + gc.SetOpaque( EFalse ); + } + + +// --------------------------------------------------------------------------- +// Gets a button control by the specified command ID. +// --------------------------------------------------------------------------- +// +CCoeControl* CEikCba::ButtonById( TInt aCommandId ) const + { + return ControlById( aCommandId ); + } + + +// --------------------------------------------------------------------------- +// Creates the scroll bar frame & sets up the scroll bar. +// --------------------------------------------------------------------------- +// +void CEikCba::CreateScrollBarFrameL() + { + if ( !iSBFrame ) + { + iSBFrame = new (ELeave) CEikCbaScrollBarFrame( this, this, ETrue ); + } + iSBFrame->ConstructL(); + } + + +TEikGroupControl CEikCba::VScrollBarAsGroupControl() + { + // Extracts vertical scroll bar from the scroll bar frame. + TEikGroupControl groupCtrl(iSBFrame->VerticalScrollBar(), 0, + KCbaScrollBarButtonWidth,TEikGroupControl::ESetLength); + return groupCtrl; + } + +void CEikCba::InsertScrollBarL() + { + TEikGroupControl SBGroupCtrl = VScrollBarAsGroupControl(); + // Insert vertical scroll bar into cba control group. + InsertControlL(SBGroupCtrl, KControlArrayScrollBarPosn); + } + + +// --------------------------------------------------------------------------- +// Replaces empty scroll bar with actual arrow head scroll bar. +// --------------------------------------------------------------------------- +// +void CEikCba::CreateArrowHeadScrollBarL() + { + if ( iSBFrame ) + { + iSBFrame->SwitchToArrowHeadScrollBarL(); + iSBFrame->VerticalScrollBar()->SetContainingCba( this ); + if ( iControlArray->Count() > KControlArrayScrollBarPosn ) + { + iControlArray->Delete( KControlArrayScrollBarPosn ); + } + InsertScrollBarL(); + } + } + + +void CEikCba::SizeChanged() + { + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + Window().SetNonFading( EFalse ); + SizeChangedInsideDialog(); + return; + } + else if ( iFlags.IsSet( ECbaEmbedded ) ) + { + Window().SetNonFading( EFalse ); + SizeChangedInPopup(); + return; + } + + const TInt aknLayoutFlags = AknLayoutFlags(); + + if ( aknLayoutFlags & EAknLayoutCbaInControlPane ) + { + Window().SetNonFading( EFalse ); + SizeChangedInControlPane(); + } + else if ( aknLayoutFlags & EAknLayoutCbaInRightPane ) + { + Window().SetNonFading( EFalse ); + SizeChangedInRightPane(); + } + else + { + Window().SetNonFading(ETrue); + SizeChangedInStaconPane(); + } + // Set the feedback areas for the softkeys. + if ( iExtension && iExtension->iEnablePostingTransparency ) + { + TBool enabled = + // AknLayoutUtils::PenEnabled() && + // ( AknLayoutFlags() & EAknLayoutCbaInRightPane ) && + !Rect().IsEmpty(); + + if ( enabled ) + { + CEikCbaButton* button1 = + static_cast( + (*iControlArray)[KControlArrayCBAButton1Posn].iControl ); + CEikCbaButton* button2 = + static_cast( + (*iControlArray)[KControlArrayCBAButton2Posn].iControl ); + + TInt leftId = (*iControlArray)[KControlArrayCBAButton1Posn].iId; + + TRAPD( err, iExtension->UpdatePostingOverlayBitmapsL( + Rect(), + button1, + button2, + aknLayoutFlags ) ); + + if ( err ) + { + // Bitmaps may not be up-to-date. + enabled = EFalse; + } + } + + if ( !enabled ) + { + // Delete and disable posting overlay support. + delete iExtension->iLskPostingOverlayBitmap; + iExtension->iLskPostingOverlayBitmap = NULL; + delete iExtension->iRskPostingOverlayBitmap; + iExtension->iRskPostingOverlayBitmap = NULL; + } + + // Broadcast current state to CEikCbaButtons + BroadcastPostingTransparency( enabled ); + } + } + +// ----------------------------------------------------------------------------- +// CEikCba::CheckSkinAndUpdateContext +// +// ----------------------------------------------------------------------------- +// +void CEikCba::CheckSkinAndUpdateContext() + { + if (AknsUtils::SkinInstance()) + { + // Use ENullBrush if there is skin background available. + iBrushAndPenContext->SetBrushStyle(CGraphicsContext::ENullBrush); + } + else + { + iBrushAndPenContext->SetBrushStyle(CGraphicsContext::ESolidBrush); + } + } + +void CEikCba::Reserved_MtsmPosition() + { + } + +void CEikCba::Reserved_MtsmObject() + { + } + +TInt CEikCba::AknLayoutFlags() const + { + TInt flags = 0; + + TBool controlPane = ETrue; + TBool staconPane = EFalse; + TBool staconPaneLeft = EFalse; + TBool staconPaneRight = EFalse; + TBool staconPaneIdle = EFalse; + TBool rightPane = EFalse; + + TInt currentStatusPaneLayoutResId = + AVKONENV->StatusPaneResIdForCurrentLayout( + AknStatuspaneUtils::CurrentStatusPaneLayoutResId() ); + + staconPane = + ((currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_USUAL_SOFTKEYS_RIGHT) || + (currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_USUAL_SOFTKEYS_LEFT) || + (currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_EMPTY_SOFTKEYS_RIGHT) || + (currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_EMPTY_SOFTKEYS_LEFT) || + (currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_IDLE_SOFTKEYS_RIGHT) || + (currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_IDLE_SOFTKEYS_LEFT)); + + staconPaneRight = + ((currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_USUAL_SOFTKEYS_RIGHT) || + (currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_EMPTY_SOFTKEYS_RIGHT) || + (currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_IDLE_SOFTKEYS_RIGHT)); + + staconPaneIdle = + ((currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_IDLE_SOFTKEYS_RIGHT) || + (currentStatusPaneLayoutResId == R_AVKON_STACON_PANE_LAYOUT_IDLE_SOFTKEYS_LEFT)); + + staconPaneLeft = !staconPaneRight; + controlPane = !staconPane; + + if ( IsAreaSideRightPaneActive() ) + { + rightPane = ETrue; + controlPane = EFalse; + staconPane = EFalse; + staconPaneLeft = EFalse; + staconPaneRight = EFalse; + staconPaneIdle = EFalse; + } + + if (staconPane) + { + flags |= EAknLayoutCbaInStaconPane; + } + if (controlPane) + { + flags |= EAknLayoutCbaInControlPane; + } + if (staconPaneLeft) + { + flags |= EAknLayoutCbaInStaconPaneLeft; + } + if (staconPaneRight) + { + flags |= EAknLayoutCbaInStaconPaneRight; + } + if (staconPaneIdle) + { + flags |= EAknLayoutCbaInStaconPaneIdle; + } + if (rightPane) + { + flags |= EAknLayoutCbaInRightPane; + } + + return flags; + } + + +// --------------------------------------------------------------------------- +// Handles size change events in bottom softkey layout. +// --------------------------------------------------------------------------- +// +void CEikCba::SizeChangedInControlPane() + { + TRect screen; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen ); + + TBool isLandscape( Layout_Meta_Data::IsLandscapeOrientation() ); + TBool flatLscLayout( isLandscape && + AknStatuspaneUtils::FlatLayoutActive() ); + + // We must check for landscape mode bottom softkeys. + TInt bottomPaneVariety = isLandscape ? ( flatLscLayout ? 2 : 6 ) : 1; + + TAknWindowComponentLayout controlPane( + DoCompose( + AknLayoutScalable_Avkon::application_window( 0 ), + DoCompose( + AknLayoutScalable_Avkon::area_bottom_pane( bottomPaneVariety ), + AknLayoutScalable_Avkon::control_pane() ) ) ); + + TAknLayoutRect cbarect; + cbarect.LayoutRect( screen, controlPane.LayoutLine() ); + TRect rect( cbarect.Rect().Size() ); + + TRect posInScreen( cbarect.Rect() ); + + TBool mskEnabledInPlatform( iMSKEnabledInPlatform && + IsMskEnabledLayoutActive() ); + + TBool mskEnabledInApplication( AknLayoutUtils::MSKEnabled() && iMSKset ); + + // Set the softkey frame rectangles in touch layouts. + if ( iExtension && AknLayoutUtils::PenEnabled() ) + { + TAknLayoutRect layoutRect; + TBool frameSizeChanged( EFalse ); + + if ( mskEnabledInPlatform || flatLscLayout ) + { + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::control_pane_g6( 0 ).LayoutLine() ); + frameSizeChanged = layoutRect.Rect() != iExtension->iLeftFrameOuterRect; + iExtension->iLeftFrameOuterRect = layoutRect.Rect(); + + layoutRect.LayoutRect( iExtension->iLeftFrameOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + iExtension->iLeftFrameInnerRect = layoutRect.Rect(); + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::control_pane_g8( 0 ).LayoutLine() ); + frameSizeChanged = frameSizeChanged || layoutRect.Rect() != iExtension->iRightFrameOuterRect; + iExtension->iRightFrameOuterRect = layoutRect.Rect(); + layoutRect.LayoutRect( iExtension->iRightFrameOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + iExtension->iRightFrameInnerRect = layoutRect.Rect(); + + if ( mskEnabledInPlatform ) + { + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::control_pane_g7( 0 ).LayoutLine() ); + frameSizeChanged = frameSizeChanged || layoutRect.Rect() != iExtension->iMiddleFrameOuterRect; + iExtension->iMiddleFrameOuterRect = layoutRect.Rect(); + layoutRect.LayoutRect( iExtension->iMiddleFrameOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + iExtension->iMiddleFrameInnerRect = layoutRect.Rect(); + } + else + { + iExtension->iMiddleFrameOuterRect.SetRect( 0, 0, 0, 0 ); + } + } + else + { + if ( AknLayoutUtils::LayoutMirrored() ) + { + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_cp1().LayoutLine() ); + frameSizeChanged = layoutRect.Rect() != iExtension->iRightFrameOuterRect; + iExtension->iRightFrameOuterRect = layoutRect.Rect(); + layoutRect.LayoutRect( iExtension->iRightFrameOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + iExtension->iRightFrameInnerRect = layoutRect.Rect(); + + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_cp2().LayoutLine() ); + frameSizeChanged = frameSizeChanged || layoutRect.Rect() != iExtension->iLeftFrameOuterRect; + iExtension->iLeftFrameOuterRect = layoutRect.Rect(); + + layoutRect.LayoutRect( iExtension->iLeftFrameOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + iExtension->iLeftFrameInnerRect = layoutRect.Rect(); + } + else + { + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_cp1().LayoutLine() ); + frameSizeChanged = layoutRect.Rect() != iExtension->iLeftFrameOuterRect; + iExtension->iLeftFrameOuterRect = layoutRect.Rect(); + + layoutRect.LayoutRect( iExtension->iLeftFrameOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + iExtension->iLeftFrameInnerRect = layoutRect.Rect(); + + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_cp2().LayoutLine() ); + frameSizeChanged = frameSizeChanged || layoutRect.Rect() != iExtension->iRightFrameOuterRect; + iExtension->iRightFrameOuterRect = layoutRect.Rect(); + layoutRect.LayoutRect( iExtension->iRightFrameOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + iExtension->iRightFrameInnerRect = layoutRect.Rect(); + } + } + + if ( frameSizeChanged ) + { + TRAP_IGNORE( iExtension->UpdateSoftkeyFrameL( EFalse ) ); + } + } + + DoSetLayers( KAknsIIDNone ); + + TInt textVariety; + TInt graphVariety; + + // Even if the application is not MSK enabled, + // use MSK layout when MSK is enabled in platform. + if ( isLandscape ) + { + if ( mskEnabledInPlatform ) + { + textVariety = 3; + graphVariety = 2; + } + else + { + TBool extendedLayout( AknStatuspaneUtils::ExtendedFlatLayoutActive() ); + textVariety = extendedLayout ? 3 : 2; + graphVariety = extendedLayout ? 3 : 2; + } + } + else if ( mskEnabledInPlatform ) + { + textVariety = 3; + graphVariety = 4; + } + else + { + textVariety = 0; + graphVariety = 4; + } + + if ( iExtension->iEnablePostingTransparency || + ( iCbaFlags & EEikCbaFlagTransparent ) || ( iCbaFlags & EEikCbaFlagSemiTransparent ) ) + { + textVariety = 6; // Outline font used + } + + // This uses correct coordinates to calculate the positions of softkey labels. + // Unfortunately we do not have access to the labels inside CEikCbaButtons, + // that's the reason for a hack with ComponentControl(). + // (This is the only place that knows of all softkeys ...) + if ( iControlArray->Count() != 0 ) + { + CCoeControl* leftSoftkey = (*iControlArray)[KControlArrayCBAButton1Posn].iControl; + CCoeControl* rightSoftkey = (*iControlArray)[KControlArrayCBAButton2Posn].iControl; + CCoeControl* MSKSoftkey = NULL; + + CEikCbaButton* leftSKButton = + static_cast( leftSoftkey ); + CEikCbaButton* rightSKButton = + static_cast( rightSoftkey ); + CEikCbaButton* MSKButton = NULL; + + TAknTextLineLayout controlPaneTextLayout; + + if ( !leftSKButton->IsImageOn() ) + { + controlPaneTextLayout = + AknLayoutScalable_Avkon::control_pane_t1( textVariety ).LayoutLine(); + + if ( iCbaFlags & EEikCbaFlagOutlineFont ) + { + // Sets outline font property. + controlPaneTextLayout.iFont |= KOutlineFontMask; + } + + CEikLabel* cbaLabel = + static_cast( leftSoftkey->ComponentControl( 0 ) ); + AknLayoutUtils::LayoutLabel( cbaLabel, + Rect(), + controlPaneTextLayout ); + LayoutControl( leftSKButton, cbaLabel->Rect() ); + leftSKButton->TruncateLabelText(); + } + else + { + TAknLayoutRect qgn_graf_sk_left; + qgn_graf_sk_left.LayoutRect( + rect, + AknLayoutScalable_Avkon::control_pane_g1( graphVariety ).LayoutLine() ); + leftSoftkey->ComponentControl( 0 )->SetRect( qgn_graf_sk_left.Rect() ); + leftSoftkey->SetRect( qgn_graf_sk_left.Rect() ); + } + + if ( !rightSKButton->IsImageOn() ) + { + controlPaneTextLayout = + AknLayoutScalable_Avkon::control_pane_t2( textVariety ).LayoutLine(); + + if ( iCbaFlags & EEikCbaFlagOutlineFont ) + { + // Sets outline font property. + controlPaneTextLayout.iFont |= KOutlineFontMask; + } + + CEikLabel* cbaLabel = + static_cast( rightSoftkey->ComponentControl( 0 ) ); + AknLayoutUtils::LayoutLabel( cbaLabel, + Rect(), + controlPaneTextLayout ); + LayoutControl( rightSKButton, cbaLabel->Rect() ); + rightSKButton->TruncateLabelText(); + } + else + { + TAknLayoutRect qgn_graf_sk_right; + qgn_graf_sk_right.LayoutRect( + rect, + AknLayoutScalable_Avkon::control_pane_g2( graphVariety ).LayoutLine() ); + rightSoftkey->ComponentControl( 0 )->SetRect( qgn_graf_sk_right.Rect() ); + rightSoftkey->SetRect( qgn_graf_sk_right.Rect() ); + } + + // Scrollbar will go over MSK!!! needs to be fixed. + if ( VScrollBarAsControl()->Model()->ScrollBarUseful() ) + { + CCoeControl* scroller = (*iControlArray)[KControlArrayScrollBarPosn].iControl; + AknLayoutUtils::LayoutControl( + scroller, + rect, + AKN_LAYOUT_WINDOW_Control_pane_elements_Line_1 ); + } + + TInt textMSKVariety = 3; + TInt graphicMSKVariety = 0; + + if ( mskEnabledInApplication && mskEnabledInPlatform ) + { + MSKSoftkey = (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl; + MSKButton = static_cast( MSKSoftkey ); + + if ( !MSKButton->IsImageOn() ) + { + controlPaneTextLayout = + AknLayoutScalable_Avkon::control_pane_t3( + textMSKVariety ).LayoutLine(); + + if ( iCbaFlags & EEikCbaFlagOutlineFont ) + { + // Sets outline font property. + controlPaneTextLayout.iFont |= KOutlineFontMask; + } + + CEikLabel* cbaLabel = + static_cast( MSKSoftkey->ComponentControl( 0 ) ); + AknLayoutUtils::LayoutLabel( cbaLabel, + Rect(), + controlPaneTextLayout ); + LayoutControl( MSKButton, cbaLabel->Rect() ); + MSKButton->TruncateLabelText(); + } + else + { + TAknLayoutRect qgn_graf_sk_msk; + qgn_graf_sk_msk.LayoutRect( + rect, + AknLayoutScalable_Avkon::control_pane_g4( + graphicMSKVariety ).LayoutLine() ); + TRect rect( qgn_graf_sk_msk.Rect() ); + + // aid_value_unit2 is 10ux10u rectangle + TAknWindowComponentLayout unit( AknLayoutScalable_Avkon::aid_value_unit2() ); + TInt delta = unit.LayoutLine().iW / 10 / 2; // half units + if ( MSKButton->PressedDown() ) + { + rect.Move( delta, delta ); + } + MSKSoftkey->ComponentControl( 0 )->SetRect( rect ); + MSKSoftkey->SetRect( rect ); + } + } + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + const TBool transparentSoftkeys = + iExtension->iEnablePostingTransparency || + ( iCbaFlags & EEikCbaFlagTransparent ) || + ( iCbaFlags & EEikCbaFlagSemiTransparent ); + TRgb leftColor; + TRgb rightColor; + TRgb MSKColor; + TInt errorl; + TInt errorr; + TInt errorMSK; + + TBool idleState = AknStatuspaneUtils::IdleLayoutActive(); + if ( idleState ) + { + errorl = AknsUtils::GetCachedColor( + skin, + leftColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG15 ); + + errorr = AknsUtils::GetCachedColor( + skin, + rightColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG16 ); + + errorMSK = AknsUtils::GetCachedColor( + skin, + MSKColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG57 ); + } + else if ( iPopupVisible ) + { + errorl = AknsUtils::GetCachedColor( + skin, + leftColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG17 ); + + errorr = AknsUtils::GetCachedColor( + skin, + rightColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG18 ); + + errorMSK = AknsUtils::GetCachedColor( + skin, + MSKColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG58 ); + } + else + { + errorl = AknsUtils::GetCachedColor( + skin, + leftColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG13 ); + + errorr = AknsUtils::GetCachedColor( + skin, + rightColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG14 ); + + errorMSK = AknsUtils::GetCachedColor( + skin, + MSKColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG56 ); + } + + if ( transparentSoftkeys ) + { + rightColor = KRgbWhite; + leftColor = KRgbWhite; + } + if ( leftSKButton->PressedDown() ) + { + leftColor.SetAlpha( KPressedDownAlphaValue ); + + AknsUtils::GetCachedColor( + skin, + leftColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG69 ); + + if ( transparentSoftkeys ) + { + // alpha has no effect with display posting. + leftColor = TRgb( 128, 128, 128 ); + } + } + else if ( rightSKButton->PressedDown() ) + { + rightColor.SetAlpha( KPressedDownAlphaValue ); + + AknsUtils::GetCachedColor( + skin, + rightColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG69 ); + + if ( transparentSoftkeys ) + { + // alpha has no effect with display posting. + rightColor = TRgb( 128, 128, 128 ); + } + } + else if ( MSKButton && MSKButton->PressedDown() ) + { + MSKColor.SetAlpha( KPressedDownAlphaValue ); + + AknsUtils::GetCachedColor( + skin, + MSKColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG69 ); + + } + + if( !errorl && !errorr ) + { + // Error ignored + TRAP( errorl, AknLayoutUtils::OverrideControlColorL( + *leftSoftkey, + EColorLabelText, + leftColor) ); + + TRAP( errorr, AknLayoutUtils::OverrideControlColorL( + *rightSoftkey, + EColorLabelText, + rightColor) ); + + if ( transparentSoftkeys ) + { + // Outline color is black. + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( + *leftSoftkey, + EColorControlBackground, + KRgbBlack ) ); + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( + *rightSoftkey, + EColorControlBackground, + KRgbBlack ) ); + } + } + + if ( mskEnabledInApplication && mskEnabledInPlatform && !errorMSK ) + { + // Error ignored. + TRAP( errorMSK, AknLayoutUtils::OverrideControlColorL( + *MSKSoftkey, + EColorLabelText, + MSKColor) ); + } + + // If MSK colors not set in skin, use left CBA color. + if ( mskEnabledInApplication && mskEnabledInPlatform && errorMSK && !errorl ) + { + // Error ignored. + TRAP( errorMSK, + { + AknLayoutUtils::OverrideControlColorL( + *MSKSoftkey, + EColorLabelText, + leftColor); + } ); + } + + DrawDeferred(); + } + + AknsUtils::RegisterControlPosition( this, posInScreen.iTl ); + } + + +void CEikCba::SizeChangedInStaconPane() + { + TRect screen( iAvkonAppUi->ApplicationRect() ); + TBool softKeysUpAndDownMirrored = EFalse; + + TInt variety = 0; + if (AknLayoutFlags() & EAknLayoutCbaInStaconPaneLeft) + { + variety = 1; + } + + TAknWindowComponentLayout layout0; + TAknWindowComponentLayout layout1; + TAknWindowComponentLayout layout2; + TAknWindowComponentLayout imageLayout; + TAknTextComponentLayout textLayout; + + // Read right (top in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_top_pane(2); + layout1 = AknLayoutScalable_Avkon::stacon_top_pane(); + + // If clock is shown in stacon, cba area is smaller. + TInt topCbaVariety = variety; + if (AknStatuspaneUtils::ExtendedStaconPaneActive()) + { + topCbaVariety += 4; + } + + TInt textVariety = variety; + if ( iExtension->iEnablePostingTransparency || ( iCbaFlags & EEikCbaFlagTransparent ) ) + { + textVariety += 2; // Outline font used + } + + layout2 = AknLayoutScalable_Avkon::control_top_pane_stacon(topCbaVariety); + imageLayout = AknLayoutScalable_Avkon::control_top_pane_stacon_g1(); + textLayout = AknLayoutScalable_Avkon::control_top_pane_stacon_t1(textVariety); + + TAknTextComponentLayout rightSoftKeyTextLayout( + DoComposeText(layout0, DoComposeText(layout1, DoComposeText(layout2, textLayout))) ); + TAknWindowComponentLayout rightSoftKeyImageLayout( + DoCompose(layout0, DoCompose(layout1, DoCompose(layout2, imageLayout))) ); + + // Calculate softkey rects. + TAknWindowLineLayout rightSoftkeyLayout( + DoCompose( layout0, DoCompose(layout1, layout2)).LayoutLine() ); + TAknLayoutRect rightSoftkeyLayoutRect; + rightSoftkeyLayoutRect.LayoutRect(screen, rightSoftkeyLayout); + TRect rightSoftKeyButtonRect( rightSoftkeyLayoutRect.Rect() ); + + TAknTextLineLayout rightSoftkeyTextLayout( rightSoftKeyTextLayout.LayoutLine() ); + TAknWindowLineLayout rightSoftkeyImageLayout( rightSoftKeyImageLayout.LayoutLine() ); + + // Read left (bottom in landscape) softkey layout. + layout0 = AknLayoutScalable_Avkon::area_bottom_pane(2); + layout1 = AknLayoutScalable_Avkon::stacon_bottom_pane(); + + // If clock is shown in stacon, cba area is smaller. + TInt bottomCbaVariety = variety; + if (AknStatuspaneUtils::ExtendedStaconPaneActive()) + { + bottomCbaVariety += 2; + } + + layout2 = AknLayoutScalable_Avkon::control_bottom_pane_stacon(bottomCbaVariety); + imageLayout = AknLayoutScalable_Avkon::control_bottom_pane_stacon_g1(); + textLayout = AknLayoutScalable_Avkon::control_bottom_pane_stacon_t1(textVariety); + + TAknTextComponentLayout leftSoftKeyTextLayout( + DoComposeText(layout0, DoComposeText(layout1, DoComposeText(layout2, textLayout))) ); + TAknWindowComponentLayout leftSoftKeyImageLayout( + DoCompose(layout0, DoCompose(layout1, DoCompose(layout2, imageLayout))) ); + + // Calculate softkey rects + TAknWindowLineLayout leftSoftkeyLayout( + DoCompose( layout0, DoCompose(layout1, layout2) ).LayoutLine() ); + TAknLayoutRect leftSoftkeyLayoutRect; + leftSoftkeyLayoutRect.LayoutRect(screen, leftSoftkeyLayout); + TRect leftSoftKeyButtonRect( leftSoftkeyLayoutRect.Rect() ); + + TAknTextLineLayout leftSoftkeyTextLayout( leftSoftKeyTextLayout.LayoutLine() ); + TAknWindowLineLayout leftSoftkeyImageLayout( leftSoftKeyImageLayout.LayoutLine() ); + + // If softkeys are on the "other" side, then swap the texts and images here... + if (variety == 1) + { + CWsScreenDevice* dev = iEikonEnv->ScreenDevice(); + TPixelsAndRotation sizeAndRotation; + dev->GetScreenModeSizeAndRotation(dev->CurrentScreenMode(), sizeAndRotation); + + TBool isLandscape( Layout_Meta_Data::IsLandscapeOrientation() ); + + // If landscape orientation uses 270 degree rotation ( or 0 degree + // rotation in case of default portrait rotation uses 90 degree value), + // only then mirror L & R (actually upper and lower in stacon). + if ( isLandscape && + ( sizeAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationRotated270 || + sizeAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationNormal ) ) + { + softKeysUpAndDownMirrored = ETrue; + TAknTextLineLayout tmpTextLineLayout( leftSoftkeyTextLayout ); + TAknWindowLineLayout tmpWindowLineLayout( leftSoftkeyImageLayout ); + TRect tmpRect( leftSoftKeyButtonRect ); + + leftSoftKeyButtonRect = rightSoftKeyButtonRect; + leftSoftkeyTextLayout = rightSoftkeyTextLayout; + leftSoftkeyImageLayout = rightSoftkeyImageLayout; + + rightSoftKeyButtonRect = tmpRect; + rightSoftkeyTextLayout = tmpTextLineLayout; + rightSoftkeyImageLayout = tmpWindowLineLayout; + } + } + + // Set skin background. + TRect screenRect( iAvkonAppUi->ApplicationRect() ); + TAknWindowLineLayout layout( AknLayoutScalable_Avkon::area_top_pane(2).LayoutLine() ); + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( screenRect, layout ); + TRect staconTop( layoutRect.Rect() ); + + layout = AknLayoutScalable_Avkon::area_bottom_pane(2).LayoutLine(); + layoutRect.LayoutRect( screenRect, layout ); + TRect staconBottom( layoutRect.Rect() ); + + TBool skLeft = AknLayoutFlags() & EAknLayoutCbaInStaconPaneLeft; + TBool idle = AknLayoutFlags() & EAknLayoutCbaInStaconPaneIdle; + + TAknsItemID topMaskIID = KAknsIIDNone; + TAknsItemID bottomMaskIID = KAknsIIDNone; + + if ( idle ) + { + if ( skLeft ) + { + iStaconBgContextTop->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconLtIdle ); + iStaconBgContextBottom->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconLbIdle ); + } + else + { + iStaconBgContextTop->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconRtIdle ); + iStaconBgContextBottom->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconRbIdle ); + } + iStaconBgContextTop->SetLayerImage( ECbaLayerWallpaper, KAknsIIDWallpaper ); + iStaconBgContextTop->SetLayerRect( ECbaLayerWallpaper, screen ); + iStaconBgContextTop->SetLayerRect( ECbaLayerBackground, staconTop ); + + topMaskIID = KAknsIIDQgnGrafBgLscTopMaskIcon; + + iStaconBgContextBottom->SetLayerImage( ECbaLayerWallpaper, KAknsIIDWallpaper ); + iStaconBgContextBottom->SetLayerRect( ECbaLayerWallpaper, screen ); + iStaconBgContextBottom->SetLayerRect( ECbaLayerBackground, staconBottom ); + + bottomMaskIID = KAknsIIDQgnGrafBgLscBottomMaskIcon; + } + else + { + // If not in idle, then there is no wallpaper, thus clear wallpaper layer. + if ( skLeft ) + { + iStaconBgContextTop->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconLt ); + iStaconBgContextBottom->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconLb ); + } + else + { + iStaconBgContextTop->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconRt ); + iStaconBgContextBottom->SetLayerImage( ECbaLayerBackground, KAknsIIDQsnBgAreaStaconRb ); + } + iStaconBgContextTop->SetLayerRect( ECbaLayerBackground, staconTop ); + iStaconBgContextTop->SetLayerImage( ECbaLayerWallpaper, KAknsIIDNone ); + topMaskIID = KAknsIIDNone; + + iStaconBgContextBottom->SetLayerRect( ECbaLayerBackground, staconBottom ); + iStaconBgContextBottom->SetLayerImage( ECbaLayerWallpaper, KAknsIIDNone ); + bottomMaskIID = KAknsIIDNone; + } + + // If setting layer mask fails, ignore the error. + // This causes UI elements to be opaque and thus parts of the wallpaper is hidden. + TRAP_IGNORE( + iStaconBgContextBottom->SetLayerMaskAndSizeL( bottomMaskIID, staconBottom ); + iStaconBgContextTop->SetLayerMaskAndSizeL( topMaskIID, staconTop ); + ); + + TRect cba( Rect() ); + // This uses correct coordinates to calculate the positions of softkey labels. + // Unfortunately we do not have access to the labels inside CEikCbaButtons, + // that's the reason for a hack with ComponentControl(). + // (This is the only place that knows of both left and right softkey ...) + if (iControlArray->Count() != 0) + { + CCoeControl *leftSoftkey = (*iControlArray)[KControlArrayCBAButton1Posn].iControl; + CCoeControl *rightSoftkey = (*iControlArray)[KControlArrayCBAButton2Posn].iControl; + + // Left SK. + if (!(((CEikCbaButton*)leftSoftkey)->IsImageOn())) + { + AknLayoutUtils::LayoutLabel((CEikLabel*)leftSoftkey->ComponentControl( 0 ), + Rect(), + leftSoftkeyTextLayout ); + LayoutControl( (CEikCbaButton*)leftSoftkey, + leftSoftkey->ComponentControl( 0 )->Rect() ); + ((CEikCbaButton*)leftSoftkey)->TruncateLabelText(); + } + else + { + TAknLayoutRect qgn_graf_sk_left; + qgn_graf_sk_left.LayoutRect(cba, leftSoftkeyImageLayout); + leftSoftkey->ComponentControl(0)->SetRect(qgn_graf_sk_left.Rect()); + leftSoftkey->SetRect(leftSoftKeyButtonRect); + + // To make sure mop chain is updated, do it here. If not done, only skin background + // suffers. + TRAP_IGNORE(((CEikCbaButton*)leftSoftkey)->SetContainerWindowL(*this)); + } + + // Right SK. + if (!(((CEikCbaButton*)rightSoftkey)->IsImageOn())) + { + AknLayoutUtils::LayoutLabel((CEikLabel*)rightSoftkey->ComponentControl( 0 ), + Rect(), + rightSoftkeyTextLayout ); + LayoutControl( (CEikCbaButton*)rightSoftkey, + rightSoftkey->ComponentControl( 0 )->Rect() ); + ((CEikCbaButton*)rightSoftkey)->TruncateLabelText(); + } + else + { + TAknLayoutRect qgn_graf_sk_right; + qgn_graf_sk_right.LayoutRect(cba, rightSoftkeyImageLayout); + rightSoftkey->ComponentControl(0)->SetRect(qgn_graf_sk_right.Rect()); + rightSoftkey->SetRect(rightSoftKeyButtonRect); + + // To make sure mop chain is updated, do it here. If not done, only skin background + // suffers. + TRAP_IGNORE(((CEikCbaButton*)rightSoftkey)->SetContainerWindowL(*this)); + } + + // Landscape mode scrollbar layout is not set here, let application do if needed. + CCoeControl* scroller = (*iControlArray)[KControlArrayScrollBarPosn].iControl; + if (scroller) + { + scroller->SetSize(TSize(0,0)); + } + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + const TBool transparentSoftkeys = + iExtension->iEnablePostingTransparency || + ( iCbaFlags & EEikCbaFlagTransparent ); + TRgb rightSkColor; + TRgb leftSkColor; + + TInt error1 = 0; + TInt error2 = 0; + + if (idle) + { + error1 = AknsUtils::GetCachedColor( skin, rightSkColor, KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG41 ); // text #41 stacon area top softkey text in idle #0 + + error2 = AknsUtils::GetCachedColor( skin, leftSkColor, KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG42 ); // text #42 stacon area bottom softkey text in idle #0 + } + else + { + error1 = AknsUtils::GetCachedColor( skin, rightSkColor, KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG39 ); // text #39 stacon area top softkey text #0 + + error2 = AknsUtils::GetCachedColor( skin, leftSkColor, KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG40 ); // text #40 stacon area bottom softkey text #0 + } + + if ( transparentSoftkeys ) + { + rightSkColor = KRgbWhite; + leftSkColor = KRgbWhite; + } + if (softKeysUpAndDownMirrored) + { + TRgb tmp = rightSkColor; + rightSkColor = leftSkColor; + leftSkColor = tmp; + } + + if ( ((CEikCbaButton*)leftSoftkey)->PressedDown() ) + { + leftSkColor.SetAlpha( KPressedDownAlphaValue ); + + AknsUtils::GetCachedColor( + skin, + leftSkColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG69 ); + + if ( transparentSoftkeys ) + { + // alpha has no effect with display posting. + leftSkColor = TRgb( 128, 128, 128 ); + } + } + else if ( ((CEikCbaButton*)rightSoftkey)->PressedDown() ) + { + rightSkColor.SetAlpha( KPressedDownAlphaValue ); + + AknsUtils::GetCachedColor( + skin, + rightSkColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG69 ); + + if ( transparentSoftkeys ) + { + // alpha has no effect with display posting. + rightSkColor = TRgb( 128, 128, 128 ); + } + } + + if( !error1 && !error2 ) + { + // Error ignored. + TRAP( error1, AknLayoutUtils::OverrideControlColorL(*leftSoftkey, + EColorLabelText, + leftSkColor) ); + TRAP( error2, AknLayoutUtils::OverrideControlColorL(*rightSoftkey, + EColorLabelText, + rightSkColor) ); + if ( transparentSoftkeys ) + { + // outline color is black. + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( + *leftSoftkey, + EColorControlBackground, + KRgbBlack ) ); + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( + *rightSoftkey, + EColorControlBackground, + KRgbBlack ) ); + } + } + + if (iStaconLabelFont) + { + ((CEikCbaButton*)leftSoftkey)->SetLabelFont(iStaconLabelFont); + ((CEikCbaButton*)rightSoftkey)->SetLabelFont(iStaconLabelFont); + } + + DrawDeferred(); + } + + AknsUtils::RegisterControlPosition( this, TPoint(0,0) ); + } + + +//------------------------------------------------------------------------------ +// CEikCba::SizeChangedInRightPane() +//------------------------------------------------------------------------------ +// +void CEikCba::SizeChangedInRightPane() + { + TRect screen; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen ); + + TAknWindowComponentLayout rightAreaLayout( + AknLayoutScalable_Avkon::area_side_right_pane( 0 ) ); + + TAknWindowComponentLayout topSKLayout( + DoCompose( rightAreaLayout, + AknLayoutScalable_Avkon::sctrl_sk_top_pane() ) ); + + TAknWindowComponentLayout bottomSKLayout( + DoCompose( rightAreaLayout, + AknLayoutScalable_Avkon::sctrl_sk_bottom_pane() ) ); + + // Calculate softkey rects. + + // Right (top in landscape) softkey layout. + TAknLayoutRect rightSoftkeyLayoutRect; + rightSoftkeyLayoutRect.LayoutRect( screen, + topSKLayout.LayoutLine() ); + TRect rightSoftKeyButtonRect( rightSoftkeyLayoutRect.Rect() ); + + // Left (bottom in landscape) softkey layout. + TAknLayoutRect leftSoftkeyLayoutRect; + leftSoftkeyLayoutRect.LayoutRect( screen, + bottomSKLayout.LayoutLine() ); + TRect leftSoftKeyButtonRect( leftSoftkeyLayoutRect.Rect() ); + + // Set the softkey frame rectangles in touch layouts. + if ( iExtension && AknLayoutUtils::PenEnabled() ) + { + TBool frameSizeChanged( + iExtension->iLeftFrameOuterRect != leftSoftKeyButtonRect || + iExtension->iRightFrameOuterRect != rightSoftKeyButtonRect ); + iExtension->iLeftFrameOuterRect = leftSoftKeyButtonRect; + iExtension->iRightFrameOuterRect = rightSoftKeyButtonRect; + if ( frameSizeChanged ) + { + TRAP_IGNORE( iExtension->UpdateSoftkeyFrameL( EFalse ) ); + } + } + + // Calculate softkey image and text layouts. + TInt softkeyTextVariety = 0; + + if ( iExtension->iEnablePostingTransparency || ( iCbaFlags & EEikCbaFlagTransparent ) ) + { + softkeyTextVariety = 1; // Outline font used + } + + // Right (top in landscape) softkey layout. + TAknTextLineLayout rightSoftkeyTextLayout( + DoComposeText( + topSKLayout, + AknLayoutScalable_Avkon::sctrl_sk_top_pane_t1(softkeyTextVariety) ).LayoutLine() ); + + TAknWindowLineLayout rightSoftkeyImageLayout( + DoCompose( + topSKLayout, + AknLayoutScalable_Avkon::sctrl_sk_top_pane_g1() ).LayoutLine() ); + + // Left (bottom in landscape) softkey layout. + TAknTextLineLayout leftSoftkeyTextLayout( + DoComposeText( + bottomSKLayout, + AknLayoutScalable_Avkon::sctrl_sk_bottom_pane_t1(softkeyTextVariety) ).LayoutLine() ); + + TAknWindowLineLayout leftSoftkeyImageLayout( + DoCompose( + bottomSKLayout, + AknLayoutScalable_Avkon::sctrl_sk_bottom_pane_g1() ).LayoutLine() ); + + // Set skin background. + + DoSetLayers( KAknsIIDNone ); + + TRect cba( Rect() ); + + // This uses correct coordinates to calculate the positions + // of softkey labels. Unfortunately we do not have access to + // the labels inside CEikCbaButtons, that's the reason for a + // hack with ComponentControl(). + // (This is the only place that knows of both left and right softkey ...) + if ( iControlArray->Count() != 0 ) + { + CCoeControl* leftSoftkeyControl = + (*iControlArray)[KControlArrayCBAButton1Posn].iControl; + CCoeControl* rightSoftkeyControl = + (*iControlArray)[KControlArrayCBAButton2Posn].iControl; + + CEikCbaButton* leftSoftkey = + static_cast( leftSoftkeyControl ); + CEikCbaButton* rightSoftkey = + static_cast( rightSoftkeyControl ); + + // Left SK. + if ( !leftSoftkey->IsImageOn() ) + { + AknLayoutUtils::LayoutLabel( + static_cast( leftSoftkeyControl->ComponentControl( 0 ) ), + cba, + leftSoftkeyTextLayout ); + LayoutControl( + leftSoftkey, + leftSoftkeyControl->ComponentControl( 0 )->Rect() ); + leftSoftkey->TruncateLabelText(); + } + else + { + TAknLayoutRect qgn_graf_sk_left; + qgn_graf_sk_left.LayoutRect( cba, leftSoftkeyImageLayout ); + leftSoftkeyControl->ComponentControl( 0 )->SetRect( qgn_graf_sk_left.Rect() ); + leftSoftkeyControl->SetRect( leftSoftKeyButtonRect ); + + // To make sure mop chain is updated, do it here. + // If not done, only skin background suffers. + TRAP_IGNORE( leftSoftkey->SetContainerWindowL( *this ) ); + } + + // Right SK. + if ( !rightSoftkey->IsImageOn() ) + { + AknLayoutUtils::LayoutLabel( + static_cast( rightSoftkeyControl->ComponentControl( 0 ) ), + cba, + rightSoftkeyTextLayout ); + LayoutControl( + rightSoftkey, + rightSoftkeyControl->ComponentControl( 0 )->Rect() ); + rightSoftkey->TruncateLabelText(); + } + else + { + TAknLayoutRect qgn_graf_sk_right; + qgn_graf_sk_right.LayoutRect( cba, rightSoftkeyImageLayout ); + rightSoftkeyControl->ComponentControl( 0 )->SetRect( qgn_graf_sk_right.Rect() ); + rightSoftkeyControl->SetRect( rightSoftKeyButtonRect ); + + // To make sure mop chain is updated, do it here. + // If not done, only skin background suffers. + TRAP_IGNORE( rightSoftkey->SetContainerWindowL( *this ) ); + } + + // Landscape mode scrollbar layout is not set here, let application do if needed. + CCoeControl* scroller = (*iControlArray)[KControlArrayScrollBarPosn].iControl; + if ( scroller ) + { + scroller->SetSize( TSize( 0, 0 ) ); + } + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + const TBool transparentSoftkeys = + iExtension->iEnablePostingTransparency || + ( iCbaFlags & EEikCbaFlagTransparent ); + + TRgb rightSkColor; + TRgb leftSkColor; + + TInt error1 = 0; + TInt error2 = 0; + if ( transparentSoftkeys ) + { + rightSkColor = KRgbWhite; + leftSkColor = KRgbWhite; + } + else if ( AknStatuspaneUtils::IdleLayoutActive() ) + { + // Text #41 stacon area top softkey text in idle #0 + error1 = AknsUtils::GetCachedColor( skin, + rightSkColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG41 ); + + // Text #42 stacon area bottom softkey text in idle #0 + error2 = AknsUtils::GetCachedColor( skin, + leftSkColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG42 ); + } + else + { + // Text #39 stacon area top softkey text #0 + error1 = AknsUtils::GetCachedColor( skin, + rightSkColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG39 ); + + // Text #40 stacon area bottom softkey text #0 + error2 = AknsUtils::GetCachedColor( skin, + leftSkColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG40 ); + } + + if ( leftSoftkey->PressedDown() ) + { + leftSkColor.SetAlpha( KPressedDownAlphaValue ); + + AknsUtils::GetCachedColor( + skin, + leftSkColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG69 ); + + + if ( transparentSoftkeys ) + { + // alpha has no effect with display posting. + leftSkColor = TRgb( 128, 128, 128 ); + } + } + else if ( rightSoftkey->PressedDown() ) + { + rightSkColor.SetAlpha( KPressedDownAlphaValue ); + + AknsUtils::GetCachedColor( + skin, + rightSkColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG69 ); + + if ( transparentSoftkeys ) + { + // alpha has no effect with display posting. + rightSkColor = TRgb( 128, 128, 128 ); + } + } + + if( !error1 && !error2 ) + { + // Error ignored. + TRAP( error1, + AknLayoutUtils::OverrideControlColorL( *leftSoftkeyControl, + EColorLabelText, + leftSkColor ) ); + TRAP( error2, + AknLayoutUtils::OverrideControlColorL( *rightSoftkeyControl, + EColorLabelText, + rightSkColor ) ); + + if ( transparentSoftkeys ) + { + // outline color is black. + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( + *leftSoftkeyControl, + EColorControlBackground, + KRgbBlack ) ); + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( + *rightSoftkeyControl, + EColorControlBackground, + KRgbBlack ) ); + } + } + + if ( iRightPaneLabelFont ) + { + leftSoftkey->SetLabelFont( iRightPaneLabelFont ); + rightSoftkey->SetLabelFont( iRightPaneLabelFont ); + } + + DrawDeferred(); + } + + AknsUtils::RegisterControlPosition( this, TPoint( 0, 0 ) ); + } + + + +void CEikCba::SizeChangedInsideDialog() + { + // Give both LSK and RSK buttons half of the available space. + // + if ( iControlArray ) + { + TRect buttonRect1( Rect() ); + TRect buttonRect2( Rect() ); + + TInt width = ( buttonRect1.iBr.iX - buttonRect1.iTl.iX ) / 2 - 4; + + buttonRect1.iBr.iX = buttonRect1.iTl.iX + width; + buttonRect2.iTl.iX = buttonRect2.iBr.iX - width; + + if ( (*iControlArray)[KControlArrayCBAButton1Posn].iControl ) + { + (*iControlArray)[KControlArrayCBAButton1Posn].iControl->SetRect( buttonRect1 ); + } + + if ( (*iControlArray)[KControlArrayCBAButton2Posn].iControl ) + { + (*iControlArray)[KControlArrayCBAButton2Posn].iControl->SetRect( buttonRect2 ); + } + } + } + + +void CEikCba::SizeChangedInPopup() + { + TRAP_IGNORE( iExtension->UpdateSoftkeyFrameL( EFalse ) ); + + TAknLayoutRect layoutRect; + TRect rect ( Rect() ); + + // Button widths are calculated based on cba area width + // margin width is taken from layout + layoutRect.LayoutRect( + rect, + AknLayoutScalable_Avkon::popup_sk_window_g1( 0 ) ); + + TInt margin = layoutRect.Rect().iTl.iX - rect.iTl.iX; + TInt buttonWidth = ( rect.Width() - margin * 2 ) / 2; + TSize buttonSize ( buttonWidth, layoutRect.Rect().Height() ); + + iExtension->iLeftFrameOuterRect = TRect( + TPoint( rect.iTl.iX + margin, layoutRect.Rect().iTl.iY ), + buttonSize ); + iExtension->iRightFrameOuterRect = TRect( + TPoint( iExtension->iLeftFrameOuterRect.iBr.iX, + layoutRect.Rect().iTl.iY ), + TPoint( rect.iBr.iX - margin, layoutRect.Rect().iBr.iY ) ); + + layoutRect.LayoutRect( iExtension->iLeftFrameOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + iExtension->iLeftFrameInnerRect = layoutRect.Rect(); + UpdateLabels( ETrue ); + + layoutRect.LayoutRect( iExtension->iRightFrameOuterRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + iExtension->iRightFrameInnerRect = layoutRect.Rect(); + UpdateLabels( ETrue ); + + if ( iControlArray->Count() > KControlArrayCBAButtonMSKPosn ) + { + CCoeControl* msk = + (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl; + + if ( msk ) + { + msk->SetRect( TRect() ); + } + } + } + + +void CEikCba::UpdateFonts() + { + // Control pane: + // Use the layout dll to get the right font for the CBA. + TAknTextLineLayout layout( + AknLayoutScalable_Avkon::control_pane_t1( + Layout_Meta_Data::IsLandscapeOrientation() ? 2 : 0 ).LayoutLine() ); + if ( iCbaFlags & EEikCbaFlagOutlineFont ) + { + // Sets outline font property. + layout.iFont |= KOutlineFontMask; + } + const CFont* customfont = 0; + iLabelFont = AknLayoutUtils::FontFromId( layout.FontId(), customfont ); + + // Stacon pane: + TAknTextLineLayout staconTextLayout( + AknLayoutScalable_Avkon::control_bottom_pane_stacon_t1( 0 ).LayoutLine() ); + + if ( iCbaFlags & EEikCbaFlagOutlineFont ) + { + // Sets outline font property. + staconTextLayout.iFont |= KOutlineFontMask; + } + const CFont* staconCustomfont = 0; + iStaconLabelFont = AknLayoutUtils::FontFromId( staconTextLayout.FontId(), + staconCustomfont ); + + // Right pane: + TInt rightPaneTextVariety = 0; + + if ( iExtension->iEnablePostingTransparency || + ( iCbaFlags & EEikCbaFlagTransparent ) || ( iCbaFlags & EEikCbaFlagSemiTransparent ) ) + { + rightPaneTextVariety = 1; // Outline font used + } + + TAknTextLineLayout rightPaneTextLayout( + AknLayoutScalable_Avkon::sctrl_sk_bottom_pane_t1( + rightPaneTextVariety ).LayoutLine() ); + + if ( iCbaFlags & EEikCbaFlagOutlineFont ) + { + // Sets outline font property. + rightPaneTextLayout.iFont |= KOutlineFontMask; + } + const CFont* rightPaneCustomFont = 0; + iRightPaneLabelFont = + AknLayoutUtils::FontFromId( + rightPaneTextLayout.FontId(), rightPaneCustomFont ); + } + +// Enhanced CBA + +// ----------------------------------------------------------------------------- +// Used to offer list of commands for softkeys. +// @param aCommandList A list of command ids to be offered for sofkeys. +// @since 5.0 +// ----------------------------------------------------------------------------- +#ifdef RD_ENHANCED_CBA +EXPORT_C void CEikCba::OfferCommandListL(const RArray& aCommandList) + { + if( !iCommandTable ) + { + iCommandTable = CEikCommandTable::NewL(); + } + else + { + delete iCommandTable; + iCommandTable = NULL; + iCommandTable = CEikCommandTable::NewL(); + } + + TInt count = aCommandList.Count(); + + // Stack existing commands for possible leave while adding the new commands. + RArray previousIds; + CleanupClosePushL( previousIds ); + + // Store the existing commands. + for ( TInt i = 0; i < iControlArray->Count(); i++ ) + { + TEikGroupControl& groupCtrl=(*iControlArray)[i]; + previousIds.AppendL( groupCtrl.iId ); + } + + iCommandTable->Reset(); + + for ( TInt ii = 0; ii < count; ii++ ) + { + TInt resourceId( aCommandList[ii] ); + + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC( reader, resourceId ); + + TUint8 version( (TUint8)reader.ReadUint8() ); + TInt longCommandId( 0 ); + + CEikEnhancedCbaButton* button = new (ELeave) CEikEnhancedCbaButton; + CleanupStack::PushL( button ); + + if( version == EEikCbaButtonLink ) + { + TInt aButtonId = reader.ReadInt32(); // Read ENHANCED_CBA_BUTTON id from LLINK + TResourceReader linkReader; // reader for reading linked resource + iCoeEnv->CreateResourceReaderLC( linkReader, aButtonId ); + TUint8 ver( linkReader.ReadUint8() ); + + if( ver == EEikEnhancedCbaButton ) + { + button->ConstructFromResourceL( linkReader ); + } + CleanupStack::PopAndDestroy( ); // linkReader + } + else if( version == EEikEnhancedCbaButton ) + { + button->ConstructFromResourceL( reader ); + } + else // command version not regognized + { + CleanupStack::PopAndDestroy(2); // button and reader + continue; // go for next command + } + + iCommandTable->AddCommandL( button ); + + CleanupStack::Pop( button ); + CleanupStack::PopAndDestroy(); // reader + } + + for (TInt i = 0; i < KMaxButtonsInCommandTable + 1; i++) // +1 for scrollbar + { + if ( i != KControlArrayScrollBarPosn ) + { + CEikEnhancedCbaButton* button; + if( i > KControlArrayScrollBarPosn ) + { + button = iCommandTable->Command( i-1 ); + } + else + { + button = iCommandTable->Command( i ); + } + + if ( !button ) + { + button = new (ELeave) CEikEnhancedCbaButton; + button->SetTextBitmapMode( iExtension->iEnablePostingTransparency ); + CleanupStack::PushL( button ); + button->ConstructEmptyButtonL(); + } + else + { + CleanupStack::PushL( button ); + } + + TRAPD( errorcode, AddCommandToStackL( i, button->CommandId(), button->LabelText(), + NULL, NULL ) ); + + if ( errorcode ) // In case of error restore previous commands before leave + { + for ( TInt counter = 0; counter < i; counter++ ) + { + // Do not deal with the scroller as a CEikCbaButton; skip its index. + if (counter != KControlArrayScrollBarPosn) + { + // Following adjusts for the fact that the scroller command is + // missing from the previousIds array. Same index adjust as later on. + TInt indexInPreviousIds = counter; + if ( counter > 1 ) + { + indexInPreviousIds = counter - 1; + } + RemoveCommandFromStack( counter,previousIds[indexInPreviousIds] ); + } + } + + User::Leave( errorcode ); + } + CleanupStack::PopAndDestroy( button ); + } + } + + // Remove the original commands from the temporary store. +1 for scroll bar. + for ( TInt controlId = 0; controlId < KMaxButtonsInCommandTable + 1; controlId++ ) + { + if ( controlId != KControlArrayScrollBarPosn ) + { + TInt controlPosition = controlId; + if ( controlId > 1 ) + { + controlPosition--; + } + RemovePreviousCommand( controlId ); + } + } + + CleanupStack::PopAndDestroy(); // previousIds + } +#else // !RD_ENHANCED_CBA +EXPORT_C void CEikCba::OfferCommandListL(const RArray& /*aCommandList*/) + { + User::Leave( KErrNotSupported ); + } +#endif // RD_ENHANCED_CBA + +// ----------------------------------------------------------------------------- +// Used to offer list of commands for softkeys. +// @param aResourceId Id for CBA resource that defines enhanced cba buttons. +// @since 5.0 +// ----------------------------------------------------------------------------- +#ifdef RD_ENHANCED_CBA +EXPORT_C void CEikCba::OfferCommandListL(const TInt aResourceId) + { + if ( !iCommandTable ) // This is needed if cba was not constructed with enhanced cba. + { + iCommandTable = CEikCommandTable::NewL(); + } + + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader, aResourceId); + iCbaFlags = reader.ReadInt32(); + + TBool enhancedCba( EFalse ); + if ( ( iCbaFlags & EEikEnhancedButtonGroup ) == EEikEnhancedButtonGroup ) + { + enhancedCba = ETrue; + } + + __ASSERT_DEBUG( enhancedCba, Panic(EEikPanicCBAIsNotEnhancedCba) ); + + reader.ReadInt16(); // Skip width resource. + reader.ReadInt32(); // Skip related buttons resource. + + TInt count = reader.ReadInt16(); + + // Stack existing commands for possible leave while adding the new commands. + RArray previousIds; + CleanupClosePushL( previousIds ); + + // Store the existing commands. + for ( TInt i = 0; i < iControlArray->Count(); i++ ) + { + TEikGroupControl& groupCtrl = (*iControlArray)[i]; + previousIds.AppendL( groupCtrl.iId ); + } + + iCommandTable->Reset(); + + // Get new commands. + for ( TInt ii = 0; ii < count; ii++ ) + { + TUint8 version( (TUint8)reader.ReadUint8() ); + TInt commandId( 0 ); + TInt longCommandId( 0 ); + + CEikEnhancedCbaButton* button = new (ELeave) CEikEnhancedCbaButton; + button->SetTextBitmapMode( iExtension->iEnablePostingTransparency ); + CleanupStack::PushL( button ); + + if( version == EEikCbaButtonLink ) + { + TInt aButtonId = reader.ReadInt32(); // Read ENHANCED_CBA_BUTTON id from LLINK + TResourceReader linkReader; // reader for reading linked resource + iCoeEnv->CreateResourceReaderLC( linkReader, aButtonId ); + TUint8 ver( linkReader.ReadUint8() ); + + if( ver == EEikEnhancedCbaButton ) + { + button->ConstructFromResourceL( linkReader ); + } + + CleanupStack::PopAndDestroy(); // linkReader + } + else if( version == EEikEnhancedCbaButton ) + { + button->ConstructFromResourceL( reader ); + } + else + { + CleanupStack::PopAndDestroy( button ); + continue; // jump over the rest + } + + iCommandTable->AddCommandL( button ); + + CleanupStack::Pop( button ); + } + + CleanupStack::PopAndDestroy(); // reader + + for (TInt i = 0; i < KMaxButtonsInCommandTable + 1; i++) // +1 for scrollbar + { + if ( i != KControlArrayScrollBarPosn ) + { + CEikEnhancedCbaButton* button; + if( i > KControlArrayScrollBarPosn ) + { + button = iCommandTable->Command( i - 1 ); + } + else + { + button = iCommandTable->Command( i ); + } + + if ( !button ) + { + button = new (ELeave) CEikEnhancedCbaButton; + button->SetTextBitmapMode( iExtension->iEnablePostingTransparency ); + CleanupStack::PushL( button ); + button->ConstructEmptyButtonL(); + } + else + { + CleanupStack::PushL( button ); + } + + TRAPD( errorcode, AddCommandToStackL( i, button->CommandId(), button->LabelText(), + NULL, NULL ) ); + + if ( errorcode ) // In case of error restore previous commands before leave. + { + for ( TInt counter = 0; counter < i; counter++ ) + { + // Do not deal with the scroller as a CEikCbaButton; skip its index. + if ( counter != KControlArrayScrollBarPosn ) + { + // Following adjusts for the fact that the scroller command is + // missing from the previousIds array. Same index adjust as later on. + TInt indexInPreviousIds = counter; + if ( counter > 1 ) + { + indexInPreviousIds = counter - 1; + } + RemoveCommandFromStack( counter, previousIds[indexInPreviousIds] ); + } + } + User::Leave( errorcode ); + } + CleanupStack::PopAndDestroy( button ); + } + } + + // Remove the original commands from the temporary store. +1 for scroll bar. + for ( TInt controlId = 0; controlId < KMaxButtonsInCommandTable + 1; controlId++ ) + { + if ( controlId != KControlArrayScrollBarPosn ) + { + TInt controlPosition=controlId; + if ( controlId > 1 ) + { + controlPosition--; + } + + RemovePreviousCommand( controlId ); + } + } + + CleanupStack::PopAndDestroy(); // previousIds + } +#else // !RD_ENHANCED_CBA +EXPORT_C void CEikCba::OfferCommandListL(const TInt /*aResourceId*/) + { + User::Leave( KErrNotSupported ); + } +#endif // RD_ENHANCED_CBA + +// ----------------------------------------------------------------------------- +// Used to check if a certain command have been approved to the current command set. +// @param aCommandId The id for command which existence should be checked. +// @since 5.0 +// ----------------------------------------------------------------------------- +#ifdef RD_ENHANCED_CBA +EXPORT_C TBool CEikCba::IsCommandInGroup(const TInt aCommandId) const + { + return ButtonById(aCommandId) ? ETrue : EFalse; // check the iControlArray + } +#else // !RD_ENHANCED_CBA +EXPORT_C TBool CEikCba::IsCommandInGroup(const TInt /*aCommandId*/) const + { + return EFalse; + } +#endif // RD_ENHANCED_CBA + +// ----------------------------------------------------------------------------- +// Replace existing command with a new command +// @param aCommandId Id for command that should be replaced. +// @param aResourceId Resource id for new enhanced cba button. +// @since 5.0 +// ----------------------------------------------------------------------------- +#ifdef RD_ENHANCED_CBA +EXPORT_C void CEikCba::ReplaceCommand(const TInt aReplaceCommandId, const TInt aResourceId) + { + TInt index = IndexById( aReplaceCommandId ); + TRAPD(err, SetCommandL( index, aResourceId ) ); + } +#else +EXPORT_C void CEikCba::ReplaceCommand(const TInt /*aReplaceCommandId*/, const TInt /*aResourceId*/) + { + } +#endif // RD_ENHANCED_CBA + +void CEikCba::HandleControlEventL( CCoeControl* aControl, TCoeEvent aEventType ) + { + if ( !iFlags.IsSet( ECbaInsideDialog ) ) + { + //User::Panic( _L( "CBA inside dialog" ), KErrNotSupported ); + return; + } + + if ( aEventType == EEventStateChanged ) + { + TInt command = NULL; + + if ( aControl == (*iControlArray)[KControlArrayCBAButton1Posn].iControl ) + { + command = (*iControlArray)[KControlArrayCBAButton1Posn].iId; + } + else if ( aControl == (*iControlArray)[KControlArrayCBAButton2Posn].iControl ) + { + command = (*iControlArray)[KControlArrayCBAButton2Posn].iId; + } + + // CAknButton sends control event to CEikCba upon pointer event, + // while also increasing it's state value. Because of the way + // CAknButton is used as softkey control, and it's states as stack + // support, we must revert the state back here. + CAknButton* button = static_cast( aControl ); + TInt state( button->StateIndex() ); + if ( state > 0 ) + { + state--; + button->SetCurrentState( state, EFalse ); + } + + + if( command ) + { + iCommandObserver->ProcessCommandL( command ); + } + } + } + + +void CEikCba::MakeVisible( TBool aVisible ) + { + if ( aVisible ) + { + TBool redrawNeeded( EFalse ); + + if ( AknLayoutUtils::PenEnabled() ) + { + CEikCbaButton* leftSK = static_cast( + (*iControlArray)[KControlArrayCBAButton1Posn].iControl ); + CEikCbaButton* rightSK = static_cast( + (*iControlArray)[KControlArrayCBAButton2Posn].iControl ); + CEikCbaButton* middleSK = NULL; + + if ( iMSKset && AknLayoutUtils::MSKEnabled() ) + { + middleSK = + static_cast( + (*iControlArray)[KControlArrayCBAButtonMSKPosn].iControl ); + } + + if ( leftSK && leftSK->PressedDown() ) + { + leftSK->SetPressedDown( EFalse ); + redrawNeeded = ETrue; + } + + if ( rightSK && rightSK->PressedDown() ) + { + rightSK->SetPressedDown( EFalse ); + redrawNeeded = ETrue; + } + + if ( middleSK && middleSK->PressedDown() ) + { + middleSK->SetPressedDown( EFalse ); + redrawNeeded = ETrue; + } + + if ( redrawNeeded ) + { + SizeChanged(); + } + } + + if ( iFlags[ECbaChangeRecordedSkin] ) + { + DoSkinChange(); + } + + if ( iFlags[ECbaChangeRecordedLayout] ) + { + DoLayoutChange(); + redrawNeeded = ETrue; + } + + if ( iFlags[ECbaChangeRecordedColor] ) + { + DoColorChange(); + } + + TBool isVisible = IsVisible(); + CEikControlGroup::MakeVisible( aVisible ); + + if ( redrawNeeded || !isVisible || IsEmpty() ) + { + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + DrawDeferred(); + } + else + { + DrawNow(); + } + } + } + else + { + Window().ClearRedrawStore(); + CEikControlGroup::MakeVisible( aVisible ); + } + + ReportContentChangedEvent(); + } + + +// ----------------------------------------------------------------------------- +// Sets layer images and rects. +// @since 5.0 +// ----------------------------------------------------------------------------- +void CEikCba::DoSetLayers( const TAknsItemID& aIID ) + { + // Skin background is not drawn by embedded CBA. + if ( iFlags.IsSet( ECbaEmbedded ) ) + { + return; + } + + TAknLayoutRect cbarect; + TRect screen; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen ); + + TAknWindowComponentLayout applicationWindow( + AknLayoutScalable_Avkon::application_window( 0 ) ); + + TBool isLandscape( Layout_Meta_Data::IsLandscapeOrientation() ); + TBool rightPaneActive( IsAreaSideRightPaneActive() ); + TBool idleLayout( AknStatuspaneUtils::IdleLayoutActive() ); + + if ( rightPaneActive ) + { + cbarect.LayoutRect( + screen, + DoCompose( + applicationWindow, + AknLayoutScalable_Avkon::area_side_right_pane( 0 ) ).LayoutLine() ); + } + else + { + // We must check for landscape mode bottom SKs + TInt bottomPaneVariety = 1; + + if ( isLandscape ) + { + // In flat iBgContext is used and flat is "landscape". + bottomPaneVariety = 6; + } + + TAknWindowComponentLayout bottomArea( + AknLayoutScalable_Avkon::area_bottom_pane( bottomPaneVariety ) ); + TAknWindowComponentLayout controlPane( + AknLayoutScalable_Avkon::control_pane() ); + controlPane = DoCompose( + applicationWindow, + DoCompose( + bottomArea, controlPane ) ); + cbarect.LayoutRect( screen, controlPane.LayoutLine() ); + } + + TRect cbaRect( cbarect.Rect() ); + + TAknsItemID myIID( iBgIID ); + TAknsItemID maskIID( KAknsIIDNone ); + + if ( AknLayoutUtils::PenEnabled() ) + { + // Widescreen landscape layout or touch portrait. + + // Empty the layers. + for ( TInt i = 0; i < ECbaLayerN; i++ ) + { + iMLBgContext->SetLayerImage( i, KAknsIIDNone ); + } + + TInt currentBgIIDMinor( aIID.iMinor ); + if ( aIID == KAknsIIDNone ) + { + currentBgIIDMinor = iBgIID.iMinor; + } + + // Right pane CBA areas don't have their own skin + // backgrounds, so the screen background is used + // and correct ID is mapped here. + switch ( currentBgIIDMinor ) + { + case EAknsMinorNone: + { + if ( rightPaneActive ) + { + myIID = idleLayout ? KAknsIIDQsnBgScreenIdle : + KAknsIIDQsnBgScreen; + } + else + { + myIID = idleLayout ? KAknsIIDQsnBgAreaControlIdle : + KAknsIIDQsnBgAreaControl; + } + break; + } + case EAknsMinorQsnBgAreaControl: + default: + { + if ( rightPaneActive ) + { + myIID = idleLayout ? KAknsIIDQsnBgScreenIdle : + KAknsIIDQsnBgScreen; + } + else + { + myIID = idleLayout ? KAknsIIDQsnBgAreaControlIdle : + KAknsIIDQsnBgAreaControl; + } + break; + } + case EAknsMinorQsnBgAreaControlPopup: + { + if ( rightPaneActive ) + { + myIID = idleLayout ? KAknsIIDQsnBgScreenIdle : + KAknsIIDQsnBgScreen; + } + else + { + myIID = idleLayout ? KAknsIIDQsnBgAreaControlIdle : + KAknsIIDQsnBgAreaControlPopup; + } + break; + } + case EAknsMinorQsnBgAreaControlIdle: + { + if ( rightPaneActive ) + { + myIID = idleLayout ? KAknsIIDQsnBgScreenIdle : + KAknsIIDQsnBgScreen; + } + else + { + myIID = idleLayout ? KAknsIIDQsnBgAreaControlIdle : + KAknsIIDQsnBgAreaControl; + } + break; + } + case EAknsMinorQsnBgAreaControlMp: + { + myIID = rightPaneActive ? KAknsIIDQsnBgScreenMp : + KAknsIIDQsnBgAreaControlMp; + break; + } + } + if ( idleLayout && iExtension && !( iExtension->iWallpaperInUse == 0 )) + { + maskIID = KAknsIIDQgnIndiSctrlSkMaskRightPrt; + } + else + { + maskIID = rightPaneActive ? KAknsIIDQgnGrafBgLscBottomMaskIcon : + KAknsIIDQgnGrafBgPrtBottomMaskIcon; + } + + if ( idleLayout ) + { + if ( iExtension && iExtension->iWallpaperInUse == 0 ) + { + iMLBgContext->SetLayerImage( ECbaLayerWallpaper, myIID ); + iMLBgContext->SetLayerRect( + ECbaLayerWallpaper, rightPaneActive ? screen : cbaRect ); + } + else + { + iMLBgContext->SetLayerImage( ECbaLayerWallpaper, KAknsIIDWallpaper ); + iMLBgContext->SetLayerRect( ECbaLayerWallpaper, screen ); + } + } + else + { + iMLBgContext->SetLayerImage( ECbaLayerWallpaper, KAknsIIDNone ); + maskIID = KAknsIIDNone; + } + + iMLBgContext->SetLayerImage( ECbaLayerBackground, myIID ); + iMLBgContext->SetLayerRect( + ECbaLayerBackground, rightPaneActive ? screen : cbaRect ); + + if (iExtension && + (!(iExtension->iBackgroundMaskID == maskIID && iExtension->iCbaRect == cbaRect) || + iExtension->iIfSkinChanged || + iExtension->iBackgroundMaskID == KAknsIIDNone)) + { + TRAP_IGNORE( iMLBgContext->SetLayerMaskAndSizeL( + maskIID, rightPaneActive ? screen : cbaRect ) ); + iExtension->iBackgroundMaskID = maskIID; + iExtension->iCbaRect = cbaRect; + } + } + else // non-nHD layout + { + if ( idleLayout ) + { + if ( aIID == KAknsIIDNone ) + { + myIID = iBgIID; + } + + iMLBgContext->SetLayerImage( ECbaLayerWallpaper, KAknsIIDWallpaper ); + iMLBgContext->SetLayerRect( ECbaLayerWallpaper, screen ); + iMLBgContext->SetLayerImage( ECbaLayerBackground, myIID ); + iMLBgContext->SetLayerRect( ECbaLayerBackground, cbaRect ); + + if ( isLandscape ) + { + maskIID = KAknsIIDQgnGrafBgLscSideRightMaskIcon; + } + else + { + maskIID = KAknsIIDQgnGrafBgPrtBottomMaskIcon; + } + } + else + { + if ( aIID == KAknsIIDNone ) + { + myIID = KAknsIIDQsnBgAreaControl; + } + + iMLBgContext->SetLayerImage( ECbaLayerBackground, myIID ); + iMLBgContext->SetLayerImage( ECbaLayerWallpaper, KAknsIIDNone ); + iMLBgContext->SetLayerRect( ECbaLayerBackground, cbaRect ); + } + + TRAP_IGNORE( iMLBgContext->SetLayerMaskAndSizeL( maskIID, cbaRect ) ); + } + + DrawDeferred(); + } + + +void CEikCba::LayoutControl( CCoeControl* aControl, const TRect& aRect ) + { + if ( !iFlags.IsSet( ECbaInsideDialog ) ) + { + TRect rect( aRect ); + // aid_value_unit2 is 10ux10u rectangle. + TAknWindowComponentLayout unit( AknLayoutScalable_Avkon::aid_value_unit2() ); + // Move 0.5 units to right and down. + TInt delta = unit.LayoutLine().iW / 10 / 2; + if ( ( (CEikCbaButton*)aControl )->PressedDown() ) + { + rect.Move( delta, delta ); + } + aControl->SetRect( rect ); + aControl->ComponentControl( 0 )->SetRect( rect ); + } + } + +void CEikCba::BroadcastPostingTransparency( TBool aEnable ) + { + // Communicate change to CBA buttons. + for ( TInt i = 0; i < iControlArray->Count(); i++ ) + { + if ( i != KControlArrayScrollBarPosn ) // To avoid tinkering with scrollbar. + { + TEikGroupControl& gCtrl = iControlArray->At( i ); + CEikCbaButton* button = dynamic_cast( gCtrl.iControl ); + if ( button ) + { + button->SetTextBitmapMode( aEnable ); + } + } + } + } + + +// --------------------------------------------------------------------------- +// CEikCba::SetFadeState +// Sets the CBA faded if it's contents are empty. +// --------------------------------------------------------------------------- +// +void CEikCba::SetFadeState() + { + TBool canBeFaded = + IsEmpty() && !( ( iCbaFlags & EEikCbaFlagTransparent ) + || ( iExtension && iExtension->iEnablePostingTransparency ) ); + + // No unfading when system is faded + if ( !( !canBeFaded + && static_cast( iCoeEnv->AppUi() )->IsFaded() ) ) + { + Window().SetFaded( canBeFaded, RWindowTreeNode::EFadeIncludeChildren ); + } + } + + +// --------------------------------------------------------------------------- +// CEikCba::UpdateLabels +// Updates softkey labels in case of embedded softkeys. +// --------------------------------------------------------------------------- +// +void CEikCba::UpdateLabels( TBool aDrawDeferred ) + { + if ( iControlArray->Count() != 0) + { + CCoeControl *leftSoftkey = ( *iControlArray ) + [ KControlArrayCBAButton1Posn ].iControl; + CCoeControl *rightSoftkey = ( *iControlArray ) + [ KControlArrayCBAButton2Posn ].iControl; + + if ( !( ( ( CEikCbaButton* ) leftSoftkey )->IsImageOn() ) ) + { + TAknTextLineLayout textLayout( + AknLayoutScalable_Avkon::popup_sk_window_t1( 0 ).LayoutLine() ); + + if ( iCbaFlags & EEikCbaFlagOutlineFont ) + { + textLayout.iFont |= KOutlineFontMask; + } + + AknLayoutUtils::LayoutLabel( ( CEikLabel* ) + leftSoftkey->ComponentControl( 0 ), + Rect(), + textLayout ); + + LayoutControl( (CEikCbaButton*)leftSoftkey, + leftSoftkey->ComponentControl( 0 )->Rect() ); + ((CEikCbaButton*)leftSoftkey)->TruncateLabelText(); + } + + if ( !( ( ( CEikCbaButton* ) rightSoftkey )->IsImageOn() ) ) + { + TAknTextLineLayout textLayout( + AknLayoutScalable_Avkon::popup_sk_window_t1_copy1( 0 ).LayoutLine() ); + + if ( iCbaFlags & EEikCbaFlagOutlineFont ) + { + textLayout.iFont |= KOutlineFontMask; + } + AknLayoutUtils::LayoutLabel((CEikLabel*) + rightSoftkey->ComponentControl( 0 ), + Rect(), + textLayout ); + LayoutControl( (CEikCbaButton*)rightSoftkey, + rightSoftkey->ComponentControl( 0 )->Rect() ); + ((CEikCbaButton*)rightSoftkey)->TruncateLabelText(); + } + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + + TRgb leftColor; + TRgb rightColor; + + TInt errorl; + TInt errorr; + + if ( iPopupVisible ) + { + errorl = AknsUtils::GetCachedColor( + skin, + leftColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG17 ); + + errorr = AknsUtils::GetCachedColor( + skin, + rightColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG18 ); + } + else + { + errorl = AknsUtils::GetCachedColor( + skin, + leftColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG13 ); + + errorr = AknsUtils::GetCachedColor( + skin, + rightColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG14 ); + } + + if ( ((CEikCbaButton*)leftSoftkey)->PressedDown() ) + { + leftColor.SetAlpha( KPressedDownAlphaValue ); + + AknsUtils::GetCachedColor( + skin, + leftColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG69 ); + } + else if ( ((CEikCbaButton*)rightSoftkey)->PressedDown() ) + { + rightColor.SetAlpha( KPressedDownAlphaValue ); + + AknsUtils::GetCachedColor( + skin, + rightColor, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG69 ); + } + + if( !errorl && !errorr ) + { + // Error ignored + TRAP( errorl, AknLayoutUtils::OverrideControlColorL( + *leftSoftkey, + EColorLabelText, + leftColor) ); + + TRAP( errorr, AknLayoutUtils::OverrideControlColorL( + *rightSoftkey, + EColorLabelText, + rightColor) ); + } + + if ( aDrawDeferred ) + { + DrawDeferred(); + } + } + } + + +// ----------------------------------------------------------------------------- +// EikSoftkeyPostingTransparency::MakeTransparent +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt EikSoftkeyPostingTransparency::MakeTransparent( + CEikButtonGroupContainer& aButtonGroupContainer, + TBool aEnable ) + { + CEikCba* cba = dynamic_cast( aButtonGroupContainer.ButtonGroup() ); + TInt ret = KErrNone; + if ( cba ) + { + if ( aEnable && ( cba->ButtonGroupFlags() & EEikCbaFlagTransparent ) ) + { + // EikSoftkeyPostingTransparency is not supported if + // EEikCbaFlagTransparent is enabled + ret = KErrArgument; + } + else + { + cba->EnablePostingTransparency( aEnable ); + } + } + return ret; + } + +// ----------------------------------------------------------------------------- +// CEikCba::EnablePostingTransparency +// +// ----------------------------------------------------------------------------- +// +void CEikCba::EnablePostingTransparency( TBool aEnable ) + { + if ( iExtension ) + { + if ( iExtension->iEnablePostingTransparency != aEnable ) + { + iExtension->iEnablePostingTransparency = aEnable; + + UpdateFonts(); + + if ( !aEnable ) + { + delete iExtension->iLskPostingOverlayBitmap; + iExtension->iLskPostingOverlayBitmap = NULL; + delete iExtension->iRskPostingOverlayBitmap; + iExtension->iRskPostingOverlayBitmap = NULL; + + // Update label text color. SizeChanged + // will not call BroadcastPostingTransparency in this case. + // It has to be called directly from here. + SizeChanged(); + + BroadcastPostingTransparency( EFalse ); + } + else + { + // Update background bitmaps. SizeChanged + // will also call BroadcastPostingTransparency. + SizeChanged(); + } + + DrawDeferred(); + } + } + } + + +// --------------------------------------------------------------------------- +// CEikCba::IsEmpty +// Checks if the CBA has no commands. +// --------------------------------------------------------------------------- +// +EXPORT_C TBool CEikCba::IsEmpty() const + { + TBool isEmpty( ETrue ); + + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + // Not supported for full screen query. + isEmpty = EFalse; + } + else + { + for ( TInt i = 0; i < iControlArray->Count(); i++ ) + { + if ( i != KControlArrayScrollBarPosn ) // Do not take scrollbar into account. + { + TEikGroupControl& gCtrl = iControlArray->At( i ); + if ( gCtrl.iId != EEikBidBlank && + gCtrl.iId != EAknSoftkeyEmpty && + ( gCtrl.iId < 0 || gCtrl.iId > 2 ) ) + { + isEmpty = EFalse; + } + else + { + if ( gCtrl.iControl && + ( !(static_cast(gCtrl.iControl))->IsEmptyText() + || (static_cast(gCtrl.iControl))->IsImageOn() ) + ) + { + isEmpty = EFalse; + } + } + } + } + } + + return isEmpty; + } + + +// --------------------------------------------------------------------------- +// CEikCba::Flags +// Returns flags. +// --------------------------------------------------------------------------- +// +TBitFlags CEikCba::Flags() + { + return iFlags; + } + + +// --------------------------------------------------------------------------- +// CEikCba::SetContentObserver +// Sets content observer. +// --------------------------------------------------------------------------- +// +void CEikCba::SetContentObserver( TCallBack aCallBack ) + { + if ( iExtension ) + { + iExtension->iContentObserver = aCallBack; + } + } + + +// --------------------------------------------------------------------------- +// CEikCba::ReportContentChangedEvent +// Reports state changed event if cba changed from empty to non-empty +// or vice versa. +// --------------------------------------------------------------------------- +// +void CEikCba::ReportContentChangedEvent() + { + if ( ItemSpecificSoftkey() ) + { + UpdateItemSpecificSoftkey( + iExtension->Active() && !Window().IsFaded() ); + } + + if ( !iFlags.IsSet( ECbaEmbedded ) ) + { + return; + } + + TBool isEmpty( !IsVisible() || IsEmpty() ); + TBool reportStateChanged( EFalse ); + if ( !isEmpty && !iFlags.IsSet( ECbaHasContent ) ) + { + reportStateChanged = ETrue; + iFlags.Set( ECbaHasContent ); + } + else if ( isEmpty && iFlags.IsSet( ECbaHasContent ) ) + { + reportStateChanged = ETrue; + iFlags.Clear( ECbaHasContent ); + } + + // Report state changed event if changed from empty to non-empty + // or vice versa. Dialog knows to increase its height so that + // also cba is visible + if ( reportStateChanged ) + { + Window().Invalidate(); + if ( iExtension && iExtension->iContentObserver.iFunction ) + { + iExtension->iContentObserver.CallBack(); // return value ignored + } + } + } + +// --------------------------------------------------------------------------- +// CEikCba::DrawEmbeddedSoftkey +// Draws embedded softkey +// --------------------------------------------------------------------------- +// +void CEikCba::DrawEmbeddedSoftkey( TEikGroupControl& aGroupControl, + const TRect& aRect, + CWindowGc& aGc, + CFbsBitmap* /*aMask*/ ) const + { + CEikCbaButton* button = + static_cast( aGroupControl.iControl ); + + TAknLayoutRect layoutRect; + TRect innerRect; + layoutRect.LayoutRect( aRect, + AknLayoutScalable_Avkon::bg_sctrl_sk_pane_g1() + .LayoutLine() ); + innerRect = layoutRect.Rect(); + + + if( button->PressedDown() ) // draw PressedFrame + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + aGc, + aRect, + innerRect, + KAknsIIDQgnFrSctrlSkButtonPressed, + KAknsIIDQgnFrSctrlSkButtonCenterPressed ); + } + else // draw Frame + { + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + aGc, + aRect, + innerRect, + KAknsIIDQgnFrSctrlSkButton, + KAknsIIDQgnFrSctrlSkButtonCenter); + } + } + +TBool CEikCba::UpdateIconL() + { + if ( iFlags.IsSet( ECbaInsideDialog ) ) + { + return EFalse; + } + + if ( !iExtension->iIfMskIconSet || + !MskAllowed() ) + { + return EFalse; + } + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + if ( !skin ) + { + return EFalse; + } + + TEikGroupControl &gCtrl = iControlArray->At( KControlArrayCBAButtonMSKPosn ); + + CEikCbaButton *button = static_cast( gCtrl.iControl ); + if ( !button ) + { + return EFalse; + } + + CFbsBitmap *bitmap = NULL; + CFbsBitmap *mask = NULL; + + TAknLayoutRect qgn_graf_sk_msk; + TRect rect; + qgn_graf_sk_msk.LayoutRect( + rect, + AknLayoutScalable_Avkon::control_pane_g4( 0 ).LayoutLine() ); + + TSize iconSize( qgn_graf_sk_msk.Rect().Width(), + qgn_graf_sk_msk.Rect().Height() ); + + AknsUtils::CreateIconL( + skin, + iExtension->iMSKSkinID, + bitmap, + mask, + *iExtension->iBmpFile, + iExtension->iBmp, + iExtension->iBmpM ); + + if ( bitmap ) // Bitmap not set -> do not use image. + { + AknIconUtils::DisableCompression( bitmap ); + AknIconUtils::DisableCompression( mask ); + AknIconUtils::SetSize( bitmap, iconSize ); + CEikImage* image = new (ELeave) CEikImage; + image->SetPicture( bitmap, mask ); + + // Transfers ownership of the image (image owns bitmap and mask). + button->SetImage( *image ); + + SizeChanged(); + + button->DrawNow(); + } + else + { + button->ReplaceImageByLabel(); // remove old image + } + + button->SetContainerWindowL( *this ); + + return ETrue; + + } + + +// --------------------------------------------------------------------------- +// Checks if the middle softkey should be used. +// Should be used with the SetMSKVisibility-method to set MSK visibility +// when on layout changes etc. +// --------------------------------------------------------------------------- +// +TBool CEikCba::MskAllowed() const + { + return ( iMSKEnabledInPlatform && + AknLayoutUtils::MSKEnabled() && + IsMskEnabledLayoutActive() ); + } + + +// --------------------------------------------------------------------------- +// CEikCba::SoftkeyStatusChangeAllowed +// Returns ETrue if softkey status change is allowed. +// --------------------------------------------------------------------------- +// +TBool CEikCba::SoftkeyStatusChangeAllowed( + TInt aSoftkeyPosition, TBool aDisabled ) + { + TBool allowChange( ETrue ); + if ( aSoftkeyPosition == KControlArrayCBAButton1Posn ) + { + if ( aDisabled ) + { + iFlags.Set( ECbaItemSoftkeyDisabledByClient ); + } + else + { + iFlags.Clear( ECbaItemSoftkeyDisabledByClient ); + if ( iFlags.IsSet( ECbaItemSoftkeyDisabled ) ) + { + allowChange = EFalse; + } + } + } + return allowChange; + } + + +// --------------------------------------------------------------------------- +// CEikCba::ItemSpecificSoftkey +// Returns item specific softkey control if it state should be updated. +// --------------------------------------------------------------------------- +// +TEikGroupControl* CEikCba::ItemSpecificSoftkey() const + { + TEikGroupControl* lsk( NULL ); + if ( iFlags.IsSet( ECbaItemSpecificSoftkeyInUse ) ) + { + TEikGroupControl& leftSoftkey = + ( *iControlArray ) [ KControlArrayCBAButton1Posn ]; + if ( leftSoftkey.iId != EAknSoftkeyOptions + || iFlags.IsSet( ECbaItemSoftkeyDisabled ) ) + { + lsk = &leftSoftkey; + } + } + return lsk; + } + + +// --------------------------------------------------------------------------- +// CEikCba::UpdateItemSpecificSoftkey +// Updates item specific softkey. +// --------------------------------------------------------------------------- +// +void CEikCba::UpdateItemSpecificSoftkey( TBool aVisibleCollection ) + { + if ( iFlags.IsSet( ECbaSingleClickEnabled ) + && iExtension && iExtension->iItemActionMenu ) + { + TEikGroupControl* leftSk = ItemSpecificSoftkey(); + if ( leftSk ) + { + TBool enableSk( leftSk->iId == EAknSoftkeyOptions || + iExtension->iItemActionMenu->CollectionSoftkeyVisible( + aVisibleCollection ) ); + UpdateItemSpecificSoftkey( *leftSk->iControl, enableSk ); + } + } + } + + +// --------------------------------------------------------------------------- +// CEikCba::UpdateItemSpecificSoftkey +// Updates item specific softkey. +// --------------------------------------------------------------------------- +// +void CEikCba::UpdateItemSpecificSoftkey( CCoeControl& aControl, TBool aEnable ) + { + TBool skEnabled( aControl.IsVisible() && !aControl.IsDimmed() ); + TBool changeState( EFalse ); + if ( !aEnable ) + { + iFlags.Set( ECbaItemSoftkeyDisabled ); + if ( skEnabled ) + { + changeState = ETrue; + } + } + else + { + iFlags.Clear( ECbaItemSoftkeyDisabled ); + if ( !skEnabled + && iFlags.IsClear( ECbaItemSoftkeyDisabledByClient ) ) + { + changeState = ETrue; + } + } + if ( changeState ) + { + if ( !iFlags.IsSet( ECbaInsideDialog ) ) + { + aControl.MakeVisible( aEnable ); + } + else + { + aControl.SetDimmed( !aEnable ); + aControl.DrawDeferred(); + } + } + } + + +// +// class CEikCbaButton +// + +CEikCbaButton::~CEikCbaButton() + { + AKNTASHOOK_REMOVE(); + delete iLabel; + if ( iImage ) + { + iImage->SetMask( iMask ); + } + delete iImage; + delete iSfeMask; + delete iButtonOptions; + delete iText; + + } + +void CEikCbaButton::ConstructL(TGulAlignmentValue aAlignment) + { + iLabel = new(ELeave) CEikLabel; + iPressedDown = EFalse; + iLabel->SetBufferReserveLengthL(KMaxCbaLabelLength); + UpdateLabelText(TPtrC()); + iLabel->SetAlignment(aAlignment); + + iButtonOptions = new(ELeave) CArrayFixFlat(1); + iText = new(ELeave) CDesCArrayFlat(1); + + if ( iUseTextBitmap ) + { + iLabel->MakeVisible( EFalse ); + } + AKNTASHOOK_ADDL( this, "CEikCbaButton" ); + } + +void CEikCbaButton::AddCommandL(const TDesC& aText) + { + UpdateLabelText(aText); + } + +struct STempCleanup + { + CDesCArray* iText; + CArrayFix* iButtonOptions; + }; + +LOCAL_C void CleanupTemp(TAny* aPtr) + { + STempCleanup& temp = *(STempCleanup*)aPtr; + const TInt count = temp.iText->Count(); + if (temp.iButtonOptions->Count() == count) + { + temp.iButtonOptions->Delete(count - 1); + } + temp.iText->Delete(count - 1); + } + +void CEikCbaButton::PushCommandL(TInt aCommandId,const TDesC& aText) + { + if (!iButtonOptions) + { + iButtonOptions = new(ELeave) CArrayFixFlat(1); + } + if (!iText) + { + iText = new(ELeave) CDesCArrayFlat(1); + } + + iText->AppendL(iFullLabelText); + + STempCleanup temp; + SButtonOptions options; + temp.iText = iText; + temp.iButtonOptions = iButtonOptions; + CleanupStack::PushL(TCleanupItem(CleanupTemp,&temp)); + options.iCommandId = aCommandId; + options.iDimmed = iLabel->IsDimmed(); + iLabel->SetDimmed(EFalse); + iButtonOptions->AppendL(options); + UpdateLabelText(aText); + CleanupStack::Pop(); // temp + } + +TInt CEikCbaButton::PopCommand() + { + if (!iButtonOptions) + { + return -1; + } + + TInt count = iButtonOptions->Count(); + --count; + + if (count < 0) + { + return -1; + } + + const SButtonOptions buttonOptions = (*iButtonOptions)[count]; + iButtonOptions->Delete(count); + TPtrC text = (*iText)[count]; + UpdateLabelText(text); + iText->Delete(count); + if (iButtonOptions->Count() == 0) + { + delete iButtonOptions; + iButtonOptions = NULL; + delete iText; + iText = NULL; + } + iLabel->SetDimmed(buttonOptions.iDimmed); + if (!iDoImage) + { + iLabel->DrawDeferred(); + } + else + { + iImage->DrawNow(); + } + return buttonOptions.iCommandId; + } + +void CEikCbaButton::RemoveCommand(TInt aCommandId) + { + if (!iButtonOptions) + { + return; + } + TInt index = IndexFromCommandId(aCommandId); + if (index != KErrNotFound) + { + iButtonOptions->Delete(index); + iText->Delete(index); + if (iButtonOptions->Count() == 0) + { + delete iButtonOptions; + iButtonOptions = NULL; + delete iText; + iText = NULL; + } + } + } + +void CEikCbaButton::RemovePreviousCommand() + { + if (!iButtonOptions) + { + return; + } + TInt index = iButtonOptions->Count() - 2; + if (index >= 0) + { + iButtonOptions->Delete(index); + iText->Delete(index); + } + } + +TInt CEikCbaButton::IndexFromCommandId(TInt aCommandId) + { + TInt index; + TKeyArrayFix key(0, ECmpTInt); + SButtonOptions options; + options.iCommandId = aCommandId; + if (iButtonOptions->Find(options, key, index) == KErrNone) + { + return index; + } + else + { + return KErrNotFound; + } + } + +void CEikCbaButton::SetContainerWindowL(const CCoeControl& aContainer) + { + CCoeControl::SetContainerWindowL(aContainer); + if (!iDoImage) + { + iLabel->SetContainerWindowL(aContainer); + } + else + { + iImage->SetContainerWindowL(aContainer); + } + } + +void CEikCbaButton::ConstructFromResourceL(TResourceReader& aReader, TGulAlignmentValue anAlignment) + { + ConstructL(anAlignment); + UpdateLabelText(aReader.ReadTPtrC()); + aReader.ReadTPtrC(); // bmp filename + aReader.ReadInt16(); // bmp id + aReader.ReadInt16(); // bmp mask id + } + +TSize CEikCbaButton::MinimumSize() + { + if (!iDoImage) + { + return iLabel->MinimumSize(); + } + else + { + return iImage->MinimumSize(); + } + } + +TInt CEikCbaButton::CountComponentControls() const + { + return 1; + } + +CCoeControl* CEikCbaButton::ComponentControl(TInt aIndex) const + { + if (aIndex==0) + { + if (!iDoImage) + { + return iLabel; + } + else + { + // If SfeMask is available, then check the effect state (iPressedDown). + if ( iSfeMask ) + { + if ( iPressedDown ) + { + iImage->SetMask( iSfeMask ); + } + else + { + iImage->SetMask( iMask ); + } + } + return iImage; + } + } + return 0; + } + + +// --------------------------------------------------------------------------- +// Handles size change events for CBA button. +// --------------------------------------------------------------------------- +// +void CEikCbaButton::SizeChanged() + { + // Resizing is done at CEikCba::SizeChanged(). + // We cannot resize here because this control has wrong + // coordinate system available. + + } + + +EXPORT_C void CEikCbaButton::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + CCoeControl::HandlePointerEventL(aPointerEvent); + } + +EXPORT_C void* CEikCbaButton::ExtensionInterface( TUid /*aInterface*/ ) + { + return NULL; + } + +void CEikCbaButton::SetDimmed(TBool aDimmed) + { + CCoeControl::SetDimmed(aDimmed); + if (!iDoImage) + { + iLabel->SetDimmed(aDimmed); + } + else + { + // Drawing dimmed CEikImages don't work (problem in uiklaf). + //iImage->SetDimmed(aDimmed); + } + } + + +// --------------------------------------------------------------------------- +// Updates the softkey label. +// --------------------------------------------------------------------------- +// +void CEikCbaButton::UpdateLabelText( TPtrC aLabelText ) + { + // Updates the label text with the given label, using tab delimited + // label text to identify normal / alternative labels. + if ( aLabelText.Length() > KMaxCbaLabelLength ) + { + // Cannot take more chars than maximum buffer size. + iFullLabelText.Copy( aLabelText.Left( KMaxCbaLabelLength ) ); + } + else + { + iFullLabelText.Copy( aLabelText ); + } + + TInt find = aLabelText.Locate( CEditableText::ETabCharacter ); + if ( find == KErrNotFound ) + { + iLongLabelText.Set( iFullLabelText ); + iShortLabelText.Set( iFullLabelText ); + } + else + { + iLongLabelText.Set( iFullLabelText.Left( find ) ); + iShortLabelText.Set( + iFullLabelText.Right( aLabelText.Length() - find - 1 ) ); + } + + // Default to showing the long text. + // Won't leave since we've already set maximum buffer length. + TRAP_IGNORE( iLabel->SetTextL( iLongLabelText ) ); + if ( IsReadyToDraw() ) + { + TruncateLabelText(); + } + } + + +void CEikCbaButton::SetTextBitmapMode( TBool aEnableBitmap ) + { + iUseTextBitmap = aEnableBitmap; + if ( iLabel ) + { + iLabel->MakeVisible( !aEnableBitmap ); + } + } + +void CEikCbaButton::DrawToContext( CBitmapContext& aContext, CBitmapContext& aMaskContext, const TPoint& aOffset ) const + { + if ( iLabel ) + { + // Draw text into EColor16MA bitmap + aContext.SetOrigin( -aOffset ); + iLabel->DrawToContext( aContext, NULL ); + + // Update mask + // The mask should have a black background and the text in white. + TRgb maskColor = KRgbWhite; + aMaskContext.SetOrigin( -aOffset ); + iLabel->DrawToContext( aMaskContext, &maskColor ); + } + } + +void CEikCbaButton::SwitchToShortTextL(TBool aShortText) + { + if (aShortText) + { + iLabel->SetTextL(iShortLabelText); + } + else + { + iLabel->SetTextL(iLongLabelText); + } + + if (IsReadyToDraw()) + { + TruncateLabelText(); + } + + if (!iDoImage) + { + iLabel->DrawDeferred(); + } + else + { + iImage->DrawDeferred(); + } + } + +void CEikCbaButton::SetLabelFont(const CFont* aLabelFont) + { + iLabel->SetFont(aLabelFont); + } + +void CEikCbaButton::TruncateLabelText() + { + // Truncation removed from here, as it was not bidi-text compatible. + // Let CEikLabel handle truncation instead. + iLabel->CropText(); + } + +TBool CEikCbaButton::IsEmptyText() const + { + if ( iDoImage ) + { + return EFalse; + } + + TPtrC text( iFullLabelText ); + TBool allSpaces = ETrue; + + for ( TInt i = 0; i < text.Length(); ++i ) + { + if ( !TChar(text[i]).IsSpace() ) + { + allSpaces = EFalse; + break; + } + } + + return allSpaces; + } + +void CEikCbaButton::ConstructEmptyButtonL() + { + ConstructL( EHRightVCenter ); // creates label + _LIT(KEmptyText, ""); + TPtrC16 ptr(KEmptyText); + UpdateLabelText( ptr ); + } + +TBool CEikCbaButton::PressedDown() const + { + return iPressedDown; + } + +void CEikCbaButton::SetPressedDown( const TBool aPressedDown ) + { + iPressedDown = aPressedDown; + } + +// ----------------------------------------------------------------------------- +// EikSoftkeyImage::SetImage +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void EikSoftkeyImage::SetImage( + CEikButtonGroupContainer* aButtonGroupContainer, + CEikImage& aImage, + TBool aLeft) + { // static + TInt commandPos = aLeft ? 0 : 2; + TInt commandId = aButtonGroupContainer->ButtonGroup()->CommandId(commandPos); + CEikCbaButton* cbaButton = (CEikCbaButton*) aButtonGroupContainer->ControlOrNull(commandId); + if ( cbaButton ) + { + cbaButton->SetImage(aImage); + // Draw button once with old size, as rect size is different with icon and text + cbaButton->DrawNow(); + + aButtonGroupContainer->SetRect(aButtonGroupContainer->Rect()); + // Draw previosly set image + cbaButton->DrawNow(); + aButtonGroupContainer->DrawNow(); + } + } + +// ----------------------------------------------------------------------------- +// EikSoftkeyImage::SetLabel +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void EikSoftkeyImage::SetLabel( + CEikButtonGroupContainer* aButtonGroupContainer, + TBool aLeft) + { // static + TInt commandPos = aLeft ? 0 : 2; + TInt commandId = aButtonGroupContainer->ButtonGroup()->CommandId(commandPos); + CEikCbaButton* cbaButton = (CEikCbaButton*) aButtonGroupContainer->ControlOrNull(commandId); + if ( cbaButton ) + { + cbaButton->ReplaceImageByLabel(); + // Draw button once with old size, as rect size is different with icon and text + cbaButton->DrawNow(); + + TRect screenRect = iAvkonAppUi->ApplicationRect(); + aButtonGroupContainer->SetBoundingRect(screenRect); + // Draw previosly set label + cbaButton->DrawNow(); + aButtonGroupContainer->DrawNow(); + } + } + +// ----------------------------------------------------------------------------- +// CEikCbaButton::SetImage +// +// ----------------------------------------------------------------------------- +// +void CEikCbaButton::SetImage(CEikImage &aImage) + { + iDoImage = ETrue; + + if ( iImage ) + { + iImage->SetMask( iMask ); + } + delete iImage; + delete iSfeMask; + iSfeMask = NULL; + iImage = &aImage; + if ( iImage ) + { + TRAP_IGNORE( PrepareImageL() ); + } + else + { + ReplaceImageByLabel(); + } + } + +// ----------------------------------------------------------------------------- +// CEikCbaButton::PrepareImageL +// Prepares Image for softkey feedback effect. Creates needed mask for +// pressed down state. +// ----------------------------------------------------------------------------- +// +void CEikCbaButton::PrepareImageL() + { + // 50% transparent pressed down image is made with a alternative mask + // which is created when a image is set to CEikCbaButton. + // Original mask is copied and each of its pixels color components is + // halved. Bit-shifting to the right makes color value to half --> + // image looks 50% transparent with this mask + const CFbsBitmap* mask = iImage->Mask(); + iMask = mask; + + if ( !iMask ) + { + return; + } + + iSfeMask = new (ELeave) CFbsBitmap; + User::LeaveIfError( iSfeMask->Create( mask->SizeInPixels(), mask->DisplayMode() ) ); + + CFbsBitmapDevice* device = CFbsBitmapDevice::NewL( iSfeMask ); + CleanupStack::PushL( device ); + + CFbsBitGc* gc( NULL ); + User::LeaveIfError( device->CreateContext( gc ) ); + + gc->SetPenStyle( CGraphicsContext::ESolidPen ); + gc->BitBlt( TPoint(0,0), mask ); + + iSfeMask->LockHeap(); + TInt w = iSfeMask->SizeInPixels().iWidth; + TInt h = iSfeMask->SizeInPixels().iHeight; + TInt dataStride = iSfeMask->DataStride() - w; + TUint8* address = (TUint8*) iSfeMask->DataAddress(); + + for ( TInt i = 0; i < h; ++i ) + { + for ( TInt j = 0; j < w; j++ ) + { + *address >>= 1; + ++address; + } + address += dataStride; + } + + iSfeMask->UnlockHeap(); + CleanupStack::PopAndDestroy( device ); // device + + delete gc; + } +// ----------------------------------------------------------------------------- +// CEikCbaButton::ReplaceImageByLabel +// +// ----------------------------------------------------------------------------- +// +void CEikCbaButton::ReplaceImageByLabel() + { + iDoImage = EFalse; + if ( iImage ) + { + // avoid mem leak. + iImage->SetMask( iMask ); + delete iImage; + iImage = NULL; + delete iSfeMask; + iSfeMask = NULL; + } + } + +// +// CEikEnhancedCbaButton +// + +// ----------------------------------------------------------------------------- +// default constructor +// ----------------------------------------------------------------------------- +CEikEnhancedCbaButton::CEikEnhancedCbaButton() + { + } + +// ----------------------------------------------------------------------------- +// default destructor +// ----------------------------------------------------------------------------- +CEikEnhancedCbaButton::~CEikEnhancedCbaButton() + { + } + +// ----------------------------------------------------------------------------- +// Sets command type for current button +// @param aCommandType Command type to be set +// ----------------------------------------------------------------------------- +#ifdef RD_ENHANCED_CBA +void CEikEnhancedCbaButton::SetCommandType( const TInt aCommandType ) + { + iCommandType = aCommandType; + } +#else +void CEikEnhancedCbaButton::SetCommandType( const TInt /*aCommandType*/ ) + { + } +#endif // RD_ENHANCED_CBA +// ----------------------------------------------------------------------------- +// returns command's type for current button +// @return TInt command's type +// ----------------------------------------------------------------------------- + +TInt CEikEnhancedCbaButton::CommandType() const + { +#ifdef RD_ENHANCED_CBA + return iCommandType; +#else + return 0; +#endif // RD_ENHANCED_CBA + } + +// ----------------------------------------------------------------------------- +// returns command id for current button +// @return TInt command's id +// ----------------------------------------------------------------------------- +TInt CEikEnhancedCbaButton::CommandId() const + { +#ifdef RD_ENHANCED_CBA + return iCommandId; +#else + return 0; +#endif // RD_ENHANCED_CBA + } + +// ----------------------------------------------------------------------------- +// constructs button based on resource definition +// @param aReader created resource reader for reading information from resource file +// ----------------------------------------------------------------------------- +#ifdef RD_ENHANCED_CBA +void CEikEnhancedCbaButton::ConstructFromResourceL(TResourceReader& aReader) + { + // Alignment set to right. + ConstructL( EHRightVCenter ); // creates label + iCommandType = aReader.ReadUint8(); + iCommandId = aReader.ReadInt16(); + // iFullLabelText.Copy( aReader.ReadTPtrC() ); + UpdateLabelText( aReader.ReadTPtrC() ); + + aReader.ReadTPtrC(); // bmp filename + aReader.ReadInt16(); // bmp id + aReader.ReadInt16(); // bmp mask id + } +#else +void CEikEnhancedCbaButton::ConstructFromResourceL(TResourceReader&) + { + } +#endif // RD_ENHANCED_CBA + +// ----------------------------------------------------------------------------- +// Constructs empty button with id EAknSoftkeyEmpty +// ----------------------------------------------------------------------------- +void CEikEnhancedCbaButton::ConstructEmptyButtonL() + { +#ifdef RD_ENHANCED_CBA + ConstructL( EHRightVCenter ); // creates label + iCommandType = EEikCommandTypeAnyCommand; + iCommandId = EAknSoftkeyEmpty; + _LIT(KEmptyText, ""); + TPtrC16 ptr(KEmptyText); + UpdateLabelText( ptr ); +#endif + } + +// ----------------------------------------------------------------------------- +// Used to get the label's text for the button +// @return TPtrC label text +// ----------------------------------------------------------------------------- +TPtrC* CEikEnhancedCbaButton::LabelText() + { +#ifdef RD_ENHANCED_CBA + return &iLongLabelText; +#else + return NULL; +#endif + } + +// +// CEikCommandTable +// + +CEikCommandTable* CEikCommandTable::NewL() + { +#ifdef RD_ENHANCED_CBA + CEikCommandTable* self = CEikCommandTable::NewLC(); + CleanupStack::Pop( self ); + return self; +#else + return NULL; +#endif + } + +CEikCommandTable* CEikCommandTable::NewLC() + { +#ifdef RD_ENHANCED_CBA + CEikCommandTable* self = new (ELeave) CEikCommandTable; + CleanupStack::PushL( self ); + self->ConstructL(); + return self; +#else + return NULL; +#endif + } + +// ----------------------------------------------------------------------------- +// Construction for command table +// priority configuration is read from the resource file +// ----------------------------------------------------------------------------- +void CEikCommandTable::ConstructL() + { +#ifdef RD_ENHANCED_CBA + // Get the cba priority configuration + TResourceReader reader; + CCoeEnv::Static()->CreateResourceReaderLC( reader, R_EIK_CBA_PRIORITIES ); + + // Amount of buttons (should match with KMaxButtonsInCommandTable). + TInt count = reader.ReadInt16(); + + __ASSERT_DEBUG( count == KMaxButtonsInCommandTable, + Panic(EEikPanicCBAButtonCountDiffersFromCommandTableSize) ); + + for ( TInt i = 0; i < count; i++ ) + { + TInt priorities( reader.ReadInt16() ); // Amount of priorities for current button. + RArray arr; + for ( TInt ii = 0; ii < priorities; ii++ ) + { + TInt8 commandType( reader.ReadInt8() ); + arr.Append( commandType ); + } + iPriorities.Append( arr ); + } + + CleanupStack::PopAndDestroy(); // reader +#endif + } + +#ifdef RD_ENHANCED_CBA +CEikCommandTable::CEikCommandTable() : iPriorities(1) +#else +CEikCommandTable::CEikCommandTable() +#endif // RD_ENHANCED_CBA + { + } + + +CEikCommandTable::~CEikCommandTable() + { +#ifdef RD_ENHANCED_CBA + iCommandButtons.Reset(); // Reset array + for(TInt i = 0; i < iPriorities.Count(); i++) + { + iPriorities[i].Reset(); + } + iPriorities.Reset(); +#endif + } + +// ----------------------------------------------------------------------------- +// Used to add a command to CommandTable +// @param aButton button to be added +// ----------------------------------------------------------------------------- +#ifndef RD_ENHANCED_CBA +TInt CEikCommandTable::AddCommandL(CEikEnhancedCbaButton* /*aButton*/) + { + return KErrNone; + } +#else +TInt CEikCommandTable::AddCommandL(CEikEnhancedCbaButton* aButton) + { + // CommandType tells in which button this command should be placed + TInt commandType( aButton->CommandType() ); + TInt index( KErrNotFound ); + + // Find button and index for this button. + TInt button( 0 ); + for ( button = 0; button < iPriorities.Count(); button++ ) + { + index = iPriorities[button].Find( commandType ); + if ( index != KErrNotFound ) + { + CEikEnhancedCbaButton* existingButton = Command( button ); + // If command placed on this index, check if new priority is lower. + if( existingButton ) + { + TInt existingPriority = iPriorities[button].Find( existingButton->CommandType() ); + + // Delete existing command button if new command has higher priority (lower index). + if( index < existingPriority || existingPriority == KErrNotFound ) + { + delete existingButton; + existingButton = NULL; + iCommandButtons[button] = aButton; + break; + } + } + else + { + iCommandButtons[button] = aButton; + break; + } + } + } + + // Delete button if it's not placed. + if( button == iPriorities.Count() ) + { + delete aButton; + aButton = NULL; + } + return KErrNone; + } +#endif // RD_ENHANCED_CBA + +// ----------------------------------------------------------------------------- +// Used to check if CommandTable has a button with a certain id. +// @param aCommandId Id to be checked. +// ----------------------------------------------------------------------------- +#ifndef RD_ENHANCED_CBA +TBool CEikCommandTable::IsCommandPlaced(const TInt /*aCommandId*/) const + { +#else // !RD_ENHANCED_CBA +TBool CEikCommandTable::IsCommandPlaced(const TInt aCommandId) const + { + TInt count( iCommandButtons.Count() ); + + for ( TInt i = 0; i < count; i++ ) + { + if ( iCommandButtons[i] ) + { + if ( iCommandButtons[i]->CommandId() == aCommandId ) + { + return ETrue; + } + } + } +#endif // RD_ENHANCED_CBA + return EFalse; // if no match for command id + } + +// ----------------------------------------------------------------------------- +// Used to replace command with a new command. +// @param aCommandId Id for command that should be replaced. +// @param aResourceId Id for new ENHANCED_CBA_BUTTON resource to be placed in the CommandTable. +// ----------------------------------------------------------------------------- +#ifndef RD_ENHANCED_CBA +void CEikCommandTable::ReplaceCommandL( const TInt /*aCommandId*/, const TInt /*aResourceId*/ ) + { +#else // !RD_ENHANCED_CBA +void CEikCommandTable::ReplaceCommandL( const TInt aCommandId, const TInt aResourceId ) + { + // If the command is not in the command table, return. + if( !IsCommandPlaced( aCommandId ) ) + { + return; + } + + TInt index( iCommandButtons.Count() ); + + CEikEnhancedCbaButton* oldButton = NULL; + + for( TInt i = 0; i < index; i++ ) + { + if( iCommandButtons[i] ) + { + if( iCommandButtons[i]->CommandId() == aCommandId ) + { + oldButton = iCommandButtons[i]; + index = i; + break; // Index is the index of replacement. + } + } + } + + CEikEnhancedCbaButton* button = new (ELeave) CEikEnhancedCbaButton; + button->SetTextBitmapMode( iExtension->iEnablePostingTransparency ); + CleanupStack::PushL( button ); + TResourceReader reader; + CCoeEnv::Static()->CreateResourceReaderLC( reader, aResourceId ); + + // Construct new button. + TUint8 version( (TUint8)reader.ReadUint8() ); // version + button->ConstructFromResourceL( reader ); + CleanupStack::Pop( button ); + CleanupStack::PopAndDestroy(); // reader + + // Store new button to command table. + iCommandButtons[index] = button; // transfers ownership + + // Delete old button. + delete oldButton; +#endif // !RD_ENHANCED_CBA + } + +// ----------------------------------------------------------------------------- +// Used to get CEikEnhancedCbaButton for current control button (1-4). +// @param aCommandIndex Index for requested button, use enum TCommandTableCbaPositions. +// @return CEikCbaButton for current position, NULL if no button placed in that position. +// ----------------------------------------------------------------------------- +#ifdef RD_ENHANCED_CBA +CEikEnhancedCbaButton* CEikCommandTable::Command( const TInt aCommandIndex ) + { + return iCommandButtons[aCommandIndex]; + } +#else // RD_ENHANCED_CBA +CEikEnhancedCbaButton* CEikCommandTable::Command( const TInt /*aCommandIndex*/ ) + { + return NULL; + } +#endif // RD_ENHANCED_CBA + +// ----------------------------------------------------------------------------- +// Reset CommandTable +// ----------------------------------------------------------------------------- +void CEikCommandTable::Reset() + { +#ifdef RD_ENHANCED_CBA + iCommandButtons.Reset(); +#endif // RD_ENHANCED_CBA + } + +// ----------------------------------------------------------------------------- +// Sets command observer +// ----------------------------------------------------------------------------- +EXPORT_C void AknCbaContentObserver::SetContentObserver( + CEikCba* aCba, + TCallBack aCallBack ) + { + if ( aCba ) + { + aCba->SetContentObserver( aCallBack ); + } + } + +// End of file