--- /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