uifw/ganes/src/HgDrawUtils.cpp
changeset 47 2f0c06423c72
parent 46 0e1e0022bd03
child 53 3c67ea82fafc
equal deleted inserted replaced
46:0e1e0022bd03 47:2f0c06423c72
     1 /*
       
     2 * Copyright (c) 2009 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:     
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "HgDrawUtils.h"
       
    20 
       
    21 #include "HgMarquee.h"
       
    22 
       
    23 #include <gdi.h>
       
    24 #include <gulicon.h>
       
    25 #include <AknUtils.h>
       
    26 #include <AknsUtils.h>
       
    27 #include <AknsControlContext.h>
       
    28 #include <AknsDrawUtils.h>
       
    29 #include <AknsListBoxBackgroundControlContext.h>
       
    30 #include <aknlayoutscalable_avkon.cdl.h>
       
    31 #include <AknBidiTextUtils.h>
       
    32 
       
    33 const TInt KHgDrawUtilsGranularity(10);
       
    34 const TInt KHgDrawUtilsMaxNumberOfLines(4);
       
    35 
       
    36 CHgDrawUtils* CHgDrawUtils::NewL( TCallBack& aMarqueeCallback )
       
    37     {
       
    38     CHgDrawUtils* self = new (ELeave) CHgDrawUtils();
       
    39     CleanupStack::PushL( self );
       
    40     self->ConstructL( aMarqueeCallback );
       
    41     CleanupStack::Pop(self);
       
    42     return self;
       
    43     }
       
    44 
       
    45 CHgDrawUtils::~CHgDrawUtils()
       
    46     {
       
    47     delete iMarquee;
       
    48     }
       
    49     
       
    50 
       
    51 void DrawEmptyListImpl_real_DrawUpToTwoLines( CGraphicsContext &aGc,
       
    52                                               TPtrC aText,
       
    53                                               TAknLayoutText &aLine1,
       
    54                                               TAknLayoutText &aLine2,
       
    55                                               TInt aLine1length,
       
    56                                               TInt aLine2length,
       
    57                                               const CFont* aFont,
       
    58                                               TRgb aColor,
       
    59                                               TDes& aBuffer )
       
    60     {
       
    61     TRAPD( error,
       
    62         {
       
    63         CArrayFix<TInt>* wrapWidthArray = new( ELeave ) CArrayFixFlat<TInt>(KHgDrawUtilsGranularity);
       
    64         CleanupStack::PushL( wrapWidthArray );
       
    65 
       
    66         wrapWidthArray->AppendL( aLine1length );
       
    67         wrapWidthArray->AppendL( aLine2length );
       
    68         
       
    69         AknBidiTextUtils::ConvertToVisualAndWrapToStringL( 
       
    70             aText, *wrapWidthArray, *aFont, aBuffer, ETrue );
       
    71         
       
    72         CleanupStack::PopAndDestroy( wrapWidthArray ); // wrapWidthArray
       
    73         } ); // TRAP end
       
    74     
       
    75     if ( error != KErrNone )
       
    76         {
       
    77         aBuffer = aText;
       
    78         }
       
    79     
       
    80     // Drawing text
       
    81     aGc.Reset();
       
    82     TBool oneline( EFalse );
       
    83     TPtrC ptr = aBuffer;
       
    84     TPtrC top = ptr;
       
    85     TInt off = ptr.Locate('\n');
       
    86     if ( off >= 0 )
       
    87         {
       
    88         top.Set(ptr.Left(off));
       
    89         ptr.Set(ptr.Mid(off+1));
       
    90 
       
    91         TInt off1 = ptr.Locate('\n');
       
    92         if ( off1 >= 0 )
       
    93             {
       
    94             ptr.Set(ptr.Left(off1));
       
    95             }
       
    96         else
       
    97             {
       
    98             oneline = ETrue;
       
    99             }
       
   100         }
       
   101     
       
   102     aGc.SetBrushStyle(CGraphicsContext::ENullBrush);
       
   103 
       
   104     // no layout exist for popup list - mainpane layout is ok for X
       
   105     // coords, center vertically.  Also need to calculate vertical
       
   106     // position for mainpane lists, since laf is broken as designed.
       
   107     // If you don't believe this, try using laf values in phonebook.
       
   108     aGc.UseFont( aFont );
       
   109     aGc.SetPenColor( aColor );
       
   110     
       
   111     aLine1.DrawText(aGc, top, EFalse, aColor );
       
   112     if ( !oneline )
       
   113         {
       
   114         aLine2.DrawText( aGc, ptr, EFalse, aColor );
       
   115         }
       
   116     aGc.DiscardFont();
       
   117     }    
       
   118 
       
   119 void DrawEmptyListImpl_real_DrawMoreThanTwoLines( const TRect &aParentRect,
       
   120                                                   CGraphicsContext &aGc,
       
   121                                                   TPtrC aText,
       
   122                                                   TRgb aColor,
       
   123                                                   TDes& buffer )
       
   124 
       
   125     {
       
   126     // fetch layouts
       
   127     TAknLayoutText line[KHgDrawUtilsMaxNumberOfLines];
       
   128     
       
   129     line[0].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t1(2) );
       
   130     line[1].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t3(0) );
       
   131     line[2].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t4(0) );
       
   132     line[3].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t5(0) );
       
   133 
       
   134     TInt lineLength[KHgDrawUtilsMaxNumberOfLines];
       
   135     TInt i;
       
   136     for ( i = 0; i < KHgDrawUtilsMaxNumberOfLines; i++ )
       
   137         {
       
   138         lineLength[i] = line[i].TextRect().Width();
       
   139         }
       
   140     
       
   141     const CFont *bigFont = line[0].Font();
       
   142     const CFont *smallFont = line[1].Font(); 
       
   143 
       
   144     // wrap text
       
   145     TInt off = aText.Locate('\n');
       
   146     TPtrC rest( aText );
       
   147     rest.Set( aText.Right(aText.Length() - off - 1 ));
       
   148 
       
   149     HBufC* firstLine = NULL;
       
   150     
       
   151     TRAPD( error1, 
       
   152             {
       
   153             firstLine = HBufC::NewL(
       
   154                 aText.Left(off).Length() + KAknBidiExtraSpacePerLine );
       
   155             });
       
   156 
       
   157     if (error1 == KErrNone)
       
   158         {
       
   159         TPtr firstLinePtr = firstLine->Des();
       
   160         AknBidiTextUtils::ConvertToVisualAndClip(
       
   161                                 aText.Left(off),
       
   162                                 firstLinePtr,
       
   163                                 *bigFont,
       
   164                                 lineLength[0],
       
   165                                 lineLength[0] );
       
   166         }
       
   167     
       
   168     TRAPD( error2,
       
   169         {
       
   170         CArrayFix<TInt>* wrapWidthArray = new( ELeave ) CArrayFixFlat<TInt>(KHgDrawUtilsGranularity);
       
   171         CleanupStack::PushL( wrapWidthArray );
       
   172         
       
   173         // wrap small font lines
       
   174         wrapWidthArray->Reset();
       
   175         for ( i = 1; i < KHgDrawUtilsMaxNumberOfLines; i++ )
       
   176             {
       
   177             wrapWidthArray->AppendL( lineLength[i] );
       
   178             }
       
   179         
       
   180         AknBidiTextUtils::ConvertToVisualAndWrapToStringL( 
       
   181             rest, *wrapWidthArray, *smallFont, buffer, ETrue );
       
   182         
       
   183         CleanupStack::PopAndDestroy( wrapWidthArray ); // wrapWidthArray
       
   184         } ); // TRAP end
       
   185     
       
   186     
       
   187     TPtrC ptr[KHgDrawUtilsMaxNumberOfLines];
       
   188     TInt n = 0;
       
   189     
       
   190     if (error1 == KErrNone)
       
   191         {
       
   192         ptr[0].Set( firstLine->Des() );
       
   193         }
       
   194     if ( error1 != KErrNone || error2 != KErrNone )
       
   195         {
       
   196         ptr[0].Set(aText.Left(off));
       
   197         }
       
   198     else
       
   199         {
       
   200         TInt newlines[3];
       
   201         n = 0;
       
   202         for ( i = 0; i < buffer.Length(); i++ )
       
   203             {
       
   204             if ( buffer[i] != '\n' )
       
   205                 {
       
   206                 continue;
       
   207                 }
       
   208             newlines[n] = i;
       
   209             
       
   210             n++;
       
   211             if ( n >= 3 )
       
   212                 {
       
   213                 break;
       
   214                 }
       
   215             }
       
   216         
       
   217         if ( n >= 1 )
       
   218             {
       
   219             ptr[1].Set( buffer.Left( newlines[0] ) );
       
   220             }
       
   221         if ( n >= 2 )
       
   222             {
       
   223             ptr[2].Set( buffer.Mid( newlines[0] + 1, newlines[1] - newlines[0] - 1 ) );
       
   224             }
       
   225         if ( n >= 3 )
       
   226             {
       
   227             ptr[3].Set( buffer.Mid( newlines[1] + 1, newlines[2] - newlines[1] - 1 ) );
       
   228             }
       
   229         }
       
   230     
       
   231     // draw texts
       
   232     aGc.SetBrushStyle(CGraphicsContext::ENullBrush);
       
   233     
       
   234     for ( i = 0; i < KHgDrawUtilsMaxNumberOfLines; i++ )
       
   235         {
       
   236         line[i].DrawText( aGc, ptr[i], EFalse, aColor );
       
   237         }
       
   238 
       
   239     delete firstLine;
       
   240     }
       
   241 
       
   242 void DrawEmptyListImpl_real( const TRect &aClientRect,
       
   243                              CGraphicsContext &aGc,
       
   244                              TPtrC aText,
       
   245                              const TRgb& aColor  )
       
   246     {
       
   247     if ( !aText.Length() )
       
   248         {
       
   249         return;
       
   250         }
       
   251 
       
   252     HBufC* hbuf = HBufC::New( aText.Size() + 3 * ( KAknBidiExtraSpacePerLine  +1 )
       
   253                               + 10 );  // reserve space for newlines
       
   254     if ( !hbuf )
       
   255         { // can't really do anything
       
   256         return;
       
   257         }
       
   258 
       
   259     TPtr buffer(hbuf->Des());
       
   260     
       
   261     /*
       
   262     * input text can be either
       
   263     * - "line1"
       
   264     * - "line1 which will be wrapped to 2 lines and truncated with..."
       
   265     * - "line1\nline2"
       
   266     * - "line1\nMany other lines which will be wrapped to several lines"
       
   267     *
       
   268     * there are 3 layouts
       
   269     * - 1 line with big font,
       
   270     * - 2 lines with big font
       
   271     * - 1 line with big font + 1..3 lines with small font (not for popup lists)
       
   272     *
       
   273     *  so first we need to check if given text has a newline,
       
   274     *  if so, then we need to check if given text fits to 2 lines or
       
   275     *  should it be split to several small font lines
       
   276     */
       
   277 
       
   278     TInt i, n;
       
   279     n = 0;
       
   280     for (i = 0; i < aText.Length(); i ++)
       
   281         {
       
   282         if ( aText[i] == '\n' )
       
   283             {
       
   284             n++;
       
   285             }
       
   286         }
       
   287 
       
   288     
       
   289     TAknTextComponentLayout layout1( AknLayoutScalable_Avkon::main_pane_empty_t1( 0 ) );
       
   290     TAknTextComponentLayout layout2( AknLayoutScalable_Avkon::main_pane_empty_t2( 0 ) );
       
   291     TAknLayoutText line1;
       
   292     TAknLayoutText line2;
       
   293 
       
   294     line1.LayoutText( aClientRect, layout1 );
       
   295     TInt line1length = line1.TextRect().Size().iWidth;
       
   296 
       
   297     line2.LayoutText( aClientRect, layout2 ); 
       
   298     TInt line2length = line2.TextRect().Size().iWidth;
       
   299 
       
   300     const CFont *font = line1.Font();
       
   301 
       
   302     if ( n == 0 )
       
   303         { // one line, or one line which will be wrapped to two
       
   304         DrawEmptyListImpl_real_DrawUpToTwoLines( aGc, aText, line1, line2,
       
   305                                                  line1length, line2length,
       
   306                                                  font, aColor, buffer );
       
   307         delete hbuf;
       
   308         return;
       
   309         }
       
   310     
       
   311     TRAPD( error,
       
   312         {
       
   313         CArrayFix<TInt>* wrapWidthArray = new( ELeave ) CArrayFixFlat<TInt>(KHgDrawUtilsGranularity);
       
   314         CleanupStack::PushL( wrapWidthArray );
       
   315 
       
   316         wrapWidthArray->AppendL( line1length );
       
   317         wrapWidthArray->AppendL( line2length );
       
   318         wrapWidthArray->AppendL( line2length ); // allow wrap to 3 lines
       
   319         
       
   320         AknBidiTextUtils::ConvertToVisualAndWrapToStringL(
       
   321             aText, *wrapWidthArray, *font, buffer, ETrue );
       
   322 
       
   323         CleanupStack::PopAndDestroy( wrapWidthArray ); // wrapWidthArray
       
   324         } ); // TRAP end
       
   325 
       
   326 
       
   327     n = 0;
       
   328     for ( i = 0; i < buffer.Length(); i ++)
       
   329         {
       
   330         if (buffer[i] == '\n')
       
   331             {
       
   332             n++;
       
   333             }
       
   334         }
       
   335 
       
   336     // wrapping adds a \n to end of each line --> n < 3
       
   337     // there is no layout for empty popuplist
       
   338     if ( error != KErrNone || n < 3 )
       
   339         { // 2 lines which fit to 2 line space
       
   340         DrawEmptyListImpl_real_DrawUpToTwoLines( aGc, aText, line1, line2,
       
   341                                                  line1length, line2length,
       
   342                                                  font, aColor, buffer );
       
   343         }
       
   344     else
       
   345         { // 1 line with big font + 1..3 lines with small font
       
   346         DrawEmptyListImpl_real_DrawMoreThanTwoLines( aClientRect, aGc, aText, aColor, buffer );
       
   347         }
       
   348 
       
   349     delete hbuf;
       
   350     }
       
   351 
       
   352 void CHgDrawUtils::DrawEmptyText(
       
   353         CWindowGc& aGc, 
       
   354         const TRect& aRect,
       
   355         const TDesC& aText,
       
   356         const TRgb& aColor 
       
   357         ) const
       
   358     {
       
   359     DrawEmptyListImpl_real(aRect, aGc, aText, aColor);
       
   360     }
       
   361 
       
   362 // -----------------------------------------------------------------------------
       
   363 // CHgScroller::DrawImage()
       
   364 // -----------------------------------------------------------------------------
       
   365 //
       
   366 void CHgDrawUtils::DrawImage(
       
   367         CWindowGc& aGc, 
       
   368         const TRect& aRect,
       
   369         const TAknWindowComponentLayout& aLayout,
       
   370         const CGulIcon& aIcon
       
   371         ) const
       
   372     {
       
   373     TAknLayoutRect image;
       
   374     image.LayoutRect(aRect, aLayout);
       
   375 //    image.DrawImage(aGc, aIcon.Bitmap(), aIcon.Mask());
       
   376     TSize slotSize(image.Rect().Size());
       
   377     TPoint cropPoint(0,0);
       
   378     TPoint toTl(image.Rect().iTl);
       
   379     if( aIcon.Bitmap() && aIcon.Bitmap()->SizeInPixels() != slotSize )
       
   380         {
       
   381         TSize bitmapSize( aIcon.Bitmap()->SizeInPixels() );
       
   382         if( bitmapSize.iWidth != slotSize.iWidth )
       
   383             {
       
   384             if( bitmapSize.iWidth < slotSize.iWidth )
       
   385                 {
       
   386                 // Bitmap smaller than slot -> move draw position
       
   387                 toTl.iX += ( slotSize.iWidth - bitmapSize.iWidth )/2;
       
   388                 }
       
   389             else
       
   390                 {
       
   391                 // Slot smaller than bitmap -> move crop rect position
       
   392                 cropPoint.iX += ( bitmapSize.iWidth - slotSize.iWidth )/2;
       
   393                 }
       
   394             }
       
   395         
       
   396         if( bitmapSize.iHeight != slotSize.iHeight )
       
   397             {
       
   398             if( bitmapSize.iHeight < slotSize.iHeight )
       
   399                 {
       
   400                 // Bitmap smaller than slot -> move draw position
       
   401                 toTl.iY += ( slotSize.iHeight - bitmapSize.iHeight )/2;
       
   402                 }
       
   403             else
       
   404                 {
       
   405                 // Slot smaller than bitmap -> move crop rect position
       
   406                 cropPoint.iY += ( bitmapSize.iHeight - slotSize.iHeight )/2;
       
   407                 }
       
   408             }
       
   409         }
       
   410 
       
   411     TRect cropRect(cropPoint, slotSize);
       
   412     
       
   413     if (aIcon.Mask()) 
       
   414         { 
       
   415         aGc.BitBltMasked(toTl, aIcon.Bitmap(), cropRect, aIcon.Mask(), ETrue); 
       
   416         }
       
   417      else
       
   418         {
       
   419         aGc.BitBlt(toTl, aIcon.Bitmap(), cropRect);
       
   420         }
       
   421     }
       
   422 
       
   423 // -----------------------------------------------------------------------------
       
   424 // CHgScroller::DrawText()
       
   425 // -----------------------------------------------------------------------------
       
   426 //
       
   427 void CHgDrawUtils::DrawText(
       
   428         CWindowGc& aGc, 
       
   429         const TRect& aRect,
       
   430         const TAknTextComponentLayout& aLayout,
       
   431         const TDesC& aText,
       
   432         const TRgb& aColor
       
   433         ) const
       
   434     {
       
   435     TAknLayoutText textLayout;
       
   436     textLayout.LayoutText(aRect, aLayout.LayoutLine());
       
   437     textLayout.DrawText(aGc, aText, ETrue, aColor );
       
   438     }
       
   439 
       
   440 // -----------------------------------------------------------------------------
       
   441 // CHgScroller::DrawTextMarquee()
       
   442 // -----------------------------------------------------------------------------
       
   443 //
       
   444 void CHgDrawUtils::DrawTextMarquee(
       
   445         CWindowGc& aGc, 
       
   446         const TRect& aRect,
       
   447         const TAknTextComponentLayout& aLayout,
       
   448         const TDesC& aText,
       
   449         const TRgb& aColor,
       
   450         const TInt& aMarqueeLine
       
   451         )
       
   452     {
       
   453     TBool drawn = EFalse;
       
   454     
       
   455     if( iMarqueeLine == aMarqueeLine)
       
   456         
       
   457         {
       
   458         if( iMarquee->DrawText(
       
   459                 aGc, 
       
   460                 aRect, 
       
   461                 aLayout.LayoutLine(), 
       
   462                 aText,
       
   463                 aColor))
       
   464             {
       
   465             iMarquee->Reset();
       
   466             iMarqueeLine++;
       
   467             }
       
   468         else
       
   469             {
       
   470             drawn = ETrue;
       
   471             }
       
   472         }
       
   473 
       
   474     if(!drawn)
       
   475         {
       
   476         DrawText(aGc, aRect, aLayout, aText, aColor);
       
   477         }
       
   478     }
       
   479 
       
   480 
       
   481 CHgDrawUtils::CHgDrawUtils()
       
   482     {
       
   483     
       
   484     }
       
   485 
       
   486 void CHgDrawUtils::ConstructL( TCallBack& aMarqueeCallback )
       
   487     {
       
   488     iMarquee = CHgMarquee::NewL();
       
   489     iMarquee->SetRedrawCallBack( aMarqueeCallback );
       
   490     }
       
   491 
       
   492 void CHgDrawUtils::ResetMarquee()
       
   493     {
       
   494     if(iMarquee)
       
   495         {
       
   496         iMarquee->Reset();
       
   497         iMarqueeLine = 0;
       
   498         }
       
   499     }
       
   500 
       
   501 void CHgDrawUtils::EnableMarquee( TBool aEnable )
       
   502     {
       
   503     iMarquee->EnableMarquee(aEnable);
       
   504     }