--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/aknnavide.cpp Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1946 @@
+/*
+* Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation of the decorator class for navigation
+* pane controls.
+*
+*/
+
+
+// SYSTEM INCLUDE FILES
+#include <AknsUtils.h>
+#include <AknsDrawUtils.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <layoutmetadata.cdl.h>
+#include <touchfeedback.h>
+
+#include <AknTasHook.h>
+// USER INCLUDE FILES
+#include "aknappui.h"
+#include "aknconsts.h"
+#include "aknnavilabel.h"
+#include "aknnavide.h"
+#include "AknNaviObserver.h"
+#include "AknUtils.h"
+#include "AknStatuspaneUtils.h"
+#include "AknNaviDecoratorObserver.h"
+#include "akntabgrp.h"
+#include "akntitle.h"
+#include "AknTitlePaneLabel.h"
+
+
+const TInt KEikNavidePointerRepeatInterval = 500000; // in micro seconds
+
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+NONSHARABLE_CLASS( CAknNavigationDecoratorExtension ) : public CBase
+ {
+public:
+ enum
+ {
+ ENaviDecoratorNoSide = 0,
+ ENaviDecoratorLeftSide,
+ ENaviDecoratorRightSide
+ };
+
+public:
+ static CAknNavigationDecoratorExtension* NewL();
+ ~CAknNavigationDecoratorExtension();
+
+private:
+ CAknNavigationDecoratorExtension();
+ CAknNavigationDecoratorExtension( const CAknNavigationDecoratorExtension* aExtension );
+
+public:
+ CPeriodic* iTimer;
+ TInt iEffectTimerCount;
+ TInt iOutermostRepeats;
+ TInt iBlinkingSide;
+ };
+
+CAknNavigationDecoratorExtension* CAknNavigationDecoratorExtension::NewL()
+ {
+ CAknNavigationDecoratorExtension* naviExtension =
+ new (ELeave) CAknNavigationDecoratorExtension();
+ return naviExtension;
+ }
+
+CAknNavigationDecoratorExtension::CAknNavigationDecoratorExtension() :
+ iTimer(NULL), iEffectTimerCount(0), iOutermostRepeats(0), iBlinkingSide(0)
+ {
+ }
+
+CAknNavigationDecoratorExtension::~CAknNavigationDecoratorExtension()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// IsMaskAllBlack
+//
+// Checks whether the given bitmap is all black (first row ignored).
+// The width of the bitmap is assumed to be 8 or less (sufficient for arrows).
+//
+// Returns: Boolean value.
+// -----------------------------------------------------------------------------
+//
+static TBool IsMaskAllBlack( CFbsBitmap* bitmap )
+ {
+ if ( !bitmap )
+ {
+ return EFalse;
+ }
+
+ TSize size( bitmap->SizeInPixels() );
+
+ if ( size.iWidth > 8 )
+ {
+ return EFalse;
+ }
+
+ TBuf8<8> scanLineBuf;
+
+ for ( TInt y = 1; y < size.iHeight; y++ )
+ {
+ bitmap->GetScanLine( scanLineBuf,
+ TPoint( 0, y ),
+ size.iWidth,
+ EGray256 );
+ for ( TInt x = 0; x < size.iWidth; x++ )
+ {
+ if ( scanLineBuf[x] != 0 )
+ {
+ return EFalse;
+ }
+ }
+ }
+
+ return ETrue;
+ }
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+EXPORT_C CAknNavigationDecorator* CAknNavigationDecorator::NewL(
+ CAknNavigationControlContainer* /*aNavigationControlContainer*/,
+ CCoeControl* aDecoratedControl,
+ TControlType aType )
+ {
+ CleanupStack::PushL( aDecoratedControl );
+ CAknNavigationDecorator* self = new (ELeave) CAknNavigationDecorator;
+
+ self->iDecoratedControl = aDecoratedControl;
+
+ CleanupStack::Pop( aDecoratedControl );
+
+ // Control type must be set before calling constructor.
+ self->iControlType = aType;
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self ); // self
+ AKNTASHOOK_ADDL( self, "CAknNavigationDecorator" );
+ return self;
+ }
+
+EXPORT_C CAknNavigationDecorator::~CAknNavigationDecorator()
+ {
+ AKNTASHOOK_REMOVE();
+ if ( iContainer )
+ {
+ iContainer->Pop( this );
+ }
+
+ if ( iLayoutStyleTimer )
+ {
+ iLayoutStyleTimer->Cancel();
+ delete iLayoutStyleTimer;
+ }
+
+ if( iExtension && iExtension->iTimer )
+ {
+ if ( iExtension->iTimer->IsActive() )
+ {
+ CancelTimer();
+ }
+
+ delete iExtension->iTimer;
+ }
+
+ delete iExtension;
+ delete iDecoratedControl;
+ }
+
+
+EXPORT_C void CAknNavigationDecorator::ConstructL()
+ {
+ iDecoratedControl->SetObserver( this );
+
+ iNaviArrowsVisible = EFalse;
+ iNaviArrowLeftDimmed = ETrue;
+ iNaviArrowRightDimmed = ETrue;
+
+ TBool isLandscape( Layout_Meta_Data::IsLandscapeOrientation() );
+
+ iLayoutStyleTimer = CPeriodic::NewL( CActive::EPriorityIdle );
+ if ( AknStatuspaneUtils::FlatLayoutActive() &&
+ !isLandscape )
+ {
+ iLayoutFlags |= ENaviControlLayoutNarrow;
+ iLayoutFlags |= ENaviControlLayoutModeForced;
+ }
+
+ // Wide layout is used in usual portrait mode,
+ // except for tabs in non-touch layouts.
+ else if ( AknStatuspaneUtils::UsualLayoutActive() &&
+ !isLandscape &&
+ ( iControlType != ETabGroup ||
+ AknLayoutUtils::PenEnabled() ) )
+ {
+ iLayoutFlags |= ENaviControlLayoutWide;
+ iLayoutFlags |= ENaviControlLayoutModeForced;
+ }
+ else
+ {
+ iLayoutFlags |= ENaviControlLayoutNormal;
+ iLayoutFlags |= ENaviControlLayoutModeAutomatic;
+ }
+
+ iExtension = CAknNavigationDecoratorExtension::NewL();
+
+ ActivateL();
+ }
+
+EXPORT_C CCoeControl* CAknNavigationDecorator::DecoratedControl()
+ {
+ // In case the decorated control is of the ENaviVolume type, this
+ // function returns the CAknVolumeControl object which is a component
+ // control of the volume popup, instead of the volume popup control itself.
+ // This is in order to maintain BC.
+ if ( iControlType == ENaviVolume )
+ {
+ CCoeControl* volumeControl = iDecoratedControl->ComponentControl( 5 );
+
+ if ( volumeControl )
+ {
+ return volumeControl;
+ }
+ }
+
+ return iDecoratedControl;
+ }
+
+EXPORT_C void CAknNavigationDecorator::MakeScrollButtonVisible( TBool aVisible )
+ {
+ TBool differ = ( iNaviArrowsVisible != aVisible );
+
+ iNaviArrowsVisible = aVisible;
+
+ if ( iControlType == ENaviLabel )
+ {
+ if ( iNaviArrowsVisible )
+ {
+ STATIC_CAST( CAknNaviLabel*, iDecoratedControl )->
+ SetNaviLabelType( CAknNaviLabel::ENavigationLabel );
+ }
+ else
+ {
+ STATIC_CAST( CAknNaviLabel*, iDecoratedControl )->
+ SetNaviLabelType( CAknNaviLabel::EAdditionalInfoLabel );
+ }
+ }
+ else if ( iControlType == ETabGroup )
+ {
+ static_cast<CAknTabGroup*>(
+ iDecoratedControl )->SetNaviArrowsVisible( aVisible );
+ }
+
+ if ( differ )
+ {
+ SizeChanged();
+ }
+ }
+
+EXPORT_C TBool CAknNavigationDecorator::ScrollButtonVisible() const
+ {
+ return iNaviArrowsVisible;
+ }
+
+EXPORT_C void CAknNavigationDecorator::SetScrollButtonDimmed(
+ TScrollButton aButton,
+ TBool aDimmed )
+ {
+ if ( aButton == ELeftButton )
+ {
+ iNaviArrowLeftDimmed = aDimmed;
+
+ if ( aDimmed )
+ {
+ iExtension->iBlinkingSide =
+ CAknNavigationDecoratorExtension::ENaviDecoratorRightSide;
+ }
+ }
+ if ( aButton == ERightButton )
+ {
+ iNaviArrowRightDimmed = aDimmed;
+
+ if ( aDimmed )
+ {
+ iExtension->iBlinkingSide =
+ CAknNavigationDecoratorExtension::ENaviDecoratorLeftSide;
+ }
+ }
+ }
+
+EXPORT_C TBool CAknNavigationDecorator::IsScrollButtonDimmed(
+ TScrollButton aButton ) const
+ {
+ if ( aButton == ELeftButton )
+ {
+ return iNaviArrowLeftDimmed;
+ }
+ if ( aButton == ERightButton )
+ {
+ return iNaviArrowRightDimmed;
+ }
+ return ETrue;
+ }
+
+EXPORT_C void CAknNavigationDecorator::SetControlType( TControlType aType )
+ {
+ iControlType = aType;
+ }
+
+EXPORT_C CAknNavigationDecorator::TControlType CAknNavigationDecorator::ControlType() const
+ {
+ return iControlType;
+ }
+
+EXPORT_C void CAknNavigationDecorator::SizeChanged()
+ {
+ if ( iControlType == ENaviVolume )
+ {
+ // The control for ENaviVolume type does not reside in the navi pane
+ // anymore, so the control size doesn't need to be adjusted if navi pane
+ // size changes.
+ return;
+ }
+
+ TBool isLandscape( Layout_Meta_Data::IsLandscapeOrientation() );
+ TBool flatLayout( AknStatuspaneUtils::FlatLayoutActive() );
+
+ if ( isLandscape &&
+ flatLayout &&
+ !AknLayoutUtils::PenEnabled() &&
+ NaviControlLayoutMode() == ENaviControlLayoutModeAutomatic &&
+ NaviControlLayoutStyle() == ENaviControlLayoutNormal )
+ {
+ if ( iLayoutStyleTimer && !iLayoutStyleTimer->IsActive() )
+ {
+ InitLayoutStyleTimer();
+ }
+ }
+ else
+ {
+ CancelLayoutStyleTimer();
+ }
+
+ TBool wideInUseInLsc( EFalse );
+
+ if ( NaviControlLayoutStyle() != ENaviControlLayoutNarrow &&
+ flatLayout &&
+ !isLandscape )
+ {
+ iLayoutFlags &= ~ENaviControlLayoutNormal;
+ iLayoutFlags &= ~ENaviControlLayoutWide;
+ iLayoutFlags |= ENaviControlLayoutNarrow;
+ }
+
+ // Only flat layout supports narrow mode for now.
+ if ( NaviControlLayoutStyle() == ENaviControlLayoutNarrow )
+ {
+ if ( !flatLayout ||
+ ( isLandscape && AknLayoutUtils::PenEnabled() ) )
+ {
+ iLayoutFlags &= ~ENaviControlLayoutNarrow;
+ iLayoutFlags |= ENaviControlLayoutNormal;
+ }
+ }
+ // Wide layout is supported only in portrait mode.
+ else if ( NaviControlLayoutStyle() == ENaviControlLayoutWide )
+ {
+ if ( Layout_Meta_Data::IsLandscapeOrientation() )
+ {
+ wideInUseInLsc = ETrue;
+ }
+ }
+
+ if ( NaviControlLayoutStyle() == ENaviControlLayoutNarrow &&
+ NaviControlLayoutStyleSupported( ENaviControlLayoutNarrow ) )
+ {
+ SizeChangedInNarrowLayout();
+ }
+ else if ( NaviControlLayoutStyle() == ENaviControlLayoutWide &&
+ !wideInUseInLsc )
+ {
+ SizeChangedInWideLayout();
+ }
+ else // Normal layout
+ {
+ SizeChangedInNormalLayout();
+ }
+
+ // Finally call the navi arrow bitmap getter, as it will
+ // resize the navi arrows to correct size.
+ if ( iContainer )
+ {
+ iContainer->NaviArrowBitmap( 0 );
+ iContainer->NaviArrowBitmap( 1 );
+ }
+ }
+
+void CAknNavigationDecorator::SizeChangedInNormalLayout()
+ {
+ TRect rect;
+ TRect leftArrowRect;
+ TRect rightArrowRect;
+
+ CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
+ if ( statusPane &&
+ statusPane->CurrentLayoutResId() == R_AVKON_STATUS_PANE_LAYOUT_USUAL_EXT &&
+ iControlType == ETabGroup )
+ {
+ // At the moment this special handling is required for tab group
+ // in portrait mode, because tabs don't support wide navi pane layout yet.
+ TAknLayoutRect layoutRect;
+
+ TRect screenRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screenRect );
+
+ TBool isHDLayoutActive( AknStatuspaneUtils::HDLayoutActive() );
+
+ TAknWindowComponentLayout topArea(
+ AknLayoutScalable_Avkon::area_top_pane( isHDLayoutActive ? 8 : 0 ) );
+ TAknWindowComponentLayout spLayout(
+ AknLayoutScalable_Avkon::status_pane( isHDLayoutActive ? 1 : 0 ) );
+
+ TAknWindowComponentLayout layout(
+ TAknWindowComponentLayout::Compose( topArea, spLayout ) );
+
+ layoutRect.LayoutRect( screenRect, layout );
+ TRect spRect( layoutRect.Rect() );
+
+ layoutRect.LayoutRect(
+ spRect,
+ AknLayoutScalable_Avkon::navi_pane( isHDLayoutActive ? 8 : 5 ) );
+ rect = layoutRect.Rect();
+ rect.Move( -rect.iTl.iX, -rect.iTl.iY );
+ leftArrowRect = NaviArrowRect( ELeftButton, EFalse, rect );
+ rightArrowRect = NaviArrowRect( ERightButton, EFalse, rect );
+ }
+ else
+ {
+ rect = ParentRect();
+
+ if ( iControlType == ENaviVolume &&
+ !Layout_Meta_Data::IsLandscapeOrientation() &&
+ AknStatuspaneUtils::SmallLayoutActive() )
+ {
+ // Small status pane volume control has it's own positions for
+ // navi arrows, but in landscape the data doesn't exist
+ // so normal navi arrow positions are used.
+
+ // These layout data items aren't mirrored.
+ TBool layoutMirrored( AknLayoutUtils::LayoutMirrored() );
+
+ TRect naviPaneRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ENaviPane,
+ naviPaneRect );
+
+ naviPaneRect.Move( -naviPaneRect.iTl.iX,
+ -naviPaneRect.iTl.iY );
+
+ TAknLayoutRect layoutRect;
+ layoutRect.LayoutRect(
+ naviPaneRect,
+ layoutMirrored ?
+ AknLayoutScalable_Avkon::status_small_pane_g6( 0 ) :
+ AknLayoutScalable_Avkon::status_small_pane_g5( 0 ) );
+ leftArrowRect = layoutRect.Rect();
+
+ layoutRect.LayoutRect(
+ naviPaneRect,
+ layoutMirrored ?
+ AknLayoutScalable_Avkon::status_small_pane_g5( 0 ) :
+ AknLayoutScalable_Avkon::status_small_pane_g6( 0 ) );
+ rightArrowRect = layoutRect.Rect();
+ }
+ else
+ {
+ leftArrowRect = NaviArrowRect( ELeftButton );
+ rightArrowRect = NaviArrowRect( ERightButton );
+ }
+ }
+
+ if ( iControlType == ETabGroup )
+ {
+ rect = DecoratedTabControlRect( AknLayoutUtils::PenEnabled(),
+ ETrue );
+ }
+
+ iArrowRightSize = rightArrowRect.Size();
+ iArrowLeftSize = leftArrowRect.Size();
+
+ iArrowRightPos = TPoint( rightArrowRect.iTl.iX, rect.iTl.iY );
+ iArrowLeftPos = TPoint( leftArrowRect.iTl.iX, rect.iTl.iY );
+
+ TSize rectSize( rect.Size() );
+
+ // In case the decorated control is tab group, the tab layout mode
+ // must be set before it's size is set.
+ if ( iControlType == ETabGroup )
+ {
+ CAknTabGroup* tabGroup = static_cast <CAknTabGroup*> (iDecoratedControl);
+ TRAP_IGNORE( tabGroup->SetNarrowTabLayoutL( EFalse ) );
+ }
+
+ if ( ScrollButtonVisible() )
+ {
+ iDecoratedControl->SetRect( rect );
+ }
+ else
+ {
+ iDecoratedControl->SetRect( Rect() );
+ }
+ }
+
+
+void CAknNavigationDecorator::SizeChangedInNarrowLayout()
+ {
+ TRect rect( DecoratedControlNarrowRect( this->ControlType() ) );
+
+ TRect leftArrowRect( NaviArrowRect( ELeftButton, ETrue ) );
+ TRect rightArrowRect( NaviArrowRect( ERightButton, ETrue ) );
+
+ iArrowRightSize = rightArrowRect.Size();
+ iArrowRightPos = rightArrowRect.iTl;
+
+ iArrowLeftSize = leftArrowRect.Size();
+ iArrowLeftPos = leftArrowRect.iTl;
+
+ // Tab group is handled specificly...
+ if ( iControlType == ETabGroup )
+ {
+ // Note. Size is set bigger than normally.
+ // Tabs take this into account in layout calculations (akntabgrp.cpp).
+ iDecoratedControl->SetRect( Rect() );
+ CAknTabGroup* tabGroup = static_cast <CAknTabGroup*> (iDecoratedControl);
+ // This sets tab size using animation.
+ TBool useAnimation( Layout_Meta_Data::IsLandscapeOrientation() );
+ TRAP_IGNORE( tabGroup->SetNarrowTabLayoutL( ETrue, useAnimation ) );
+ }
+ else
+ {
+ if ( ScrollButtonVisible() )
+ {
+ iDecoratedControl->SetRect( TRect( iArrowLeftPos.iX + iArrowLeftSize.iWidth,
+ rect.iTl.iY,
+ iArrowRightPos.iX,
+ rect.iBr.iY ) );
+ }
+ else
+ {
+ iDecoratedControl->SetRect( rect );
+ }
+ }
+ }
+
+
+void CAknNavigationDecorator::SizeChangedInWideLayout()
+ {
+ TRect rect( Rect() );
+ TRect parentRect;
+
+ if ( iControlType == ETabGroup &&
+ !AknLayoutUtils::PenEnabled() )
+ {
+ parentRect = DecoratedTabControlRect( EFalse, ETrue );
+ }
+ else
+ {
+ parentRect = ParentRect();
+ }
+
+ if ( rect.Width() < parentRect.Width() ||
+ rect.Height() < parentRect.Height() )
+ {
+ rect = parentRect;
+ }
+
+ TRect leftArrowRect( NaviArrowRect( ELeftButton ) );
+ TRect rightArrowRect( NaviArrowRect( ERightButton ) );
+
+ iArrowRightSize = rightArrowRect.Size();
+ iArrowLeftSize = leftArrowRect.Size();
+
+ if ( ScrollButtonVisible() )
+ {
+ rect.iTl.iX += iArrowRightSize.iWidth;
+ rect.iBr.iX -= iArrowLeftSize.iWidth;
+ }
+
+ if ( parentRect.Height() < rect.Height() )
+ {
+ iArrowRightPos = TPoint( rect.iBr.iX, parentRect.iTl.iY );
+ iArrowLeftPos = TPoint( rect.iTl.iX - iArrowLeftSize.iWidth, parentRect.iTl.iY );
+ }
+ else
+ {
+ iArrowRightPos = TPoint( rect.iBr.iX, rightArrowRect.iTl.iY );
+ iArrowLeftPos = TPoint( rect.iTl.iX - iArrowLeftSize.iWidth, iArrowRightPos.iY );
+ }
+
+ // In case the decorated control is tab group, the tab layout mode
+ // must be set before it's size is set.
+ if ( iControlType == ETabGroup )
+ {
+ CAknTabGroup* tabGroup = static_cast <CAknTabGroup*> ( iDecoratedControl );
+ TRAP_IGNORE( tabGroup->SetNarrowTabLayoutL( EFalse) );
+ }
+
+ iDecoratedControl->SetRect( rect );
+ }
+
+EXPORT_C TInt CAknNavigationDecorator::CountComponentControls() const
+ {
+ if ( iContainer && iDecoratedControl )
+ {
+ return 1;
+ }
+
+ return 0;
+ }
+
+
+EXPORT_C CCoeControl* CAknNavigationDecorator::ComponentControl(TInt /*aIndex*/) const
+ {
+ // DecoratedControl() isn't declared as const but doesn't actually
+ // change anything.
+ return ( const_cast<CAknNavigationDecorator*>(this)->DecoratedControl() );
+ }
+
+
+EXPORT_C void* CAknNavigationDecorator::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknNavigationDecorator::HandlePointerEventL
+// Handles pointer events by checking first if the pointer event was
+// in the arrow areas and sending the arrow event to observer,
+// and if not sending the pointer event to all child components.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknNavigationDecorator::HandlePointerEventL(
+ const TPointerEvent& aPointerEvent )
+ {
+ if ( AknLayoutUtils::PenEnabled() )
+ {
+ TRect naviPaneRect( ParentRect() );
+ TRect parentRect = naviPaneRect;
+
+ TRect statusPaneRect;
+ AknLayoutUtils::LayoutMetricsRect(
+ AknLayoutUtils::EStatusPane, statusPaneRect );
+
+ // In certain status pane layouts the navi pane has extended
+ // touch responsive area in the layout data which is larger
+ // than the actual decorator size.
+ CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
+ if ( statusPane )
+ {
+ TInt currentLayoutResId( statusPane->CurrentLayoutResId() );
+
+ if ( currentLayoutResId == R_AVKON_WIDESCREEN_PANE_LAYOUT_USUAL ||
+ currentLayoutResId == R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE )
+ {
+ TAknLayoutRect layoutRect;
+ layoutRect.LayoutRect(
+ statusPaneRect,
+ AknLayoutScalable_Avkon::aid_touch_navi_pane() );
+ parentRect = layoutRect.Rect();
+
+ // Make the parent rect navi pane relative and move it so
+ // that the bottom sides of the real navi pane area and the
+ // touch pane responsive area are aligned. This means
+ // that the iTl.iY will become negative, which is required
+ // for pointer events in which the down event happens
+ // inside the decorator rect, but the up event in the
+ // extended area above the decorator rect.
+ parentRect.Move( -parentRect.iTl.iX,
+ -( parentRect.iTl.iY +
+ ( parentRect.Height() -
+ naviPaneRect.Height() ) ) );
+ }
+ }
+
+ TRect rightArrowTabRect( iArrowRightPos, iArrowRightSize );
+ TRect leftArrowTabRect( iArrowLeftPos, iArrowLeftSize );
+
+ // Get tab arrow touch aid rects from layout data, they extend the
+ // arrow areas bit to the decorated control's area to make the arrows
+ // more "finger usable".
+ TAknLayoutRect arrowAidLayout;
+ arrowAidLayout.LayoutRect(
+ statusPaneRect,
+ AknLayoutScalable_Avkon::aid_touch_tab_arrow_left(
+ Layout_Meta_Data::IsLandscapeOrientation() ? 2 : 0 ) );
+
+ // The arrows are the same size so use only the other's width.
+ TInt aidWidth( arrowAidLayout.Rect().Width() );
+
+ rightArrowTabRect.iTl.iX -= aidWidth;
+ leftArrowTabRect.iBr.iX += aidWidth;
+
+ TBool rightArrowTapped(
+ iNaviArrowsVisible &&
+ !iNaviArrowRightDimmed &&
+ rightArrowTabRect.Contains( aPointerEvent.iPosition ) );
+
+ TBool leftArrowTapped(
+ iNaviArrowsVisible &&
+ !iNaviArrowLeftDimmed &&
+ leftArrowTabRect.Contains( aPointerEvent.iPosition ) );
+
+ // Inform controls if tapped to arrows.
+ if ( aPointerEvent.iType == TPointerEvent::EButton1Down ||
+ aPointerEvent.iType == TPointerEvent::EButtonRepeat )
+ {
+ // Detects whether tap hits left arrow.
+ if ( leftArrowTapped && iNaviDecoratorObserver )
+ {
+ MTouchFeedback* feedback = MTouchFeedback::Instance();
+ if ( feedback &&
+ ( iDecoratedControl && !iDecoratedControl->IsDimmed() ) )
+ {
+ TTouchLogicalFeedback feedbackType =
+ ( aPointerEvent.iType == TPointerEvent::EButtonRepeat ?
+ ETouchFeedbackSensitiveButton :
+ ETouchFeedbackBasicButton );
+ feedback->InstantFeedback( this, feedbackType, aPointerEvent );
+ }
+
+ iNaviDecoratorObserver->HandleNaviDecoratorEventL(
+ MAknNaviDecoratorObserver::EAknNaviDecoratorEventLeftTabArrow );
+
+ // Request pointer repeat to implement longtapping
+ Window().RequestPointerRepeatEvent(
+ KEikNavidePointerRepeatInterval, leftArrowTabRect );
+
+ // Don't pass the event to children as the tap point
+ // may be in the decorated control's area and it's
+ // already handled here.
+ }
+ // Detects whether tap hits right arrow.
+ else if ( rightArrowTapped && iNaviDecoratorObserver )
+ {
+ MTouchFeedback* feedback = MTouchFeedback::Instance();
+ if ( feedback &&
+ ( iDecoratedControl && !iDecoratedControl->IsDimmed() ) )
+ {
+ TTouchLogicalFeedback feedbackType =
+ ( aPointerEvent.iType == TPointerEvent::EButtonRepeat ?
+ ETouchFeedbackSensitiveButton :
+ ETouchFeedbackBasicButton );
+ feedback->InstantFeedback( this, feedbackType, aPointerEvent );
+ }
+
+ iNaviDecoratorObserver->HandleNaviDecoratorEventL(
+ MAknNaviDecoratorObserver::EAknNaviDecoratorEventRightTabArrow );
+
+ // Request pointer repeat to implement longtapping
+ Window().RequestPointerRepeatEvent(
+ KEikNavidePointerRepeatInterval, rightArrowTabRect );
+
+ // Don't pass the event to children as the tap point
+ // may be in the decorated control's area and it's
+ // already handled here.
+ }
+ else
+ {
+ // Pass the pointer events to children.
+ CCoeControl::HandlePointerEventL( aPointerEvent );
+ }
+
+ // check if navi label was hit
+ }
+ else if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
+ {
+ if ( iControlType == ENaviLabel )
+ {
+ if ( parentRect.Contains( aPointerEvent.iPosition ) &&
+ iNaviDecoratorObserver )
+ {
+ iNaviDecoratorObserver->HandleNaviDecoratorEventL(
+ MAknNaviDecoratorObserver::EAknNaviDecoratorEventNaviLabel );
+ }
+ }
+ else if( !rightArrowTapped && !leftArrowTapped )
+ {
+ CCoeControl::HandlePointerEventL( aPointerEvent );
+ }
+
+ // feedback is also given on up event from arrows
+ if ( rightArrowTapped || leftArrowTapped )
+ {
+ MTouchFeedback* feedback = MTouchFeedback::Instance();
+ if ( feedback &&
+ ( iDecoratedControl && !iDecoratedControl->IsDimmed() ) )
+ {
+ feedback->InstantFeedback( this,
+ ETouchFeedbackBasicButton,
+ ETouchFeedbackVibra,
+ aPointerEvent );
+ }
+ }
+ }
+ else
+ {
+ if ( !rightArrowTapped && !leftArrowTapped )
+ {
+ // Pass other pointer events to children if it
+ // happened outside the arrow areas.
+ CCoeControl::HandlePointerEventL( aPointerEvent );
+ }
+ }
+ }
+ }
+
+
+EXPORT_C void CAknNavigationDecorator::HandleControlEventL(
+ CCoeControl* /*aControl*/, TCoeEvent aEventType )
+ {
+ TInt event = aEventType;
+ switch ( event )
+ {
+ case MAknNavigationObserver::ENaviEventHandleNavigation:
+ {
+ iNaviArrowRightDimmed = EFalse;
+ iNaviArrowLeftDimmed = EFalse;
+ break;
+ }
+ case MAknNavigationObserver::ENaviEventRightMostItemReached:
+ {
+ iNaviArrowRightDimmed = ETrue;
+ iNaviArrowLeftDimmed = EFalse;
+ break;
+ }
+ case MAknNavigationObserver::ENaviEventLeftMostItemReached:
+ {
+ iNaviArrowRightDimmed = EFalse;
+ iNaviArrowLeftDimmed = ETrue;
+ break;
+ }
+ case MAknNavigationObserver::ENaviEventOneItemExists:
+ {
+ iNaviArrowRightDimmed = ETrue;
+ iNaviArrowLeftDimmed = ETrue;
+ break;
+ }
+ case MAknNavigationObserver::ENaviEventAlreadyLeftmostItem:
+ {
+#ifdef RD_ANIMATION_EFFECTS
+ iExtension->iBlinkingSide =
+ CAknNavigationDecoratorExtension::ENaviDecoratorRightSide;
+ StartTimerL();
+ return;
+#else
+ break;
+#endif // RD_ANIMATION_EFFECTS
+ }
+ case MAknNavigationObserver::ENaviEventAlreadyRightmostItem:
+ {
+#ifdef RD_ANIMATION_EFFECTS
+ iExtension->iBlinkingSide =
+ CAknNavigationDecoratorExtension::ENaviDecoratorLeftSide;
+ StartTimerL();
+ return;
+#else // RD_ANIMATION_EFFECTS
+ break;
+#endif
+ }
+ case MAknNavigationObserver::ENaviEventRedrawNeeded:
+ break;
+ default:
+ break;
+ }
+
+ ReportEventL( MCoeControlObserver::EEventStateChanged );
+
+ MCoeControlObserver* observer = Observer();
+ // If event was not sent yet to the navigation control container, send it now
+ if ( iContainer && observer != iContainer )
+ {
+ SetObserver( iContainer );
+ ReportEventL( MCoeControlObserver::EEventStateChanged );
+ SetObserver( observer );
+ }
+ }
+
+
+EXPORT_C void CAknNavigationDecorator::Draw( const TRect& /*aRect*/ ) const
+ {
+ // Draw navigation pane scroll indicator arrows if visible
+ if ( iNaviArrowsVisible && iContainer )
+ {
+ CWindowGc& gc = SystemGc();
+
+ CFbsBitmap* colorbmp = iContainer->NaviColorBitmap();
+
+ if ( !iNaviArrowLeftDimmed )
+ {
+ CFbsBitmap* arrowBmp = &( iContainer->NaviArrowBitmap( 0 ) );
+ CFbsBitmap* arrowMask = &( iContainer->NaviArrowBitmap( 1 ) );
+
+ TPoint arrowPos( iArrowLeftPos );
+
+ if ( arrowBmp )
+ {
+ TInt arrowHeight( arrowBmp->SizeInPixels().iHeight );
+ if ( arrowHeight < Size().iHeight )
+ {
+ arrowPos.iY = ( Size().iHeight - arrowHeight ) / 2;
+ }
+ }
+
+ if( colorbmp && !IsMaskAllBlack( arrowMask ) )
+ {
+ gc.BitBltMasked(
+ arrowPos,
+ colorbmp,
+ TRect( iArrowLeftSize ),
+ arrowMask,
+ ETrue );
+ }
+ else
+ {
+ gc.BitBltMasked(
+ arrowPos,
+ arrowBmp,
+ TRect( iArrowLeftSize ),
+ arrowMask,
+ ETrue );
+ }
+ }
+
+ if ( !iNaviArrowRightDimmed )
+ {
+ CFbsBitmap* arrowBmp = &( iContainer->NaviArrowBitmap( 2 ) );
+ CFbsBitmap* arrowMask = &( iContainer->NaviArrowBitmap( 3 ) );
+
+ TPoint arrowPos( iArrowRightPos );
+
+ if ( arrowBmp )
+ {
+ TInt arrowHeight( arrowBmp->SizeInPixels().iHeight );
+ if ( arrowHeight < Size().iHeight )
+ {
+ arrowPos.iY = ( Size().iHeight - arrowHeight ) / 2;
+ }
+ }
+
+ if( colorbmp && !IsMaskAllBlack( arrowMask ) )
+ {
+ gc.BitBltMasked(
+ arrowPos,
+ colorbmp,
+ TRect( iArrowRightSize ),
+ arrowMask,
+ ETrue );
+ }
+ else
+ {
+ gc.BitBltMasked(
+ arrowPos,
+ arrowBmp,
+ TRect( iArrowRightSize ),
+ arrowMask,
+ ETrue );
+ }
+ }
+ }
+ }
+
+void CAknNavigationDecorator::SetNaviStack(
+ CAknNavigationControlContainer* aContainer )
+ {
+ iContainer = aContainer;
+
+ if ( iContainer &&
+ iControlType == ETabGroup )
+ {
+ CAknTabGroup* tabGroup =
+ static_cast <CAknTabGroup*> ( iDecoratedControl );
+ tabGroup->SetDecoratorLayout( iLayoutFlags & ENaviControlLayoutNarrow );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CAknNavigationDecorator::SetNaviDecoratorObserver
+// Sets observer for navidecorator.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknNavigationDecorator::SetNaviDecoratorObserver(
+ MAknNaviDecoratorObserver* aObserver )
+ {
+ if ( AknLayoutUtils::PenEnabled() )
+ {
+ iNaviDecoratorObserver = aObserver;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknNavigationDecorator::ParentRect
+// Returns the navigation decorator rectangle.
+// ---------------------------------------------------------------------------
+//
+TRect CAknNavigationDecorator::ParentRect()
+ {
+ return DecoratedControlRect( iControlType, iNaviArrowsVisible );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknNavigationDecorator::DecoratedControlNarrowRect
+// Returns the navigation decorator rectangle used in the narrow layout.
+// ---------------------------------------------------------------------------
+//
+TRect CAknNavigationDecorator::DecoratedControlNarrowRect(
+ TInt /*aControlType*/ )
+ {
+ TBool landscape( Layout_Meta_Data::IsLandscapeOrientation() );
+
+ // Status pane area
+ TRect statusPaneRect;
+ AknLayoutUtils::LayoutMetricsRect(
+ AknLayoutUtils::EStatusPane, statusPaneRect );
+
+ // Navi pane area
+ TRect naviPaneRect;
+ AknLayoutUtils::LayoutMetricsRect(
+ AknLayoutUtils::ENaviPane, naviPaneRect );
+
+ // Short navi pane
+ TAknLayoutRect naviSrtRect;
+ naviSrtRect.LayoutRect(
+ statusPaneRect,
+ AknLayoutScalable_Avkon::navi_pane_srt( 0 ) );
+
+ TRect rect( naviSrtRect.Rect() );
+
+ // Set relative to navipane coordinates
+ rect.Move( -naviPaneRect.iTl.iX, 0 );
+ rect.iTl.iY = 0;
+ rect.SetHeight( naviSrtRect.Rect().Height() );
+
+ return rect;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknNavigationDecorator::DecoratedControlRect
+// Returns the rectangle of the navigation decorator in relation to the
+// navi pane.
+// ---------------------------------------------------------------------------
+//
+TRect CAknNavigationDecorator::DecoratedControlRect( TInt aControlType,
+ TBool aArrowsUsed )
+ {
+ TRect rect;
+
+ switch ( aControlType )
+ {
+ case ETabGroup:
+ {
+ rect = DecoratedTabControlRect( ETrue, aArrowsUsed );
+ break;
+ }
+ case ENaviVolume:
+ {
+ rect = DecoratedVolumeControlRect();
+ break;
+ }
+ default:
+ {
+ rect = DecoratedDefaultControlRect();
+ break;
+ }
+ }
+
+ return rect;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknNavigationDecorator::DecoratedControlRect
+// Returns the default rectangle of the navigation decorator.
+// ---------------------------------------------------------------------------
+//
+TRect CAknNavigationDecorator::DecoratedDefaultControlRect()
+ {
+ TRect rect;
+
+ TRect naviPaneRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ENaviPane, naviPaneRect );
+
+ if ( AknStatuspaneUtils::SmallLayoutActive() )
+ {
+ // screen
+ TRect screenRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screenRect );
+
+ // top area
+ TAknLayoutRect topAreaLayoutRect;
+ topAreaLayoutRect.LayoutRect(
+ screenRect,
+ AknLayoutScalable_Avkon::area_top_pane( 1 ) );
+
+ // small statuspane
+ TAknLayoutRect statusPaneLayoutRect;
+ statusPaneLayoutRect.LayoutRect(
+ topAreaLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::status_small_pane() );
+ TRect statusPaneRect( statusPaneLayoutRect.Rect() );
+
+ TAknWindowComponentLayout signalPaneLayout(
+ AknLayoutScalable_Avkon::status_small_pane_g2( 0 ) );
+ TAknLayoutRect signalPaneLayoutRect;
+ signalPaneLayoutRect.LayoutRect( statusPaneRect, signalPaneLayout );
+
+ rect = statusPaneRect;
+
+ CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
+ if ( statusPane &&
+ statusPane->PaneCapabilities(TUid::Uid(EEikStatusPaneUidSignal)).IsInCurrentLayout() )
+ {
+ TSize size( rect.Size() );
+ size.iWidth -= signalPaneLayoutRect.Rect().Width();
+ rect.SetSize( size );
+ }
+
+ // Adjust the size for the navi pane content so that there's space for
+ // the possible navi arrows.
+ TInt arrowWidth = NaviArrowRect( ELeftButton ).Width();
+ rect.iTl.iX += arrowWidth;
+ rect.iBr.iX -= arrowWidth;
+ }
+ else if ( AknStatuspaneUtils::StaconPaneActive() )
+ {
+ // navi navi pane
+ TAknLayoutRect naviNaviLayoutRect;
+ naviNaviLayoutRect.LayoutRect(
+ naviPaneRect,
+ AknLayoutScalable_Avkon::navi_navi_pane() );
+
+ // pane for text and graphics
+ TAknLayoutRect naviControlLayoutRect;
+ naviControlLayoutRect.LayoutRect(
+ naviNaviLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_icon_text_pane() );
+
+ rect = naviControlLayoutRect.Rect();
+
+ // Set relative to stacon navipane coordinates
+ rect.Move( -naviPaneRect.iTl.iX,
+ -naviControlLayoutRect.Rect().iTl.iY );
+ }
+ else
+ {
+ // navi navi pane
+ TAknLayoutRect naviNaviLayoutRect;
+ naviNaviLayoutRect.LayoutRect(
+ naviPaneRect,
+ AknLayoutScalable_Avkon::navi_navi_pane() );
+
+ // pane for text and graphics
+ TAknLayoutRect naviControlLayoutRect;
+ naviControlLayoutRect.LayoutRect(
+ naviNaviLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_icon_text_pane() );
+ TRect naviControlRect( naviControlLayoutRect.Rect() );
+
+ rect = naviControlRect;
+ rect.Move( -naviNaviLayoutRect.Rect().iTl.iX,
+ -naviControlRect.iTl.iY );
+ }
+
+ return rect;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAknNavigationDecorator::DecoratedTabControlRect
+// Returns the tab group rectangle in relation to the navi pane.
+// ---------------------------------------------------------------------------
+//
+TRect CAknNavigationDecorator::DecoratedTabControlRect( TBool aTopAdjacent,
+ TBool aArrowsUsed )
+ {
+ TRect rect;
+
+ // "Stacon" statuspane
+ if ( AknStatuspaneUtils::StaconPaneActive() )
+ {
+ TRect naviPaneRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ENaviPane,
+ naviPaneRect );
+
+ TInt variety = AknStatuspaneUtils::ExtendedStaconPaneActive() ? 1 : 0;
+
+ TAknLayoutRect staconNaviTabRect;
+ staconNaviTabRect.LayoutRect(
+ naviPaneRect,
+ AknLayoutScalable_Avkon::navi_navi_pane_stacon( variety ) );
+
+ // tab pane
+ TAknLayoutRect tabsPaneLayoutRect;
+ tabsPaneLayoutRect.LayoutRect(
+ staconNaviTabRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_tabs_pane() );
+ TRect tabsRect( tabsPaneLayoutRect.Rect() );
+
+ rect = tabsRect;
+
+ // Set relative to stacon navipane coordinates
+ rect.Move( -staconNaviTabRect.Rect().iTl.iX, -tabsRect.iTl.iY );
+ }
+ else
+ {
+ TBool penEnabled( AknLayoutUtils::PenEnabled() );
+ TRect naviPaneRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ENaviPane,
+ naviPaneRect );
+
+ if ( !penEnabled )
+ {
+ // Tab pane is the only control which doesn't use the wide navi pane
+ // layout in non-touch portrait mode, so we can't get the navi
+ // pane rect directly from AknLayoutUtils.
+ TRect statusPaneRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EStatusPane,
+ statusPaneRect );
+
+ TAknLayoutRect naviPaneLayoutRect;
+ naviPaneLayoutRect.LayoutRect(
+ statusPaneRect,
+ AknLayoutScalable_Avkon::navi_pane( 5 ) );
+ naviPaneRect = naviPaneLayoutRect.Rect();
+ }
+
+ if ( aArrowsUsed )
+ {
+ // navi navi pane
+ TAknLayoutRect naviNaviPaneLayoutRect;
+ naviNaviPaneLayoutRect.LayoutRect(
+ naviPaneRect,
+ AknLayoutScalable_Avkon::navi_navi_pane() );
+
+ // tab pane
+ TAknLayoutRect tabsPaneLayoutRect;
+ tabsPaneLayoutRect.LayoutRect(
+ naviNaviPaneLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_tabs_pane() );
+ TRect tabsRect( tabsPaneLayoutRect.Rect() );
+
+ rect = tabsRect;
+
+ if ( aTopAdjacent )
+ {
+ rect.Move( -naviNaviPaneLayoutRect.Rect().iTl.iX,
+ -tabsRect.iTl.iY );
+ }
+ else
+ {
+ rect.Move( -naviNaviPaneLayoutRect.Rect().iTl.iX,
+ -( tabsRect.iTl.iY - ( naviPaneRect.Height() -
+ tabsRect.Height() ) ) );
+ }
+ }
+ else
+ {
+ rect = naviPaneRect;
+ rect.Move( -naviPaneRect.iTl.iX,
+ -naviPaneRect.iTl.iY );
+ }
+ }
+
+ return rect;
+ }
+
+
+TRect CAknNavigationDecorator::DecoratedVolumeControlRect()
+ {
+ TRect rect;
+
+ // screen
+ TRect screenRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screenRect );
+
+ if ( AknStatuspaneUtils::SmallLayoutActive() )
+ {
+ // top area
+ TAknLayoutRect topAreaLayoutRect;
+ topAreaLayoutRect.LayoutRect(
+ screenRect,
+ AknLayoutScalable_Avkon::area_top_pane( 1 ) );
+
+ // small statuspane
+ TAknLayoutRect statusPaneLayoutRect;
+ statusPaneLayoutRect.LayoutRect(
+ topAreaLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::status_small_pane() );
+ TRect statusPaneRect( statusPaneLayoutRect.Rect() );
+
+ rect = statusPaneRect;
+
+ statusPaneLayoutRect.LayoutRect(
+ rect,
+ AknLayoutScalable_Avkon::status_small_volume_pane() );
+ rect = statusPaneLayoutRect.Rect();
+ }
+
+ else if ( AknStatuspaneUtils::StaconPaneActive() )
+ {
+ // bottom area
+ TAknLayoutRect bottomAreaLayoutRect;
+ bottomAreaLayoutRect.LayoutRect(
+ screenRect,
+ AknLayoutScalable_Avkon::area_bottom_pane( 2 ) );
+
+ // stacon bottom
+ TAknLayoutRect staconBottomLayoutRect;
+ staconBottomLayoutRect.LayoutRect(
+ bottomAreaLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::stacon_bottom_pane() );
+
+ TInt naviPaneVariety = AknStatuspaneUtils::StaconSoftKeysRight() ? 2 : 3;
+ TAknLayoutRect staconNaviRect;
+ staconNaviRect.LayoutRect(
+ staconBottomLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::navi_pane_stacon( naviPaneVariety ) );
+
+ TAknLayoutRect staconNaviControlRect;
+ staconNaviControlRect.LayoutRect(
+ staconNaviRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_pane() );
+
+ TAknLayoutRect volumeControlRect;
+ volumeControlRect.LayoutRect(
+ staconNaviControlRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_volume_pane() );
+
+ rect = volumeControlRect.Rect();
+
+ // Set relative to stacon navipane coordinates
+ rect.Move( -staconNaviRect.Rect().iTl.iX, 0 );
+ rect.iTl.iY = 0;
+ rect.SetHeight( volumeControlRect.Rect().Height() );
+ }
+
+ // "Flat" statuspane
+ else if ( AknStatuspaneUtils::FlatLayoutActive() )
+ {
+ TAknLayoutRect naviRect;
+ naviRect.LayoutRect(
+ screenRect,
+ AknLayoutScalable_Avkon::navi_pane( 2 ) );
+
+ TAknLayoutRect naviNaviLayoutRect;
+ naviNaviLayoutRect.LayoutRect(
+ naviRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_pane() );
+
+ TAknLayoutRect volumeControlRect;
+ volumeControlRect.LayoutRect(
+ naviNaviLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_volume_pane() );
+
+ rect = volumeControlRect.Rect();
+
+ rect.Move( -naviNaviLayoutRect.Rect().iTl.iX, 0 );
+ rect.iTl.iY = 0;
+ rect.SetHeight( volumeControlRect.Rect().Height() );
+ }
+
+ else
+ {
+ // Is battery pane visible in current layout
+ TInt battery = AknStatuspaneUtils::ExtendedLayoutActive() ? 5 : 0; // classic or extended
+
+ if ( AknStatuspaneUtils::IdleLayoutActive() )
+ {
+ battery = AknStatuspaneUtils::ExtendedLayoutActive() ? 6 : 1; // classic or extended
+ }
+ else if ( AknStatuspaneUtils::UsualLayoutActive() &&
+ !Layout_Meta_Data::IsLandscapeOrientation() )
+ {
+ battery = 7;
+ }
+
+ if ( AknStatuspaneUtils::HDLayoutActive() && battery == 5 )
+ {
+ battery = 8;
+ }
+
+ // app window
+ TAknLayoutRect applicationWindowLayoutRect;
+ applicationWindowLayoutRect.LayoutRect(
+ screenRect,
+ AknLayoutScalable_Avkon::application_window( 0 ) );
+
+ // statuspane
+ TAknLayoutRect statusPaneLayoutRect;
+ statusPaneLayoutRect.LayoutRect(
+ applicationWindowLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::status_pane( 0 ) );
+
+ // navi pane
+ TAknLayoutRect naviPaneLayoutRect;
+ naviPaneLayoutRect.LayoutRect(
+ statusPaneLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::navi_pane( battery ) );
+
+ TAknLayoutRect naviNaviLayoutRect;
+ naviNaviLayoutRect.LayoutRect(
+ naviPaneLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_pane() );
+
+ TAknLayoutRect volumeControlRect;
+ volumeControlRect.LayoutRect(
+ naviNaviLayoutRect.Rect(),
+ AknLayoutScalable_Avkon::navi_navi_volume_pane() );
+ TRect volumeRect( volumeControlRect.Rect() );
+
+ rect = volumeRect;
+
+ rect.Move( -naviNaviLayoutRect.Rect().iTl.iX, -volumeRect.iTl.iY );
+ }
+
+ return rect;
+ }
+
+EXPORT_C void CAknNavigationDecorator::SetNaviControlLayoutStyle(
+ TAknNaviControlLayoutStyle aStyle )
+ {
+ if ( AknStatuspaneUtils::FlatLayoutActive() &&
+ !Layout_Meta_Data::IsLandscapeOrientation() )
+ {
+ // In portrait flat sp mode only narrow mode is allowed.
+ iLayoutFlags &= ~ENaviControlLayoutNarrow;
+ iLayoutFlags &= ~ENaviControlLayoutNormal;
+ iLayoutFlags |= ENaviControlLayoutNarrow;
+ }
+ else if ( NaviControlLayoutStyleSupported( aStyle ) )
+ {
+ iLayoutFlags &= ~ENaviControlLayoutNarrow;
+ iLayoutFlags &= ~ENaviControlLayoutNormal;
+ iLayoutFlags &= ~ENaviControlLayoutWide;
+ iLayoutFlags |= aStyle;
+ }
+
+ if ( NaviControlLayoutMode() == ENaviControlLayoutModeAutomatic &&
+ NaviControlLayoutStyle() == ENaviControlLayoutNormal )
+ {
+ InitLayoutStyleTimer();
+ }
+ else
+ {
+ CancelLayoutStyleTimer();
+ }
+
+ if ( iContainer )
+ {
+ iContainer->SetSize( iContainer->Size() );
+ }
+ else
+ {
+ SizeChanged();
+ }
+ }
+
+
+EXPORT_C CAknNavigationDecorator::TAknNaviControlLayoutStyle CAknNavigationDecorator::NaviControlLayoutStyle()
+ {
+ if ( iLayoutFlags & ENaviControlLayoutNarrow )
+ {
+ return ENaviControlLayoutNarrow;
+ }
+ else if ( iLayoutFlags & ENaviControlLayoutWide )
+ {
+ return ENaviControlLayoutWide;
+ }
+ else
+ {
+ return ENaviControlLayoutNormal;
+ }
+ }
+
+
+EXPORT_C void CAknNavigationDecorator::SetNaviControlLayoutMode(
+ TAknNaviControlLayoutMode aMode )
+ {
+ iLayoutFlags &= ~ENaviControlLayoutModeAutomatic;
+ iLayoutFlags &= ~ENaviControlLayoutModeForced;
+ iLayoutFlags |= aMode;
+
+ if ( NaviControlLayoutMode() == ENaviControlLayoutModeForced )
+ {
+ CancelLayoutStyleTimer();
+ }
+ else
+ {
+ if ( NaviControlLayoutMode() == ENaviControlLayoutModeAutomatic &&
+ NaviControlLayoutStyle() == ENaviControlLayoutNormal )
+ {
+ InitLayoutStyleTimer();
+ }
+ }
+ }
+
+
+EXPORT_C CAknNavigationDecorator::TAknNaviControlLayoutMode CAknNavigationDecorator::NaviControlLayoutMode()
+ {
+ if ( iLayoutFlags & ENaviControlLayoutModeForced )
+ {
+ return ENaviControlLayoutModeForced;
+ }
+ else
+ {
+ return ENaviControlLayoutModeAutomatic;
+ }
+ }
+
+
+EXPORT_C TBool CAknNavigationDecorator::NaviControlLayoutStyleSupported(
+ TAknNaviControlLayoutStyle aStyle )
+ {
+ TBool retVal( EFalse );
+ TBool penEnabled( AknLayoutUtils::PenEnabled() );
+
+ if ( aStyle == ENaviControlLayoutNormal )
+ {
+ retVal = ETrue;
+ }
+ else if ( aStyle == ENaviControlLayoutNarrow )
+ {
+ if ( ( iControlType == ETabGroup && !penEnabled ) ||
+ iControlType == ENaviLabel ||
+ iControlType == ENaviImage ||
+ iControlType == EHintText ||
+ iControlType == EEditorIndicator )
+ {
+ retVal = ETrue;
+ }
+ }
+ else if ( aStyle == ENaviControlLayoutWide )
+ {
+ // Wide layout is not currently supported for tabs in non-touch
+ // layouts.
+ if ( iControlType == ETabGroup && !penEnabled )
+ {
+ retVal = EFalse;
+ }
+ else
+ {
+ retVal = ETrue;
+ }
+ }
+
+ return retVal;
+ }
+
+
+void CAknNavigationDecorator::InitLayoutStyleTimer()
+ {
+ if ( IsVisible() )
+ {
+ const TInt KIdleDelay = 5000000; // 5 s
+ iLayoutStyleTimer->Cancel();
+ iLayoutStyleTimer->Start(TTimeIntervalMicroSeconds32(KIdleDelay),
+ TTimeIntervalMicroSeconds32(KIdleDelay),
+ TCallBack(CAknNavigationDecorator::LayoutStyleEvent, this));
+ }
+ }
+
+void CAknNavigationDecorator::CancelLayoutStyleTimer()
+ {
+ if (iLayoutStyleTimer && iLayoutStyleTimer->IsActive())
+ {
+ iLayoutStyleTimer->Cancel();
+ }
+ }
+
+TInt CAknNavigationDecorator::LayoutStyleEvent( TAny* aPtr )
+ {
+ ( ( CAknNavigationDecorator*) aPtr )->DoLayoutStyleEvent();
+ return ETrue;
+ }
+
+void CAknNavigationDecorator::DoLayoutStyleEvent()
+ {
+ // First check that status pane layout or layout mode
+ // has not been changed during timeout time.
+ if ( !iContainer ||
+ ( iContainer && iContainer->Top() != this ) ||
+ !AknStatuspaneUtils::FlatLayoutActive() ||
+ NaviControlLayoutMode() != ENaviControlLayoutModeAutomatic ||
+ !IsVisible() )
+ {
+ CancelLayoutStyleTimer();
+ return;
+ }
+
+ // Only if automatic mode is active and control supports narrow layout style
+ // and titlepane text does not fit completely in normal mode
+ // we change the layout style...
+ CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
+ CCoeControl* navipanecontrol = NULL;
+ CCoeControl* titlepaneControl = NULL;
+ TBool textDoesFitVisibleTitlePaneArea = EFalse;
+
+ if ( statusPane )
+ {
+ TRAP_IGNORE( navipanecontrol =
+ statusPane->ControlL(TUid::Uid( EEikStatusPaneUidNavi ) ) );
+ CAknTitlePane* titlePane =
+ dynamic_cast <CAknTitlePane*> ( titlepaneControl );
+
+ TRAP_IGNORE( titlepaneControl =
+ statusPane->ControlL(TUid::Uid( EEikStatusPaneUidTitle ) ) );
+
+ if ( navipanecontrol && titlePane )
+ {
+ CAknTitlePaneLabel* titleLabel =
+ static_cast <CAknTitlePaneLabel*> ( titlePane->TextLabel() );
+
+ if ( titleLabel )
+ {
+ // check it text fits, add some safety margin (15%)
+ TInt textlength = titleLabel->TextLength();
+ TInt visibleAreaForText =
+ titlepaneControl->Size().iWidth - navipanecontrol->Size().iWidth;
+ if ( textlength < ( visibleAreaForText * 85 / 100) )
+ {
+ textDoesFitVisibleTitlePaneArea = ETrue;
+ }
+ }
+ }
+ }
+
+ if ( NaviControlLayoutMode() == ENaviControlLayoutModeAutomatic &&
+ NaviControlLayoutStyleSupported( ENaviControlLayoutNarrow ) &&
+ !textDoesFitVisibleTitlePaneArea )
+ {
+ SetNaviControlLayoutStyle( ENaviControlLayoutNarrow );
+ SizeChanged();
+ DrawDeferred();
+ }
+
+ CancelLayoutStyleTimer();
+ }
+
+TInt CAknNavigationDecorator::IndicationDrawCallbackL( TAny* aThis )
+ {
+ CAknNavigationDecorator* decorator =
+ static_cast<CAknNavigationDecorator*>(aThis);
+
+ decorator->SmallDirectionIndicationL();
+
+ return KErrNone;
+ }
+
+void CAknNavigationDecorator::SmallDirectionIndicationL()
+ {
+ TRect rect;
+
+ // Cancel blinking if moved from the min or max position,
+ // unless the area is blank. Then redraw and cancel after redraw
+ if ( !iNaviArrowLeftDimmed &&
+ !iNaviArrowRightDimmed &&
+ ( iExtension->iEffectTimerCount % 2 == 0 ) )
+ {
+ CancelTimer();
+ return;
+ }
+
+ // Stop timer if done normal-inverted-normal-inverted-normal sequence
+ // or the user has changed the value from the min or max
+ if ( iExtension->iEffectTimerCount >= 3 ||
+ ( !iNaviArrowLeftDimmed &&
+ !iNaviArrowRightDimmed ) )
+ {
+ CancelTimer();
+ }
+
+ Window().Invalidate( rect );
+ ActivateGc();
+
+ rect = TRect( iArrowLeftSize );
+
+ // Draw navigation pane scroll indicator arrows if visible
+ if ( iNaviArrowsVisible && iContainer )
+ {
+ CWindowGc& gc = SystemGc();
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
+
+ CFbsBitmap* colorbmp = iContainer->NaviColorBitmap();
+
+ if ( iExtension->iBlinkingSide ==
+ CAknNavigationDecoratorExtension::ENaviDecoratorLeftSide )
+ {
+ if( iExtension->iEffectTimerCount % 2 == 1 &&
+ !iNaviArrowLeftDimmed )
+ {
+ CFbsBitmap* arrowBmp = &(iContainer->NaviArrowBitmap(0));
+ CFbsBitmap* arrowMask = &(iContainer->NaviArrowBitmap(1));
+ if( colorbmp && !IsMaskAllBlack( arrowMask ) )
+ {
+ gc.BitBltMasked( iArrowLeftPos,
+ colorbmp,
+ rect,
+ arrowMask,
+ ETrue );
+ }
+ else
+ {
+ gc.BitBltMasked( iArrowLeftPos,
+ arrowBmp,
+ rect,
+ arrowMask,
+ ETrue );
+ }
+ }
+ else
+ {
+ // draw empty
+ AknsDrawUtils::Background(
+ skin,
+ cc,
+ this,
+ gc,
+ TRect( iArrowLeftPos, rect.Size() ),
+ KAknsDrawParamDefault );
+ }
+ }
+ rect = TRect( iArrowRightSize );
+
+ if ( iExtension->iBlinkingSide ==
+ CAknNavigationDecoratorExtension::ENaviDecoratorRightSide )
+ {
+ if ( iExtension->iEffectTimerCount % 2 == 1 &&
+ !iNaviArrowRightDimmed )
+ {
+ CFbsBitmap* arrowBmp = &(iContainer->NaviArrowBitmap(2));
+ CFbsBitmap* arrowMask = &(iContainer->NaviArrowBitmap(3));
+ if( colorbmp && !IsMaskAllBlack( arrowMask ) )
+ {
+ gc.BitBltMasked( iArrowRightPos,
+ colorbmp,
+ rect,
+ arrowMask,
+ ETrue );
+ }
+ else
+ {
+ gc.BitBltMasked( iArrowRightPos,
+ arrowBmp,
+ rect,
+ arrowMask,
+ ETrue );
+ }
+ }
+ else
+ {
+ // draw empty
+ AknsDrawUtils::Background(
+ skin,
+ cc,
+ this,
+ gc,
+ TRect( iArrowRightPos, rect.Size() ),
+ KAknsDrawParamDefault );
+ }
+ }
+ }
+
+ DeactivateGc();
+
+ iExtension->iEffectTimerCount++;
+ }
+
+
+void CAknNavigationDecorator::StartTimerL()
+ {
+ if ( !iExtension->iTimer )
+ {
+ iExtension->iTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+ }
+ else if ( iExtension->iTimer->IsActive() )
+ {
+ return; // do not re-start as we have the feedback ongoing
+ }
+
+ iExtension->iEffectTimerCount = 0;
+
+ const TTimeIntervalMicroSeconds32 KArrowFeedbackActionTime = 160 * 1000;
+
+ TCallBack callback( IndicationDrawCallbackL, this );
+ iExtension->iTimer->Start( KArrowFeedbackActionTime,
+ KArrowFeedbackActionTime,
+ callback );
+ }
+
+void CAknNavigationDecorator::CancelTimer()
+ {
+ if ( iExtension && iExtension->iTimer )
+ {
+ if ( iExtension->iTimer->IsActive() )
+ {
+ iExtension->iTimer->Cancel();
+ }
+ }
+ }
+
+EXPORT_C void CAknNavigationDecorator::HandleResourceChange( TInt aType )
+ {
+ if ( iControlType == ENaviVolume )
+ {
+ // We must forward the event to the volume popup instead
+ // of the old style volume control.
+ iDecoratedControl->HandleResourceChange( aType );
+ }
+ else
+ {
+ CCoeControl::HandleResourceChange( aType );
+ }
+
+ if ( aType == KEikDynamicLayoutVariantSwitch )
+ {
+ TAknNaviControlLayoutStyle layoutStyle = NaviControlLayoutStyle();
+ TAknNaviControlLayoutMode layoutMode = NaviControlLayoutMode();
+ TBool sizeChangedCalled( EFalse );
+
+ if ( layoutMode == ENaviControlLayoutModeAutomatic &&
+ layoutStyle == ENaviControlLayoutNarrow )
+ {
+ SetNaviControlLayoutStyle( ENaviControlLayoutNormal );
+ sizeChangedCalled = ETrue;
+ }
+ else if ( iControlType == ETabGroup &&
+ AknStatuspaneUtils::UsualLayoutActive() &&
+ !Layout_Meta_Data::IsLandscapeOrientation() )
+ {
+ // Need special handling for tab group in portrait mode usual
+ // layout if switching from touch layout to a non-touch layout
+ // or vice versa since the wide layout is not supported in
+ // non-touch layout but is always used for tab groups in
+ // portrait touch layouts.
+ if ( AknLayoutUtils::PenEnabled() )
+ {
+ if ( layoutStyle != ENaviControlLayoutWide )
+ {
+ SetNaviControlLayoutMode( ENaviControlLayoutModeForced );
+ SetNaviControlLayoutStyle( ENaviControlLayoutWide );
+ sizeChangedCalled = ETrue;
+ }
+ }
+ else
+ {
+ if ( layoutStyle == ENaviControlLayoutWide )
+ {
+ SetNaviControlLayoutMode( ENaviControlLayoutModeAutomatic );
+ SetNaviControlLayoutStyle( ENaviControlLayoutNormal );
+ sizeChangedCalled = ETrue;
+ }
+ }
+ }
+
+ if ( !sizeChangedCalled )
+ {
+ SizeChanged();
+ }
+ }
+ }
+
+
+TRect CAknNavigationDecorator::NaviArrowRect( TScrollButton aScrollButton,
+ TBool aNarrowLayout,
+ TRect aNaviRect )
+ {
+ TAknLayoutRect layoutRect;
+ TRect arrowRect;
+
+ TAknWindowComponentLayout arrowLayout;
+ if ( aNarrowLayout )
+ {
+ arrowLayout = aScrollButton == ELeftButton ?
+ AknLayoutScalable_Avkon::navi_navi_pane_srt_g1( 0 ) :
+ AknLayoutScalable_Avkon::navi_navi_pane_srt_g2( 0 );
+ }
+ else
+ {
+ arrowLayout = aScrollButton == ELeftButton ?
+ AknLayoutScalable_Avkon::navi_navi_pane_g1( 0 ) :
+ AknLayoutScalable_Avkon::navi_navi_pane_g2( 0 );
+ }
+
+ // aNaviRect is empty by default
+ if ( !aNaviRect.IsEmpty() )
+ {
+ layoutRect.LayoutRect( aNaviRect, arrowLayout );
+ arrowRect = layoutRect.Rect();
+ }
+ else
+ {
+ if ( aNarrowLayout )
+ {
+ TRect naviPaneRect( DecoratedControlNarrowRect( 0 ) ); // parameter not used
+ layoutRect.LayoutRect( naviPaneRect, arrowLayout );
+ arrowRect = layoutRect.Rect();
+ }
+ else
+ {
+ TRect naviPaneRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ENaviPane,
+ naviPaneRect );
+
+ naviPaneRect.Move( -naviPaneRect.iTl.iX,
+ -naviPaneRect.iTl.iY );
+
+ layoutRect.LayoutRect(
+ naviPaneRect,
+ AknLayoutScalable_Avkon::navi_navi_pane() );
+ TRect naviNaviRect( layoutRect.Rect() );
+
+ layoutRect.LayoutRect( naviNaviRect, arrowLayout );
+ arrowRect = layoutRect.Rect();
+ }
+ }
+
+ return arrowRect;
+ }
+
+// End of File