diff -r 000000000000 -r 2f259fa3e83a uifw/EikStd/coctlsrc/akntoolbarextensionview.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/EikStd/coctlsrc/akntoolbarextensionview.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,1598 @@ +/* +* Copyright (c) 2007 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: Popup toolbar extension +* +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "akntoolbaritem.h" +#include "akntoolbarextensionview.h" + +#include "aknresourceprovider.h" + +const TInt KNoItemSelected = -1; +const TUint32 KToolbarExtensionBgColor = 0x00000000; +const TInt KToolBarExtensionBgAlpha = 0x7F; +const TInt KToolbarButtonBeforeTimeout = 300; + +enum TDirection + { + EDirectionLeft = 0, + EDirectionRight, + EDirectionUp, + EDirectionDown, + ENoDirection + }; + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CAknToolbarExtensionView::NewL +// --------------------------------------------------------------------------- +// +CAknToolbarExtensionView* CAknToolbarExtensionView::NewL( TResourceReader& aReader, + CAknToolbarExtension* aExtension ) + { + CAknToolbarExtensionView* self = new ( ELeave ) CAknToolbarExtensionView( aExtension); + CleanupStack::PushL( self ); + self->ConstructL(); + self->ConstructFromResourceL( aReader ); + CleanupStack::Pop( self ); + + return self; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CAknToolbarExtensionView::~CAknToolbarExtensionView() + { + SetFocus( EFalse ); + CEikonEnv::Static()->EikAppUi()->RemoveFromStack( this ); + if ( iSelectedItem >= 0 && iSelectedItem < iItems.Count() ) + { + TRAP_IGNORE( iItems[iSelectedItem]->SetIsSelectedL(EFalse) ); + } + iVisibleItems.Reset(); + iItems.ResetAndDestroy(); + delete iFrameContext; + delete iResourceProvider; + } + +// --------------------------------------------------------------------------- +// From class CCoeControl. +// Constructs extension view +// --------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::ConstructFromResourceL( TResourceReader& aReader ) + { + TInt numberOfItems = aReader.ReadInt16(); + TBool noFrame(EFalse); + for ( TInt i = 0; i < numberOfItems; ++i ) + { + CAknToolbarItem* item = ConstructControlLC( aReader ); + if ( item->Control() ) + { + iItems.AppendL( item ); + item->Control()->SetContainerWindowL( *this ); + item->Control()->SetObserver( iExtension ); + + if ( item->ControlType() == EAknCtButton ) + { + CAknButton* button = static_cast(item->Control() ); + TInt flags = button->ButtonFlags(); + if ( !noFrame && ( !( flags & KAknButtonNoFrame ) || + !( flags & KAknButtonPressedDownFrame ) ) ) + { + // Set flag KAknButtonNoFrame for all buttons except the one + // after an editor + flags |= KAknButtonNoFrame; + flags |= KAknButtonPressedDownFrame; + button->RegisterResourceProvider( iResourceProvider ); + button->SetButtonFlags( flags ); + } + else if ( noFrame ) + { + // Setting frames for the button that comes after an editor + if ( flags & KAknButtonNoFrame ) + { + flags &= ~KAknButtonNoFrame; + flags &= ~KAknButtonPressedDownFrame; + button->SetButtonFlags( flags ); + } + noFrame = EFalse; + } + AdjustButtonL( *button ); + } + else + { + if ( Editor( item->ControlType() ) ) + { + noFrame = ETrue; + } + } + CleanupStack::Pop( item ); + } + else + { + CleanupStack::PopAndDestroy( item ); + item = NULL; + } + } + + if ( iExtension->ExtensionFlags() & KAknTbExtensionDsaMode ) + { + iFrameContext->SetFrame( KAknsIIDQgnGrafPopupTrans ); + } + + ActivateL(); + // Activating here the items, because ActivateL uses CountComponentControls + // which is currently 0 since iVisibleItems is still empty + for ( TInt i = 0; i < iItems.Count(); i++ ) + { + iItems[i]->Control()->ActivateL(); + } + SetComponentsToInheritVisibility( ETrue ); + } + +// --------------------------------------------------------------------------- +// From class CCoeControl. +// Shows or hides extension view +// --------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::MakeVisible( TBool aVisible ) + { + TBool isVisible = IsVisible(); + + if ( aVisible && !isVisible ) + { + // the toolbar extension is shown, this happens only with pointer event? + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback ) + { + feedback->InstantFeedback( ETouchFeedbackPopUp ); + } + + TRect rect; + TRAP_IGNORE( rect = CalculateSizeL() ); + CEikonEnv::Static()->EikAppUi()->UpdateStackedControlFlags( this, + 0, ECoeStackFlagRefusesFocus | ECoeStackFlagRefusesAllKeys ); + CEikonEnv::Static()->EikAppUi()->HandleStackChanged(); + + // Calling this here, so that iVisibleItems array has been updated and + // all items visible in extension get call makevisible + CAknControl::MakeVisible( aVisible ); + SetRect( rect ); + DrawableWindow()->SetOrdinalPosition( 0, ECoeWinPriorityNormal ); + TBool floating = !IsNonFocusing(); + for ( TInt i = 0; i < iItems.Count(); i++ ) + { + if ( !floating && Editor( iItems[i]->ControlType() ) ) + { + TRAP_IGNORE( SelectItemL( i, ETrue ) ); + break; + } + if ( floating && iItems[i]->ControlType() == EAknCtButton ) + { + CAknButton* button = static_cast( iItems[i]->Control() ); + TInt j = 0; + while( button->State( j ) ) + { + //Setting the texts empty + TRAP_IGNORE( button->State( j++ )->SetTextL( KNullDesC ) ); + } + } + } + + if ( floating && iVisibleItems.Count() ) + { + iSelectedItem = NextFocusable( 1 ); + TRAP_IGNORE( iVisibleItems[iSelectedItem]->SetFocusL( + ETrue, EFalse, ENoDrawNow, this ) ); + } + if ( iPreviousItem >= 0 && IsNonFocusing() ) + { + CAknToolbarItem* prevItem = iVisibleItems[iPreviousItem]; + if ( prevItem->Control() ) + { + if ( prevItem->ControlType() == EAknCtButton || + prevItem->ControlType() == EAknCtToolbarExtension ) + { + CAknButton* button = static_cast( prevItem->Control() ); + button->ResetState(); + } + } + iPreviousItem = KNoItemSelected; + } + DrawNow(); + } + else if ( !aVisible && isVisible ) + { + CEikonEnv::Static()->EikAppUi()->UpdateStackedControlFlags( this, + ~0, ECoeStackFlagRefusesFocus | ECoeStackFlagRefusesAllKeys ); + CEikonEnv::Static()->EikAppUi()->HandleStackChanged(); + CAknControl::MakeVisible( aVisible ); + TRAP_IGNORE( SelectItemL( iSelectedItem, EFalse ) ); + DrawableWindow()->SetOrdinalPosition( 0, ECoeWinPriorityNeverAtFront ); + } + else + { + CAknControl::MakeVisible( aVisible ); + } + } + +// --------------------------------------------------------------------------- +// From class OfferKeyEventL. +// Consumes key events if floating toolbar extension +// --------------------------------------------------------------------------- +// +TKeyResponse CAknToolbarExtensionView::OfferKeyEventL( + const TKeyEvent& aKeyEvent, TEventCode aType ) + { + if ( aKeyEvent.iCode == EKeyYes || !IsVisible() ) + { + return EKeyWasNotConsumed; + } + //LSK, RSK, KeyOk + else if ( IsNonFocusing() && aType == EEventKey + && ( aKeyEvent.iCode == EKeyDevice0 + || aKeyEvent.iCode == EKeyDevice1 + || aKeyEvent.iCode == EKeyDevice3 ) ) + { + if( IsVisible()&& ( aKeyEvent.iCode == EKeyDevice0 || + aKeyEvent.iCode == EKeyDevice1 )) + { + iExtension->SetShown(EFalse); + return EKeyWasConsumed; + } + return EKeyWasNotConsumed; + } + // When this is visible and without focus, nothing to do + // + // Exception for key filter: Image capture key (not a complete solution: + // the key map may change corrding to the products) + else if ( IsNonFocusing()&& aType == EEventKey + &&(!( aKeyEvent.iScanCode == EStdKeyDevice3 + || aKeyEvent.iScanCode == EStdKeyEnter )) ) + { + return EKeyWasConsumed; + } + else if( IsVisible() && aType == EEventKey ) + { + switch ( aKeyEvent.iCode ) + { + case EKeyRightArrow: + MoveHighlightL( EDirectionRight, 0 ); + break; + case EKeyLeftArrow: + MoveHighlightL( EDirectionLeft, 0 ); + break; + case EKeyUpArrow: + MoveHighlightL( EDirectionUp, 0 ); + break; + case EKeyDownArrow: + MoveHighlightL( EDirectionDown, 0 ); + break; + default: + break; + } + return EKeyWasConsumed; + } + else + { + CAknToolbarItem* item = NULL; + if ( iSelectedItem >= 0 && iSelectedItem < iVisibleItems.Count() ) + { + item = iVisibleItems[iSelectedItem]; + } + // All key events can be given to buttons, other toolbar items must + // be seleceted to get events + if ( item && item->Control() ) + { + if ( ( item->ControlType() == EAknCtButton ) || + ( item->ControlType() == EAknCtToolbarExtension ) || item->IsSelected() ) + { + if ( aKeyEvent.iScanCode == EStdKeyDevice0 ) + { + TKeyEvent keyEvent = aKeyEvent; + // Button does not accept key events if the code is EStdKeyDevice0 + // so changing the key event to EStdKeyDevice3 + keyEvent.iScanCode = EStdKeyDevice3; + item->Control()->OfferKeyEventL( keyEvent, aType ); + } + else if ( aKeyEvent.iScanCode == EStdKeyDevice1 ) + { + MakeVisible( EFalse ); + // Close extension view and let also extension know about it + // so it can change state + iExtension->ViewClosed(); + // Toolbar should perhaps be closed too! + } + else + { + item->Control()->OfferKeyEventL( aKeyEvent, aType ); + } + } + } + + return EKeyWasNotConsumed; + } + + } + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::CountComponentControls +// Gets the number of controls contained in a compound control. +// ----------------------------------------------------------------------------- +// +TInt CAknToolbarExtensionView::CountComponentControls() const + { + return iVisibleItems.Count(); + } + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::ComponentControl +// Gets the specified component of a compound control. +// ----------------------------------------------------------------------------- +// +CCoeControl* CAknToolbarExtensionView::ComponentControl( TInt aIndex ) const + { + if ( aIndex < 0 || aIndex >= iVisibleItems.Count() ) + { + return NULL; + } + return iVisibleItems[aIndex]->Control(); + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::HandleResourceChange +// Handles resource changes +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::HandleResourceChange( TInt aType ) + { + + iResourceProvider->HandleResourceChange( aType ); + + // Hide extension, if non-focusing, and no pen support. Later... + + if ( aType == KEikDynamicLayoutVariantSwitch ) + { + if ( IsVisible() ) + { + TRect rect; + TRAP_IGNORE( rect = CalculateSizeL() ); + SetRect( rect ); + } + } + + // Not calling base class function here, because only visible controls would + // be returned by ComponentControl, and thus the font would not be updated + // for all controls + for ( TInt i = 0; i < iItems.Count(); ++i ) + { + iItems[i]->Control()->HandleResourceChange( aType ); + if ( iItems[i]->ControlType() == EAknCtButton ) + { + CAknButton* button = static_cast( iItems[i]->Control() ); + + if ( aType == KEikDynamicLayoutVariantSwitch ) + { + TBool useOutline = iExtension->ExtensionFlags() & KAknTbExtensionDsaMode; + const CFont* font = AknLayoutUtils::FontFromId( AknLayoutScalable_Avkon:: + cell_tb_ext_pane_t1( useOutline ? 0 : 1 ).LayoutLine().FontId() ); + button->SetTextFont( font ); + } + + if ( aType == KAknsMessageSkinChange ) + { + if ( iExtension->ExtensionFlags() & KAknTbExtensionDsaMode ) + { + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( + *button, EColorControlBackground, KRgbWhite ) ); + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( + *button, EColorButtonText, KRgbBlack ) ); + } + } + } + } + + + + // Remember to check here if iSelectedItem still is in iVisibleItems, and if + // not then do something. + if ( ( aType == KAknsMessageSkinChange || + aType == KEikDynamicLayoutVariantSwitch ) && IsVisible() ) + { + DrawDeferred(); + } + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::HandlePointerEventL +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::HandlePointerEventL( + const TPointerEvent& aPointerEvent ) + { + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + if ( !Rect().Contains( aPointerEvent.iPosition) ) + { + iIsDownOutside = ETrue; + } + else + { + iIsDownOutside = EFalse; + } + } + if ( aPointerEvent.iType == TPointerEvent::EButton1Up ) + { + if ( !Rect().Contains( aPointerEvent.iPosition) && iIsDownOutside ) + { + // tapped outside view, + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback ) + { + feedback->InstantFeedback( ETouchFeedbackPopUp ); + } + + MakeVisible( EFalse ); + // Close extension view and let also extension know about it + // so it can change state + iExtension->ViewClosed(); + iIsDownOutside = EFalse; + return; + } + } + + TPointerEvent event( aPointerEvent ); + TBool override ( EFalse ); + + if ( aPointerEvent.iType == TPointerEvent::EButton1Down && IsNonFocusing() && iPreviousItem >=0 ) + { + CAknToolbarItem* prevItem = iVisibleItems[iPreviousItem]; + if ( prevItem->Control() && + !prevItem->Control()->Rect().Contains( aPointerEvent.iPosition ) ) + { + if ( prevItem->ControlType() == EAknCtButton || + prevItem->ControlType() == EAknCtToolbarExtension ) + { + CAknButton* button = static_cast( prevItem->Control() ); + event.iType = TPointerEvent::EButton1Up; + button->HandlePointerEventL ( event ); + } + } + } + // Cancel previous button + if ( iPreviousItem >=0 && ( aPointerEvent.iType == TPointerEvent::EDrag || + aPointerEvent.iType == TPointerEvent::EButtonRepeat ) ) + { + CAknToolbarItem* prevItem = iVisibleItems[iPreviousItem]; + + if ( prevItem->Control() && + !prevItem->Control()->Rect().Contains( aPointerEvent.iPosition ) ) + { + if ( prevItem->ControlType() == EAknCtButton || + prevItem->ControlType() == EAknCtToolbarExtension ) + { + CAknButton* button = static_cast( prevItem->Control() ); + event.iType = TPointerEvent::EButton1Up; + button->HandlePointerEventL ( event ); + override = ETrue; + iPreviousItem = KNoItemSelected; + } + } + } + + CAknToolbarItem* item = NULL; + for ( TInt ii = 0; ii < iVisibleItems.Count(); ++ii ) + { + item = iVisibleItems[ii]; + if ( item->Control() && + item->Control()->Rect().Contains( aPointerEvent.iPosition ) ) + { + if ( item->ControlType() == EAknCtButton || + item->ControlType() == EAknCtToolbarExtension ) + { + CAknButton* button = static_cast( item->Control() ); + if ( ii != iPreviousItem ) + { + if ( !button->IsDimmed() && !IsNonFocusing() ) + { + MoveHighlightL( ENoDirection, ii ); + // focus has moved from one button to another due to dragging, + // give sensitive feedback + if ( iPreviousItem != iSelectedItem ) + { + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback && + ( aPointerEvent.iType == TPointerEvent::EDrag || + aPointerEvent.iType == TPointerEvent::EButtonRepeat ) ) + { + feedback->InstantFeedback( ETouchFeedbackSensitiveButton ); + } + } + } + if ( aPointerEvent.iType == TPointerEvent::EDrag || + aPointerEvent.iType == TPointerEvent::EButtonRepeat ) + { + // focus has moved from one button to another due to dragging, + // give sensitive feedback + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback && + ( aPointerEvent.iType == TPointerEvent::EDrag || + aPointerEvent.iType == TPointerEvent::EButtonRepeat ) ) + { + feedback->InstantFeedback( ETouchFeedbackSensitiveButton ); + } + button->SetHelpNoteTimeouts( KToolbarButtonBeforeTimeout, 0 ); + event.iType = TPointerEvent::EButton1Down; + button->HandlePointerEventL( event ); + override = ETrue; + } + iPreviousItem = ii; + } + + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + iDownItem = ii; + button->SetHelpNoteTimeouts( KToolbarButtonBeforeTimeout, 0 ); + } + + if ( aPointerEvent.iType == TPointerEvent::EButton1Up ) + { + // Up and down events are in different items, give basic + // feedback to the released item. + if ( ii != iDownItem ) + { + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback ) + { + feedback->InstantFeedback( ETouchFeedbackBasicButton ); + } + } + + button->HandlePointerEventL( aPointerEvent ); + iPreviousItem = KNoItemSelected; + override = ETrue; + } + } + if ( IsNonFocusing() ) + { + SelectItemL( ii, ETrue ); + } + } + } + if ( !override ) + { + CAknControl::HandlePointerEventL( aPointerEvent ); + } + } + + +// ----------------------------------------------------------------------------- +// Returns control corresponding the specified command id. +// ----------------------------------------------------------------------------- +// +CCoeControl* CAknToolbarExtensionView::ControlOrNull( TInt aCommandId ) const + { + for ( TInt i=0; i < iItems.Count(); i++ ) + { + if ( aCommandId == iItems[i]->CommandId() ) + { + return iItems[i]->Control(); + } + } + return NULL; + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtension::CommandIdByControl +// +// ----------------------------------------------------------------------------- +// +TInt CAknToolbarExtensionView::CommandIdByControl( CCoeControl* aControl ) const + { + for ( TInt i=0; i < iItems.Count(); i++ ) + { + if ( aControl == iItems[i]->Control() ) + { + return iItems[i]->CommandId(); + } + } + return KErrNotFound; + } + + + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::Editor +// Checks if the controltype given is editor +// ----------------------------------------------------------------------------- +// +TBool CAknToolbarExtensionView::Editor( TInt aControlType ) + { + // This is almost copied from toolbar item, perhaps to CAknToolbarUtils + switch ( aControlType ) + { + case EEikCtEdwin: + case EEikCtGlobalTextEditor: + case EEikCtRichTextEditor: + case EAknCtIntegerEdwin: + case EEikCtFlPtEd: + case EEikCtFxPtEd: + return ETrue; + default: + return EFalse; + } + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::AddItemL +// Adds new extension item +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::AddItemL( CCoeControl* aItem, + TInt aType, + TInt aCommandId, + TInt aFlags, + TInt aIndex ) + { + if ( aItem && aIndex >= 0 && aIndex <= iItems.Count() ) + { + aItem->SetContainerWindowL( *this ); + aItem->SetObserver( iExtension ); + aItem->ActivateL(); + CAknToolbarItem* tbItem = new ( ELeave ) CAknToolbarItem( aItem, aType, + aCommandId, aFlags ); + CleanupStack::PushL( tbItem ); + iItems.InsertL( tbItem, aIndex ); + CleanupStack::Pop( tbItem ); + if ( aType == EAknCtButton ) + { + CAknButton* button = static_cast( aItem ); + AdjustButtonL( *button ); + } + CheckButtonFrames( ETrue, aIndex ); + // Do something here for the selected item when focusing toolbar ready + } + else + { + User::Leave( KErrArgument ); + } + } + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::AdjustButtonL +// Adjusts button to what is needed by toolbar extension view. +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::AdjustButtonL( CAknButton& aButton ) + { + aButton.SetTextAndIconAlignment( CAknButton::EIconOverText ); + + TBool useOutline = iExtension->ExtensionFlags() & KAknTbExtensionDsaMode; + const CFont* font = AknLayoutUtils::FontFromId( AknLayoutScalable_Avkon:: + cell_tb_ext_pane_t1( useOutline ? 0 : 1 ).LayoutLine().FontId() ); + + aButton.SetTextFont( font ); + aButton.SetTextColorIds( KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG60 ); + + if ( iExtension->ExtensionFlags() & KAknTbExtensionDsaMode ) + { + AknLayoutUtils::OverrideControlColorL( aButton, + EColorControlBackground, KRgbWhite ); + AknLayoutUtils::OverrideControlColorL( aButton, + EColorButtonText, KRgbBlack ); + } + } + + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::RemoveItemL +// Removes an item corresponding to command id +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::RemoveItemL( TInt aCommandId ) + { + TInt itemIndex = ToolbarItemIndexById( EFalse, aCommandId ); + if ( itemIndex == KErrNotFound ) + { + User::Leave( KErrNotFound ); + } + if ( itemIndex >= 0 && itemIndex < iItems.Count() ) + { + // Need to remove item also from iVisibleItems array, so the non-existent + // item is not returned by ComponentControl + TInt visibleIndex = ToolbarItemIndexById( ETrue, aCommandId ); + if ( visibleIndex >= 0 && visibleIndex < iVisibleItems.Count() ) + { + iVisibleItems.Remove( visibleIndex ); + } + delete iItems[itemIndex]; + iItems.Remove( itemIndex ); + // Need to check button frames so that only the item next to editor has + // frames + CheckButtonFrames( EFalse, itemIndex ); + } + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::Draw +// Draw frames for extension view +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::Draw( const TRect& aRect ) const + { + TRect rect( Rect() ); + CWindowGc& gc = SystemGc(); + gc.SetClippingRect( aRect ); + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + if ( iExtension->ExtensionFlags() & KAknTbExtensionDsaMode ) + { + gc.SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha ); + gc.SetBrushColor( TRgb( KToolbarExtensionBgColor, KToolBarExtensionBgAlpha ) ); + gc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + gc.DrawRect( rect ); + gc.SetDrawMode( CGraphicsContext::EDrawModePEN ); + TSize penSize( 1, 1 ); + gc.SetPenSize( penSize ); + gc.SetPenStyle( CGraphicsContext::EDottedPen ); + gc.SetPenColor( KRgbWhite ); + gc.SetBrushStyle( CGraphicsContext::ENullBrush ); + gc.DrawRect( rect ); + } + else + { + AknsDrawUtils::Background( skin, iFrameContext, gc, rect ); + } + + + // draw toolbar item highlight + if ( !IsNonFocusing() && iSelectedItem != KNoItemSelected ) + { + CAknToolbarItem* item = iVisibleItems[iSelectedItem]; + if ( item && item->HighlightRect().Intersects( aRect ) ) + { + TRect outerRect( item->HighlightRect() ); + TRect innerRect(outerRect); + + TAknWindowLineLayout unit = AknLayoutScalable_Avkon::aid_value_unit2().LayoutLine(); + innerRect.Shrink( unit.iW/10, unit.iH/10 ); + + if ( !AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), + gc, outerRect, innerRect, + KAknsIIDQsnFrGrid, KAknsIIDDefault ) ) + { + gc.SetBrushColor( KRgbRed ); + gc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + gc.DrawRect( item->HighlightRect() ); + } + } + } + + + } + +// --------------------------------------------------------------------------- +// Default constructor +// --------------------------------------------------------------------------- +// +CAknToolbarExtensionView::CAknToolbarExtensionView( + CAknToolbarExtension* aExtension): iExtension( aExtension ), + iSelectedItem( KNoItemSelected ), iNumberOfColumns( 1 ), + iIsDownOutside( EFalse ) + { + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::ConstructL +// 2nd phase constructor +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::ConstructL() + { + CreateWindowL(); + if( 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); + if ( iExtension->ExtensionFlags() & KAknTbExtensionTransparent ) + { + iFrameContext = CAknsFrameBackgroundControlContext::NewL( KAknsIIDQgnGrafPopupTrans, + TRect(), TRect(), EFalse ); + } + else + { + iFrameContext = CAknsFrameBackgroundControlContext::NewL( KAknsIIDQsnFrPopupSub, + TRect(), TRect(), EFalse ); + } + } + else + { + iFrameContext = CAknsFrameBackgroundControlContext::NewL( KAknsIIDQsnFrPopupSub, + TRect(), TRect(), EFalse ); + + } + } + else + { + iFrameContext = CAknsFrameBackgroundControlContext::NewL( KAknsIIDQsnFrPopupSub, + TRect(), TRect(), EFalse ); + } + + SetGloballyCapturing( ETrue ); + SetPointerCapture( ETrue ); + // Control stack priority needs to be same as toolbars, otherwise floating + // toolbar will receive the key events when extension is open. If lowering + // toolbar's control stack priority, then this can be lowered too. + CEikonEnv::Static()->EikAppUi()->AddToStackL( this, ECoeStackPriorityCba, + ECoeStackFlagRefusesFocus | ECoeStackFlagRefusesAllKeys ); + MakeVisible( EFalse ); + SetFocusing( EFalse ); + + iResourceProvider = CAknResourceProvider::NewL(); + iPreviousItem = KNoItemSelected; + } + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::ConstructControlLC +// Constructs one of the toolbar extension items +// ----------------------------------------------------------------------------- +// +CAknToolbarItem* CAknToolbarExtensionView::ConstructControlLC( TResourceReader& aReader ) + { + CAknToolbarItem* item = new(ELeave) CAknToolbarItem; + CleanupStack::PushL( item ); + item->ConstructFromResourceL( aReader ); + return item; + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::CalculateSizeL +// Calculates size and position for toolbar extension +// ----------------------------------------------------------------------------- +// +TRect CAknToolbarExtensionView::CalculateSizeL() + { + iVisibleItems.Reset(); + TBool landscape = Layout_Meta_Data::IsLandscapeOrientation(); + + + TRect extensionRect; + TRect windowRect; + TRect gridExtRect; + TRect cellExtRect; + + TRect mainPaneRect = static_cast + ( iEikonEnv->AppUiFactory() )->ClientRect(); + TBool floating = !IsNonFocusing(); + + if ( floating ) + { + extensionRect = RectFromLayout( mainPaneRect, + AknLayoutScalable_Avkon::popup_tb_float_extension_window( 0 ) ); + + windowRect = TRect( TPoint(), extensionRect.Size() ); + + gridExtRect = RectFromLayout( windowRect, + AknLayoutScalable_Avkon::grid_tb_float_ext_pane( 0 ) ); + + cellExtRect = RectFromLayout( gridExtRect, + AknLayoutScalable_Avkon::cell_tb_float_ext_pane( 0, 0, 0 ) ); + } + else + { + extensionRect = RectFromLayout( mainPaneRect, + AknLayoutScalable_Avkon::popup_tb_extension_window( 0 ) ); + + windowRect = TRect( TPoint(), extensionRect.Size() ); + + gridExtRect = RectFromLayout( windowRect, + AknLayoutScalable_Avkon::grid_tb_ext_pane( landscape ? 1 : 0 ) ); + + cellExtRect = RectFromLayout( gridExtRect, + AknLayoutScalable_Avkon::cell_tb_ext_pane( landscape ? 1 : 0, 0, 0 ) ); + } + + TSize buttonSize = cellExtRect.Size(); + + iNumberOfColumns = gridExtRect.Width() / buttonSize.iWidth; + + // Calculate and set controls positions according to layout rects + TInt extensionWidth = CalculateControlPositions( + windowRect, gridExtRect, cellExtRect ); + + //In some cases, extension height is more larger than grid rect. + //And for they are only used to define the margin size, width is more exact than height. + TSize viewSize( extensionWidth + ( extensionRect.Width() - gridExtRect.Width() ), + ( extensionRect.Width() - gridExtRect.Width() ) + iNumberOfRows * + buttonSize.iHeight ); + + TInt variety = GetVariety( iNumberOfRows - 1, landscape ); + + // To get the correct y-coordinate + TRect positionRect = RectFromLayout( mainPaneRect, floating ? + AknLayoutScalable_Avkon::popup_tb_float_extension_window( variety ) : + AknLayoutScalable_Avkon::popup_tb_extension_window( variety ) ); + + if( landscape && !floating ) + { + + TRect extButtonRect( iExtension->Rect() ); + + // Calculate new y coordinate according to button middle point + TInt newY = extButtonRect.iTl.iY + mainPaneRect.iTl.iY; + // Check that rect with new y fits to extension view area + if( newY < extensionRect.iTl.iY ) // Top + { + newY = extensionRect.iTl.iY; + } + else if( newY + viewSize.iHeight > extensionRect.iBr.iY ) // Bottom + { + newY = positionRect.iTl.iY; + } + positionRect.iTl.iY = newY; + } + //In some case, such as browser application, + //view position is incorrect in portait mode. So, reset the position + //according to the view size and toolbar window position. + else if ( !landscape && !floating + && iExtension && iExtension->DrawableWindow() ) + { + TPoint buttonPos = iExtension->DrawableWindow()->Position(); + TInt newY = buttonPos.iY - viewSize.iHeight; + if ( newY < extensionRect.iTl.iY ) + { + newY = extensionRect.iTl.iY; + } + positionRect.iTl.iY = newY; + } + + TInt xCoordinate = extensionRect.iTl.iX; + // Get + if ( iNumberOfRows == 1 ) + { + variety = 0; + // Currently checking from number of items, might need to be changed + if ( iVisibleItems.Count() == 2 ) + { + variety = landscape ? 5 : 1; + } + else if ( iVisibleItems.Count() == 3 && landscape) + { + variety = 6; + } + extensionRect = RectFromLayout( mainPaneRect, + AknLayoutScalable_Avkon::popup_tb_extension_window( variety ) ); + xCoordinate = extensionRect.iTl.iX; + } + + TPoint position( xCoordinate, positionRect.iTl.iY ); + + TRect outerRect( TPoint(), viewSize ); + TRect innerRect(outerRect); + + TAknWindowLineLayout unit = AknLayoutScalable_Avkon::aid_value_unit2().LayoutLine(); + innerRect.Shrink( unit.iW/10, unit.iH/10 ); + iFrameContext->SetFrameRects( outerRect , innerRect ); + + return TRect( position, viewSize ); + } + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::CalculateControlPositions +// +// ----------------------------------------------------------------------------- +// +TInt CAknToolbarExtensionView::CalculateControlPositions( TRect& aWindowRect, + TRect& aGridRect, + TRect& aCellRect ) + { + TInt width( 0 ), extensionWidth( 0 ), row( 0 ); + TPoint controlPosition( 0, 0 ); + TInt maxNumberOfRows = aGridRect.Height() / aCellRect.Height(); + TSize cellSize = aCellRect.Size(); + TInt extGridRight = aGridRect.iBr.iX; + TInt extGridLeft = aGridRect.iTl.iX; + TBool floating = !IsNonFocusing(); + // iVisibleItems may not be updated, so count hidden items + TInt visibleItems( iItems.Count() - CountHiddenItems() ); + + // If extension does not fill the whole grid rect, this takes the missing + // cells width into account when locating items from right to left + if ( AknLayoutUtils::LayoutMirrored() && visibleItems < iNumberOfColumns ) + { + TInt missingCells( iNumberOfColumns - visibleItems ); + extGridRight = aGridRect.iBr.iX - cellSize.iWidth * missingCells; + } + + // Fetch button icon size + TSize iconSize; + if ( floating ) + { + iconSize = RectFromLayout( aCellRect, + AknLayoutScalable_Avkon::cell_tb_float_ext_pane_g1( 1 ) ).Size(); + } + else + { + iconSize = RectFromLayout( aCellRect, + AknLayoutScalable_Avkon::cell_tb_ext_pane_g1( 1 ) ).Size(); + } + + for ( TInt i = 0; i < iItems.Count(); i++ ) + { + if ( iItems[i]->IsHidden() ) + { + continue; + } + // Buttons + if ( iItems[i]->ControlType() == EAknCtButton ) + { + + // Layout items from right to left -> calculate position from right + // end of the grid rect + if ( AknLayoutUtils::LayoutMirrored() ) + { + controlPosition.SetXY( extGridRight - width - cellSize.iWidth, + aGridRect.iTl.iY + row * cellSize.iHeight ); + } + // Left to right + else + { + controlPosition.SetXY( extGridLeft + width, + aGridRect.iTl.iY + row * cellSize.iHeight ); + } + + width += cellSize.iWidth; + iItems[i]->Control()->SetExtent( controlPosition, cellSize ); + TRAP_IGNORE( iVisibleItems.AppendL( iItems[i] ) ); + CAknButton* button = static_cast( + iItems[i]->Control() ); + button->SetIconSize( iconSize ); + if ( floating ) + { + TRect highlightRect = RectFromLayout( + TRect( controlPosition, cellSize ), + AknLayoutScalable_Avkon::grid_highlight_pane_cp12( 0 ) ); + iItems[i]->SetHighlightRect( highlightRect ); + } + } + // Editors take the whole row + else if ( Editor( iItems[i]->ControlType() ) ) + { + // Changing to next line + if ( width > 0 ) + { + width = 0; + row++; + } + if ( row >= maxNumberOfRows ) + { + break; + } + + TInt position = maxNumberOfRows - row - 1; + TRAP_IGNORE( ResizeFindPaneL( aWindowRect, + Layout_Meta_Data::IsLandscapeOrientation(), position, i ) ); + width = aGridRect.Width(); + } + else + { + // Other controls here later.. + } + + extensionWidth = Max( extensionWidth , width ); + + // No more items to this row + if ( width + cellSize.iWidth > aGridRect.Width() ) + { + width = 0; + // No more item to extension + if ( row + 1 >= maxNumberOfRows || i + 1 == iItems.Count() ) + { + break; + } + + // Switch row only if there are visible items left to locate + if ( iVisibleItems.Count() < visibleItems ) + { + row++; + } + } + + } + iNumberOfRows = row + 1; + return extensionWidth; + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::CountHiddenItems +// Returns hidden items count +// ----------------------------------------------------------------------------- +// +TInt CAknToolbarExtensionView::CountHiddenItems() + { + TInt hiddenItems( 0 ); + for ( TInt i = 0; i < iItems.Count(); i++ ) + { + if ( iItems[i]->IsHidden() ) + { + hiddenItems++; + } + } + return hiddenItems; + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::SelectItemL +// Selects or unselects items +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::SelectItemL( TInt aIndex, TBool aSelect ) + { + if ( aSelect ) + { + if ( aIndex != iSelectedItem ) + { + if ( iSelectedItem > KNoItemSelected && + iSelectedItem < iVisibleItems.Count() ) + { + iVisibleItems[iSelectedItem]->SetIsSelectedL( EFalse ); + } + + if ( aIndex > KNoItemSelected && aIndex < iVisibleItems.Count() ) + { + if ( iVisibleItems[aIndex]->SetIsSelectedL( ETrue ) ) + { + iSelectedItem = aIndex; + } + else + { + iSelectedItem = KNoItemSelected; + } + } + else + { + iSelectedItem = KNoItemSelected; + } + } + } + else + { + if ( aIndex == iSelectedItem ) + { + if ( aIndex != KNoItemSelected && aIndex < iVisibleItems.Count() ) + { + iVisibleItems[aIndex]->SetIsSelectedL( EFalse ); + } + iSelectedItem = KNoItemSelected; + } + } + } + + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::RectFromLayout +// ----------------------------------------------------------------------------- +// +TRect CAknToolbarExtensionView::RectFromLayout( const TRect& aParent, + const TAknWindowComponentLayout& aComponentLayout ) const + { + TAknWindowLineLayout lineLayout = aComponentLayout.LayoutLine(); + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( aParent, lineLayout ); + return layoutRect.Rect(); + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::ResizeFindPane +// Resizes editor and the button after it. +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::ResizeFindPaneL( TRect& aWindowRect, TBool aLandscape, + TInt aPosition, TInt& aIndex ) + { + TRect editorRect = RectFromLayout( aWindowRect, + AknLayoutScalable_Avkon::tb_ext_find_pane( aLandscape ? 1 : 0 ) ); + + editorRect.Move( 0, -editorRect.Height() * ( aPosition ) ); + + TAknTextLineLayout layoutLine = + AknLayoutScalable_Avkon::tb_ext_find_pane_t1( 0 ).LayoutLine(); + TAknLayoutText layoutText; + layoutText.LayoutText( editorRect, layoutLine ); + // Using curretly the skin color id of hwr/vkb input field + TAknsQsnTextColorsIndex colorIndex = EAknsCIQsnTextColorsCG60; + + CEikEdwin* edwin = static_cast( iItems[aIndex]->Control() ); + AknLayoutUtils::LayoutEdwin( edwin, editorRect, layoutLine, colorIndex ); + + iVisibleItems.AppendL( iItems[aIndex] ); + + if ( aIndex + 1 >= iItems.Count() || iItems[aIndex +1]->ControlType() != + EAknCtButton ) + { + // If no button after editor, then return + return; + } + aIndex++; + // Now calculate the size for the button after editor + TRect findButtonRect = RectFromLayout( editorRect, + AknLayoutScalable_Avkon::tb_ext_find_button_pane( 0 ) ); + iItems[aIndex]->Control()->SetRect( findButtonRect ); + iVisibleItems.AppendL( iItems[aIndex] ); + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::GetVariety +// ----------------------------------------------------------------------------- +// +TInt CAknToolbarExtensionView::GetVariety( TInt aRow, TBool aLandscape ) + { + TInt variety = 0; + if ( IsNonFocusing() ) + { + TInt index = iExtension->ExtensionPosition(); + switch ( aRow ) + { + case 0: + if ( index == 0 ) + { + variety = aLandscape ? 7 : 2; + } + else if ( index == 1 ) + { + variety = aLandscape ? 6 : 2; + } + else + { + variety = aLandscape ? 5 : 1; + } + break; + case 1: + if ( index == 0 ) + { + variety = aLandscape ? 0 : 3; + } + else if ( index == 1 ) + { + variety = aLandscape ? 6 : 3; + } + else + { + variety = aLandscape ? 8 : 3; + } + break; + case 2: + default: + variety = aLandscape ? 0 : 4; + break; + case 3: + variety = 0; + break; + } + } + else + { + switch ( aRow ) + { + case 0: + variety = 3; + break; + case 1: + variety = 2; + break; + case 2: + variety = 1; + break; + case 3: + default: + variety = 0; + break; + } + } + return variety; + } + + +// ----------------------------------------------------------------------------- +// When an item is added, hidden or removed, there is a need to check that +// the buttons have correct frames. +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::CheckButtonFrames( TBool aAdd, TInt aIndex ) + { + // @todo What if adding editors? Then need to check next buttons, does this + // work then? + + // this is the index from which to remove noframes flag if necessary + TInt index = aIndex; + if ( aIndex > 0 && Editor( iItems[aIndex - 1]->ControlType() ) ) + { + // Add here later code also for hiding/unhiding + if ( iItems[aIndex]->ControlType() == EAknCtButton ) + { + CAknButton* button = static_cast( iItems[aIndex]->Control() ); + TInt flags = button->ButtonFlags(); + // Add frames for the button because it comes after an editor + if ( flags & KAknButtonNoFrame ) + { + flags &= ~KAknButtonNoFrame; + flags &= ~KAknButtonPressedDownFrame; + button->UnregisterResourceProvider(); + button->SetButtonFlags( flags ); + } + } + index++; + } + + if ( aAdd && iItems.Count() > index && + iItems[index]->ControlType() == EAknCtButton ) + { + CAknButton* button = static_cast( iItems[index]->Control() ); + TInt flags = button->ButtonFlags(); + // Checking that the button that was previously after editor + // does not have frames + if ( !( flags & KAknButtonNoFrame ) || !( flags & KAknButtonPressedDownFrame ) ) + { + flags |= KAknButtonNoFrame; + flags |= KAknButtonPressedDownFrame; + button->RegisterResourceProvider( iResourceProvider ); + button->SetButtonFlags( flags ); + } + } + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::ToolbarItemIndexById +// Returns the index of the toolbar item inside of the iItems or iVisibleItems +// array. +// ----------------------------------------------------------------------------- +// +TInt CAknToolbarExtensionView::ToolbarItemIndexById( TBool aVisibleItems, + const TInt aId ) const + { + for ( TInt i = 0; i < aVisibleItems ? iVisibleItems.Count() : + iItems.Count(); i++ ) + { + CAknToolbarItem* item = aVisibleItems ? iVisibleItems[i] : iItems[i]; + if ( item && item->CommandId() == aId ) + { + return i; + } + } + return KErrNotFound; + } + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::MoveHighlightL +// Moves highlight from one item to another. Does nothing if this is fixed +// toolbar extension's view. +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::MoveHighlightL( TInt aDirection, TInt aIndex ) + { + if ( IsNonFocusing() || !iVisibleItems.Count() ) + { + iSelectedItem = KNoItemSelected; + return; + } + + TInt oldFocused = iSelectedItem; + if ( iSelectedItem == KNoItemSelected ) + { + iSelectedItem = 0; + } + + switch ( aDirection ) + { + case EDirectionUp: + { + iSelectedItem = NextFocusable( -iNumberOfColumns ); + break; + } + + case EDirectionDown: + { + iSelectedItem = NextFocusable( iNumberOfColumns ); + break; + } + case EDirectionRight: + { + iSelectedItem = NextFocusable( 1 ); + break; + } + + case EDirectionLeft: + { + iSelectedItem = NextFocusable( -1 ); + break; + } + case ENoDirection: + { + iSelectedItem = aIndex; + break; + } + } + + CAknToolbarItem* item = NULL; + + if ( iSelectedItem != KNoItemSelected ) + { + item = iVisibleItems[iSelectedItem]; + + // set this item focused + item->SetFocusL( ETrue, EFalse, ENoDrawNow, this ); + DrawNow( item->HighlightRect() ); + } + item = NULL; + + if ( oldFocused != KNoItemSelected && oldFocused != aIndex ) + { + item = iVisibleItems[oldFocused]; + if ( item && item->Control() ) + { + SelectItemL( oldFocused, EFalse ); + + // take the focus away + item->SetFocusL( EFalse, EFalse, EDrawNow, this ); + DrawNow( item->HighlightRect() ); + } + } + } + + + +// ----------------------------------------------------------------------------- +// CAknToolbarExtensionView::NextFocusable +// Calculates next focusable item. Used with floating toolbar extension. +// ----------------------------------------------------------------------------- +// +TInt CAknToolbarExtensionView::NextFocusable( TInt aStep ) + { + TInt index = iSelectedItem; + TInt startIndex = iSelectedItem; + + CAknButton* button = NULL; + // we will do it till we don't get valid non-dimmed item or till we don't + // make the whole round ( all items are dimmed ) + do + { + button = NULL; + if ( aStep == 1 && index >= iVisibleItems.Count() - 1 ) + { + index = 0; + } + else if ( aStep == -1 && index == 0 ) + { + index = iVisibleItems.Count() - 1; + } + else if ( aStep > 1 ) + { + if ( index + aStep >= iVisibleItems.Count() ) + { + index = ( index + 1 ) % aStep; + } + else + { + index += aStep; + } + } + else if ( aStep < -1 ) + { + if ( index + aStep < 0 ) + { + TInt modResult = index - 1; + index = iVisibleItems.Count() - 1 ; + if ( modResult < 0 ) + { + modResult = iNumberOfColumns - 1; + } + while ( index % ( +aStep ) != modResult ) + { + index--; + } + } + else + { + index += aStep; + } + } + else + { + index += aStep; + } + button = static_cast( iVisibleItems[index]->Control() ); + + } while ( ( !button || button->IsDimmed() ) && startIndex != index ); + + return index; + } + + +// ----------------------------------------------------------------------------- +// Sets item dimmed +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::SetItemDimmed( TInt aCommandId, TBool aDimmed ) + { + CCoeControl* control = ControlOrNull( aCommandId ); + if ( control ) + { + control->SetDimmed( aDimmed ); + if ( IsVisible() ) + { + control->DrawNow(); + } + } + } + +// ----------------------------------------------------------------------------- +// Hides an item +// ----------------------------------------------------------------------------- +// +void CAknToolbarExtensionView::HideItemL( TInt aCommandId, TBool aHide ) + { + CAknToolbarItem* item = NULL; + for ( TInt i=0; i < iItems.Count(); i++ ) + { + if ( aCommandId == iItems[i]->CommandId() ) + { + item = iItems[i]; + break; + } + } + + if ( item && item->Control() && item->IsHidden() != aHide ) + { + item->SetHidden( aHide ); + } + } + +//end file