uifw/ganes/src/HgMarquee.cpp
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/ganes/src/HgMarquee.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,471 @@
+/*
+* Copyright (c) 2004 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:       Text scrolling functionality.
+*
+*/
+
+
+// INCLUDE FILES
+#include "HgMarquee.h"
+#include <biditext.h>
+#include <AknBidiTextUtils.h>
+#include <AknUtils.h>
+#include <AknLayout2ScalableDef.h>
+#include "HgConstants.h"
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::CAknMarqueeControl
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CHgMarquee::CHgMarquee(const TInt aLoops, const TInt aScrollAmount, 
+                                       const TInt aScrollDelay) : 
+    iDelta(0),
+    iDelay(aScrollDelay),
+    iSpeed(aScrollAmount),
+    iInterval(KHgMarqueeInterval),
+    iLoops(0),
+    iMaxLoops(aLoops),
+    iLastCharacter(EFalse)
+    {
+    iFlags.Set( EFlagIsBeginningOfLoop );
+    iFlags.Set( EFlagUseVisualToLogicalConversion );
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::ConstructL()
+    {
+    iPeriodicTimer = CPeriodic::NewL(CActive::EPriorityIdle);
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CHgMarquee* CHgMarquee::NewLC(const TInt aLoops, 
+                                                       const TInt aScrollAmount,
+                                                       const TInt aScrollDelay)
+    {
+    CHgMarquee* self = new( ELeave )CHgMarquee(aLoops, aScrollAmount, aScrollDelay);
+    
+    CleanupStack::PushL( self );
+    self->ConstructL();
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CHgMarquee* CHgMarquee::NewL(const TInt aLoops, 
+                                                      const TInt aScrollAmount,
+                                                      const TInt aScrollDelay)
+    {
+    CHgMarquee* self = CHgMarquee::NewLC(aLoops, aScrollAmount, aScrollDelay);
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+    
+// Destructor
+CHgMarquee::~CHgMarquee()
+    {
+    if (iPeriodicTimer)
+        {
+        iPeriodicTimer->Cancel();
+        delete iPeriodicTimer;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::SetRedrawCallBack
+// 
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::SetRedrawCallBack(TCallBack& aCallBack)
+    {
+    iCallBack = aCallBack;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::DrawText
+// 
+// -----------------------------------------------------------------------------
+//
+TBool CHgMarquee::DrawText(
+    CWindowGc& aGc,
+    const TRect& aRect,
+    const TAknTextComponentLayout& aTextLayout,
+    const TDesC& aText,
+    const TRgb& aColor )
+    {
+    // In this function, TAknLayoutText::DrawText performs logical-to-visual
+    // conversion for the given text.
+    if ( iLoops < iMaxLoops && aText.Length() < KAknSensibleLength ) // Has every loop been executed
+        {
+        TAknLayoutText textLayout;
+        textLayout.LayoutText( aRect, aTextLayout );
+
+        TRect marqueeRect( textLayout.TextRect() );
+        TInt textWidth = textLayout.Font()->TextWidthInPixels( aText );
+        if ( textWidth <= marqueeRect.Width() )
+            {
+            iLoops = iMaxLoops;
+            return ETrue;
+            }
+    
+        if ( TBidiText::TextDirectionality( aText ) == TBidiText::ELeftToRight )
+            iFlags.Set( EFlagIsWestern );
+        else
+            iFlags.Clear( EFlagIsWestern );
+
+        aGc.SetClippingRect( marqueeRect );
+        
+        if ( iFlags.IsSet( EFlagIsBeginningOfLoop ) &&
+            !iFlags.IsSet( EFlagIsWaitingForCallBack ) )
+            {
+            Stop();     // Just in case
+            textLayout.DrawText( aGc, aText, iFlags.IsSet( EFlagUseVisualToLogicalConversion ), aColor );
+            iFlags.Clear( EFlagIsBeginningOfLoop );
+            Start();
+            }
+        else if ( iDelta == 0 ) // we are still drawing non-scrolling text (2 line lists need this)
+            {
+            textLayout.DrawText( aGc, aText, iFlags.IsSet( EFlagUseVisualToLogicalConversion ), aColor );
+            }
+        else if ( iFlags.IsSet( EFlagIsWestern ) ) // Scrolls from right to left.
+            {
+            DrawWestern(
+                    aGc, 
+                    aRect, 
+                    marqueeRect, 
+                    aTextLayout, 
+                    textLayout, 
+                    aText, 
+                    textWidth, 
+                    aColor);
+            }
+        else    // Non-western, scrolls from left to right.
+            {
+            DrawNonWestern(
+                    aGc, 
+                    aRect, 
+                    marqueeRect, 
+                    aTextLayout, 
+                    textLayout, 
+                    aText, 
+                    textWidth, 
+                    aColor);
+            }
+
+        aGc.CancelClippingRect();
+        // Time to let the parent know if all loops aren't executed yet.
+        return EFalse;
+        }
+    else    // No more loops to be executed -> draw text in the default position.
+        {
+        Stop();         // No need to generate events any longer.
+        return ETrue;   // Indicate the parent that marquee has stopped,  
+        }               // parent is then able to for example truncate the text.
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::DrawWestern
+// Starts scrolling the text.
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::DrawWestern( CWindowGc& aGc,
+                         const TRect& aRect,
+                         const TRect& aMarqueeRect,
+                         const TAknTextComponentLayout& aTextLayout,
+                         TAknLayoutText aLayout,
+                         const TDesC& aText,
+                         TInt aTextWidth,
+                         const TRgb& aColor )
+    {
+    TRect rect = aRect;
+    rect.SetWidth( aRect.Width() + ( aTextWidth - aMarqueeRect.Width() ) );
+    rect.Move(-iDelta, 0);
+
+    // ESRY-7M5A33
+    // Due to text rolling region is not actual parent region, 
+    // textLayout.TextRect() is incorrect. Introduce a temparory layout to recalculate.   
+    TAknTextLineLayout  tmpTextLineLayout = aTextLayout;
+    tmpTextLineLayout.iW = aTextWidth;
+    aLayout.LayoutText( rect, tmpTextLineLayout );
+        
+    aLayout.DrawText( aGc, aText, iFlags.IsSet( EFlagUseVisualToLogicalConversion ), aColor );
+
+    if ( iFlags.IsSet( EFlagIsWaitingForCallBack ) )
+        {
+        // do nothing
+        }
+    // Sliding behaviour: When the last character is visible, scrolling stops
+    // and starts from the beginning after a short delay.
+    else if ( aLayout.TextRect().iBr.iX >= aMarqueeRect.iBr.iX )
+        {
+        iFlags.Clear( EFlagIsBeginningOfLoop );
+        if ( !iPeriodicTimer->IsActive() )
+            Start();
+        }
+    else    // Last character has appeared, so let's make it reappear from the other 
+        {   // side after a delay
+        iFlags.Set( EFlagIsBeginningOfLoop );
+        iFlags.Set( EFlagIsWaitingForCallBack );
+        iLastCharacter = ETrue;
+        Stop();    // Cancel all outstanding requests.
+        ++iLoops;
+        Start();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::DrawNonWestern
+// Starts scrolling the text.
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::DrawNonWestern( CWindowGc& aGc,
+                         const TRect& aRect,
+                         const TRect& aMarqueeRect,
+                         const TAknTextComponentLayout& aTextLayout,
+                         TAknLayoutText aLayout,
+                         const TDesC& aText,
+                         TInt aTextWidth,
+                         const TRgb& aColor )
+    {
+    TRect rect = aRect;
+    // Prepare rect to be scrolled from l -> r
+    rect.iTl.iX = rect.iTl.iX - ( aTextWidth - aMarqueeRect.Width() );
+    rect.Move(iDelta, 0);
+
+    // note refer to case western               
+    TAknTextLineLayout  tmpTextLineLayout = aTextLayout;
+    tmpTextLineLayout.iW = aTextWidth;
+    aLayout.LayoutText( rect, tmpTextLineLayout );
+    
+    aLayout.DrawText( aGc, aText, iFlags.IsSet( EFlagUseVisualToLogicalConversion ), aColor );
+
+    if ( iFlags.IsSet( EFlagIsWaitingForCallBack ) )
+        {
+        // do nothing
+        }
+    else if ( aLayout.TextRect().iTl.iX < aMarqueeRect.iTl.iX ) 
+        {
+        iFlags.Clear( EFlagIsBeginningOfLoop );
+        if ( !iPeriodicTimer->IsActive() )
+            Start();
+        }
+    else    // Last character has appeared
+        {
+        iFlags.Set( EFlagIsBeginningOfLoop );
+        iFlags.Set( EFlagIsWaitingForCallBack );
+        iLastCharacter = ETrue;
+        Stop();    // Cancel all outstanding requests.
+        ++iLoops;
+        Start();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::Start
+// Starts scrolling the text.
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::Start()
+    {
+    if ( iFlags.IsSet( EFlagIsOn ) ) 
+        {
+        if ( !iPeriodicTimer->IsActive() )  // start timer if not already started
+            {
+            iPeriodicTimer->Start( TTimeIntervalMicroSeconds32( iDelay ),
+                                   TTimeIntervalMicroSeconds32( iInterval ), 
+                                   TCallBack( CHgMarquee::ScrollEvent, this ) );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::Stop
+// Stops scrolling the text.
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::Stop()
+    {
+    //Stop the timer if it is active
+    if ( iPeriodicTimer->IsActive() )
+        {
+        iPeriodicTimer->Cancel();
+        }
+    if ( !iFlags.IsSet(EFlagIsWaitingForCallBack) )
+        {
+        iDelta = 0;            // reset scroll position
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::Reset
+// Resets the animation data.
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::Reset()
+    {
+    iDelta = 0;            // reset scroll position
+    iLoops = 0;
+    iLastCharacter = EFalse;
+    Stop();
+    iFlags.Set( EFlagIsBeginningOfLoop );
+    iFlags.Clear( EFlagIsWaitingForCallBack );
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::IsMarqueeOn
+// Returns marquee status
+// Two versions to discard compiler warnings
+// -----------------------------------------------------------------------------
+//
+#ifdef __WINS__
+const TBool CHgMarquee::IsMarqueeOn()
+    {
+    return iFlags.IsSet( EFlagIsOn );
+    }
+#else
+TBool CHgMarquee::IsMarqueeOn()
+    {
+    return iFlags.IsSet( EFlagIsOn );
+    }
+#endif // __WINS__
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::SetSpeedInPixels
+// sets scrolling speed in pixels
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::SetSpeedInPixels(TInt aSpeed)
+    {
+    if ( aSpeed <= 0 )
+        aSpeed = KHgMarqueeSpeed;
+    iSpeed = aSpeed;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::SetDelay
+// Sets delay between loops
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::SetDelay(TInt aDelay)
+    {
+    if ( aDelay < 0 )
+        aDelay = KHgMarqueeDelay;
+    iDelay = aDelay;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::SetInterval
+// Sets scrolling interval
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::SetInterval(TInt aInterval)
+    {
+    iInterval = aInterval;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::SetLoops
+// Sets the amount of maximum loops to be executed.
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::SetLoops(TInt aLoops)
+    {
+    if ( aLoops < 0 )
+        aLoops = KHgMarqueeLoops;
+    iMaxLoops = aLoops;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::DoScroll
+// advances text position and instructs parent control to do a redraw
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::DoScroll()
+    {
+    if ( !iFlags.IsSet( EFlagIsWaitingForCallBack ) )
+        {
+        iDelta += iSpeed;            // advance text
+        }
+  
+    iFlags.Clear( EFlagIsWaitingForCallBack );
+    
+    if ( !iCallBack.CallBack() )   // stop timer if callback returns false
+        {
+        iPeriodicTimer->Cancel();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::ScrollEvent
+// This static function is called by the periodic timer
+// -----------------------------------------------------------------------------
+//
+TInt CHgMarquee::ScrollEvent(TAny * aPtr)
+    {
+    ( ( CHgMarquee* ) aPtr )->DoScroll();
+    return TRUE; // run again
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::EnableMarquee
+// Enables/disables marquee feature.
+// -----------------------------------------------------------------------------
+//
+void CHgMarquee::EnableMarquee(TBool aEnable)
+    {
+    if ( aEnable )
+        {
+        iFlags.Set( EFlagIsOn );
+        }
+    else
+        {
+        iFlags.Clear( EFlagIsOn );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknMarqueeControl::UseLogicalToVisualConversion
+// -----------------------------------------------------------------------------
+//
+
+void CHgMarquee::UseLogicalToVisualConversion(
+    TBool aUseConversion )
+    {
+    if ( aUseConversion )
+        {
+        iFlags.Set( EFlagUseVisualToLogicalConversion );
+        }
+    else
+        {
+        iFlags.Clear( EFlagUseVisualToLogicalConversion );
+        }
+    }
+
+//  End of File