uifw/ganes/src/HgMarquee.cpp
changeset 47 2f0c06423c72
parent 46 0e1e0022bd03
child 53 3c67ea82fafc
equal deleted inserted replaced
46:0e1e0022bd03 47:2f0c06423c72
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:       Text scrolling functionality.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "HgMarquee.h"
       
    21 #include <biditext.h>
       
    22 #include <AknBidiTextUtils.h>
       
    23 #include <AknUtils.h>
       
    24 #include <AknLayout2ScalableDef.h>
       
    25 #include "HgConstants.h"
       
    26 
       
    27 // ============================ MEMBER FUNCTIONS ===============================
       
    28 
       
    29 // -----------------------------------------------------------------------------
       
    30 // CAknMarqueeControl::CAknMarqueeControl
       
    31 // C++ default constructor can NOT contain any code, that
       
    32 // might leave.
       
    33 // -----------------------------------------------------------------------------
       
    34 //
       
    35 CHgMarquee::CHgMarquee(const TInt aLoops, const TInt aScrollAmount, 
       
    36                                        const TInt aScrollDelay) : 
       
    37     iDelta(0),
       
    38     iDelay(aScrollDelay),
       
    39     iSpeed(aScrollAmount),
       
    40     iInterval(KHgMarqueeInterval),
       
    41     iLoops(0),
       
    42     iMaxLoops(aLoops),
       
    43     iLastCharacter(EFalse)
       
    44     {
       
    45     iFlags.Set( EFlagIsBeginningOfLoop );
       
    46     iFlags.Set( EFlagUseVisualToLogicalConversion );
       
    47     }
       
    48 
       
    49 // -----------------------------------------------------------------------------
       
    50 // CAknMarqueeControl::ConstructL
       
    51 // Symbian 2nd phase constructor can leave.
       
    52 // -----------------------------------------------------------------------------
       
    53 //
       
    54 void CHgMarquee::ConstructL()
       
    55     {
       
    56     iPeriodicTimer = CPeriodic::NewL(CActive::EPriorityIdle);
       
    57     }
       
    58 
       
    59 // -----------------------------------------------------------------------------
       
    60 // CAknMarqueeControl::NewLC
       
    61 // Two-phased constructor.
       
    62 // -----------------------------------------------------------------------------
       
    63 //
       
    64 CHgMarquee* CHgMarquee::NewLC(const TInt aLoops, 
       
    65                                                        const TInt aScrollAmount,
       
    66                                                        const TInt aScrollDelay)
       
    67     {
       
    68     CHgMarquee* self = new( ELeave )CHgMarquee(aLoops, aScrollAmount, aScrollDelay);
       
    69     
       
    70     CleanupStack::PushL( self );
       
    71     self->ConstructL();
       
    72 
       
    73     return self;
       
    74     }
       
    75 
       
    76 // -----------------------------------------------------------------------------
       
    77 // CAknMarqueeControl::NewL
       
    78 // Two-phased constructor.
       
    79 // -----------------------------------------------------------------------------
       
    80 //
       
    81 CHgMarquee* CHgMarquee::NewL(const TInt aLoops, 
       
    82                                                       const TInt aScrollAmount,
       
    83                                                       const TInt aScrollDelay)
       
    84     {
       
    85     CHgMarquee* self = CHgMarquee::NewLC(aLoops, aScrollAmount, aScrollDelay);
       
    86     CleanupStack::Pop( self );
       
    87 
       
    88     return self;
       
    89     }
       
    90     
       
    91 // Destructor
       
    92 CHgMarquee::~CHgMarquee()
       
    93     {
       
    94     if (iPeriodicTimer)
       
    95         {
       
    96         iPeriodicTimer->Cancel();
       
    97         delete iPeriodicTimer;
       
    98         }
       
    99     }
       
   100 
       
   101 // -----------------------------------------------------------------------------
       
   102 // CAknMarqueeControl::SetRedrawCallBack
       
   103 // 
       
   104 // -----------------------------------------------------------------------------
       
   105 //
       
   106 void CHgMarquee::SetRedrawCallBack(TCallBack& aCallBack)
       
   107     {
       
   108     iCallBack = aCallBack;
       
   109     }
       
   110 
       
   111 // -----------------------------------------------------------------------------
       
   112 // CAknMarqueeControl::DrawText
       
   113 // 
       
   114 // -----------------------------------------------------------------------------
       
   115 //
       
   116 TBool CHgMarquee::DrawText(
       
   117     CWindowGc& aGc,
       
   118     const TRect& aRect,
       
   119     const TAknTextComponentLayout& aTextLayout,
       
   120     const TDesC& aText,
       
   121     const TRgb& aColor )
       
   122     {
       
   123     // In this function, TAknLayoutText::DrawText performs logical-to-visual
       
   124     // conversion for the given text.
       
   125     if ( iLoops < iMaxLoops && aText.Length() < KAknSensibleLength ) // Has every loop been executed
       
   126         {
       
   127         TAknLayoutText textLayout;
       
   128         textLayout.LayoutText( aRect, aTextLayout );
       
   129 
       
   130         TRect marqueeRect( textLayout.TextRect() );
       
   131         TInt textWidth = textLayout.Font()->TextWidthInPixels( aText );
       
   132         if ( textWidth <= marqueeRect.Width() )
       
   133             {
       
   134             iLoops = iMaxLoops;
       
   135             return ETrue;
       
   136             }
       
   137     
       
   138         if ( TBidiText::TextDirectionality( aText ) == TBidiText::ELeftToRight )
       
   139             iFlags.Set( EFlagIsWestern );
       
   140         else
       
   141             iFlags.Clear( EFlagIsWestern );
       
   142 
       
   143         aGc.SetClippingRect( marqueeRect );
       
   144         
       
   145         if ( iFlags.IsSet( EFlagIsBeginningOfLoop ) &&
       
   146             !iFlags.IsSet( EFlagIsWaitingForCallBack ) )
       
   147             {
       
   148             Stop();     // Just in case
       
   149             textLayout.DrawText( aGc, aText, iFlags.IsSet( EFlagUseVisualToLogicalConversion ), aColor );
       
   150             iFlags.Clear( EFlagIsBeginningOfLoop );
       
   151             Start();
       
   152             }
       
   153         else if ( iDelta == 0 ) // we are still drawing non-scrolling text (2 line lists need this)
       
   154             {
       
   155             textLayout.DrawText( aGc, aText, iFlags.IsSet( EFlagUseVisualToLogicalConversion ), aColor );
       
   156             }
       
   157         else if ( iFlags.IsSet( EFlagIsWestern ) ) // Scrolls from right to left.
       
   158             {
       
   159             DrawWestern(
       
   160                     aGc, 
       
   161                     aRect, 
       
   162                     marqueeRect, 
       
   163                     aTextLayout, 
       
   164                     textLayout, 
       
   165                     aText, 
       
   166                     textWidth, 
       
   167                     aColor);
       
   168             }
       
   169         else    // Non-western, scrolls from left to right.
       
   170             {
       
   171             DrawNonWestern(
       
   172                     aGc, 
       
   173                     aRect, 
       
   174                     marqueeRect, 
       
   175                     aTextLayout, 
       
   176                     textLayout, 
       
   177                     aText, 
       
   178                     textWidth, 
       
   179                     aColor);
       
   180             }
       
   181 
       
   182         aGc.CancelClippingRect();
       
   183         // Time to let the parent know if all loops aren't executed yet.
       
   184         return EFalse;
       
   185         }
       
   186     else    // No more loops to be executed -> draw text in the default position.
       
   187         {
       
   188         Stop();         // No need to generate events any longer.
       
   189         return ETrue;   // Indicate the parent that marquee has stopped,  
       
   190         }               // parent is then able to for example truncate the text.
       
   191     }
       
   192 
       
   193 // -----------------------------------------------------------------------------
       
   194 // CAknMarqueeControl::DrawWestern
       
   195 // Starts scrolling the text.
       
   196 // -----------------------------------------------------------------------------
       
   197 //
       
   198 void CHgMarquee::DrawWestern( CWindowGc& aGc,
       
   199                          const TRect& aRect,
       
   200                          const TRect& aMarqueeRect,
       
   201                          const TAknTextComponentLayout& aTextLayout,
       
   202                          TAknLayoutText aLayout,
       
   203                          const TDesC& aText,
       
   204                          TInt aTextWidth,
       
   205                          const TRgb& aColor )
       
   206     {
       
   207     TRect rect = aRect;
       
   208     rect.SetWidth( aRect.Width() + ( aTextWidth - aMarqueeRect.Width() ) );
       
   209     rect.Move(-iDelta, 0);
       
   210 
       
   211     // ESRY-7M5A33
       
   212     // Due to text rolling region is not actual parent region, 
       
   213     // textLayout.TextRect() is incorrect. Introduce a temparory layout to recalculate.   
       
   214     TAknTextLineLayout  tmpTextLineLayout = aTextLayout;
       
   215     tmpTextLineLayout.iW = aTextWidth;
       
   216     aLayout.LayoutText( rect, tmpTextLineLayout );
       
   217         
       
   218     aLayout.DrawText( aGc, aText, iFlags.IsSet( EFlagUseVisualToLogicalConversion ), aColor );
       
   219 
       
   220     if ( iFlags.IsSet( EFlagIsWaitingForCallBack ) )
       
   221         {
       
   222         // do nothing
       
   223         }
       
   224     // Sliding behaviour: When the last character is visible, scrolling stops
       
   225     // and starts from the beginning after a short delay.
       
   226     else if ( aLayout.TextRect().iBr.iX >= aMarqueeRect.iBr.iX )
       
   227         {
       
   228         iFlags.Clear( EFlagIsBeginningOfLoop );
       
   229         if ( !iPeriodicTimer->IsActive() )
       
   230             Start();
       
   231         }
       
   232     else    // Last character has appeared, so let's make it reappear from the other 
       
   233         {   // side after a delay
       
   234         iFlags.Set( EFlagIsBeginningOfLoop );
       
   235         iFlags.Set( EFlagIsWaitingForCallBack );
       
   236         iLastCharacter = ETrue;
       
   237         Stop();    // Cancel all outstanding requests.
       
   238         ++iLoops;
       
   239         Start();
       
   240         }
       
   241     }
       
   242 
       
   243 // -----------------------------------------------------------------------------
       
   244 // CAknMarqueeControl::DrawNonWestern
       
   245 // Starts scrolling the text.
       
   246 // -----------------------------------------------------------------------------
       
   247 //
       
   248 void CHgMarquee::DrawNonWestern( CWindowGc& aGc,
       
   249                          const TRect& aRect,
       
   250                          const TRect& aMarqueeRect,
       
   251                          const TAknTextComponentLayout& aTextLayout,
       
   252                          TAknLayoutText aLayout,
       
   253                          const TDesC& aText,
       
   254                          TInt aTextWidth,
       
   255                          const TRgb& aColor )
       
   256     {
       
   257     TRect rect = aRect;
       
   258     // Prepare rect to be scrolled from l -> r
       
   259     rect.iTl.iX = rect.iTl.iX - ( aTextWidth - aMarqueeRect.Width() );
       
   260     rect.Move(iDelta, 0);
       
   261 
       
   262     // note refer to case western               
       
   263     TAknTextLineLayout  tmpTextLineLayout = aTextLayout;
       
   264     tmpTextLineLayout.iW = aTextWidth;
       
   265     aLayout.LayoutText( rect, tmpTextLineLayout );
       
   266     
       
   267     aLayout.DrawText( aGc, aText, iFlags.IsSet( EFlagUseVisualToLogicalConversion ), aColor );
       
   268 
       
   269     if ( iFlags.IsSet( EFlagIsWaitingForCallBack ) )
       
   270         {
       
   271         // do nothing
       
   272         }
       
   273     else if ( aLayout.TextRect().iTl.iX < aMarqueeRect.iTl.iX ) 
       
   274         {
       
   275         iFlags.Clear( EFlagIsBeginningOfLoop );
       
   276         if ( !iPeriodicTimer->IsActive() )
       
   277             Start();
       
   278         }
       
   279     else    // Last character has appeared
       
   280         {
       
   281         iFlags.Set( EFlagIsBeginningOfLoop );
       
   282         iFlags.Set( EFlagIsWaitingForCallBack );
       
   283         iLastCharacter = ETrue;
       
   284         Stop();    // Cancel all outstanding requests.
       
   285         ++iLoops;
       
   286         Start();
       
   287         }
       
   288     }
       
   289 
       
   290 // -----------------------------------------------------------------------------
       
   291 // CAknMarqueeControl::Start
       
   292 // Starts scrolling the text.
       
   293 // -----------------------------------------------------------------------------
       
   294 //
       
   295 void CHgMarquee::Start()
       
   296     {
       
   297     if ( iFlags.IsSet( EFlagIsOn ) ) 
       
   298         {
       
   299         if ( !iPeriodicTimer->IsActive() )  // start timer if not already started
       
   300             {
       
   301             iPeriodicTimer->Start( TTimeIntervalMicroSeconds32( iDelay ),
       
   302                                    TTimeIntervalMicroSeconds32( iInterval ), 
       
   303                                    TCallBack( CHgMarquee::ScrollEvent, this ) );
       
   304             }
       
   305         }
       
   306     }
       
   307 
       
   308 // -----------------------------------------------------------------------------
       
   309 // CAknMarqueeControl::Stop
       
   310 // Stops scrolling the text.
       
   311 // -----------------------------------------------------------------------------
       
   312 //
       
   313 void CHgMarquee::Stop()
       
   314     {
       
   315     //Stop the timer if it is active
       
   316     if ( iPeriodicTimer->IsActive() )
       
   317         {
       
   318         iPeriodicTimer->Cancel();
       
   319         }
       
   320     if ( !iFlags.IsSet(EFlagIsWaitingForCallBack) )
       
   321         {
       
   322         iDelta = 0;            // reset scroll position
       
   323         }
       
   324     }
       
   325 
       
   326 // -----------------------------------------------------------------------------
       
   327 // CAknMarqueeControl::Reset
       
   328 // Resets the animation data.
       
   329 // -----------------------------------------------------------------------------
       
   330 //
       
   331 void CHgMarquee::Reset()
       
   332     {
       
   333     iDelta = 0;            // reset scroll position
       
   334     iLoops = 0;
       
   335     iLastCharacter = EFalse;
       
   336     Stop();
       
   337     iFlags.Set( EFlagIsBeginningOfLoop );
       
   338     iFlags.Clear( EFlagIsWaitingForCallBack );
       
   339     }
       
   340 
       
   341 // -----------------------------------------------------------------------------
       
   342 // CAknMarqueeControl::IsMarqueeOn
       
   343 // Returns marquee status
       
   344 // Two versions to discard compiler warnings
       
   345 // -----------------------------------------------------------------------------
       
   346 //
       
   347 #ifdef __WINS__
       
   348 const TBool CHgMarquee::IsMarqueeOn()
       
   349     {
       
   350     return iFlags.IsSet( EFlagIsOn );
       
   351     }
       
   352 #else
       
   353 TBool CHgMarquee::IsMarqueeOn()
       
   354     {
       
   355     return iFlags.IsSet( EFlagIsOn );
       
   356     }
       
   357 #endif // __WINS__
       
   358 
       
   359 // -----------------------------------------------------------------------------
       
   360 // CAknMarqueeControl::SetSpeedInPixels
       
   361 // sets scrolling speed in pixels
       
   362 // -----------------------------------------------------------------------------
       
   363 //
       
   364 void CHgMarquee::SetSpeedInPixels(TInt aSpeed)
       
   365     {
       
   366     if ( aSpeed <= 0 )
       
   367         aSpeed = KHgMarqueeSpeed;
       
   368     iSpeed = aSpeed;
       
   369     }
       
   370 
       
   371 // -----------------------------------------------------------------------------
       
   372 // CAknMarqueeControl::SetDelay
       
   373 // Sets delay between loops
       
   374 // -----------------------------------------------------------------------------
       
   375 //
       
   376 void CHgMarquee::SetDelay(TInt aDelay)
       
   377     {
       
   378     if ( aDelay < 0 )
       
   379         aDelay = KHgMarqueeDelay;
       
   380     iDelay = aDelay;
       
   381     }
       
   382 
       
   383 // -----------------------------------------------------------------------------
       
   384 // CAknMarqueeControl::SetInterval
       
   385 // Sets scrolling interval
       
   386 // -----------------------------------------------------------------------------
       
   387 //
       
   388 void CHgMarquee::SetInterval(TInt aInterval)
       
   389     {
       
   390     iInterval = aInterval;
       
   391     }
       
   392 
       
   393 // -----------------------------------------------------------------------------
       
   394 // CAknMarqueeControl::SetLoops
       
   395 // Sets the amount of maximum loops to be executed.
       
   396 // -----------------------------------------------------------------------------
       
   397 //
       
   398 void CHgMarquee::SetLoops(TInt aLoops)
       
   399     {
       
   400     if ( aLoops < 0 )
       
   401         aLoops = KHgMarqueeLoops;
       
   402     iMaxLoops = aLoops;
       
   403     }
       
   404 
       
   405 // -----------------------------------------------------------------------------
       
   406 // CAknMarqueeControl::DoScroll
       
   407 // advances text position and instructs parent control to do a redraw
       
   408 // -----------------------------------------------------------------------------
       
   409 //
       
   410 void CHgMarquee::DoScroll()
       
   411     {
       
   412     if ( !iFlags.IsSet( EFlagIsWaitingForCallBack ) )
       
   413         {
       
   414         iDelta += iSpeed;            // advance text
       
   415         }
       
   416   
       
   417     iFlags.Clear( EFlagIsWaitingForCallBack );
       
   418     
       
   419     if ( !iCallBack.CallBack() )   // stop timer if callback returns false
       
   420         {
       
   421         iPeriodicTimer->Cancel();
       
   422         }
       
   423     }
       
   424 
       
   425 // -----------------------------------------------------------------------------
       
   426 // CAknMarqueeControl::ScrollEvent
       
   427 // This static function is called by the periodic timer
       
   428 // -----------------------------------------------------------------------------
       
   429 //
       
   430 TInt CHgMarquee::ScrollEvent(TAny * aPtr)
       
   431     {
       
   432     ( ( CHgMarquee* ) aPtr )->DoScroll();
       
   433     return TRUE; // run again
       
   434     }
       
   435 
       
   436 // -----------------------------------------------------------------------------
       
   437 // CAknMarqueeControl::EnableMarquee
       
   438 // Enables/disables marquee feature.
       
   439 // -----------------------------------------------------------------------------
       
   440 //
       
   441 void CHgMarquee::EnableMarquee(TBool aEnable)
       
   442     {
       
   443     if ( aEnable )
       
   444         {
       
   445         iFlags.Set( EFlagIsOn );
       
   446         }
       
   447     else
       
   448         {
       
   449         iFlags.Clear( EFlagIsOn );
       
   450         }
       
   451     }
       
   452 
       
   453 // -----------------------------------------------------------------------------
       
   454 // CAknMarqueeControl::UseLogicalToVisualConversion
       
   455 // -----------------------------------------------------------------------------
       
   456 //
       
   457 
       
   458 void CHgMarquee::UseLogicalToVisualConversion(
       
   459     TBool aUseConversion )
       
   460     {
       
   461     if ( aUseConversion )
       
   462         {
       
   463         iFlags.Set( EFlagUseVisualToLogicalConversion );
       
   464         }
       
   465     else
       
   466         {
       
   467         iFlags.Clear( EFlagUseVisualToLogicalConversion );
       
   468         }
       
   469     }
       
   470 
       
   471 //  End of File