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