phoneuis/easydialing/src/easydialinglistboxdata.cpp
branchRCL_3
changeset 3 8871b09be73b
child 4 24062c24fe38
equal deleted inserted replaced
2:c84cf270c54f 3:8871b09be73b
       
     1 /*
       
     2 * Copyright (c) 2010 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:  Easy dialing list box data.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 
       
    21 #include "easydialinglistboxdata.h"
       
    22 #include "easydialinglistbox.h"
       
    23 #include "easydialinglistboxview.h"
       
    24 #include "easydialinglistboxitemdrawer.h"
       
    25 #include "easydialingpanics.h"
       
    26 
       
    27 #include "easydialingcontactdatamanager.h"
       
    28 #include <easydialing.mbg>
       
    29 #include <phonebook2.mbg>
       
    30 #include <phonebook2ece.mbg>
       
    31 
       
    32 // AvKON and drawing header files
       
    33 #include <aknlayoutscalable_avkon.cdl.h>
       
    34 #include <akniconconfig.h>
       
    35 #include <gulicon.h>
       
    36 #include <AknBidiTextUtils.h>
       
    37 #include <bidivisual.h>
       
    38 
       
    39 #include <aknlistloadertfx.h>
       
    40 #include <aknlistboxtfxinternal.h>
       
    41 #include <aknlistboxtfx.h>
       
    42 
       
    43 #include <akntransitionutils.h>
       
    44 #include <avkon.rsg>
       
    45 
       
    46 
       
    47 // EXTERNAL DATA STRUCTURES
       
    48 
       
    49 // EXTERNAL FUNCTION PROTOTYPES  
       
    50 
       
    51 // CONSTANTS
       
    52 
       
    53 // KHighlightSeparatorChar is character used to separate matching and non-matching
       
    54 // portions of contact names. 
       
    55 const TInt KHighlightSeparatorChar = 0x1F;
       
    56 _LIT( KHighlightSeparatorCharAsLit, "\x1F" );
       
    57 
       
    58 
       
    59 // KContactNameFontHeightPercent is contact name font height relative to list item height.
       
    60 const TInt KContactNameFontHeightPercent = 35;
       
    61 
       
    62 // KCompanyNameFontHeightPercent is company name font height relative to list item height.
       
    63 const TInt KCompanyNameFontHeightPercent = 30;
       
    64 
       
    65 // KTextBoundingBoxHeightPercent gives the text bounding box height in percentages 
       
    66 // relative to font height. This must be over 100, or part of the text cuts off.
       
    67 const TInt KTextBoundingBoxHeightPercent = 120;
       
    68 
       
    69 // KTextPlacementPercent controls how text is placed vertically within its bounding box. 
       
    70 // The value is between 0 and 100. 0 means in top part, 50 mean in the middle, 100 means in the
       
    71 // bottom. 
       
    72 const TInt KTextPlacementPercent = 70;
       
    73 
       
    74 // KMarginXPercent defines a width of horizontal margin used in many places. In relation to
       
    75 // the width of the item rectangle.
       
    76 const TInt KMarginXPercent = 2;
       
    77 
       
    78 // KMarginYPercent defines a height of vertical margin. In relation to
       
    79 // the height of the item rectangle. Currently used only with contact thumbnail.
       
    80 const TInt KMarginYPercent = 4;
       
    81 
       
    82 // KContacNameYOffsetPercent defines the vertical placement of contact name in relation to 
       
    83 // item height.
       
    84 const TInt KContactNameYOffsetPercent = 10;
       
    85 
       
    86 // KCompanyNameYOffsetPercent defines the vertical placement of company name in relation to 
       
    87 // item height.
       
    88 const TInt KCompanyNameYOffsetPercent = 60;
       
    89 
       
    90 // KArrowIconSizePercent defines the size of action menu icon relative to item height.
       
    91 const TInt KArrowIconSizePercent = 20;
       
    92 
       
    93 // KMatchingTextMarginInPixels the absolute pixel width of highlight margin. Highlight margin
       
    94 // is an extra space in highlight boundary to make the text look less crowded.
       
    95 const TInt KMatchingTextMarginInPixels = 3;
       
    96 
       
    97 // KMatchingTextMarginInPixels is the absolute pixel value for rounding used in highlight 
       
    98 // rectangle.
       
    99 const TInt KHighligthRectangleRoundingYInPixels = 4;
       
   100 
       
   101 // KThumbnailAspectRatio is the aspect ratio of contact thumbnail in percents. 133 for instance
       
   102 // is 4:3 aspect ration.
       
   103 const TInt KThumbnailAspectRatio = 133;
       
   104 
       
   105 const TInt KCent = 100;
       
   106 
       
   107 const TInt KMaxRunInfoArrayCount = 20;
       
   108 
       
   109 // IMPLEMENTATION SPECIFIC CONSTANTS
       
   110 // The mif file from where you would like to show the 
       
   111 // icon on the screen.
       
   112 _LIT( KFavouriteIconBitmapFile, "\\resource\\apps\\phonebook2.mif" );
       
   113 _LIT( KEasyDialingBitmapFile, "\\resource\\apps\\easydialing.mif" );
       
   114 _LIT( KPhonebook2EceBitmapFile, "\\resource\\apps\\phonebook2ece.mif" );
       
   115 
       
   116 // MACROS
       
   117 
       
   118 // LOCAL CONSTANTS AND MACROS
       
   119 
       
   120 // MODULE DATA STRUCTURES
       
   121 
       
   122 // GLOBAL FUNCTION PROTOTYPES
       
   123 TRect ContactImageBoundingBox( const TRect& aItemRect );
       
   124 TRect ArrowIconBoundingBox(const TRect& aItemRect);
       
   125 
       
   126 // LOCAL FUNCTION PROTOTYPES
       
   127 static TRect ContactNameBoundingBox(
       
   128         const TRect& aItemRect, 
       
   129         const CFont* aContactNameFont, 
       
   130         TBool aIsCurrentItem,
       
   131         TBool aIsFavourite, 
       
   132         TBool aThumbnailsShown );
       
   133 static TRect CompanyNameBoundingBox(
       
   134         const TRect& aItemRect, 
       
   135         const CFont* aCompanyNameFont, 
       
   136         TBool aIsCurrentItem,
       
   137         TBool aThumbnailsShown );
       
   138 static TRect FavouriteIconBoundingBox( const TRect& aContactNameBoundingBox, TInt aTextWidth );
       
   139 static TRect MirrorLayoutBoundingBox(const TRect& aSourceRect, TRect& aBoundingBoxRect);
       
   140 static TInt BaseLineOffset( const TRect& aTextBoundingBox, const CFont* aFont );
       
   141 static TBool ContainsRightToLeftText( const TDesC& aDesc );
       
   142 static TInt HighlightSeparatorCount( const TDesC& aText );
       
   143 static HBufC* ConvertToVisualAndClipLC( const TDesC& aText, const CFont& aFont, const TRect& aBoundingBox ); 
       
   144 
       
   145 static void ClipTextToWidth(
       
   146         TDes& aText,
       
   147         const CFont& aFont,
       
   148         TInt aMaxWidthInPixels,
       
   149         TBool& aMatch );
       
   150 
       
   151 static TBool DrawPieceOfText(
       
   152         const TRect& aBoundingBox,
       
   153         TInt& aXOffset,
       
   154         CWindowGc &aGc, 
       
   155         const TDesC& aText,
       
   156         TBool aMatch,
       
   157         const CFont* aFont,
       
   158         const CEasyDialingListBoxData::TExtendedColors& aColors,
       
   159         TBool aHighLight);
       
   160 
       
   161 static TInt DrawTextWithMatchHighlightL(
       
   162         const TRect& aBoundingBox,
       
   163         CWindowGc &aGc, 
       
   164         const TDesC& aText,
       
   165         const CFont* aFont,
       
   166         const CEasyDialingListBoxData::TExtendedColors& aColors,
       
   167         TBool aHighLight );
       
   168 
       
   169 static TInt CalculateTextWidth(
       
   170         const TRect& aBoundingBox,
       
   171         const TDesC& aText,
       
   172         const CFont* aFont );
       
   173 
       
   174 static TBool CalculateTextPieceWidth(
       
   175         const TRect& aBoundingBox,
       
   176         TInt& aXOffset,
       
   177         const TDesC& aText,
       
   178         TBool aMatch,
       
   179         const CFont* aFont );
       
   180 
       
   181 // FORWARD DECLARATIONS
       
   182 
       
   183 
       
   184 /*
       
   185  * ==============================================================================
       
   186  * 
       
   187  * 
       
   188  * class EasyDialingListBoxData::TExtendedColors
       
   189  * 
       
   190  * 
       
   191  * ==============================================================================
       
   192  */
       
   193 
       
   194 
       
   195 // -----------------------------------------------------------------------------
       
   196 // TExtendedColors
       
   197 // 
       
   198 // -----------------------------------------------------------------------------
       
   199 //       
       
   200 CEasyDialingListBoxData::TExtendedColors::TExtendedColors() :
       
   201 CFormattedCellListBoxData::TColors(),
       
   202 iMatchingText(KRgbBlack),
       
   203 iMatchingBack(KRgbDarkYellow)
       
   204     {
       
   205     }
       
   206 
       
   207 
       
   208 /*
       
   209  * ==============================================================================
       
   210  * 
       
   211  * 
       
   212  * class CEasyDialingListBoxData
       
   213  * 
       
   214  * 
       
   215  * ==============================================================================
       
   216  */
       
   217 
       
   218 
       
   219 // -----------------------------------------------------------------------------
       
   220 // CEasyDialingListBoxData
       
   221 // 
       
   222 // -----------------------------------------------------------------------------
       
   223 //       
       
   224 CEasyDialingListBoxData::CEasyDialingListBoxData() :
       
   225 CFormattedCellListBoxData()
       
   226     {
       
   227     }
       
   228 
       
   229 // -----------------------------------------------------------------------------
       
   230 // Destructor
       
   231 // 
       
   232 // -----------------------------------------------------------------------------
       
   233 //       
       
   234 CEasyDialingListBoxData::~CEasyDialingListBoxData()
       
   235     {
       
   236     // Release fonts. ReleaseFont function can cope with null pointer
       
   237     // so we don't need to null check them.
       
   238     CWsScreenDevice& screenDev = *( CEikonEnv::Static()->ScreenDevice() );
       
   239     screenDev.ReleaseFont( iContactNameFont );
       
   240     screenDev.ReleaseFont( iCompanyNameFont );
       
   241     
       
   242     delete iArrowPointingRight;
       
   243     delete iArrowPointingLeft;
       
   244     delete iColorBitmap;
       
   245     delete iDummyThumbnail;
       
   246     
       
   247     iContactDataManager = NULL;
       
   248     }
       
   249 
       
   250 // -----------------------------------------------------------------------------
       
   251 // NewL
       
   252 // 
       
   253 // -----------------------------------------------------------------------------
       
   254 //       
       
   255 CEasyDialingListBoxData* CEasyDialingListBoxData::NewL()
       
   256     {
       
   257     CEasyDialingListBoxData* self = new (ELeave) CEasyDialingListBoxData();
       
   258     
       
   259     CleanupStack::PushL( self );
       
   260     self->ConstructLD();
       
   261     CleanupStack::Pop( self );
       
   262  
       
   263     return self;
       
   264     }
       
   265 
       
   266 
       
   267 // -----------------------------------------------------------------------------
       
   268 // DrawData
       
   269 // 
       
   270 // -----------------------------------------------------------------------------
       
   271 //       
       
   272 void CEasyDialingListBoxData::DrawData(
       
   273     const TListItemProperties& aProperties, 
       
   274     CWindowGc& aGc,
       
   275     const TDesC* aText,
       
   276     const TRect& aRect,
       
   277     TBool aHighlight,
       
   278     const TExtendedColors& aColors ) const
       
   279     {
       
   280     const TRect &aItemRect = aRect;
       
   281     
       
   282     if ( aHighlight )
       
   283         {
       
   284         DrawHighlight( aGc, aItemRect );
       
   285         }
       
   286     
       
   287     // Draw the actual items.
       
   288     DrawDataFormatted( aProperties, aGc, aText, aItemRect, 
       
   289             aHighlight, aColors );
       
   290     }
       
   291 
       
   292 
       
   293 // -----------------------------------------------------------------------------
       
   294 // ConstructLD
       
   295 // 
       
   296 // -----------------------------------------------------------------------------
       
   297 //       
       
   298 void CEasyDialingListBoxData::ConstructLD()
       
   299     {
       
   300     CFormattedCellListBoxData::ConstructLD();
       
   301     
       
   302     // EasyDialing bitmap file is attempted to be read from the same directory where the
       
   303     // executed binary is located
       
   304     TFileName dllFileName;
       
   305     Dll::FileName( dllFileName );
       
   306      
       
   307     TParse parse;
       
   308     User::LeaveIfError(parse.Set(KEasyDialingBitmapFile, &dllFileName, NULL));
       
   309     TFileName bitmapFileName(parse.FullName());
       
   310       
       
   311     CFbsBitmap* bm;
       
   312     CFbsBitmap* mask;
       
   313     
       
   314     // iArrowPointingLeft is the icon displayed for the selected item in EasyDialingListBox
       
   315     AknIconUtils::CreateIconL( bm, mask, bitmapFileName, EMbmEasydialingQgn_indi_org_arrow_left, 
       
   316             EMbmEasydialingQgn_indi_org_arrow_left_mask );
       
   317 
       
   318     iArrowPointingLeft = CGulIcon::NewL( bm, mask );
       
   319 
       
   320     AknIconUtils::CreateIconL( bm, mask, bitmapFileName, EMbmEasydialingQgn_indi_org_arrow_right, 
       
   321             EMbmEasydialingQgn_indi_org_arrow_right_mask );
       
   322 
       
   323     iArrowPointingRight = CGulIcon::NewL( bm, mask );
       
   324 
       
   325     // Only mask for the icons are used. iColorBitmap is used for making the icon 
       
   326     // to follow text color changes according to skin.
       
   327     iColorBitmap = new (ELeave) CFbsBitmap;
       
   328 
       
   329     // Contact default thumbnail is not available in themes. It is read from phonebook resource. 
       
   330     AknIconUtils::CreateIconL( bm, mask, KPhonebook2EceBitmapFile,
       
   331             EMbmPhonebook2eceQgn_prop_pb_thumb_unknown, EMbmPhonebook2eceQgn_prop_pb_thumb_unknown_mask );
       
   332     iDummyThumbnail = CGulIcon::NewL( bm, mask );
       
   333 
       
   334     }
       
   335 
       
   336 
       
   337 // -----------------------------------------------------------------------------
       
   338 // DrawHighlight
       
   339 // 
       
   340 // -----------------------------------------------------------------------------
       
   341 //       
       
   342 void CEasyDialingListBoxData::DrawHighlight( CWindowGc &aGc, const TRect &aItemRect ) const
       
   343     {
       
   344     MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( &aGc );
       
   345     if ( transApi )
       
   346         {
       
   347         transApi->Invalidate(MAknListBoxTfxInternal::EListHighlight );
       
   348         transApi->BeginRedraw( MAknListBoxTfxInternal::EListHighlight, aItemRect );
       
   349         transApi->StartDrawing( MAknListBoxTfxInternal::EListHighlight );
       
   350         aGc.SetClippingRect( iControl->Rect() );
       
   351         }
       
   352 
       
   353     TAknLayoutRect outerRect;
       
   354     TAknLayoutRect innerRect;
       
   355     outerRect.LayoutRect( aItemRect, TAknWindowComponentLayout::Compose(
       
   356             AknLayoutScalable_Avkon::list_highlight_pane_cp1(),
       
   357             AknLayoutScalable_Avkon::list_highlight_pane_g10_cp1() ).LayoutLine() );
       
   358     innerRect.LayoutRect( aItemRect, TAknWindowComponentLayout::Compose(
       
   359             AknLayoutScalable_Avkon::list_highlight_pane_cp1(),
       
   360             AknLayoutScalable_Avkon::list_highlight_pane_g1_cp1() ).LayoutLine() );
       
   361     MAknsControlContext *cc = AknsDrawUtils::ControlContext( Control() );
       
   362 
       
   363     if ( !cc ) 
       
   364         {
       
   365         cc = SkinBackgroundContext();
       
   366         }
       
   367 
       
   368     if ( cc )
       
   369         {
       
   370         aGc.SetPenStyle( CGraphicsContext::ENullPen );
       
   371         AknsDrawUtils::DrawFrame(
       
   372                 AknsUtils::SkinInstance(), 
       
   373                 aGc,
       
   374                 outerRect.Rect(),
       
   375                 innerRect.Rect(),
       
   376                 KAknsIIDQsnFrList,
       
   377                 KAknsIIDQsnFrListCenter );
       
   378         }
       
   379 
       
   380     if ( transApi )
       
   381         {
       
   382         aGc.CancelClippingRect();
       
   383         transApi->StopDrawing();
       
   384         transApi->EndRedraw( MAknListBoxTfxInternal::EListHighlight );
       
   385         }
       
   386     }
       
   387 
       
   388 
       
   389 // -----------------------------------------------------------------------------
       
   390 // DrawDataFormatted
       
   391 // 
       
   392 // -----------------------------------------------------------------------------
       
   393 // 
       
   394 // ToDo: SetSize function could be called once for all static data in SizeChanged.
       
   395 // Applies at least to icons.
       
   396 void CEasyDialingListBoxData::DrawDataFormatted( 
       
   397         TListItemProperties /* aProperties */,
       
   398         CWindowGc& aGc,
       
   399         const TDesC* aText,
       
   400         const TRect& aItemRect,
       
   401         TBool aHighlight,
       
   402         const TExtendedColors& aColors ) const
       
   403     {
       
   404     TPtrC cellText;
       
   405 
       
   406     TInt error = TextUtils::ColumnText( cellText , 0, aText );
       
   407     __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) );
       
   408     __ASSERT_DEBUG( iContactNameFont, EasyDialingPanic( EEasyDialingNoFontFound ) );
       
   409     __ASSERT_DEBUG( iCompanyNameFont, EasyDialingPanic( EEasyDialingNoFontFound ) );
       
   410     
       
   411     MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( &aGc );
       
   412     if ( transApi )
       
   413         {
       
   414         transApi->StartDrawing( MAknListBoxTfxInternal::EListItem );
       
   415         if ( transApi->EffectsDisabled() )
       
   416             {
       
   417             aGc.SetClippingRect( iControl->Rect() );
       
   418             }
       
   419         }
       
   420 
       
   421     TRect boundingBox = ContactImageBoundingBox( aItemRect );
       
   422     if ( AknLayoutUtils::LayoutMirrored() )
       
   423         {
       
   424         boundingBox = MirrorLayoutBoundingBox( aItemRect, boundingBox );
       
   425         }
       
   426     
       
   427     //Draws the Contact Thumbnail Icon if exists else draws the dummy contact thumbnail
       
   428     TBool fav = ContactThumbnailDrawing( aGc, boundingBox, cellText );   
       
   429 
       
   430     error = TextUtils::ColumnText( cellText , 1, aText );
       
   431     __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) );
       
   432 
       
   433     boundingBox = ContactNameBoundingBox( aItemRect,
       
   434                                           iContactNameFont,
       
   435                                           aHighlight,
       
   436                                           fav,
       
   437                                           iContactDataManager->GetContactThumbnailSetting() );
       
   438     TRect nameRectUnMirrored = boundingBox; // used for favourite star drawing
       
   439 
       
   440     if ( AknLayoutUtils::LayoutMirrored() )
       
   441         {
       
   442         boundingBox = MirrorLayoutBoundingBox( aItemRect, boundingBox );
       
   443         }
       
   444 
       
   445     // favourite icon size is set the same as contact name bounding box height.
       
   446     TInt favouriteIconSize = boundingBox.Height();
       
   447     
       
   448     TRect arrowRect = ArrowIconBoundingBox( aItemRect );
       
   449     if ( AknLayoutUtils::LayoutMirrored() )
       
   450         {
       
   451         arrowRect = MirrorLayoutBoundingBox( aItemRect, arrowRect );
       
   452         }
       
   453     
       
   454     // Draw arrow icon if the item is in focus.
       
   455     if ( aHighlight )
       
   456         {
       
   457         DrawArrowIcon( aGc, arrowRect );
       
   458         }
       
   459 
       
   460     TInt textWidth( 0 );
       
   461     TInt err( KErrNone );
       
   462     TRAP( err, textWidth = DrawTextWithMatchHighlightL(
       
   463             boundingBox, aGc, cellText, iContactNameFont, aColors, aHighlight ) );
       
   464 
       
   465     if ( !err && TextUtils::ColumnText( cellText , 2, aText ) == KErrNone ) 
       
   466         {
       
   467         TRect companyNameBoundingBox = CompanyNameBoundingBox( 
       
   468                 aItemRect, iCompanyNameFont, aHighlight, iContactDataManager->GetContactThumbnailSetting() );
       
   469         if ( AknLayoutUtils::LayoutMirrored() )
       
   470             {
       
   471             companyNameBoundingBox = MirrorLayoutBoundingBox( aItemRect, companyNameBoundingBox );
       
   472             }
       
   473         TRAP( err, DrawTextWithMatchHighlightL(
       
   474                 companyNameBoundingBox, aGc, cellText, iCompanyNameFont, aColors, aHighlight ) );
       
   475         }
       
   476 
       
   477     if ( !err && fav )
       
   478         {
       
   479         // Draws the Favourite Icon
       
   480         DrawFavouriteIcon( aGc, nameRectUnMirrored, textWidth, aItemRect );
       
   481         }
       
   482     
       
   483     if ( transApi )
       
   484         {
       
   485         aGc.CancelClippingRect();
       
   486         transApi->StopDrawing();
       
   487         }
       
   488     }
       
   489 
       
   490 // -----------------------------------------------------------------------------
       
   491 // ContactThumbnailDrawing
       
   492 // 
       
   493 // Draws the Contact Thumbnail Icon if any else draws the dummy contact thumbnail
       
   494 // -----------------------------------------------------------------------------
       
   495 
       
   496 TBool CEasyDialingListBoxData::ContactThumbnailDrawing(CWindowGc& aGc, TRect aBoundingBox, TPtrC aCellText) const
       
   497     {
       
   498     TBool fav(EFalse);
       
   499     CFbsBitmap* thumbnail(NULL);
       
   500     TBool isLoaded = iContactDataManager->GetThumbnailAndFav(aCellText, thumbnail, fav);
       
   501     if ( isLoaded && thumbnail )
       
   502         {
       
   503         // center the thumbnail in its rect
       
   504         TSize size(thumbnail->SizeInPixels());
       
   505         TInt xOffset = (aBoundingBox.Width() - size.iWidth) / 2;
       
   506         TInt yOffset = (aBoundingBox.Height() - size.iHeight) / 2;
       
   507         TPoint tl(aBoundingBox.iTl.iX + xOffset, aBoundingBox.iTl.iY + yOffset);
       
   508         TRect sourceRect( TPoint(0,0),size);
       
   509         aGc.BitBlt(tl, thumbnail, sourceRect);
       
   510         }
       
   511     else if ( isLoaded && iContactDataManager->GetContactThumbnailSetting() )
       
   512         {
       
   513         // draw dummy thumnbnail, but only if we know that the contact doesn't
       
   514         // have a thumbnail, and thumbnail drawing is enabled.
       
   515         AknIconUtils::SetSize(iDummyThumbnail->Bitmap(), aBoundingBox.Size());
       
   516         AknIconUtils::SetSize(iDummyThumbnail->Mask(), aBoundingBox.Size());
       
   517         aGc.BitBltMasked( aBoundingBox.iTl, iDummyThumbnail->Bitmap(),
       
   518                 TRect( TPoint(0,0), aBoundingBox.Size() ), 
       
   519                 iDummyThumbnail->Mask(), ETrue );
       
   520         }
       
   521     return fav;
       
   522     }
       
   523 
       
   524 
       
   525 // -----------------------------------------------------------------------------
       
   526 // DrawArrowIcon
       
   527 //  Draws the Action Menu 
       
   528 // -----------------------------------------------------------------------------
       
   529 void CEasyDialingListBoxData::DrawArrowIcon( 
       
   530         CWindowGc& aGc, TRect aArrowRect) const
       
   531     {
       
   532     // Action Menu Arrow for opening the Action Menu
       
   533     if ( AknLayoutUtils::LayoutMirrored() )
       
   534         {
       
   535         // For mirrored layout the UI logic is mirrored as well
       
   536         AknIconUtils::SetSize( iArrowPointingLeft->Mask(), aArrowRect.Size() );
       
   537         aGc.BitBltMasked( aArrowRect.iTl, iColorBitmap,
       
   538                 TRect( TPoint(0,0), aArrowRect.Size() ), 
       
   539                 iArrowPointingLeft->Mask(), ETrue );
       
   540 
       
   541         }
       
   542     else
       
   543         {
       
   544         AknIconUtils::SetSize( iArrowPointingRight->Mask(), aArrowRect.Size() );
       
   545         aGc.BitBltMasked( aArrowRect.iTl, iColorBitmap,
       
   546                 TRect( TPoint(0,0), aArrowRect.Size() ), 
       
   547                 iArrowPointingRight->Mask(), ETrue );
       
   548         }
       
   549     }
       
   550 
       
   551 // -----------------------------------------------------------------------------
       
   552 // DrawFavouriteIcon
       
   553 // 
       
   554 // Draws the Favourite Icon
       
   555 // -----------------------------------------------------------------------------
       
   556 void CEasyDialingListBoxData::DrawFavouriteIcon(
       
   557         CWindowGc& aGc, 
       
   558          TRect aNameRectUnMirrored,
       
   559          TInt aTextWidth,
       
   560          TRect aEffectiveRect) const
       
   561     {
       
   562     CFbsBitmap* favouriteIcon;
       
   563     CFbsBitmap* favouriteIconMask;
       
   564     TRect favouriteIconBoundingBox;
       
   565 
       
   566     favouriteIconBoundingBox = FavouriteIconBoundingBox( aNameRectUnMirrored, aTextWidth );
       
   567 
       
   568     if ( AknLayoutUtils::LayoutMirrored() )
       
   569         {
       
   570         favouriteIconBoundingBox = MirrorLayoutBoundingBox(aEffectiveRect, favouriteIconBoundingBox);
       
   571         }
       
   572 
       
   573     aGc.SetBrushStyle( CGraphicsContext::ENullBrush );
       
   574     TRect sourceRect( TPoint(0,0), favouriteIconBoundingBox.Size() );
       
   575 
       
   576     if( AknsUtils::SkinInstance()->GetCachedItemData(KAknsIIDQgnFsContactsFavorite) )
       
   577         {
       
   578         AknsDrawUtils::DrawCachedImage( AknsUtils::SkinInstance(), aGc, sourceRect, 
       
   579                 KAknsIIDQgnFsContactsFavorite );
       
   580         }
       
   581     else
       
   582         {
       
   583         // Create the bitmap and mask to draw.
       
   584         TRAP_IGNORE( AknIconUtils::CreateIconL(favouriteIcon, favouriteIconMask, KFavouriteIconBitmapFile, 
       
   585                 EMbmPhonebook2Qgn_prop_pb_topc, EMbmPhonebook2Qgn_prop_pb_topc_mask ));
       
   586 
       
   587         // Set size for the bitmap and mask
       
   588         AknIconUtils::SetSize(favouriteIcon, favouriteIconBoundingBox.Size());
       
   589         AknIconUtils::SetSize(favouriteIconMask, favouriteIconBoundingBox.Size());
       
   590         aGc.BitBltMasked( favouriteIconBoundingBox.iTl , favouriteIcon, sourceRect, favouriteIconMask, ETrue);
       
   591         }
       
   592     }
       
   593 // -----------------------------------------------------------------------------
       
   594 // SetContactDataManager
       
   595 // 
       
   596 // -----------------------------------------------------------------------------
       
   597 // 
       
   598 void CEasyDialingListBoxData::SetContactDataManager(CEasyDialingContactDataManager* aContactDataManager)
       
   599     {
       
   600     iContactDataManager = aContactDataManager;
       
   601     }
       
   602 
       
   603 // -----------------------------------------------------------------------------
       
   604 // HandleItemSizeChange
       
   605 // 
       
   606 // -----------------------------------------------------------------------------
       
   607 //
       
   608 void CEasyDialingListBoxData::HandleItemSizeChange()
       
   609     {
       
   610     TInt height = iControl->ItemHeight();
       
   611     TSize size( height, height );
       
   612     TRAP_IGNORE( UpdateColorBitmapL( size ) );
       
   613     
       
   614     // Obtain fonts.
       
   615     ObtainFonts( height );
       
   616     
       
   617     // TODO: also bounding boxes could be updated and stored here
       
   618     }
       
   619 
       
   620 // -----------------------------------------------------------------------------
       
   621 // ObtainFonts
       
   622 // 
       
   623 // -----------------------------------------------------------------------------
       
   624 //       
       
   625 void CEasyDialingListBoxData::ObtainFonts( TInt aItemHeight )
       
   626     {
       
   627     CWsScreenDevice& screenDev = *( CEikonEnv::Static()->ScreenDevice() );
       
   628     
       
   629     // Release previous fonts. ReleaseFont function can cope with null pointers
       
   630     // so we don't need to null check them.
       
   631     screenDev.ReleaseFont( iContactNameFont );
       
   632     screenDev.ReleaseFont( iCompanyNameFont );
       
   633     
       
   634     // Get a logical font to a basis for our own fonts.
       
   635     const CFont* logicalFont = AknLayoutUtils::FontFromId( EAknLogicalFontSecondaryFont );
       
   636 
       
   637     // Extract font information
       
   638     TFontSpec fontSpec = logicalFont->FontSpecInTwips();
       
   639     
       
   640     // Calculate contact name font height in TWIPs.
       
   641     TInt fontHeightPixels = aItemHeight * KContactNameFontHeightPercent / KCent;
       
   642     TInt fontHeightTwips = screenDev.VerticalPixelsToTwips( fontHeightPixels );
       
   643     
       
   644     // Set height, weight, and posture.
       
   645     fontSpec.iHeight = fontHeightTwips;
       
   646     fontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightBold );
       
   647     fontSpec.iFontStyle.SetPosture( EPostureUpright );
       
   648     
       
   649     // Obtain contact name font
       
   650     TInt err = screenDev.GetNearestFontToDesignHeightInTwips( iContactNameFont, fontSpec );
       
   651     __ASSERT_DEBUG( err == KErrNone, EasyDialingPanic( EEasyDialingNoFontFound ) ); 
       
   652     
       
   653     // Calculate company name font height in TWIPs.
       
   654     fontHeightPixels = aItemHeight * KCompanyNameFontHeightPercent / KCent;
       
   655     fontHeightTwips = screenDev.VerticalPixelsToTwips( fontHeightPixels );
       
   656     fontSpec.iHeight = fontHeightTwips;
       
   657     fontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightNormal );
       
   658     
       
   659     // Obtain company name font.  
       
   660     err = screenDev.GetNearestFontToDesignHeightInTwips( iCompanyNameFont, fontSpec );
       
   661     __ASSERT_DEBUG( err == KErrNone, EasyDialingPanic( EEasyDialingNoFontFound ) ); 
       
   662    }
       
   663 
       
   664 
       
   665 // -----------------------------------------------------------------------------
       
   666 // UpdateColorBitmapL
       
   667 // ColorBitmap is redrawn when UI layout or text color (Theme) changes
       
   668 // -----------------------------------------------------------------------------
       
   669 //       
       
   670 void CEasyDialingListBoxData::UpdateColorBitmapL( const TSize& aSize )
       
   671     {
       
   672     TRgb color;
       
   673     // Get the HighLighted text color in ListBox from the Theme
       
   674     AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), color, 
       
   675                                KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG10 );
       
   676     
       
   677     // Create a bitmap with the similar display mode than what the device currently
       
   678     // uses for using it as an offscreen bitmap
       
   679     AknIconConfig::TPreferredDisplayMode mode;
       
   680     AknIconConfig::PreferredDisplayMode( mode, AknIconConfig::EImageTypeOffscreen );
       
   681     User::LeaveIfError( iColorBitmap->Create( aSize, mode.iBitmapMode ) );
       
   682 
       
   683     // Create a new drawing device and graphics context for enabling drawing to
       
   684     // the offscreen bitmap
       
   685     CFbsBitmapDevice* destinationDevice = CFbsBitmapDevice::NewL( iColorBitmap );
       
   686     CleanupStack::PushL(destinationDevice);
       
   687 
       
   688     CFbsBitGc* destinationGc;
       
   689     User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) );
       
   690 
       
   691     // Set the color and style for pen and brush and draw a rectangle to the
       
   692     // bitmap graphics
       
   693     destinationGc->SetPenColor( color );
       
   694     destinationGc->SetPenStyle( CGraphicsContext::ESolidPen );
       
   695     destinationGc->SetBrushColor( color );
       
   696     destinationGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   697     destinationGc->DrawRect( TRect( TPoint( 0,0 ), aSize ) );
       
   698 
       
   699     // Colorbitmap is ready, cleanup
       
   700     delete destinationGc;    
       
   701     CleanupStack::PopAndDestroy(destinationDevice); 
       
   702     }
       
   703 
       
   704 // -----------------------------------------------------------------------------
       
   705 // SetEDLBXControl
       
   706 // 
       
   707 // -----------------------------------------------------------------------------
       
   708 //       
       
   709 void CEasyDialingListBoxData::SetEDLBXControl(CEasyDialingListBox* aControl)
       
   710     {
       
   711     iControl = aControl;
       
   712     }
       
   713 
       
   714 
       
   715 /*
       
   716  * ==============================================================================
       
   717  * 
       
   718  * Local functions
       
   719  * 
       
   720  * ==============================================================================
       
   721  */
       
   722 
       
   723 
       
   724 // -----------------------------------------------------------------------------
       
   725 // ContactImageBoundingBox
       
   726 // Calculates the area where contact thumbnail is confined
       
   727 // -----------------------------------------------------------------------------
       
   728 //
       
   729 TRect ContactImageBoundingBox(const TRect& aItemRect)
       
   730     {
       
   731     TInt leftMargin = aItemRect.Width() * KMarginXPercent / KCent;
       
   732     TInt topMargin = KMarginYPercent * aItemRect.Height() / KCent;
       
   733     TInt bottomMargin = topMargin;
       
   734     TInt width = ((aItemRect.Height() - topMargin - bottomMargin) * KThumbnailAspectRatio) / KCent;
       
   735 
       
   736     return TRect(
       
   737             aItemRect.iTl.iX + leftMargin,
       
   738             aItemRect.iTl.iY + topMargin,
       
   739             aItemRect.iTl.iX + leftMargin + width,
       
   740             aItemRect.iBr.iY - bottomMargin);  
       
   741     }
       
   742 
       
   743 // -----------------------------------------------------------------------------
       
   744 // ContactNameBoundingBox
       
   745 // Calculates the area to which the contact name and possible match highlights
       
   746 // are confined.
       
   747 //      
       
   748 // -----------------------------------------------------------------------------
       
   749 //
       
   750 static TRect ContactNameBoundingBox(
       
   751         const TRect& aItemRect,
       
   752         const CFont* aContactNameFont,
       
   753         TBool aIsCurrentItem,
       
   754         TBool aIsFavourite,
       
   755         TBool aThumbnailsShown )
       
   756     {
       
   757     // Position X will contain the starting position of text from left side of item rect.
       
   758     TInt positionX = aItemRect.Width() * KMarginXPercent / KCent;
       
   759     
       
   760     if (aThumbnailsShown)
       
   761         {
       
   762         // If contact image is shown, text starts from right side of contact picture + margin.
       
   763         TRect contactImageBoundingBox = ContactImageBoundingBox( aItemRect );
       
   764         positionX += contactImageBoundingBox.Width();
       
   765         positionX += aItemRect.Width() * KMarginXPercent / KCent;
       
   766         }
       
   767     
       
   768     TInt topMargin = KContactNameYOffsetPercent * aItemRect.Height() / KCent;
       
   769     TInt height = KTextBoundingBoxHeightPercent * aContactNameFont->FontMaxHeight() / KCent;
       
   770     TInt rightMargin = KMarginXPercent * aItemRect.Width() / KCent;
       
   771     
       
   772     // Reserve space for communication launcher icon.
       
   773     // Communication launcher icon is shown only id item is highlighted.
       
   774     if ( aIsCurrentItem )
       
   775         {
       
   776         rightMargin += KArrowIconSizePercent * aItemRect.Height() / KCent;
       
   777         }
       
   778     
       
   779     // If item is favourite, reserve space for favourite icon. Icon dimensions are the same as bounding box height.
       
   780     if ( aIsFavourite )
       
   781         {
       
   782         rightMargin += height;
       
   783         }
       
   784     
       
   785     return TRect(
       
   786         aItemRect.iTl.iX + positionX,
       
   787         aItemRect.iTl.iY + topMargin,
       
   788         aItemRect.iTl.iX + aItemRect.Width() - rightMargin,
       
   789         aItemRect.iTl.iY + topMargin + height);
       
   790     }
       
   791 
       
   792 
       
   793 // -----------------------------------------------------------------------------
       
   794 // CompanyNameBoundingBox
       
   795 // Calculates the area to which the company name and possible match highlights
       
   796 // are confined.
       
   797 // -----------------------------------------------------------------------------
       
   798 //
       
   799 static TRect CompanyNameBoundingBox(
       
   800         const TRect& aItemRect, 
       
   801         const CFont* aCompanyNameFont, 
       
   802         TBool aIsCurrentItem,
       
   803         TBool aThumbnailsShown )
       
   804     {
       
   805     // Position X will contain the starting position of text from left side of item rect.
       
   806     TInt positionX = aItemRect.Width() * KMarginXPercent / KCent;
       
   807     
       
   808     if (aThumbnailsShown)
       
   809         {
       
   810         // If contact image is show, text starts from right side of contact picture + margin.
       
   811         TRect contactImageBoundingBox = ContactImageBoundingBox( aItemRect );
       
   812         positionX += contactImageBoundingBox.Width();
       
   813         positionX += aItemRect.Width() * KMarginXPercent / KCent;
       
   814         }
       
   815     
       
   816     TInt topMargin = KCompanyNameYOffsetPercent * aItemRect.Height() / KCent;
       
   817     TInt height = KTextBoundingBoxHeightPercent * aCompanyNameFont->FontMaxHeight() / KCent;
       
   818     TInt rightMargin = KMarginXPercent * aItemRect.Width() / KCent;
       
   819 
       
   820     // Reserve space for communication launcher icon.
       
   821     // Communication launcher icon is shown only id item is highlighted.
       
   822     if ( aIsCurrentItem )
       
   823         {
       
   824         rightMargin += KArrowIconSizePercent * aItemRect.Height() / KCent;
       
   825         }
       
   826     
       
   827     return TRect(
       
   828         aItemRect.iTl.iX + positionX,
       
   829         aItemRect.iTl.iY + topMargin,
       
   830         aItemRect.iTl.iX + aItemRect.Width() - rightMargin,
       
   831         aItemRect.iTl.iY + topMargin + height);
       
   832     }
       
   833 
       
   834 
       
   835 // -----------------------------------------------------------------------------
       
   836 // ArrowIconBoundingBox
       
   837 // Calculates the area to which the action menu icon is drawn.
       
   838 // -----------------------------------------------------------------------------
       
   839 //
       
   840 TRect ArrowIconBoundingBox(const TRect& aItemRect)
       
   841     {
       
   842     TInt iconSize = KArrowIconSizePercent * aItemRect.Height() / KCent;
       
   843     TInt rightMargin = KMarginXPercent * aItemRect.Width() / KCent;
       
   844     TInt positionX = aItemRect.iBr.iX - rightMargin - iconSize;
       
   845     TInt topMargin = ( aItemRect.Height() - iconSize ) / 2; // Icon is vertically centered.
       
   846 
       
   847     return TRect(
       
   848         positionX,
       
   849         aItemRect.iTl.iY + topMargin,
       
   850         positionX + iconSize,
       
   851         aItemRect.iTl.iY + topMargin + iconSize );
       
   852     }
       
   853 
       
   854 
       
   855 // -----------------------------------------------------------------------------
       
   856 // FavouriteIconBoundingBox
       
   857 // Calculates the area to which the favourite icon is drawn.
       
   858 // Because favourite icon is drawn in the same line with contact name,
       
   859 // this function takes contact name bounding box as the parameter, not
       
   860 // the whole item rect. 
       
   861 // -----------------------------------------------------------------------------
       
   862 //
       
   863 static TRect FavouriteIconBoundingBox( const TRect& aContactNameBoundingBox, TInt aTextWidth )
       
   864     {
       
   865     return TRect(
       
   866             aContactNameBoundingBox.iTl.iX + aTextWidth,
       
   867             aContactNameBoundingBox.iTl.iY,
       
   868             aContactNameBoundingBox.iTl.iX + aTextWidth + aContactNameBoundingBox.Height(),
       
   869             aContactNameBoundingBox.iBr.iY);
       
   870     }
       
   871 
       
   872 
       
   873 
       
   874 // -----------------------------------------------------------------------------
       
   875 // BaseLineOffset
       
   876 //
       
   877 // -----------------------------------------------------------------------------
       
   878 //
       
   879 static TInt BaseLineOffset( const TRect& aTextBoundingBox, const CFont* aFont )
       
   880     {
       
   881     TInt fontHeight = aFont->FontMaxHeight();
       
   882     TInt topMargin = KTextPlacementPercent * (aTextBoundingBox.Height() - fontHeight) / KCent;
       
   883     return fontHeight + topMargin - aFont->FontMaxDescent();
       
   884     }
       
   885 
       
   886 
       
   887 // -----------------------------------------------------------------------------
       
   888 // MirrorLayoutBoundingBox
       
   889 //
       
   890 // -----------------------------------------------------------------------------
       
   891 //
       
   892 static TRect MirrorLayoutBoundingBox(const TRect& aSourceRect, TRect& aBoundingBoxRect)
       
   893     {
       
   894     return TRect(
       
   895             aSourceRect.iTl.iX + aSourceRect.iBr.iX - aBoundingBoxRect.iBr.iX,
       
   896             aBoundingBoxRect.iTl.iY,
       
   897             aSourceRect.iTl.iX + aSourceRect.iBr.iX - aBoundingBoxRect.iTl.iX,
       
   898             aBoundingBoxRect.iBr.iY);
       
   899     }
       
   900 
       
   901 
       
   902 // -----------------------------------------------------------------------------
       
   903 // ClipTextToWidth
       
   904 // Cuts the text in the given pixel width. Also considers match highlight
       
   905 // issues.
       
   906 // NOTE: Can change the aMatch parameter if considers that there is too little
       
   907 // width for matching highlight.
       
   908 // NOTE 2: This function cannot handle right-to-left or bidirectional text currently.
       
   909 // These cases must be handled elsewhere.
       
   910 // -----------------------------------------------------------------------------
       
   911 //
       
   912 
       
   913 _LIT( KThreeDots, "..." );
       
   914 
       
   915 static void ClipTextToWidth(
       
   916         TDes& aText,
       
   917         const CFont& aFont,
       
   918         TInt aMaxWidthInPixels,
       
   919         TBool& aMatch)
       
   920     {
       
   921     TInt minimumWidth = aFont.TextWidthInPixels( KThreeDots );
       
   922     
       
   923     // If this is a matching piece of text, also match text marginals need to be counted.
       
   924     if ( aMatch )
       
   925         {
       
   926         minimumWidth += 2 * KMatchingTextMarginInPixels;
       
   927         }
       
   928     
       
   929     if ( minimumWidth > aMaxWidthInPixels )
       
   930         {
       
   931         
       
   932         // Not enough space for any text. 
       
   933         aText.Zero();
       
   934         aMatch = EFalse; // No match highlight shown.
       
   935         return;
       
   936         }
       
   937     
       
   938     if ( aMatch )
       
   939         {
       
   940         aMaxWidthInPixels -= 2 * KMatchingTextMarginInPixels;
       
   941         }
       
   942     
       
   943     AknTextUtils::ClipToFit( aText, aFont, aMaxWidthInPixels );    
       
   944     }
       
   945 
       
   946 
       
   947 // -----------------------------------------------------------------------------
       
   948 // DrawPieceOfText
       
   949 // Draws a piece of text of contact, either matching or not matching.
       
   950 // Updates aXOffset argument by adding drawn text width.
       
   951 //
       
   952 // @return: ETrue, if there was enough space for the text to draw. 
       
   953 // NOTE: CWindowGc font must be set before calling this function. 
       
   954 // -----------------------------------------------------------------------------
       
   955 //
       
   956 static TBool DrawPieceOfText(
       
   957         const TRect& aBoundingBox,
       
   958         TInt& aXOffset,
       
   959         CWindowGc &aGc, 
       
   960         const TDesC& aText,
       
   961         TBool aMatch,
       
   962         const CFont* aFont,
       
   963         const CEasyDialingListBoxData::TExtendedColors& aColors,
       
   964         TBool aHighLight )
       
   965     {    
       
   966     if (aText.Length() == 0) 
       
   967         {
       
   968         return ETrue;
       
   969         }
       
   970     
       
   971     HBufC* newText = aText.Alloc();
       
   972     if ( !newText )
       
   973         {
       
   974         return EFalse;
       
   975         }
       
   976     
       
   977     TPtr textPtr = newText->Des();
       
   978     
       
   979     // textWidth is the width needed for the text. 
       
   980     TInt textWidth = AknBidiTextUtils::MeasureTextBoundsWidth( *aFont, textPtr, CFont::TMeasureTextInput::EFVisualOrder );
       
   981     
       
   982     // whole width includes also possible highlight margins. 
       
   983     TInt wholeWidth = textWidth + ( aMatch ? 2 * KMatchingTextMarginInPixels : 0);
       
   984     
       
   985     // availableWidth is the space left for drawing. 
       
   986     TInt availableWidth = aBoundingBox.Width() - aXOffset;
       
   987     
       
   988     if ( availableWidth < wholeWidth )
       
   989         {
       
   990         ClipTextToWidth( textPtr, *aFont, availableWidth, aMatch );
       
   991         wholeWidth = availableWidth;
       
   992         if ( aMatch )
       
   993             {
       
   994             textWidth = wholeWidth - (2 * KMatchingTextMarginInPixels);
       
   995             }
       
   996         else
       
   997             {
       
   998             textWidth = wholeWidth;
       
   999             }
       
  1000         }
       
  1001     
       
  1002     // textBox is rectangle for text without highlight.
       
  1003     TRect textBox( aBoundingBox );
       
  1004     textBox.iTl.iX += aXOffset;
       
  1005     textBox.iBr.iX = textBox.iTl.iX + textWidth;
       
  1006     
       
  1007     TInt baseLineOffset = BaseLineOffset( textBox, aFont );
       
  1008     
       
  1009     if ( aMatch )
       
  1010         {
       
  1011         // highlightBox rectangle for text with highlight.
       
  1012         // Compared to no highlight, it has extra margins on both sides.
       
  1013         TRect highlightBox( textBox );
       
  1014         highlightBox.iBr.iX = highlightBox.iTl.iX + wholeWidth;
       
  1015         
       
  1016         // Also boundingBox is shifted right for one margin width.
       
  1017         textBox.iTl.iX += KMatchingTextMarginInPixels;
       
  1018         textBox.iBr.iX += KMatchingTextMarginInPixels;
       
  1019        
       
  1020         // Outline of matching highlight is of same colour as text.
       
  1021         // This looks quite OK.
       
  1022         aGc.SetPenColor( aColors.iMatchingText );
       
  1023         aGc.SetBrushStyle( CGraphicsContext::ESolidBrush );
       
  1024         aGc.SetBrushColor( aColors.iMatchingBack );
       
  1025         
       
  1026         aGc.DrawRoundRect( highlightBox, TSize( KMatchingTextMarginInPixels, KHighligthRectangleRoundingYInPixels ) );
       
  1027         
       
  1028         aGc.SetBrushStyle( CGraphicsContext::ENullBrush );
       
  1029         }
       
  1030     else 
       
  1031         {
       
  1032         if ( aHighLight )
       
  1033             {
       
  1034             aGc.SetPenColor( aColors.iHighlightedText );                 
       
  1035             }
       
  1036         else 
       
  1037             {
       
  1038             aGc.SetPenColor( aColors.iText );                   
       
  1039             }
       
  1040         }
       
  1041     
       
  1042     aGc.DrawText( textPtr, textBox, baseLineOffset );
       
  1043     delete newText;
       
  1044     aXOffset += wholeWidth;
       
  1045     return ETrue;
       
  1046     }
       
  1047 
       
  1048 
       
  1049 // -----------------------------------------------------------------------------
       
  1050 // DrawTextWithMatchHighlight
       
  1051 // Draws a string with match highlight. Highlighted and non-highlighted
       
  1052 // parts are separated with KHighlightSeparatorChar.
       
  1053 // The first text part is not highlighted and from that on highlight
       
  1054 // is on on every other text piece.
       
  1055 // 
       
  1056 // -----------------------------------------------------------------------------
       
  1057 //
       
  1058 static TInt DrawTextWithMatchHighlightL(
       
  1059         const TRect& aBoundingBox,
       
  1060         CWindowGc &aGc, 
       
  1061         const TDesC& aText,
       
  1062         const CFont* aFont,
       
  1063         const CEasyDialingListBoxData::TExtendedColors& aColors,
       
  1064         TBool aHighLight)
       
  1065     {
       
  1066     TInt xOffset = 0;
       
  1067     
       
  1068     HBufC* visualBuf = ConvertToVisualAndClipLC( aText, *aFont, aBoundingBox );
       
  1069     
       
  1070     TInt calculatedTextWidth = CalculateTextWidth( aBoundingBox, *visualBuf, aFont );
       
  1071     
       
  1072     if ( AknLayoutUtils::LayoutMirrored() )
       
  1073         {
       
  1074         xOffset = aBoundingBox.Width() - calculatedTextWidth;
       
  1075         }
       
  1076     TPtrC textPiece;
       
  1077     TInt textPieceIndex = 0;
       
  1078     TBool match = EFalse;
       
  1079 
       
  1080     aGc.UseFont( aFont );
       
  1081     aGc.SetBrushStyle( CGraphicsContext::ENullBrush );
       
  1082 
       
  1083     while ( TextUtils::ColumnText( textPiece , textPieceIndex, visualBuf, KHighlightSeparatorChar) == KErrNone ) 
       
  1084         {
       
  1085         if (! DrawPieceOfText( aBoundingBox, xOffset, aGc, textPiece, match, aFont, aColors, aHighLight ))
       
  1086             {
       
  1087             // If there was not enough space for this piece of text, exit the loop stop drawing further pieces.
       
  1088             break;
       
  1089             }
       
  1090 
       
  1091         // Toggle match
       
  1092         match = !match;
       
  1093 
       
  1094         ++textPieceIndex;
       
  1095         }
       
  1096     
       
  1097     CleanupStack::PopAndDestroy( visualBuf );
       
  1098 
       
  1099     aGc.DiscardFont();
       
  1100     
       
  1101     return calculatedTextWidth;
       
  1102     }
       
  1103 
       
  1104 // -----------------------------------------------------------------------------
       
  1105 // CalculateTextWidth
       
  1106 // Calculates the width of the text and returns it 
       
  1107 // -----------------------------------------------------------------------------
       
  1108 //
       
  1109 static TInt CalculateTextWidth(const TRect& aBoundingBox, const TDesC& aText, const CFont* aFont )
       
  1110     {
       
  1111     
       
  1112     TInt xOffset = 0;
       
  1113     TPtrC textPiece;
       
  1114     TInt textPieceIndex = 0;
       
  1115     TBool match = EFalse;
       
  1116 
       
  1117     while ( TextUtils::ColumnText( textPiece , textPieceIndex, &aText, KHighlightSeparatorChar) == KErrNone ) 
       
  1118         {
       
  1119         if (! CalculateTextPieceWidth( aBoundingBox, xOffset, textPiece, match, aFont ))
       
  1120             {
       
  1121             // If there was not enough space for this piece of text, exit the loop stop drawing further pieces.
       
  1122             break;
       
  1123             }
       
  1124 
       
  1125         // Toggle match
       
  1126         match = !match;
       
  1127 
       
  1128         ++textPieceIndex;
       
  1129         }
       
  1130 
       
  1131     return xOffset;
       
  1132     }
       
  1133 
       
  1134 // -----------------------------------------------------------------------------
       
  1135 // CalculateTextPieceWidth
       
  1136 // 
       
  1137 // Calculates the width of the text piece of highlighted text. 
       
  1138 // The function is aware of the available width for the text, and can take
       
  1139 // possible clippings into account. 
       
  1140 //
       
  1141 // The available width is given by parameters aBoundingBox (space for all text
       
  1142 // pieces) and aXOffset (now much of that space has already been used).
       
  1143 //
       
  1144 // The function adds the text width to the aXOffset reference parameter.
       
  1145 // Returns EFalse, if there is no more space for new text pieces, otherwise
       
  1146 // ETrue.
       
  1147 //
       
  1148 // This function contains the same logic as function DrawPieceOfText.
       
  1149 // -----------------------------------------------------------------------------
       
  1150 //
       
  1151 static TBool CalculateTextPieceWidth(
       
  1152         const TRect& aBoundingBox,
       
  1153         TInt& aXOffset,
       
  1154         const TDesC& aText,
       
  1155         TBool aMatch,
       
  1156         const CFont* aFont )
       
  1157     {    
       
  1158     if (aText.Length() == 0) 
       
  1159         {
       
  1160         return ETrue;
       
  1161         }
       
  1162 
       
  1163     // textWidth is the width needed for the text. 
       
  1164     TInt textWidth = AknBidiTextUtils::MeasureTextBoundsWidth( *aFont, aText, CFont::TMeasureTextInput::EFVisualOrder );
       
  1165 
       
  1166     // whole width includes also possible highlight margins. 
       
  1167     TInt wholeWidth = textWidth + ( aMatch ? 2 * KMatchingTextMarginInPixels : 0);
       
  1168 
       
  1169     // availableWidth is the space left for drawing. 
       
  1170     TInt availableWidth = aBoundingBox.Width() - aXOffset;
       
  1171 
       
  1172     if ( availableWidth < wholeWidth )
       
  1173         {
       
  1174 
       
  1175         // We get to this branch, if there is not enough space for the text piece.
       
  1176         HBufC* newText = aText.Alloc();
       
  1177         if ( !newText )
       
  1178             {
       
  1179             return EFalse;
       
  1180             }
       
  1181 
       
  1182         TPtr textPtr = newText->Des();
       
  1183         
       
  1184         // Clip the text so that it fits the space.
       
  1185         ClipTextToWidth( textPtr, *aFont, availableWidth, aMatch );
       
  1186 
       
  1187         if ( textPtr.Length() > 0 )
       
  1188             {
       
  1189             wholeWidth = AknBidiTextUtils::MeasureTextBoundsWidth( *aFont, textPtr, CFont::TMeasureTextInput::EFVisualOrder );
       
  1190             wholeWidth += (aMatch ? 2 * KMatchingTextMarginInPixels : 0);
       
  1191 
       
  1192             aXOffset += wholeWidth;
       
  1193             }
       
  1194 
       
  1195         delete newText;
       
  1196 
       
  1197         return EFalse;
       
  1198         }
       
  1199 
       
  1200     aXOffset += wholeWidth;
       
  1201 
       
  1202     return ETrue;
       
  1203     }
       
  1204 
       
  1205 // -----------------------------------------------------------------------------
       
  1206 // ContainsRightToLeftText
       
  1207 // 
       
  1208 // Returns true if argument descriptor contains right-to-left text.
       
  1209 // -----------------------------------------------------------------------------
       
  1210 //
       
  1211 static TBool ContainsRightToLeftText( const TDesC& aDesc )
       
  1212     {
       
  1213     TBool rtlFound = EFalse;
       
  1214     
       
  1215     // TRunInfoArray contains information of the directionalities of the different sections of the aText    
       
  1216     TBidirectionalState::TRunInfo array[ KMaxRunInfoArrayCount ];
       
  1217     
       
  1218     // Initialize the TBidiLogicalToVisual converter for making the conversion from logical to visual order
       
  1219     TBidiLogicalToVisual converter( aDesc, array, KMaxRunInfoArrayCount );
       
  1220     
       
  1221     // Do the reordering. Amount of different directionality sections is returned.
       
  1222     TInt count( converter.Reorder() );
       
  1223     // If there are more directionality blocks than we are prepared to handle, just ignore
       
  1224     // the rest. Those shouldn't fit the screen anyway.
       
  1225     count = Min( count, KMaxRunInfoArrayCount );
       
  1226     
       
  1227     for ( TInt i = 0 ; i < count && !rtlFound ; i++ )
       
  1228         {
       
  1229         // iDirection is 0 for left-to-right text.
       
  1230         if (array[i].iDirection)
       
  1231             {
       
  1232             rtlFound = ETrue;
       
  1233             }
       
  1234         }
       
  1235 
       
  1236     return rtlFound;
       
  1237     }
       
  1238 
       
  1239 // -----------------------------------------------------------------------------
       
  1240 // ConvertToVisualAndClipL
       
  1241 // 
       
  1242 // Clip bidirectional text to given box and convert it to visual order, ensuring
       
  1243 // that the match highlights don't get broken in the process. Result is given
       
  1244 // as new heap descriptor which is left to CleanupStack.
       
  1245 // NOTE1: No clipping happens here if given descriptor contains only 
       
  1246 // left-to-right text. 
       
  1247 // NOTE2: It's assumed that there can be highlights only in pure LTR and RTL
       
  1248 // texts. Highlights for mixed LTR-RTL text cannot be handled properly.
       
  1249 // -----------------------------------------------------------------------------
       
  1250 //
       
  1251 static HBufC* ConvertToVisualAndClipLC( const TDesC& aText, 
       
  1252                                        const CFont& aFont, 
       
  1253                                        const TRect& aBoundingBox )
       
  1254     {
       
  1255     HBufC* buf = HBufC::NewLC( aText.Length() + KAknBidiExtraSpacePerLine );
       
  1256     TPtr ptr = buf->Des();
       
  1257     ptr.Copy( aText );
       
  1258     
       
  1259     // Calling AknBidiTextUtils::ConvertToVisualAndClip doesn't work correctly 
       
  1260     // with the highlight separator characters (they are not considered to be 
       
  1261     // zero-length). To minimise the problem, we call the function only when 
       
  1262     // necessary, i.e. when given text really contains RTL text. This should be 
       
  1263     // considered as temporary solutions because now the problem of excessive 
       
  1264     // truncation still remains with RTL languages.
       
  1265     if ( ContainsRightToLeftText( ptr ) )
       
  1266         {
       
  1267         AknBidiTextUtils::ConvertToVisualAndClipL(
       
  1268                 ptr, aFont, aBoundingBox.Width(),
       
  1269                 aBoundingBox.Width() );
       
  1270         
       
  1271         // If there's an odd number of highlight separators in the RTL text, 
       
  1272         // then the matching and and not-matching parts have gone 
       
  1273         // off-sync in the visual conversion (because parts are drawn starting 
       
  1274         // from left and first part is always interpreted as not-matching part).
       
  1275         // Fix this by adding one highlight separator.
       
  1276         TInt sepCount = HighlightSeparatorCount( ptr );
       
  1277         if ( sepCount % 2 )
       
  1278             {
       
  1279             if ( ptr.Length() == ptr.MaxLength() )
       
  1280                 {
       
  1281                 // There's no more space available. We need to reallocate the 
       
  1282                 // buffer in order to fit the extra separator character.
       
  1283                 HBufC* newBuf = buf->ReAllocL( buf->Length() + 1 );
       
  1284                 CleanupStack::Pop( buf ); // original buf deleted by ReAllocL
       
  1285                 buf = newBuf;
       
  1286                 CleanupStack::PushL( buf );
       
  1287                 ptr.Set( buf->Des() );
       
  1288                 }
       
  1289             ptr.Insert( 0, KHighlightSeparatorCharAsLit );
       
  1290             }
       
  1291         }
       
  1292     
       
  1293     return buf;
       
  1294     }
       
  1295 
       
  1296 // -----------------------------------------------------------------------------
       
  1297 // HighlightSeparatorCount
       
  1298 // 
       
  1299 // Returns number of match highlight separator characters in the text
       
  1300 // -----------------------------------------------------------------------------
       
  1301 //
       
  1302 static TInt HighlightSeparatorCount( const TDesC& aText )
       
  1303     {
       
  1304     TInt len = aText.Length();
       
  1305     TInt sepCount = 0;
       
  1306     
       
  1307     for ( TInt i = 0; i < len; i++ )
       
  1308         {
       
  1309         if ( aText[i] == KHighlightSeparatorChar )
       
  1310             {
       
  1311             sepCount++;
       
  1312             }
       
  1313         }
       
  1314     
       
  1315     return sepCount;
       
  1316     }
       
  1317 
       
  1318 //  End of File.
       
  1319