uifw/AvKon/src/AknTitlePaneLabel.cpp
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/AknTitlePaneLabel.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1467 @@
+/*
+* Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Implementation of title pane's label.
+*
+*/
+
+
+// SYSTEM INCLUDES
+#include <e32def.h>
+#include <AknPictographInterface.h>
+#include <AknPictographDrawerInterface.h>
+#include <bidivisual.h>
+#include <biditext.h>
+#include <akniconconfig.h>
+#include <layoutmetadata.cdl.h>
+
+#include <AknTasHook.h> // for testability hooks
+// USER INCLUDES
+#include "AknTitlePaneLabel.h"
+#include "AknUtils.h"
+#include "AknLayoutFont.h"
+#include "aknappui.h"
+#include "AknBidiTextUtils.h"
+#include "AknStatuspaneUtils.h"
+
+// General effects-related constants
+const TInt KScrollTimerInterval                     = 50000; // 20 events/s
+const TInt KScrollTimerDelay                        = KScrollTimerInterval;
+const TInt KScrollTimerDelayBeforeDirectionReversal = 3000000; // 3s
+const TInt KStartValue                              = 0;
+const TInt KEndValue                                = 255;
+const TInt KMinInterval                             = 50000;
+const TInt KScaleMagicNumber                        = 208;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+CAknTitlePaneLabel::CAknTitlePaneLabel()
+    {
+    AKNTASHOOK_ADD( this, "CAknTitlePaneLabel" );
+    }
+
+
+CAknTitlePaneLabel::~CAknTitlePaneLabel()
+    {
+    AKNTASHOOK_REMOVE();
+    delete iMask;
+    delete iMaskDevice;
+    delete iMaskGc;
+
+    delete iBitmap;
+    delete iBitmapDevice;
+    delete iBitmapGc;
+
+    if ( iEffectTimer )
+        {
+        iEffectTimer->Cancel();
+        delete iEffectTimer;
+        ControlEnv()->RemoveForegroundObserver( *this );
+        }
+    delete iEffectQueue;
+    delete iScrollingText;
+    }
+
+
+void CAknTitlePaneLabel::Draw( const TRect& aRect ) const
+    {
+    if ( iEffect == EEffectNone )
+        {
+        CEikLabel::Draw( aRect );
+        }
+
+    // Text is paused before starting to scroll,
+    // drawn without truncation character.
+    else if ( iEffect == EEffectPause && iPreviousEffect == EEffectNone )
+        {
+        // const_cast is required to call the DrawWithoutTruncation() function.
+        TRAPD( err,
+               const_cast<CAknTitlePaneLabel*>( this )->DrawWithoutTruncationL( aRect ) );
+
+        if ( err != KErrNone )
+            {
+            CEikLabel::Draw( aRect );
+            }
+        }
+    else
+        {
+        DrawWithEffect( aRect );
+        }
+    }
+
+
+void CAknTitlePaneLabel::DrawWithoutTruncationL( const TRect& aRect )
+    {
+    // Copy of the truncated text in CEikLabel is made first.
+    HBufC* truncatedText = HBufC::NewL( Text()->Length() );
+    CleanupStack::PushL( truncatedText );
+
+    TPtr ptr( truncatedText->Des() );
+    ptr.Copy( *Text() );
+
+    // CEikLabel's text is set to the full text and is drawn.
+    SetTextL( *iScrollingText );
+    CEikLabel::Draw( aRect );
+
+    // CEikLabel's text is set back to the truncated form.
+    SetTextL( ptr );
+
+    CleanupStack::PopAndDestroy( truncatedText );
+    }
+
+
+void CAknTitlePaneLabel::DrawWithEffect( const TRect& aRect ) const
+    {
+    if ( iEffect && iBitmap && iMask && iBitmapGc && iMaskGc )
+        {
+        // Bitblit using mask, this creates the fade effect
+        CWindowGc& gc = SystemGc();
+        gc.BitBltMasked(
+            iTextLayout.TextRect().iTl,
+            iBitmap,
+            iTextLayout.TextRect(),
+            iMask,
+            ETrue );
+        }
+    else
+        {
+        CEikLabel::Draw( aRect );
+        }
+    }
+
+
+void CAknTitlePaneLabel::DrawTextWithEffect() const
+    {
+    switch ( iEffect )
+        {
+        case EEffectFadeToLeft:
+        case EEffectFadeToRight:
+            {
+            DrawTextWithFadeEffect();
+            break;
+            }
+        case EEffectDefaultScroll:
+            {
+            DrawTextWithScrollEffect();
+            break;
+            }
+        case EEffectDefaultScrollWithFade:
+        case EEffectLoopScrollWithFade:
+        case EEffectScrollOnceWithFade:
+        case EEffectFadeOut:
+        case EEffectFadeIn:
+        case EEffectToggleScrolledTextTruncation:
+            {
+            DrawTextWithScrollAndFadeEffect();
+            break;
+            }
+        case EEffectPause:
+        case EEffectNone:
+        default:
+            {
+            break;
+            }
+        }
+
+    if ( DrawableWindow() )
+        {
+        DrawDeferred();
+        }
+
+    if ( iObserver && iObserver->DrawableWindow() )
+        {
+        iObserver->DrawDeferred();
+        }
+    }
+
+
+void CAknTitlePaneLabel::DrawTextWithFadeEffect() const
+    {
+    if ( iEffect &&
+         iBitmap &&
+         iMask &&
+         iBitmapGc &&
+         iMaskGc &&
+         iTitleText &&
+         iScrollingText )
+        {
+        InitBitmaps();
+        iMaskGc->SetPenStyle( CGraphicsContext::ESolidPen );
+        iMaskGc->SetBrushStyle( CGraphicsContext::ENullBrush );
+        iBitmapGc->SetPenStyle( CGraphicsContext::ESolidPen );
+        iBitmapGc->SetBrushStyle( CGraphicsContext::ENullBrush );
+
+        if ( IsStrikethrough() )
+            {
+            iMaskGc->SetStrikethroughStyle( EStrikethroughOn );
+            iBitmapGc->SetStrikethroughStyle( EStrikethroughOn );
+            }
+        else
+            {
+            iMaskGc->SetStrikethroughStyle( EStrikethroughOff );
+            iBitmapGc->SetStrikethroughStyle( EStrikethroughOff );
+            }
+
+        if ( IsUnderlined() )
+            {
+            iMaskGc->SetUnderlineStyle( EUnderlineOn );
+            iBitmapGc->SetUnderlineStyle( EUnderlineOn );
+            }
+        else
+            {
+            iMaskGc->SetUnderlineStyle( EUnderlineOff );
+            iBitmapGc->SetUnderlineStyle( EUnderlineOff );
+            }
+
+        const CFont* fontUsed =
+            AknLayoutUtils::FontFromId( iTextLayoutLine.FontId() );
+        iBitmapGc->UseFont( fontUsed );
+
+        // First draw with white color for masking purpose
+        const CAknLayoutFont* layoutFont =
+            CAknLayoutFont::AsCAknLayoutFontOrNull( fontUsed );
+        TInt textPaneAscent( 0 );
+        if ( layoutFont )
+            {
+            textPaneAscent = layoutFont->TextPaneTopToBaseline();
+            }
+        else
+            {
+            textPaneAscent = fontUsed->AscentInPixels();
+            }
+
+        CGraphicsContext::TTextAlign textAlign( CGraphicsContext::ELeft );
+        if( AknLayoutUtils::LayoutMirrored() )
+            {
+            textAlign = CGraphicsContext::ERight;
+            }
+
+        iBitmapGc->SetPenColor( KRgbWhite );
+        iBitmapGc->DrawText( *iScrollingText,
+                             iTextLayout.TextRect(),
+                             textPaneAscent,
+                             textAlign,
+                             0 );
+
+        // Draw pictographs
+        if ( iPictographInterface )
+            {
+            iPictographInterface->Interface()->DrawPictographsInText(
+                *iBitmapGc,
+                *fontUsed,
+                *iScrollingText,
+                iTextLayout.TextRect(),
+                textPaneAscent,
+                textAlign,
+                0 );
+            }
+
+        // Draw text to mask
+        iMaskGc->BitBltMasked(
+            Rect().iTl,
+            iBitmap,
+            TRect( iBitmap->SizeInPixels() ),
+            iBitmap,
+            ETrue );
+
+        TRgb color( KRgbBlack );
+        if ( IsDimmed() )
+            {
+            color = iEikonEnv->ControlColor( EColorLabelDimmedText, *this );
+            }
+        else
+            {
+            color = iEikonEnv->ControlColor( EColorLabelText, *this );
+            }
+
+        iBitmapGc->SetPenColor( color );
+        iBitmapGc->DrawText( *iScrollingText,
+                             iTextLayout.TextRect(),
+                             textPaneAscent,
+                             textAlign,
+                             0 );
+
+        // Draw pictographs
+        if ( iPictographInterface )
+            {
+            iPictographInterface->Interface()->DrawPictographsInText(
+                *iBitmapGc,
+                *fontUsed,
+                *iScrollingText,
+                iTextLayout.TextRect(),
+                textPaneAscent,
+                textAlign,
+                0 );
+            }
+
+        iBitmapGc->DiscardFont(); // Release the font cache
+        }
+    }
+
+void CAknTitlePaneLabel::DrawTextWithScrollEffect() const
+    {
+    if ( iEffect &&
+         iBitmap &&
+         iMask &&
+         iBitmapGc &&
+         iMaskGc &&
+         iTitleText &&
+         iScrollingText )
+        {
+        InitBitmaps();
+        iMaskGc->SetPenStyle( CGraphicsContext::ESolidPen );
+        iMaskGc->SetBrushStyle( CGraphicsContext::ENullBrush );
+        iBitmapGc->SetPenStyle( CGraphicsContext::ESolidPen );
+        iBitmapGc->SetBrushStyle( CGraphicsContext::ENullBrush );
+
+        TRect rect( iScrollRect );
+
+        TRgb color( KRgbBlack );
+        if ( IsDimmed() )
+            {
+            color = iEikonEnv->ControlColor( EColorLabelDimmedText, *this );
+            }
+        else
+            {
+            color = iEikonEnv->ControlColor( EColorLabelText, *this );
+            }
+
+        const CFont* fontUsed =
+            AknLayoutUtils::FontFromId( iTextLayoutLine.FontId() );
+        const CAknLayoutFont* layoutFont =
+            CAknLayoutFont::AsCAknLayoutFontOrNull( fontUsed );
+        TInt textPaneAscent( 0 );
+        if ( layoutFont )
+            {
+            textPaneAscent = layoutFont->TextPaneTopToBaseline();
+            }
+        else
+            {
+            textPaneAscent = fontUsed->AscentInPixels();
+            }
+
+        CGraphicsContext::TTextAlign textAlign( CGraphicsContext::ELeft );
+
+        if ( iWesternText )
+            {
+            rect.iTl.iX -= iScrollPosition;
+            }
+        else
+            {
+            rect.iBr.iX += iScrollPosition;
+            textAlign = CGraphicsContext::ERight;
+            }
+
+        iBitmapGc->SetPenColor( KRgbWhite );
+        iBitmapGc->UseFont( fontUsed );
+
+        TBool truncated = Text()->Locate( KEllipsis ) != KErrNotFound;
+        if ( !iScrollPosition && truncated )
+            {
+            // Draw truncated text
+            iBitmapGc->DrawText( *Text(), rect, textPaneAscent, textAlign, 0 );
+            // Draw pictographs
+            if ( iPictographInterface )
+                {
+                iPictographInterface->Interface()->DrawPictographsInText(
+                    *iBitmapGc,
+                    *fontUsed,
+                    *Text(),
+                    rect,
+                    textPaneAscent,
+                    textAlign,
+                    0 );
+                }
+            }
+        else if ( iScrollingText )
+            {
+            // Draw non-truncated text
+            iBitmapGc->DrawText( *iScrollingText,
+                                 rect,
+                                 textPaneAscent,
+                                 textAlign,
+                                 0 );
+            // Draw pictographs
+            if ( iPictographInterface )
+                {
+                iPictographInterface->Interface()->DrawPictographsInText(
+                    *iBitmapGc,
+                    *fontUsed,
+                    *iScrollingText,
+                    rect,
+                    textPaneAscent,
+                    textAlign,
+                    0 );
+                }
+            }
+
+        // Draw text to mask
+        iMaskGc->BitBltMasked(
+            Rect().iTl,
+            iBitmap,
+            TRect( iBitmap->SizeInPixels() ),
+            iBitmap,
+            ETrue );
+
+        iBitmapGc->SetPenColor( color );
+
+        if ( !iScrollPosition && truncated )
+            {
+            // Draw truncated text
+            iBitmapGc->DrawText( *Text(), rect, textPaneAscent, textAlign, 0 );
+            // Draw pictographs
+            if ( iPictographInterface )
+                {
+                iPictographInterface->Interface()->DrawPictographsInText(
+                    *iBitmapGc,
+                    *fontUsed,
+                    *Text(),
+                    rect,
+                    textPaneAscent,
+                    textAlign,
+                    0 );
+                }
+            }
+        else if ( iScrollingText )
+            {
+            // Draw non-truncated text
+            iBitmapGc->DrawText( *iScrollingText,
+                                 rect,
+                                 textPaneAscent,
+                                 textAlign,
+                                 0 );
+            // Draw pictographs
+            if ( iPictographInterface )
+                {
+                iPictographInterface->Interface()->DrawPictographsInText(
+                    *iBitmapGc,
+                    *fontUsed,
+                    *iScrollingText,
+                    rect,
+                    textPaneAscent,
+                    textAlign,
+                    0 );
+                }
+            }
+
+        iBitmapGc->DiscardFont(); // Release the font cache
+        }
+    }
+
+
+void CAknTitlePaneLabel::DrawTextWithScrollAndFadeEffect() const
+    {
+    DrawTextWithScrollEffect();
+    }
+
+
+void CAknTitlePaneLabel::SetTextEffect( TInt aEffect,
+                                        TRect aEffectRect,
+                                        TInt aEffectDuration,
+                                        TRect aLabelRect,
+                                        TAknLayoutText aTextLayout,
+                                        TAknTextLineLayout aTextLayoutLine,
+                                        HBufC* aTitleText,
+                                        CCoeControl* aObserver)
+    {
+    iPreviousEffect = iEffect;
+
+    iObserver = aObserver;
+    iTextLayout = aTextLayout;
+    iTextLayoutLine = aTextLayoutLine;
+
+    if ( ( iTitleText != aTitleText && iScrollingText ) ||
+         ( !iScrollingText && aEffect ) )
+        {
+        TRAP_IGNORE( CreateScrollingTextL( aTitleText ) );
+        }
+
+    iTitleText = aTitleText;
+    iEffectDuration = aEffectDuration;
+
+    iWesternText =
+        TBidiText::TextDirectionality( *Text() ) == TBidiText::ELeftToRight;
+
+    if ( aEffect == EEffectScrollOnceWithFade ||
+         aEffect == EEffectLoopScrollWithFade ||
+         aEffect == EEffectLoopScroll ||
+         aEffect == EEffectDefaultScrollWithFade ||
+         aEffect == EEffectDefaultScroll )
+        {
+        iScrollPosition = 0;
+        }
+
+    iScrollRect = iTextLayout.TextRect();
+    if ( iScrollRect.iTl.iX < aEffectRect.iTl.iX )
+        {
+        iScrollRect.iTl.iX = aEffectRect.iTl.iX;
+        }
+    if ( iScrollRect.iBr.iX > aEffectRect.iBr.iX )
+        {
+        iScrollRect.iBr.iX = aEffectRect.iBr.iX;
+        }
+
+    const CFont* fontUsed =
+        AknLayoutUtils::FontFromId( aTextLayoutLine.FontId() );
+    CFont::TMeasureTextInput input;
+    input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
+    iTextLength = fontUsed->MeasureText( *aTitleText, &input );
+
+    iOperatorNamePhase = 0;
+
+    if ( !aEffect ||
+         iEffect != aEffect ||
+         iEffectRect != aEffectRect ||
+         Rect() != aLabelRect )
+        {
+        iEffect = aEffect;
+        iEffectRect = aEffectRect;
+        if ( !iEffect )
+            {
+            TRgb color( iEikonEnv->ControlColor( EColorLabelText, *this ) );
+            // We cast here a bit dangerously, this might be changed someday.
+            TAknMultiLineTextLayout* multilinePtr = NULL;
+            multilinePtr =
+                static_cast<TAknMultiLineTextLayout*> ( &aTextLayoutLine );
+            AknLayoutUtils::LayoutLabel(this, aLabelRect, *multilinePtr);
+            // Layoutlabel loses the color, set it back to right one
+            TRAP_IGNORE(
+                AknLayoutUtils::OverrideControlColorL(
+                    *this, EColorLabelText, color ) );
+            }
+        else
+            {
+            if ( aEffect != EEffectPause )
+                {
+                SetRect( aLabelRect );
+                }
+            }
+
+        iEffectLabelSize = Size();
+
+        TInt error = KErrNone;
+        TRAP( error, InitEffectL() );
+        if ( error != KErrNone )
+            {
+            iEffect = EEffectNone;
+            }
+        }
+
+    // Do effect event at least once
+    DoEffectEvent();
+
+    // Setup timer for furter effect events if needed
+    if ( iEffect != EEffectPause )
+        {
+        TRAP_IGNORE( InitTimerL( KScrollTimerDelay, KScrollTimerInterval ) );
+        }
+    }
+
+
+TInt CAknTitlePaneLabel::TextEffect()
+    {
+    return iEffect;
+    }
+
+
+void CAknTitlePaneLabel::InitEffectL()
+    {
+    if ( EffectBitmapsNeeded( iEffect ) )
+        {
+        delete iMask;
+        iMask = NULL;
+        delete iMaskDevice;
+        iMaskDevice = NULL;
+        delete iMaskGc;
+        iMaskGc = NULL;
+
+        delete iBitmap;
+        iBitmap = NULL;
+        delete iBitmapDevice;
+        iBitmapDevice = NULL;
+        delete iBitmapGc;
+        iBitmapGc = NULL;
+
+        iMask = new (ELeave) CFbsBitmap();
+        iMask->Create( Size(), EGray256 );
+        iMaskDevice = CFbsBitmapDevice::NewL( iMask );
+        iMaskDevice->CreateContext( iMaskGc );
+
+        AknIconConfig::TPreferredDisplayMode mode;
+        AknIconConfig::PreferredDisplayMode(
+            mode,
+            AknIconConfig::EImageTypeOffscreen );
+
+        iBitmap = new (ELeave) CFbsBitmap();
+        iBitmap->Create( Size(), mode.iBitmapMode );
+        iBitmapDevice = CFbsBitmapDevice::NewL( iBitmap );
+        iBitmapDevice->CreateContext( iBitmapGc );
+
+        InitBitmaps();
+        }
+    }
+
+
+void CAknTitlePaneLabel::InitTimerL( TInt aDelay, TInt aInterval )
+    {
+    CancelTimer();
+
+    if ( EffectEventsNeeded( iEffect ) )
+        {
+        if ( !iEffectTimer )
+            {
+            iEffectTimer = CPeriodic::NewL( CActive::EPriorityIdle );
+            ControlEnv()->AddForegroundObserverL( *this );
+            }
+
+        if ( !iEffectTimer->IsActive() )  // start timer if not already started
+            {
+            iEffectTimer->Start(
+                TTimeIntervalMicroSeconds32( aDelay ),
+                TTimeIntervalMicroSeconds32( aInterval ),
+                TCallBack( CAknTitlePaneLabel::EffectEvent, this ) );
+            }
+        }
+    else
+        {
+        iScrollPosition = 0;
+        }
+    }
+
+
+void CAknTitlePaneLabel::CancelTimer()
+    {
+    if ( iEffectTimer && iEffectTimer->IsActive() )
+        {
+        iEffectTimer->Cancel();
+        }
+    }
+
+
+void CAknTitlePaneLabel::InitBitmaps() const
+    {
+    iBitmapGc->SetPenColor( KRgbBlack );
+    iBitmapGc->SetPenStyle( CGraphicsContext::ENullPen );
+    iBitmapGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+    iBitmapGc->SetBrushColor( KRgbBlack );
+    iBitmapGc->DrawRect( TRect( Size() ) );
+
+    iMaskGc->SetPenColor( KRgbBlack );
+    iMaskGc->SetPenStyle( CGraphicsContext::ENullPen );
+    iMaskGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+    iMaskGc->SetBrushColor( KRgbWhite );
+    iMaskGc->DrawRect( TRect( Size() ) );
+
+    iMaskGc->SetPenStyle( CGraphicsContext::ESolidPen );
+    iMaskGc->SetBrushStyle( CGraphicsContext::ENullBrush );
+
+    TInt width = iEffectRect.Width();
+
+    TRect parentRect( Rect() );
+
+    TBool isLandscape( Layout_Meta_Data::IsLandscapeOrientation() );
+    TBool flatSp( AknStatuspaneUtils::FlatLayoutActive() );
+
+    switch ( iEffect )
+        {
+        case EEffectFadeToLeft:
+            {
+            TInt KMaxFadeSteps = KEndValue - KStartValue;
+            TInt usedFadeStep = 0;
+            TInt usedDrawStep = 1;
+
+            if ( width < KMaxFadeSteps &&
+                 width != 0)
+                {
+                usedFadeStep = KMaxFadeSteps / width;
+                }
+            else
+                {
+                usedFadeStep = 1;
+                usedDrawStep = width / KMaxFadeSteps;
+                }
+
+            TInt startValue( KStartValue );
+
+            // In portrait mode flat status pane layout
+            // we fade the text fully, because the navi
+            // pane content and title pane can't be displayed
+            // at the same time.
+
+            TRgb rgb;
+            rgb.SetRed( startValue );
+            rgb.SetGreen( startValue );
+            rgb.SetBlue( startValue );
+
+            TRect rect;
+            for ( TInt x = 0; x < width; x += usedDrawStep )
+                {
+                iMaskGc->SetPenColor( rgb );
+                iMaskGc->SetBrushColor( rgb );
+                rect.iTl.iX = iEffectRect.iTl.iX + x;
+                rect.iTl.iY = 0;
+                rect.iBr.iX = rect.iTl.iX + usedDrawStep;
+                rect.iBr.iY = rect.iTl.iY + parentRect.Height();
+
+                iMaskGc->DrawRect( rect );
+                rgb.SetRed( rgb.Red() + usedFadeStep );
+                rgb.SetGreen( rgb.Green() + usedFadeStep );
+                rgb.SetBlue( rgb.Blue() + usedFadeStep );
+                }
+
+            iMaskGc->SetPenStyle( CGraphicsContext::ENullPen );
+            iMaskGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+            iMaskGc->SetPenColor( KRgbBlack );
+            iMaskGc->SetBrushColor( KRgbBlack );
+            iMaskGc->DrawRect( TRect( parentRect.iTl.iX,
+                                      parentRect.iTl.iY,
+                                      iEffectRect.iTl.iX,
+                                      parentRect.iBr.iY ) );
+            break;
+            }
+        case EEffectFadeToRight:
+            {
+            TInt KMaxFadeSteps = KEndValue - KStartValue;
+            TInt usedFadeStep = 0;
+            TInt usedDrawStep = 1;
+
+
+            if ( width < KMaxFadeSteps &&
+                 width != 0 )
+                {
+                usedFadeStep = KMaxFadeSteps / width;
+                }
+            else
+                {
+                usedFadeStep = 1;
+                usedDrawStep = width / KMaxFadeSteps;
+                }
+
+            TInt startValue( KStartValue );
+
+            // In portrait mode flat status pane layout
+            // we fade the text fully, because the navi
+            // pane content and title pane can't be displayed
+            // at the same time.
+
+            TRgb rgb;
+            rgb.SetRed( startValue );
+            rgb.SetGreen( startValue );
+            rgb.SetBlue( startValue );
+
+            TRect rect;
+            for ( TInt x = width - 1; x >= 0; x -= usedDrawStep )
+                {
+                iMaskGc->SetPenColor( rgb );
+                iMaskGc->SetBrushColor( rgb );
+                rect.iTl.iX = iEffectRect.iTl.iX + x;
+                rect.iTl.iY = 0;
+                rect.iBr.iX = rect.iTl.iX + usedDrawStep;
+                rect.iBr.iY = rect.iTl.iY + parentRect.Height();
+                iMaskGc->DrawRect( rect );
+                rgb.SetRed( rgb.Red() + usedFadeStep );
+                rgb.SetGreen( rgb.Green() + usedFadeStep );
+                rgb.SetBlue( rgb.Blue() + usedFadeStep );
+                }
+
+            iMaskGc->SetPenStyle( CGraphicsContext::ENullPen );
+            iMaskGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+            iMaskGc->SetPenColor( KRgbBlack );
+            iMaskGc->SetBrushColor( KRgbBlack );
+            iMaskGc->DrawRect( TRect( iEffectRect.iBr.iX,
+                                      parentRect.iTl.iY,
+                                      parentRect.iBr.iX,
+                                      parentRect.iBr.iY ) );
+            break;
+            }
+        case EEffectDefaultScrollWithFade:
+        case EEffectLoopScrollWithFade:
+        case EEffectScrollOnceWithFade:
+            {
+            if ( !TextNeedsTruncation() || iScrollPosition == 0 )
+                {
+                return; // No need to fade if not even scrolled.
+                }
+
+            // We fade about 5-10% of the text area end/start to make
+            // scrolling text appear/disappear smoother.
+            width = iEffectRect.Width() / 30;
+            TRect leftFadeEffectRect( iEffectRect );
+            leftFadeEffectRect.iBr.iX = leftFadeEffectRect.iTl.iX + width;
+
+            TRect rightFadeEffectRect = iEffectRect;
+            rightFadeEffectRect.iTl.iX = rightFadeEffectRect.iBr.iX - width;
+
+            TInt KMaxFadeSteps = KEndValue - KStartValue;
+            TInt usedFadeStep  = 0;
+            TInt usedDrawStep  = 1;
+
+            if ( width < KMaxFadeSteps &&
+                 width != 0 )
+                {
+                usedFadeStep = KMaxFadeSteps / width;
+                }
+            else
+                {
+                usedFadeStep = 1;
+                usedDrawStep = width / KMaxFadeSteps;
+                }
+
+            TRgb rgb;
+            rgb.SetRed( KStartValue );
+            rgb.SetGreen( KStartValue );
+            rgb.SetBlue( KStartValue );
+
+            TRect rect;
+            for ( TInt x = 0; x < width; x += usedDrawStep )
+                {
+                iMaskGc->SetPenColor( rgb );
+                iMaskGc->SetBrushColor( rgb );
+                rect.iTl.iX = leftFadeEffectRect.iTl.iX + x;
+                rect.iTl.iY = 0;
+                rect.iBr.iX = rect.iTl.iX + usedDrawStep;
+                rect.iBr.iY = rect.iTl.iY + parentRect.Height();
+
+                iMaskGc->DrawRect( rect );
+                rgb.SetRed( rgb.Red() + usedFadeStep );
+                rgb.SetGreen( rgb.Green() + usedFadeStep );
+                rgb.SetBlue( rgb.Blue() + usedFadeStep );
+                }
+
+            iMaskGc->SetPenStyle( CGraphicsContext::ENullPen );
+            iMaskGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+            iMaskGc->SetPenColor( KRgbBlack );
+            iMaskGc->SetBrushColor( KRgbBlack );
+            iMaskGc->DrawRect( TRect( parentRect.iTl.iX,
+                                      parentRect.iTl.iY,
+                                      leftFadeEffectRect.iTl.iX,
+                                      parentRect.iBr.iY ) );
+
+
+            iMaskGc->SetPenStyle( CGraphicsContext::ESolidPen );
+            iMaskGc->SetBrushStyle( CGraphicsContext::ENullBrush );
+
+            KMaxFadeSteps = KEndValue - KStartValue;
+            usedFadeStep  = 0;
+            usedDrawStep  = 1;
+
+            if ( width < KMaxFadeSteps &&
+                 width != 0 )
+                {
+                usedFadeStep = KMaxFadeSteps / width;
+                }
+            else
+                {
+                usedFadeStep = 1;
+                usedDrawStep = width / KMaxFadeSteps;
+                }
+
+            rgb.SetRed( KStartValue );
+            rgb.SetGreen( KStartValue );
+            rgb.SetBlue( KStartValue );
+
+            for ( TInt x = width - 1; x >= 0; x -= usedDrawStep )
+                {
+                iMaskGc->SetPenColor( rgb );
+                iMaskGc->SetBrushColor( rgb );
+                rect.iTl.iX = rightFadeEffectRect.iTl.iX + x;
+                rect.iTl.iY = 0;
+                rect.iBr.iX = rect.iTl.iX + usedDrawStep;
+                rect.iBr.iY = rect.iTl.iY + parentRect.Height();
+
+                iMaskGc->DrawRect( rect );
+                rgb.SetRed( rgb.Red() + usedFadeStep );
+                rgb.SetGreen( rgb.Green() + usedFadeStep );
+                rgb.SetBlue( rgb.Blue() + usedFadeStep );
+                }
+
+            iMaskGc->SetPenStyle( CGraphicsContext::ENullPen );
+            iMaskGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+            iMaskGc->SetBrushColor( KRgbBlack );
+            iMaskGc->DrawRect( TRect( rightFadeEffectRect.iBr.iX,
+                                      parentRect.iTl.iY,
+                                      parentRect.iBr.iX,
+                                      parentRect.iBr.iY ) );
+            break;
+            }
+        case EEffectFadeOut:
+        case EEffectFadeIn:
+            {
+            TRgb fadeRgb;
+            fadeRgb.SetRed( iFadeInOutValue );
+            fadeRgb.SetGreen( iFadeInOutValue );
+            fadeRgb.SetBlue( iFadeInOutValue );
+            iMaskGc->SetPenStyle( CGraphicsContext::ENullPen );
+            iMaskGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+            iMaskGc->SetPenColor( fadeRgb );
+            iMaskGc->SetBrushColor( fadeRgb );
+            iMaskGc->DrawRect( iEffectRect );
+
+            iMaskGc->SetPenStyle( CGraphicsContext::ENullPen );
+            iMaskGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+            iMaskGc->SetPenColor( KRgbBlack );
+            iMaskGc->SetBrushColor( KRgbBlack );
+            iMaskGc->DrawRect( TRect( parentRect.iTl.iX,
+                                      parentRect.iTl.iY,
+                                      iEffectRect.iTl.iX,
+                                      parentRect.iBr.iY ) );
+            break;
+            }
+        case EEffectPause:
+        case EEffectNone:
+        case EEffectToggleScrolledTextTruncation:
+        case EEffectDefaultScroll:
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+
+CFbsBitmap* CAknTitlePaneLabel::TextAsBitmap()
+    {
+    if ( iEffect != EEffectNone )
+        {
+        return iBitmap;
+        }
+    else
+        {
+        return NULL;
+        }
+    }
+
+
+CFbsBitmap* CAknTitlePaneLabel::TextAsMask()
+    {
+    if ( iEffect != EEffectNone )
+        {
+        return iMask;
+        }
+    else
+        {
+        return NULL;
+        }
+    }
+
+
+void CAknTitlePaneLabel::HandleGainingForeground()
+    {
+    TRAP_IGNORE( InitTimerL( KScrollTimerDelay, KScrollTimerInterval ) );
+    }
+
+void CAknTitlePaneLabel::HandleLosingForeground()
+    {
+    CancelTimer();
+    }
+
+
+TInt CAknTitlePaneLabel::EffectEvent( TAny* aPtr )
+    {
+    static_cast<CAknTitlePaneLabel*> ( aPtr )->DoEffectEvent();
+    return ETrue;
+    }
+
+
+TBool CAknTitlePaneLabel::DoDefaultScrollEffectEvent()
+    {
+    TBool done( EFalse );
+    if ( !TextNeedsTruncation() )
+        {
+        iScrollStep = 0;
+        done        = ETrue;
+        }
+
+    if ( iScrollDirectionBackwards )
+        {
+        iScrollStep = -ScrollStepInPixels();
+        if ( iScrollPosition == 0 )
+            {
+            // If text is at the other end, switch
+            // scrolling direction and continue.
+            iScrollDirectionBackwards = EFalse;
+            TRAP_IGNORE(
+                InitTimerL(
+                    KScrollTimerDelayBeforeDirectionReversal,
+                    KScrollTimerInterval ) ); // Make a littler longer delay at the ends
+            }
+        }
+    else
+        {
+        iScrollStep = ScrollStepInPixels();
+        if ( iScrollPosition + iScrollRect.Width() > iTextLength + iScrollRect.Width() / 10 )
+            {
+            // If text is at the other end, switch scrolling direction and continue
+            iScrollDirectionBackwards = ETrue;
+            TRAP_IGNORE(
+                InitTimerL(
+                    KScrollTimerDelayBeforeDirectionReversal,
+                    KScrollTimerInterval ) ); // Make a littler longer delay at the ends
+            }
+        }
+    iScrollPosition += iScrollStep;
+    return done;
+    }
+
+
+TBool CAknTitlePaneLabel::DoLoopScrollEffectEvent()
+    {
+    TBool done( EFalse );
+    if ( !TextNeedsTruncation() )
+        {
+        iScrollStep = 0;
+        done        = ETrue;
+        }
+
+    iScrollStep = ScrollStepInPixels();
+    if ( iScrollPosition > iTextLength + iScrollRect.Width() / 10 )
+        {
+        // If text has scrolled away from screen, start again from the other end
+        iScrollPosition = -iScrollRect.Width();
+        }
+    iScrollPosition += iScrollStep;
+    return done;
+    }
+
+
+TBool CAknTitlePaneLabel::DoScrollOnceEffectEvent()
+    {
+    TBool done( EFalse );
+    if ( !TextNeedsTruncation() )
+        {
+        iScrollStep = 0;
+        done        = ETrue;
+        }
+    else
+        {
+        iScrollStep = ScrollStepInPixels();
+        if ( iScrollPosition + iScrollRect.Width() > iTextLength + iScrollRect.Width() / 10 )
+            {
+            // If text is at the other end, continue with fade after timout
+            iScrollStep = 0;
+            done        = ETrue;
+            }
+        }
+    iScrollPosition += iScrollStep;
+    return done;
+    }
+
+
+TBool CAknTitlePaneLabel::DoFadeInEffectEvent()
+    {
+    TBool done( EFalse );
+    if ( iEffectDuration )
+        {
+        TInt interval = iEffectDuration / KEndValue;
+
+        if ( interval < KMinInterval )
+            {
+            interval = KMinInterval;
+            iFadeInOutStep = iEffectDuration / KMinInterval;
+            }
+        else
+            {
+            iFadeInOutStep = 1;
+            }
+
+        if ( iFadeInOutStep < 1 )
+            {
+            iFadeInOutStep = 1;
+            }
+        if ( iFadeInOutStep > KEndValue )
+            {
+            iFadeInOutStep = KEndValue;
+            }
+
+        TRAP_IGNORE( InitTimerL( interval, interval ) );
+
+        iEffectDuration = 0;
+        iFadeInOutValue = 0; // start from fully invisible
+        }
+
+    if ( iFadeInOutValue + iFadeInOutStep > KEndValue )
+        {
+        iFadeInOutValue = KEndValue;
+        done = ETrue;
+        }
+    else
+        {
+        iFadeInOutValue += iFadeInOutStep;
+        }
+
+    return done;
+    }
+
+TBool CAknTitlePaneLabel::DoFadeOutEffectEvent()
+    {
+    TBool done( EFalse );
+    if ( iEffectDuration )
+        {
+        TInt interval = iEffectDuration / KEndValue;
+
+        if ( interval < KMinInterval )
+            {
+            interval = KMinInterval;
+            iFadeInOutStep = iEffectDuration / KMinInterval;
+            }
+        else
+            {
+            iFadeInOutStep = 1;
+            }
+
+        if ( iFadeInOutStep < 1 )
+            {
+            iFadeInOutStep = 1;
+            }
+        if ( iFadeInOutStep > KEndValue )
+            {
+            iFadeInOutStep = KEndValue;
+            }
+
+        TRAP_IGNORE( InitTimerL( interval, interval ) );
+
+        iEffectDuration = 0;
+        iFadeInOutValue = KEndValue; // start from fully visible
+        }
+
+    if ( iFadeInOutValue - iFadeInOutStep < 0 )
+        {
+        iFadeInOutValue = 0;
+        done = ETrue;
+        }
+    else
+        {
+        iFadeInOutValue -= iFadeInOutStep;
+        }
+
+    return done;
+    }
+
+
+TBool CAknTitlePaneLabel::DoPauseEffectEvent()
+    {
+    TBool done( EFalse );
+    if ( iEffectDuration )
+        {
+        TRAP_IGNORE( InitTimerL( iEffectDuration, iEffectDuration ) );
+        iEffectDuration = 0;
+        }
+    else
+        {
+        done = ETrue;
+        }
+    return done;
+    }
+
+
+TBool CAknTitlePaneLabel::DoToggleScrolledTextTruncationEffectEvent()
+    {
+    iScrollPosition = 0;
+    return ETrue;
+    }
+
+
+void CAknTitlePaneLabel::DoEffectEvent()
+    {
+    TBool done( EFalse );
+
+    switch ( iEffect )
+        {
+        case EEffectDefaultScroll:
+        case EEffectDefaultScrollWithFade:
+            done = DoDefaultScrollEffectEvent();
+            break;
+        case EEffectLoopScroll:
+        case EEffectLoopScrollWithFade:
+            done = DoLoopScrollEffectEvent();
+            break;
+        case EEffectFadeIn:
+            done = DoFadeInEffectEvent();
+            break;
+        case EEffectFadeOut:
+            done = DoFadeOutEffectEvent();
+            break;
+        case EEffectPause:
+            done = DoPauseEffectEvent();
+            break;
+        case EEffectScrollOnceWithFade:
+            done = DoScrollOnceEffectEvent();
+            break;
+        case EEffectToggleScrolledTextTruncation:
+            done = DoToggleScrolledTextTruncationEffectEvent();
+            break;
+        default:
+            iScrollStep = 0;
+            done = ETrue;
+            break;
+        }
+
+    // Draw text
+    DrawTextWithEffect();
+
+    // If done then process next effect
+    if ( done )
+        {
+        NextEffect();
+        }
+    }
+
+TBool CAknTitlePaneLabel::TextNeedsTruncation() const
+    {
+    if ( iTextLength > iScrollRect.Width() )
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+
+TBool CAknTitlePaneLabel::EffectEventsNeeded( TInt aEffect ) const
+    {
+    if ( aEffect == EEffectDefaultScroll ||
+         aEffect == EEffectDefaultScrollWithFade ||
+         aEffect == EEffectLoopScroll ||
+         aEffect == EEffectLoopScrollWithFade ||
+         aEffect == EEffectFadeOut ||
+         aEffect == EEffectFadeIn ||
+         aEffect == EEffectScrollOnceWithFade ||
+         aEffect == EEffectPause )
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+
+TBool CAknTitlePaneLabel::EffectBitmapsNeeded( TInt aEffect ) const
+    {
+    if ( aEffect == EEffectDefaultScroll ||
+         aEffect == EEffectDefaultScrollWithFade ||
+         aEffect == EEffectLoopScroll ||
+         aEffect == EEffectLoopScrollWithFade ||
+         aEffect == EEffectFadeOut ||
+         aEffect == EEffectFadeIn ||
+         aEffect == EEffectScrollOnceWithFade ||
+         aEffect == EEffectFadeToLeft ||
+         aEffect == EEffectFadeToRight )
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+
+TInt CAknTitlePaneLabel::ScrollStepInPixels() const
+    {
+    TInt stepInPixels = 2;
+
+    // Adjust scrolling speed according to screen size
+    TRect screenRect( iAvkonAppUi->ApplicationRect() );
+
+    TInt scale = KScaleMagicNumber;
+    if ( screenRect.Height() > screenRect.Width() )
+        {
+        scale = screenRect.Height();
+        }
+    else
+        {
+        scale = screenRect.Width();
+        }
+
+    stepInPixels = ( stepInPixels * scale ) / KScaleMagicNumber;
+
+    if ( stepInPixels < 1 )
+        {
+        stepInPixels = 1;
+        }
+
+    return stepInPixels;
+    }
+
+
+void CAknTitlePaneLabel::InitEffectQueueL()
+    {
+    if ( !iEffectQueue )
+        {
+        iEffectQueue = new (ELeave) CArrayFixFlat<SAknTitleLableEffect>( 2 );
+        }
+    iEffectQueue->Reset();
+    iNextEffectInEffectQueue = 0;
+    }
+
+
+void CAknTitlePaneLabel::AddToEffectQueueL( SAknTitleLableEffect aEffect )
+    {
+    if ( iEffectQueue )
+        {
+        iEffectQueue->AppendL( aEffect );
+        }
+    }
+
+
+void CAknTitlePaneLabel::ActivateEffectQueue()
+    {
+    if ( iEffectQueue && iEffectQueue->Count() > iNextEffectInEffectQueue )
+        {
+        iNextEffectInEffectQueue++;
+        SetTextEffect(
+            iEffectQueue->At( iNextEffectInEffectQueue - 1 ).iEffect,
+            iEffectQueue->At( iNextEffectInEffectQueue - 1 ).iEffectRect,
+            iEffectQueue->At( iNextEffectInEffectQueue - 1 ).iEffectDuration,
+            iEffectQueue->At( iNextEffectInEffectQueue - 1 ).iLabelRect,
+            iEffectQueue->At( iNextEffectInEffectQueue - 1 ).iTextLayout,
+            iEffectQueue->At( iNextEffectInEffectQueue - 1 ).iTextLayoutLine,
+            iEffectQueue->At( iNextEffectInEffectQueue - 1 ).iTitleText,
+            iEffectQueue->At( iNextEffectInEffectQueue - 1 ).iObserver);
+        }
+    }
+
+
+void CAknTitlePaneLabel::NextEffect()
+    {
+    CancelTimer();
+    ActivateEffectQueue();
+    }
+
+
+TInt CAknTitlePaneLabel::TextLength()
+    {
+    return iTextLength;
+    }
+
+
+void CAknTitlePaneLabel::HandleResourceChange( TInt aType )
+    {
+    CEikLabel::HandleResourceChange( aType );
+
+    if ( aType == KEikDynamicLayoutVariantSwitch )
+        {
+        CancelTimer();
+        TRAP_IGNORE( InitEffectQueueL() );
+        iEffect = 0;
+        }
+    }
+
+
+void CAknTitlePaneLabel::SetPictographInterface(
+    CAknPictographInterface& aInterface )
+    {
+    TRAP_IGNORE( EnablePictographsL( aInterface ) );
+    iPictographInterface = &aInterface;
+    }
+
+
+void CAknTitlePaneLabel::InvalidateText()
+    {
+    iTitleText = NULL;
+    }
+
+
+TBool CAknTitlePaneLabel::EffectQueueIsEmpty()
+    {
+    if ( iEffectQueue && iEffectQueue->Count() > 0 )
+        {
+        return EFalse;
+        }
+    else
+        {
+        return ETrue;
+        }
+    }
+
+
+void CAknTitlePaneLabel::CreateScrollingTextL( const HBufC* aOriginalText )
+    {
+    delete iScrollingText;
+    iScrollingText = NULL;
+
+    if ( aOriginalText )
+        {
+        const CFont* fontUsed =
+            AknLayoutUtils::FontFromId( iTextLayoutLine.FontId() );
+        CFont::TMeasureTextInput input;
+        TInt textLength = fontUsed->MeasureText( *aOriginalText, &input );
+        // Add some safety margin ( must be at least this )
+        textLength = textLength + textLength / 2;
+        if ( textLength < Size().iWidth )
+            {
+            textLength = Size().iWidth;
+            }
+
+        iScrollingText = HBufC::NewL(
+            aOriginalText->Length() + KAknBidiExtraSpacePerLine );
+        TPtr ptr( iScrollingText->Des() );
+        ptr.Fill(' ');
+        AknBidiTextUtils::ConvertToVisualAndClip(
+            *aOriginalText,
+            ptr,
+            *iFont,
+            textLength,
+            textLength );
+
+        // Linefeed chars are always removed since this
+        // text should never be used with 2-line text.
+        ReplaceControlCharacters( iScrollingText, ETrue );
+        }
+    }
+
+
+void CAknTitlePaneLabel::ReplaceControlCharacters( HBufC* aText,
+                                                   TBool aReplaceLinefeeds )
+    {
+    // Remove chars 0x00 to 0x1F and 0x2029 (Paragraph separator).
+    _LIT(KAknTitleLableStripListControlChars, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x2029");
+    // 0x0A (Newline) and 0x2029 (Paragraph separator) excluded.
+    _LIT(KAknTitleLableStripListControlCharsWithoutLinefeed, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F");
+
+    // Replace with space (0x20)
+    TChar replacementChar( 0x20 );
+
+    const TDesC& aChars = KAknTitleLableStripListControlChars;
+    const TDesC& aCharsWithoutLinefeed =
+        KAknTitleLableStripListControlCharsWithoutLinefeed;
+
+    TUint16* ptr = const_cast<TUint16*> ( aText->Ptr() );
+
+    TInt src = 0;
+    TInt srclength = aText->Length();
+    while( src < srclength )
+        {
+        TChar c( ptr[src] );
+        if ( aReplaceLinefeeds )
+            {
+            if ( aChars.LocateF( c ) != KErrNotFound )
+                {
+                ptr[src] = TUint16( replacementChar );
+                }
+            }
+        else
+            {
+            if ( aCharsWithoutLinefeed.LocateF( c ) != KErrNotFound )
+                {
+                ptr[src] = TUint16( replacementChar );
+                }
+            }
+        ++src;
+        }
+    }