uifw/AvKon/src/akntabgrp.cpp
changeset 0 2f259fa3e83a
child 9 aabf2c525e0f
child 14 3320e4e6e8bb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/akntabgrp.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,4460 @@
+/*
+* 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 for tab navigation control.
+*
+*/
+
+
+// SYSTEM INCLUDE FILES
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <uikon/eikdefmacros.h>
+#endif
+#include <w32std.h>
+#include <barsread.h>
+#include <eikbctrl.h>
+#include <eiklabel.h>
+#include <eikimage.h>
+#include <eikenv.h>
+#include <AknLayoutDef.h>
+#include <AknsUtils.h>
+#include <AknIconUtils.h>
+#include <AknDef.h>
+#include <e32std.h>
+#include <AknStatuspaneUtils.h>
+#include <layoutmetadata.cdl.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <akniconconfig.h>
+
+#include <AknTasHook.h>
+#include <touchfeedback.h>
+
+// USER INCLUDE FILES
+#include "aknappui.h"
+#include "avkon.hrh"
+#include "AknNaviObserver.h"
+#include "AknPanic.h"
+#include "akntabgrp.h"
+#include "AknTabObserver.h"
+#include "aknenv.h"
+#include "AknBitmapMirrorUtils.h"
+#include "AknTabGrpGraphics.h"
+#include "aknnavide.h"
+#include "AknNaviDecoratorObserver.h"
+
+// GLOBAL CONSTANTS
+
+const TInt KTabArrayGranularity             = 4;
+const TInt KAknTabGroupNoTabs               = KErrNotFound;
+const TInt KTabColorBitmapQueueGranularity  = 2;
+const TInt KTabColorBitmapActiveColorIndex  = 0;
+const TInt KTabColorBitmapPassiveColorIndex = 1;
+
+/** Maximum number of tabs that can be shown in the tab group at a time. */
+const TInt KMaxNumberOfVisibleTabs          = 4;
+
+/** Maximum number of frames in the tab group animations. */
+const TInt KMaxAmountOfAnimationEvents      = 80;
+
+/** Interval used between the frames in tab group animations. */
+const TInt KAnimationEventInterval          = 25000; // 40 events/s
+
+/** Speed value for the layout switch animation, smaller value is faster. */
+const TInt KLayoutSwitchAnimationSpeed      = 25;
+
+/** Minimum horizontal step size value for the tab cycle animation. */
+const TInt KMinimumCycleAnimationStepSize   = 3;
+
+/** Tolerance used for pointer event position's x-value in tab navigation. */
+const TInt KDragNavigationTolerance         = 5;
+
+//
+// Extension to CAknTab
+//
+
+NONSHARABLE_CLASS( CAknTabExtension ) : public CBase
+    {
+public:
+    static CAknTabExtension* NewL();
+    ~CAknTabExtension();
+
+private:
+    CAknTabExtension();
+
+public:
+
+    /** Indicates whether or not the tab is shown in narrow tab group layout. */
+    TBool iNarrowTabLayout;
+
+    /** Total amount of tab in the tab group, needed to decide right layoutlines. */
+    TInt  iNumberOfTabsInTabGroup;
+
+    /** Indicates whether or not this tab is drawn using multi-color mode. */
+    TBool iMultiColorMode;
+
+    /** Indicates whether or not the tab is shown in long tab group layout. */
+    TBool iLongTab;
+    };
+
+CAknTabExtension* CAknTabExtension::NewL()
+    {
+    CAknTabExtension* self = new ( ELeave ) CAknTabExtension();
+    return self;
+    }
+
+
+CAknTabExtension::CAknTabExtension()
+    {
+    }
+
+CAknTabExtension::~CAknTabExtension()
+    {
+    }
+
+//
+// CAknTab
+//
+
+CAknTab::~CAknTab()
+    {
+    AKNTASHOOK_REMOVE();
+    delete iLabel;
+    delete iBitmap;
+    delete iBitmapMask;
+
+    if ( iColorBitmaps )
+        {
+        iColorBitmaps->ResetAndDestroy();
+        delete iColorBitmaps;
+        iColorBitmaps = NULL;
+        }
+
+    delete iExtension;
+    }
+
+CAknTab* CAknTab::NewL( const CCoeControl& aParent, TResourceReader& aReader )
+    {
+    CAknTab* self = CAknTab::NewLC( aParent, aReader );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+CAknTab* CAknTab::NewLC( const CCoeControl& aParent, TResourceReader& aReader )
+    {
+    CAknTab* self = new (ELeave) CAknTab( 0 ); // default tab id
+    CleanupStack::PushL( self );
+    self->SetContainerWindowL( aParent );
+    self->ConstructFromResourceL( aReader );
+    AKNTASHOOK_ADDL( self, "CAknTab" );
+    return self;
+    }
+
+CAknTab* CAknTab::NewL( TInt aId,
+                        const CCoeControl& aParent,
+                        const TDesC& aTabText )
+    {
+    CAknTab* self = CAknTab::NewLC( aId, aParent, aTabText );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+CAknTab* CAknTab::NewLC( TInt aId,
+                         const CCoeControl& aParent,
+                         const TDesC& aTabText )
+    {
+    CAknTab* self = new (ELeave) CAknTab( aId );
+    CleanupStack::PushL( self );
+    self->SetContainerWindowL( aParent );
+    self->ConstructL( aTabText );
+    AKNTASHOOK_ADDL( self, "CAknTab" );
+    return self;
+    }
+
+CAknTab* CAknTab::NewL( TInt aId,
+                        const CCoeControl& aParent,
+                        const TDesC& aTabText,
+                        const CFbsBitmap* aTabBitmap,
+                        const CFbsBitmap* aMask )
+    {
+    CAknTab* self = CAknTab::NewLC( aId, aParent, aTabText, aTabBitmap, aMask );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+CAknTab* CAknTab::NewLC( TInt aId,
+                         const CCoeControl& aParent,
+                         const TDesC& aTabText,
+                         const CFbsBitmap* aTabBitmap,
+                         const CFbsBitmap* aMask )
+    {
+    CAknTab* self = new (ELeave) CAknTab( aId );
+    CleanupStack::PushL( self );
+    self->SetContainerWindowL( aParent );
+    self->ConstructL( aTabText );
+    self->ConstructL( aTabBitmap, aMask );
+    AKNTASHOOK_ADDL( self, "CAknTab" );
+    return self;
+    }
+
+CAknTab* CAknTab::NewL( TInt aId,
+                        const CCoeControl& aParent,
+                        const CFbsBitmap* aTabBitmap,
+                        const CFbsBitmap* aMask )
+    {
+    CAknTab* self = CAknTab::NewLC( aId, aParent, aTabBitmap, aMask );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+CAknTab* CAknTab::NewLC( TInt aId,
+                         const CCoeControl& aParent,
+                         const CFbsBitmap* aTabBitmap,
+                         const CFbsBitmap* aMask )
+    {
+    CAknTab* self = new (ELeave) CAknTab( aId );
+    CleanupStack::PushL( self );
+    self->SetContainerWindowL( aParent );
+    self->ConstructL( aTabBitmap, aMask );
+    AKNTASHOOK_ADDL( self, "CAknTab" );
+    return self;
+    }
+
+CAknTab::CAknTab( TInt aId ) : iId( aId )
+    {
+    }
+
+void CAknTab::ConstructFromResourceL( TResourceReader& aReader )
+    {
+    if ( !iExtension )
+        {
+        iExtension = CAknTabExtension::NewL();
+        }
+
+    iId = aReader.ReadInt16(); // tab id
+
+    HBufC* txt = aReader.ReadHBufCL(); // tab text
+    if ( txt )
+        {
+        CleanupStack::PushL( txt );
+        ConstructL( *txt );
+        CleanupStack::PopAndDestroy( txt );
+        }
+
+    HBufC* bitmapFile = aReader.ReadHBufCL(); // bmp filename
+    TInt bitmapId     = aReader.ReadInt16();  // bmp id
+    TInt maskId       = aReader.ReadInt16();  // bmp mask id
+
+    if ( bitmapFile )
+        {
+        CleanupStack::PushL( bitmapFile );
+        TFileName fileName( *bitmapFile );
+        CompleteWithAppPath( fileName );
+        if ( bitmapId != KErrNotFound )
+            {
+            CFbsBitmap* bitmap;
+            if ( maskId != KErrNotFound )
+                {
+                CFbsBitmap* mask;
+                AknIconUtils::CreateIconLC( bitmap,
+                                            mask,
+                                            fileName,
+                                            bitmapId,
+                                            maskId );
+                CleanupStack::Pop( mask );
+                CleanupStack::Pop( bitmap );
+                // moves ownership of bitmap and mask at beginning =>
+                // no need to have bitmap/mask in cleanupstack
+                ConstructL( bitmap, mask );
+                }
+            else
+                {
+                bitmap = AknIconUtils::CreateIconL( fileName, bitmapId );
+                // moves ownership of bitmap and mask at beginning =>
+                // no need to have bitmap/mask in cleanupstack
+                ConstructL( bitmap );
+                }
+            }
+        CleanupStack::PopAndDestroy( bitmapFile );  // bitmapFile
+        }
+
+    LoadColorBitmapL();
+    }
+
+void CAknTab::ConstructL( const TDesC& aTabText )
+    {
+    if ( !iExtension )
+        {
+        iExtension = CAknTabExtension::NewL();
+        }
+
+    iLabel = new (ELeave) CEikLabel;
+    iLabel->SetContainerWindowL( *this );
+    iLabel->SetTextL( aTabText );
+    iLabel->SetAlignment( EHCenterVCenter );
+    iLabel->SetAllMarginsTo( KNaviTabMargins );
+
+    if ( AknLayoutUtils::Variant() == EEuropeanVariant )
+        {
+        iLabel->SetFont( LatinBold12() );
+        }
+    else    // APAC
+        {
+        iLabel->SetFont( ApacPlain12() );
+        }
+
+    LoadColorBitmapL();
+    }
+
+void CAknTab::ConstructL( const CFbsBitmap* aTabBitmap,
+                          const CFbsBitmap* aMask )
+    {
+    if ( !iExtension )
+        {
+        iExtension = CAknTabExtension::NewL();
+        }
+
+    iBitmap = aTabBitmap;
+    iBitmapMask = aMask;
+    LoadColorBitmapL();
+    }
+
+void CAknTab::ReplaceTextL( const TDesC& aTabText )
+    {
+    if ( iLabel )
+        {
+        iLabel->SetTextL( aTabText );
+        }
+    }
+
+void CAknTab::SetActive( TBool aActive, TDrawNow aDrawNow )
+    {
+    iActive = aActive;
+
+    if ( aDrawNow == EDrawNow )
+        {
+        DrawNow();
+        }
+    }
+
+TBool CAknTab::Active() const
+    {
+    return iActive;
+    }
+
+
+TInt CAknTab::Id() const
+    {
+    return iId;
+    }
+
+
+enum CAknTab::TAknTabDataType CAknTab::TabType() const
+    {
+    TAknTabDataType tabType( EAknTabNone );
+
+    if ( iLabel && iBitmap )
+        {
+        tabType = EAknTabTextAndIcon;
+        }
+    else if ( iBitmap )
+        {
+        tabType = EAknTabIcon;
+        }
+    else if ( iLabel )
+        {
+        tabType = EAknTabText;
+        }
+
+    return tabType;
+    }
+
+
+TSize CAknTab::MinimumSize()
+    {
+    TSize minSize;
+
+    if ( iLabel )
+        {
+        minSize += iLabel->MinimumSize();
+        }
+    if ( iBitmap )
+        {
+        minSize += iBitmap->SizeInPixels();
+        }
+
+    return minSize;
+    }
+
+
+void CAknTab::SetDimmed( TBool aDimmed )
+    {
+    CCoeControl::SetDimmed( aDimmed );
+
+    if ( iLabel )
+        {
+        iLabel->SetDimmed( aDimmed );
+        }
+    }
+
+
+void CAknTab::GetColorUseListL( CArrayFix<TCoeColorUse>& aColorUseList ) const
+    {
+    TCoeColorUse colorUse;
+    colorUse.SetLogicalColor( EColorDialogBackground );
+    colorUse.SetUse( TCoeColorUse::EBack |
+                     TCoeColorUse::ESurrounds |
+                     TCoeColorUse::EActive |
+                     TCoeColorUse::ENormal |
+                     TCoeColorUse::ENeutral );
+    aColorUseList.AppendL( colorUse );
+    }
+
+
+void CAknTab::SizeChanged()
+    {
+    if ( AknStatuspaneUtils::FlatLayoutActive() &&
+         !iExtension->iNarrowTabLayout )
+        {
+        SizeChangedInFlatLayout();
+        }
+    else if ( iExtension->iNarrowTabLayout )
+        {
+        SizeChangedInNarrowLayout();
+        }
+    else
+        {
+        SizeChangedInNormalLayout();
+        }
+    }
+
+
+void CAknTab::SizeChangedInNormalLayout()
+    {
+    if ( !iColorBitmaps )
+        {
+        TRAP_IGNORE( LoadColorBitmapL() );
+        }
+
+    TBool landscape( Layout_Meta_Data::IsLandscapeOrientation() );
+    TBool staconPaneActive( AknStatuspaneUtils::StaconPaneActive() );
+    TBool longTab( iExtension && iExtension->iLongTab );
+    TRect rect( Rect() );
+
+    if ( iLabel && iBitmap )
+        {
+        iBitmapRect.LayoutRect(
+            rect,
+            AknLayoutScalable_Avkon::navi_navi_icon_text_pane_g1() );
+        AknIconUtils::SetSize( const_cast<CFbsBitmap*> ( iBitmap ),
+                               iBitmapRect.Rect().Size() );
+
+        AknLayoutUtils::LayoutLabel(
+            iLabel,
+            rect,
+            AknLayoutScalable_Avkon::navi_navi_icon_text_pane_t1() );
+
+        iLabel->CropText();
+        }
+    else
+        {
+        if ( iLabel )
+            {
+            TAknTextComponentLayout textLayout;
+
+            switch ( iExtension->iNumberOfTabsInTabGroup )
+                {
+                case 1:
+                    {
+                    textLayout =
+                        AknLayoutScalable_Avkon::tabs_2_long_active_pane_t1(
+                            landscape );
+                    break;
+                    }
+
+                case 2:
+                    {
+                    if ( longTab )
+                        {
+                        textLayout =
+                            AknLayoutScalable_Avkon::tabs_2_long_active_pane_t1(
+                                landscape );
+                        }
+                    else
+                        {
+                        if ( iActive )
+                            {
+                            textLayout =
+                                AknLayoutScalable_Avkon::tabs_2_active_pane_t1(
+                                    landscape );
+                            }
+                        else
+                            {
+                            textLayout =
+                                AknLayoutScalable_Avkon::tabs_2_passive_pane_t1(
+                                    landscape );
+                            }
+                        }
+                    break;
+                    }
+
+                case 3:
+                    {
+                    if ( longTab )
+                        {
+                        textLayout =
+                            AknLayoutScalable_Avkon::tabs_3_long_active_pane_t1(
+                                landscape );
+                        }
+                    else
+                        {
+                        if ( iActive )
+                            {
+                            textLayout =
+                                AknLayoutScalable_Avkon::tabs_3_active_pane_t1(
+                                    landscape );
+                            }
+                        else
+                            {
+                            textLayout =
+                                AknLayoutScalable_Avkon::tabs_3_passive_pane_t1(
+                                    landscape );
+                            }
+                        }
+                    break;
+                    }
+
+                case 4:
+                default:
+                    {
+                    textLayout =
+                        AknLayoutScalable_Avkon::tabs_4_active_pane_t1(
+                            landscape );
+                    break;
+                    }
+                }
+
+            AknLayoutUtils::LayoutLabel( iLabel, rect, textLayout );
+
+            iLabel->CropText();
+            }
+
+        if ( iBitmap )
+            {
+            TAknWindowComponentLayout l1( TAknWindowComponentLayout::Compose(
+                AknLayoutScalable_Avkon::navi_tabs_2_pane(),
+                TAknWindowComponentLayout::Compose(
+                    AknLayoutScalable_Avkon::tabs_2_active_pane( 0 ),
+                    AknLayoutScalable_Avkon::tabs_2_active_pane_g1() ) ) );
+
+            TAknWindowComponentLayout l2( TAknWindowComponentLayout::Compose(
+                AknLayoutScalable_Avkon::navi_tabs_3_pane(),
+                TAknWindowComponentLayout::Compose(
+                    AknLayoutScalable_Avkon::tabs_3_active_pane( 0 ),
+                    AknLayoutScalable_Avkon::tabs_3_active_pane_g1() ) ) );
+
+            TAknWindowComponentLayout l3( TAknWindowComponentLayout::Compose(
+                AknLayoutScalable_Avkon::navi_tabs_4_pane(),
+                TAknWindowComponentLayout::Compose(
+                    AknLayoutScalable_Avkon::tabs_4_active_pane( 0 ),
+                    AknLayoutScalable_Avkon::tabs_4_active_pane_g1() ) ) );
+
+            TAknLayoutRect layoutRect;
+
+            layoutRect.LayoutRect( rect, l1 );
+            TRect r1( layoutRect.Rect() );
+            layoutRect.LayoutRect( rect, l2 );
+            TRect r2( layoutRect.Rect() );
+            layoutRect.LayoutRect( rect, l3 );
+            TRect r3( layoutRect.Rect() );
+
+            TInt w = rect.Size().iWidth;
+            TSize size;
+
+            if ( w < r2.Width() ) // smaller than 3 icon layout - use 4 icon layout
+                {
+                size.iWidth = r3.Width();
+                size.iHeight = r3.Height();
+                }
+            else if ( w >= r2.Width() && w < r1.Width() )  // use 3 icon layout
+                {
+                size.iWidth = r2.Width();
+                size.iHeight = r2.Height();
+                }
+            else // same or larger than 2 icon layout - use 2 icon layout
+                {
+                size.iWidth = r1.Width();
+                size.iHeight = r1.Height();
+                }
+
+            AknIconUtils::SetSize( const_cast<CFbsBitmap*> (iBitmap), size );
+
+            TInt imageWidth  = iBitmap->SizeInPixels().iWidth;
+            TInt imageXPos   = rect.Width() - imageWidth;
+            TInt imageHeight = iBitmap->SizeInPixels().iHeight;
+            TInt imageYPos   = rect.Height() - imageHeight;
+
+            TRect nRect( 0,0, rect.Width(), rect.Height() );
+
+            if ( imageXPos < 0 || imageYPos < 0 )
+                {
+                iBitmapRect.LayoutRect( nRect,
+                                        ELayoutEmpty,
+                                        rect.iTl.iX,
+                                        rect.iTl.iY,
+                                        ELayoutEmpty,
+                                        ELayoutEmpty,
+                                        rect.Width(),
+                                        rect.Height());
+                }
+            else
+                {
+                // Center image.
+                imageXPos  = imageXPos >> 1;
+                imageXPos += rect.iTl.iX;
+                imageYPos  = imageYPos >> 1;
+                imageYPos += rect.iTl.iY;
+
+                iBitmapRect.LayoutRect( nRect,
+                                        ELayoutEmpty,
+                                        imageXPos,
+                                        imageYPos,
+                                        ELayoutEmpty,
+                                        ELayoutEmpty,
+                                        imageWidth,
+                                        imageHeight );
+                }
+            }
+        }
+    }
+
+
+void CAknTab::SizeChangedInNarrowLayout()
+    {
+    if ( !iColorBitmaps )
+        {
+        TRAP_IGNORE( LoadColorBitmapL() );
+        }
+
+    TBool isStaconPaneActive( AknStatuspaneUtils::StaconPaneActive() );
+    TBool longTab( iExtension && iExtension->iLongTab );
+
+    TRect rect( Rect() );
+
+    if ( iLabel && iBitmap )
+        {
+        iBitmapRect.LayoutRect(
+            rect,
+            AknLayoutScalable_Avkon::navi_navi_icon_text_pane_srt_g1() );
+        AknIconUtils::SetSize( const_cast<CFbsBitmap*> ( iBitmap ),
+                               iBitmapRect.Rect().Size() );
+        AknLayoutUtils::LayoutLabel(
+            iLabel,
+            rect,
+            AknLayoutScalable_Avkon::navi_navi_icon_text_pane_srt_t1( 0 ) );
+
+        iLabel->CropText();
+        }
+    else
+        {
+        if ( iLabel )
+            {
+            TAknTextComponentLayout textLayout;
+
+            switch ( iExtension->iNumberOfTabsInTabGroup )
+                {
+                case 1:
+                    {
+                    textLayout =
+                        AknLayoutScalable_Avkon::tabs_2_long_active_pane_t1(
+                            isStaconPaneActive );
+                    break;
+                    }
+
+                case 2:
+                    {
+                    if ( longTab )
+                        {
+                        textLayout =
+                            AknLayoutScalable_Avkon::tabs_2_long_active_pane_srt_t1(
+                                isStaconPaneActive );
+                        }
+                    else
+                        {
+                        textLayout =
+                            AknLayoutScalable_Avkon::tabs_2_active_pane_srt_t1(
+                                isStaconPaneActive );
+                        }
+                    break;
+                    }
+
+                case 3:
+                    {
+                    if ( longTab )
+                        {
+                        textLayout =
+                            AknLayoutScalable_Avkon::tabs_3_long_active_pane_srt_t1(
+                                isStaconPaneActive );
+                        }
+                    else
+                        {
+                        textLayout =
+                            AknLayoutScalable_Avkon::tabs_3_active_pane_srt_t1(
+                                isStaconPaneActive );
+                        }
+                    break;
+                    }
+
+                case 4:
+                default:
+                    {
+                    textLayout =
+                        AknLayoutScalable_Avkon::tabs_4_active_pane_srt_t1(
+                            isStaconPaneActive );
+                    break;
+                    }
+                }
+
+            AknLayoutUtils::LayoutLabel( iLabel, rect, textLayout );
+
+            iLabel->CropText();
+            }
+
+        if ( iBitmap )
+            {
+            TAknWindowComponentLayout l1(
+                AknLayoutScalable_Avkon::tabs_2_active_pane_srt_g1() );
+            TAknWindowComponentLayout l2(
+                AknLayoutScalable_Avkon::tabs_3_active_pane_srt_g1() );
+            TAknWindowComponentLayout l3(
+                AknLayoutScalable_Avkon::tabs_4_active_pane_srt_g1() );
+
+            TAknLayoutRect layoutRect;
+
+            layoutRect.LayoutRect( rect, l1 );
+            TRect r1 = layoutRect.Rect();
+            layoutRect.LayoutRect( rect, l2 );
+            TRect r2 = layoutRect.Rect();
+            layoutRect.LayoutRect( rect, l3 );
+            TRect r3 = layoutRect.Rect();
+
+            TInt w = rect.Size().iWidth;
+            TSize size;
+
+            if ( w < r2.Width() )  // smaller than 3 icon layout - use 4 icon layout
+                {
+                size.iWidth = r3.Width();
+                size.iHeight = r3.Height();
+                }
+            else if ( w >= r2.Width() && w < r1.Width() )  // use 3 icon layout
+                {
+                size.iWidth = r2.Width();
+                size.iHeight = r2.Height();
+                }
+            else // same or larger than 2 icon layout - use 2 icon layout
+                {
+                size.iWidth = r1.Width();
+                size.iHeight = r1.Height();
+                }
+
+            AknIconUtils::SetSize( const_cast<CFbsBitmap*> (iBitmap), size );
+
+            TInt imageWidth  = iBitmap->SizeInPixels().iWidth;
+            TInt imageXPos   = rect.Width() - imageWidth;
+            TInt imageHeight =  iBitmap->SizeInPixels().iHeight;
+            TInt imageYPos   = rect.Height() - imageHeight;
+
+            TRect nRect( 0,0, rect.Width(), rect.Height() );
+
+            if ( imageXPos < 0 || imageYPos < 0 )
+                {
+                iBitmapRect.LayoutRect( nRect,
+                                        ELayoutEmpty,
+                                        rect.iTl.iX,
+                                        rect.iTl.iY,
+                                        ELayoutEmpty,
+                                        ELayoutEmpty,
+                                        rect.Width(),
+                                        rect.Height() );
+                }
+            else
+                {
+                // Center image.
+                imageXPos  = imageXPos >> 1;
+                imageXPos += rect.iTl.iX;
+                imageYPos  = imageYPos >> 1;
+                imageYPos += rect.iTl.iY;
+                iBitmapRect.LayoutRect( nRect,
+                                        ELayoutEmpty,
+                                        imageXPos,
+                                        imageYPos,
+                                        ELayoutEmpty,
+                                        ELayoutEmpty,
+                                        imageWidth,
+                                        imageHeight );
+                }
+            }
+        }
+
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles size change events in flat status pane layouts.
+// ---------------------------------------------------------------------------
+//
+void CAknTab::SizeChangedInFlatLayout()
+    {
+    if ( !iColorBitmaps )
+        {
+        TRAP_IGNORE( LoadColorBitmapL() );
+        }
+
+    TBool longTab( iExtension && iExtension->iLongTab );
+
+    TRect rect( Rect() );
+
+    if ( iLabel && iBitmap )
+        {
+        iBitmapRect.LayoutRect( rect, AknLayoutScalable_Avkon::navi_navi_icon_text_pane_g1() );
+
+        AknIconUtils::SetSize( const_cast<CFbsBitmap*> ( iBitmap ),
+                               iBitmapRect.Rect().Size() );
+
+        AknLayoutUtils::LayoutLabel(
+            iLabel,
+            rect,
+            AknLayoutScalable_Avkon::navi_navi_icon_text_pane_t1() );
+
+        iLabel->CropText();
+        }
+    else
+        {
+        if ( iLabel )
+            {
+            TAknTextComponentLayout textLayout;
+
+            switch ( iExtension->iNumberOfTabsInTabGroup )
+                {
+                case 1:
+                    {
+                    textLayout =
+                        AknLayoutScalable_Avkon::tabs_2_long_active_pane_t1( 0 );
+                    break;
+                    }
+
+                case 2:
+                    {
+                    if ( longTab )
+                        {
+                        textLayout =
+                            AknLayoutScalable_Avkon::tabs_2_long_active_pane_t1( 0 );
+                        }
+                    else
+                        {
+                        if ( iActive )
+                            {
+                            textLayout =
+                                AknLayoutScalable_Avkon::tabs_2_active_pane_t1( 0 );
+                            }
+                        else
+                            {
+                            textLayout =
+                                AknLayoutScalable_Avkon::tabs_2_passive_pane_t1( 0 );
+                            }
+                        }
+                    break;
+                    }
+
+                case 3:
+                    {
+                    if ( longTab )
+                        {
+                        textLayout =
+                            AknLayoutScalable_Avkon::tabs_3_long_active_pane_t1( 0 );
+                        }
+                    else
+                        {
+                        if ( iActive )
+                            {
+                            textLayout =
+                                AknLayoutScalable_Avkon::tabs_3_active_pane_t1( 0 );
+                            }
+                        else
+                            {
+                            textLayout =
+                                AknLayoutScalable_Avkon::tabs_3_passive_pane_t1( 0 );
+                            }
+                        }
+                    break;
+                    }
+
+                case 4:
+                default:
+                    {
+                    textLayout =
+                        AknLayoutScalable_Avkon::tabs_4_active_pane_t1( 0 );
+                    break;
+                    }
+                }
+
+            AknLayoutUtils::LayoutLabel( iLabel, rect, textLayout );
+
+            iLabel->CropText();
+            }
+
+        if ( iBitmap )
+            {
+            TAknWindowComponentLayout l1(
+                AknLayoutScalable_Avkon::tabs_2_active_pane_g1() );
+            TAknWindowComponentLayout l2(
+                AknLayoutScalable_Avkon::tabs_3_active_pane_g1() );
+            TAknWindowComponentLayout l3(
+                AknLayoutScalable_Avkon::tabs_4_active_pane_g1() );
+
+            TAknLayoutRect layoutRect;
+
+            layoutRect.LayoutRect( rect, l1 );
+            TRect r1 = layoutRect.Rect();
+            layoutRect.LayoutRect( rect, l2 );
+            TRect r2 = layoutRect.Rect();
+            layoutRect.LayoutRect( rect, l3 );
+            TRect r3 = layoutRect.Rect();
+
+            TInt w = rect.Size().iWidth;
+            TSize size;
+
+            if ( w < r2.Width() )  // smaller than 3 icon layout - use 4 icon layout
+                {
+                size.iWidth = r3.Width();
+                size.iHeight = r3.Height();
+                }
+            else if ( w >= r2.Width() && w < r1.Width() )  // use 3 icon layout
+                {
+                size.iWidth = r2.Width();
+                size.iHeight = r2.Height();
+                }
+            else // same or larger than 2 icon layout - use 2 icon layout
+                {
+                size.iWidth = r1.Width();
+                size.iHeight = r1.Height();
+                }
+
+            AknIconUtils::SetSize( const_cast<CFbsBitmap*> (iBitmap), size );
+
+            TInt imageWidth  = iBitmap->SizeInPixels().iWidth;
+            TInt imageXPos   = rect.Width() - imageWidth;
+            TInt imageHeight =  iBitmap->SizeInPixels().iHeight;
+            TInt imageYPos   = rect.Height() - imageHeight;
+
+            TRect nRect( 0,0, rect.Width(), rect.Height() );
+
+            if ( imageXPos < 0 || imageYPos < 0 )
+                {
+                iBitmapRect.LayoutRect( nRect,
+                                        ELayoutEmpty,
+                                        rect.iTl.iX,
+                                        rect.iTl.iY,
+                                        ELayoutEmpty,
+                                        ELayoutEmpty,
+                                        rect.Width(),
+                                        rect.Height() );
+                }
+            else
+                {
+                // Center image.
+                imageXPos  = imageXPos >> 1;
+                imageXPos += rect.iTl.iX;
+                imageYPos  = imageYPos >> 1;
+                imageYPos += rect.iTl.iY;
+                iBitmapRect.LayoutRect( nRect,
+                                        ELayoutEmpty,
+                                        imageXPos,
+                                        imageYPos,
+                                        ELayoutEmpty,
+                                        ELayoutEmpty,
+                                        imageWidth,
+                                        imageHeight );
+                }
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the amount of component controls.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTab::CountComponentControls() const
+    {
+    TInt count( 0 );
+
+    if ( iLabel )
+        {
+        count++;
+        }
+
+    return count;
+    }
+
+
+CCoeControl* CAknTab::ComponentControl( TInt /*aIndex*/ ) const
+    {
+    return iLabel;
+    }
+
+void CAknTab::Draw( const TRect& /*aRect*/ ) const
+    {
+    if ( iLabel )
+        {
+        MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+        TRgb color;
+
+
+        if ( iExtension->iNumberOfTabsInTabGroup == 1 ) // >= EAknTabWidthWithOneTab
+            {
+            TInt error = AknsUtils::GetCachedColor( skin, color,
+                KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG2 );
+            if ( !error )
+                {
+                // Ignore error
+                TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( *iLabel,
+                    EColorLabelText, color ) );
+                }
+            }
+        else
+            {
+            if ( iActive )
+                {
+                TInt error = AknsUtils::GetCachedColor( skin, color,
+                    KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG3 );
+                if ( !error )
+                    {
+                    // Ignore error
+                    TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( *iLabel,
+                        EColorLabelText, color ) );
+                    }
+                }
+            else
+                {
+                TInt error = AknsUtils::GetCachedColor( skin, color,
+                    KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG4 );
+                if ( !error )
+                    {
+                    // Ignore error
+                    TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( *iLabel,
+                        EColorLabelText, color ) );
+                    }
+                }
+            }
+
+        }
+
+    if ( iBitmap )
+        {
+        TBool legacyDraw = EFalse;
+        CWindowGc& gc=SystemGc();
+        MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+        if ( skin && !iExtension->iMultiColorMode )
+            {
+            CFbsBitmap* colorBitmap = NULL;
+            if (iColorBitmaps &&
+                iColorBitmaps->At(KTabColorBitmapActiveColorIndex) &&
+                iColorBitmaps->At(KTabColorBitmapPassiveColorIndex) )
+                {
+                if( iActive )
+                    {
+                    colorBitmap = iColorBitmaps->At(KTabColorBitmapActiveColorIndex);
+                    }
+                else
+                    {
+                    colorBitmap = iColorBitmaps->At(KTabColorBitmapPassiveColorIndex);
+                    }
+                }
+
+            if ( colorBitmap && iBitmapMask )
+                {
+                iBitmapRect.DrawImage( gc,
+                                       colorBitmap,
+                                       const_cast<CFbsBitmap*> ( iBitmapMask ) );
+                }
+            else
+                {
+                legacyDraw = ETrue;
+                }
+            }
+        else // No skin (legacy drawing) or multi-colored drawing.
+            {
+            legacyDraw = ETrue;
+            }
+        if ( legacyDraw )
+            {
+            iBitmapRect.DrawImage( gc,
+                                   const_cast<CFbsBitmap*>( iBitmap ),
+                                   const_cast<CFbsBitmap*>( iBitmapMask ) );
+            }
+        }
+    }
+
+void CAknTab::HandlePointerEventL( const TPointerEvent& aPointerEvent )
+    {
+    if ( aPointerEvent.iType==TPointerEvent::EButton1Down &&
+         !iActive &&
+         !IsDimmed() )
+        {
+        ReportEventL( MCoeControlObserver::EEventStateChanged );
+        }
+    }
+
+EXPORT_C void* CAknTab::ExtensionInterface( TUid /*aInterface*/ )
+    {
+    return NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// Loads the bitmap used in drawing the tab icon with correct color.
+// ---------------------------------------------------------------------------
+//
+void CAknTab::LoadColorBitmapL()
+    {
+    if ( iColorBitmaps )
+        {
+        iColorBitmaps->ResetAndDestroy();
+        delete iColorBitmaps;
+        iColorBitmaps = NULL;
+        }
+
+    TRect rect( Rect() );
+
+    if ( rect.IsEmpty() )
+        {
+        // We cannot decide the right color.
+        // This method will be called again when the rect is set.
+        return;
+        }
+
+    if ( !iColorBitmaps )
+        {
+        iColorBitmaps = new (ELeave) CAknTabColorBitmapArray(
+            KTabColorBitmapQueueGranularity );
+        CFbsBitmap* activeColorBitmap = new (ELeave) CFbsBitmap();
+        CleanupStack::PushL(activeColorBitmap);
+        CFbsBitmap* passiveColorBitmap = new (ELeave) CFbsBitmap();
+        CleanupStack::PushL( passiveColorBitmap );
+        iColorBitmaps->AppendL( activeColorBitmap );
+        iColorBitmaps->AppendL( passiveColorBitmap );
+        CleanupStack::Pop( 2, activeColorBitmap );
+        }
+
+    TBool isStaconPaneActive( AknStatuspaneUtils::StaconPaneActive() );
+    TBool isFlatLayoutActive(
+        isStaconPaneActive ? EFalse : AknStatuspaneUtils::FlatLayoutActive() );
+
+    TAknLayoutRect layoutRect;
+    // LAF does not contain line for EAknTabWidthWithOneTab
+    // so we use this instead.
+    layoutRect.LayoutRect( rect, AknLayoutScalable_Avkon::navi_tabs_2_pane() );
+    TRect tabRect = layoutRect.Rect();
+    if ( tabRect.Width() < 0 || tabRect.Height() < 0 )
+        {
+        tabRect.SetRect( 0, 0, 0, 0 );
+        }
+
+    if ( !( iColorBitmaps &&
+            iColorBitmaps->At( KTabColorBitmapActiveColorIndex ) &&
+            iColorBitmaps->At( KTabColorBitmapPassiveColorIndex ) ) )
+        {
+        return;
+        }
+
+    // Note 64K or 16M mode seems to have some issues with some HW possibly
+    // related to bitmap compression, so we use display's color mode
+    // here instead for now instead of the AknIconConfig's preferred
+    // display mode.
+    TDisplayMode screenDisplayMode( iEikonEnv->ScreenDevice()->DisplayMode() );
+    iColorBitmaps->At( KTabColorBitmapActiveColorIndex )->Create(
+        Size(), screenDisplayMode );
+    iColorBitmaps->At( KTabColorBitmapPassiveColorIndex )->Create(
+        Size(), screenDisplayMode );
+
+    TRgb color( KRgbGray );
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+    // First active color...
+    TAknsQsnIconColorsIndex colorIndex;
+    if (iExtension->iNumberOfTabsInTabGroup == 1)
+        {
+        colorIndex = EAknsCIQsnIconColorsCG7;
+        }
+    else
+        {
+        colorIndex = EAknsCIQsnIconColorsCG8;
+        }
+    AknsUtils::GetCachedColor( skin,
+                               color,
+                               KAknsIIDQsnIconColors,
+                               colorIndex );
+
+    CFbsBitmapDevice* destinationDevice =
+        CFbsBitmapDevice::NewL(
+            iColorBitmaps->At( KTabColorBitmapActiveColorIndex ) );
+    CleanupStack::PushL( destinationDevice );
+    CFbsBitGc* destinationGc;
+    User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) );
+    destinationGc->SetPenColor( color );
+    destinationGc->SetPenStyle( CGraphicsContext::ESolidPen );
+    destinationGc->SetBrushColor( color );
+    destinationGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+    destinationGc->DrawRect(
+        TRect( iColorBitmaps->At( KTabColorBitmapActiveColorIndex )->SizeInPixels() ) );
+
+    delete destinationGc;
+    CleanupStack::PopAndDestroy( destinationDevice );
+
+    // ...then passive color.
+    AknsUtils::GetCachedColor( skin,
+                               color,
+                               KAknsIIDQsnIconColors,
+                               EAknsCIQsnIconColorsCG9 );
+
+    destinationDevice =
+        CFbsBitmapDevice::NewL(
+            iColorBitmaps->At( KTabColorBitmapPassiveColorIndex ) );
+    CleanupStack::PushL(destinationDevice);
+    User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) );
+    destinationGc->SetPenColor( color );
+    destinationGc->SetPenStyle( CGraphicsContext::ESolidPen );
+    destinationGc->SetBrushColor( color );
+    destinationGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+    destinationGc->DrawRect(
+        TRect( iColorBitmaps->At( KTabColorBitmapPassiveColorIndex )->SizeInPixels() ) );
+
+    delete destinationGc;
+    CleanupStack::PopAndDestroy( destinationDevice );
+    }
+
+
+void CAknTab::HandleResourceChange( TInt aType )
+    {
+    CCoeControl::HandleResourceChange( aType );
+
+    if ( aType == KEikDynamicLayoutVariantSwitch ||
+         aType == KEikColorResourceChange ||
+         aType == KAknsMessageSkinChange )
+        {
+        TRAP_IGNORE( LoadColorBitmapL() );
+        DrawDeferred();
+        }
+    }
+
+void CAknTab::SetTotalAmountOfTabs( TInt aAmount )
+    {
+    iExtension->iNumberOfTabsInTabGroup = aAmount;
+    
+    if ( !iColorBitmaps )
+    	{
+      LoadColorBitmapL();
+      }
+    }
+
+void CAknTab::SetNarrowTabLayout( TBool aNarrow )
+    {
+    iExtension->iNarrowTabLayout = aNarrow;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknTab::SetMultiColorMode
+// ---------------------------------------------------------------------------
+//
+void CAknTab::SetMultiColorMode( TBool aMultiColor )
+    {
+    if ( iExtension )
+        {
+        iExtension->iMultiColorMode = aMultiColor;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknTab::MultiColorMode
+// ---------------------------------------------------------------------------
+//
+TBool CAknTab::MultiColorMode() const
+    {
+    if ( iExtension )
+        {
+        return iExtension->iMultiColorMode;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknTab::SetLongTabLayout
+// Sets this tab to use long layout.
+// ---------------------------------------------------------------------------
+//
+void CAknTab::SetLongTabLayout( TBool aLongTab )
+    {
+    if ( iExtension )
+        {
+        iExtension->iLongTab = aLongTab;
+        }
+    }
+
+
+// ================= PRIVATE CLASS =======================
+
+class CAknTabGroupExtension : public CBase
+    {
+public:
+
+    /** Types of supported tab group animations. */
+    enum TTabAnimationType
+        {
+        /**
+        * No animation is currently used.
+        */
+        ENoAnimation = 0,
+        /**
+        * Animation type used when switching between
+        * normal and flat tab group layout.
+        */
+        ELayoutSwitchAnimation,
+        /**
+        * Animation type used when cycling between tabs in three tab layout
+        * when there are more than three tabs in the tab group.
+        */
+        ETabCycleAnimation
+        };
+
+    CAknTabGroupExtension();
+    ~CAknTabGroupExtension(){};
+
+public: // Member data.
+
+    CFbsBitmap*           iStaconTabBitmaps[KTabNumberOfTabBitmaps];
+    CFbsBitmap*           iStaconTabMaskBitmaps[KTabNumberOfTabBitmaps];
+    CAknTabGroupGraphics* iTabSvgGraphics;
+
+    /** Layout used for the tab background graphics. */
+    CAknTabGroupGraphics::SAknTabGroupBackgroundLayout iTabBackgroundLayout;
+
+    /** Layout used for the tab background graphics during tab animation. */
+    CAknTabGroupGraphics::SAknTabGroupBackgroundLayout iNextTabBackgroundLayout;
+
+    /** Timer used in tab animations. */
+    CPeriodic* iTabAnimationTimer;
+
+    /** Type of the current tab animation. */
+    TTabAnimationType iTabAnimationType;
+
+    /** Amount of completed tab animation steps. */
+    TInt iAmountOfDoneAnimationEvents;
+
+    /** Direction of the current tab cycle animation (left or right). */
+    CAknTabGroup::TDirection iTabCycleAnimationDirection;
+
+    /** Horizontal distance left in the tab cycle animation. */
+    TInt iTabCycleAnimationDistanceLeft;
+
+    /** Is the tab cycle animation in process. */
+    TBool iTabCycleAnimationOngoing;
+
+    /**
+    * Specifies on which side of the tab group there are tabs
+    * that don't fit in the set of currently displayed tabs.
+    */
+    CAknTabGroupGraphics::TTabsHidden iTabsHidden;
+
+    TBool             iTabAnimationDoubleBufferNarrowTabLayout;
+    TBool             iTabAnimationDoubleBufferLongTabs;
+    TInt              iTabAnimationDoubleBufferNumberOfTabsShown;
+    TInt              iTabAnimationDoubleBufferpositionActive;
+
+    TBool  iNarrowTabLayout;
+    TBool  iNarrowTabLayoutNext;
+
+    /** Are navigation arrows shown in the current tab layout. */
+    TBool  iNaviArrowsUsed;
+
+    /** Index of the tab where pointer down event happened. */
+    TInt   iPointerDownTab;
+
+    /** X-value of the pointer down event position. */
+    TInt   iPointerDownXPosition;
+
+    /** This is the tab width that is set by the application. */
+    TInt   iRequestedTabWidth;
+    };
+
+
+CAknTabGroupExtension::CAknTabGroupExtension()
+    {
+    iPointerDownTab       = -1;
+    iPointerDownXPosition = -1;
+    }
+
+
+//
+// CAknTabGroup
+//
+
+EXPORT_C CAknTabGroup::CAknTabGroup() : iActiveTab(KAknTabGroupNoTabs)
+    {
+    iTabFixedWidth     = -1;
+    iFirstShownTab     = 0;
+    iNumberOfTabsShown = 0;
+
+    // Tab bitmaps and masks for every tab group layouts
+    iBitmapNames[0]  = EMbmAvkonQgn_graf_tab_21;
+    iBitmapNames[1]  = EMbmAvkonQgn_graf_tab_22;
+    iBitmapNames[2]  = EMbmAvkonQgn_graf_tab_long_21;
+    iBitmapNames[3]  = EMbmAvkonQgn_graf_tab_long_22;
+    iBitmapNames[4]  = EMbmAvkonQgn_graf_tab_long_31;
+    iBitmapNames[5]  = EMbmAvkonQgn_graf_tab_long_32;
+    iBitmapNames[6]  = EMbmAvkonQgn_graf_tab_long_33;
+    iBitmapNames[7]  = EMbmAvkonQgn_graf_tab_31;
+    iBitmapNames[8]  = EMbmAvkonQgn_graf_tab_32;
+    iBitmapNames[9]  = EMbmAvkonQgn_graf_tab_33;
+    iBitmapNames[10] = EMbmAvkonQgn_graf_tab_41;
+    iBitmapNames[11] = EMbmAvkonQgn_graf_tab_42;
+    iBitmapNames[12] = EMbmAvkonQgn_graf_tab_43;
+    iBitmapNames[13] = EMbmAvkonQgn_graf_tab_44;
+
+    iBitmapMaskNames[0]  = EMbmAvkonQgn_graf_tab_21_mask;
+    iBitmapMaskNames[1]  = EMbmAvkonQgn_graf_tab_22_mask;
+    iBitmapMaskNames[2]  = EMbmAvkonQgn_graf_tab_long_21_mask;
+    iBitmapMaskNames[3]  = EMbmAvkonQgn_graf_tab_long_22_mask;
+    iBitmapMaskNames[4]  = EMbmAvkonQgn_graf_tab_long_31_mask;
+    iBitmapMaskNames[5]  = EMbmAvkonQgn_graf_tab_long_32_mask;
+    iBitmapMaskNames[6]  = EMbmAvkonQgn_graf_tab_long_33_mask;
+    iBitmapMaskNames[7]  = EMbmAvkonQgn_graf_tab_31_mask;
+    iBitmapMaskNames[8]  = EMbmAvkonQgn_graf_tab_32_mask;
+    iBitmapMaskNames[9]  = EMbmAvkonQgn_graf_tab_33_mask;
+    iBitmapMaskNames[10] = EMbmAvkonQgn_graf_tab_41_mask;
+    iBitmapMaskNames[11] = EMbmAvkonQgn_graf_tab_42_mask;
+    iBitmapMaskNames[12] = EMbmAvkonQgn_graf_tab_43_mask;
+    iBitmapMaskNames[13] = EMbmAvkonQgn_graf_tab_44_mask;
+
+    iMirrored = AknLayoutUtils::LayoutMirrored();
+    }
+
+EXPORT_C CAknTabGroup::~CAknTabGroup()
+    {
+    AKNTASHOOK_REMOVE();
+    if ( iTabArray )
+        {
+        iTabArray->ResetAndDestroy();
+        }
+    delete iTabArray;
+
+    for ( TInt i = 0; i < KTabNumberOfTabBitmaps; i++ )
+        {
+        delete( iTabBitmaps[i] );
+        delete( iTabMaskBitmaps[i] );
+        }
+
+    if ( iExtension )
+        {
+        for ( TInt j = 0; j < KTabNumberOfTabBitmaps; j++ )
+            {
+            delete( iExtension->iStaconTabBitmaps[j] );
+            delete( iExtension->iStaconTabMaskBitmaps[j] );
+            }
+
+        delete iExtension->iTabSvgGraphics;
+        if ( iExtension->iTabAnimationTimer )
+            {
+            iExtension->iTabAnimationTimer->Cancel();
+            delete iExtension->iTabAnimationTimer;
+            }
+        }
+
+    delete iExtension;
+
+    }
+
+EXPORT_C CAknTabGroup* CAknTabGroup::NewL( const CCoeControl& aParent )
+    {
+    CAknTabGroup* self = CAknTabGroup::NewLC( aParent );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+EXPORT_C CAknTabGroup* CAknTabGroup::NewLC( const CCoeControl& aParent )
+    {
+    CAknTabGroup* self = new (ELeave) CAknTabGroup;
+    CleanupStack::PushL( self );
+    self->SetContainerWindowL( aParent );
+    self->ConstructL();
+    AKNTASHOOK_ADDL( self, "CAknTabGroup" );
+    return self;
+    }
+
+EXPORT_C TInt CAknTabGroup::AddTabL( TResourceReader& aReader )
+    {
+    CAknTab* newTab = CAknTab::NewL( *this, aReader );
+    CommonAddTabL( newTab ); // Takes ownership of newTab safely.
+    return newTab->Id();
+    }
+
+EXPORT_C void CAknTabGroup::AddTabL( TInt aTabId, const TDesC& aTabText )
+    {
+    CAknTab* newTab = CAknTab::NewL( aTabId, *this, aTabText );
+    CommonAddTabL( newTab );  // Takes ownership of newTab safely.
+    }
+
+
+EXPORT_C void CAknTabGroup::AddTabL( TInt aTabId,
+                                     const TDesC& aTabText,
+                                     const CFbsBitmap* aTabBitmap,
+                                     const CFbsBitmap* aMask)
+    {
+    CAknTab* newTab = CAknTab::NewL( aTabId, *this, aTabText, aTabBitmap, aMask );
+    CommonAddTabL( newTab );  // Takes ownership of newTab safely.
+    }
+
+
+EXPORT_C void CAknTabGroup::AddTabL( TInt aTabId,
+                                     const CFbsBitmap* aTabBitmap,
+                                     const CFbsBitmap* aMask)
+    {
+    CAknTab* newTab = CAknTab::NewL( aTabId, *this, aTabBitmap, aMask );
+    CommonAddTabL( newTab );  // Takes ownership of newTab safely.
+    }
+
+void CAknTabGroup::CommonAddTabL( CAknTab* aTab )
+    {
+    CleanupStack::PushL( aTab );
+    aTab->SetObserver( this );
+    aTab->SetControlContext( this );
+
+    if ( iMirrored && iTabObserver )
+        {
+        // If tab group is mirrored then tabs are inserted in
+        // reverse order.
+        iTabArray->InsertL( 0, aTab );
+        }
+    else
+        {
+        iTabArray->AppendL( aTab );
+        }
+
+    CleanupStack::Pop( aTab );
+
+    if ( iTabFixedWidth < 0 && TabCount() > 1 )
+        {
+        SetTabFixedWidthL( KTabWidthWithTwoTabs );
+        }
+    }
+
+EXPORT_C void CAknTabGroup::ReplaceTabL( TResourceReader& aReader )
+    {
+    CAknTab* newTab = CAknTab::NewL( *this, aReader );
+    CommonReplaceTabL( newTab ); // Takes ownership of the newTab safely
+    }
+
+EXPORT_C void CAknTabGroup::ReplaceTabL( TInt aTabId,const TDesC& aTabText )
+    {
+    CAknTab* newTab=CAknTab::NewL( aTabId, *this, aTabText );
+    CommonReplaceTabL( newTab ); // Takes ownership of the newTab safely
+    }
+
+EXPORT_C void CAknTabGroup::ReplaceTabL( TInt aTabId,
+                                         const TDesC& aTabText,
+                                         const CFbsBitmap* aTabBitmap,
+                                         const CFbsBitmap* aMask )
+    {
+    CAknTab* newTab = CAknTab::NewL( aTabId, *this, aTabText, aTabBitmap, aMask );
+    CommonReplaceTabL( newTab ); // Takes ownership of the newTab safely
+    }
+
+EXPORT_C void CAknTabGroup::ReplaceTabL( TInt aTabId,
+                                         const CFbsBitmap* aTabBitmap,
+                                         const CFbsBitmap* aMask )
+    {
+    CAknTab* newTab = CAknTab::NewL( aTabId, *this, aTabBitmap, aMask );
+    CommonReplaceTabL( newTab ); // Takes ownership of the newTab safely
+    }
+
+void CAknTabGroup::CommonReplaceTabL( CAknTab* aTab )
+    {
+    CleanupStack::PushL( aTab );
+    aTab->SetObserver( this );
+    TInt tabIndex = ConvertTabIndex( TabIndexFromId( aTab->Id() ) );
+    __ASSERT_ALWAYS( tabIndex >= 0, Panic( EAknPanicOutOfRange ) );
+
+    // Is replaced tab active tab or not
+    TBool isActiveTab =  iTabArray->At( tabIndex )->Active();
+    TBool isMultiColor = iTabArray->At( tabIndex )->MultiColorMode();
+    delete iTabArray->At( tabIndex );
+    iTabArray->Delete( tabIndex );
+    iTabArray->InsertL( tabIndex, aTab );
+    CleanupStack::Pop( aTab );
+
+    aTab->SetMultiColorMode( isMultiColor );
+    aTab->SetControlContext( this );
+    aTab->SetActive( isActiveTab, ENoDrawNow );
+    SizeChanged();
+    TInt event = MAknNavigationObserver::ENaviEventRedrawNeeded;
+    ReportEventL( static_cast<MCoeControlObserver::TCoeEvent>( event ) );
+    }
+
+EXPORT_C void CAknTabGroup::ReplaceTabTextL( TInt aTabId, const TDesC& aTabText )
+    {
+    TInt tabIndex = ConvertTabIndex( TabIndexFromId( aTabId ) );
+    __ASSERT_ALWAYS( tabIndex >= 0, Panic( EAknPanicOutOfRange ) );
+    iTabArray->At( tabIndex )->ReplaceTextL( aTabText );
+    SizeChanged();
+    TInt event = MAknNavigationObserver::ENaviEventRedrawNeeded;
+    ReportEventL( STATIC_CAST( MCoeControlObserver::TCoeEvent, event ) );
+    }
+
+EXPORT_C void CAknTabGroup::DeleteTabL( TInt aTabId )
+    {
+    TInt oldActiveTab = iActiveTab;
+    TInt tabIndex = ConvertTabIndex( TabIndexFromId( aTabId ) );
+    __ASSERT_ALWAYS( tabIndex >= 0, Panic( EAknPanicOutOfRange ) );
+    delete iTabArray->At( tabIndex );
+    iTabArray->Delete( tabIndex );
+    TInt tabCount = TabCount();
+    if ( tabCount == 0 )
+        {
+        iActiveTab = KAknTabGroupNoTabs;
+        }
+    if ( tabIndex < iActiveTab )
+        {
+        iActiveTab--;
+        }
+    else if ( tabIndex == iActiveTab && iActiveTab == tabCount )
+        {
+        iActiveTab--;
+        if ( iFirstShownTab > 0 )
+            {
+            iFirstShownTab--;
+            }
+        }
+
+    SizeChanged();
+
+    TInt event = MAknNavigationObserver::ENaviEventRedrawNeeded;
+    if ( tabCount <= 1 )
+        {
+        event = MAknNavigationObserver::ENaviEventOneItemExists;
+        }
+    else if ( iActiveTab == 0 && oldActiveTab != 0 )
+        {
+        event = MAknNavigationObserver::ENaviEventLeftMostItemReached;
+        }
+    else if ( iActiveTab == ( tabCount - 1 ) &&
+              oldActiveTab != tabCount )
+        {
+        event = MAknNavigationObserver::ENaviEventRightMostItemReached;
+        }
+
+    ReportEventL( static_cast<MCoeControlObserver::TCoeEvent>( event ) );
+    }
+
+void CAknTabGroup::ConstructL()
+    {
+    iExtension = new (ELeave) CAknTabGroupExtension();
+    iExtension->iTabSvgGraphics = CAknTabGroupGraphics::NewL();
+    iExtension->iTabAnimationTimer = CPeriodic::NewL( CActive::EPriorityIdle );
+    iTabArray = new (ELeave) CArrayPtrFlat<CAknTab>( KTabArrayGranularity );
+    }
+
+EXPORT_C void CAknTabGroup::SetActiveTabById( TInt aTabId )
+    {
+    TInt tabIndex = Index( aTabId );
+    SetActiveTabByIndex( ConvertTabIndex( tabIndex ) );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets the active tab by tab index.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknTabGroup::SetActiveTabByIndex( TInt aTabIndex )
+    {
+    const TInt numTabs = TabCount();
+
+    TInt realIndex = ConvertTabIndex( aTabIndex );
+
+    // When iActiveTab doesn't change, nothing need to do.
+    if ( realIndex == iActiveTab )
+        {
+        return;
+        }
+
+    if ( realIndex >= 0 && realIndex < numTabs )
+        {
+        CArrayPtr<CAknTab>& tabArray = *iTabArray;
+        if ( iActiveTab >= 0 )
+            {
+            tabArray[iActiveTab]->SetFocus( EFalse, ENoDrawNow );
+            tabArray[iActiveTab]->SetActive( EFalse, ENoDrawNow );
+            }
+        iActiveTab = realIndex;
+        tabArray[iActiveTab]->SetFocus( ETrue, ENoDrawNow );
+        tabArray[iActiveTab]->SetActive( ETrue, ENoDrawNow );
+
+        if ( AknLayoutUtils::PenEnabled() &&
+             iTabFixedWidth == KTabWidthWithThreeTabs )
+            {
+            if ( realIndex != RightMostTabIndex() &&
+                 realIndex != LeftMostTabIndex() )
+                {
+                iFirstShownTab = realIndex - 1;
+                }
+            else if ( realIndex < iFirstShownTab )
+                {
+                iFirstShownTab = realIndex;
+                }
+            else if ( realIndex >= ( iFirstShownTab + iNumberOfTabsShown ) )
+                {
+                iFirstShownTab = realIndex - iNumberOfTabsShown + 1;
+                }
+            }
+        else
+            {
+            if ( realIndex < iFirstShownTab )
+                {
+                iFirstShownTab = realIndex;
+                }
+
+            if ( realIndex >= ( iFirstShownTab + iNumberOfTabsShown ) )
+                {
+                iFirstShownTab = realIndex - iNumberOfTabsShown + 1;
+                }
+            }
+
+        SizeChanged();
+
+        if ( !AknStatuspaneUtils::FlatLayoutActive() &&
+             iExtension->iTabAnimationType ==
+                 CAknTabGroupExtension::ELayoutSwitchAnimation )
+            {
+            CancelTabAnimationEventTimer();
+            }
+
+        SetDecoratorLayout( EFalse );
+        TRAP_IGNORE( InitTabAnimationL() );
+
+        ReportNavigationEvent();
+        }
+    }
+
+EXPORT_C TInt CAknTabGroup::ActiveTabId() const
+    {
+    if ( iActiveTab >= 0 )
+        {
+        return iTabArray->At( iActiveTab )->Id();
+        }
+
+    return KErrNotFound;
+    }
+
+EXPORT_C TInt CAknTabGroup::ActiveTabIndex() const
+    {
+    return ConvertTabIndex( iActiveTab );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets the width (used layout) of the tabs.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknTabGroup::SetTabFixedWidthL( TInt aWidth )
+    {
+    if ( iExtension )
+        {
+        // Store the requested width in case it's mapped here to another
+        // width but usable in some other layout.
+        iExtension->iRequestedTabWidth = aWidth;
+        }
+
+    TInt  numberOfTabsShown = iNumberOfTabsShown;
+    TInt  tabFixedWidth     = iTabFixedWidth;
+    TBool longTabs          = iLongTabs;
+
+    iLongTabs = EFalse;
+
+    if ( aWidth <= KTabWidthWithTwoTabs && aWidth > KTabWidthWithThreeTabs )
+        {
+        iNumberOfTabsShown = 2;
+        iTabFixedWidth = KTabWidthWithTwoTabs;
+        }
+    else if ( AknLayoutUtils::PenEnabled() )
+        {
+        if ( aWidth <= KTabWidthWithThreeTabs )
+            {
+            iNumberOfTabsShown = 3;
+            iTabFixedWidth = KTabWidthWithThreeTabs;
+            }
+        else
+            {
+            iNumberOfTabsShown = 1;
+            iTabFixedWidth = KTabWidthWithOneTab;
+            }
+        }
+    else
+        {
+        if ( aWidth <= KTabWidthWithThreeTabs &&
+             aWidth > KTabWidthWithFourTabs )
+            {
+            iNumberOfTabsShown = 3;
+            iTabFixedWidth = KTabWidthWithThreeTabs;
+            }
+        else if ( aWidth <= KTabWidthWithFourTabs )
+            {
+            iNumberOfTabsShown = 4;
+            iTabFixedWidth = KTabWidthWithFourTabs;
+            }
+        else if ( aWidth <= KTabWidthWithThreeLongTabs )
+            {
+            iNumberOfTabsShown = 3;
+            iTabFixedWidth = KTabWidthWithThreeLongTabs;
+            iLongTabs = ETrue;
+            }
+        else if ( aWidth <= KTabWidthWithTwoLongTabs )
+            {
+            iNumberOfTabsShown = 2;
+            iTabFixedWidth = KTabWidthWithTwoLongTabs;
+            iLongTabs = ETrue;
+            }
+        else
+            {
+            iNumberOfTabsShown = 1;
+            iTabFixedWidth = KTabWidthWithOneTab;
+            }
+        }
+
+    // When iNumberOfTabsShown, iTabFixedWidth, iLongTabs don't change,
+    // there's no reason to do LoadTabBitmapsL(), etc.
+    if ( numberOfTabsShown == iNumberOfTabsShown &&
+         tabFixedWidth == iTabFixedWidth &&
+         longTabs == iLongTabs )
+        {
+        return;
+        }
+
+    TInt tabCount = TabCount();
+
+    for ( TInt ii = 0; ii < tabCount; ii++ )
+        {
+        // Tell the tabs about the long tab layout
+        // for them to be able to layout their content
+        // correctly.
+        CAknTab* tab = iTabArray->At( ii );
+        tab->SetLongTabLayout( iLongTabs );
+        }
+
+    SizeChanged();
+
+    if ( iExtension &&
+         iExtension->iTabSvgGraphics &&
+         iExtension->iTabSvgGraphics->TabGroupBackgroundAvailable() )
+        {
+        iExtension->iTabBackgroundLayout.iUse = EFalse;
+
+        iExtension->iTabSvgGraphics->DrawTabGroupBackgroundL(
+            CAknTabGroupGraphics::ENoDraw,
+            iLongTabs,
+            iNumberOfTabsShown,
+            1,
+            NULL,
+            iExtension->iTabBackgroundLayout,
+            CAknTabGroupGraphics::ENone );
+
+        iExtension->iTabBackgroundLayout.iUse = ETrue;
+        SetDecoratorLayout( EFalse );
+        }
+
+    LoadTabBitmapsL( iNumberOfTabsShown, iLongTabs );
+    }
+
+
+EXPORT_C void CAknTabGroup::DimTab( TInt aTabId, TBool aDimmed )
+    {
+    TInt index = Index( aTabId );
+    if ( index >= 0 )
+        {
+        CAknTab* tabToDim = iTabArray->At( index );
+        tabToDim->SetDimmed( aDimmed );
+        }
+    }
+
+EXPORT_C TBool CAknTabGroup::IsTabDimmed( TInt aTabId ) const
+    {
+    TInt index = Index( aTabId );
+    if ( index < 0 )
+        {
+        return EFalse;
+        }
+    CAknTab* tabToCheck = iTabArray->At( index );
+    return tabToCheck->IsDimmed();
+    }
+
+EXPORT_C TInt CAknTabGroup::TabIndexFromId( TInt aTabId ) const
+    {
+    const TInt numTabs = TabCount();
+
+    for ( TInt ii = 0; ii < numTabs; ii++ )
+        {
+        if ( aTabId == iTabArray->At(ii)->Id() )
+            {
+            return ConvertTabIndex( ii );
+            }
+        }
+
+    return KErrNotFound;
+    }
+
+EXPORT_C TInt CAknTabGroup::TabIdFromIndex( TInt aTabIndex ) const
+    {
+    TInt realIndex = ConvertTabIndex( aTabIndex );
+    const TInt numTabs = TabCount();
+    if( ( realIndex >= 0 ) && ( realIndex < numTabs ) )
+        {
+        return iTabArray->At( realIndex )->Id();
+        }
+
+    return KErrNotFound;
+    }
+
+EXPORT_C TInt CAknTabGroup::TabCount() const
+    {
+    return iTabArray->Count();
+    }
+
+
+EXPORT_C void CAknTabGroup::SetObserver( MAknTabObserver* aObserver )
+    {
+    if ( !iTabObserver && iTabArray && TabCount() > 0 && iMirrored )
+        {
+        //
+        // If there isn't observer set but there is tabs already in array
+        // then the order of tabs must be changed if layout is mirrored.
+        //
+        TRAP_IGNORE( ReverseTabOrderL() );
+        iTabObserver = aObserver;
+        iActiveTab = ConvertTabIndex( iActiveTab );
+        SetActiveTabByIndex( ConvertTabIndex( iActiveTab ) );
+        }
+    else
+        {
+        iTabObserver = aObserver;
+        }
+    }
+
+void CAknTabGroup::ReverseTabOrderL()
+    {
+    if ( !iTabArray )
+        {
+        return;
+        }
+
+    CArrayPtr<CAknTab>* oldArray = iTabArray;
+    iTabArray = new(ELeave) CArrayPtrFlat<CAknTab>( KTabArrayGranularity );
+    CleanupStack::PushL( oldArray );
+    for ( TInt i = 0; i < oldArray->Count(); i++ )
+        {
+        iTabArray->InsertL( 0, oldArray->At(i) );
+        }
+
+    oldArray->Reset();
+    CleanupStack::PopAndDestroy( oldArray );
+    SizeChanged();
+    }
+
+
+EXPORT_C TSize CAknTabGroup::MinimumSize()
+    {
+    TAknWindowLineLayout layout;
+    CurrentLayout( layout );
+    TAknLayoutRect layoutRect;
+    layoutRect.LayoutRect( ParentRect( iExtension->iNaviArrowsUsed ), layout );
+    TRect rect( layoutRect.Rect() );
+
+    return rect.Size();
+    }
+
+
+EXPORT_C TKeyResponse CAknTabGroup::OfferKeyEventL( const TKeyEvent& aKeyEvent,
+                                                    TEventCode aType )
+    {
+    if ( aType != EEventKey )
+        {
+        return EKeyWasNotConsumed;
+        }
+
+    TKeyResponse keyResponse = EKeyWasNotConsumed;
+
+    switch ( aKeyEvent.iCode )
+        {
+        case EKeyLeftArrow:
+            if ( iActiveTab != LeftMostTabIndex() || aKeyEvent.iRepeats == 0 )
+                {
+                if ( CycleFocus( ELeft,EDrawNow ) )
+                    {
+                    keyResponse = EKeyWasConsumed;
+                    }
+                }
+            break;
+
+        case EKeyRightArrow:
+            if ( iActiveTab != RightMostTabIndex() || aKeyEvent.iRepeats == 0 )
+                {
+                if ( CycleFocus( ERight,EDrawNow ) )
+                    {
+                    keyResponse = EKeyWasConsumed;
+                    }
+                }
+            break;
+
+        default:
+            break;
+        }
+
+    if ( iTabObserver && keyResponse != EKeyWasNotConsumed )
+        {
+        iTabObserver->TabChangedL( ConvertTabIndex( iActiveTab ) );
+        }
+
+    return keyResponse;
+    }
+
+
+EXPORT_C void CAknTabGroup::GetColorUseListL(
+    CArrayFix<TCoeColorUse>& aColorUseList ) const
+    {
+    TCoeColorUse colorUse;
+    colorUse.SetLogicalColor( EColorDialogBackground );
+    colorUse.SetUse( TCoeColorUse::EBack |
+                     TCoeColorUse::ESurrounds |
+                     TCoeColorUse::EActive |
+                     TCoeColorUse::ENormal |
+                     TCoeColorUse::ENeutral );
+    aColorUseList.AppendL( colorUse );
+    }
+
+
+EXPORT_C void CAknTabGroup::HandleControlEventL( CCoeControl* aControl,
+                                                 TCoeEvent aEventType )
+    {
+    switch ( aEventType )
+        {
+        case EEventStateChanged:
+            HandleTabStateChanged( aControl );
+            break;
+        default:
+            break;
+        }
+    }
+
+
+EXPORT_C void CAknTabGroup::PrepareContext( CWindowGc& /*aGc*/ ) const
+    {
+    }
+
+
+EXPORT_C void CAknTabGroup::SizeChanged()
+    {
+    // In flat statuspane we do things differently because the layout may vary.
+    if ( AknStatuspaneUtils::FlatLayoutActive() && !NarrowTabLayout() )
+        {
+        SizeChangedInFlatLayout();
+        }
+    if ( NarrowTabLayout() )
+        {
+        SizeChangedInNarrowLayout();
+        }
+    else
+        {
+        SizeChangedInNormalLayout();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles size change events in normal tab group layout.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::SizeChangedInNormalLayout()
+    {
+    TRect rect( ParentRect( iExtension->iNaviArrowsUsed ) );
+
+    TInt tabsDrawn = iNumberOfTabsShown;
+    TInt numTabs   = TabCount();
+
+    if ( tabsDrawn > numTabs )
+        {
+        tabsDrawn = numTabs;
+        }
+
+    if ( ( iFirstShownTab + iNumberOfTabsShown ) > numTabs )
+        {
+        iFirstShownTab = 0;
+        }
+
+    // set bitmap sizes
+    TAknWindowLineLayout defaultLayout;
+    CurrentLayout( defaultLayout );
+    TAknLayoutRect r;
+    r.LayoutRect( rect, defaultLayout );
+    TRect tabPaneRect( r.Rect() );
+    TSize size( tabPaneRect.Size() );
+
+    for ( TInt i = 0; i < iNumberOfTabsShown; i++ )
+        {
+        AknIconUtils::SetSize( iTabBitmaps[i], size );
+        }
+
+    if ( iExtension->iTabCycleAnimationOngoing )
+        {
+        TRect emptyRect( 0, 0, 0, 0 );
+        for ( TInt j = 0; j < numTabs; j++)
+            {
+            CAknTab* thisTab = iTabArray->At( j );
+            thisTab->SetRect( emptyRect );
+            }
+
+        for ( TInt ii = 0; ii < tabsDrawn + 1; ii++ )
+            {
+            TInt tabIndex =
+                iExtension->iTabCycleAnimationDirection == ELeft ? iActiveTab - 1 + ii :
+                                                                   iActiveTab - 2 + ii;
+
+            if ( tabIndex >= numTabs ||
+                 tabIndex < 0 )
+                {
+                break;
+                }
+
+            CAknTab* thisTab = iTabArray->At( tabIndex );
+            thisTab->SetNarrowTabLayout( EFalse ); // set to normal layout mode
+            thisTab->SetTotalAmountOfTabs( iNumberOfTabsShown );
+
+            switch ( ii )
+                {
+                case 0:
+                    {
+                    if ( iExtension->iTabCycleAnimationDirection == ELeft )
+                        {
+                        TRect tabRect( iExtension->iTabSvgGraphics->TabRectFromLayout(
+                            iExtension->iNextTabBackgroundLayout.iHiddenTabLeft ) );
+                        thisTab->SetRect( tabRect );
+                        }
+                    else
+                        {
+                        TRect tabRect( iExtension->iTabSvgGraphics->TabRectFromLayout(
+                            iExtension->iNextTabBackgroundLayout.iFirstTab ) );
+                        thisTab->SetRect( tabRect );
+                        }
+                    break;
+                    }
+
+                case 1:
+                    {
+                    if ( iExtension->iTabCycleAnimationDirection == ELeft )
+                        {
+                        TRect tabRect( iExtension->iTabSvgGraphics->TabRectFromLayout(
+                            iExtension->iNextTabBackgroundLayout.iFirstTab ) );
+                        thisTab->SetRect( tabRect );
+                        }
+                    else
+                        {
+                        TRect tabRect( iExtension->iTabSvgGraphics->TabRectFromLayout(
+                            iExtension->iNextTabBackgroundLayout.iSecondTab ) );
+                        thisTab->SetRect( tabRect );
+                        }
+                    break;
+                    }
+
+                case 2:
+                    {
+                    if ( iExtension->iTabCycleAnimationDirection == ELeft )
+                        {
+                        TRect tabRect( iExtension->iTabSvgGraphics->TabRectFromLayout(
+                            iExtension->iNextTabBackgroundLayout.iSecondTab ) );
+                        thisTab->SetRect( tabRect );
+                        }
+                    else
+                        {
+                        TRect tabRect( iExtension->iTabSvgGraphics->TabRectFromLayout(
+                            iExtension->iNextTabBackgroundLayout.iThirdTab ) );
+                        thisTab->SetRect( tabRect );
+                        }
+                    break;
+                    }
+
+                case 3:
+                    {
+                    if ( iExtension->iTabCycleAnimationDirection == ELeft )
+                        {
+                        TRect tabRect( iExtension->iTabSvgGraphics->TabRectFromLayout(
+                            iExtension->iNextTabBackgroundLayout.iThirdTab ) );
+                        thisTab->SetRect( tabRect );
+                        }
+                    else
+                        {
+                        TRect tabRect( iExtension->iTabSvgGraphics->TabRectFromLayout(
+                            iExtension->iNextTabBackgroundLayout.iHiddenTabRight ) );
+                        thisTab->SetRect( tabRect );
+                        }
+                    break;
+                    }
+                }
+            }
+        }
+    else
+        {
+        for ( TInt ii=0; ii < tabsDrawn; ii++ )
+            {
+            CAknTab* thisTab = iTabArray->At( ii + iFirstShownTab );
+            thisTab->SetNarrowTabLayout( EFalse ); // set to normal layout mode
+            thisTab->SetTotalAmountOfTabs( iNumberOfTabsShown );
+
+            TAknLayoutRect tabLayoutRect;
+
+            switch ( iNumberOfTabsShown )
+                {
+                case 1:
+                    {
+                    thisTab->SetRect( tabPaneRect );
+                    break;
+                    }
+
+                case 2:
+                    {
+                    if ( iLongTabs )
+                        {
+                        tabLayoutRect.LayoutRect(
+                            tabPaneRect,
+                            AknLayoutScalable_Avkon::tabs_2_long_active_pane( ii ) );
+                        thisTab->SetRect( tabLayoutRect.Rect() );
+                        }
+                    else
+                        {
+                        tabLayoutRect.LayoutRect(
+                            tabPaneRect,
+                            AknLayoutScalable_Avkon::tabs_2_active_pane( ii ) );
+                        thisTab->SetRect( tabLayoutRect.Rect() );
+                        }
+
+                    break;
+                    }
+
+                case 3:
+                    {
+                    if ( iLongTabs )
+                        {
+                        tabLayoutRect.LayoutRect(
+                            tabPaneRect,
+                            AknLayoutScalable_Avkon::tabs_3_long_active_pane( ii ) );
+                        thisTab->SetRect( tabLayoutRect.Rect() );
+                        }
+                    else
+                        {
+                        tabLayoutRect.LayoutRect(
+                            tabPaneRect,
+                            AknLayoutScalable_Avkon::tabs_3_active_pane( ii ) );
+                        thisTab->SetRect( tabLayoutRect.Rect() );
+                        }
+
+                    break;
+                    }
+
+                case 4:
+                    {
+                    tabLayoutRect.LayoutRect(
+                        tabPaneRect,
+                        AknLayoutScalable_Avkon::tabs_4_active_pane( ii ) );
+                    thisTab->SetRect( tabLayoutRect.Rect() );
+                    break;
+                    }
+                }
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles size change events in narrow tab group layout.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::SizeChangedInNarrowLayout()
+    {
+    TRect rect( ParentRect( iExtension->iNaviArrowsUsed ) );
+
+    TRect containerNarrowRect(
+        CAknNavigationDecorator::DecoratedControlNarrowRect(
+            CAknNavigationDecorator::ETabGroup ) );
+
+    TInt tabsDrawn = iNumberOfTabsShown;
+    TInt numTabs   = TabCount();
+
+    if ( tabsDrawn > numTabs )
+        {
+        tabsDrawn = numTabs;
+        }
+
+    if ( ( iFirstShownTab + iNumberOfTabsShown ) > numTabs )
+        {
+        iFirstShownTab = 0;
+        }
+
+    // set bitmap sizes
+    TAknWindowLineLayout defaultLayout;
+    CurrentLayout( defaultLayout );
+    TAknLayoutRect r;
+    r.LayoutRect( rect, defaultLayout );
+    TRect tabPaneRect( r.Rect() );
+    TSize size( tabPaneRect.Size() );
+
+    for ( TInt i = 0; i < iNumberOfTabsShown; i++ )
+        {
+        AknIconUtils::SetSize( iTabBitmaps[i], size );
+        }
+
+    for ( TInt ii = 0; ii < tabsDrawn; ii++ )
+        {
+        CAknTab* thisTab = iTabArray->At( ii + iFirstShownTab );
+        CAknTab::TAknTabDataType type = thisTab->TabType();
+        thisTab->SetNarrowTabLayout( ETrue ); // set to narrow layout mode
+        thisTab->SetTotalAmountOfTabs( iNumberOfTabsShown );
+
+        // In flat statuspane we do things differently because the layout may vary.
+        if ( AknStatuspaneUtils::FlatLayoutActive() && NarrowTabLayout() )
+            {
+            // only active tab shows content in narrow layout
+            if ( thisTab->Active() || iNumberOfTabsShown == 1 )
+                {
+                CAknTabGroupGraphics::SAknTabLayout activeTabLayout;
+                TInt positionActive = iActiveTab - iFirstShownTab;
+
+                if ( positionActive == 0 )
+                    {
+                    activeTabLayout = iExtension->iTabBackgroundLayout.iFirstTab;
+                    }
+                else if ( positionActive == 1 )
+                    {
+                    activeTabLayout = iExtension->iTabBackgroundLayout.iSecondTab;
+                    }
+                else if ( positionActive == 2 )
+                    {
+                    activeTabLayout = iExtension->iTabBackgroundLayout.iThirdTab;
+                    }
+                else if ( positionActive == 3 )
+                    {
+                    activeTabLayout = iExtension->iTabBackgroundLayout.iFourthTab;
+                    }
+
+                TRect parentRect( activeTabLayout.iLeft );
+                parentRect.BoundingRect( activeTabLayout.iMiddle );
+                parentRect.BoundingRect( activeTabLayout.iRight );
+
+                if ( iNumberOfTabsShown == 1 )
+                    {
+                    thisTab->SetRect( containerNarrowRect );
+                    }
+                else
+                    {
+                    thisTab->SetRect( parentRect );
+                    }
+                }
+            else
+                {
+                thisTab->SetSize( TSize( 0, 0 ) );
+                }
+
+            continue;
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles size change events in flat status pane layout.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::SizeChangedInFlatLayout()
+    {
+    TRect rect( ParentRect( iExtension->iNaviArrowsUsed ) );
+
+    TRect containerNarrowRect(
+        CAknNavigationDecorator::DecoratedControlRect(
+            CAknNavigationDecorator::ETabGroup,
+            iExtension->iNaviArrowsUsed ) );
+
+    TInt tabsDrawn = iNumberOfTabsShown;
+    TInt numTabs   = TabCount();
+
+    if ( tabsDrawn > numTabs )
+        {
+        tabsDrawn = numTabs;
+        }
+
+    if ( ( iFirstShownTab + iNumberOfTabsShown ) > numTabs )
+        {
+        iFirstShownTab = 0;
+        }
+
+    // set bitmap sizes
+    TAknWindowLineLayout defaultLayout;
+    CurrentLayout( defaultLayout );
+    TAknLayoutRect r;
+    r.LayoutRect( containerNarrowRect, defaultLayout );
+    TRect tabPaneRect( r.Rect() );
+    TSize size( tabPaneRect.Size() );
+
+    for ( TInt i = 0; i < iNumberOfTabsShown; i++ )
+        {
+        AknIconUtils::SetSize( iTabBitmaps[i], size );
+        }
+
+    for ( TInt ii = 0; ii < tabsDrawn; ii++ )
+        {
+        CAknTab* thisTab = iTabArray->At( ii + iFirstShownTab );
+        CAknTab::TAknTabDataType type = thisTab->TabType();
+        thisTab->SetNarrowTabLayout( ETrue ); // set to narrow layout mode
+        thisTab->SetTotalAmountOfTabs( iNumberOfTabsShown );
+
+        if ( AknStatuspaneUtils::FlatLayoutActive() )
+            {
+            CAknTabGroupGraphics::SAknTabLayout activeTabLayout;
+            TInt positionActive = iActiveTab - iFirstShownTab;
+
+            if ( positionActive == 0 )
+                {
+                activeTabLayout = iExtension->iTabBackgroundLayout.iFirstTab;
+                }
+            else if ( positionActive == 1 )
+                {
+                activeTabLayout = iExtension->iTabBackgroundLayout.iSecondTab;
+                }
+            else if ( positionActive == 2 )
+                {
+                activeTabLayout = iExtension->iTabBackgroundLayout.iThirdTab;
+                }
+            else if ( positionActive == 3 )
+                {
+                activeTabLayout = iExtension->iTabBackgroundLayout.iFourthTab;
+                }
+
+            TRect parentRect( activeTabLayout.iLeft );
+            parentRect.BoundingRect( activeTabLayout.iMiddle );
+            parentRect.BoundingRect( activeTabLayout.iRight );
+
+            if ( iNumberOfTabsShown == 1 )
+                {
+                thisTab->SetRect( containerNarrowRect );
+                }
+            else
+                {
+                thisTab->SetRect( parentRect );
+                }
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the amount of component controls.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt CAknTabGroup::CountComponentControls() const
+    {
+    TInt count( 0 );
+
+    // Check if tabs are supposed to be visible in current layout.
+    if ( !TabsVisibleInCurrentLayout() ||
+         iActiveTab < 0 )
+        {
+        count = 0;
+        }
+    else
+        {
+        TInt numTabs = TabCount();
+        if ( iLongTabs && iActiveTab >= 0 )
+            {
+            // In long tab layout only one tab is drawn at a time.
+            count = 1;
+            }
+        else if ( numTabs < iNumberOfTabsShown ||
+                  iExtension->iTabCycleAnimationOngoing )
+            {
+            // It's required that all tabs can be drawn during
+            // the tab cycle animation, so return the
+            // entire amount of tabs.
+            count = numTabs;
+            }
+        else
+            {
+            // Else return amount of the displayed tabs.
+            count = iNumberOfTabsShown;
+            }
+        }
+
+    return count;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Gets a component control (tab control) by the control index.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CCoeControl* CAknTabGroup::ComponentControl( TInt aIndex ) const
+    {
+    CCoeControl* control = NULL;
+
+    if ( iLongTabs )
+        {
+        control = iTabArray->At( iActiveTab );
+        }
+    else
+        {
+        TInt index( aIndex );
+        if ( !iExtension->iTabCycleAnimationOngoing )
+            {
+            index += iFirstShownTab;
+            }
+        control = iTabArray->At( index );
+        }
+
+    return control;
+    }
+
+EXPORT_C void CAknTabGroup::FocusChanged( TDrawNow aDrawNow )
+    {
+    if ( iActiveTab >= 0 )
+        {
+        iTabArray->At( iActiveTab )->SetFocus( IsFocused(), aDrawNow );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Converts a mirrored tab index to it's non-mirrored index.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTabGroup::ConvertTabIndex( TInt aIndex ) const
+    {
+    if ( iMirrored && iTabObserver && aIndex >= 0 )
+        {
+        return TabCount() - 1 - aIndex;
+        }
+
+    return aIndex;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Draws the tab group background graphics.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknTabGroup::Draw( const TRect& /*aRect*/ ) const
+    {
+    TRect rect( ParentRect( iExtension->iNaviArrowsUsed ) );
+
+    // Are tabs supposed to be visible in current layout.
+    if ( !TabsVisibleInCurrentLayout() )
+        {
+        return;  // No tabs shown
+        }
+
+    if ( iActiveTab < 0 || iNumberOfTabsShown == 1 )
+        {
+        return;
+        }
+
+    TInt bitmapNo = 0;
+    TInt positionActive = iActiveTab - iFirstShownTab;
+
+    // Find out a correct background bitmap for tabs
+    if ( iNumberOfTabsShown == 2 )
+        if ( iLongTabs )
+            {
+            bitmapNo = positionActive + KTabIndexOfFirstTabBitmapInTwoLongTabsSet;
+            }
+        else
+            {
+            bitmapNo = positionActive + KTabIndexOfFirstTabBitmapInTwoTabsSet;
+            }
+    if ( iNumberOfTabsShown == 3 )
+        if ( iLongTabs )
+            {
+            bitmapNo = positionActive + KTabIndexOfFirstTabBitmapInThreeLongTabsSet;
+            }
+        else
+            {
+            bitmapNo = positionActive + KTabIndexOfFirstTabBitmapInThreeTabsSet;
+            }
+    if ( iNumberOfTabsShown == 4 )
+        {
+        bitmapNo = positionActive + KTabIndexOfFirstTabBitmapInFourTabsSet;
+        }
+
+    CWindowGc& gc = SystemGc();
+
+    if (iExtension && iExtension->iTabSvgGraphics
+            && iExtension->iTabSvgGraphics->TabGroupBackgroundAvailable())
+        {
+
+        if (iExtension->iNarrowTabLayout)
+            {
+            iExtension->iTabSvgGraphics->DrawTabGroupNarrowBackgroundL(
+                    CAknTabGroupGraphics::ENormal, iLongTabs,
+                    iNumberOfTabsShown, positionActive + 1, &gc,
+                    iExtension->iTabBackgroundLayout);
+
+            iExtension->iTabSvgGraphics->DrawTabGroupNarrowBackgroundL(
+                    CAknTabGroupGraphics::EMaskOnly, iLongTabs,
+                    iNumberOfTabsShown, positionActive + 1, &gc,
+                    iExtension->iTabBackgroundLayout);
+            }
+        else
+            {
+            CAknTabGroupGraphics::TTabAnimationType animation(
+                    CAknTabGroupGraphics::ENoAnimation);
+            TBool animationOngoing( iExtension->iTabCycleAnimationOngoing );
+            
+            if ( animationOngoing )
+                {
+                animation
+                        = iExtension->iTabCycleAnimationDirection == ELeft
+                                                                           ? CAknTabGroupGraphics::ECycleToLeft
+                                                                              : CAknTabGroupGraphics::ECycleToRight;
+                }
+            iExtension->iTabSvgGraphics->DrawTabGroupBackgroundL(
+                    CAknTabGroupGraphics::ENormal, iLongTabs,
+                    iNumberOfTabsShown, positionActive + 1, &gc,
+                    animationOngoing ? iExtension->iNextTabBackgroundLayout
+                                       : iExtension->iTabBackgroundLayout,
+                    iExtension->iTabsHidden, animation);
+
+            iExtension->iTabSvgGraphics->DrawTabGroupBackgroundL(
+                    CAknTabGroupGraphics::EMaskOnly,
+                    iLongTabs,
+                    iNumberOfTabsShown,
+                    positionActive + 1,
+                    &gc,
+                    animationOngoing ? iExtension->iNextTabBackgroundLayout
+                                       : iExtension->iTabBackgroundLayout,
+                    iExtension->iTabsHidden, animation);
+            }
+        }
+    else
+        {
+        // Old legacy draw code
+        if (iTabBitmaps[bitmapNo] && iTabMaskBitmaps[bitmapNo])
+            {
+            gc.BitBltMasked(rect.iTl, iTabBitmaps[bitmapNo], rect,
+                    iTabMaskBitmaps[bitmapNo], ETrue);
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles the pointer events that happen inside tab group control.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknTabGroup::HandlePointerEventL(
+    const TPointerEvent& aPointerEvent )
+    {
+    if ( AknLayoutUtils::PenEnabled() && iNumberOfTabsShown > 0 )
+        {
+        TInt newTab = -1;
+
+        // If the tab background graphics are not drawn, then we can't
+        // use it to calculate tab rects and use only the x-value of
+        // the pointer event position.
+        TBool tabBackgroundUsed( iTabFixedWidth != KTabWidthWithOneTab );
+
+        if ( tabBackgroundUsed )
+            {
+            CAknTabGroupGraphics::SAknTabGroupBackgroundLayout* layout =
+                &iExtension->iTabBackgroundLayout;
+
+            CAknTabGroupGraphics::SAknTabLayout* tabLayout[KMaxNumberOfVisibleTabs];
+            Mem::FillZ( tabLayout, sizeof( TUint ) * KMaxNumberOfVisibleTabs );
+
+            // Sort the layout array into right order. Tabs need to be tested
+            // according to their "z-order" so that the currently active tab
+            // is tested last.
+
+            TInt currentTab = iActiveTab - iFirstShownTab;
+
+            switch ( iNumberOfTabsShown )
+                {
+                case 1:
+                    {
+                    tabLayout[0] = &layout->iFirstTab;
+                    break;
+                    }
+
+                case 2:
+                    {
+                    if ( currentTab == 0 )
+                        {
+                        tabLayout[0] = &layout->iSecondTab;
+                        tabLayout[1] = &layout->iFirstTab;
+                        }
+                    else
+                        {
+                        tabLayout[0] = &layout->iFirstTab;
+                        tabLayout[1] = &layout->iSecondTab;
+                        }
+                    break;
+                    }
+
+                case 3:
+                    {
+                    switch ( currentTab )
+                        {
+                        case 0:
+                            tabLayout[0] = &layout->iThirdTab;
+                            tabLayout[1] = &layout->iSecondTab;
+                            tabLayout[2] = &layout->iFirstTab;
+                            break;
+
+                        case 1:
+                            tabLayout[0] = &layout->iThirdTab;
+                            tabLayout[1] = &layout->iFirstTab;
+                            tabLayout[2] = &layout->iSecondTab;
+                            break;
+
+                        default:
+                            tabLayout[0] = &layout->iFirstTab;
+                            tabLayout[1] = &layout->iSecondTab;
+                            tabLayout[2] = &layout->iThirdTab;
+                        }
+                    break;
+                    }
+
+                case 4:
+                    {
+                    if ( NarrowTabLayout() )
+                        {
+                        switch ( currentTab )
+                            {
+                            case 0:
+                                tabLayout[0] = &layout->iFourthTab;
+                                tabLayout[1] = &layout->iThirdTab;
+                                tabLayout[2] = &layout->iSecondTab;
+                                tabLayout[3] = &layout->iFirstTab;
+                                break;
+
+                            case 1:
+                                tabLayout[0] = &layout->iFourthTab;
+                                tabLayout[1] = &layout->iThirdTab;
+                                tabLayout[2] = &layout->iFirstTab;
+                                tabLayout[3] = &layout->iSecondTab;
+                                break;
+
+                            case 2:
+                                tabLayout[0] = &layout->iFourthTab;
+                                tabLayout[1] = &layout->iFirstTab;
+                                tabLayout[2] = &layout->iSecondTab;
+                                tabLayout[3] = &layout->iThirdTab;
+                                break;
+
+                            default:
+                                tabLayout[0] = &layout->iFirstTab;
+                                tabLayout[1] = &layout->iSecondTab;
+                                tabLayout[2] = &layout->iThirdTab;
+                                tabLayout[3] = &layout->iFourthTab;
+                            }
+                        }
+                    else
+                        {
+                        switch ( currentTab )
+                            {
+                            case 0:
+                                tabLayout[0] = &layout->iFourthTab;
+                                tabLayout[1] = &layout->iThirdTab;
+                                tabLayout[2] = &layout->iSecondTab;
+                                tabLayout[3] = &layout->iFirstTab;
+                                break;
+
+                            case 1:
+                                tabLayout[0] = &layout->iFourthTab;
+                                tabLayout[1] = &layout->iThirdTab;
+                                tabLayout[2] = &layout->iFirstTab;
+                                tabLayout[3] = &layout->iSecondTab;
+                                break;
+
+                            case 2:
+                                tabLayout[0] = &layout->iFourthTab;
+                                tabLayout[1] = &layout->iSecondTab;
+                                tabLayout[2] = &layout->iFirstTab;
+                                tabLayout[3] = &layout->iThirdTab;
+                                break;
+
+                            default:
+                                tabLayout[0] = &layout->iThirdTab;
+                                tabLayout[1] = &layout->iSecondTab;
+                                tabLayout[2] = &layout->iFirstTab;
+                                tabLayout[3] = &layout->iFourthTab;
+                            }
+                        }
+                    break;
+                    }
+
+                default:
+                    {
+                    User::Leave( KErrArgument );
+                    }
+                }
+
+            // Loop through the layout array & pick the last suitable tab.
+            TRect* rect;
+
+            for ( TInt tab = 0; tab < iNumberOfTabsShown; ++tab )
+                {
+                rect = &tabLayout[tab]->iLeft;
+
+                for ( TInt part = CAknTabGroupGraphics::ELeft;
+                      part <= CAknTabGroupGraphics::ERight;
+                      ++part )
+                    {
+                    if ( rect->Contains( aPointerEvent.iPosition ) )
+                        {
+                        if ( iExtension->iTabSvgGraphics->TabClickedL( 
+                                part, *rect, aPointerEvent.iPosition,
+                                tab == KMaxNumberOfVisibleTabs - 1 ) )
+                            {
+                            if ( tabLayout[tab] == &layout->iFirstTab )
+                                {
+                                newTab = iFirstShownTab;
+                                }
+                            else if ( tabLayout[tab] == &layout->iSecondTab )
+                                {
+                                newTab = iFirstShownTab + 1;
+                                }
+                            else if ( tabLayout[tab] == &layout->iThirdTab )
+                                {
+                                newTab = iFirstShownTab + 2;
+                                }
+                            else
+                                {
+                                newTab = iFirstShownTab + 3;
+                                }
+                            break;
+                            }
+                        }
+
+                    // advance pointer to the next tab component
+                    if ( part < CAknTabGroupGraphics::ERight )
+                        {
+                        rect++;
+                        }
+                    }
+                }
+            }
+
+        if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
+            {
+            if( newTab> -1 )
+                {
+                MTouchFeedback* feedback = MTouchFeedback::Instance();
+
+                // Feedback is given only if new tab wasn't already active
+                // Use two convertTabIndex to cancel the mirror effects, because the newTab is always the phsical index.
+                TBool isActiveTab = iTabArray->At( ConvertTabIndex( ConvertTabIndex( newTab ) ) )->Active();
+                TTouchFeedbackType type = static_cast<TTouchFeedbackType>(ETouchFeedbackAudio | ETouchFeedbackVibra);
+                if ( feedback && !isActiveTab )
+                    {
+                    feedback->InstantFeedback( this,
+                        ETouchFeedbackTab, 
+                        type,
+                        aPointerEvent );
+                    }
+                }
+            if ( !tabBackgroundUsed )
+                {
+                // In one tab layout handle the navigation always by
+                // pointer position.
+                newTab = iActiveTab;
+                }
+            iExtension->iPointerDownTab       = newTab;
+            iExtension->iPointerDownXPosition = aPointerEvent.iPosition.iX;
+            return;
+            }
+        else if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
+            {
+            if( newTab> -1 )
+                {
+                MTouchFeedback* feedback = MTouchFeedback::Instance();
+
+                // Feedback is given only if new tab wasn't already active
+                // Use two convertTabIndex to cancel the mirror effects, because the newTab is always the phsical index.
+                TBool isActiveTab = iTabArray->At( ConvertTabIndex( ConvertTabIndex( newTab ) ) )->Active();
+                if ( feedback && !isActiveTab )
+                    {
+                    feedback->InstantFeedback( this,
+                        ETouchFeedbackTab, 
+                        ETouchFeedbackVibra,
+                        aPointerEvent );
+                    }
+                }
+            if ( !tabBackgroundUsed )
+                {
+                // In one tab layout handle the navigation always by
+                // pointer position.
+                newTab = -1;
+                }
+
+            // if the button up event occurs ouside tabgroup, ignore it.
+            if ( !Rect().Contains( aPointerEvent.iPosition ) || iExtension->iPointerDownTab != newTab )
+                {
+                iExtension->iPointerDownTab       = -1;
+                iExtension->iPointerDownXPosition = -1;
+                return ;
+                }
+
+            if ( newTab != iActiveTab &&
+                 newTab > -1 &&
+                 newTab == iExtension->iPointerDownTab &&
+                 iNumberOfTabsShown > 1 )
+                {
+                if ( iTabObserver )
+                    {
+                    TDirection direction = newTab > iActiveTab ? ERight : ELeft;
+
+                    CancelTabAnimationEventTimer();
+
+                    StartCycleAnimationL( direction, newTab );
+
+                    SetActiveTabByIndex( ConvertTabIndex( newTab ) );
+
+                    iTabObserver->TabChangedL( ConvertTabIndex( newTab ) );
+                    }
+
+                else
+                    {
+                    // Kludge: if there is no tab observer, we need to
+                    // generate a keyevent to the application so it knows
+                    // to activate the correct view.
+                    //
+                    // The real fix would be to update applications to
+                    // implement MAknTabObserver::TabChangedL and to
+                    // activate the correct view there.
+                    TInt tabsToSkip = newTab - iActiveTab;
+                    TKeyEvent code;
+                    code.iCode = EKeyRightArrow;
+                    code.iModifiers = iEikonEnv->WsSession().GetModifierState();
+                    code.iRepeats = 0; // some applications are ignoring repeated events
+                    if ( tabsToSkip < 0 )
+                        {
+                        code.iCode = EKeyLeftArrow;
+                        tabsToSkip = -tabsToSkip;
+                        }
+
+                    for ( TInt i = 0; i < tabsToSkip; i++ )
+                        {
+                        iEikonEnv->SimulateKeyEventL( code, EEventKey );
+                        }
+                    }
+                }
+            else
+                {
+                if ( newTab != iExtension->iPointerDownTab && iExtension->iPointerDownTab > -1 )
+                    {
+                    if ( newTab == -1 )
+                        {
+                        if ( iExtension->iPointerDownXPosition + KDragNavigationTolerance <
+                                 aPointerEvent.iPosition.iX )
+                            {
+                            newTab = iExtension->iPointerDownTab + 1;
+                            }
+                        else if ( iExtension->iPointerDownXPosition - KDragNavigationTolerance >
+                                      aPointerEvent.iPosition.iX )
+                            {
+                            newTab = iExtension->iPointerDownTab - 1;
+                            }
+                        else
+                            {
+                            newTab = iExtension->iPointerDownTab;
+                            }
+                        }
+
+                    if ( iExtension->iPointerDownTab < newTab &&
+                         iActiveTab > LeftMostTabIndex() )
+                        {
+                        if ( iTabObserver )
+                            {
+                            CycleFocus( ELeft, EDrawNow );
+                            iTabObserver->TabChangedL( ConvertTabIndex( iActiveTab ) );
+                            }
+                        else
+                            {
+                            // Kludge: if there is no tab observer generate a keyevent to
+                            // instruct the application to change the view.
+                            TKeyEvent code;
+                            code.iCode = EKeyLeftArrow;
+                            iEikonEnv->SimulateKeyEventL( code, EEventKey );
+                            }
+                        }
+                    else if ( iExtension->iPointerDownTab > newTab &&
+                              iActiveTab < RightMostTabIndex() )
+                        {
+                        if ( iTabObserver )
+                            {
+                            CycleFocus( ERight, EDrawNow );
+                            iTabObserver->TabChangedL( ConvertTabIndex( iActiveTab ) );
+                            }
+                        else
+                            {
+                            // Kludge: if there is no tab observer generate a keyevent to
+                            // instruct the application to change the view.
+                            TKeyEvent code;
+                            code.iCode = EKeyRightArrow;
+                            iEikonEnv->SimulateKeyEventL( code, EEventKey );
+                            }
+                        }
+                    }
+                }
+
+            iExtension->iPointerDownTab       = -1;
+            iExtension->iPointerDownXPosition = -1;
+            }
+        }
+    }
+
+
+EXPORT_C void* CAknTabGroup::ExtensionInterface( TUid /*aInterface*/ )
+    {
+    return NULL;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknTabGroup::SetTabMultiColorMode
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknTabGroup::SetTabMultiColorMode( TInt aTabId,
+                                                  TBool aMultiColor )
+    {
+    TInt tabIndex = ConvertTabIndex( TabIndexFromId( aTabId ) );
+    if ( tabIndex >= 0 && tabIndex < TabCount() )
+        {
+        iTabArray->At( tabIndex )->SetMultiColorMode( aMultiColor );
+        }
+    }
+
+
+TBool CAknTabGroup::CycleFocus( TDirection aDirection, TDrawNow /*aDrawNow*/ )
+    {
+    if ( iActiveTab < 0 )
+        {
+        return EFalse;
+        }
+
+    if ( AknStatuspaneUtils::FlatLayoutActive() )
+        {
+        SetDecoratorLayout( EFalse );
+        }
+     else
+        {
+        CancelTabAnimationEventTimer();
+        }
+
+    TInt numTabs = TabCount();
+
+    if ( ( iActiveTab <= 0 ) && ( aDirection==ELeft ) )
+        {
+        TInt event = MAknNavigationObserver::ENaviEventAlreadyLeftmostItem;
+        TRAP_IGNORE( ReportEventL(
+                static_cast<MCoeControlObserver::TCoeEvent>( event ) ) );
+        return EFalse;
+        }
+    else if ( ( iActiveTab >= ( numTabs - 1 ) ) && ( aDirection==ERight ) )
+        {
+        TInt event = MAknNavigationObserver::ENaviEventAlreadyRightmostItem;
+        TRAP_IGNORE( ReportEventL(
+                static_cast<MCoeControlObserver::TCoeEvent>( event ) ) );
+        return EFalse;
+        }
+
+    TInt tabIndex = ( aDirection == ERight ) ? iActiveTab + 1 : iActiveTab - 1;
+
+    CAknTab* thisTab = (*iTabArray)[tabIndex];
+
+    // This starts the animation only if required.
+    TRAP_IGNORE( StartCycleAnimationL( aDirection, tabIndex ) );
+
+    (*iTabArray)[iActiveTab]->SetFocus( EFalse, ENoDrawNow );
+    thisTab->SetFocus( ETrue, ENoDrawNow );
+
+    SetActiveTabByIndex( ConvertTabIndex( tabIndex ) );
+
+    return ETrue;
+    }
+
+
+void CAknTabGroup::HandleTabStateChanged( CCoeControl* aControl )
+    {
+    const TInt numTabs = TabCount();
+
+    if ( numTabs > 1 )
+        {
+        CAknTab* newTab = static_cast<CAknTab*>( aControl );
+        CArrayPtr<CAknTab>& tabArray = *iTabArray;
+
+        TInt ii = 0;
+        for( ; ii < numTabs; ii++ )
+            {
+            if( tabArray[ii] == newTab )
+                {
+                break;
+                }
+            }
+
+        tabArray[iActiveTab]->SetFocus( EFalse, EDrawNow );
+        SetActiveTabByIndex( ConvertTabIndex( ii ) );
+        }
+    else
+        {
+        ReportNavigationEvent();
+        }
+    }
+
+
+TInt CAknTabGroup::Index( TInt aTabId ) const
+    {
+    const TInt numTabs = iTabArray->Count();
+
+    for (TInt ii = 0; ii < numTabs; ii++ )
+        {
+        CAknTab* thisTab=iTabArray->At(ii);
+        if ( thisTab->Id() == aTabId )
+            {
+            return ii;
+            }
+        }
+    return KErrNotFound;
+    }
+
+
+// --------------------------------------------------------------------------
+// Returns the index of the leftmost tab in the tab group.
+// --------------------------------------------------------------------------
+//
+TInt CAknTabGroup::LeftMostTabIndex() const
+    {
+    TInt index = 0;
+    const TInt numTabs = TabCount();
+
+    while ( iTabArray->At( index )->IsDimmed() )
+        {
+        if ( ++index >= numTabs )
+            {
+            return KErrNotFound;
+            }
+        }
+
+    return index;
+    }
+
+
+// --------------------------------------------------------------------------
+// Returns the index of the rightmost tab in the tab group.
+// --------------------------------------------------------------------------
+//
+TInt CAknTabGroup::RightMostTabIndex() const
+    {
+    TInt index = TabCount() - 1;
+
+    if ( index >= 0 )
+        {
+        while ( iTabArray->At( index )->IsDimmed() )
+            {
+            if ( --index < 0 )
+                {
+                return KErrNotFound;
+                }
+            }
+        return index;
+        }
+    else
+        {
+        return KErrNotFound;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Reports a navigation event to the navi pane decorator.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::ReportNavigationEvent()
+    {
+    TInt active   = ConvertTabIndex( ActiveTabIndex() );
+    TInt tabCount = TabCount();
+
+    TInt event = MAknNavigationObserver::ENaviEventHandleNavigation;
+
+    if ( tabCount <= 1 )
+        {
+        event = MAknNavigationObserver::ENaviEventOneItemExists;
+        }
+    else if ( active == 0 )
+        {
+        event = MAknNavigationObserver::ENaviEventLeftMostItemReached;
+        }
+    else if ( active >= ( tabCount - 1 ) )
+        {
+        event = MAknNavigationObserver::ENaviEventRightMostItemReached;
+        }
+
+    TRAP_IGNORE( ReportEventL(
+        static_cast<MCoeControlObserver::TCoeEvent>( event ) ) );
+    }
+
+
+void CAknTabGroup::LoadTabBitmapsL( TInt aNumberOfTabsShown, TBool aLongTabs )
+    {
+    TInt i = 0;
+    for ( i = 0; i < KTabNumberOfTabBitmaps; i++ )
+        {
+        delete( iTabBitmaps[i] );
+        iTabBitmaps[i] = NULL;
+        delete( iTabMaskBitmaps[i] );
+        iTabMaskBitmaps[i] = NULL;
+        }
+
+    TInt first = KErrNotFound;  // Bitmap indexes to bitmap name array
+    TInt last  = KErrNotFound;
+
+    // Figures out what tab background bitmaps are needed.
+    if ( aNumberOfTabsShown == 1 )
+        {
+        return;
+        }
+    else if ( aNumberOfTabsShown == 2 )
+        {
+        if ( aLongTabs )
+            {
+            first = KTabIndexOfFirstTabBitmapInTwoLongTabsSet;
+            last = KTabIndexOfLastTabBitmapInTwoLongTabsSet;
+            }
+        else
+            {
+            first = KTabIndexOfFirstTabBitmapInTwoTabsSet;
+            last = KTabIndexOfLastTabBitmapInTwoTabsSet;
+            }
+        }
+    else if ( aNumberOfTabsShown == 3 )
+        {
+        if ( aLongTabs )
+            {
+            first = KTabIndexOfFirstTabBitmapInThreeLongTabsSet;
+            last = KTabIndexOfLastTabBitmapInThreeLongTabsSet;
+            }
+        else
+            {
+            first = KTabIndexOfFirstTabBitmapInThreeTabsSet;
+            last = KTabIndexOfLastTabBitmapInThreeTabsSet;
+            }
+        }
+    else if ( aNumberOfTabsShown == 4 )
+        {
+        first = KTabIndexOfFirstTabBitmapInFourTabsSet;
+        last = KTabIndexOfLastTabBitmapInFourTabsSet;
+        }
+
+    if ( first < 0 )
+        {
+        return;
+        }
+
+    TRect rect( ParentRect( iExtension->iNaviArrowsUsed ) );
+
+    if ( iExtension &&
+         iExtension->iTabSvgGraphics &&
+         iExtension->iTabSvgGraphics->TabGroupBackgroundAvailable() )
+        {
+        // The background graphics are no more created in this case, instead
+        // backgrounds are drawn to a single double buffer
+        // (and other double buffer for stacon).
+        CAknTabGroupGraphics* tabgraphics = iExtension->iTabSvgGraphics;
+
+        tabgraphics->SetTabGroupBackgroundParent(
+            ParentRect( iExtension->iNaviArrowsUsed ) );
+        }
+    else
+        {
+        MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+        TAknWindowLineLayout layout;
+        CurrentLayout( layout );
+        TAknLayoutRect layoutRect;
+        layoutRect.LayoutRect( rect, layout );
+        TSize size ( layoutRect.Rect().Size() );
+
+        // This code is for legacy bitmaps, we should newer go here anymore.
+        if ( skin )
+            {
+            for ( i = first; i <= last; i++ )
+                {
+                TAknsItemID iid;
+                iid.Set( EAknsMajorAvkon, iBitmapNames[i] );
+                AknsUtils::CreateIconL( skin,
+                                        iid,
+                                        iTabBitmaps[i],
+                                        iTabMaskBitmaps[i],
+                                        KAvkonBitmapFile,
+                                        iBitmapNames[i],
+                                        iBitmapMaskNames[i] );
+
+                AknIconUtils::SetSize( iTabBitmaps[i],
+                                       size,
+                                       EAspectRatioNotPreserved );
+                }
+            }
+        else
+            {
+            TAknLayoutRect layoutRect;
+            layoutRect.LayoutRect( rect,
+                AknLayoutScalable_Avkon::navi_tabs_2_pane() );
+
+            // Loads only those tab background bitmaps that are needed.
+            for ( i = first; i <= last; i++ )
+                {
+                // Delete (in case skin loading created some bitmaps)
+                delete iTabBitmaps[i];
+                iTabBitmaps[i] = NULL;
+                delete iTabMaskBitmaps[i];
+                iTabMaskBitmaps[i] = NULL;
+
+                AknIconUtils::CreateIconL( iTabBitmaps[i],
+                                           iTabMaskBitmaps[i],
+                                           KAvkonBitmapFile,
+                                           iBitmapNames[i],
+                                           iBitmapMaskNames[i] );
+
+                // Validate all loaded bitmaps by setting their sizes.
+                AknIconUtils::SetSize( iTabBitmaps[i],
+                                       layoutRect.Rect().Size(),
+                                       EAspectRatioNotPreserved );
+                }
+            }
+        }
+
+    InitTabAnimationL();
+    }
+
+
+void CAknTabGroup::HandleResourceChange( TInt aType )
+    {
+    // First forward event to child controls,
+    // skin change must be forwarded to ALL tabs...
+    if( aType == KAknsMessageSkinChange || aType == KEikColorResourceChange )
+        {
+        TInt numTabs = TabCount();
+        for ( TInt i = 0; i < numTabs; i++ )
+            {
+            iTabArray->At(i)->HandleResourceChange( aType );
+            }
+        }
+    else
+        {
+        CCoeControl::HandleResourceChange( aType );
+        }
+
+    // ...now handle events
+    if ( aType == KAknsMessageSkinChange )
+        {
+        // If this fails, svg tab graphics are not available.
+        // Then defaults to bitmaps if possible.
+        TRAP_IGNORE( InitTabGroupGraphicsL() );
+        TRAP_IGNORE( LoadTabBitmapsL( iNumberOfTabsShown, iLongTabs ) );
+        }
+
+    if ( aType == KEikDynamicLayoutVariantSwitch )
+        {
+        // If double buffers are used in this layout,
+        // then initialize its layouts at this point.
+        if ( iExtension &&
+             iExtension->iTabSvgGraphics &&
+             iExtension->iTabSvgGraphics->TabGroupBackgroundAvailable() )
+                {
+                TRAP_IGNORE( SwitchTabLayoutL() );
+
+                iExtension->iTabSvgGraphics->SetTabGroupBackgroundParent(
+                    ParentRect( iExtension->iNaviArrowsUsed ) );
+
+                iExtension->iTabBackgroundLayout.iUse = EFalse;
+                TRAP_IGNORE( iExtension->iTabSvgGraphics->DrawTabGroupBackgroundL(
+                                CAknTabGroupGraphics::ENoDraw,
+                                iLongTabs,
+                                iNumberOfTabsShown,
+                                1,
+                                NULL,
+                                iExtension->iTabBackgroundLayout,
+                                CAknTabGroupGraphics::ENone ) );
+                iExtension->iTabBackgroundLayout.iUse = ETrue;
+                SetDecoratorLayout( EFalse );
+                }
+
+        if ( iExtension )
+            {
+            iExtension->iNarrowTabLayout = EFalse;
+            }
+
+        if ( !COMPARE_BOOLS( iMirrored, AknLayoutUtils::LayoutMirrored() ) )
+            {
+            TInt active = ActiveTabIndex();
+            TRAPD( err, ReverseTabOrderL() );
+            if ( err == KErrNone )
+                {
+                iMirrored = AknLayoutUtils::LayoutMirrored();
+                SetActiveTabByIndex( active );
+                }
+            }
+
+        SizeChanged();
+        TRAP_IGNORE( LoadTabBitmapsL( iNumberOfTabsShown, iLongTabs ) );
+        }
+    }
+
+
+TBool CAknTabGroup::TabsVisibleInCurrentLayout() const
+    {
+    TBool tabsVisible = ETrue;
+
+    // Tabs are not shown in idle layouts and in portrait flat
+    // status pane layout because there's not enough space.
+    if ( AknStatuspaneUtils::IdleLayoutActive() ||
+         ( AknStatuspaneUtils::FlatLayoutActive() &&
+           !Layout_Meta_Data::IsLandscapeOrientation() ) )
+        {
+        tabsVisible = EFalse;  // No tabs shown
+        }
+
+    return tabsVisible;
+    }
+
+
+void CAknTabGroup::CurrentLayout( TAknWindowLineLayout& aLayout ) const
+    {
+    TAknWindowLineLayout layout( AknLayoutScalable_Avkon::navi_tabs_2_pane() );
+
+    if ( iLongTabs )
+        {
+        switch ( iNumberOfTabsShown )
+            {
+            case 3:
+                {
+                layout = AknLayoutScalable_Avkon::navi_tabs_3_long_pane();
+                break;
+                }
+            default:
+                {
+                layout = AknLayoutScalable_Avkon::navi_tabs_2_long_pane();
+                break;
+                }
+            }
+        }
+    else
+        {
+        switch ( iNumberOfTabsShown )
+            {
+            case 4:
+                {
+                layout = AknLayoutScalable_Avkon::navi_tabs_4_pane();
+                break;
+                }
+            case 3:
+                {
+                layout = AknLayoutScalable_Avkon::navi_tabs_3_pane();
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+        }
+
+    aLayout = layout;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles navication decorator events scrolling tabs to left/right
+// Depending on event
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknTabGroup::HandleNaviDecoratorEventL( TInt aEventID )
+    {
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        switch ( aEventID )
+            {
+            case MAknNaviDecoratorObserver::EAknNaviDecoratorEventLeftTabArrow:
+                {
+                if ( iTabObserver )
+                    {
+                    if ( iActiveTab != LeftMostTabIndex() )
+                        {
+                        CycleFocus( ELeft, EDrawNow );
+                        }
+                    iTabObserver->TabChangedL( ConvertTabIndex( iActiveTab ) );
+                    }
+                else
+                    {
+                    // Kludge: if there is no tab observer generate a keyevent to
+                    // instruct the application to change the view.
+                    TKeyEvent code;
+                    code.iCode = EKeyLeftArrow;
+                    iEikonEnv->SimulateKeyEventL( code, EEventKey );
+                    }
+                }
+                break;
+
+            case MAknNaviDecoratorObserver::EAknNaviDecoratorEventRightTabArrow:
+                {
+                if ( iTabObserver )
+                    {
+                    if ( iActiveTab != RightMostTabIndex() )
+                        {
+                        CycleFocus( ERight, EDrawNow );
+                        }
+                    iTabObserver->TabChangedL( ConvertTabIndex( iActiveTab ) );
+                    }
+                else
+                    {
+                    // Kludge: if there is no tab observer generate a keyevent to
+                    // instruct the application to change the view.
+                    TKeyEvent code;
+                    code.iCode = EKeyRightArrow;
+                    iEikonEnv->SimulateKeyEventL( code, EEventKey );
+                    }
+                }
+                break;
+
+            default:
+                break;
+            }
+        }
+    }
+
+EXPORT_C void CAknTabGroup::Reserved1()
+    {
+    }
+
+EXPORT_C void CAknTabGroup::Reserved2()
+    {
+    }
+
+EXPORT_C void CAknTabGroup::Reserved3()
+    {
+    }
+
+void CAknTabGroup::InitTabGroupGraphicsL()
+    {
+    if ( iExtension && iExtension->iTabSvgGraphics )
+        {
+        delete iExtension->iTabSvgGraphics;
+        iExtension->iTabSvgGraphics = NULL;
+        iExtension->iTabSvgGraphics = CAknTabGroupGraphics::NewL();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Starts the animation timer.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::InitTabAnimationEventTimer()
+    {
+    TInt delay = 1;
+    iExtension->iTabAnimationTimer->Cancel();
+    iExtension->iTabAnimationTimer->Start(
+        TTimeIntervalMicroSeconds32( delay ),
+        TTimeIntervalMicroSeconds32( KAnimationEventInterval ),
+        TCallBack( CAknTabGroup::TabAnimationEvent, this ) );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Cancels the animation timer.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::CancelTabAnimationEventTimer()
+    {
+    if ( iExtension &&
+         iExtension->iTabAnimationTimer &&
+         iExtension->iTabAnimationTimer->IsActive() )
+        {
+        iExtension->iTabAnimationTimer->Cancel();
+        iExtension->iAmountOfDoneAnimationEvents = 0;
+
+        if ( iExtension->iTabAnimationType ==
+                 CAknTabGroupExtension::ETabCycleAnimation )
+            {
+            iExtension->iTabCycleAnimationOngoing = EFalse;
+
+            iExtension->iTabsHidden = CAknTabGroupGraphics::EOnBothSides;
+            if ( iFirstShownTab == 0 )
+                {
+                iExtension->iTabsHidden = CAknTabGroupGraphics::EOnRightSide;
+                }
+            else if ( iFirstShownTab == TabCount() - iNumberOfTabsShown )
+                {
+                iExtension->iTabsHidden = CAknTabGroupGraphics::EOnLeftSide;
+                }
+            }
+
+        iExtension->iTabAnimationType =
+            CAknTabGroupExtension::ENoAnimation;
+        }
+    }
+
+TInt CAknTabGroup::TabAnimationEvent( TAny* aPtr )
+    {
+    static_cast<CAknTabGroup*>( aPtr )->DoTabAnimationEvent();
+    return ETrue;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Animation timer callback.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::DoTabAnimationEvent()
+    {
+    // In this method we calculate the new positions of tabs during
+    // the animation cycle.
+
+    // We do this safety check because of possible problems with layout data.
+    iExtension->iAmountOfDoneAnimationEvents++;
+    if ( iExtension->iAmountOfDoneAnimationEvents > KMaxAmountOfAnimationEvents )
+        {
+        CancelTabAnimationEventTimer();
+        SizeChanged();
+        TRAP_IGNORE( InitTabAnimationL() );
+        DrawDeferred();
+        return;
+        }
+
+    TBool firstDone  = EFalse;
+    TBool secondDone = EFalse;
+    TBool thirdDone  = EFalse;
+    TBool fourthDone = EFalse;
+
+    if ( iExtension->iTabAnimationType ==
+             CAknTabGroupExtension::ETabCycleAnimation )
+        {
+        if ( iExtension->iAmountOfDoneAnimationEvents == 1 )
+            {
+            // Calculate the initial distance to go on the first event.
+            iExtension->iTabCycleAnimationDistanceLeft =
+                iExtension->iTabBackgroundLayout.iSecondTab.iLeft.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFirstTab.iLeft.iTl.iX;
+            }
+
+        // Calculate the step size used in this frame, currently
+        // using ease-out.
+        TInt stepSize = iExtension->iTabCycleAnimationDistanceLeft /
+                            KMinimumCycleAnimationStepSize;
+
+        // Sanity check, ensure that animation doesn't move too slow.
+        if ( stepSize < KMinimumCycleAnimationStepSize )
+            {
+            stepSize = KMinimumCycleAnimationStepSize;
+            }
+
+        if ( iExtension->iTabCycleAnimationDirection ==
+                 CAknTabGroup::ERight )
+            {
+            // Adjust the step size sign according to the direction
+            // we're moving to.
+            stepSize = -stepSize;
+            }
+
+        // Decrease the distance left by the step size.
+        iExtension->iTabCycleAnimationDistanceLeft -= Abs( stepSize );
+
+        // Move the tabs.
+        iExtension->iTabSvgGraphics->AdjustTabLayoutRect(
+            iExtension->iNextTabBackgroundLayout.iHiddenTabLeft, stepSize, 0 );
+        iExtension->iTabSvgGraphics->AdjustTabLayoutRect(
+            iExtension->iNextTabBackgroundLayout.iFirstTab, stepSize, 0 );
+        iExtension->iTabSvgGraphics->AdjustTabLayoutRect(
+            iExtension->iNextTabBackgroundLayout.iSecondTab, stepSize, 0 );
+        iExtension->iTabSvgGraphics->AdjustTabLayoutRect(
+            iExtension->iNextTabBackgroundLayout.iThirdTab, stepSize, 0 );
+        iExtension->iTabSvgGraphics->AdjustTabLayoutRect(
+            iExtension->iNextTabBackgroundLayout.iHiddenTabRight, stepSize, 0 );
+        }
+    else
+        {
+        // This seems to be quite ok speed for the animation.
+        TInt defaultStepSize = Rect().Width() / KLayoutSwitchAnimationSpeed;
+
+        // Sanity check
+        if ( defaultStepSize == 0 )
+            {
+            defaultStepSize = 1;
+            }
+
+        // First find out where we are moving, how far is the destination.
+        TInt firstTabHorizontalDistanceLeft  =
+        iExtension->iNextTabBackgroundLayout.iFirstTab.iLeft.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFirstTab.iLeft.iTl.iX;
+
+        TInt secondTabHorizontalDistanceLeft =
+        iExtension->iNextTabBackgroundLayout.iSecondTab.iLeft.iTl.iX -
+                iExtension->iTabBackgroundLayout.iSecondTab.iLeft.iTl.iX;
+
+        TInt thirdTabHorizontalDistanceLeft  =
+        iExtension->iNextTabBackgroundLayout.iThirdTab.iLeft.iTl.iX -
+                iExtension->iTabBackgroundLayout.iThirdTab.iLeft.iTl.iX;
+
+        TInt fourthTabHorizontalDistanceLeft =
+        iExtension->iNextTabBackgroundLayout.iFourthTab.iLeft.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFourthTab.iLeft.iTl.iX;
+
+        TInt firstTabHorizontalDistanceMiddle  =
+        iExtension->iNextTabBackgroundLayout.iFirstTab.iMiddle.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFirstTab.iMiddle.iTl.iX;
+
+        TInt secondTabHorizontalDistanceMiddle =
+        iExtension->iNextTabBackgroundLayout.iSecondTab.iMiddle.iTl.iX -
+                iExtension->iTabBackgroundLayout.iSecondTab.iMiddle.iTl.iX;
+
+        TInt thirdTabHorizontalDistanceMiddle  =
+        iExtension->iNextTabBackgroundLayout.iThirdTab.iMiddle.iTl.iX -
+                iExtension->iTabBackgroundLayout.iThirdTab.iMiddle.iTl.iX;
+
+        TInt fourthTabHorizontalDistanceMiddle =
+        iExtension->iNextTabBackgroundLayout.iFourthTab.iMiddle.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFourthTab.iMiddle.iTl.iX;
+
+        TInt firstTabHorizontalDistanceRight  =
+        iExtension->iNextTabBackgroundLayout.iFirstTab.iRight.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFirstTab.iRight.iTl.iX;
+
+        TInt secondTabHorizontalDistanceRight =
+        iExtension->iNextTabBackgroundLayout.iSecondTab.iRight.iTl.iX -
+                iExtension->iTabBackgroundLayout.iSecondTab.iRight.iTl.iX;
+
+        TInt thirdTabHorizontalDistanceRight  =
+        iExtension->iNextTabBackgroundLayout.iThirdTab.iRight.iTl.iX -
+                iExtension->iTabBackgroundLayout.iThirdTab.iRight.iTl.iX;
+
+        TInt fourthTabHorizontalDistanceRight =
+        iExtension->iNextTabBackgroundLayout.iFourthTab.iRight.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFourthTab.iRight.iTl.iX;
+
+        TInt usedStepSizeForFirstTabLeft  = defaultStepSize;
+        TInt usedStepSizeForSecondTabLeft = defaultStepSize;
+        TInt usedStepSizeForThirdTabLeft  = defaultStepSize;
+        TInt usedStepSizeForFourthTabLeft = defaultStepSize;
+
+        TInt usedStepSizeForFirstTabMiddle  = defaultStepSize;
+        TInt usedStepSizeForSecondTabMiddle = defaultStepSize;
+        TInt usedStepSizeForThirdTabMiddle  = defaultStepSize;
+        TInt usedStepSizeForFourthTabMiddle = defaultStepSize;
+
+        TInt usedStepSizeForFirstTabRight  = defaultStepSize;
+        TInt usedStepSizeForSecondTabRight = defaultStepSize;
+        TInt usedStepSizeForThirdTabRight  = defaultStepSize;
+        TInt usedStepSizeForFourthTabRight = defaultStepSize;
+
+
+        // If we are close to end, then adjust the step size. Also if we are moving to normal layout
+        // from narrow, do it with one big step.
+        if ( Abs( firstTabHorizontalDistanceLeft ) < Abs( usedStepSizeForFirstTabLeft ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForFirstTabLeft = Abs( firstTabHorizontalDistanceLeft );
+            }
+        if ( Abs( firstTabHorizontalDistanceMiddle ) < Abs( usedStepSizeForFirstTabMiddle ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForFirstTabMiddle = Abs( firstTabHorizontalDistanceMiddle );
+            }
+        if ( Abs( firstTabHorizontalDistanceRight ) < Abs( usedStepSizeForFirstTabRight ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForFirstTabRight = Abs( firstTabHorizontalDistanceRight );
+            }
+
+        if ( Abs( secondTabHorizontalDistanceLeft ) < Abs( usedStepSizeForSecondTabLeft ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForSecondTabLeft = Abs( secondTabHorizontalDistanceLeft );
+            }
+        if ( Abs( secondTabHorizontalDistanceMiddle ) < Abs( usedStepSizeForSecondTabMiddle ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForSecondTabMiddle = Abs( secondTabHorizontalDistanceMiddle );
+            }
+        if ( Abs( secondTabHorizontalDistanceRight ) < Abs( usedStepSizeForSecondTabRight ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForSecondTabRight = Abs( secondTabHorizontalDistanceRight );
+            }
+
+        if ( Abs( thirdTabHorizontalDistanceLeft ) < Abs( usedStepSizeForThirdTabLeft ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForThirdTabLeft = Abs(thirdTabHorizontalDistanceLeft);
+            }
+        if ( Abs( thirdTabHorizontalDistanceMiddle ) < Abs( usedStepSizeForThirdTabMiddle ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForThirdTabMiddle = Abs(thirdTabHorizontalDistanceMiddle);
+            }
+        if ( Abs( thirdTabHorizontalDistanceRight ) < Abs( usedStepSizeForThirdTabRight) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForThirdTabRight = Abs(thirdTabHorizontalDistanceRight);
+            }
+
+        if ( Abs( fourthTabHorizontalDistanceLeft ) < Abs( usedStepSizeForFourthTabLeft ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForFourthTabLeft = Abs(fourthTabHorizontalDistanceLeft);
+            }
+        if ( Abs( fourthTabHorizontalDistanceMiddle ) < Abs( usedStepSizeForFourthTabMiddle ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForFourthTabMiddle = Abs(fourthTabHorizontalDistanceMiddle);
+            }
+        if ( Abs( fourthTabHorizontalDistanceRight ) < Abs( usedStepSizeForFourthTabRight ) ||
+             !NarrowTabLayoutNext() )
+            {
+            usedStepSizeForFourthTabRight = Abs(fourthTabHorizontalDistanceRight);
+            }
+
+
+        // First tab
+        if ( firstTabHorizontalDistanceLeft < 0 )
+            {
+            usedStepSizeForFirstTabLeft = -usedStepSizeForFirstTabLeft;
+            }
+
+        if ( firstTabHorizontalDistanceMiddle < 0 )
+            {
+            usedStepSizeForFirstTabMiddle = -usedStepSizeForFirstTabMiddle;
+            }
+
+        if ( firstTabHorizontalDistanceRight < 0 )
+            {
+            usedStepSizeForFirstTabRight = -usedStepSizeForFirstTabRight;
+            }
+
+    iExtension->iTabBackgroundLayout.iFirstTab.iLeft.Move( usedStepSizeForFirstTabLeft, 0 );
+    iExtension->iTabBackgroundLayout.iFirstTab.iRight.Move( usedStepSizeForFirstTabRight, 0 );
+
+    iExtension->iTabBackgroundLayout.iFirstTab.iMiddle.iTl.iX =
+        iExtension->iTabBackgroundLayout.iFirstTab.iLeft.iBr.iX;
+
+    iExtension->iTabBackgroundLayout.iFirstTab.iMiddle.iBr.iX =
+        iExtension->iTabBackgroundLayout.iFirstTab.iRight.iTl.iX;
+
+        if ( ( iExtension->iNextTabBackgroundLayout.iFirstTab.iLeft.iTl.iX -
+                   iExtension->iTabBackgroundLayout.iFirstTab.iLeft.iTl.iX == 0 ) &&
+             ( iExtension->iNextTabBackgroundLayout.iFirstTab.iMiddle.iTl.iX -
+                   iExtension->iTabBackgroundLayout.iFirstTab.iMiddle.iTl.iX == 0 ) &&
+             ( iExtension->iNextTabBackgroundLayout.iFirstTab.iRight.iTl.iX -
+                   iExtension->iTabBackgroundLayout.iFirstTab.iRight.iTl.iX == 0 ) )
+            {
+            firstDone = ETrue;
+            }
+
+        // Second tab
+        if ( secondTabHorizontalDistanceLeft < 0 )
+            {
+            usedStepSizeForSecondTabLeft = -usedStepSizeForSecondTabLeft;
+            }
+        if ( secondTabHorizontalDistanceMiddle < 0 )
+            {
+            usedStepSizeForSecondTabMiddle = -usedStepSizeForSecondTabMiddle;
+            }
+        if ( secondTabHorizontalDistanceRight < 0 )
+            {
+            usedStepSizeForSecondTabRight = -usedStepSizeForSecondTabRight;
+            }
+
+    iExtension->iTabBackgroundLayout.iSecondTab.iLeft.Move(usedStepSizeForSecondTabLeft,0);
+    iExtension->iTabBackgroundLayout.iSecondTab.iRight.Move(usedStepSizeForSecondTabRight,0);
+
+    iExtension->iTabBackgroundLayout.iSecondTab.iMiddle.iTl.iX =
+        iExtension->iTabBackgroundLayout.iSecondTab.iLeft.iBr.iX;
+
+    iExtension->iTabBackgroundLayout.iSecondTab.iMiddle.iBr.iX =
+        iExtension->iTabBackgroundLayout.iSecondTab.iRight.iTl.iX;
+
+        if ( ( iExtension->iNextTabBackgroundLayout.iSecondTab.iLeft.iTl.iX -
+                   iExtension->iTabBackgroundLayout.iSecondTab.iLeft.iTl.iX == 0 ) &&
+             ( iExtension->iNextTabBackgroundLayout.iSecondTab.iMiddle.iTl.iX -
+                   iExtension->iTabBackgroundLayout.iSecondTab.iMiddle.iTl.iX == 0 ) &&
+             ( iExtension->iNextTabBackgroundLayout.iSecondTab.iRight.iTl.iX -
+                   iExtension->iTabBackgroundLayout.iSecondTab.iRight.iTl.iX == 0 ) )
+            {
+            secondDone = ETrue;
+            }
+
+        // Third tab
+        if ( thirdTabHorizontalDistanceLeft < 0 )
+            {
+            usedStepSizeForThirdTabLeft = -usedStepSizeForThirdTabLeft;
+            }
+        if ( thirdTabHorizontalDistanceMiddle < 0 )
+            {
+            usedStepSizeForThirdTabMiddle = -usedStepSizeForThirdTabMiddle;
+            }
+        if ( thirdTabHorizontalDistanceRight < 0 )
+            {
+            usedStepSizeForThirdTabRight = -usedStepSizeForThirdTabRight;
+            }
+
+    iExtension->iTabBackgroundLayout.iThirdTab.iLeft.Move(usedStepSizeForThirdTabLeft,0);
+    iExtension->iTabBackgroundLayout.iThirdTab.iRight.Move(usedStepSizeForThirdTabRight,0);
+
+    iExtension->iTabBackgroundLayout.iThirdTab.iMiddle.iTl.iX =
+        iExtension->iTabBackgroundLayout.iThirdTab.iLeft.iBr.iX;
+
+    iExtension->iTabBackgroundLayout.iThirdTab.iMiddle.iBr.iX =
+        iExtension->iTabBackgroundLayout.iThirdTab.iRight.iTl.iX;
+
+        if ( ( iExtension->iNextTabBackgroundLayout.iThirdTab.iLeft.iTl.iX -
+                   iExtension->iTabBackgroundLayout.iThirdTab.iLeft.iTl.iX == 0 ) &&
+             ( iExtension->iNextTabBackgroundLayout.iThirdTab.iMiddle.iTl.iX -
+                   iExtension->iTabBackgroundLayout.iThirdTab.iMiddle.iTl.iX == 0 ) &&
+             ( iExtension->iNextTabBackgroundLayout.iThirdTab.iRight.iTl.iX -
+                   iExtension->iTabBackgroundLayout.iThirdTab.iRight.iTl.iX == 0 ) )
+            {
+            thirdDone = ETrue;
+            }
+
+        // Fourth tab
+        if ( fourthTabHorizontalDistanceLeft < 0 )
+            {
+            usedStepSizeForFourthTabLeft = -usedStepSizeForFourthTabLeft;
+            }
+        if ( fourthTabHorizontalDistanceMiddle < 0 )
+            {
+            usedStepSizeForFourthTabMiddle = -usedStepSizeForFourthTabMiddle;
+            }
+        if ( fourthTabHorizontalDistanceRight < 0 )
+            {
+            usedStepSizeForFourthTabRight = -usedStepSizeForFourthTabRight;
+            }
+
+    iExtension->iTabBackgroundLayout.iFourthTab.iLeft.Move(
+        usedStepSizeForFourthTabLeft, 0 );
+    iExtension->iTabBackgroundLayout.iFourthTab.iRight.Move(
+        usedStepSizeForFourthTabRight, 0 );
+    iExtension->iTabBackgroundLayout.iFourthTab.iMiddle.iTl.iX =
+        iExtension->iTabBackgroundLayout.iFourthTab.iLeft.iBr.iX;
+    iExtension->iTabBackgroundLayout.iFourthTab.iMiddle.iBr.iX =
+        iExtension->iTabBackgroundLayout.iFourthTab.iRight.iTl.iX;
+
+        if ( ( iExtension->iNextTabBackgroundLayout.iFourthTab.iLeft.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFourthTab.iLeft.iTl.iX == 0 ) &&
+             ( iExtension->iNextTabBackgroundLayout.iFourthTab.iMiddle.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFourthTab.iMiddle.iTl.iX == 0 ) &&
+             ( iExtension->iNextTabBackgroundLayout.iFourthTab.iRight.iTl.iX -
+                iExtension->iTabBackgroundLayout.iFourthTab.iRight.iTl.iX == 0 ) )
+            {
+            fourthDone = ETrue;
+            }
+        }
+
+   // Then lets adjust the tab content to right places.
+   if ( NarrowTabLayoutNext() )
+       {
+       TBool refreshTabs = iExtension->iNarrowTabLayout;
+       iExtension->iNarrowTabLayout = ETrue;
+       if ( refreshTabs )
+           {
+           SizeChanged();
+           }
+       }
+   else
+       {
+       TBool refreshTabs = !iExtension->iNarrowTabLayout;
+       iExtension->iNarrowTabLayout = EFalse;
+       if ( refreshTabs )
+           {
+           SizeChanged();
+           }
+       }
+
+    // Check if we are done with the animation
+    if ( firstDone && secondDone && thirdDone && fourthDone ||
+         ( iExtension->iTabAnimationType == CAknTabGroupExtension::ETabCycleAnimation &&
+           iExtension->iTabCycleAnimationDistanceLeft <= 0 ) )
+        {
+        CancelTabAnimationEventTimer(); // done
+        SizeChanged();
+        }
+
+    // Finally draw the tabs to their new places. Note that drawing must draw
+    // tabs little differently in this animated case. See Draw() method.
+    TRAP_IGNORE( InitTabAnimationL() );
+        
+    DrawDeferred();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets the narrow/normal layout state of the tab group.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::SetNarrowTabLayoutL( TBool aNarrow, TBool aUseAnimation )
+    {
+    if ( iExtension->iTabCycleAnimationOngoing )
+        {
+        // Narrow tab layout is not currently supported in touch layouts
+        // and this may should not be called during tab cycle animation.
+        return;
+        }
+
+    if ( !aUseAnimation )
+        {
+        // Switch the layout directly without using the animation.
+        iExtension->iNarrowTabLayout = aNarrow;
+        iExtension->iTabAnimationType =
+            CAknTabGroupExtension::ENoAnimation;
+        }
+    else
+        {
+        iExtension->iTabAnimationType =
+            CAknTabGroupExtension::ELayoutSwitchAnimation;
+        }
+
+    iExtension->iNarrowTabLayoutNext = aNarrow;
+
+    iExtension->iTabSvgGraphics->SetTabGroupBackgroundParent(
+        ParentRect( iExtension->iNaviArrowsUsed ) );
+
+    // Calculate new destination positions for animated tabs.
+    TInt positionActive = iActiveTab - iFirstShownTab;
+    if ( aNarrow )
+        {
+        iExtension->iNextTabBackgroundLayout.iUse = EFalse;
+        iExtension->iTabSvgGraphics->DrawTabGroupNarrowBackgroundL(
+            CAknTabGroupGraphics::ENoDraw,
+            iLongTabs,
+            iNumberOfTabsShown,
+            positionActive + 1,
+            NULL,
+            iExtension->iNextTabBackgroundLayout );
+        iExtension->iNextTabBackgroundLayout.iUse = ETrue;
+
+        if ( !aUseAnimation )
+            {
+            iExtension->iTabBackgroundLayout.iUse = EFalse;
+            iExtension->iTabSvgGraphics->DrawTabGroupNarrowBackgroundL(
+                CAknTabGroupGraphics::ENoDraw,
+                iLongTabs,
+                iNumberOfTabsShown,
+                positionActive + 1,
+                NULL,
+                iExtension->iTabBackgroundLayout );
+            iExtension->iTabBackgroundLayout.iUse = ETrue;
+            }
+        }
+    else
+        {
+        iExtension->iNextTabBackgroundLayout.iUse = EFalse;
+        iExtension->iTabSvgGraphics->DrawTabGroupBackgroundL(
+            CAknTabGroupGraphics::ENoDraw,
+            iLongTabs,
+            iNumberOfTabsShown,
+            positionActive + 1,
+            NULL,
+            iExtension->iNextTabBackgroundLayout,
+            CAknTabGroupGraphics::ENone );
+        iExtension->iNextTabBackgroundLayout.iUse = ETrue;
+
+        iExtension->iTabBackgroundLayout.iUse = EFalse;
+        iExtension->iTabSvgGraphics->DrawTabGroupBackgroundL(
+            CAknTabGroupGraphics::ENoDraw,
+            iLongTabs,
+            iNumberOfTabsShown,
+            positionActive + 1,
+            NULL,
+            iExtension->iTabBackgroundLayout,
+            CAknTabGroupGraphics::ENone );
+        iExtension->iTabBackgroundLayout.iUse = ETrue;
+        }
+
+    InitTabAnimationL();
+
+    if ( AknStatuspaneUtils::FlatLayoutActive() )
+        {
+        InitTabAnimationEventTimer();
+        }
+    else
+        {
+        CancelTabAnimationEventTimer();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets the tab group internal state of the navi arrow visibility.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::SetNaviArrowsVisible( TBool aVisible )
+    {
+    if ( iExtension )
+        {
+        iExtension->iNaviArrowsUsed = aVisible;
+        }
+    }
+
+
+TBool CAknTabGroup::NarrowTabLayoutNext()
+    {
+    return iExtension && iExtension->iNarrowTabLayoutNext;
+    }
+
+TBool CAknTabGroup::NarrowTabLayout()
+    {
+    return iExtension && iExtension->iNarrowTabLayout;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets the layout of the navi decorator to match the current
+// tab group layout.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::SetDecoratorLayout( TBool aNarrow )
+    {
+    CEikStatusPaneBase* statusPane           = CEikStatusPaneBase::Current();
+    CAknNavigationControlContainer* naviPane = NULL;
+    CAknNavigationDecorator* decorator       = NULL;
+
+    if ( statusPane )
+        {
+        CCoeControl* control = NULL;
+        TRAPD( err, control = statusPane->ControlL(
+            TUid::Uid( EEikStatusPaneUidNavi ) ) );
+
+        if ( !err && control )
+            {
+            // Control cannot be casted directly because someone may have
+            // swapped the control. Use this workaround instead.
+            control->MopGetObject( naviPane );
+            if ( naviPane )
+                {
+                decorator = naviPane->Top();
+                if ( decorator && decorator->DecoratedControl() != this )
+                    {
+                    decorator = NULL;
+                    }
+                }
+            }
+        }
+
+    // Check first that application has not forced any layout mode.
+    if ( aNarrow )
+        {
+        if ( decorator &&
+             decorator->NaviControlLayoutMode() ==
+                CAknNavigationDecorator::ENaviControlLayoutModeAutomatic )
+           {
+           decorator->SetNaviControlLayoutStyle(
+               CAknNavigationDecorator::ENaviControlLayoutNarrow );
+           }
+        }
+    else
+        {
+        if ( decorator &&
+             decorator->NaviControlLayoutMode() ==
+                CAknNavigationDecorator::ENaviControlLayoutModeAutomatic )
+           {
+           decorator->SetNaviControlLayoutStyle(
+            CAknNavigationDecorator::ENaviControlLayoutNormal );
+           }
+        }
+
+    // Only use tab arrows in non-touch layouts and in the one tab layout.
+    TBool naviArrowsShouldBeVisible( iTabFixedWidth == KTabWidthWithOneTab ||
+                                     !AknLayoutUtils::PenEnabled() );
+    if ( decorator &&
+         !COMPARE_BOOLS( decorator->ScrollButtonVisible(), naviArrowsShouldBeVisible ) )
+        {
+        decorator->MakeScrollButtonVisible( naviArrowsShouldBeVisible );
+        }
+    else
+        {
+        if ( iExtension )
+            {
+            // Ensure that the value here is correct if navi decorator
+            // already has it correct.
+            iExtension->iNaviArrowsUsed = naviArrowsShouldBeVisible;
+            }
+        }
+
+    // After this method call decorator will set this class size right by
+    // calling us back at CAknTabGroup::SetNarrowTabLayoutL().
+    // If decorator does not exist we call ourself SetNarrowTabLayout.
+    if ( !decorator )
+        {
+        TRAP_IGNORE( SetNarrowTabLayoutL( aNarrow ) );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Creates if necessary and draws the tab group background double buffer.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::InitTabAnimationL()
+    {
+    TRect rect( ParentRect( iExtension->iNaviArrowsUsed ) );
+
+    TSize size( rect.iBr.iX, rect.iBr.iY );
+
+    if ( size.iHeight <= 0 || size.iWidth <= 0 )
+        {
+        size = rect.Size();
+        }
+
+    TInt positionActive = iActiveTab - iFirstShownTab;
+
+    TBool penEnabled( AknLayoutUtils::PenEnabled() );
+
+    if ( penEnabled && iTabFixedWidth == KTabWidthWithThreeTabs )
+        {
+        // It's ensured here that the focused tab background graphic is drawn
+        // behind the middle tab in touch layouts when using three tab
+        // layout, if the currently active tab is not the leftmost or
+        // rightmost tab.
+        if ( iActiveTab != RightMostTabIndex() &&
+             iActiveTab != LeftMostTabIndex() )
+            {
+            positionActive = 1;
+            }
+        }
+
+    if ( !iExtension->iNarrowTabLayout )
+        {
+        TInt tabCount = TabCount();
+        iExtension->iTabsHidden = CAknTabGroupGraphics::ENone;
+        TBool animationOngoing( iExtension->iTabCycleAnimationOngoing );
+        TBool firstAnimationUpdate( animationOngoing
+                && iExtension->iAmountOfDoneAnimationEvents == 0 );
+
+                if ( tabCount > iNumberOfTabsShown && penEnabled )
+                    {
+                    iExtension->iTabsHidden = CAknTabGroupGraphics::ETwoOnBothSides;
+                    if ( animationOngoing &&
+                         ( ( iFirstShownTab == 0 &&
+                             iExtension->iTabCycleAnimationDirection == ELeft ) ||
+                           ( iFirstShownTab == tabCount - ( iNumberOfTabsShown ) &&
+                             iExtension->iTabCycleAnimationDirection == ERight ) ) )
+                        {
+                        iExtension->iTabsHidden = CAknTabGroupGraphics::EOnBothSides;
+                        }
+                    else if ( iActiveTab < iNumberOfTabsShown &&
+                         ( ( iFirstShownTab == 0 &&
+                             !animationOngoing ) ||
+                           firstAnimationUpdate &&
+                           iExtension->iTabCycleAnimationDirection == ERight ) )
+                        {
+                        iExtension->iTabsHidden = CAknTabGroupGraphics::EOnRightSide;
+                        }
+                    else if ( iActiveTab >= tabCount - ( iNumberOfTabsShown ) &&
+                              ( ( !animationOngoing &&
+                                  iFirstShownTab == tabCount - ( iNumberOfTabsShown ) ) ||
+                                firstAnimationUpdate &&
+                                iExtension->iTabCycleAnimationDirection == ELeft ) )
+                        {
+                        iExtension->iTabsHidden = CAknTabGroupGraphics::EOnLeftSide;
+                        }
+                    }
+
+        if (firstAnimationUpdate)
+            {
+            iExtension->iNextTabBackgroundLayout.iUse = EFalse;
+            }
+        else
+            {
+            iExtension->iNextTabBackgroundLayout.iUse = ETrue;
+            }
+
+        }
+
+    iExtension->iTabAnimationDoubleBufferNarrowTabLayout
+            = iExtension->iNarrowTabLayout;
+    iExtension->iTabAnimationDoubleBufferNumberOfTabsShown
+            = iNumberOfTabsShown;
+    iExtension->iTabAnimationDoubleBufferpositionActive = positionActive;
+    iExtension->iTabAnimationDoubleBufferLongTabs = iLongTabs;
+
+    iExtension->iTabBackgroundLayout.iUse = ETrue;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Gets the tab group's parent rectangle.
+// ---------------------------------------------------------------------------
+//
+TRect CAknTabGroup::ParentRect( TBool aArrowsUsed )
+    {
+    TBool scaled( ETrue );
+
+    if ( !AknLayoutUtils::PenEnabled() )
+        {
+        CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
+
+        if ( statusPane )
+            {
+            // In portrait mode the tab group needs to be adjacent
+            // the bottom of the navi pane.
+            TInt layoutResId = statusPane->CurrentLayoutResId();
+            if ( layoutResId == R_AVKON_STATUS_PANE_LAYOUT_USUAL_EXT ||
+                 layoutResId == R_AVKON_STATUS_PANE_LAYOUT_EMPTY )
+                {
+                scaled = EFalse;
+                }
+            }
+        }
+
+    TRect parentRect(
+        CAknNavigationDecorator::DecoratedTabControlRect( scaled,
+                                                          aArrowsUsed ) );
+
+    return parentRect;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Starts the tab group cycle animation.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::StartCycleAnimationL( TDirection aDirection,
+                                         TInt aNewTab )
+    {
+    TInt tabCount( TabCount() );
+
+    // First check if the animation should be used.
+    // The cycle animation is currently used only in following situation:
+    //  1) The three tab layout is active.
+    //  2) Touch layout is used.
+    //  3) Cycling the focus changes the first shown tab of the tab group.
+    //
+    if ( iTabFixedWidth == KTabWidthWithThreeTabs &&          // 1
+         AknLayoutUtils::PenEnabled() &&                      // 2
+         tabCount > iNumberOfTabsShown &&
+         ( ( iActiveTab > 0 && iActiveTab < tabCount - 2 &&   // 3
+             aDirection == ERight ) ||
+           ( iActiveTab > 1 && iActiveTab < tabCount - 1 &&   // 3
+             aDirection == ELeft ) ||
+           ( iActiveTab == 0 &&                               // 3
+             aNewTab == ( iNumberOfTabsShown - 1 ) ) ||
+           ( iActiveTab == tabCount - 1 &&                    // 3
+             aNewTab == tabCount - iNumberOfTabsShown ) ) )
+        {
+        iExtension->iTabAnimationType =
+            CAknTabGroupExtension::ETabCycleAnimation;
+
+        iExtension->iTabCycleAnimationOngoing = ETrue;
+        iExtension->iTabCycleAnimationDirection = aDirection;
+
+        iExtension->iTabSvgGraphics->SetTabGroupBackgroundParent(
+            ParentRect( iExtension->iNaviArrowsUsed ) );
+
+        iExtension->iNextTabBackgroundLayout.iUse = EFalse;
+
+        InitTabAnimationEventTimer();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Switches the current tab layout to one that is usable in the current
+// layout.
+// ---------------------------------------------------------------------------
+//
+void CAknTabGroup::SwitchTabLayoutL()
+    {
+    TBool penEnabled( AknLayoutUtils::PenEnabled() );
+
+    if ( penEnabled && ( iTabFixedWidth == KTabWidthWithTwoLongTabs ||
+                         iTabFixedWidth == KTabWidthWithThreeLongTabs ||
+                         iTabFixedWidth == KTabWidthWithFourTabs ) )
+        {
+        // If the current tab width is not supported in touch
+        // layout then switch it to a corresponding one.
+        SetTabFixedWidthL( iTabFixedWidth );
+        }
+    else if ( iExtension && iTabFixedWidth != iExtension->iRequestedTabWidth )
+        {
+        // Else try to set the requested width if it's supported in
+        // the new layout.
+        SetTabFixedWidthL( iExtension->iRequestedTabWidth );
+        }
+    else
+        {
+        // Nothing to do.
+        return;
+        }
+
+    // Set the correct focus if tab width is changed in layout
+    // switch.
+    if ( iActiveTab >= 0 )
+        {
+        if ( penEnabled && iTabFixedWidth == KTabWidthWithThreeTabs )
+            {
+            if ( iActiveTab != RightMostTabIndex() &&
+                    iActiveTab != LeftMostTabIndex() )
+                {
+                iFirstShownTab = iActiveTab - 1;
+                }
+            else if ( iActiveTab < iFirstShownTab )
+                {
+                iFirstShownTab = iActiveTab;
+                }
+            else if ( iActiveTab >= ( iFirstShownTab + iNumberOfTabsShown ) )
+                {
+                iFirstShownTab = iActiveTab - iNumberOfTabsShown + 1;
+                }
+            }
+        else
+            {
+            if ( iActiveTab < iFirstShownTab )
+                {
+                iFirstShownTab = iActiveTab;
+                }
+
+            if ( iActiveTab >= ( iFirstShownTab + iNumberOfTabsShown ) )
+                {
+                iFirstShownTab = iActiveTab - iNumberOfTabsShown + 1;
+                }
+            }
+        SizeChanged();
+        }
+
+    CancelTabAnimationEventTimer();
+    }
+
+ //  End of File