diff -r 000000000000 -r 2f259fa3e83a uifw/ganes/src/HgMarquee.cpp --- /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 +#include +#include +#include +#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