diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/src/aknutils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/src/aknutils.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,6584 @@ +/* +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: General Avkon Utilities. Includes: +* - listbox utilities +* - layout utilities +* - text utilities +* +*/ + + +#include "AknUtils.h" +#include "AknBidiTextUtils.h" +#include +#include +#include +#include +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "avkon.hrh" +#include + +#include "aknappui.h" +#include "AknPanic.h" +#include "aknkeys.h" +#include +#include "AknLib.h" +#include "akntitle.h" + +#include +#include +#include + +#include +#include +#include + +#include "aknsfld.h" +#include "AknTextWrapper.h" +#include + + +#include +#include +#include + +#include + +#include + +#include "aknlists.h" +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include "AknLineBreaker.h" +#include "AknBuildVariant.h" +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "AknFontSpecificationLayoutFont.h" +#include +#include +#include +#include "AvkonVariant.hrh" + +#include +#include +#include +#include +#include +#include +#include +#include "AknLayoutUtilsHelpers.h" + +#include "AknAdaptiveSearch.h" +#include + +#include + +#ifdef RD_HINDI_PHONETIC_INPUT +#include +#endif + +using namespace AknLayout; + +// CONSTANTS + +const TInt KAknStringBufferSize = 256; +const TInt KTextColorNone = -1; +const TInt KFontHeightComparisonDivisor = 20; +const TInt KInvalidIndex = -1; + +enum TAknLayoutEdwinPanic + { + EAknLayoutEdwinPanicNoEdwin, + EAknLayoutEdwinPanicNoLinesOverMaxNoLines, + EAknLayoutEdwinPanicNotSupported + }; + +void Panic(TAknLayoutEdwinPanic aPanic) + { + _LIT(KAknLayoutUtilsLayoutEdwin,"AknLayoutUtils::LayoutEdwin"); + User::Panic(KAknLayoutUtilsLayoutEdwin, aPanic); + }; + +void Panic(TLafPanic aPanic) + { + _LIT(KLafEnv,"LafEnv"); + User::Panic(KLafEnv, aPanic); + }; + +// For debugging purposes. +#ifdef AKNUTILS_ENABLE_TRACES + #define LOGTEXT(AAA) RDebug::Print(AAA) + #define LOGTEXT1(AAA,BBB) RDebug::Print(AAA,BBB) + #define LOGTEXT2(AAA,BBB,CCC) RDebug::Print(AAA,BBB,CCC) + #define LOGTEXT3(AAA,BBB,CCC,DDD) RDebug::Print(AAA,BBB,CCC,DDD) + #define LOGTEXT4(AAA,BBB,CCC,DDD,EEE) RDebug::Print(AAA,BBB,CCC,DDD,EEE) +#else + #define LOGTEXT(AAA) NULL + #define LOGTEXT1(AAA,BBB) NULL + #define LOGTEXT2(AAA,BBB,CCC) NULL + #define LOGTEXT3(AAA,BBB,CCC,DDD) NULL + #define LOGTEXT4(AAA,BBB,CCC,DDD,EEE) NULL +#endif + +// +// Automatic numbering for columnlistbox. +// CListBoxNumbers +// +EXPORT_C CListBoxNumbers::CListBoxNumbers(CEikTextListBox *aListBox) + { + iListBox = aListBox; + } + +EXPORT_C void CListBoxNumbers::ConstructL() + { + UpdateL(); + } + + +EXPORT_C void CListBoxNumbers::UpdateL() + { + TInt e = iListBox->Model()->NumberOfItems(); + MDesCArray* itemList = iListBox->Model()->ItemTextArray(); + CDesCArray* itemArray = STATIC_CAST(CDesCArray*,itemList); + for (int i=0;i data; + data.Num(i+1); + data+=item.Right(item.Length()-pos); + itemArray->Delete(i); + itemArray->InsertL(i,data); + } + } + + +// Fonts + +EXPORT_C const CFont *LatinPlain12() + { + switch (AknLayoutUtils::Variant()) + { + case EEuropeanVariant: + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlp12))); + + case EApacVariant: + // should not come here ever + return ApacPlain12(); + + default: + return 0; + } + + } + +EXPORT_C const CFont *LatinBold12() + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlb12))); + } + +EXPORT_C const CFont *LatinBold13() + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlb13))); + } +EXPORT_C const CFont *LatinBold16() + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlb16))); + } + +EXPORT_C const CFont *LatinBold17() + { + switch (AknLayoutUtils::Variant()) + { + case EEuropeanVariant: + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlb17))); + + case EApacVariant: + return LatinBold13(); + + default: + return 0; + } + } + +EXPORT_C const CFont *LatinBold19() + { + switch (AknLayoutUtils::Variant()) + { + case EEuropeanVariant: + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlb19))); + + case EApacVariant: + return LatinBold17(); + + default: + return 0; + } + + } +EXPORT_C const CFont *ClockBold30() + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAcb30))); + } + +EXPORT_C const CFont *NumberPlain5() + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAcp5))); + } + +EXPORT_C const CFont *LatinClock14() + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAcb14))); + } + +const CFont *CalcBold21() + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAcalc21))); + } + +const CFont *CalcOperBold21() + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAco21))); + } + +const CFont *CalcOperBold13() + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAco13))); + } + +EXPORT_C const CFont *ApacPlain12() + { + // Combined font is used for all subvariants + if ( AknLayoutUtils::Variant() == EApacVariant ) + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidCombinedChinesePlain12))); + } + else + { + //this should not be called in Western builds + //__ASSERT_DEBUG(0, Panic(ELafPanicUsingFontFromWrongVariant)); + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlb13))); + } + + } + +EXPORT_C const CFont *ApacPlain16() + { + // Combined font is used for all subvariants + if ( AknLayoutUtils::Variant() == EApacVariant ) + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidCombinedChinesePlain16))); + } + else + { + //this should not be called in Western builds + //__ASSERT_DEBUG(0, Panic(ELafPanicUsingFontFromWrongVariant)); + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlb13))); + } + } + +const CFont* PrimaryFont() + { + if ( AknLayoutUtils::Variant() == EApacVariant ) + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidCombinedChinesePlain16))); + } + else + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlb13))); + } + } + +const CFont* SecondaryFont() + { + if ( AknLayoutUtils::Variant() == EApacVariant ) + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidCombinedChinesePlain12))); + } + else + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlp12))); + } + } + +const CFont* TitleFont() + { + if ( AknLayoutUtils::Variant() == EApacVariant ) + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidCombinedChinesePlain16))); + } + else + { + return CEikonEnv::Static()->Font(TLogicalFont(TUid::Uid(KScreenFontUidAlb19))); + } + } + + +// +// Find implementation +// + +EXPORT_C +void AknFind::HandleFindPopupProcessCommandL( TInt aCommand, + CEikListBox * aListBox, + CAknSearchField *aSearch, + CCoeControl *aParentControl ) + { + _AKNTRACE_FUNC_ENTER; + if ( aSearch && aCommand == EAknCmdFindPopupActivated ) + { + if ( aListBox ) + { + aSearch->SetOldItemIndex( aListBox->CurrentItemIndex() ); + } + aSearch->MakeVisible( ETrue ); + aSearch->SetFocus( ETrue ); + HandlePopupFindSizeChanged( aParentControl, aListBox, aSearch ); + } + _AKNTRACE_FUNC_EXIT; + } + +EXPORT_C +void AknFind::HandleFixedFindSizeChanged( CCoeControl *aParentControl, + CAknColumnListBox *aListBox, + CAknSearchField *aSearchField ) + { + _AKNTRACE_FUNC_ENTER; + TAknWindowLineLayout empty; + empty.iC = 0; + empty.il = 0; + empty.it = 0; + empty.ir = 0; + empty.ib = 0; + empty.iW = ELayoutEmpty; + empty.iH = ELayoutEmpty; + + TAknWindowLineLayout findPane = AknLayoutScalable_Avkon::find_pane().LayoutLine(); + TAknWindowLineLayout listPane; + + // listPane should equal to parent's rect + listPane.il = aParentControl->Rect().iTl.iX; + listPane.ir = ELayoutEmpty; + listPane.it = aParentControl->Rect().iTl.iY; + listPane.ib = ELayoutEmpty; + + // this check is required since it's not guaranteed that listbox's SetRect + // has been called when this code is executed + if ( aParentControl->Size().iWidth > 0 ) + { + listPane.iW = aParentControl->Size().iWidth; + listPane.ir = ELayoutEmpty; + } + else + { + listPane.iW = ELayoutEmpty; + listPane.ir = 0; + } + + // but findpane's height should be subtracted + listPane.iH = aParentControl->Size().iHeight - findPane.iH; + + // findPane's width should equal to listPane's width + findPane.iW = listPane.iW; + + HandleFindSizeChangedLayouts( aParentControl, + aListBox, + aSearchField, + findPane, + listPane, + EFalse, + empty ); + _AKNTRACE_FUNC_EXIT; + } + + +EXPORT_C +void AknFind::HandlePopupFindSizeChanged( CCoeControl *aParentControl, + CEikListBox *aListBox, + CAknSearchField *aSearchField ) + { + _AKNTRACE_FUNC_ENTER; + TAknWindowLineLayout findPane = AknLayoutScalable_Avkon::popup_find_window().LayoutLine(); + TAknWindowLineLayout listPane; + + // listPane should equal to parent's rect + listPane.il = aParentControl->Rect().iTl.iX; + listPane.it = aParentControl->Rect().iTl.iY; + listPane.ib = 0; + listPane.iH = ELayoutEmpty; + + // this check is required since it's not guaranteed that listbox's SetRect + // has been called when this code is executed + if ( aParentControl->Size().iWidth > 0 ) + { + listPane.iW = aParentControl->Size().iWidth; + listPane.ir = ELayoutEmpty; + } + else + { + listPane.iW = ELayoutEmpty; + listPane.ir = 0; + } + + // findPane's width should equal to listPane's width + findPane.iW = listPane.iW; + + HandleFindSizeChangedLayouts( aParentControl, + aListBox, + aSearchField, + findPane, + listPane, + ETrue, + main_pane( screen().Rect(), 0, 1, 1) ); + _AKNTRACE_FUNC_EXIT; + } + + +// THIS METHOD IS DEPRECATED +EXPORT_C void AknFind::HandleFindSizeChanged(CCoeControl *aParentControl, + CEikListBox *aListBox, + CAknSearchField *aSearchField, + TBool ispopup, + TInt aFindWindowResourceId, + TInt aListAreaResourceId, + TInt aListResourceIdWithFindPopup, + TInt aFindWindowParentResourceId) + { + _AKNTRACE_FUNC_ENTER; + if (aSearchField) + { + aSearchField->SetListbox(aListBox); + aSearchField->SetParentCtrl(aParentControl); + STATIC_CAST(CAknFilteredTextListBoxModel*,aListBox->Model())->Filter()->SetParentControl(aParentControl); + TRect parentrect = aParentControl->Rect(); + if (ispopup) + { // popup find position is different + ((CAknFilteredTextListBoxModel*)aListBox->Model())->Filter()->SetPopup(); + parentrect = iAvkonAppUi->ApplicationRect(); + TBuf criteria; + aSearchField->GetSearchText(criteria); + if (aSearchField->IsVisible() ) + aListAreaResourceId = aListResourceIdWithFindPopup; + } + else + { // normal find has different empty list + CAknColumnListBoxView *view = STATIC_CAST(CAknColumnListBoxView*,aListBox->View()); + view->EnableFindEmptyList(); + } + TAknLayoutRect lrect; + lrect.LayoutRect(parentrect, aFindWindowParentResourceId); + AknLayoutUtils::LayoutControl(aSearchField, lrect.Rect(), aFindWindowResourceId); + _AKNTRACE( "[%s][%s] SearchField Rect iTl: %d,%d; iBr: %d,%d", + "AknFind", __FUNCTION__, + lrect.Rect().iTl.iX, lrect.Rect().iTl.iY, + lrect.Rect().iBr.iX, lrect.Rect().iBr.iY + ); + } + AknLayoutUtils::LayoutControl(aListBox, aParentControl->Rect(), aListAreaResourceId); + _AKNDEBUG( + if ( aListBox ) + { + _AKNTRACE( "[%s][%s] ListBox Rect iTl: %d,%d; iBr: %d,%d", + "AknFind", __FUNCTION__, + aParentControl->Rect().iTl.iX, aParentControl->Rect().iTl.iY, + aParentControl->Rect().iBr.iX, aParentControl->Rect().iBr.iY + ); + } + ); + _AKNTRACE_FUNC_EXIT; + } + +EXPORT_C void AknFind::HandleFindSizeChangedLayouts( + CCoeControl *aParentControl, + CEikListBox *aListBox, + CAknSearchField *aSearchField, + const TAknWindowLineLayout& aFindWindow, + const TAknWindowLineLayout& aListArea, + TBool aIsPopup, + const TAknWindowLineLayout& aFindWindowParent) + { + _AKNTRACE_FUNC_ENTER; + TAknWindowLineLayout tempListArea = aListArea; + + if (aSearchField) + { + aSearchField->SetParentCtrl(aParentControl); + aSearchField->SetListbox(aListBox); + CAknFilteredTextListBoxModel* m = static_cast ( aListBox->Model() ); + if ( m->Filter() ) + { + m->Filter()->SetParentControl( aParentControl ); + } + + TRect parentrect( aParentControl->Rect() ); + + if (aIsPopup) + { // popup find position is different + if ( m->Filter() ) + { + m->Filter()->SetPopup(); + } + // TPTN-7AXDMZ. For fixed toolbar. + TRect rect; + parentrect = AknLayoutUtils::LayoutMetricsRect( + AknLayoutUtils::EApplicationWindow, rect) ? + rect : + iAvkonAppUi->ApplicationRect(); + + if ( iAvkonAppUi->CurrentFixedToolbar() + && AknLayoutUtils::PenEnabled() + && !Layout_Meta_Data::IsLandscapeOrientation() ) + { + CAknToolbar* toolbar = iAvkonAppUi->CurrentFixedToolbar(); + TInt flags = toolbar->ToolbarFlags(); + if ( flags & KAknToolbarFixed + && !( flags & KAknToolbarDefault ) + && toolbar->IsShown() ) + { + parentrect.iBr.iY -= toolbar->Rect().Height(); + } + } + TBuf criteria; + aSearchField->GetSearchText(criteria); + if (aSearchField->IsVisible() ) + { + if (tempListArea.iH == ELayoutEmpty) + { + tempListArea.iH = TInt16(ELayoutP - tempListArea.it - tempListArea.ib); + } + + tempListArea.iH = + TUint16(tempListArea.iH - ( AknLayoutScalable_Avkon::popup_find_window().LayoutLine().iH - 1 ) ); + } + } + else + { // normal find has different empty list + CAknColumnListBoxView *view = STATIC_CAST(CAknColumnListBoxView*,aListBox->View()); + view->EnableFindEmptyList(); + } + + TAknLayoutRect lrect; + lrect.LayoutRect(parentrect, aFindWindowParent); + AknLayoutUtils::LayoutControl(aSearchField, lrect.Rect(), aFindWindow); + _AKNTRACE( "[%s][%s] SearchField Rect iTl: %d,%d; iBr: %d,%d", + "AknFind", __FUNCTION__, + lrect.Rect().iTl.iX, lrect.Rect().iTl.iY, + lrect.Rect().iBr.iX, lrect.Rect().iBr.iY + ); + } + + AknLayoutUtils::LayoutControl(aListBox, aParentControl->Rect(), tempListArea); + _AKNDEBUG( + if ( aListBox ) + { + _AKNTRACE( "[%s][%s] ListBox Rect iTl: %d,%d; iBr: %d,%d", + "AknFind", __FUNCTION__, + aListBox->Rect().iTl.iX, aListBox->Rect().iTl.iY, + aListBox->Rect().iBr.iX, aListBox->Rect().iBr.iY + ); + } + ); + if ( aListBox ) + { + aListBox->DrawNow(); + } + _AKNTRACE_FUNC_EXIT; + } + +void AknFind::HandleFindPaneVisibility(CAknSearchField *aSearchField, TBool ispopup, TBool textnotchanged, TBool &aNeedRefresh) + { + if (ispopup) + { + TBuf criteria; + aSearchField->GetSearchText(criteria); + TBool oldvisibility = aSearchField->IsVisible(); + TBool findboxvisible; + TInt newlength = criteria.Length(); + + _AKNTRACE( "[%s][%s] Text Length is: %d", + "AknFind", __FUNCTION__, newlength ); + + if (newlength == 0) + { + findboxvisible = EFalse; + if (textnotchanged && oldvisibility) + { + findboxvisible=ETrue; + } + } + else + { + findboxvisible = ETrue; + } + if (findboxvisible != oldvisibility) + { + aSearchField->SetFocus(findboxvisible); + aSearchField->MakeVisible(findboxvisible); + aNeedRefresh = ETrue; + } + _AKNTRACE( "[%s][%s] SearchField's visibility is: %d", + "AknFind", __FUNCTION__, aNeedRefresh ); + } + } + +#define ISFINDWORDSEPARATOR( aCh ) ( (aCh) == ' ' || (aCh) == '-' || (aCh) == '\t' ) +const TInt KMatchingBufferLength(256); +const TInt KLitSpace(' '); +const TInt KLitStar('*'); +const TInt KLitTab('\t'); + +EXPORT_C TBool AknFind::IsFindMatch( const TDesC &aItemString, const TDesC &aSearchText ) + { + TInt length = aItemString.Length(); + for( TInt i = 0; i < length; i++ ) + { + if ( i==0 || ISFINDWORDSEPARATOR( aItemString[i-1] ) ) + { + if ( aItemString.Mid(i).FindC( aSearchText ) == 0 ) + { + return ETrue; + } + } + } + return EFalse; + } + +EXPORT_C TBool AknFind::IsFindWordSeparator(TChar aCh) + { + return ISFINDWORDSEPARATOR( aCh ); + } + +// ----------------------------------------------------------------------------- +// For Vietnamese AS +// +// ----------------------------------------------------------------------------- +// +inline TChar ReplaceVietnameseChar( const TChar aCh ) + { + TChar Char = aCh.GetUpperCase(); + if ( (Char >= 0x00C0 && Char <= 0x00C3) || Char == 0x102 || + ((Char >= 0x1EA0 && Char <= 0x1EB6) && Char%2 == 0) ) + { + Char = 0x0041; // A + return Char; + } + if ( (Char >= 0x00C8 && Char <= 0x00CA) || + ((Char >= 0x1EB8 && Char <= 0x1EC6) && Char%2 == 0) ) + { + Char = 0x0045; // E + return Char; + } + if ( Char == 0x00CC || Char == 0x00CD || Char == 0x0128 || + Char == 0x1EC8 || Char == 0x1ECA ) + { + Char = 0x0049; // I + return Char; + } + if ( (Char >= 0x00D2 && Char <= 0x00D5 ) || Char == 0x1ECE || Char == 0x1ECC || + ((Char >= 0x1ED0 && Char <= 0x1ED8) && Char%2 == 0)) + { + Char = 0x004F; // O + return Char; + } + if ( Char == 0x1EDA || Char == 0x1EDC || Char == 0x1EDE || + Char == 0x1EE0 || Char == 0x1EE2 ) + { + Char = 0x01A0; // O-horn + return Char; + } + if ( Char == 0x00DA || Char == 0x00D9 || Char == 0x0168 || + Char == 0x1EE4 || Char == 0x1EE6 ) + { + Char = 0x0055; // U + return Char; + } + if ( (Char >= 0x1EE8 && Char <= 0x1EF0) && Char%2 == 0 ) + { + Char = 0x01AF; // U-horn + return Char; + } + if ( ((Char >= 0x1EF2 && Char <= 0x1EF8) && Char%2 == 0) || Char == 0x00DD ) + { + Char = 0x0059; // Y + return Char; + } + return Char; + } + + /** + * Checks current character is it special character from Vietnamese language . + * + * @since 5.0 + * @return @c ETrue If it is accent from Vietnamese language, otherwise EFalse. + */ +inline TBool IsVietnameseSpecialCharacter( TChar aCh ) + { + if ( ( aCh >= 0x0300 && aCh <= 0x0303 ) || aCh == 0x0306 || + aCh == 0x0309 || aCh == 0x0323 || aCh == 0x031B ) + { + return ETrue; + } + return EFalse; + } + +// --------------------------------------------------------------------------- +// Checks the current character for special character from Thai language . +// --------------------------------------------------------------------------- +inline TBool IsThaiSpecialCharacter( TChar aCh ) + { + if( ( aCh > 0xE46 && aCh < 0xE4F ) || aCh == 0xE3A ) + { + return ETrue; + } + return EFalse; + } + +// --------------------------------------------------------------------------- +// IsAdaptiveFindMatch +// --------------------------------------------------------------------------- +// +EXPORT_C TBool AknFind::IsAdaptiveFindMatch( const TDesC& aItemText, + const TDesC& aSearchText, + HBufC*& aNextChars ) + { + HBufC16* searchText( NULL ); + TRAPD( error, searchText = HBufC16::NewL( KMatchingBufferLength ) ); + if ( error == KErrNone ) + { + TInt itemStringLength = aItemText.Length(); + TInt searchTextLength = aSearchText.Length(); + + if ( searchTextLength < KMatchingBufferLength ) + { + searchText->Des().Append( aSearchText ); + } + else + { + searchText->Des().Append( aSearchText.Left(KMatchingBufferLength-1) ); + } + + searchText->Des().Append( KLitStar ); + + TInt all_result = KErrNotFound; + for( TInt i = 0; i < itemStringLength; i++ ) + { + if ( i==0 || IsFindWordSeparator( aItemText[i-1] ) ) + { + TInt result = aItemText.Mid(i).MatchC( searchText->Des() ); + + if( result != KErrNotFound ) + { + all_result = result; + if( i < (itemStringLength-searchTextLength) ) + { + if( !(IsThaiSpecialCharacter(aItemText[i+searchTextLength])) && !(IsVietnameseSpecialCharacter( aItemText[i+searchTextLength]) )) + { + TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemText[i+searchTextLength]) ); + } + } + } + } // if (i==0 ..) + } // for + + if( all_result != KErrNotFound ) + { + delete searchText; + return ETrue; + } + else + { + delete searchText; + return EFalse; + } + + } // if (error == KErrNone) + + delete searchText; + return EFalse; + } + + +/** + * For Devanagari AS + * Checks if the passed string denotes one of the four special + * Devanagari ligatures - refer UI specs for the description of special ligatures + * @param aCharString - The string containing set of characters to be checked + * @return ETrue if a special ligature is found EFalse otherwise. + */ +inline TBool IsSpecialIndicLigature(const TDesC& aCharString ) + { + TBool ret = EFalse; + if( aCharString.Length() >= 3 ) + { + //First check for Devanagari special ligatures + if( + ( ( (aCharString[0] == 0x915) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x937) ) || + ( (aCharString[0] == 0x91C) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x91E) ) || + ( (aCharString[0] == 0x936) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x930) ) || + ( (aCharString[0] == 0x924) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x930) ) )) + { + ret = ETrue; + } + } + return ret; + } + +/** + * For Devanagari AS + * Checks if the given character is a Indic consonant. + * @param aSearchChar - Character to be checked. + * @return ETrue if this is an independent character EFalse otherwise. + */ +inline TBool IsIndicConsonant(const TChar aSearchChar) + { + if ( + ( aSearchChar >= 0x0915 && aSearchChar <= 0x0939 ) + || ( aSearchChar >= 0x0958 && aSearchChar <= 0x0961 ) + ) + { + return ETrue; + } + else + { + return EFalse; + } + } + + +/** + * For Devanagari AS + * Checks if aCh denotes a consonant with nukta. + * @param aCh - character to be checked + * @return ETrue if aCh is a consonant with nukta EFalse otherwise. + */ +inline TBool IsIndicCombinedChar( const TChar aCh ) + { + if ( aCh < 0x0900 || aCh > 0x0980 ) + { + return EFalse; + } + else + { + return ( aCh == 0x0929 || aCh == 0x0931 + || aCh == 0x0934 || (aCh >= 0x0958 && aCh <= 0x095F) ); + } + } + +/** + * For Devanagari AS + * This is to check if the character can be displayed on the + * adaptive search grid or not. + * @param aCh character to be displayed on adaptive search grid + * @return ETrue if the character is valid for AS Grid EFalse otherwise. + */ +TBool inline IsValidCharForASGrid(TChar aCh) + { + //first check for Devanagari character range. + if ( aCh < 0x0900 || aCh > 0x0980 ) + { + return ETrue; + } + else + { + return ( + !( (aCh >= 0x0901 && aCh <= 0x0903) || //Devanagari modifier + (aCh >= 0x093C && aCh <= 0x094D) //Devanagari dependent vowels + ) ); + } + } + + +/** + * For Devanagari AS + * Returns the correcponding character without nukta + * @param aCh - character to be stripped of nukta * + * @return corresponding character with nukta + */ +inline TChar RemoveIndicNukta( const TChar aCh ) + { + switch (aCh) + { + case 0x0929 : return 0x0928; //vocallic 'nna' to 'na' + case 0x0931 : return 0x0930; //vocallic 'rra' to 'ra' + case 0x0934 : return 0x0933; //vocallic 'lllla' to 'lla' + case 0x0958 : return 0x0915; //vocallic 'qa' to 'ka' + case 0x0959 : return 0x0916; //vocallic 'khha' to 'kha' + case 0x095A : return 0x0917; //vocallic 'ghha' to 'ga' + case 0x095B : return 0x091C; //letter 'za' to 'ja' + case 0x095C : return 0x0921; //vocallic 'dddha' to 'da' + case 0x095D : return 0x0922; //vocallic 'rha' to 'ddha' + case 0x095E : return 0x092B; //letter 'fa' to 'pha' + case 0x095F : return 0x092F; //letter 'yya' to 'ya' + + default : return aCh; + } + } + + +// ----------------------------------------------------------------------------- +// For Devanagari AS +// Checks if the last character entered is a Indic halant character. +// @param aCh - character to be checked +// @return ETrue if this is a halant character EFalse otherwise +// ----------------------------------------------------------------------------- +inline TBool IsIndicHalantChar(const TChar aCh) + { + return ( aCh == 0x094D ); + } + +// --------------------------------------------------------------------------- +// For Devanagari AS +// AknFind::UpdateNextCharsL +// --------------------------------------------------------------------------- +// +void AknFind::UpdateNextCharsL( HBufC*& aNextChars, const TDesC& aItemString ) + { + _AKNTRACE_FUNC_ENTER; + TChar searchChar = aItemString[0]; + //Check if this is an Indic special ligature + if ( IsIndicConsonant(searchChar) && aItemString.Length() > 2 + && IsSpecialIndicLigature(aItemString) + && KErrNotFound == (*aNextChars).Find(aItemString.Mid(0,3)) ) + { + //Check if we have enough space for 3 more characters + if( aNextChars->Des().Length() >= aNextChars->Des().MaxLength()-3 ) + { + aNextChars = aNextChars->ReAllocL( aNextChars->Des().MaxLength()+10 ); + TInt length1 = aNextChars->Des().Length(); + TInt maxlength1 = aNextChars->Des().MaxLength(); + } + aNextChars->Des().Append( aItemString.Mid(0,3) ); + } + else + { + if ( !IsValidCharForASGrid(searchChar) ) + { + return; + } + //check if this is an Indic combined Char + if ( IsIndicCombinedChar(searchChar) ) + { + searchChar = RemoveIndicNukta( searchChar ); + } + //Now update the nextChars string + TInt strLength = aNextChars->Length(); + for ( TInt i(0); i < strLength ; ++i ) + { + if ( IsSpecialIndicLigature( (*aNextChars).Mid(i) ) ) + { + //As aItemString is not a special ligature (checked above) + //we can move directly to the 3rd character from here + i+=2; + continue; + } + else if ( searchChar.GetUpperCase() == (*aNextChars)[i] || + searchChar.GetLowerCase() == (*aNextChars)[i] ) + { + //already exists - do nothing + return; + } + //else continue the loop + } + //So this character is not yet in the list of nextChars. + if( aNextChars->Des().Length() == aNextChars->Des().MaxLength() ) + { + aNextChars = aNextChars->ReAllocL( aNextChars->Des().MaxLength()+10 ); + } + aNextChars->Des().Append( searchChar ); + } + _AKNTRACE_FUNC_EXIT; + } + +// ----------------------------------------------------------------------------- +// AknFind::UpdateNextCharsL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void AknFind::UpdateNextCharsL( HBufC*& aNextChars, TChar aCh ) + { + TChar ch_temp = aCh; + aCh = ReplaceVietnameseChar ( ch_temp ); + if( ( aNextChars->Locate(aCh.GetLowerCase() ) == KErrNotFound ) && + ( aNextChars->Locate(aCh.GetUpperCase() ) == KErrNotFound ) ) + { + if( aNextChars->Des().Length() == aNextChars->Des().MaxLength() ) + { + aNextChars = aNextChars->ReAllocL( aNextChars->Des().MaxLength()+10 ); + TInt length1 = aNextChars->Des().Length(); + TInt maxlength1 = aNextChars->Des().MaxLength(); + } + aNextChars->Des().Append( aCh ); + } + } + +// --------------------------------------------------------------------------- +// UpdateNextCharsFromString +// --------------------------------------------------------------------------- +// +EXPORT_C void AknFind::UpdateNextCharsFromString( HBufC*& aNextChars, const TDesC& aItemString ) + { + TInt itemStringLength = aItemString.Length(); + + for( TInt i = 0; i < itemStringLength; i++ ) + { + if ( i == 0 || IsFindWordSeparator( aItemString[i-1] ) ) + { + // If Indic letter + if ( aItemString[i] >= 0x0900 && aItemString[i] <= 0x0980 ) + { + TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString.Mid(i) ) ); + } + else if (!(IsVietnameseSpecialCharacter( aItemString[i]))) + { + TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString[i] ) ); + } + } + } + } + +// --------------------------------------------------------------------------- +// UpdateItemTextAccordingToFlag +// --------------------------------------------------------------------------- +// +EXPORT_C void AknFind::UpdateItemTextAccordingToFlag( const TDesC& aInputText, + TBitFlags32 aColumnFlag, + TDes& aOutText ) + { + TInt MaxColumn = 32; + TPtrC tmptext; + for ( TInt column=0; column 0 ) + { + // delete the trailing whitespace + aOutText.Delete( (aOutText.Length()-1), 1 ); + } + aOutText.UpperCase(); + } + + + +EXPORT_C +TKeyResponse AknFind::HandleFindOfferKeyEventL( const TKeyEvent &aKeyEvent, + TEventCode aType, + CCoeControl * /*aListBoxParent*/, + CEikListBox *aListBox, + CAknSearchField *aSearchField, + TBool ispopup, + TBool &aNeedRefresh ) + { + if (aType != EEventKey) + { + return EKeyWasNotConsumed; + } + + if (aKeyEvent.iCode == '#') + { + return EKeyWasNotConsumed; + } + + aNeedRefresh = EFalse; + + if (!aSearchField || !aListBox) + { + return EKeyWasNotConsumed; + } + + + TBool removePopup = EFalse; + + /* THE case where normal letters come from keyboard */ + TKeyResponse result = EKeyWasNotConsumed; + TBuf<256> criteria; + aSearchField->GetSearchText(criteria); + TInt oldlength = criteria.Length(); + + if ( !aSearchField->IsVisible() && oldlength == 0 ) + { + aSearchField->SetOldItemIndex( aListBox->CurrentItemIndex() ); + } + + // EHLI-7PKBEJ Old code just support ITUT keypad... now we extend it + // to QWERTY keyboard. + if ( aSearchField->IsVisible() == EFalse && ispopup && oldlength == 0 + && TChar(aKeyEvent.iCode).IsPrint()) + { + aSearchField->SetFocus(ETrue); + aSearchField->MakeVisible(ETrue); + + ((CAknFilteredTextListBoxModel*)aListBox->Model())->Filter()->DeferredSendFullKeyEventToFepL(aKeyEvent); + + aNeedRefresh = ETrue; + return EKeyWasConsumed; + } + + if ( aSearchField->OfferKeyEventL( aKeyEvent, aType ) == EKeyWasConsumed ) + { + result = EKeyWasConsumed; + } + + ((CAknFilteredTextListBoxModel*)aListBox->Model())->Filter()->HandleOfferkeyEventL(); + + // remove popup if search criteria is empty and backspace is pressed + if ( aSearchField->IsVisible() && ispopup + && aKeyEvent.iCode == EKeyBackspace && oldlength == 0 ) + { + removePopup = ETrue; + TInt olditem = aSearchField->OldItemIndex(); + if ( olditem >= 0 ) // when list is empty, olditem is -1 + { + aListBox->SetCurrentItemIndex( olditem ); + } + } + HandleFindPaneVisibility(aSearchField, ispopup, !removePopup, aNeedRefresh); + return result; + } + + +EXPORT_C void CAknFilteredTextListBoxModel::CreateFilterL(CEikListBox *aListBox, CAknSearchField *aSearchField) + { + __ASSERT_DEBUG(iFilter==0, Panic(EAknPanicOutOfRange)); + iFilter = new(ELeave) CAknListBoxFilterItems(aListBox, aSearchField,this, aListBox->View()); + iFilter->ConstructL(); + } +EXPORT_C void CAknFilteredTextListBoxModel::RemoveFilter() + { + delete iFilter; + iFilter = NULL; + } + +EXPORT_C CAknListBoxFilterItems *CAknFilteredTextListBoxModel::Filter() const + { + return iFilter; + } + + +EXPORT_C const MDesCArray *CAknFilteredTextListBoxModel::MatchableTextArray() const {return this; } + +EXPORT_C TInt CAknFilteredTextListBoxModel::MdcaCount() const + { + return ItemTextArray()->MdcaCount(); + } + +EXPORT_C TPtrC CAknFilteredTextListBoxModel::MdcaPoint(TInt aIndex) const + { + if (iFilter) + return iFilter->DefaultMatchableItemFromItem(ItemTextArray()->MdcaPoint(aIndex)); + else + return ItemTextArray()->MdcaPoint(aIndex); + } + +EXPORT_C CAknFilteredTextListBoxModel::~CAknFilteredTextListBoxModel() + { + delete iFilter; + } + +EXPORT_C TInt CAknFilteredTextListBoxModel::NumberOfItems() const + { + return iFilter ? iFilter->FilteredNumberOfItems() : CTextListBoxModel::NumberOfItems(); + } + +EXPORT_C TPtrC CAknFilteredTextListBoxModel::ItemText(TInt aItemIndex) const + { + return CTextListBoxModel::ItemText(iFilter? iFilter->FilteredItemIndex(aItemIndex) : aItemIndex); + } + +EXPORT_C TAny* CAknFilteredTextListBoxModel::MListBoxModel_Reserved() + { + return NULL; + } + +class CFindExtension : public CBase + { +public: + CIdle* iIdle; + CFindUtil* iFindUtil; + HBufC16* iNextChars; // for adaptive search + HBufC* iDigraphChars; + TKeyEvent iKeyEvent; + + }; + +EXPORT_C void CAknListBoxFilterItems::DeferredSendKeyEventToFepL(TUint aValue) + { + __ASSERT_DEBUG(iKeyValue == 0, Panic(EAknPanicOutOfRange)); + if (iExtension) + { + iExtension->iKeyEvent.iCode = aValue; + iExtension->iKeyEvent.iScanCode = aValue; + if ( iExtension->iIdle ) + { + delete iExtension->iIdle; + iExtension->iIdle = 0; + } + iExtension->iIdle = CIdle::New(-20); + if (iExtension->iIdle) + { + iExtension->iIdle->Start(TCallBack(IdleCallBack, this)); + } + } + } + +void CAknListBoxFilterItems::DeferredSendFullKeyEventToFepL( + const TKeyEvent& aEvent ) + { + if ( iExtension ) + { + iExtension->iKeyEvent = aEvent; + if ( iExtension->iIdle ) + { + delete iExtension->iIdle; + iExtension->iIdle = 0; + } + iExtension->iIdle = CIdle::New(-20); + if ( iExtension->iIdle ) + { + iExtension->iIdle->Start( TCallBack( IdleCallBack, this)); + } + } + } + +TInt CAknListBoxFilterItems::IdleCallBack(TAny *aFilterItems) + { + TInt err = KErrNone; + CAknListBoxFilterItems *items = + static_cast(aFilterItems); + if ( items->iExtension ) + { + TKeyEvent& event(items->iExtension->iKeyEvent); + CCoeEnv *coeEnv = CCoeEnv::Static(); + // THE PART THAT COMMUNICATES WITH FEP. + TRAP_IGNORE( + { + coeEnv->SimulateKeyEventL(event,EEventKeyDown); + coeEnv->SimulateKeyEventL(event,EEventKey); + coeEnv->SimulateKeyEventL(event,EEventKeyUp); + } + ); + delete items->iExtension->iIdle; + items->iExtension->iIdle = 0; + } + else + { + err = KErrArgument; + } + return err; + } + +EXPORT_C CAknListBoxFilterItems::CAknListBoxFilterItems(CEikListBox *aListBox, CAknSearchField *aSearchField, MListBoxModel *aModel, CListBoxView *aView) + : iModel(aModel), iView(aView), iListBox(aListBox), iSearchField(aSearchField) + { + } + +EXPORT_C void CAknListBoxFilterItems::SetParentControl(CCoeControl *aControl) + { + iParentControl = aControl; + } + +EXPORT_C void CAknListBoxFilterItems::SetPopup() + { + iIsPopup = ETrue; + } + +EXPORT_C void CAknListBoxFilterItems::SetListBox(CEikListBox *aListBox) + { + iListBox = aListBox; + } + +EXPORT_C void CAknListBoxFilterItems::SetSearchField(CAknSearchField *aSearchField) + { + iSearchField = aSearchField; + if (iSearchField) + iSearchField->SetObserver(this); + } + +EXPORT_C void CAknListBoxFilterItems::SetModel(MListBoxModel *aModel) + { + iModel = aModel; + } + +EXPORT_C void CAknListBoxFilterItems::SetView(CListBoxView *aView) + { + iView = aView; + } + +EXPORT_C CCoeControl *CAknListBoxFilterItems::FindBox() const + { + return iSearchField; + } + +EXPORT_C void CAknListBoxFilterItems::ConstructL() + { + __ASSERT_DEBUG(iShownIndexes==0, Panic(EAknPanicOutOfRange)); + iShownIndexes = new(ELeave) CArrayFixFlat(5); + iSelectionIndexes = new(ELeave) CArrayFixFlat(5); + iOldSearchCriteria = _L("").AllocL(); + iExtension = new(ELeave)CFindExtension; + + // Returns NULL if findutil not supported + iExtension->iFindUtil = CFindUtil::NewL(); + + iExtension->iNextChars = HBufC16::NewL( 10 ); + iExtension->iDigraphChars = StringLoader::LoadL( R_QTN_ADS_DIGRAPH );; + + NoCriteriaL(); + HandleItemAdditionL(); + if (iSearchField) + iSearchField->SetObserver(this); + + const MDesCArray *array = iModel->MatchableTextArray(); + iOldItemCount = array->MdcaCount(); + } + +EXPORT_C CAknListBoxFilterItems::~CAknListBoxFilterItems() + { + if (iExtension) + { + delete iExtension->iIdle; + delete iExtension->iFindUtil; + delete iExtension->iNextChars; + delete iExtension->iDigraphChars; + delete iExtension; + } + delete iShownIndexes; + delete iSelectionIndexes; + delete iOldSearchCriteria; + delete iEmptyListText; + } + +EXPORT_C void CAknListBoxFilterItems::HandleItemArrayChangeL() + { + HBufC16* newcriteria = HBufC16::NewL( KMatchingBufferLength ); + TPtr ptr_newcriteria( newcriteria->Des() ); + + if ( iSearchField ) + { + iSearchField->GetSearchText( ptr_newcriteria ); + } + + CleanupStack::PushL( newcriteria ); + ReleaseCriteriaL( ptr_newcriteria ); + + delete iOldSearchCriteria; + iOldSearchCriteria = NULL; + iOldSearchCriteria = newcriteria->Des().AllocL(); + + CleanupStack::PopAndDestroy ( newcriteria ); + // We should redraw the listbox + HandleItemAdditionL(); // calls DrawDeferred() + + // If adaptive search manage with next characters + if( iSearchField && IsAdaptiveSearch() ) + { + // Handles filtering + + // Clear next characters + ClearNextChars(); + TBitFlags32 columnFlag = iSearchField->ListColumnFilterFlags(); + + HBufC16* temptext = HBufC16::NewL( KMatchingBufferLength ); + TPtr ptr_temptext( temptext->Des() ); + CleanupStack::PushL( temptext ); + const MDesCArray *array = iModel->MatchableTextArray(); + const CAknFilteredTextListBoxModel* arr = (CAknFilteredTextListBoxModel*)(iModel->MatchableTextArray()); + + for ( TInt i = iShownIndexes->Count()-1; i>=0; i-- ) + { + TPtrC itemtext = arr->ItemText( i ); + AknFind::UpdateItemTextAccordingToFlag( itemtext, columnFlag, ptr_temptext ); + + // this need to be done for update next characters for AdaptiveGrid + // ESMG-7LKAE4, use FindUtil is slow, but it is necessary for Chinese + if ( AknLayoutUtils::Variant() == EApacVariant ) + { + iExtension->iFindUtil->Interface()->MatchAdaptiveRefineL( + ptr_temptext, KNullDesC, iExtension->iNextChars); + } + else + { + AknFind::UpdateNextCharsFromString( iExtension->iNextChars, temptext->Des() ); + } + ptr_temptext.Zero(); + } + iSearchField->SetAdaptiveGridChars( *(iExtension->iNextChars) ); + CleanupStack::PopAndDestroy ( temptext ); + } + iOldItemCount = iModel->MatchableTextArray()->MdcaCount(); + if ( iOldItemCount>0 && iListBox ) + { + iListBox->SetCurrentItemIndex(0); + } + } + + +/** + * Editor sends messages to this object as control events. + */ +EXPORT_C void CAknListBoxFilterItems::HandleControlEventL(CCoeControl *aControl, TCoeEvent aEventType) + { + TBool refresh = EFalse; + switch(aEventType) + { + case EEventStateChanged: + if (iParentControl) + { + HandleOfferkeyEventL(); + if (iSearchField) + { + AknFind::HandleFindPaneVisibility(iSearchField, iIsPopup, ETrue, refresh); + } + if (refresh) + { + if (iListBox) + { + if (iIsPopup) + { + AknFind::HandlePopupFindSizeChanged(iParentControl, iListBox, iSearchField); + } + else + { + AknFind::HandleFixedFindSizeChanged(iParentControl, (CAknColumnListBox*)iListBox, iSearchField); + } + } + iParentControl -> DrawDeferred(); + } + } + break; + default: + break; + } + if (iObserver) iObserver->HandleControlEventL(aControl, aEventType); + } + +void CAknListBoxFilterItems::HandleItemAdditionL() + { + iDisableChangesToShownIndexes = ETrue; + if (iListBox) + { + TRAP_IGNORE(iListBox->HandleItemAdditionL()); + } + iDisableChangesToShownIndexes = EFalse; + } + +void CAknListBoxFilterItems::HandleItemRemovalL() + { + iDisableChangesToShownIndexes = ETrue; + if (iListBox) + { + TRAP_IGNORE(iListBox->HandleItemRemovalL()); + } + iDisableChangesToShownIndexes = EFalse; + } + +EXPORT_C void CAknListBoxFilterItems::SetObserver(MCoeControlObserver *aObserver) + { + iObserver = aObserver; + } + +EXPORT_C void CAknListBoxFilterItems::HandleOfferkeyEventL() + { + if (!iOldSearchCriteria) + { + // This can happen if we have leaved on one of our AllocL()'s and the application resumes the execution. + // Thus, we'll leave and feel safe later in this method to use iOldSearchCriteria without checking it. + iOldSearchCriteria = _L("").AllocL(); // try to resume to valid state... + User::Leave(KErrNoMemory); + } + // + // NOTE! Order of calls to iListBox is important in this method. + // The SetCurrentItemIndex(0) call MUST be before HandleItemAdditionL() + // and handleitemremovalL() calls. + // + // Check if search string has changed. + TBuf<256> newcriteria; + if (iSearchField) + iSearchField->GetSearchText(newcriteria); + + // Check if item count has changed. + const MDesCArray *array = iModel->MatchableTextArray(); + if (array->MdcaCount() != iOldItemCount) + { + ReleaseCriteriaL(newcriteria); + if (newcriteria.Compare(*iOldSearchCriteria) != 0 && iShownIndexes->Count()>0) + { + if (iListBox) + iListBox->SetCurrentItemIndex(0); + } + HandleItemAdditionL(); + iOldItemCount = array->MdcaCount(); + } + else + { + if (newcriteria.Compare(*iOldSearchCriteria) == 0) return; + if (iShownIndexes->Count()>0) + if (iListBox) + iListBox->SetCurrentItemIndex(0); + + FetchSelectionIndexesFromListBoxL(); + if (newcriteria.Length() == 0) + { + NoCriteriaL(); + HandleItemAdditionL(); + } + else if ( newcriteria.Length() > (*iOldSearchCriteria).Length() && + newcriteria.Find(*iOldSearchCriteria) == 0 ) + { + TightenCriteriaL(newcriteria); + HandleItemRemovalL(); + } + else + { + ReleaseCriteriaL(newcriteria); + HandleItemAdditionL(); + } + PushSelectionIndexesToListBoxL(); + } + + delete iOldSearchCriteria; + iOldSearchCriteria = NULL; + iOldSearchCriteria = newcriteria.AllocL(); + if (iListBox) + iListBox->DrawDeferred(); + } + + +EXPORT_C TPtrC CAknListBoxFilterItems::DefaultMatchableItemFromItem( TPtrC aText ) + { + // This implementation requirescolumnlistbox or formattedcelllistbox itemdrawer/data.. + iMatchableText = aText.Left(Min(aText.Length(), iMatchableText.MaxLength()-1)); + AknTextUtils::ReplaceCharacters(iMatchableText, KAknReplaceListControlChars, TChar(' ')); + _LIT(KSpace," "); + AknTextUtils::PackWhiteSpaces(iMatchableText, KSpace); + + if ( iMatchableText.Length() && iMatchableText[0] == ' ' ) + { + // remove one space if its at beginning of the string. + iMatchableText = iMatchableText.Mid(1); + } + return iMatchableText; + } + +EXPORT_C TInt CAknListBoxFilterItems::FilteredNumberOfItems() const + { + return iShownIndexes->Count(); + } + +EXPORT_C TInt CAknListBoxFilterItems::FilteredItemIndex(TInt aVisibleItemIndex) const + { + return iShownIndexes->At(aVisibleItemIndex); + } + +EXPORT_C TInt CAknListBoxFilterItems::VisibleItemIndex(TInt aOriginalIndex) const + { + TKeyArrayFix key(0, ECmpTInt); + TInt pos; + if (!(iShownIndexes->Find(aOriginalIndex, key,pos))) + return pos; // found + else + return -1; // not found + } + +EXPORT_C CArrayFix *CAknListBoxFilterItems::SelectionIndexes() + { + return iSelectionIndexes; + } + +EXPORT_C void CAknListBoxFilterItems::UpdateSelectionIndexesL() + { + FetchSelectionIndexesFromListBoxL(); + } + +EXPORT_C void CAknListBoxFilterItems::UpdateSelectionIndexL(TInt aVisibleIndex) + { + if (!iView) return; + TInt realindex = FilteredItemIndex(aVisibleIndex); + if (!iView->ItemIsSelected(aVisibleIndex)) + { + // Not selected - remove the item from selection indexes if it still exists there. + TKeyArrayFix key(0, ECmpTInt); + TInt pos; + if (!(iSelectionIndexes->Find(realindex, key,pos))) + { + iSelectionIndexes->Delete(pos); + } + } + else + { // Selected -- add the item to seletion indexes if it didnt exists there yet + TKeyArrayFix key(0,ECmpTInt); + TInt pos; + if (iSelectionIndexes->Find(realindex, key, pos)) + { + iSelectionIndexes->AppendL(realindex); + } + } + } + +EXPORT_C TInt CAknListBoxFilterItems::NonFilteredNumberOfItems() const + { + if (iModel->MatchableTextArray()) + return iModel->MatchableTextArray()->MdcaCount(); + else + return iModel->NumberOfItems(); + } + +void CAknListBoxFilterItems::InstallEmptyTextL() + { + if (iEmptyListText) return; // Do not install, if we have one already + if (!iListBox ||!iListBox->View()) return; // Do not install, if we do not have listbox yet. + + iEmptyListText = iListBox->View()->EmptyListText()->AllocL(); + TResourceReader rr; + CEikonEnv::Static()->CreateResourceReaderLC(rr, R_AVKON_FIND_NO_MATCHES); + TPtrC ptr = rr.ReadTPtrC(); + if (iListBox && iListBox->View()) + iListBox->View()->SetListEmptyTextL(ptr); + CleanupStack::PopAndDestroy(); // resourcereader rr + } + +void CAknListBoxFilterItems::UninstallEmptyTextL() + { + if (!iEmptyListText) return; + if (!iListBox || !iListBox->View()) return; + iListBox->View()->SetListEmptyTextL(iEmptyListText->Des()); + delete iEmptyListText; + iEmptyListText = 0; + } + +void CAknListBoxFilterItems::FetchSelectionIndexesFromListBoxL() + { + // go through all visible items, and update + //the iSelectionIndexes (of this class, not listbox) to match + // with all visible item selection states! + TInt count = FilteredNumberOfItems(); + for(TInt i=0; iFind(realindex,key,pos) ) + iView->DeselectItem(i); + else + iView->SelectItemL(i); + } + } + +EXPORT_C void CAknListBoxFilterItems::ResetFilteringL() + { + if (iDisableChangesToShownIndexes) return; + + // needs to be done or selections go broken. + FetchSelectionIndexesFromListBoxL(); + + delete iOldSearchCriteria; + iOldSearchCriteria = NULL; + iOldSearchCriteria = _L("").AllocL(); + + NoCriteriaL(); + // needs to be done or scrollbar crashes + HandleItemAdditionL(); + PushSelectionIndexesToListBoxL(); + } + +EXPORT_C void CAknListBoxFilterItems::UpdateCachedDataL() + { + TBuf<256> newcriteria; + if (iSearchField) + iSearchField->GetSearchText(newcriteria); + + delete iOldSearchCriteria; + iOldSearchCriteria = NULL; + iOldSearchCriteria = newcriteria.AllocL(); + + FetchSelectionIndexesFromListBoxL(); + } + + +void CAknListBoxFilterItems::NoCriteriaL(TBool aUpdateAS) + { + if (iDisableChangesToShownIndexes) return; + // Handles filtering + TInt count =0; + if (iModel->MatchableTextArray()) + count = iModel->MatchableTextArray()->MdcaCount(); + else + count = iModel->NumberOfItems(); + + iShownIndexes->Reset(); + + const MDesCArray *array = iModel->MatchableTextArray(); + const CAknFilteredTextListBoxModel* arr = (CAknFilteredTextListBoxModel*)(iModel->MatchableTextArray()); + + // If adaptive search manage with next characters + if( iSearchField && IsAdaptiveSearch() ) + { + ClearNextChars(); + TBitFlags32 columnFlag = iSearchField->ListColumnFilterFlags(); + HBufC* temptext = HBufC::NewL( KMatchingBufferLength ); + CleanupStack::PushL( temptext ); + TPtr ptr_temptext( temptext->Des() ); + + for( TInt i = 0; i < count; i++ ) + { + TPtrC itemtext = arr->ItemTextArray()->MdcaPoint(i); + AknFind::UpdateItemTextAccordingToFlag( itemtext, columnFlag, ptr_temptext ); + + // this need to be done for update iNextChars for AdaptiveGrid + // ESMG-7LKAE4, use FindUtil is slow, but it is necessary for Chinese + if ( AknLayoutUtils::Variant() == EApacVariant ) + { + iExtension->iFindUtil->Interface()->MatchAdaptiveRefineL( + ptr_temptext, KNullDesC, iExtension->iNextChars); + } + else + { + AknFind::UpdateNextCharsFromString( iExtension->iNextChars, temptext->Des() ); + } + iShownIndexes->AppendL( i ); + ptr_temptext.Zero(); + } + if( aUpdateAS ) + { + TPtr nextChars = iExtension->iNextChars->Des(); + CDesCArray* array = new (ELeave) CDesCArrayFlat(10); + CleanupStack::PushL(array); + + TInt length = nextChars.Length(); + TInt count(0); + + for( TInt i = 0; i < length; i++ ) + { + if ( (i < length-2) && IsIndicHalantChar( nextChars[i+1] ) ) + { + array->AppendL( nextChars.Mid(i,3) ); + i+=2; + ++count; + } + else + { + array->AppendL( nextChars.Mid(i,1) ); + ++count; + } + } + + // Alphabetical sort + array->Sort( ECmpCollated ); + nextChars.Delete( 0, nextChars.Length() ); + + for( TInt i = 0; i < count; i++ ) + { + nextChars.Append(array->MdcaPoint(i)); + } + CleanupStack::PopAndDestroy(array); + + iSearchField->SetAdaptiveGridChars( *(iExtension->iNextChars) ); + } + CleanupStack::PopAndDestroy( temptext ); + } + else + { + for( TInt i = 0; i < count; i++ ) + { + iShownIndexes->AppendL( i ); + } + } + + // empty text + UninstallEmptyTextL(); + } + +void CAknListBoxFilterItems::TightenCriteriaL(const TDesC &aCriteria) + { + if (iDisableChangesToShownIndexes) + { + return; + } + // This loop goes backwards to avoid changing the indexes in the shownindexes list before we need them + const MDesCArray *array = iModel->MatchableTextArray(); + const CAknFilteredTextListBoxModel* arr = (CAknFilteredTextListBoxModel*)(iModel->MatchableTextArray()); + + // If adaptive search manage with next characters + if ( iExtension->iDigraphChars->Length() != 0 ) + { + NoCriteriaL( EFalse ); + } + + // an index to end of array + TInt indexEnd = iShownIndexes->Count(); + // If adaptive search manage with next characters + if( iSearchField && IsAdaptiveSearch() ) + { + ClearNextChars(); + TBitFlags32 columnFlag = iSearchField->ListColumnFilterFlags(); + HBufC16* temptext = HBufC16::NewL( KMatchingBufferLength ); + CleanupStack::PushL( temptext ); + TPtr ptr_temptext( temptext->Des() ); + for ( TInt i = iShownIndexes->Count()-1; i>=0; i-- ) + { + TInt realindex = iShownIndexes->At( i ); + TPtrC itemtext = arr->ItemTextArray()->MdcaPoint(realindex); + AknFind::UpdateItemTextAccordingToFlag( itemtext, columnFlag, ptr_temptext ); + TBool isItemVisible = IsItemVisible(ptr_temptext, aCriteria); + TBool isItemSelected = IsItemSelected(realindex); + // set it as current index when found item + if ( isItemVisible ) + { + indexEnd = iShownIndexes->Count() - i; + } + else if ( !(isItemVisible || isItemSelected) ) + { + iShownIndexes->Delete(i); + } + ptr_temptext.Zero(); + } + + TPtr nextChars = iExtension->iNextChars->Des(); + CDesCArray* array = new (ELeave) CDesCArrayFlat(10); + CleanupStack::PushL(array); + + TInt length = nextChars.Length(); + TInt count(0); + + for( TInt i = 0; i < length; i++ ) + { + if ( (i < length-2) && IsIndicHalantChar( nextChars[i+1] ) ) + { + array->AppendL( nextChars.Mid(i,3) ); + i+=2; + ++count; + } + else + { + array->AppendL( nextChars.Mid(i,1) ); + ++count; + } + } + + // Alphabetical sort + array->Sort( ECmpCollated ); + nextChars.Delete( 0, nextChars.Length() ); + + for( TInt i = 0; i < count; i++ ) + { + nextChars.Append(array->MdcaPoint(i)); + } + CleanupStack::PopAndDestroy(array); + + iSearchField->SetAdaptiveGridChars( *(iExtension->iNextChars) ); + CleanupStack::PopAndDestroy( temptext ); + } + else + { + for (TInt i = iShownIndexes->Count()-1; i>=0 ; i--) + { + TInt realindex = iShownIndexes->At(i); + TPtrC itemtext = array->MdcaPoint(realindex); + TBool isItemVisible = IsItemVisible(itemtext, aCriteria); + TBool isItemSelected = IsItemSelected(realindex); + // EAJA-7SK9UC set indexToSet as current index when found item + if ( isItemVisible ) + { + indexEnd = iShownIndexes->Count() - i; + } + else if ( !(isItemVisible || isItemSelected) ) + { + iShownIndexes->Delete(i); + } + } + } + InstallEmptyTextL(); + + // Set highlight to the first match item in markable list + if (iListBox) + { + iListBox->SetCurrentItemIndex( Max( iShownIndexes->Count() - indexEnd, 0 )); + } + } + +void CAknListBoxFilterItems::ReleaseCriteriaL( const TDesC &aCriteria ) + { + if ( iDisableChangesToShownIndexes ) + { + return; + } + + // An index to set highlight after find pane updating + TInt indexToSet = KInvalidIndex; + iShownIndexes->Reset(); + // If adaptive search field + if( iSearchField && IsAdaptiveSearch() ) + { + ClearNextChars(); + TBitFlags32 columnFlag = iSearchField->ListColumnFilterFlags(); + HBufC16* temptext = HBufC16::NewL( KMatchingBufferLength ); + CleanupStack::PushL( temptext ); + TPtr ptr_temptext( temptext->Des() ); + const MDesCArray *array = iModel->MatchableTextArray(); + const CAknFilteredTextListBoxModel* arr = (CAknFilteredTextListBoxModel*)(iModel->MatchableTextArray()); + TInt count = array->MdcaCount(); + + for (TInt i = 0; i < count; i++) + { + TPtrC itemtext = arr->ItemTextArray()->MdcaPoint(i); + AknFind::UpdateItemTextAccordingToFlag( itemtext, columnFlag, ptr_temptext ); + TBool isItemVisible = IsItemVisible(temptext->Des(), aCriteria); + // Find first match item to set highlight + if ( (indexToSet == KInvalidIndex) && isItemVisible ) + { + indexToSet = iShownIndexes->Count(); + } + if ( isItemVisible || IsItemSelected(i)) + { + iShownIndexes->AppendL(i); + } + ptr_temptext.Zero(); + } + iSearchField->SetAdaptiveGridChars( *(iExtension->iNextChars) ); + InstallEmptyTextL(); + CleanupStack::PopAndDestroy( temptext ); + } + else + { + const MDesCArray *array = iModel->MatchableTextArray(); + TInt count = array->MdcaCount(); + TInt i; + + if ( aCriteria.Length() == 0) + { + /* If there is no search criteria - most commonly when list is + * created - there is no point to test each item separately, + * just append them all. This results to a HUGE performance + * gain in large lists. + */ + for( i = 0; i < count ; i++ ) + { + iShownIndexes->AppendL(i); + } + UninstallEmptyTextL(); + } + else + { + for( i = 0; i < count ; i++ ) + { + TPtrC itemtext = array->MdcaPoint(i); + TBool isItemVisible = IsItemVisible(itemtext, aCriteria); + + // Find first match item to set highlight + if ((indexToSet == KInvalidIndex) && isItemVisible) + { + indexToSet = iShownIndexes->Count(); + } + if ( isItemVisible || IsItemSelected(i)) + { + iShownIndexes->AppendL(i); + } + } + InstallEmptyTextL(); + } + } + + // Set highlight to the first match item in markable list + if ( iListBox && indexToSet != KInvalidIndex ) + { + iListBox->SetCurrentItemIndex( Max(indexToSet, 0) ); + } + } + +void CAknListBoxFilterItems::ClearNextChars() + { + if( iExtension->iNextChars ) + { + TPtr ptr = iExtension->iNextChars->Des(); + ptr.Delete( 0, ptr.Length() ); + ptr.Zero(); + } + } + +TBool CAknListBoxFilterItems::IsAdaptiveSearch() const + { + if ( iSearchField->SearchFieldStyle() == CAknSearchField::EAdaptiveSearch || + iSearchField->SearchFieldStyle() == CAknSearchField::EAdaptive || + iSearchField->SearchFieldStyle() == CAknSearchField::EPopupAdaptiveSearch || + iSearchField->SearchFieldStyle() == CAknSearchField::EPopupAdaptiveSearchWindow ) + return ETrue; + else + return EFalse; + } + +TBool CAknListBoxFilterItems::IsItemSelected(TInt aRealIndex) const + { + TKeyArrayFix key(0, ECmpTInt); + TInt pos; + if (iSelectionIndexes->Find(aRealIndex, key, pos)) + return EFalse; + else + return ETrue; + } + +TBool CAknListBoxFilterItems::IsItemVisible(const TDesC &aItemString, const TDesC &aSearchText) + { + TBool val = ETrue; + // If findutil supported + if ( iExtension->iFindUtil ) + { + if( iSearchField && IsAdaptiveSearch() ) + { + TRAP_IGNORE( + val = iExtension->iFindUtil->Interface()->MatchAdaptiveRefineL(aItemString, aSearchText, iExtension->iNextChars)); + } + else + { + TRAP_IGNORE( + val = iExtension->iFindUtil->Interface()->MatchRefineL(aItemString, aSearchText)); + } + } + else + { + if( iSearchField && IsAdaptiveSearch() ) + { + val = AknFind::IsAdaptiveFindMatch( aItemString, aSearchText, iExtension->iNextChars ); + } + else + { + val = AknFind::IsFindMatch( aItemString, aSearchText ); + } + } + return val; + } + +TBool CAknListBoxFilterItems::IsSeparatorCharacter(TChar c) + { + return AknFind::IsFindWordSeparator(c); + } + + +EXPORT_C void AknSelectionService::HandleSelectionListProcessCommandL(TInt /*aCommand*/, + CEikListBox* /*aListBox*/) + { } + +EXPORT_C void AknSelectionService::HandleMultiselectionListProcessCommandL(TInt aCommand, + CEikListBox* aListBox) +{ + switch(aCommand) + { + case EAknSoftkeyOk: + if (aListBox->SelectionIndexes()->Count()==0 && aListBox->View()->CurrentItemIndex()>=0) + { + aListBox->View()->SelectItemL(aListBox->View()->CurrentItemIndex()); + } + } +} + +EXPORT_C void AknSelectionService::HandleMarkableListProcessCommandL(TInt aCommand, + CEikListBox* aListBox) + { + switch(aCommand) + { + + case EAknCmdMark: + aListBox->View()->SelectItemL(aListBox->View()->CurrentItemIndex()); + aListBox->View()->DrawItem(aListBox->View()->CurrentItemIndex()); + break; + case EAknCmdUnmark: + aListBox->View()->DeselectItem(aListBox->View()->CurrentItemIndex()); + aListBox->View()->DrawItem(aListBox->View()->CurrentItemIndex()); + break; + case EAknMarkAll: + { + aListBox->ClearSelection(); + TInt num = aListBox->Model()->NumberOfItems(); + if (num < 1) return; + TInt ii=0; + CArrayFixFlat* array = new(ELeave) CArrayFixFlat(20); + CleanupStack::PushL(array); + array->SetReserveL(num); + for(ii=0;iiAppendL(ii); + } + aListBox->SetSelectionIndexesL(array); + CleanupStack::PopAndDestroy(); //array + break; + } + case EAknUnmarkAll: + aListBox->ClearSelection(); + break; + }; + } +EXPORT_C void AknSelectionService::HandleMarkableListDynInitMenuPane(TInt aResourceId, CEikMenuPane *aMenu, CEikListBox *aListBox) + { + if (aResourceId == R_AVKON_MENUPANE_MARKABLE_LIST_IMPLEMENTATION) + { + TInt currentItemIndex = aListBox->View()->CurrentItemIndex(); + TBool markHidden = aListBox->View()->ItemIsSelected(currentItemIndex); + TBool unmarkHidden = !aListBox->View()->ItemIsSelected(currentItemIndex); + TBool markAllHidden = aListBox->Model()->NumberOfItems() == 0 || aListBox->SelectionIndexes()->Count()==aListBox->Model()->NumberOfItems(); + TBool unmarkAllHidden = aListBox->Model()->NumberOfItems() == 0 || aListBox->SelectionIndexes()->Count() == 0; + + aMenu->SetItemDimmed(EAknCmdMark, markHidden); + aMenu->SetItemDimmed(EAknCmdUnmark, unmarkHidden); + aMenu->SetItemDimmed(EAknMarkAll, markAllHidden); + aMenu->SetItemDimmed(EAknUnmarkAll, unmarkAllHidden); + } + if (aResourceId == R_AVKON_MENUPANE_MARKABLE_LIST_EDIT_LIST_IMPLEMENTATION + || aResourceId == R_AVKON_MENUPANE_FIND_POPUP_IMPLEMENTATION_MARKABLE + ) + { + TBool editListHidden = aListBox->Model()->NumberOfItems()==0; + + aMenu->SetItemDimmed(EAknCmdEditListMenu, editListHidden); + } + + } + +EXPORT_C void AknSelectionService::HandleMarkableListDynInitMenuItem(CEikMenuPane *aMenu, CEikListBox *aListBox, TInt aCommandId, TBool aCanBeAppliedToMultipleItems) + { + TBool itemhidden = EFalse; + if (!aCanBeAppliedToMultipleItems && aListBox->SelectionIndexes()->Length() > 0) + { + itemhidden = ETrue; + } + aMenu->SetItemDimmed(aCommandId, itemhidden); + } +EXPORT_C void AknSelectionService::HandleMarkableListUpdateAfterCommandExecution(CEikListBox *aListBox) + { + aListBox->ClearSelection(); + } + +EXPORT_C TKeyResponse AknSelectionService::HandleMenuListOfferKeyEventL(const TKeyEvent &aKeyEvent, TEventCode aType, CEikListBox *aListBox) + { + // Ignore number keys, clear key and shift key + if (AknKeys::IsNumberKey(aKeyEvent,aType)) return EKeyWasConsumed; + switch(aKeyEvent.iCode) + { + case EKeyDelete: + case EKeyLeftShift: + case EKeyRightShift: + return EKeyWasConsumed; + default: + break; + }; + + return aListBox->OfferKeyEventL(aKeyEvent, aType); + } +EXPORT_C void AknSelectionService::HandleItemRemovalAndPositionHighlightL(CEikListBox *aListBox, TInt aValueOfCurrentItemIndexBeforeRemoval, CArrayFix &aIndexesToRemovedItemsBeforeRemoval) + { + AknListBoxUtils::HandleItemRemovalAndPositionHighlightL(aListBox, aValueOfCurrentItemIndexBeforeRemoval, aIndexesToRemovedItemsBeforeRemoval); + } + +EXPORT_C void AknSelectionService::HandleItemRemovalAndPositionHighlightL(CEikListBox *aListBox, TInt aValueOfCurrentItemIndexBeforeRemoval, TBool aCurrentItemWasRemoved) + { + AknListBoxUtils::HandleItemRemovalAndPositionHighlightL(aListBox, aValueOfCurrentItemIndexBeforeRemoval, aCurrentItemWasRemoved); + } + +EXPORT_C void AknEditUtils::ConstructEditingL(CEikEdwin *aEdwin, TInt aResourceId) + { + TResourceReader rr; + CEikonEnv::Static()->CreateResourceReaderLC(rr, aResourceId); + ConstructEditingL(aEdwin, rr); + CleanupStack::PopAndDestroy(); + } + +EXPORT_C void AknEditUtils::ConstructEditingL(CEikEdwin *aEdwin, const SAknEditorParameters &aParams) + { + ConstructEditingL(aEdwin, + aParams.iEditingSpace, + aParams.iEditingWindow, + aParams.iCharacterCase, + aParams.iJustification, + aParams.iAllowedToMoveInsertionPoint, + aParams.iCursorYesNo, + aParams.iOverflowYesNo); + } + +EXPORT_C void AknEditUtils::ConstructEditingL(CEikEdwin *aEdwin, TResourceReader &aReader) + { + TInt editingSpace = aReader.ReadInt16(); + TInt editingWindow = aReader.ReadInt16(); + TInt characterCase = aReader.ReadInt16(); + TInt justification = aReader.ReadInt16(); + TInt allowedToMoveInsertionPoint = aReader.ReadInt16(); + TInt cursorYesNo = aReader.ReadInt16(); + TInt overflowYesNo = aReader.ReadInt16(); + ConstructEditingL(aEdwin, editingSpace, editingWindow, characterCase, justification, allowedToMoveInsertionPoint, cursorYesNo, overflowYesNo); + } + + +EXPORT_C void AknEditUtils::ConstructEditingL(CEikEdwin* aEdwin, + TInt aEditingSpace, + TInt aEditingWindow, + TInt aCharacterCase, + TInt aJustification, + TBool aAllowedToMoveInsertionPoint, + TBool aCursorYesNo, + TBool aOverflowYesNo) + { + ConstructEditingL(aEdwin,aEditingSpace,aEditingWindow,aCharacterCase,aJustification, + aAllowedToMoveInsertionPoint, aCursorYesNo, aOverflowYesNo, ETrue); + } + +// +// CAknLayoutUtils +// +EXPORT_C void AknLayoutUtils::LayoutLabel(CEikLabel* aLabel, const TRect &aLabelParent, TInt aResourceId, const CFont *aCustomFont) + { + TResourceReader rr; + TRAPD(error, + { + CEikonEnv::Static()->CreateResourceReaderLC(rr, aResourceId); + LayoutLabel(aLabel, aLabelParent, rr, aCustomFont); + CleanupStack::PopAndDestroy(); + }); + if (error != KErrNone) + { + aLabel->SetRect(TRect(aLabelParent.iTl, TSize(2,2))); + } +#ifdef AKNUTILS_ENABLE_TRACES + __ASSERT_DEBUG(error == KErrNone, LOGTEXT(_L("AknLayoutUtils:LayoutLabel: Resource reader failed."))); +#endif // AKNUTILS_ENABLE_TRACES + } + +EXPORT_C void AknLayoutUtils::LayoutLabel(CEikLabel* aLabel, const TRect &aLabelParent, const SAknLayoutLabel &aL, const CFont *aCustomFont) + { + LayoutLabel(aLabel,aLabelParent, aL.iFont, aL.iC, aL.iL, aL.iR, aL.iB, aL.iW, aL.iJ, aL.iNextLineB, aCustomFont); + } + +EXPORT_C void AknLayoutUtils::LayoutLabel(CEikLabel* aLabel, const TRect &aLabelParent, const TAknMultiLineTextLayout &aL, const CFont *aCustomFont) + { + // if we are using non-encoded fonts, baseline is top relative + // however for encoded fonts, at this stage baseline is actually bottom + // however baseline skip is always a positive delta + TInt correctNextBaseline = TAknFontId::IsEncodedFont(aL.FontId()) ? aL.iB - aL.BaselineSkip() : aL.iB + aL.BaselineSkip(); + LayoutLabel(aLabel,aLabelParent, aL.FontId(), aL.iC, aL.il, aL.ir, aL.iB, aL.iW, aL.iJ, correctNextBaseline, aCustomFont); + } + +EXPORT_C void AknLayoutUtils::LayoutLabel(CEikLabel* aLabel, const TRect &aLabelParent, const TAknTextLineLayout &aL, const CFont *aCustomFont) + { + LayoutLabel(aLabel,aLabelParent, aL.FontId(), aL.iC, aL.il, aL.ir, aL.iB, aL.iW, aL.iJ, aL.iB, aCustomFont); + } + +EXPORT_C void AknLayoutUtils::LayoutLabel(CEikLabel* aLabel, const TRect &aLabelParent, TResourceReader& aReader, const CFont *aCustomFont) + { + TInt fontid = aReader.ReadInt16(); + TInt C = aReader.ReadInt16(); + TInt lm = aReader.ReadInt16(); + TInt rm = aReader.ReadInt16(); + TInt B = aReader.ReadInt16(); + TInt W = aReader.ReadInt16(); + TInt J = aReader.ReadInt16(); + TInt NB = aReader.ReadInt16(); + if (NB == 0) NB = B; + LayoutLabel(aLabel, aLabelParent, fontid, C, lm, rm, B, W, J,NB, aCustomFont); + } + +EXPORT_C void AknLayoutUtils::LayoutLabel(CEikLabel* aLabel, const TRect &aLabelParent, TInt fontid, TInt aColor, TInt aLeftMargin, TInt aRightMargin, TInt aBaseline, TInt aWidth, TInt aJustification, TInt aNextLineB, const CFont *aCustomFont) + { + aBaseline = CorrectBaseline(aLabelParent.Height(), aBaseline, fontid); + aNextLineB = CorrectBaseline(aLabelParent.Height(), aNextLineB, fontid); + + TInt lastBaseLine(0); + if(aNextLineB!=0) + lastBaseLine = (aNextLineB - aBaseline) * aLabel->NumberOfLines() - (aNextLineB - aBaseline); + + const CFont *font = FontFromId(fontid, aCustomFont); + TRect rect = AknLayoutUtils::TextRectFromCoords(aLabelParent, font, aLeftMargin, aRightMargin, aBaseline, aWidth, lastBaseLine); + // Default color is 215 and 99% of cases uses it -- and we want to avoid extra leaving function here. + TRAP_IGNORE(OverrideControlColorL(*aLabel, EColorLabelText, AKN_LAF_COLOR_STATIC(aColor))); + // The semantics of "Gap between lines" is relative to the CFont::HeightInPixels + // That is, the "Gap" is DEFINED to be the difference between the baseline separation and CFont::HeightInPixels + aLabel->SetPixelGapBetweenLines(aNextLineB - aBaseline - font->HeightInPixels()); + aLabel->SetLabelAlignment(aJustification); + aLabel->SetFont(font); + aLabel->SetRect(rect); + } + + +EXPORT_C void AknLayoutUtils::LayoutEdwin(CEikEdwin *aEdwin, const TRect &aEdwinParent, TInt aResourceId, TInt aNumberOfLines, const CFont *aCustomFont, TBool aMinimizeEdwinView) + { + TResourceReader rr; + TRAPD(error, + { + CEikonEnv::Static()->CreateResourceReaderLC(rr, aResourceId); + LayoutEdwin(aEdwin, aEdwinParent, rr, aNumberOfLines, aCustomFont,aMinimizeEdwinView); + CleanupStack::PopAndDestroy(); + }); + if (error != KErrNone) + { + aEdwin->SetRect(TRect(aEdwinParent.iTl, TSize(2,2))); + } +#ifdef AKNUTILS_ENABLE_TRACES + __ASSERT_DEBUG(error == KErrNone, LOGTEXT(_L("AknLayoutUtils:LayoutEdwin: Resource reader failed."))); +#endif // AKNUTILS_ENABLE_TRACES + } + + +EXPORT_C void AknLayoutUtils::LayoutEdwin(CEikEdwin* aEdwin, const TRect &aEdwinParent, const SAknLayoutEdwin &aL, const CFont *aCustomFont, TBool aMinimizeEdwinView) + { + LayoutEdwin(aEdwin,aEdwinParent, aL.iFont, aL.iC, aL.iL, aL.iR, aL.iB, aL.iW, aL.iJ, aL.iNumberOfLinesShown, aL.iNextLineB, aCustomFont,aMinimizeEdwinView); + } + +EXPORT_C void AknLayoutUtils::LayoutEdwin( CEikEdwin* aEdwin, + const TRect &aEdwinParent, + const TAknMultiLineTextLayout &aL, + const CFont *aCustomFont, + TBool aMinimizeEdwinView ) + { + LayoutEdwin( aEdwin, aEdwinParent, aL, (TAknsQsnTextColorsIndex)KTextColorNone, + aCustomFont, aMinimizeEdwinView ); + } + + +EXPORT_C void AknLayoutUtils::LayoutEdwin( CEikEdwin* aEdwin, + const TRect &aEdwinParent, + const TAknMultiLineTextLayout &aL, + TAknsQsnTextColorsIndex aOverrideColor, + const CFont *aCustomFont, + TBool aMinimizeEdwinView ) + { + TInt B = aL.iB; + TInt secondBaseline = 0; + TInt baselineDelta = aL.BaselineSkip(); + + if (IsParentRelative(B)) + B = B - ELayoutP + aEdwinParent.Height(); + if (baselineDelta != 0) + secondBaseline = TAknFontId::IsEncodedFont(aL.FontId()) ? B - baselineDelta : B + baselineDelta; + + LayoutEdwin( aEdwin, + aEdwinParent, + aL.FontId(), + aL.iC, + aL.il, + aL.ir, + aL.iB, + aL.iW, + aL.iJ, + aL.NumberOfLinesShown(), + secondBaseline, + aOverrideColor, + aCustomFont, + aMinimizeEdwinView ); + + } + +EXPORT_C void AknLayoutUtils::LayoutEdwin( CEikEdwin* aEdwin, + const TRect &aEdwinParent, + const TAknTextLineLayout &aL, + TAknsQsnTextColorsIndex aOverrideColor, + const CFont *aCustomFont, + TBool aMinimizeEdwinView ) + { + /* + Handle the different system of defaults in the layout dll and this routine: + In Aknlayout dll, zero baselineSkip() means that there is no 2nd baseline. + So in that case, 0 should be passed as secondBaseline to the called LayoutEdwin method + */ + TInt B = aL.iB; + TInt secondBaseline = 0; + TInt baselineDelta = aL.BaselineSkip(); + + if (IsParentRelative(B)) + B = B - ELayoutP + aEdwinParent.Height(); + if (baselineDelta != 0) + secondBaseline = TAknFontId::IsEncodedFont(aL.FontId()) ? B - baselineDelta : B + baselineDelta; + + LayoutEdwin( aEdwin, aEdwinParent, aL.FontId(), aL.iC, aL.il, aL.ir, aL.iB, + aL.iW, aL.iJ, aL.NumberOfLinesShown(), secondBaseline, + aOverrideColor, aCustomFont, aMinimizeEdwinView ); + } + +EXPORT_C void AknLayoutUtils::LayoutEdwin(CEikEdwin* aEdwin, const TRect &aEdwinParent, const TAknTextLineLayout &aL, const CFont *aCustomFont, TBool aMinimizeEdwinView) + { + LayoutEdwin( aEdwin, aEdwinParent, aL, (TAknsQsnTextColorsIndex) KTextColorNone, + aCustomFont, aMinimizeEdwinView); + } + +EXPORT_C void AknLayoutUtils::LayoutEdwin(CEikEdwin *aEdwin, const TRect &aEdwinParent, TResourceReader &aReader, TInt aNumberOfLines, const CFont *aCustomFont, TBool aMinimizeEdwinView) + { + TInt fontid = aReader.ReadInt16(); + TInt C = aReader.ReadInt16(); + TInt lm = aReader.ReadInt16(); + TInt rm = aReader.ReadInt16(); + TInt B = aReader.ReadInt16(); + TInt W = aReader.ReadInt16(); + TInt J = aReader.ReadInt16(); + TInt numberOfLinesShown = aReader.ReadInt16(); + if ( aNumberOfLines ) + numberOfLinesShown = aNumberOfLines ; + TInt aNextLineBaseline = aReader.ReadInt16(); + LayoutEdwin(aEdwin, aEdwinParent, fontid, C, lm, rm, B, W, J, numberOfLinesShown, aNextLineBaseline, aCustomFont,aMinimizeEdwinView); + } + +EXPORT_C void AknLayoutUtils::LayoutEdwin( CEikEdwin *aEdwin, + const TRect &aEdwinParent, + TInt fontid, + TInt aColor, + TInt aLeftMargin, + TInt aRightMargin, + TInt aBaseline, + TInt aWidth, + TInt aJustification, + TInt aNumberOfLinesShown, + TInt aSecondLineBaseline, + const CFont *aCustomFont, + TBool aMinimizeEdwinView ) + { + LayoutEdwin( aEdwin, + aEdwinParent, + fontid, + aColor, + aLeftMargin, + aRightMargin, + aBaseline, + aWidth, + aJustification, + aNumberOfLinesShown, + aSecondLineBaseline, + (TAknsQsnTextColorsIndex) KTextColorNone, + aCustomFont, + aMinimizeEdwinView ); + + } + +TBool IsEmpty(TInt aValue) + { + return aValue == ELayoutEmpty; + } + +EXPORT_C void AknLayoutUtils::LayoutEdwin( CEikEdwin *aEdwin, + const TRect &aEdwinParent, + TInt fontid, + TInt aColor, + TInt aLeftMargin, + TInt aRightMargin, + TInt aBaseline, + TInt aWidth, + TInt aJustification, + TInt aNumberOfLinesShown, + TInt aSecondLineBaseline, + TAknsQsnTextColorsIndex aOverrideColor, + const CFont *aCustomFont, + TBool aMinimizeEdwinView ) + { +// Whether we test on IsEncodedFont is determined by how well the code +// can cope with "lay file" layouts and legacy and logical font ids. +// It is highly desirable that we can manage with only the layoutEdwinScalable implementation +// if(TAknFontSpecification::IsEncodedFont(aFontId)) + if ( aCustomFont ) + { + __ASSERT_DEBUG( CAknLayoutFont::AsCAknLayoutFontOrNull( aCustomFont ), Panic( EAknPanicFontProvisionFailure ) ); + } + + AknLayoutUtilsHelpers::LayoutEdwinScalable( aEdwin, + aEdwinParent, + fontid, + aColor, + aLeftMargin, + aRightMargin, + aBaseline, + aWidth, + aJustification, + aNumberOfLinesShown, + aSecondLineBaseline, + aOverrideColor, + static_cast(aCustomFont), + aMinimizeEdwinView); + } + +EXPORT_C void AknLayoutUtils::LayoutEdwin( CEikEdwin* aEdwin, + const TRect& aEdwinParent, + const TAknTextLineLayout& aLayout, + TInt aNumberOfLinesToShowOverride, + TInt aBaselineSeparationOverride, + TAknsQsnTextColorsIndex aOverrideColor, + TInt& aNumberOfVisibleLines ) + { + __ASSERT_DEBUG(aEdwin,Panic(EAknLayoutEdwinPanicNoEdwin)); + + TInt fontId = aLayout.FontId(); + + // EFontCustom id not supported + __ASSERT_DEBUG( fontId!=EFontCustom ,Panic(EAknLayoutEdwinPanicNotSupported)); + + const CAknLayoutFont* font = AknLayoutUtils::LayoutFontFromId( fontId, NULL); + + TInt firstBaseline = CorrectBaseline(aEdwinParent.Height(), aLayout.iB, fontId); + firstBaseline += 1; // This puts baseline into a more natural definition + // baseline now refers to the distance from the top of the parent down to the baseline + + TInt leftMargin = aLayout.ir; + TInt rightMargin = aLayout.il; + TInt width = aLayout.iW; + if (IsParentRelative(leftMargin)) { leftMargin = aEdwinParent.Width() - ELayoutP + leftMargin; } + if (IsParentRelative(rightMargin)) { rightMargin = aEdwinParent.Width() - ELayoutP + rightMargin; } + if (IsParentRelative(width)) { width = aEdwinParent.Width() - ELayoutP + width; } + + if (IsEmpty(leftMargin)) { leftMargin = aEdwinParent.Width() - rightMargin - width; } + if (IsEmpty(rightMargin)) { rightMargin = aEdwinParent.Width() - leftMargin - width; } + if (IsEmpty(width)) { width = aEdwinParent.Width() - leftMargin - rightMargin; } + + TAknTextDecorationMetrics metrics( fontId ); + + TInt numberOfLinesToShow = aLayout.NumberOfLinesShown(); + if ( aNumberOfLinesToShowOverride > 0) + numberOfLinesToShow = aNumberOfLinesToShowOverride; + __ASSERT_DEBUG(!(aEdwin->MaximumHeightInLines())||numberOfLinesToShow<=aEdwin->MaximumHeightInLines(),Panic(EAknLayoutEdwinPanicNoLinesOverMaxNoLines)); + + TInt secondBaseline = 0; + if ( numberOfLinesToShow < 2) + { + secondBaseline = 0; + } + else + { + TInt baselineDelta = aLayout.BaselineSkip(); + if ( aBaselineSeparationOverride > 0) + baselineDelta = aBaselineSeparationOverride; + + if (baselineDelta != 0) + secondBaseline = firstBaseline + baselineDelta; + } + + AknLayoutUtilsHelpers::LayoutEdwinScalableWithCorrectedParametersAndDecorationMetrics( + aEdwin, + aEdwinParent, + font, + aLayout.iC, + leftMargin, + rightMargin, + firstBaseline, + width, + aLayout.iJ, + numberOfLinesToShow, + secondBaseline, + aOverrideColor, + metrics, + ETrue, // Constrain to fit within parent + aNumberOfVisibleLines); + + } + + +EXPORT_C TRect AknLayoutUtils::MinimizedEdwinRect(const CEikEdwin *aEdwin) + { + if (!aEdwin->TextView() || aEdwin->TextView()->AlteredViewRect().Size().iHeight == 0) + { + return aEdwin->Rect(); + } + return aEdwin->TextView()->AlteredViewRect(); + } + +EXPORT_C void AknLayoutUtils::LayoutMfne(CEikMfne *aMfne, const TRect &aMfneParent, TInt aResourceId) + { + TResourceReader rr; + TRAPD(error, + { + CEikonEnv::Static()->CreateResourceReaderLC(rr, aResourceId); + LayoutMfne(aMfne, aMfneParent, rr); + CleanupStack::PopAndDestroy(); + }); + if (error != KErrNone) + { + aMfne->SetRect(TRect(aMfneParent.iTl, TSize(2,2))); + aMfne->SetMfneAlignment(-1); // nasty + } +#ifdef AKNUTILS_ENABLE_TRACES + __ASSERT_DEBUG(error == KErrNone, LOGTEXT(_L("AknLayoutUtils:LayoutLabel: Resource reader failed."))); +#endif // AKNUTILS_ENABLE_TRACES + } + +EXPORT_C void AknLayoutUtils::LayoutMfne(CEikMfne* aMfne, const TRect &aMfneParent, const SAknLayoutMfne &aL) + { + LayoutMfne(aMfne,aMfneParent, aL.iFont, aL.iC, aL.iL, aL.iR, aL.iB, aL.iW, aL.iJ); + } + +EXPORT_C void AknLayoutUtils::LayoutMfne(CEikMfne* aMfne, const TRect &aMfneParent, const TAknTextLineLayout &aL) + { + LayoutMfne(aMfne,aMfneParent, aL.FontId(), aL.iC, aL.il, aL.ir, aL.iB, aL.iW, aL.iJ); + } + +EXPORT_C void AknLayoutUtils::LayoutMfne(CEikMfne *aMfne, const TRect &aMfneParent, TResourceReader &aReader) + { + TInt fontid = aReader.ReadInt16(); + TInt C = aReader.ReadInt16(); + TInt lm = aReader.ReadInt16(); + TInt rm = aReader.ReadInt16(); + TInt B = aReader.ReadInt16(); + TInt W = aReader.ReadInt16(); + TInt J = aReader.ReadInt16(); + LayoutMfne(aMfne, aMfneParent, fontid, C, lm, rm, B, W, J); + } + +EXPORT_C void AknLayoutUtils::LayoutMfne(CEikMfne *aMfne, const TRect &aMfneParent, TInt fontid, TInt /*aColor*/, TInt aLeftMargin, TInt aRightMargin, TInt aBaseline, TInt aWidth, TInt aJustification) + { + // This routine adds top, bottom and left and right margins to the text + + // Corrects the baseline in the case of using new scalable layout data + aBaseline = CorrectBaseline(aMfneParent.Height(), aBaseline, fontid); + + aMfne->SetBorder(TGulBorder::ENone); + const CFont *font = FontFromId(fontid); + aMfne->SetFont(font); + + TRect rect = TextRectFromCoords(aMfneParent, font, aLeftMargin, aRightMargin, aBaseline, aWidth ); + // Margin correction done already at the top + TAknTextDecorationMetrics decoration( fontid ); + TInt extension1(0); + TInt extension2(0); + decoration.GetLeftAndRightMargins( extension1, extension2 ); + + // Since these margins are the ones drawn in by the MFNE, we expand the MFNE to include these margins + rect.iTl.iX -= extension1; + rect.iBr.iX += extension2; + + // In scalable UI, these margins are also included in the height + // Done by magic numbers previously + decoration.GetTopAndBottomMargins( extension1, extension2 ); + rect.iTl.iY -= extension1; + rect.iBr.iY += extension2; + + aMfne->SetRect( rect ); + aMfne->SetMfneAlignment(aJustification); // let MNFE realign it self + } + + +EXPORT_C void AknLayoutUtils::LayoutControl(CCoeControl *aControl, const TRect &aParent, TInt aResourceId) + { + TResourceReader rr; + TRAPD(error, + { + CEikonEnv::Static()->CreateResourceReaderLC(rr, aResourceId); + LayoutControl(aControl, aParent, rr); + CleanupStack::PopAndDestroy(); + }); + if (error != KErrNone) + { + aControl->SetRect(TRect(aParent.iTl, TSize(2,2))); + } +#ifdef AKNUTILS_ENABLE_TRACES + __ASSERT_DEBUG(error == KErrNone, LOGTEXT(_L("AknLayoutUtils:LayoutControl: Resource reader failed."))); +#endif // AKNUTILS_ENABLE_TRACES + } + +EXPORT_C void AknLayoutUtils::LayoutControl(CCoeControl *aControl, const TRect &aParent, const SAknLayoutControl &aL) + { + LayoutControl(aControl, aParent, aL.iC,aL.iL, aL.iT, aL.iR, aL.iB, aL.iW, aL.iH); + } + +EXPORT_C void AknLayoutUtils::LayoutControl(CCoeControl *aControl, const TRect &aParent, const TAknWindowLineLayout &aL) + { + LayoutControl(aControl, aParent, aL.iC,aL.il, aL.it, aL.ir, aL.ib, aL.iW, aL.iH); + } + +EXPORT_C void AknLayoutUtils::LayoutControl(CCoeControl *aControl, const TRect &aParent, TResourceReader &aReader) + { + TInt C = aReader.ReadInt16(); + TInt l = aReader.ReadInt16(); + TInt t = aReader.ReadInt16(); + TInt r = aReader.ReadInt16(); + TInt b = aReader.ReadInt16(); + TInt W = aReader.ReadInt16(); + TInt H = aReader.ReadInt16(); + LayoutControl(aControl, aParent, C,l,t,r,b,W,H); + } + +EXPORT_C void AknLayoutUtils::LayoutControl(CCoeControl *aControl, const TRect &aParent, TInt /*C*/, TInt l, TInt t, TInt r, TInt b, TInt W, TInt H) + { + TRect rect = RectFromCoords(aParent, l, t, r, b, W, H); + aControl->SetRect(rect); +#ifdef AKNUTILS_ENABLE_TRACES + __ASSERT_DEBUG(aControl->Size() == rect.Size(), LOGTEXT(_L("AknLayoutUtils/LayoutControl: ERROR: Control changed its size in SizeChanged() - That is NOT allowed"))); +#endif // AKNUTILS_ENABLE_TRACES + } + + +EXPORT_C void AknLayoutUtils::LayoutImage(CEikImage *aImage, const TRect &aParent, TInt aResourceId) + { + LayoutControl(aImage, aParent, aResourceId); + } + +EXPORT_C void AknLayoutUtils::LayoutImage(CEikImage *aImage, const TRect &aParent, const SAknLayoutControl &aL) + { + LayoutImage(aImage, aParent, aL.iC,aL.iL, aL.iT, aL.iR, aL.iB, aL.iW, aL.iH); + } + +EXPORT_C void AknLayoutUtils::LayoutImage(CEikImage *aImage, const TRect &aParent, const TAknWindowLineLayout &aL) + { + LayoutImage(aImage, aParent, aL.iC,aL.il, aL.it, aL.ir, aL.ib, aL.iW, aL.iH); + } + +EXPORT_C void AknLayoutUtils::LayoutImage(CEikImage *aImage, const TRect &aParent, TResourceReader &aReader) + { + LayoutControl(aImage,aParent,aReader); + } + +EXPORT_C void AknLayoutUtils::LayoutImage(CEikImage *aImage, const TRect &aParent, TInt C, TInt l, TInt t, TInt r, TInt b, TInt W, TInt H) + { + LayoutControl(aImage, aParent,C,l,t,r,b,W,H); + TRect rect = RectFromCoords(aParent, l, t, r, b, W, H); + if (aImage->Bitmap()) + AknIconUtils::SetSize(const_cast(aImage->Bitmap()), rect.Size()); + } + +EXPORT_C void AknLayoutUtils::LayoutSecretEditor(CEikSecretEditor* aSecEd, const TRect& aParent, const SAknLayoutText &aLayout) + { + TInt left = aLayout.iL; + TInt right = aLayout.iR; + TInt baseline = AknLayoutUtils::CorrectBaseline(aParent.Height(), aLayout.iB, aLayout.iFont); + if (IsParentRelative(left)) { left = left - ELayoutP + aParent.Width(); } + if (IsParentRelative(right)) { right = right - ELayoutP + aParent.Width(); } + const CFont *font = FontFromId(aLayout.iFont); + CGraphicsContext::TTextAlign align = TextAlignFromId(aLayout.iJ); + aSecEd->AknSetFont(*font); + aSecEd->AknSetAlignment(align); + aSecEd->SetBorder(TGulBorder::ENone); + TRect rect = TextRectFromCoords(aParent, font, left, right, baseline, aLayout.iW); + // give secret editor margin as well in scalable + TAknTextDecorationMetrics decoration( font ); + TInt extension1(0); + TInt extension2(0); + + decoration.GetLeftAndRightMargins( extension1, extension2 ); + rect.iTl.iX -= extension1; + rect.iBr.iX += extension2; + + // In scalable UI, these margins are also included in the height + decoration.GetTopAndBottomMargins( extension1, extension2 ); + rect.iTl.iY -= extension1; + rect.iBr.iY += extension2; + aSecEd->SetRect(rect); + } + +EXPORT_C void AknLayoutUtils::LayoutSecretEditor(CEikSecretEditor* aSecEd, const TRect& aParent, const TAknTextLineLayout &aLayout) + { + SAknLayoutText layoutStruct = { aLayout.FontId(), aLayout.iC, aLayout.il, aLayout.ir, aLayout.iB, aLayout.iW, aLayout.iJ}; + AknLayoutUtils::LayoutSecretEditor(aSecEd, aParent, layoutStruct); + } + + +// Notice, if you use this, you must ensure that the control you use this with does not have any extra borders or +// other such things -> if you see fonts clipped from bottom, then you have borders somewhere. +EXPORT_C TRect AknLayoutUtils::TextRectFromCoords( + const TRect &aParent, + const CFont *aFont, + TInt aLeftMargin, + TInt aRightMargin, + TInt aBaseline, + TInt aWidth, + TInt aLastBaseline) + { + if (IsParentRelative(aLeftMargin)) { aLeftMargin = aParent.Width() - ELayoutP + aLeftMargin; } + if (IsParentRelative(aRightMargin)) { aRightMargin = aParent.Width() - ELayoutP + aRightMargin; } + if (IsParentRelative(aWidth)) { aWidth = aParent.Width() - ELayoutP + aWidth; } + + if (IsEmpty(aLeftMargin)) { aLeftMargin = aParent.Width() - aRightMargin - aWidth; } + if (IsEmpty(aRightMargin)) { aRightMargin = aParent.Width() - aLeftMargin - aWidth; } + if (IsEmpty(aWidth)) { aWidth = aParent.Width() - aLeftMargin - aRightMargin; } + + (void)aWidth; + TRect rect = aParent; + + // Use these as measures of baseline -> top of pane, and baseline -> bottom of pane + // If its a CAknLayoutFont, then we can use exactly what we need for this + TInt effectiveAscent(0); + TInt effectiveDescent(0); + const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( aFont ); + if ( layoutFont ) + { + effectiveAscent = layoutFont->TextPaneTopToBaseline(); + effectiveDescent = layoutFont->BaselineToTextPaneBottom(); + } + else + { + effectiveAscent = aFont->AscentInPixels(); + effectiveDescent = aFont->DescentInPixels(); + } + + rect.iTl.iX += aLeftMargin; + rect.iBr.iX -= aRightMargin; + // Add one to account for the series 60 layout definition of baseline + rect.iTl.iY += aBaseline + 1 - effectiveAscent; + // Meaning of aLastBaseline is actually (nLines-1)*baselineSeparation + // So bottom position is first baseline + aLastbaseline + descent + extra + // An extra pixel is added in the non-scalable code above, but in scalable we decide not to + // add it: + rect.iBr.iY = aParent.iTl.iY + aBaseline + 1 + aLastBaseline + effectiveDescent; //Vesa + +#ifdef _DEBUG + TInt error = 0; + + __ASSERT_DEBUG(rect.Size().iWidth > 0, (error = 1, LOGTEXT1(_L("AknLayoutUtils: Rect width %d > 0"),rect.Size().iWidth))); + __ASSERT_DEBUG(rect.Size().iHeight > 0, (error = 2, LOGTEXT1(_L("AknLayoutUtils: Rect height %d > 0"), rect.Size().iHeight))); + __ASSERT_DEBUG(rect.Size().iWidth == aWidth, (error = 3, LOGTEXT2(_L("AknLayoutUtils: Calculated rect %d different from one from LAF %d"),rect.Size().iWidth, aWidth))); + if (error) + { + /* a good place for a breakpoint */ + error = error; + } +#endif + + return rect; + } + + +TBool IsParentRelative(TInt aVal) + { + return aVal > ELayoutP-ELayoutPRange && aVal <= ELayoutP; + } + +EXPORT_C TRect AknLayoutUtils::RectFromCoords(const TRect& aParent, TInt l, TInt t, TInt r, TInt b, TInt W, TInt H) + { + // TP HACK + if (l==0&&t==0&&r==0&&b==0&&W==0&&H==0) + { +#ifdef _AKNUTILS_ENABLE_TRACES + LOGTEXT(_L("Error in layout data; ALL ZEROS!")); +#endif // AKNUTILS_ENABLE_TRACES + W=ELayoutEmpty; + H=ELayoutEmpty; + } + // END OF HACK + + TSize sz=aParent.Size(); + if (IsParentRelative(W)) { W = sz.iWidth - ELayoutP + W; } + if (IsParentRelative(H)) { H = sz.iHeight - ELayoutP + H; } + if (IsParentRelative(r)) { r = sz.iWidth - ELayoutP + r; } + if (IsParentRelative(b)) { b = sz.iHeight - ELayoutP + b; } + if (IsParentRelative(l)) { l = sz.iWidth - ELayoutP + l; } + if (IsParentRelative(t)) { t = sz.iHeight - ELayoutP + t; } + + + if (l==ELayoutEmpty) + l=sz.iWidth-W-r; + else if (W==ELayoutEmpty) + W=sz.iWidth-r-l; + + if (t==ELayoutEmpty) + t=sz.iHeight-H-b; + else if (H==ELayoutEmpty) + H=sz.iHeight-b-t; + +#ifdef _DEBUG + TInt error = 0; + + __ASSERT_DEBUG(t>=0, + (error=1,LOGTEXT1(_L("AknLayoutUtils: Layout error: t=%d < 0 "),t))); + __ASSERT_DEBUG(aParent.Size().iWidth >= W, + (error=2,LOGTEXT2(_L("AknLayoutUtils: parent rect Width smaller than required %d >= %d"), aParent.Size().iWidth, W))); + __ASSERT_DEBUG(aParent.Size().iHeight >= H, + (error=3, LOGTEXT2(_L("AknLayoutUtils: parent rect Height smaller than required %d >= %d"), aParent.Size().iHeight, H))); + __ASSERT_DEBUG(l>=0, + (error=4,LOGTEXT1(_L("AknLayoutUtils: Layout error: l=%d >= 0"),l))); + __ASSERT_DEBUG(r==ELayoutEmpty || r>=0, + (error=5,LOGTEXT1(_L("AknLayoutUtils: Layout error: r=%d <= 0"),r))); + if (error) + { + /* A good place for breakpoint */ + error = error; + } +#endif + + return TRect(TPoint(aParent.iTl.iX+l, aParent.iTl.iY+t), TSize(W, H)); + } + +EXPORT_C TGulAlignment AknLayoutUtils::GulAlignFromId(TInt aJId) + { + TGulAlignment align; + align.SetVAlignment(EVTop); + switch(aJId) { + case ELayoutAlignNone: align.SetHAlignment(EHLeft); break; + case ELayoutAlignCenter: align.SetHAlignment(EHCenter); break; + case ELayoutAlignLeft: align.SetHAlignment(EHLeft); break; + case ELayoutAlignRight: align.SetHAlignment(EHRight); break; + case ELayoutAlignBidi: align.SetHAlignment(EHLeft); break; // mapping onto left as there seems to be no equivalent + default: align.SetHAlignment(EHLeft); break; + }; + return align; + } + +EXPORT_C CGraphicsContext::TTextAlign AknLayoutUtils::TextAlignFromId(TInt aJId) + { + CGraphicsContext::TTextAlign align; + switch(aJId) + { + case ELayoutAlignNone: align = CGraphicsContext::ELeft; break; + case ELayoutAlignCenter: align = CGraphicsContext::ECenter; break; + case ELayoutAlignLeft: align = CGraphicsContext::ELeft; break; + case ELayoutAlignRight: align = CGraphicsContext::ERight; break; + case ELayoutAlignBidi: align = CGraphicsContext::ELeft; break; // mapping onto left as there seems to be no equivalent + default: align = CGraphicsContext::ECenter; break; + }; + return align; + } + +EXPORT_C const CFont* AknLayoutUtils::FontFromId(TInt aId, const CFont *aCustomFont) + { + const CFont *font = 0; + if ( aId == EFontCustom ) + { + font = aCustomFont; + if (!font) + { // Fall-back font when null custom font is given + font = CEikonEnv::Static()-> + Font( TLogicalFont( TUid::Uid( EAknLogicalFontSecondaryFont ) ) ); //Vesa + } + } + else + { + font = CEikonEnv::Static()->Font( TLogicalFont( TUid::Uid( aId ) ) ); + } + return font; + } + +EXPORT_C const CAknLayoutFont* AknLayoutUtils::LayoutFontFromId(TInt aId, const CAknLayoutFont *aCustomFont) + { + const CAknLayoutFont *font = 0; + const CFont* cFont = 0; + if ( aId == EFontCustom ) + { + cFont = aCustomFont; + if (!cFont) + { // Fall-back font when null custom font is given + cFont = CEikonEnv::Static()-> + Font( TLogicalFont( TUid::Uid( EAknLogicalFontSecondaryFont ) ) ); + } + } + else + { + cFont = CEikonEnv::Static()->Font( TLogicalFont( TUid::Uid( aId ) ) ); + } + // Ensure type of font is correct + __ASSERT_DEBUG( CAknLayoutFont::AsCAknLayoutFontOrNull( cFont ), Panic( EAknPanicFontProvisionFailure ) ); + font = static_cast(cFont); + return font; + } + +EXPORT_C CAknLayoutFont* AknLayoutUtils::CreateLayoutFontFromSpecificationL( + const TAknFontSpecification& aSpec) + { + CWsScreenDevice* aBitmapDevice = CCoeEnv::Static()->ScreenDevice(); + return CAknFontSpecificationLayoutFont::NewL( *aBitmapDevice, aSpec ); + } + +EXPORT_C CAknLayoutFont* AknLayoutUtils::CreateLayoutFontFromSpecificationL( + const TTypeface& aTypeface, + const TAknFontSpecification& aSpec ) + { + CWsScreenDevice* aBitmapDevice = CCoeEnv::Static()->ScreenDevice(); + return CAknFontSpecificationLayoutFont::NewL( *aBitmapDevice, aTypeface, aSpec ); + } + + +EXPORT_C const CFont* AknLayoutUtils::FontFromName(const TDesC& aName) + { + _LIT(KLatinPlain12,"LatinPlain12"); + _LIT(KLatinBold12,"LatinBold12"); + _LIT(KLatinBold13,"LatinBold13"); + _LIT(KLatinBold16,"LatinBold16"); + _LIT(KLatinBold17,"LatinBold17"); + _LIT(KLatinBold19,"LatinBold19"); + _LIT(KNumberPlain5,"NumberPlain5"); + _LIT(KClockBold30,"ClockBold30"); + _LIT(KLatinClock14,"LatinClock14"); + _LIT(KCombinedChinesePlain16,"CombinedChinesePlain16"); + _LIT(KCombinedChinesePlain12,"CombinedChinesePlain12"); + _LIT(KNewThai12cl,"NewThai12cl"); + _LIT(KNewThai16g,"NewThai16g"); + _LIT(KJapanPlain12,"JapanPlain12"); + _LIT(KJapanPlain16,"JapanPlain16"); + _LIT(KCalcBold21,"CalcBold21"); + _LIT(KCalcOperBold21,"CalcOperBold21"); + _LIT(KCalcOperBold13,"CalcOperBold13"); + + TInt fontId = -1; + if (aName == KLatinPlain12) fontId = ELatinPlain12; + else if (aName == KLatinBold12) fontId = ELatinBold12; + else if (aName == KLatinBold13) fontId = ELatinBold13; + else if (aName == KLatinBold16) fontId = ELatinBold16; + else if (aName == KLatinBold17) fontId = ELatinBold17; + else if (aName == KLatinBold19) fontId = ELatinBold19; + else if (aName == KNumberPlain5) fontId = ENumberPlain5; + else if (aName == KClockBold30) fontId = EClockBold30; + else if (aName == KLatinClock14) fontId = ELatinClock14; + else if (aName == KCombinedChinesePlain16) fontId = EApacPlain16; + else if (aName == KCombinedChinesePlain12) fontId = EApacPlain12; + else if (aName == KNewThai16g) fontId = EApacPlain16; + else if (aName == KNewThai12cl) fontId = EApacPlain12; + else if (aName == KJapanPlain16) fontId = EApacPlain16; + else if (aName == KJapanPlain12) fontId = EApacPlain12; + else if (aName == KCalcBold21) fontId = ECalcBold21; + else if (aName == KCalcOperBold21) fontId = ECalcOperBold21; + else if (aName == KCalcOperBold13) fontId = ECalcOperBold13; + return FontFromId(fontId); + } + +/** +Return cursor height. +Cursor height depends on font. It is 15 for font latin bold 13 and 14 for +font latin bold 12. This means two pixels higher than font ascent and +descent. For other fonts it is not specified, nevertheless the sum of font +ascent and descent, plus 2 is returned. +*/ +EXPORT_C TInt AknLayoutUtils::CursorHeightFromFont(const TFontSpec& aFont) + { + TAknFontSpecification spec( EAknFontCategoryUndefined, aFont, NULL ); + TInt textPaneHeight(0); + // First look in system font array. Match the fontspec there + const CAknLayoutFont* font = AknLayoutUtils::MatchFontFromSystemFontArray( aFont, NULL ); + if ( font ) + textPaneHeight = font->TextPaneHeight(); + else // Use the value that was converted in TAknFontSpecification + textPaneHeight = spec.TextPaneHeight(); + TAknTextDecorationMetrics metrics( spec ); + TInt top(0); + TInt bottom(0); + metrics.GetTopAndBottomMargins( top, bottom ); + return top + bottom + textPaneHeight; + } + +/** +Return cursor width. +The cursor width depends on font. It's 2 pixels for latin bold 13 and 1 +pixel for latin bold 12. It is not specified for any other font and therefore +left to 1 pixel. +*/ +EXPORT_C TInt AknLayoutUtils::CursorWidthFromFont (const TFontSpec& aFont) + { + TAknFontSpecification spec( EAknFontCategoryUndefined, aFont, NULL ); + TAknTextDecorationMetrics decorationMetrics( spec ); + return(decorationMetrics.CursorWidth()); + } +/** +* Return cursor ascent. +* Cursor ascent depends on font. +* The cursor position is 3 pixels below the base line, the ascent is equal to +* the height minus 3. +* +*/ +EXPORT_C TInt AknLayoutUtils::CursorAscentFromFont(const TFontSpec& aFont) + { + TAknFontSpecification spec( EAknFontCategoryUndefined, aFont, NULL ); + + // Could address font provider for this: + /* + TInt dummyIndex; + const CFont* font = AknFontProvider::CreateFontFromMetrics( EFontNone, spec, dummyIndex); + TInt ascent = font->AscentInPixels(); + TAknTextDecorationMetrics metrics( spec ); + TInt topExtension; + TInt bottomExtension; + metrics.GetTopAndBottomMargins( topExtension, bottomExtension ); + return ascent + topExtension; + */ + // ...but currently return just the height + return spec.TextPaneHeight(); + } + +/** +* Returns cursor extensions +* This API takes a TFontSpec. Height in the fontspec should be in Twips, which is the default unit. +* The values returned are not only the true extensions above and below the text pane, but also includes +* any extra height or depth that is required to account for the font's maximum drawing beyond AscentInPixels +* and DescentInPixels, respectively. +* +* Thus the pixel values returned are appropriate for passing into for instance +* CTextView::SetCursorExtensions(aFirstExtension,aSecondExtension); +* +* Note that the return values are defined such that, for cursors to extend above and below the glyphs, +* both values would be positive. +* +* @param aFont Input. FontSpec of the font being used +* @param aFirstExtension Output. Distance (measured upward) to extend the cursor above CFont::AscentInPixels() +* @param aSecondExtension Output. Distance (measured downward) to extend the cursor below CFont::DescentInPixels() +*/ +EXPORT_C void AknLayoutUtils::CursorExtensionsFromFont(const TFontSpec& aFont, TInt& aFirstExtension, TInt& aSecondExtension) + { + TAknFontSpecification spec( EAknFontCategoryUndefined, aFont, NULL ); + TAknTextDecorationMetrics metrics(spec); + metrics.GetTopAndBottomMargins( aFirstExtension, aSecondExtension ); + + // Also, correct the numbers for any excesses/shortfalls in the font metrics + const CAknLayoutFont* font = AknLayoutUtils::MatchFontFromSystemFontArray( aFont, NULL ); + if ( font ) + { + aFirstExtension += font->TextPaneTopToBaseline() - font->AscentInPixels(); + aSecondExtension += font->BaselineToTextPaneBottom() - font->DescentInPixels(); + } + + } + +/** +Pixels for text highlight on the left of the text. By default there are 0 pixels +on the left of the text when highlighting. There should be 1 pixel regardless of +the font type. +*/ +EXPORT_C TInt AknLayoutUtils::HighlightLeftPixelsFromFont(const TFontSpec& aFont) + { + TAknFontSpecification spec( EAknFontCategoryUndefined, aFont, NULL ); + TAknTextDecorationMetrics metrics(spec); + TInt left(0); + TInt right(0); + metrics.GetLeftAndRightMargins( left, right); + return left; + } +/** +Pixels for text hightlight on the right of the text. By default there are 2 pixels +on the right for Font 13 and 1 pixel for Font 12. There should be 1 pixel for font +13 and 0 for Font 12. The value returned by this method will be subtracted from the +default one. +*/ +EXPORT_C TInt AknLayoutUtils::HighlightRightPixelsFromFont(const TFontSpec& aFont) + { + TAknFontSpecification spec( EAknFontCategoryUndefined, aFont, NULL ); + TAknTextDecorationMetrics metrics(spec); + TInt left(0); + TInt right(0); + metrics.GetLeftAndRightMargins( left, right); + return right; + } + +/** +* Highlight Extensions. +* The values returned DO NOT include any extra extension required to account for glyphs that extend beyond +* CFont::AscentInPixels and CFont::DescentInPixels() +* +*/ +void AknLayoutUtils::HighlightExtensionsFromFont(const TInt fontid, TInt& aLeft, TInt& aRight, TInt& aTop, TInt& aBottom) + { + TAknFontSpecification spec( fontid ); + TAknTextDecorationMetrics decorationMetrics( spec ); + decorationMetrics.GetLeftAndRightMargins(aLeft, aRight); + decorationMetrics.GetTopAndBottomMargins(aTop, aBottom); + } + +/** +* This method is used internally for matching fonts in the system font array +* when you only have a TFontSpec. +* +* (If you have a CFont, you can use CAknLayoutFont::AsCAknLayoutFontOrNull +* to detect if the font is a CAknLayoutFont.) +* +* This routine avoids having to go to the server to regenerate the font. Some +* approximations are made here. Because the == operator used in the comparison +* of TFontSpecs is not always reliable (aliases are not resolved, for instance), +* the comparison here is made based upon size and boldness only. As a result, this +* method should only be used for operations such as the determination of cursor +* and highlight metrics. +*/ +const CAknLayoutFont* AknLayoutUtils::MatchFontFromSystemFontArray( + const TFontSpec& aSpec, MGraphicsDeviceMap* /*aMap*/ ) + { + const CAknLayoutFont* font = NULL; + + CAknEnv* env = AVKONENV; + if ( env ) + { + const CArrayPtr* fontArray = env->SystemFontArray(); + if ( fontArray ) + { + // Search the array + TInt count = fontArray->Count(); + for (TInt index = 0; index < count; index++) + { + CAknSystemFont* info = fontArray->At(index); + CFont* thisFont = info->Font(); + TFontSpec thisSpec = thisFont->FontSpecInTwips(); + + // Need to make the twips check fuzzy because one or both of + // the twips values may have been through more than one twips-pixel + // or pixel-twips transformation. + TInt diff = aSpec.iHeight - thisSpec.iHeight; + if ( diff < 0 ) + diff = 0-diff; + if ( diff/KFontHeightComparisonDivisor == 0 ) + { + if ( aSpec.iFontStyle.StrokeWeight() == thisSpec.iFontStyle.StrokeWeight() ) + { + font = static_cast(thisFont); + break; + } + } + } + } + } + return font; + } +EXPORT_C TBool AknLayoutUtils::LayoutMirrored() + { + TAknLayoutId layoutId; + CAknEnv::Static()->GetCurrentLayoutId(layoutId); + + TInt retVal( EFalse ); + + if ( layoutId == EAknLayoutIdABRW ) + { + retVal = ETrue; + } + + return retVal; + } + +EXPORT_C EVariantFlag AknLayoutUtils::Variant() + { + return AknBuildVariant(); + } + +EXPORT_C ESubVariantFlag AknLayoutUtils::SubVariant() + { + switch (Variant()) + { + case EEuropeanVariant: + return ENoSubVariant; + + case EApacVariant: + { + // Subvariant comes from UI language: + switch (AknLangUtils::UserLanguage()) + { + case ELangTaiwanChinese: + return ETaiwanSubVariant; + case ELangHongKongChinese: + return EHongKongSubVariant; + case ELangPrcChinese: + return EPrcSubVariant; + default: + return EPrcSubVariant; + } + } + default: + break; + } + __ASSERT_ALWAYS(0,User::Panic(_L("Variant should only return ELAF or APAC"),0)); + return EPrcSubVariant; + } + +EXPORT_C void AknLayoutUtils::OverrideControlColorL(CCoeControl& aControl, TLogicalColor aLogicalColor, TRgb aColor) + { + CEikonEnv& env = static_cast(*aControl.ControlEnv()); + TRgb currentColor = env.ControlColor(aLogicalColor, aControl); + if (aColor == currentColor) + { + // recurse to contained controls to see if they need a color override + TInt count = aControl.CountComponentControls(); + for (TInt ii=0; iiIsLayoutAwareApp()) + { + return preferredScrollBarType; + } + else + { + // For non-layout aware apps, arrowhead scrollbar is default. + // In that case also Avkon components defaults to this. + return CEikScrollBarFrame::EArrowHead; + } + } + +EXPORT_C void AknLayoutUtils::LayoutVerticalScrollBar(CEikScrollBarFrame* aScrollBarFrame, const TRect& aControlParent, const TAknWindowLineLayout& aLayout) + { + if (aScrollBarFrame && aScrollBarFrame->VerticalScrollBar()) + { + // Only EDoubleSpan type scrollbar layout can be set + if (aScrollBarFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan) + { + CAknDoubleSpanScrollBar* scrollbar = static_cast (aScrollBarFrame->VerticalScrollBar()); + TRect rect = RectFromCoords(aControlParent, aLayout.il, aLayout.it, aLayout.ir, aLayout.ib, aLayout.iW, aLayout.iH); + if (scrollbar && (rect != TRect(scrollbar->Position(), scrollbar->Size()))) + { + scrollbar->SetFixedLayoutRect(rect); + scrollbar->SetRect(rect); + } + } + } + } + +EXPORT_C void AknLayoutUtils::LayoutHorizontalScrollBar(CEikScrollBarFrame* aScrollBarFrame, const TRect& aControlParent, const TAknWindowLineLayout& aLayout) + { + if (aScrollBarFrame && aScrollBarFrame->GetScrollBarHandle(CEikScrollBar::EHorizontal)) + { + // Only EDoubleSpan type scrollbar layout can be set + if (aScrollBarFrame->TypeOfHScrollBar() == CEikScrollBarFrame::EDoubleSpan) + { + CAknDoubleSpanScrollBar* scrollbar = static_cast (aScrollBarFrame->GetScrollBarHandle(CEikScrollBar::EHorizontal)); + TRect rect = RectFromCoords(aControlParent, aLayout.il, aLayout.it, aLayout.ir, aLayout.ib, aLayout.iW, aLayout.iH); + if (scrollbar && (rect != TRect(scrollbar->Position(), scrollbar->Size()))) + { + scrollbar->SetFixedLayoutRect(rect); + scrollbar->SetRect(rect); + } + } + } + } + + + +EXPORT_C TBool AknLayoutUtils::LayoutMetricsRect( TAknLayoutMetrics aParam, + TRect& aRect ) + { + TAknWindowComponentLayout line; + TAknLayoutRect rect; + TRect screenRect(0, 0, AKN_LAYOUT_WINDOW_screen.iW, AKN_LAYOUT_WINDOW_screen.iH); + aRect.SetRect( 0, 0, 0, 0 ); + + // No stacon pane active etc. cheking is done here before the switch-case so that we can + // have slightly better performance for some other lookups (e.g. screen). + + switch (aParam) + { + case EScreen: + aRect = screenRect; + return ETrue; + + case EApplicationWindow: + rect.LayoutRect( + screenRect, + AknLayoutScalable_Avkon::application_window( 0 ) ); + aRect = rect.Rect(); + return ETrue; + + case EStatusPane: + { + CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current(); + + if ( statusPane ) + { + TInt currentStatusPaneLayoutResId = statusPane->CurrentLayoutResId(); + + if ( AknStatuspaneUtils::StaconPaneActive() ) + { + // flat status pane in landscape mode is the whole top pane area + if ( currentStatusPaneLayoutResId == R_AVKON_STATUS_PANE_LAYOUT_USUAL_FLAT || + currentStatusPaneLayoutResId == R_AVKON_STATUS_PANE_LAYOUT_IDLE_FLAT ) + { + rect.LayoutRect( screenRect, AknLayoutScalable_Avkon::area_top_pane(8) ); // flat area_top_pane in lsc + aRect = rect.Rect(); + return ETrue; + } + else + { + rect.LayoutRect( screenRect, AknLayoutScalable_Avkon::area_top_pane(2) ); // classic area_top_pane in lsc + aRect = rect.Rect(); + rect.LayoutRect( aRect, AknLayoutScalable_Avkon::stacon_top_pane() ); + aRect = rect.Rect(); + rect.LayoutRect( aRect, AknLayoutScalable_Avkon::control_top_pane_stacon(0) ); + aRect.iBr.iX = rect.Rect().iTl.iX; // Status pane top = stacon top - control pane top. + return ETrue; + } + } + else + { + TAknWindowComponentLayout parent; + + switch ( currentStatusPaneLayoutResId ) + { + case R_AVKON_STATUS_PANE_LAYOUT_USUAL_WITH_BATTERY_PANE: + case R_AVKON_STATUS_PANE_LAYOUT_USUAL: + case R_AVKON_STATUS_PANE_LAYOUT_POWER_OFF_RECHARGE: + case R_AVKON_STATUS_PANE_LAYOUT_USUAL_MIRRORED: + case R_AVKON_STATUS_PANE_LAYOUT_POWER_OFF_RECHARGE_MIRRORED: + case R_AVKON_STATUS_PANE_LAYOUT_VT: + case R_AVKON_STATUS_PANE_LAYOUT_VT_MIRRORED: + case R_AVKON_STATUS_PANE_LAYOUT_USUAL_EXT: + default: + parent = AknLayoutScalable_Avkon::area_top_pane(0); + line = AknLayoutScalable_Avkon::status_pane(0); // classic status pane + break; + + case R_AVKON_STATUS_PANE_LAYOUT_IDLE: + case R_AVKON_STATUS_PANE_LAYOUT_IDLE_MIRRORED: + parent = AknLayoutScalable_Avkon::area_top_pane(7); + line = AknLayoutScalable_Avkon::status_idle_pane(); // idle status pane + break; + + case R_AVKON_STATUS_PANE_LAYOUT_SMALL: + case R_AVKON_STATUS_PANE_LAYOUT_SMALL_WITH_SIGNAL_PANE: + case R_AVKON_STATUS_PANE_LAYOUT_SMALL_WITH_SIGNAL_PANE_MIRRORED: + // Small status pane is the whole top area. + parent = AknLayoutScalable_Avkon::application_window(0); + if ( Layout_Meta_Data::IsLandscapeOrientation() && + AknLayoutUtils::CbaLocation() == AknLayoutUtils::EAknCbaLocationBottom ) + { + line = AknLayoutScalable_Avkon::area_top_pane(2); + } + else + { + line = AknLayoutScalable_Avkon::area_top_pane(1); + } + + break; + + case R_AVKON_STATUS_PANE_LAYOUT_USUAL_FLAT: + case R_AVKON_STATUS_PANE_LAYOUT_IDLE_FLAT: // fallthrough + { + if ( Layout_Meta_Data::IsLandscapeOrientation() && + Layout_Meta_Data::IsPenEnabled() ) + { + parent = AknLayoutScalable_Avkon::area_top_pane( 2 ); + } + else + { + parent = AknLayoutScalable_Avkon::area_top_pane( 6 ); + } + line = AknLayoutScalable_Avkon::status_pane( 1 ); // flat status pane + break; + } + + case R_AVKON_WIDESCREEN_PANE_LAYOUT_USUAL: + case R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE: // fallthrough + { + parent = AknLayoutScalable_Avkon::area_top_pane( 8 ); + line = AknLayoutScalable_Avkon::status_pane( 1 ); + break; + } + + case R_AVKON_WIDESCREEN_PANE_LAYOUT_USUAL_FLAT: + case R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT: // fallthrough + { + parent = AknLayoutScalable_Avkon::area_top_pane( 19 ); + line = AknLayoutScalable_Avkon::status_pane( 4 ); + break; + } + + case R_AVKON_WIDESCREEN_PANE_LAYOUT_USUAL_FLAT_NO_SOFTKEYS: + case R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT_NO_SOFTKEYS: // fallthrough + { + parent = AknLayoutScalable_Avkon::area_top_pane( 20 ); + line = AknLayoutScalable_Avkon::status_pane( 5 ); + break; + } + } + + rect.LayoutRect( screenRect, TAknWindowComponentLayout::Compose( parent, line ) ); + aRect = rect.Rect(); + } + return ETrue; + } + return EFalse; + } + case EPopupParent: + { + if ( screenRect.iBr.iX == 640 && screenRect.iBr.iY == 360 ) + { + TInt variety = 16; + + if ( AVKONENV->StatusPaneResIdForCurrentLayout( + AknStatuspaneUtils::CurrentStatusPaneLayoutResId() ) == + R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT_NO_SOFTKEYS ) + { + variety = 25; + } + + rect.LayoutRect( screenRect, TAknWindowComponentLayout::Compose( + AknLayoutScalable_Avkon::application_window( 0 ), + AknLayoutScalable_Avkon::main_pane( variety ) ) ); + aRect = rect.Rect(); + return ETrue; + } + else if ( screenRect.iBr.iX == 360 && screenRect.iBr.iY == 640 ) + { + TInt variety = 1; + rect.LayoutRect( screenRect, TAknWindowComponentLayout::Compose( + AknLayoutScalable_Avkon::application_window( 0 ), + AknLayoutScalable_Avkon::main_pane( variety ) ) ); + aRect = rect.Rect(); + return ETrue; + } + else + { + return LayoutMetricsRect( EMainPane, aRect ); + } + } + case EMainPane: + { + TInt variety = 3; // classic main pane variety by default + + TInt currentStatusPaneLayoutResId = AknStatuspaneUtils::CurrentStatusPaneLayoutResId(); + + switch ( currentStatusPaneLayoutResId ) + { + case R_AVKON_STACON_PANE_LAYOUT_USUAL_SOFTKEYS_RIGHT: + case R_AVKON_STACON_PANE_LAYOUT_USUAL_SOFTKEYS_LEFT: + case R_AVKON_STACON_PANE_LAYOUT_EMPTY_SOFTKEYS_RIGHT: + case R_AVKON_STACON_PANE_LAYOUT_EMPTY_SOFTKEYS_LEFT: + case R_AVKON_STACON_PANE_LAYOUT_IDLE_SOFTKEYS_RIGHT: + case R_AVKON_STACON_PANE_LAYOUT_IDLE_SOFTKEYS_LEFT: + { + // This is quite awkward but necessary since the fixed + // toolbar area can be used by the application main pane + // if the application doesn't use toolbar. + TBool toolbarVisible( EFalse ); + if ( iAvkonAppUi ) + { + CAknToolbar* fixedToolbar = + iAvkonAppUi->CurrentFixedToolbar(); + if ( fixedToolbar ) + { + TInt toolbarFlags( fixedToolbar->ToolbarFlags() ); + if ( toolbarFlags & KAknToolbarFixed && + !( toolbarFlags & KAknToolbarDefault ) && + fixedToolbar->IsShown() ) + { + toolbarVisible = ETrue; + } + } + } + + variety = toolbarVisible ? 21 : 4; + } + break; + + case R_AVKON_STATUS_PANE_LAYOUT_USUAL_WITH_BATTERY_PANE: + case R_AVKON_STATUS_PANE_LAYOUT_USUAL: + case R_AVKON_STATUS_PANE_LAYOUT_POWER_OFF_RECHARGE: + case R_AVKON_STATUS_PANE_LAYOUT_USUAL_MIRRORED: + case R_AVKON_STATUS_PANE_LAYOUT_POWER_OFF_RECHARGE_MIRRORED: + case R_AVKON_STATUS_PANE_LAYOUT_VT: + case R_AVKON_STATUS_PANE_LAYOUT_VT_MIRRORED: + case R_AVKON_STATUS_PANE_LAYOUT_USUAL_EXT: + { + // main pane variety for usual portrait main pane with + // 'area_top_pane' and 'area_bottom_pane' +#ifdef RD_SCALABLE_UI_V2 + variety = 3; + if ( iAvkonAppUi && iAvkonAppUi->TouchPane() && iAvkonAppUi->TouchPane()->IsVisible() ) + { + variety = 15; + } + else if ( iAvkonAppUi && iAvkonAppUi->CurrentFixedToolbar() ) + { + if ( AknLayoutUtils::PenEnabled() ) + { + CAknToolbar* toolbar = iAvkonAppUi->CurrentFixedToolbar(); + TInt flags = toolbar->ToolbarFlags(); + if ( flags & KAknToolbarFixed && !( flags & KAknToolbarDefault ) + && toolbar->IsShown() ) + { + variety = 18; + } + } + } +#else + variety = 3; +#endif // RD_SCALABLE_UI_V2 + } + break; + + case R_AVKON_STATUS_PANE_LAYOUT_IDLE: + case R_AVKON_STATUS_PANE_LAYOUT_IDLE_MIRRORED: + { + // main pane variety for idle state portrait main pane with + // 'area_top_pane' and 'area_bottom_pane' + variety = 8; + } + break; + + case R_AVKON_STATUS_PANE_LAYOUT_USUAL_FLAT: + case R_AVKON_STATUS_PANE_LAYOUT_IDLE_FLAT: + { + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + if ( PenEnabled() ) + { + // This is quite awkward but necessary since the fixed + // toolbar area can be used by the application main pane + // if the application doesn't use toolbar. + TBool toolbarVisible( EFalse ); + if ( iAvkonAppUi ) + { + CAknToolbar* fixedToolbar = + iAvkonAppUi->CurrentFixedToolbar(); + if ( fixedToolbar ) + { + TInt toolbarFlags( fixedToolbar->ToolbarFlags() ); + if ( toolbarFlags & KAknToolbarFixed && + !( toolbarFlags & KAknToolbarDefault ) && + fixedToolbar->IsShown() ) + { + toolbarVisible = ETrue; + } + } + } + + variety = toolbarVisible ? 21 : 4; + } + else + { + // main pane variety with 'area_top_pane' and + // 'area_bottom_pane' in landscape (without touch pane). + variety = 9; + } + } + else + { + // main pane variety with thin portrait status pane + variety = 7; + } + break; + } + case R_AVKON_STATUS_PANE_LAYOUT_SMALL: + case R_AVKON_STATUS_PANE_LAYOUT_SMALL_WITH_SIGNAL_PANE: + case R_AVKON_STATUS_PANE_LAYOUT_SMALL_WITH_SIGNAL_PANE_MIRRORED: + { + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + if ( PenEnabled() ) + { + // main pane variety with small status pane in landscape + // mode with 'area_top_pane', 'area_bottom_pane' and + // touch pane + variety = 4; + } + else + { + // main pane variety with 'area_top_pane' and + // 'area_bottom_pane' in landscape (without touch pane) + variety = 9; + } + } + else + { + // main pane variety with small status pane in portrait mode + // (with 'area_top_pane' and 'area_bottom_pane'). + variety = 6; + } + } + break; + + case R_AVKON_STATUS_PANE_EMPTY: + case R_AVKON_STATUS_PANE_LAYOUT_EMPTY: + if ( AknStatuspaneUtils::HDLayoutActive() ) + { + variety = 16; + } + else + { + variety = 1; // no variety without cba + } + break; + + case R_AVKON_WIDESCREEN_PANE_LAYOUT_USUAL: + case R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE: + { + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + variety = 4; + } + break; + } + + case R_AVKON_WIDESCREEN_PANE_LAYOUT_USUAL_FLAT: + case R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT: + { + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + variety = 21; + } + break; + } + + case R_AVKON_WIDESCREEN_PANE_LAYOUT_USUAL_FLAT_NO_SOFTKEYS: + { + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + variety = 22; + } + break; + } + + case R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT_NO_SOFTKEYS: + { + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + variety = 25; + } + break; + } + + default: + break; + } + + rect.LayoutRect( screenRect, TAknWindowComponentLayout::Compose( + AknLayoutScalable_Avkon::application_window( 0 ), + AknLayoutScalable_Avkon::main_pane( variety ) ) ); + + aRect = rect.Rect(); + return ETrue; + } + + case EControlPane: + { + if ( AknStatuspaneUtils::StaconPaneActive() ) + { + rect.LayoutRect( + screenRect, + AknLayoutScalable_Avkon::area_top_pane( 2 ) ); + TRect parent( rect.Rect() ); + + rect.LayoutRect( + parent, + AknLayoutScalable_Avkon::stacon_top_pane() ); + parent = rect.Rect(); + + rect.LayoutRect( + parent, + AknLayoutScalable_Avkon::control_top_pane_stacon( 0 ) ); + + aRect = rect.Rect(); + return ETrue; + } + else if ( AknStatuspaneUtils::HDLayoutActive() && + AknStatuspaneUtils::CurrentStatusPaneLayoutResId() != + R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT_NO_SOFTKEYS ) + { + rect.LayoutRect( + screenRect, + AknLayoutScalable_Avkon::application_window( 0 ) ); + TRect parent( rect.Rect() ); + rect.LayoutRect( + parent, + AknLayoutScalable_Avkon::area_side_right_pane( 5 ) ); + aRect = rect.Rect(); + return ETrue; + } + // Control pane in flat status pane landscape mode is the + // whole bottom pane area. + else if ( Layout_Meta_Data::IsLandscapeOrientation() && + AknStatuspaneUtils::FlatLayoutActive() ) + { + rect.LayoutRect( + screenRect, + AknLayoutScalable_Avkon::area_bottom_pane( PenEnabled() ? 2 : 6 ) ); + aRect = rect.Rect(); + return ETrue; + } + else + { + rect.LayoutRect( + screenRect, + AknLayoutScalable_Avkon::area_bottom_pane( 0 ) ); + aRect = rect.Rect(); + return ETrue; + } + } + + case EControlPaneBottom: + if (AknStatuspaneUtils::StaconPaneActive()) + { + rect.LayoutRect( screenRect, AknLayoutScalable_Avkon::area_bottom_pane(2) ); // area_bottom_pane in lsc + TRect parent = rect.Rect(); + rect.LayoutRect( parent, AknLayoutScalable_Avkon::stacon_bottom_pane() ); + parent = rect.Rect(); + rect.LayoutRect( parent, AknLayoutScalable_Avkon::control_bottom_pane_stacon(0) ); + aRect = rect.Rect(); + return ETrue; + } + return EFalse; + + case EStatusPaneBottom: + if (AknStatuspaneUtils::StaconPaneActive()) + { + rect.LayoutRect( screenRect, AknLayoutScalable_Avkon::area_bottom_pane(2) ); // area_bottom_pane in lsc + aRect = rect.Rect(); + rect.LayoutRect( aRect, AknLayoutScalable_Avkon::stacon_bottom_pane() ); + aRect = rect.Rect(); + rect.LayoutRect( aRect, AknLayoutScalable_Avkon::control_bottom_pane_stacon(0) ); + aRect.iBr.iX = rect.Rect().iTl.iX; // Status pane bottom = stacon bottom - control pane bottom. + return ETrue; + } + return EFalse; + + case EStaconTop: + if (AknStatuspaneUtils::StaconPaneActive()) + { + rect.LayoutRect( screenRect, TAknWindowComponentLayout::Compose( + AknLayoutScalable_Avkon::area_top_pane(2), + AknLayoutScalable_Avkon::stacon_top_pane() ) ); + aRect = rect.Rect(); + return ETrue; + } + return EFalse; + + case EStaconBottom: + if (AknStatuspaneUtils::StaconPaneActive()) + { + rect.LayoutRect( screenRect, TAknWindowComponentLayout::Compose( + AknLayoutScalable_Avkon::area_bottom_pane(2), + AknLayoutScalable_Avkon::stacon_bottom_pane() ) ); + aRect = rect.Rect(); + return ETrue; + } + return EFalse; + + default: + break; + } + + // Main pane descendants + + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + rect.LayoutRect( screenRect, AknLayoutScalable_Avkon::main_pane(4) ); + } + else + { + rect.LayoutRect( screenRect, AknLayoutScalable_Avkon::main_pane(3) ); + } + + TRect mainpane = rect.Rect(); + + switch (aParam) + { + case EFindPane: + rect.LayoutRect( mainpane, AknLayoutScalable_Avkon::find_pane() ); + aRect = rect.Rect(); + return ETrue; + + case EWallpaperPane: + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + rect.LayoutRect( mainpane, AknLayoutScalable_Avkon::wallpaper_pane(1) ); + } + else + { + rect.LayoutRect( mainpane, AknLayoutScalable_Avkon::wallpaper_pane(0) ); + } + aRect = rect.Rect(); + return ETrue; + + case EIndicatorPane: + // indicator pane on the left side on landscape mode + if ( Layout_Meta_Data::IsLandscapeOrientation() && LayoutMirrored() ) + { + rect.LayoutRect( mainpane, AknLayoutScalable_Avkon::indicator_pane(2) ); + } + // indicator pane on the right side on landscape mode + else if ( Layout_Meta_Data::IsLandscapeOrientation() && !LayoutMirrored() ) + { + rect.LayoutRect( mainpane, AknLayoutScalable_Avkon::indicator_pane(1) ); + } + // portrait mode + else + { + rect.LayoutRect( mainpane, AknLayoutScalable_Avkon::indicator_pane(0) ); + } + aRect = rect.Rect(); + return ETrue; + + case EAColunm: + { + TAknLayoutRect listPaneRect; + listPaneRect.LayoutRect(mainpane, AknLayoutScalable_Avkon::bg_list_pane(0)); + rect.LayoutRect(listPaneRect.Rect(), AknLayoutScalable_Avkon::bg_list_pane_g1(1)); + aRect = rect.Rect(); + return ETrue; + } + case EBColunm: + { + TAknLayoutRect listPaneRect; + listPaneRect.LayoutRect(mainpane, AknLayoutScalable_Avkon::bg_list_pane(0)); + TAknLayoutRect columnA; + columnA.LayoutRect(listPaneRect.Rect(), AknLayoutScalable_Avkon::bg_list_pane_g1(1)); + // A+B column + rect.LayoutRect(listPaneRect.Rect(), AknLayoutScalable_Avkon::bg_list_pane_g1(2)); + aRect = rect.Rect(); + // Reduce A column + aRect.iTl.iX += columnA.Rect().Width(); + return ETrue; + } + case ECColunm: + { + TAknLayoutRect listPaneRect; + listPaneRect.LayoutRect(mainpane, AknLayoutScalable_Avkon::bg_list_pane(0)); + rect.LayoutRect(listPaneRect.Rect(), AknLayoutScalable_Avkon::bg_list_pane_g2(2)); + aRect = rect.Rect(); + return ETrue; + } + case EDColunm: + { + TAknLayoutRect listScrollPaneRect; + listScrollPaneRect.LayoutRect(mainpane, AknLayoutScalable_Avkon::listscroll_gen_pane(0)); + TAknLayoutRect listGenPaneRect; + listGenPaneRect.LayoutRect(listScrollPaneRect.Rect(), AknLayoutScalable_Avkon::list_gen_pane(1)); + TAknLayoutRect listSinglePaneRect; + listSinglePaneRect.LayoutRect(listGenPaneRect.Rect(), AknLayoutScalable_Avkon::list_single_pane(0)); + TAknLayoutRect listSinglePaneG2Rect; + listSinglePaneG2Rect.LayoutRect(listSinglePaneRect.Rect(), AknLayoutScalable_Avkon::list_single_pane_g2(0)); + + aRect = listSinglePaneRect.Rect(); + + if ( LayoutMirrored() ) + { + aRect.iBr.iX = listSinglePaneG2Rect.Rect().iBr.iX; + } + else + { + aRect.iTl.iX = listSinglePaneG2Rect.Rect().iTl.iX; + } + + // Adjust the height of the rect to match with the height of the other columns. + TAknLayoutRect listPaneRect; + listPaneRect.LayoutRect(mainpane, AknLayoutScalable_Avkon::bg_list_pane(0)); + rect.LayoutRect(listPaneRect.Rect(), AknLayoutScalable_Avkon::bg_list_pane_g1(1)); + aRect.iTl.iY = rect.Rect().iTl.iY; + aRect.iBr.iY = rect.Rect().iBr.iY; + + return ETrue; + } + default: + break; + } + + // Status pane descendants + + CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current(); + TInt err = KErrNotFound; + + if (statusPane) + { + switch (aParam) + { + case ESignalPane: + TRAP(err, aRect = statusPane->PaneRectL(TUid::Uid( EEikStatusPaneUidSignal ))); + break; + + case EContextPane: + TRAP(err, aRect = statusPane->PaneRectL(TUid::Uid( EEikStatusPaneUidContext ))); + break; + + case ETitlePane: + TRAP(err, aRect = statusPane->PaneRectL(TUid::Uid( EEikStatusPaneUidTitle ))); + break; + + case EBatteryPane: + TRAP(err, aRect = statusPane->PaneRectL(TUid::Uid( EEikStatusPaneUidBattery ))); + break; + + case EUniversalIndicatorPane: + TRAP(err, aRect = statusPane->PaneRectL(TUid::Uid( EEikStatusPaneUidIndic ))); + break; + + case ENaviPane: + TRAP(err, aRect = statusPane->PaneRectL(TUid::Uid( EEikStatusPaneUidNavi ))); + break; + + default: + break; + } + } + + + if (err != KErrNone) + { + aRect = TRect(TPoint(0,0), TPoint(0,0)); + return EFalse; + } + + return ETrue; + } + + +EXPORT_C TBool AknLayoutUtils::LayoutMetricsSize(TAknLayoutMetrics aParam, TSize& aSize) + { + TRect rect; + + TBool ret = LayoutMetricsRect(aParam, rect); + aSize = rect.Size(); + return ret; + } + + +EXPORT_C TBool AknLayoutUtils::LayoutMetricsPosition(TAknLayoutMetrics aParam, TPoint& aPos) + { + TRect rect; + + TBool ret = LayoutMetricsRect(aParam, rect); + aPos = rect.iTl; + return ret; + } + + +TInt AknLayoutUtils::CorrectBaseline(TInt aParentHeight, TInt aBaseline, TInt aFontId) + { + TInt B = aBaseline; + + if( TAknFontId::IsEncodedFont(aFontId) && aFontId != ELayoutEmpty ) // This tells us that the font id has come from scalable layout API + { + TInt b = aBaseline; + if (IsParentRelative(b)) { b = aParentHeight - ELayoutP + b; } + + const CAknLayoutFont *font = LayoutFontFromId(aFontId); + TInt descent = font->BaselineToTextPaneBottom(); + + // calculate distance down from top of parent to bottom of maximal glyph + TInt top2bog = aParentHeight - b; + + // distance down to baseline is distance down to bottom of glyph minus descent + // A further 1 is subtracted to account for the definition of baseline in the + // Series 60 pre-2.8 layout specifications. + B = top2bog - descent - 1; + } + + return B; + } + +void AknLayoutUtils::CorrectFontId(TRect aParent, TInt at, TInt /*aH*/, TInt ab, TInt &aFontId) +{ + // Only ELayoutEmpty's allowed in aFontId and encoded as 0x100 in font height. + const static TUint heightMask = 0x7FC0; + TUint heightScaledBy6Bits = aFontId & heightMask; + if (heightScaledBy6Bits == 0x100 << 6) + { // ELayoutEmpty + TInt height = aParent.Height() - at - ab; + heightScaledBy6Bits = height << 6; + heightScaledBy6Bits &= heightMask; // truncate if over allocated area. + } + TInt fontId = aFontId; + fontId &= ~heightMask; + fontId |= heightScaledBy6Bits; + aFontId = fontId; +} + +EXPORT_C TBool AknLayoutUtils::ScalableLayoutInterfaceAvailable() + { + TBool available = ETrue; + + // Use layout.iW and .iH to find out the resolution, and check for those that + // do not have scalable layout interface. + /* + TAknWindowLineLayout layout = AKN_LAYOUT_WINDOW_screen; + if (layout.iW == 42 && layout.iH == 42) + { + available = EFalse; + } + */ + + return available; + } + + +// --------------------------------------------------------------------------- +// AknLayoutUtils::CbaLocation +// Returns location of softkeys (bottom, right or left) +// --------------------------------------------------------------------------- +// +EXPORT_C AknLayoutUtils::TAknCbaLocation AknLayoutUtils::CbaLocation() + { + // Bottom by default. + AknLayoutUtils::TAknCbaLocation cbaLocation( + AknLayoutUtils::EAknCbaLocationBottom ); + + if ( !Layout_Meta_Data::IsLandscapeOrientation() ) + { + //in portrait mode always bottom + return cbaLocation; + } + + TInt currentStatusPaneLayout( + AknStatuspaneUtils::CurrentStatusPaneLayoutResId() ); + if ( Layout_Meta_Data::IsPenEnabled() && + AknStatuspaneUtils::HDLayoutActive() ) + { + if ( currentStatusPaneLayout == + R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT_NO_SOFTKEYS ) + { + // In the fullscreen width landscape flat status pane layout + // the softkeys are on the bottom. + cbaLocation = AknLayoutUtils::EAknCbaLocationBottom; + return cbaLocation; + } + else + { + cbaLocation = AknLayoutUtils::EAknCbaLocationRight; + } + } + + if ( iAvkonAppUi->IsFullScreenApp() ) + { + //it means this is a normal application + if ( !iAvkonAppUi->StatusPane() ) + { + //no status pane + return cbaLocation; + } + + if ( currentStatusPaneLayout == R_AVKON_STATUS_PANE_LAYOUT_EMPTY ) + { + //or status pane layout is empty + return cbaLocation; + } + + if( !AknStatuspaneUtils::StaconPaneActive() ) + { + //or Stacon not active + return cbaLocation; + } + + if ( AknStatuspaneUtils::StaconSoftKeysRight() ) + { + // Softkey location is always on the right side in + // widescreen status pane layouts. + cbaLocation = AknLayoutUtils::EAknCbaLocationRight; + } + else if ( AknStatuspaneUtils::StaconSoftKeysLeft() ) + { + cbaLocation = AknLayoutUtils::EAknCbaLocationLeft; + } + + return cbaLocation; + } + + //else it means this is server application + CAknLayoutConfig::TScreenMode screenMode = CAknSgcClient::ScreenMode(); + + TAknPrivSoftkeyLocation privcba = screenMode.SoftkeyLocation(); + + switch( privcba ) + { + case EAknPrivSoftkeyLocationRight: + cbaLocation = AknLayoutUtils::EAknCbaLocationRight; + break; + case EAknPrivSoftkeyLocationLeft: + cbaLocation = AknLayoutUtils::EAknCbaLocationLeft; + break; + case EAknPrivSoftkeyLocationBottom: + cbaLocation = AknLayoutUtils::EAknCbaLocationBottom; + break; + default: + cbaLocation = AknLayoutUtils::EAknCbaLocationBottom; + break; + } + + return cbaLocation; + } + + +// ----------------------------------------------------------------------------- +// AknLayoutUtils::HighlightBasedRect +// ----------------------------------------------------------------------------- +// +TRect AknLayoutUtils::HighlightBasedRect( const TRect& aHighlightRect, + CCoeControl* aControl ) + { + TAknWindowComponentLayout unitData = AknLayoutScalable_Avkon::aid_value_unit2(); + TInt layoytDataUnit = unitData.LayoutLine().iW / 10; + + TRect clientRect; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, clientRect ); + + // Control is allowed to be on top of the status pane but it cannot + // overlay either stacon pane or control pane. + if ( !AknStatuspaneUtils::StaconPaneActive() ) + { + TRect statusPaneRect; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EStatusPane, + statusPaneRect ); + clientRect.BoundingRect( statusPaneRect ); + } + + TPoint location[4]; + TInt count( 0 ); + + TSize controlSize( aControl->MinimumSize() ); + TInt leftX( aHighlightRect.iTl.iX + layoytDataUnit ); + TInt rightX( aHighlightRect.iBr.iX - controlSize.iWidth - layoytDataUnit ); + + + // If aHighlightRect's width is remarkably smaller than client rect's + // width then assume we're working with a grid. Otherwise list-specific + // positioning rules are used. + if ( aHighlightRect.Width() < clientRect.Width() / 2 ) // grid + { + count = 4; + + if ( !AknLayoutUtils::LayoutMirrored() ) + { + // top left + location[0] = TPoint( leftX, aHighlightRect.iTl.iY - + controlSize.iHeight - layoytDataUnit ); + + // bottom left + location[1] = TPoint( leftX, aHighlightRect.iBr.iY + layoytDataUnit ); + + // top right + location[2] = TPoint( rightX, aHighlightRect.iTl.iY - + controlSize.iHeight - layoytDataUnit ); + + // bottom right + location[3] = TPoint( rightX, aHighlightRect.iBr.iY + layoytDataUnit ); + } + else + { + // top right + location[0] = TPoint( rightX, aHighlightRect.iTl.iY - + controlSize.iHeight - layoytDataUnit ); + + // bottom right + location[1] = TPoint( rightX, aHighlightRect.iBr.iY + layoytDataUnit ); + + // top left + location[2] = TPoint( leftX, aHighlightRect.iTl.iY - + controlSize.iHeight - layoytDataUnit ); + + // bottom left + location[3] = TPoint( leftX, aHighlightRect.iBr.iY + layoytDataUnit ); + } + } + else // listbox + { + count = 2; + + if ( !AknLayoutUtils::LayoutMirrored() ) + { + // top right + location[0] = TPoint( rightX, aHighlightRect.iTl.iY + layoytDataUnit ); + + // bottom right + location[1] = TPoint( rightX, aHighlightRect.iBr.iY - + controlSize.iHeight - layoytDataUnit ); + } + else + { + // top left + location[0] = TPoint( leftX, aHighlightRect.iTl.iY + layoytDataUnit ); + + // bottom left + location[1] = TPoint( leftX, aHighlightRect.iBr.iY - + controlSize.iHeight - layoytDataUnit ); + } + } + + // loop through all positions and pick up the first suitable one + for ( TInt i = 0; i < count; ++i ) + { + if ( clientRect.Contains( location[i] ) && + clientRect.Contains( location[i] + aControl->Size() ) ) + { + return TRect( location[i], controlSize ); + } + } + + // None of the possible rectangles was big enough. Simply return the primary + // rectangle. + return TRect( location[0], controlSize ); + } + +EXPORT_C AknLayoutUtils::TAknMainPaneState AknLayoutUtils::MainPaneState() +{ + AknLayoutUtils::TAknMainPaneState state = AknLayoutUtils::TAknMainPaneState(0); + + if (AknStatuspaneUtils::FlatLayoutActive() && !Layout_Meta_Data::IsLandscapeOrientation()) + { + state = AknLayoutUtils::TAknMainPaneState(state | AknLayoutUtils::EAknMainPaneForTinyStatusPane); + } + + + return state; + +} + +EXPORT_C TBool AknLayoutUtils::PenEnabled() + { +#ifdef RD_SCALABLE_UI_V2 + return Layout_Meta_Data::IsPenEnabled(); +#else + return EFalse; +#endif // RD_SCALABLE_UI_V2 + } + +EXPORT_C TBool AknLayoutUtils::MSKEnabled() + { + // Check the middle softkey status from CenRep. + // Value will be cached in future. + if ( CEikonEnv::Static()->AppUi() && iAvkonAppUiBase ) + { + if ( iAvkonAppUiBase->IsMSKEnabledApp() ) + { + return ETrue; + } + } + else // Cached value can't be used - fetch MSK value from CenRep. + { + if ( !Layout_Meta_Data::IsMSKEnabled() ) + { + return EFalse; + } + + TInt MSKenabled( 0 ); + CRepository* cenRep = NULL; + TRAPD( err, cenRep = CRepository::NewL( KCRUidAvkon ) ); + if ( !err ) + { + err = cenRep->Get( KAknMiddleSoftkeyEnabled, MSKenabled ); + delete cenRep; + } + + if ( err != KErrNone || MSKenabled == 0 ) + { + return EFalse; + } + + return ETrue; + } + + return EFalse; + } + + +EXPORT_C void AknLayoutUtils::GetEdwinVerticalPositionAndHeightFromLines( + TInt aEdwinParent, + const TAknTextLineLayout& aLayout, + TInt aBaselineSeparationOverRide, + TInt aNumberOfLinesToShowOverRide, + TInt& aEdwinVerticalPositionRelativeToParent, + TInt& aEdwinHeight ) + { + aEdwinHeight = AknLayoutUtilsHelpers::EdwinHeightFromLines( + aEdwinParent, + aLayout, + aBaselineSeparationOverRide, + aNumberOfLinesToShowOverRide, + aEdwinVerticalPositionRelativeToParent ); + } + +EXPORT_C TInt AknLayoutUtils::EdwinLinesWithinHeight ( + const TAknTextLineLayout& aLayout, + TInt aBaselineSeparationOverride, + TInt aMaxHeight, + TInt& aUsedHeight ) + { + return AknLayoutUtilsHelpers::EdwinLinesWithinHeight( + aLayout, + aBaselineSeparationOverride, + aMaxHeight, + aUsedHeight ); + } + +EXPORT_C TAknLayoutRect::TAknLayoutRect() : iRect(-666,-666,-666,-666) { } + +EXPORT_C void TAknLayoutRect::LayoutRect(const TRect &aParent, TInt aResourceId) + { + TResourceReader rr; + TRAPD(error, + { + CEikonEnv::Static()->CreateResourceReaderLC(rr, aResourceId); + LayoutRect(aParent, rr); + CleanupStack::PopAndDestroy(); + }); + if (error != KErrNone) + { + iColor = 0; + iRect = TRect(aParent.iTl, TSize(2,2)); + + } +#ifdef AKNUTILS_ENABLE_TRACES + __ASSERT_DEBUG(error == KErrNone, LOGTEXT(_L("TAknLayoutRect: Resource reader failed. Not everything will be drawn correctly"))); +#endif // AKNUTILS_ENABLE_TRACES + } + + +EXPORT_C void TAknLayoutRect::LayoutRect(const TRect &aParent, const AknLayoutUtils::SAknLayoutRect &aL) + { + LayoutRect(aParent, aL.iC,aL.iL, aL.iT, aL.iR, aL.iB, aL.iW, aL.iH); + } + +EXPORT_C void TAknLayoutRect::LayoutRect(const TRect &aParent, const TAknWindowLineLayout &aL) + { + LayoutRect(aParent, aL.iC,aL.il, aL.it, aL.ir, aL.ib, aL.iW, aL.iH); + } + +EXPORT_C void TAknLayoutRect::LayoutRect(const TRect &aParent, TResourceReader &aReader) + { + TInt C = aReader.ReadInt16(); + TInt l = aReader.ReadInt16(); + TInt t = aReader.ReadInt16(); + TInt r = aReader.ReadInt16(); + TInt b = aReader.ReadInt16(); + TInt W = aReader.ReadInt16(); + TInt H = aReader.ReadInt16(); + LayoutRect(aParent, C,l,t,r,b,W,H); + } + +EXPORT_C void TAknLayoutRect::LayoutRect(const TRect &aParent, TInt C, TInt l, TInt t, TInt r, TInt b, TInt W, TInt H) + { + if (C == ELayoutEmpty) + iColor = 0; + else + iColor = C; + iRect = AknLayoutUtils::RectFromCoords(aParent,l,t,r,b,W,H); + } + + EXPORT_C TRect TAknLayoutRect::Rect() const + { + __ASSERT_DEBUG(iRect != TRect(-666,-666,-666,-666), Panic(EAknPanicLayoutRectNotCalled)); + return iRect; + } + TBool TAknLayoutRect::Valid() const + { + return iRect != TRect(-666,-666,-666,-666); + } + +EXPORT_C TRgb TAknLayoutRect::Color() const + { + __ASSERT_DEBUG(iRect != TRect(-666,-666,-666,-666), Panic(EAknPanicLayoutRectNotCalled)); + return AKN_LAF_COLOR_STATIC(iColor); + } + +EXPORT_C void TAknLayoutRect::DrawRect(CWindowGc &aGc) const + { + __ASSERT_DEBUG(iRect != TRect(-666,-666,-666,-666), Panic(EAknPanicLayoutRectNotCalled)); + aGc.SetBrushColor(AKN_LAF_COLOR_STATIC(iColor)); + aGc.Clear(iRect); + } + +EXPORT_C void TAknLayoutRect::DrawOutLineRect(CWindowGc &aGc) const + { + __ASSERT_DEBUG(iRect != TRect(-666,-666,-666,-666), Panic(EAknPanicLayoutRectNotCalled)); + aGc.SetBrushColor(0xffffff); + aGc.SetBrushStyle(CGraphicsContext::ENullBrush); + aGc.SetPenColor(AKN_LAF_COLOR_STATIC(iColor)); + aGc.DrawRect(iRect); + aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); + } + +EXPORT_C void TAknLayoutRect::DrawImage(CBitmapContext &aGc, CFbsBitmap *aBitmap, CFbsBitmap *aMask) const + { + __ASSERT_DEBUG(iRect != TRect(-666,-666,-666,-666), Panic(EAknPanicLayoutRectNotCalled)); +#ifdef AKNUTILS_ENABLE_TRACES + __ASSERT_DEBUG(iRect.Size() == aBitmap->SizeInPixels(), LOGTEXT4(_L("LayoutRect/DrawImage, displayed area and image size does not match: (%d,%d) != (%d,%d)"), iRect.Size().iWidth, iRect.Size().iHeight, aBitmap->SizeInPixels().iWidth, aBitmap->SizeInPixels().iHeight)); +#endif // AKNUTILS_ENABLE_TRACES + if (aMask) + { + TSize s = iRect.Size(); + TRect rect(TPoint(0,0), s); + aGc.BitBltMasked(iRect.iTl, aBitmap, rect, aMask, ETrue); + } + else + { + aGc.SetClippingRect(iRect); + aGc.BitBlt(iRect.iTl, aBitmap); + aGc.CancelClippingRect(); + } + } + +EXPORT_C TAknLayoutText::TAknLayoutText() : iFont(0) { } + +EXPORT_C void TAknLayoutText::LayoutText(const TRect &aParent, TInt aResourceId, const CFont *aCustomFont) + { + TRAPD(error, + { + TResourceReader rr; + CEikonEnv::Static()->CreateResourceReaderLC(rr, aResourceId); + LayoutText(aParent, rr, aCustomFont); + CleanupStack::PopAndDestroy(); + }); + if (error != KErrNone) + { + iFont = LatinPlain12(); + iTextRect = TRect(aParent.iTl, TSize(aParent.Size().iWidth,2)); + iColor = 0; + iAlign = CGraphicsContext::ECenter; + iOffset = 0; + } +#ifdef AKNUTILS_ENABLE_TRACES + __ASSERT_DEBUG(error == KErrNone, LOGTEXT(_L("TAknLayoutText: Resource reader failed. Not everything will be drawn correctly."))); +#endif // AKNUTILS_ENABLE_TRACES + } + +EXPORT_C void TAknLayoutText::LayoutText(const TRect &aParent, const AknLayoutUtils::SAknLayoutText &aL, const CFont *aCustomFont) + { + LayoutText(aParent, aL.iFont, aL.iC, aL.iL, aL.iR, aL.iB, aL.iW, aL.iJ, aCustomFont); + } + +EXPORT_C void TAknLayoutText::LayoutText(const TRect &aParent, const TAknTextLineLayout &aL, const CFont *aCustomFont) + { + LayoutText(aParent, aL.FontId(), aL.iC, aL.il, aL.ir, aL.iB, aL.iW, aL.iJ, aCustomFont); + } + +EXPORT_C void TAknLayoutText::LayoutText(const TRect &aParent, TResourceReader &aReader, const CFont *aCustomFont) + { + TInt fontid = aReader.ReadInt16(); + TInt C = aReader.ReadInt16(); + TInt lm = aReader.ReadInt16(); + TInt rm = aReader.ReadInt16(); + TInt B = aReader.ReadInt16(); + TInt W = aReader.ReadInt16(); + TInt J = aReader.ReadInt16(); + LayoutText(aParent, fontid, C, lm, rm, B, W, J, aCustomFont); + } + +EXPORT_C void TAknLayoutText::LayoutText( const TRect &aParent, + TInt aFontId, + TInt aColor, + TInt aLeftMargin, + TInt aRightMargin, + TInt aBaseLine, + TInt aWidth, + TInt aJustification, + const CFont *aCustomFont ) + { + // this is most likely broken if custon font is used! + aBaseLine = AknLayoutUtils::CorrectBaseline(aParent.Height(), aBaseLine, aFontId); + + if (IsParentRelative(aLeftMargin)) { aLeftMargin = aLeftMargin - ELayoutP + aParent.Width(); } + if (IsParentRelative(aRightMargin)) { aRightMargin = aRightMargin - ELayoutP + aParent.Width(); } + if (IsParentRelative(aWidth)) { aWidth = aParent.Width() - ELayoutP + aWidth; } + + if (IsEmpty(aLeftMargin)) { aLeftMargin = aParent.Width() - aRightMargin - aWidth; } + if (IsEmpty(aRightMargin)) { aRightMargin = aParent.Width() - aLeftMargin - aWidth; } + if (IsEmpty(aWidth)) { aWidth = aParent.Width() - aLeftMargin - aRightMargin; } + + TInt fontId = aCustomFont ? EFontCustom : aFontId; + iFont = AknLayoutUtils::FontFromId(fontId, aCustomFont); + + iTextRect = aParent; + iColor = aColor; + iAlign = AknLayoutUtils::TextAlignFromId( aJustification ); + + const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( iFont ); + TInt textPaneHeight(0); + TInt textPaneAscent(0); + if ( layoutFont ) + { + textPaneHeight = layoutFont->TextPaneHeight(); + textPaneAscent = layoutFont->TextPaneTopToBaseline(); + } + else + { + textPaneHeight = iFont->HeightInPixels(); + textPaneAscent = iFont->AscentInPixels(); + } + + // everything is measured from the top down + iOffset = textPaneAscent; // Gives position of baseline relative to top of rectangle, as used in DrawText primitive + iTextRect.iTl.iY += aBaseLine + 1 - iOffset; // +1 for strange series 60 layout def'n of baseline + iTextRect.iBr.iY = iTextRect.iTl.iY + textPaneHeight; // Top to bottom is text pane height + iTextRect.iTl.iX += aLeftMargin; + iTextRect.iBr.iX -= aRightMargin; + } + + +EXPORT_C void TAknLayoutText::DrawText(CGraphicsContext &aGc, const TDesC& aText) const + { + DrawText( aGc, aText, ETrue ); + } + +EXPORT_C void TAknLayoutText::DrawText( + CGraphicsContext& aGc, + const TDesC& aText, + TBool aUseLogicalToVisualConversion ) const + { + DrawText(aGc, aText, aUseLogicalToVisualConversion, Color()); + } + +EXPORT_C void TAknLayoutText::DrawText( + CGraphicsContext& aGc, + const TDesC& aText, + TBool aUseLogicalToVisualConversion, + const TRgb &aColor + ) const + { + __ASSERT_DEBUG( iFont, Panic( EAknPanicLayoutTextNotCalled ) ); + aGc.UseFont( iFont ); + aGc.SetPenColor( aColor ); + if ( aText.Length() ) + { + HBufC* visualBuf = NULL; + TPtrC text( aText ); + + if ( aUseLogicalToVisualConversion ) + { + visualBuf = HBufC::New( aText.Length() + KAknBidiExtraSpacePerLine ); + + // In OOM, logical to visual conversion is not performed... + + if ( visualBuf ) + { + *visualBuf = aText; // copy + TPtr ptr = visualBuf->Des(); + + TInt maxWidth = iTextRect.Size().iWidth; + + // Logical to visual conversion. + AknBidiTextUtils::ConvertToVisualAndClip( + aText, + ptr, + *iFont, + maxWidth, + maxWidth ); + + text.Set( ptr ); + } + } + + // Calculate x-offset based on the used alignment + TInt margin = 0; + if ( iAlign != CGraphicsContext::ELeft ) + { + // Measure the full width of the text (ie. what DrawText needs) + TInt textWidth = AknBidiTextUtils::MeasureTextBoundsWidth( *iFont, text,CFont::TMeasureTextInput::EFVisualOrder ); + + const TInt extraWidth = iTextRect.Width() - textWidth; + if ( iAlign == CGraphicsContext::ECenter ) + { + margin = extraWidth / 2; + } + else // right aligned + { + margin = extraWidth; + } + } + + // Need to make the drawing rectangle bigger to account for underlines + TRect drawRect(iTextRect); + TInt height = drawRect.Height(); + // The underline position is not available from the GC. The following code imitates what Symbian CFbsBitGC implements. + // (height-iOffset) is the part below the baseline. Check if it sufficient + TInt extraHeightForUnderlining = 1 + Max(1, height/10)-(height-iOffset); + if ( extraHeightForUnderlining > 0 ) + drawRect.iBr.iY += extraHeightForUnderlining; + + aGc.DrawText( text, drawRect, iOffset, CGraphicsContext::ELeft, margin ); + delete visualBuf; + } + aGc.DiscardFont(); // Release the font cache + } + +EXPORT_C TRect TAknLayoutText::TextRect() const + { + __ASSERT_DEBUG(iFont, Panic(EAknPanicLayoutTextNotCalled)); + return iTextRect; + } + +TInt TAknLayoutText::BaselineOffset() const + { + __ASSERT_DEBUG(iFont, Panic(EAknPanicLayoutTextNotCalled)); + return iOffset; + } + +EXPORT_C void AknDrawWithSkins::DrawWindowShadow(CWindowGc &aGc, const TAknLayoutRect &aCoverRect, const TAknLayoutRect &aSecondShadowRect, const TAknLayoutRect &aFirstShadowRect, const TAknLayoutRect &aOutlineFrameRect, const TAknLayoutRect &aInsideAreaRect, CCoeControl *aControl) + { + MAknsSkinInstance *skin = AknsUtils::SkinInstance(); + MAknsControlContext *cc = NULL; + if (aControl) cc = AknsDrawUtils::ControlContext( aControl ); + + TBool windowFrameDrawn = EFalse; + TRect windowRect = aCoverRect.Rect(); + TAknLayoutRect topLeft; + topLeft.LayoutRect(windowRect, SkinLayout::Popup_windows_skin_placing__frame_general__Line_2()); + + TAknLayoutRect bottomRight; + bottomRight.LayoutRect(windowRect, SkinLayout::Popup_windows_skin_placing__frame_general__Line_5()); + + TRect outerRect = TRect(topLeft.Rect().iTl, bottomRight.Rect().iBr); + TRect innerRect = TRect(topLeft.Rect().iBr, bottomRight.Rect().iTl); + aGc.SetPenStyle(CGraphicsContext::ENullPen); + const TAknsItemID *frameId = &KAknsIIDQsnFrPopup; + const TAknsItemID *frameCenterId = &KAknsIIDQsnFrPopupCenter; + windowFrameDrawn = AknsDrawUtils::DrawFrame(skin, aGc, outerRect, innerRect, *frameId, *frameCenterId); + + if (!windowFrameDrawn) + { +// TInt x0 = aCoverRect.Rect().iTl.iX; +// TInt x1 = aOutlineFrameRect.Rect().iTl.iX; + TInt x2 = aFirstShadowRect.Rect().iTl.iX; + TInt x3 = aSecondShadowRect.Rect().iTl.iX; + +// TInt y0 = aCoverRect.Rect().iTl.iY; +// TInt y1 = aOutlineFrameRect.Rect().iTl.iY; + TInt y2 = aFirstShadowRect.Rect().iTl.iY; + TInt y3 = aSecondShadowRect.Rect().iTl.iY; + + TInt x4 = aOutlineFrameRect.Rect().iBr.iX; + TInt x5 = aFirstShadowRect.Rect().iBr.iX; + TInt x6 = aSecondShadowRect.Rect().iBr.iX; +// TInt x7 = aCoverRect.Rect().iBr.iX; + + TInt y4 = aOutlineFrameRect.Rect().iBr.iY; + TInt y5 = aFirstShadowRect.Rect().iBr.iY; + TInt y6 = aSecondShadowRect.Rect().iBr.iY; +// TInt y7 = aCoverRect.Rect().iBr.iY; + + aGc.SetBrushColor(aCoverRect.Color()); + AknsDrawUtils::Background(skin, cc, aControl, aGc, aCoverRect.Rect()); + + AknsDrawUtils::BackgroundBetweenRects( skin, cc, aControl, aGc, TRect(x2,y2,x4-1,y4-1), aInsideAreaRect.Rect()); + aOutlineFrameRect.DrawOutLineRect(aGc); + aGc.SetBrushColor(aFirstShadowRect.Color()); + aGc.Clear(TRect(x2,y4,x5,y5)); + aGc.Clear(TRect(x4,y2,x5,y4)); + aGc.SetBrushColor(aSecondShadowRect.Color()); + aGc.Clear(TRect(x3,y5,x6,y6)); + aGc.Clear(TRect(x5,y3,x6,y5)); + } + } + +EXPORT_C void AknDraw::DrawWindowShadow(CWindowGc &aGc, + const TAknLayoutRect &aCoverRect, + const TAknLayoutRect &aSecondShadowRect, + const TAknLayoutRect &aFirstShadowRect, + const TAknLayoutRect &aOutlineFrameRect, + const TAknLayoutRect &aInsideAreaRect) + { + AknDrawWithSkins::DrawWindowShadow(aGc, aCoverRect, aSecondShadowRect, aFirstShadowRect, aOutlineFrameRect, aInsideAreaRect, NULL); + } + +static void DrawEmptyListImpl_real( const TRect &aClientRect, + CWindowGc &aGc, + TPtrC text, + CCoeControl *aControl = NULL, + TBool aSettingPageList = EFalse ); + + +// Drawing with skins support. +EXPORT_C +void AknDrawWithSkins::DrawEmptyListWithFind( const TRect &/*aClientRect_1*/, + CWindowGc &aGc, + TPtrC text, + CCoeControl *aControl ) + { + // this method is called when a list with fixed find is used. + // should pass info on find further on up the road, but + // that makes no sense since laf is brain damaged + DrawEmptyListImpl_real( TRect(0,0,0,0), aGc, text, aControl ); + } + +EXPORT_C void AknDrawWithSkins::DrawEmptyListHeading(const TRect &aClientRect, CWindowGc& aGc, TPtrC aText, CCoeControl *aControl) + { + DrawEmptyListImpl_real( aClientRect, aGc, aText, aControl ); + } + +EXPORT_C void AknDrawWithSkins::DrawEmptyListForSettingPage(const TRect &aRect, CWindowGc &aGc, TPtrC text, CCoeControl *aControl) + { + if ( aControl && aControl->FindBackground() ) + { + DrawEmptyListImpl_real( aRect, aGc, text, NULL, ETrue); + return; + } + + DrawEmptyListImpl_real( aRect, aGc, text, aControl, ETrue); + } + +EXPORT_C void AknDrawWithSkins::DrawEmptyList(const TRect& /*aClientRect_1*/, CWindowGc &aGc, TPtrC text, CCoeControl *aControl) + { + DrawEmptyListImpl_real( TRect(0,0,0,0), + aGc, + text, + aControl ); + } + + +// Plain drawing without skins + +EXPORT_C void AknDraw::DrawEmptyListWithFind(const TRect &aClientRect_1, CWindowGc &aGc, TPtrC text) + { + AknDrawWithSkins::DrawEmptyListWithFind(aClientRect_1, aGc, text, NULL); + } + +EXPORT_C void AknDraw::DrawEmptyListHeading(const TRect &aClientRect, CWindowGc& aGc, TPtrC aText) + { + AknDrawWithSkins::DrawEmptyListHeading(aClientRect, aGc, aText, NULL); + } + +EXPORT_C void AknDraw::DrawEmptyListForSettingPage(const TRect &aRect, CWindowGc &aGc, TPtrC text) + { + AknDrawWithSkins::DrawEmptyListForSettingPage(aRect, aGc, text, NULL); + } + + +EXPORT_C void AknDraw::DrawEmptyList(const TRect &aClientRect_1, CWindowGc &aGc, TPtrC text) + { + AknDrawWithSkins::DrawEmptyList(aClientRect_1, aGc, text, NULL); + } + +/* should be deprecated */ +EXPORT_C void AknDraw::DrawEmptyListImpl(const TRect &aClientRect, CWindowGc &aGc, TPtrC text, TInt /*line1layout*/, TInt /*line2layout*/) + { + DrawEmptyListImpl_real( aClientRect, aGc, text ); + } + +TBool DrawEmptyListImpl_real_DrawBg( CWindowGc &aGc, + CCoeControl *aControl, + TBool /*aSettingPageList*/ ) + + { + // Clearing area + TRect mainPane; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPane ); + // aItemTextRect is list item's rect, width of which is smaller than width of the list + // with a scroll bar. List needs to draw under scroll bar anyway, so we need to + // modify given rect here. + TRect mainPaneRect( mainPane.Size() ); + + MAknsSkinInstance *skin = AknsUtils::SkinInstance(); + MAknsControlContext *cc = NULL; + TBool owned = EFalse; + + if (aControl) + { + cc = AknsDrawUtils::ControlContext( aControl ); + } + + if (!cc) + { + TRAPD(error, + { + const TAknsItemID *id = &KAknsIIDNone; + if (AknsUtils::AvkonSkinEnabled()) + { + cc = CAknsListBoxBackgroundControlContext::NewL( + KAknsIIDQsnBgAreaMainListGene, + mainPaneRect, EFalse, *id, mainPaneRect ); + } + }); + if (error == KErrNone) + { + owned = ETrue; + } + } + + TBool isPopupList( EFalse ); + if ( aControl ) + { + // unfortunately, there is no other way to check this. + TAknLayoutRect lr; + lr.LayoutRect( mainPane, AknLayoutScalable_Avkon::popup_menu_window( 0 ) ); + lr.LayoutRect( lr.Rect(), AknLayoutScalable_Avkon::listscroll_menu_pane( 0 ) ); + lr.LayoutRect( lr.Rect(), AknLayoutScalable_Avkon::list_menu_pane( 0 ) ); + lr.LayoutRect( lr.Rect(), AknLayoutScalable_Avkon::list_single_pane_cp2( 0 ) ); + + if ( aControl->Size().iWidth == lr.Rect().Width() ) + { + isPopupList = ETrue; + } + + AknsDrawUtils::Background( skin, cc, aControl, aGc, aControl->Rect(), + KAknsDrawParamNoClearUnderImage | + KAknsDrawParamBottomLevelRGBOnly ); + } + + if (owned) + { + delete cc; + } + + return isPopupList; + } + +void DrawEmptyListImpl_real_DrawUpToTwoLines( CWindowGc &aGc, + TPtrC aText, + TAknLayoutText &aLine1, + TAknLayoutText &aLine2, + TInt aLine1length, + TInt aLine2length, + const CFont* aFont, + TRgb aColor, + TDes& aBuffer, + TBool aPopupList, + TRect aParentRect, + TBool /*aSettingPageList*/) + { + TRAPD( error, + { + CArrayFix* wrapWidthArray = new( ELeave ) CArrayFixFlat(10); + CleanupStack::PushL( wrapWidthArray ); + + wrapWidthArray->AppendL( aLine1length ); + wrapWidthArray->AppendL( aLine2length ); + + AknBidiTextUtils::ConvertToVisualAndWrapToStringL( + aText, *wrapWidthArray, *aFont, aBuffer, ETrue ); + + CleanupStack::PopAndDestroy(); // wrapWidthArray + } ); // TRAP end + + if ( error != KErrNone ) + { + aBuffer = aText; + } + + // Drawing text + aGc.Reset(); + TBool oneline( EFalse ); + TPtrC ptr = aBuffer; + TPtrC top = ptr; + TInt off = ptr.Locate('\n'); + if ( off >= 0 ) + { + top.Set(ptr.Left(off)); + ptr.Set(ptr.Mid(off+1)); + + TInt off1 = ptr.Locate('\n'); + if ( off1 >= 0 ) + { + ptr.Set(ptr.Left(off1)); + } + else + { + oneline = ETrue; + } + } + + aGc.SetBrushStyle(CGraphicsContext::ENullBrush); + aGc.SetOpaque( ETrue ); // transparency off + + // no layout exist for popup list - mainpane layout is ok for X + // coords, center vertically. Also need to calculate vertical + // position for mainpane lists, since laf is broken as designed. + // If you don't believe this, try using laf values in phonebook. + aGc.UseFont( aFont ); + aGc.SetPenColor( aColor ); + + // center horizontally + CGraphicsContext::TTextAlign textAlign( CGraphicsContext::ECenter ); + + // center vertically + TInt h = aParentRect.Height(); + TInt lineh = aLine1.TextRect().Height(); + TRect r1( aLine1.TextRect() ); + TRect r2( aLine2.TextRect() ); + + TInt baseLineOffset( aLine1.BaselineOffset() ); + + // gap between lines - must be calculated this way, since no other + // way really exists. Could be calculated from layout data, but + // data is wrong, as 1st line is calculated from top of parent + // rect, and 2nd line is calculated from bottom of the parent + // rect. iAvkonAppUi->ClientRect() as parent rect would otherwise + // be ok and give nice results, but in phonebook ClientRect() is + // not what it should be - it is some strange amount too large. + // This can not be fixed unless layout data is fixed to use only + // top marginals. + TInt lineGap( lineh / 6 ); + + TInt m; // // middle point of texts + if ( aPopupList ) + { + m = aParentRect.iTl.iY + h / 2;// + lineh + lineGap / 2; + if ( oneline ) + { + m += lineh / 2; + } + } + else + { + m = aParentRect.iTl.iY + h / 3 + lineh + lineGap / 2; + } + + TInt b1( m - lineGap / 2 ); // bottom of 1st line + TInt b2( m + lineh + lineGap / 2 ); // botton of 2nd line + + // rects of texts + r1.iTl.iY = b1 - lineh; + r1.iBr.iY = b1; + + r2.iTl.iY = b2 - lineh; + r2.iBr.iY = b2; + + aGc.DrawText( top, r1, baseLineOffset, textAlign ); + if ( !oneline ) + { + aGc.DrawText( ptr, r2, baseLineOffset, textAlign ); + } + + + aGc.DiscardFont(); + aGc.SetOpaque( EFalse ); // transparency back on + } + +void DrawEmptyListImpl_real_DrawMoreThanTwoLines( const TRect &aParentRect, + CWindowGc &aGc, + TPtrC aText, + TRgb aColor, + TDes& buffer ) + + { + // fetch layouts + TAknLayoutText line[4]; + + line[0].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t1(2) ); + line[1].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t3(0) ); + line[2].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t4(0) ); + line[3].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t5(0) ); + + TInt lineLength[4]; + TInt i; + for ( i = 0; i < 4; i++ ) + { + lineLength[i] = line[i].TextRect().Width(); + } + + const CFont *bigFont = line[0].Font(); + const CFont *smallFont = line[1].Font(); + + // wrap text + TInt off = aText.Locate('\n'); + TPtrC rest( aText ); + rest.Set( aText.Right(aText.Length() - off - 1 )); + + HBufC* firstLine = NULL; + + TRAPD( error1, + { + firstLine = HBufC::NewL( + aText.Left(off).Length() + KAknBidiExtraSpacePerLine ); + }); + + if (error1 == KErrNone) + { + TPtr firstLinePtr = firstLine->Des(); + AknBidiTextUtils::ConvertToVisualAndClip( + aText.Left(off), + firstLinePtr, + *bigFont, + lineLength[0], + lineLength[0] ); + } + + TRAPD( error2, + { + CArrayFix* wrapWidthArray = new( ELeave ) CArrayFixFlat(10); + CleanupStack::PushL( wrapWidthArray ); + + // wrap small font lines + wrapWidthArray->Reset(); + for ( i = 1; i <= 3; i++ ) + { + wrapWidthArray->AppendL( lineLength[i] ); + } + + AknBidiTextUtils::ConvertToVisualAndWrapToStringL( + rest, *wrapWidthArray, *smallFont, buffer, ETrue ); + + CleanupStack::PopAndDestroy(); // wrapWidthArray + } ); // TRAP end + + + TPtrC ptr[4]; + TInt n = 0; + + if (error1 == KErrNone) + { + ptr[0].Set( firstLine->Des() ); + } + if ( error1 != KErrNone || error2 != KErrNone ) + { + ptr[0].Set(aText.Left(off)); + } + else + { + TInt newlines[3]; + n = 0; + for ( i = 0; i < buffer.Length(); i++ ) + { + if ( buffer[i] != '\n' ) + { + continue; + } + newlines[n] = i; + + n++; + if ( n >= 3 ) + { + break; + } + } + + if ( n >= 1 ) + { + ptr[1].Set( buffer.Left( newlines[0] ) ); + } + if ( n >= 2 ) + { + ptr[2].Set( buffer.Mid( newlines[0] + 1, newlines[1] - newlines[0] - 1 ) ); + } + if ( n >= 3 ) + { + ptr[3].Set( buffer.Mid( newlines[1] + 1, newlines[2] - newlines[1] - 1 ) ); + } + } + + // draw texts + aGc.SetBrushStyle(CGraphicsContext::ENullBrush); + aGc.SetOpaque( ETrue ); // transparency off + + for ( i = 0; i < 4; i++ ) + { + line[i].DrawText( aGc, ptr[i], EFalse, aColor ); + } + aGc.SetOpaque( EFalse ); // transparency back on + delete firstLine; + } + +void DrawEmptyListImpl_real( const TRect &aClientRect, + CWindowGc &aGc, + TPtrC aText, + CCoeControl *aControl, + TBool aSettingPageList ) + { + TBool popupList = DrawEmptyListImpl_real_DrawBg( aGc, aControl, aSettingPageList ); + if ( !aText.Length() ) + { + return; + } + + HBufC* hbuf = HBufC::New( aText.Size() + 3 * ( KAknBidiExtraSpacePerLine +1 ) + + 10 ); // reserve space for newlines + if ( !hbuf ) + { // can't really do anything + return; + } + + TPtr buffer(hbuf->Des()); + + TRgb color( KRgbBlack ); + if ( AknsUtils::AvkonSkinEnabled() ) + { + TRgb c; + MAknsSkinInstance *skin = AknsUtils::SkinInstance(); + TInt err = AknsUtils::GetCachedColor( skin, + c, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG6 ); + if ( !err ) + { + color = c; + } + } + + /* + * input text can be either + * - "line1" + * - "line1 which will be wrapped to 2 lines and truncated with..." + * - "line1\nline2" + * - "line1\nMany other lines which will be wrapped to several lines" + * + * there are 3 layouts + * - 1 line with big font, + * - 2 lines with big font + * - 1 line with big font + 1..3 lines with small font (not for popup lists) + * + * so first we need to check if given text has a newline, + * if so, then we need to check if given text fits to 2 lines or + * should it be split to several small font lines + */ + + TInt i, n; + n = 0; + for (i = 0; i < aText.Length(); i ++) + { + if ( aText[i] == '\n' ) + { + n++; + } + } + + + TAknTextComponentLayout layout1( AknLayoutScalable_Avkon::main_pane_empty_t1( 0 ) ); + TAknTextComponentLayout layout2( AknLayoutScalable_Avkon::main_pane_empty_t2( 0 ) ); + TAknLayoutText line1; + TAknLayoutText line2; + TRect clientRect( iAvkonAppUi->ClientRect() ); + TRect parentRect; + + if( aSettingPageList ) + { + parentRect = aClientRect; + } + else if( aControl ) + { + parentRect = aControl->Rect(); + } + else + { + parentRect = TRect(0,0,clientRect.Width(),clientRect.Height()); + } + + line1.LayoutText( parentRect, layout1 ); + TInt line1length = line1.TextRect().Size().iWidth; + + line2.LayoutText( parentRect, layout2 ); + TInt line2length = line2.TextRect().Size().iWidth; + + const CFont *font = line1.Font(); + + if ( n == 0 ) + { // one line, or one line which will be wrapped to two + DrawEmptyListImpl_real_DrawUpToTwoLines( aGc, aText, line1, line2, + line1length, line2length, + font, color, buffer, + popupList, parentRect, aSettingPageList ); + delete hbuf; + return; + } + + TRAPD( error, + { + CArrayFix* wrapWidthArray = new( ELeave ) CArrayFixFlat(10); + CleanupStack::PushL( wrapWidthArray ); + + wrapWidthArray->AppendL( line1length ); + wrapWidthArray->AppendL( line2length ); + wrapWidthArray->AppendL( line2length ); // allow wrap to 3 lines + + AknBidiTextUtils::ConvertToVisualAndWrapToStringL( + aText, *wrapWidthArray, *font, buffer, ETrue ); + + CleanupStack::PopAndDestroy(); // wrapWidthArray + } ); // TRAP end + + // there is no layout for empty popuplist + if ( error != KErrNone || popupList ) + { + DrawEmptyListImpl_real_DrawUpToTwoLines( aGc, aText, line1, line2, + line1length, line2length, + font, color, buffer, + popupList, parentRect, aSettingPageList ); + } + else + { // 1 line with big font + 1..3 lines with small font + DrawEmptyListImpl_real_DrawMoreThanTwoLines( parentRect, aGc, aText, color, buffer ); + } + + delete hbuf; + } + + + +EXPORT_C TBool AknTextUtils::ClipToFit(TDes& aBuffer, TClipDirection aDir, CEikFormattedCellListBox *aListBox, TInt aItemIndex, TInt aSubCellNumber) + { + CFormattedCellListBoxData *data = aListBox->ItemDrawer()->FormattedCellData(); + const CFont *font = data->Font(aListBox->ItemDrawer()->Properties(aItemIndex), aSubCellNumber); + TSize cellsize = data->SubCellSize(aSubCellNumber); + TMargins margin = data->SubCellMargins(aSubCellNumber); + TInt width = cellsize.iWidth - margin.iLeft - margin.iRight; + TInt clipgap = data->SubCellTextClipGap(aSubCellNumber); + return ClipToFit(aBuffer, *font, width, aDir, width + clipgap); + } + +EXPORT_C TBool AknTextUtils::ClipToFit(TDes& aBuffer, TClipDirection aDir, CEikColumnListBox *aListBox, TInt aItemIndex, TInt aColumnNumber) + { + CColumnListBoxData *data = aListBox->ItemDrawer()->ColumnData(); + const CFont *font = data->Font(aListBox->ItemDrawer()->Properties(aItemIndex), aColumnNumber); + TInt cellsize = data->ColumnWidthPixel(aColumnNumber); + TMargins margin = data->ColumnMargins(aColumnNumber); + TInt width = cellsize - margin.iLeft - margin.iRight; + TInt clipgap = data->ColumnTextClipGap(aColumnNumber); + return ClipToFit(aBuffer, *font, width, aDir, width + clipgap); + } + +EXPORT_C TBool AknTextUtils::ClipToFit( + TDes& aBuffer, + const CFont& aFont, + TInt aMaxWidthInPixels, + AknTextUtils::TClipDirection aDir, + TInt aClipWidth, + const TDesC& aClipString ) + { + TAknLocVariant variants[KAknMaxLocVariants]; + TInt numVariants = TAknTextWrapper::GetLocVariants( aBuffer, variants ); + + TBool truncated = ETrue; + TInt i = 0; + + TPtr buffer( NULL, 0 ); + + while ( i < numVariants && truncated ) + { + buffer.Set( NULL, 0, 0 ); + TInt length = variants[i].iEnd - variants[i].iStart; + if ( length ) + { + buffer.Set( &(aBuffer[variants[i].iStart]), length, length ); + } + + truncated = DoClipToFit( + buffer, + aFont, + aMaxWidthInPixels, + aDir, + aClipWidth, + aClipString ); + + i++; + } + + // Move the selected variant in the beginning of the target buffer + // or if it is already, set the length correctly. + i--; + + TInt start = variants[i].iStart; + + if ( start > 0 ) + { + TPtrC selected = aBuffer.Mid( start, buffer.Length() ); + aBuffer.Copy( selected ); + } + else + { + aBuffer.SetLength( buffer.Length() ); + } + + return truncated; + } + +// ----------------------------------------------------------------------------- +// AknTextUtils::DoClipToFit() +// ----------------------------------------------------------------------------- +// +TBool AknTextUtils::DoClipToFit( + TDes& aBuffer, + const CFont& aFont, + TInt aMaxWidthInPixels, + AknTextUtils::TClipDirection aDir, + TInt aClipWidth, + const TDesC& aClipString ) + { + if ( !aBuffer.Length() ) + { + return EFalse; + } + + TInt textWidth = aFont.TextWidthInPixels( aBuffer ); + + if ( textWidth <= aMaxWidthInPixels ) + { + return EFalse; + } + + TText clipChar = 0; + TInt extraWidth = 0; + if ( aClipString.Length() ) + { + clipChar = KDefaultClipChar; + extraWidth = aFont.CharWidthInPixels( clipChar ); + } + + if ( aClipWidth == KDefaultClipWidth ) + { + aClipWidth = aMaxWidthInPixels; + } + + // Not enough space even for clip char alone - return empty descriptor. + if ( aClipWidth < extraWidth ) + { + aBuffer.Zero(); + return ETrue; + } + + switch( aDir ) + { + case AknTextUtils::EClipFromEnd: + { + TInt cutOff = aFont.TextCount( aBuffer, aClipWidth - extraWidth ); + + // This is "avkon rule": should not insert ellipsis right after a space. + if ( cutOff > 1 && + aBuffer[cutOff - 1] == ' ' && + aBuffer[cutOff - 2] != ' ' ) + { + cutOff--; + } + aBuffer.SetLength( cutOff ); + if ( aClipString.Length() ) + { + aBuffer.Append( clipChar ); + } + break; + } + + case AknTextUtils::EClipFromBeginning: + { + TPtrC ptr = aBuffer; + + while ( textWidth > aClipWidth - extraWidth ) + { + TChar c = ptr[0]; + textWidth -= aFont.CharWidthInPixels( c ); + ptr.Set( ptr.Mid( 1 ) ); + } + + if ( ptr.Length() && ptr[0] == ' ' ) + { + ptr.Set( ptr.Mid( 1 ) ); + } + aBuffer.Zero(); + if ( aClipString.Length() ) + { + aBuffer.Append( clipChar ); + } + aBuffer.Append( ptr ); + break; + } + + case AknTextUtils::EDoNotClip: + break; + + default: + __ASSERT_DEBUG( 0, User::Invariant() ); + break; + }; + + return ETrue; + } + +/** + * EXPORTED TEXT WRAPPING METHODS + */ +EXPORT_C void AknTextUtils::WrapToArrayL( + const TDesC& aStringToWrap, + const CArrayFix& aLineWidthArray, + const CFont& aFont, + CArrayFix& aWrappedArray ) + { + TPtr ptr( + (TText*)aStringToWrap.Ptr(), + aStringToWrap.Length(), + aStringToWrap.Length() ); + + WrapToArrayL( + ptr, + &aLineWidthArray, + aFont, + aWrappedArray, + 0, + 0, + AknBidiTextUtils::EImplicit ); + } + +EXPORT_C void AknTextUtils::WrapToArrayL( + const TDesC& aStringToWrap, + TInt aLineWidth, + const CFont& aFont, + CArrayFix& aWrappedArray ) + { + TPtr ptr( + (TText*)aStringToWrap.Ptr(), + aStringToWrap.Length(), + aStringToWrap.Length() ); + + WrapToArrayL( + ptr, + NULL, + aFont, + aWrappedArray, + aLineWidth, + 0, + AknBidiTextUtils::EImplicit ); + } + +EXPORT_C void AknTextUtils::WrapToArrayAndClipL( + TDes& aStringToWrap, + const CArrayFix& aLineWidthArray, + const CFont& aFont, + CArrayFix& aWrappedArray) + { + WrapToArrayL( + aStringToWrap, + &aLineWidthArray, + aFont, + aWrappedArray, + 0, + TAknTextWrapper::EClip, + AknBidiTextUtils::EImplicit ); + } + +EXPORT_C void AknTextUtils::ChopToArrayAndClipL( + TDes& aStringToChop, + const CArrayFix& aLineWidthArray, + const CFont& aFont, + CArrayFix& aChoppedArray) + { + AknTextUtils::ChopToArrayAndClipL( + aStringToChop, + &aLineWidthArray, + aFont, + aChoppedArray, + 0 ); + } + +EXPORT_C void AknTextUtils::ChopToArrayAndClipL( + TDes& aStringToChop, + TInt aLineWidth, + const CFont& aFont, + CArrayFix& aChoppedArray ) + { + AknTextUtils::ChopToArrayAndClipL( + aStringToChop, + NULL, + aFont, + aChoppedArray, + aLineWidth ); + } + +EXPORT_C void AknTextUtils::WrapToStringL( + const TDesC& aStringToWrap, + const CArrayFix& aLineWidthArray, + const CFont& aFont, + TDes& aWrappedString ) + { + WrapToStringL( + aStringToWrap, + aLineWidthArray, + aFont, + aWrappedString, + 0, + AknBidiTextUtils::EImplicit ); + } + + +EXPORT_C void AknTextUtils::WrapToStringAndClipL( + const TDesC& aStringToWrap, + const CArrayFix& aLineWidthArray, + const CFont& aFont, + TDes& aWrappedString) + { + WrapToStringL( + aStringToWrap, + aLineWidthArray, + aFont, + aWrappedString, + TAknTextWrapper::EClip, + AknBidiTextUtils::EImplicit ); + } + +EXPORT_C void AknTextUtils::ReplaceCharacters(TDes &aDes, const TDesC &aChars, TChar aReplacement) + // + // Running time O(aDes.Length() * aChars.Length()) + // Does not change length of the string. + // + { + TInt src = 0; + TInt srclength = aDes.Length(); + while(src < srclength) + { + TChar c = aDes[src]; + if (aChars.LocateF(c) != KErrNotFound) + aDes[src] = TUint16(aReplacement); + ++src; + } + } + +EXPORT_C void AknTextUtils::PackWhiteSpaces(TDes &aDes, const TDesC &aWhiteSpaceChars) + // + // This one finds several whitespace characters and packs them into one + // character. O(aDes.Length() * aChars.Length()) + // + { + TInt target=0; + TInt src = 0; + TInt srclength = aDes.Length(); + TBool lastWasWhiteSpace = EFalse; + + while (src < srclength) + { + aDes[target] = aDes[src]; + TChar c = aDes[src]; + + TBool currentIsWhiteSpace = aWhiteSpaceChars.LocateF(c) != KErrNotFound; + + if (!( lastWasWhiteSpace && currentIsWhiteSpace )) + ++target; + + ++src; + lastWasWhiteSpace = currentIsWhiteSpace; + } + aDes.SetLength(target); + + } + +EXPORT_C void AknTextUtils::StripCharacters(TDes &aDes, const TDesC &aChars) + { + // + // This algorithm has running time of O(aDes.Length() * aChars.Length()). + // + TInt target=0; + TInt src = 0; + TInt srclength = aDes.Length(); + while (src < srclength) + { + aDes[target] = aDes[src]; + TChar c = aDes[src]; + if (aChars.LocateF(c) == KErrNotFound) + ++target; + ++src; + } + aDes.SetLength(target); + } + +/** +* This routine scans the descriptor passed to it, searching for a character that +* is neither space nor ECoCategory nor ECfCategory. +* +* Currently not exported outside Avkon +*/ +TBool AknTextUtils::IsEmptyText( const TDesC& aTextToTest ) + { + TBool ret = EFalse; + for(TInt i = 0; i < aTextToTest.Length(); i++) + { + TChar c (aTextToTest[i]); + + TChar::TCategory cat = c.GetCategory(); + if ( !c.IsSpace() && cat != TChar::ECoCategory && cat != TChar::ECfCategory ) + { // not space and not private use char + ret = ETrue; + break; + } + } + + return ret; + } + + +static TChar NumberToBase(TChar ch) + { + TDigitType d[] = { EDigitTypeWestern, EDigitTypeArabicIndic, EDigitTypeEasternArabicIndic, EDigitTypeDevanagari, EDigitTypeThai }; + TInt i = 0; + TInt num = sizeof(d)/sizeof(d[0]); + while(iTChar(d[i]) && chSettingCache(); + return TBidiText::ScriptDirectionality( cache.InputLanguage() ); + } + + +/** +Derive the digit type for text editor display from the current locale settings and +current input language. +The digit type should be retrieved on construction and each time the locale settings change. +This implementation is really only handling Arabic at the moment. +*/ +TDigitType AknTextUtils::InputLanguageFilteredDigitType() + { + TBool useNonLatin = DigitModeQuery(EDigitModeEditorDefault); + TDigitType retDigitType(EDigitTypeWestern); + if (useNonLatin) + { + TLocale locale; + retDigitType = locale.DigitType(); + } + return retDigitType; + } + +/** +Derive the digit type for umeric editors where the localized digit setting must be filtered +to have an appropriate display text language. +This implementation is pretty thorough and should be OK for Farsi, Urdu, Thai as well as Arabic. +*/ +TDigitType AknTextUtils::DisplayTextLanguageFilteredDigitType() + { + TBool useNonLatin = DigitModeQuery(EDigitModeNumberEditor); + TDigitType retDigitType(EDigitTypeWestern); + if (useNonLatin) + { + TLocale locale; + retDigitType = locale.DigitType(); + } + return retDigitType; + } +/** +* This implementation maps the specification issue that purely numeric editors should filter +* on display text language. +*/ +EXPORT_C TDigitType AknTextUtils::NumericEditorDigitType() + { + return DisplayTextLanguageFilteredDigitType(); + } + +/** +* This implementation maps the specification issue that alphanumeric editors should filter +* on input language. +*/ +EXPORT_C TDigitType AknTextUtils::TextEditorDigitType() + { + return InputLanguageFilteredDigitType(); + } + +/** +* This convenience method converts a display text to presentation form based upon the digit +* type setting and the current display text language. +*/ +EXPORT_C void AknTextUtils::DisplayTextLanguageSpecificNumberConversion(TDes &aDes) + { + TDigitType d = DisplayTextLanguageFilteredDigitType(); + TChar toArea = d; + const TChar maxDigitTypeChar(0x1000); + + TInt length = aDes.Length(); + for(TInt i=0;i ch) + { + ch += toArea; + ch -= fromArea; + aDes[i] = TUint16(ch); + } + break; + + default: +// #ifdef RD_HINDI + if(ch >= 0x0966 && ch <= 0x096F) //Code range for Devanagari Number range. + { + ch += toArea; + ch -= fromArea; + aDes[i] = TUint16(ch); + } +// #endif//RD_HINDI + + break; + }; + } + + } + +// arabic-indic digits are only available in arabic language. (not on hebrew) +static TBool IsArabicLanguage(TLanguage lang) + { + lang = (TLanguage)((TInt)lang & KAknLanguageMask); + return ((lang == ELangArabic) || (lang == ELangUrdu) || (lang == ELangFarsi)); + } +static TBool IsDigitTypeArabic(TDigitType dt) { return ((dt == EDigitTypeArabicIndic) || (dt == EDigitTypeEasternArabicIndic)); } +//#ifdef RD_HINDI +static TBool IsIndicLanguage(TLanguage lang) + { + lang = (TLanguage)((TInt)lang & KAknLanguageMask); + TBool ret = EFalse; + if ((lang == ELangHindi) +#ifdef RD_MARATHI + || ( lang == ELangMarathi ) +#endif // RD_MARATHI + #ifdef RD_HINDI_PHONETIC_INPUT + || (lang == KLangHindiPhonetic) + #endif + ) + ret = ETrue; + return ret; + } +static TBool IsDigitTypeIndic(TDigitType dt) { return dt == EDigitTypeDevanagari; } +//#endif//RD_HINDI + + +EXPORT_C TBool AknTextUtils::DigitModeQuery(TDigitModeQueryType t) + { + CAknSettingCache* settingsCache = NULL; + // some apps call this from their own threads, so need to check CEikonEnv::Static(). + if (CEikonEnv::Static()) settingsCache = &CAknEnv::Static()->SettingCache(); + TLocale locale; + locale.Refresh(); + + // Collect input for the algorithm to local variables + TLanguage displayLanguage = User::Language(); // UI Language + TLanguage inputLanguage = settingsCache ? settingsCache->InputLanguage() : displayLanguage; + TDigitType digitType = locale.DigitType(); + + //Hindi + TBool inputBool; + TBool uiBool; + TBool digitBool; + inputBool = +// #ifdef RD_HINDI + IsIndicLanguage(inputLanguage)| +// #endif //RD_HINDI + IsArabicLanguage(inputLanguage); + uiBool = +// #ifdef RD_HINDI + IsIndicLanguage(displayLanguage)| +// #endif //RD_HINDI + IsArabicLanguage(displayLanguage); + digitBool = +// #ifdef RD_HINDI + IsDigitTypeIndic(digitType)| +// #endif //RD_HINDI + IsDigitTypeArabic(digitType); + + // Actual work of the method starts here + TBool editor=EFalse, numberEditor=EFalse, changeable=EFalse, display = EFalse; + + if (!inputBool && !uiBool) { editor = EFalse; display = EFalse; } + if (!inputBool && uiBool && digitBool) { editor = EFalse; numberEditor = ETrue; display = ETrue; } + if (!inputBool && uiBool && !digitBool){ editor = EFalse; display = EFalse; } + if (inputBool && uiBool && digitBool) { editor = ETrue; numberEditor = ETrue; changeable=ETrue; display = ETrue; } + if (inputBool && uiBool && !digitBool) { editor = EFalse; changeable=ETrue; display = EFalse; } + if (inputBool && !uiBool) { editor = EFalse; changeable=ETrue; display = EFalse; } + + // Choose correct output depending on what the caller wants. + TBool result = EFalse; + switch(t) + { + case EDigitModeEditorDefault: + result = editor; + break; + + case EDigitModeUserModifiableEditor: + result = changeable; + break; + + case EDigitModeShownToUser: + result = display; + break; + + case EDigitModeNumberEditor: + result = numberEditor; + break; + + case EDigitModeLatinNumberEditor: + result = EFalse; // conversion is never needed + break; + }; + return result; + } + +// LRM = 200e +// RLM = 200f +// LRE = 202a // embedding +// RLE = 202b +// PDF = 202c +// LRO = 202d // override +// RLO = 202e +_LIT( KConvLRE, "\x202a" ); +_LIT( KConvRLE, "\x202b" ); +_LIT( KConvPDF, "\x202c" ); +_LIT( KConvLRM, "\x200e" ); +_LIT( KConvRLM, "\x200f" ); +EXPORT_C HBufC* AknTextUtils::ConvertFileNameL(const TDesC& aDes) + { + TPtrC fileName = aDes; + TPtrC extension = _L(""); + TInt pos = aDes.Locate(TChar('.')); + if (pos != KErrNotFound && pos > 0) + { + fileName.Set(aDes.Left(pos)); + extension.Set(aDes.Mid(pos)); + } + HBufC *buf = HBufC::NewL(fileName.Length()+extension.Length()+4); + TPtr bufptr = buf->Des(); + TBool found = EFalse; + TBool rtl = TBidiText::TextDirectionality(fileName, &found) == TBidiText::ERightToLeft; + if (!found) + { + rtl=EFalse; + + // The file name does not contain any strongly directional characters. + // File name is still rendered from the right to left if the + // file name contains arabic or arabic-indic digits with neutral characters. + TInt length = fileName.Length(); + TInt ii = 0; + while ((ii < length) && !rtl) + { + TChar c = fileName[ii++]; + // GetBdCategory() for arabic-indic digits return value EEuropeanNumber. + // For this reason this method cannot be used for arabic-indic digits. + // Arabic-indic digits start from unicode 0x06f0 and end to unicode 0x06f9 + if (c.GetBdCategory() == TChar::EArabicNumber || + ( c >= 0x06f0 && c <= 0x06f9 ) ) + { + rtl = ETrue; + } + } + } + + if (rtl) + { + bufptr.Append(KConvRLE); + } + else + { + bufptr.Append(KConvLRE); + } + + bufptr.Append(fileName); + bufptr.Append(KConvPDF); + if (rtl) + { + bufptr.Append(KConvRLM); + } + else + { + bufptr.Append(KConvLRM); + } + bufptr.Append(extension); + bufptr.Append(KConvPDF); // PDF + return buf; + } + + + +// AVKON TEXT WRAPPING + +_LIT( KWrapToStringSeparator, "\n" ); + +// ----------------------------------------------------------------------------- +// AknTextUtils::WrapToStringL() +// ----------------------------------------------------------------------------- + +void AknTextUtils::WrapToStringL( + const TDesC& aStringToWrap, + const CArrayFix& aLineWidthArray, + const CFont& aFont, + TDes& aWrappedString, + TInt aFlags, + TInt aDirectionality ) + { + if ( aWrappedString.MaxLength() < aStringToWrap.Length() ) + { + User::Leave( KErrOverflow ); + } + + aWrappedString.Copy( aStringToWrap ); + + CArrayFixFlat* wrappedArray = + new( ELeave ) CArrayFixFlat( 5 ); + + CleanupStack::PushL( wrappedArray ); + + WrapToArrayL( + aWrappedString, + &aLineWidthArray, + aFont, + *wrappedArray, + 0, + aFlags, + aDirectionality ); + + // Here we copy using the same descriptor as source and destination, + // so have to be careful not to overwrite "source" before it is copied. + + TInt count( wrappedArray->Count() ); + aWrappedString.Zero(); + + // first copy actual lines + + for ( TInt i = 0 ; i < count ; i++ ) + { + aWrappedString.Append( (*wrappedArray)[i] ); + } + + // then add newlines + + TInt index( 0 ); + + for ( TInt j = 0 ; j < count ; j++ ) + { + index += (*wrappedArray)[j].Length(); + + if ( index >= aWrappedString.MaxLength() ) + { + User::Leave( KErrOverflow ); + } + + aWrappedString.Insert( index, KWrapToStringSeparator ); + index++; + } + + CleanupStack::PopAndDestroy(); // wrappedArray + } + +// ----------------------------------------------------------------------------- +// AknTextUtils::WrapToArrayL() +// ----------------------------------------------------------------------------- + +void AknTextUtils::WrapToArrayL( + TDes& aStringToWrap, + const CArrayFix* aLineWidthArray, + const CFont& aFont, + CArrayFix& aWrappedArray, + TInt aLineWidth, + TInt aFlags, + TInt aDirectionality ) + { + TAknTextWrapper wrapper( + aStringToWrap, + aLineWidthArray, + aFont, + aWrappedArray, + aLineWidth, + aFlags, + (AknBidiTextUtils::TParagraphDirectionality)aDirectionality ); + + wrapper.WrapToArrayL(); + } + +// ----------------------------------------------------------------------------- +// AknTextUtils::ChopToArrayAndClipL() +// ----------------------------------------------------------------------------- + +void AknTextUtils::ChopToArrayAndClipL( + TDes& aStringToChop, + const CArrayFix* aLineWidthArray, + const CFont& aFont, + CArrayFix& aChoppedArray, + TInt aLineWidth ) + { + TAknTextWrapper wrapper( + aStringToChop, + aLineWidthArray, + aFont, + aChoppedArray, + aLineWidth, + TAknTextWrapper::EClip, + AknBidiTextUtils::EImplicit ); + + wrapper.ChopToArrayAndClipL(); + } + +EXPORT_C HBufC* AknTextUtils::LoadScalableTextL(CCoeEnv& aCoe, TInt aResourceId) + { +#ifdef _AKNUTILS_ENABLE_TRACES + LOGTEXT( _L("WARNING: Deprecated method used: AknTextUtils::LoadScalableTextL") ); +#endif // AKNUTILS_ENABLE_TRACES + HBufC* ret = LoadScalableTextLC(aCoe,aResourceId); + CleanupStack::Pop(); + return ret; + } + +EXPORT_C HBufC* AknTextUtils::LoadScalableTextLC(CCoeEnv& aCoe, TInt aResourceId) + { +#ifdef AKNUTILS_ENABLE_TRACES + LOGTEXT( _L("WARNING: Deprecated method used: AknTextUtils::LoadScalableTextLC") ); +#endif // AKNUTILS_ENABLE_TRACES + HBufC* ret = aCoe.AllocReadResourceL(aResourceId); + ret = ClipAccordingScreenOrientationLC(aCoe, ret); + return ret; + } + +EXPORT_C TInt AknTextUtils::LoadScalableText(CCoeEnv& aCoe, TInt aResourceId, TDes& aBuffer ) + { +#ifdef AKNUTILS_ENABLE_TRACES + LOGTEXT( _L("WARNING: Deprecated method used: AknTextUtils::LoadScalableText") ); +#endif // AKNUTILS_ENABLE_TRACES + + HBufC* temp = 0; + TRAPD( result, temp = LoadScalableTextL(aCoe,aResourceId) ); + if (result == KErrNone) + { + aBuffer.Zero(); + aBuffer.Append(temp->Length() > aBuffer.Length()?temp->Des().Left(aBuffer.Length()-1):temp->Des()); + } + delete temp; + return result; + } + +EXPORT_C HBufC* AknTextUtils::ClipAccordingScreenOrientationLC(CCoeEnv& aCoe, HBufC* aBuf) + { +#ifdef AKNUTILS_ENABLE_TRACES + LOGTEXT( _L("WARNING: Deprecated method used: AknTextUtils::ClipAccordingScreenOrientationLC") ); +#endif // AKNUTILS_ENABLE_TRACES + + CleanupStack::PushL(aBuf); + TInt separatorPos = aBuf->Des().Locate('|'); + if (separatorPos != KErrNotFound ) + { + // solve screen orientation + CAknAppUiBase::TAppUiOrientation screenOrientation= ((CAknAppUiBase*)aCoe.AppUi())->Orientation(); + if ( screenOrientation == CAknAppUiBase::EAppUiOrientationLandscape + && separatorPos != aBuf->Length() ) + { + aBuf=aBuf->Des().Right(separatorPos+1).AllocL(); + } + else + { + aBuf=aBuf->Des().Left(separatorPos).AllocL(); + } + CleanupStack::PopAndDestroy(); // old buf + CleanupStack::PushL(aBuf); // resized buffer + } + return aBuf; + } + +// ----------------------------------------------------------------------------- +// AknTextUtils::ChooseScalableText +// ----------------------------------------------------------------------------- +// +EXPORT_C TPtrC AknTextUtils::ChooseScalableText( + const TDesC& aText, + const CFont& aFont, + TInt aMaxWidthInPixels ) + { + // Get loc variants in an array. + TAknLocVariant variants[KAknMaxLocVariants]; + TInt numVariants = TAknTextWrapper::GetLocVariants( aText, variants ); + + TInt chosen = KErrNotFound; + TInt chosenWidth = KMinTInt; + + TInt shortest = KErrNotFound; + TInt shortestWidth = KMaxTInt; + + TInt start; + + for ( TInt i = 0 ; i < numVariants ; i++ ) + { + start = variants[i].iStart; + + TInt width = aFont.TextWidthInPixels( + aText.Mid( start, variants[i].iEnd - start ) ); + + // Update info of longest fitting one. + if ( width <= aMaxWidthInPixels && width > chosenWidth ) + { + chosen = i; + chosenWidth = width; + } + + // Update info of shortest one. + if ( width < shortestWidth ) + { + shortest = i; + shortestWidth = width; + } + } + + // If none of the variants fits, return the shortest one in pixels. + if ( chosen < 0 ) + { + chosen = shortest; + } + + start = variants[chosen].iStart; + return aText.Mid( start, variants[chosen].iEnd - start ); + } + +/** +* CompletePathWithAppPath +* All the components that are specified in the given descriptor (drive letter, +* path and file name, including extension) are put into the result; +* any missing components (path and drive letter) are taken from the app's path. +* +* Can be used e.g. to load a bitmap file when an application don't know where +* it has been installed. +* +* Example1: +* TFilename fname = _L("\testdir\pics.mbm"); // Use _LIT instead +* CompletePathWithAppPath( fname ); +* Result: +* fname == "c:\testdir\pics.mbm" if application was installed to c: +* +* Example2: +* TFilename fname = _L("pics.mbm"); // Use _LIT instead +* CompletePathWithAppPath( fname ); +* Result: +* fname == "c:\system\apps\myapp\pics.mbm" if application was +* installed to c:\system\apps\myapp +* +*/ +EXPORT_C TInt CompleteWithAppPath( TDes& aFileName ) + { + TParse parse; + TInt error = KErrNotSupported; + + CEikonEnv* env = CEikonEnv::Static(); + if ( env && + env->EikAppUi() && + env->EikAppUi()->Document() && + env->EikAppUi()->Application() ) + { + TFileName appName = env->EikAppUi()->Application()->AppFullName(); + // Remove app name and extension + TParsePtr appNamePtr(appName); + appName = appNamePtr.DriveAndPath(); + error = parse.Set( aFileName, &appName, NULL); + if ( !error ) + { + aFileName.Zero(); + aFileName.Append( parse.FullName() ); + } + } + + return error; + } + +EXPORT_C void AknEditUtils::ConstructEditingL(CEikEdwin* aEdwin, + TInt aEditingSpace, + TInt aEditingWindow, + TInt aCharacterCase, + TInt aJustification, + TBool aAllowedToMoveInsertionPoint, + TBool aCursorYesNo, + TBool aOverflowYesNo, + TBool aIsResizable) + { + TMargins8 editorMargins; + editorMargins.iBottom = 0; + editorMargins.iTop = 0; + editorMargins.iRight = 0; + editorMargins.iLeft = 0; + + aEdwin->SetBorderViewMargins(editorMargins); + TInt flags = 0; + if (!aCursorYesNo) flags = CEikEdwin::EAvkonDisableCursor; + if (aIsResizable && aEditingWindow != 1) flags |= CEikEdwin::EResizable; // max one row editor should not be resizable + + aEdwin->ConstructL(CEikEdwin::EWidthInPixels|CEikEdwin::ENoAutoSelection|flags, 0, aEditingSpace, aEditingWindow); + + TCharFormat charFormat; + TCharFormatMask formatMask; + CParaFormat paraFormat; + TParaFormatMask paraFormatMask; + + TCursorSelection selection = aEdwin->Selection(); + STATIC_CAST(CGlobalText*, aEdwin->Text())->ApplyParaFormatL(¶Format,paraFormatMask,selection.LowerPos(),selection.Length()); + STATIC_CAST(CGlobalText*, aEdwin->Text())->ApplyCharFormatL(charFormat,formatMask,selection.LowerPos(),selection.Length()); + + // Setting editor alignment must be done after + // other editor paragraph formatting + aEdwin->SetAlignment(aJustification); + + aEdwin->SetAknEditorCase( aCharacterCase ); // Argument is no longer and enum + + if ( !aAllowedToMoveInsertionPoint ) + { + // No implementation here + } + + if ( aOverflowYesNo ) + { + // No implementation here + } + } + +static void IsAvailableLanguageL( const TInt aLanguage, TBool& aSupported ) + { + aSupported = EFalse; + + CPtiEngine* ptiEngine = CPtiEngine::NewL(); + CleanupStack::PushL( ptiEngine ); + RArray language(6); + CleanupClosePushL( language ); + ptiEngine->GetAvailableLanguagesL( language ); + for ( int i = 0; i < language.Count(); i++ ) + { + if ( language[i] == aLanguage ) + { + aSupported = ETrue; + break; + } + } + CleanupStack::PopAndDestroy( &language ); + CleanupStack::PopAndDestroy( ptiEngine ); + } + +EXPORT_C TInt DefaultInputLanguageFromUILanguage(const TInt aUiLanguage) + { + // Remove operator variant bits + TInt inputLanguage = aUiLanguage & KAknLanguageMask; + TBool supportedLang = EFalse; + + TRAP_IGNORE( IsAvailableLanguageL( inputLanguage, supportedLang ) ); + if ( supportedLang ) + { + return inputLanguage; + } + + // unknown, use default hard-coded convert code + switch (inputLanguage) + { + case ELangAmerican: + case KLangTaiwanEnglish: + case KLangHongKongEnglish: + case KLangPrcEnglish: + case KLangThaiEnglish: + case KLangApacEnglish: + case KLangIndicEnglish: + inputLanguage = ELangEnglish; + break; + case KLangJapaneseEnglish: + inputLanguage = ELangJapanese; + break; + case ELangBrazilianPortuguese: + inputLanguage = ELangPortuguese; + break; + case ELangCanadianFrench: + inputLanguage = ELangFrench; + break; + case ELangBelgianFlemish: + inputLanguage = ELangDutch; + break; + case ELangLatinAmericanSpanish: + inputLanguage = ELangSpanish; + break; + case KLangApacMalay: + inputLanguage = ELangMalay; + break; + case KLangApacIndonesian: + inputLanguage = ELangIndonesian; + break; + default: + break; + } + return inputLanguage; + } + +// ----------------------------------------------------------------------------- +// SetKeyblockMode +// ----------------------------------------------------------------------------- +// +EXPORT_C void SetKeyblockMode( TAknKeyBlockMode aMode ) + { + RAknUiServer client; + if ( client.Connect() == KErrNone ) + { + client.SetKeyblockMode( (TAknKeySoundOpcode) aMode ); + client.Close(); + } + } + +// ----------------------------------------------------------------------------- +// AknDateTimeUtils::ConvertUtcTimeToHomeTime +// ----------------------------------------------------------------------------- +// +EXPORT_C void AknDateTimeUtils::ConvertUtcTimeToHomeTime( TTime& aTime ) + { + TTimeIntervalSeconds universalTimeOffset( User::UTCOffset() ); + aTime += universalTimeOffset; + } + +// ----------------------------------------------------------------------------- +// AknLangUtils::DisplayLanguageTagL +// ----------------------------------------------------------------------------- +// +EXPORT_C HBufC* AknLangUtils::DisplayLanguageTagL() + { + HBufC* tag = StringLoader::LoadL( R_QTN_LANGUAGE_RFC3066_TAG, CEikonEnv::Static() ); + return tag; + } + +// ----------------------------------------------------------------------------- +// AknLangUtils::UserLanguage +// ----------------------------------------------------------------------------- +// +TLanguage AknLangUtils::UserLanguage() + { + return (TLanguage)(User::Language() & KAknLanguageMask); + } + +// ----------------------------------------------------------------------------- +// AknPopupUtils::Position +// ----------------------------------------------------------------------------- +// +EXPORT_C TPoint AknPopupUtils::Position( const TSize& aSize, + TBool aSoftkeysVisible ) + { + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( TRect(), AknLayoutScalable_Avkon::Screen( 0 ) ); + + TRect screen( layoutRect.Rect() ); + + TInt x = ( screen.Width() - aSize.iWidth ) >> 1; + TInt y = screen.Height() - aSize.iHeight; + + // Popups are centered on y-axis if screen orientation is landscape or + // softkeys are not visible. + if ( !aSoftkeysVisible || Layout_Meta_Data::IsLandscapeOrientation() ) + { + y >>= 1; + } + + return TPoint( x, y ); + } + + +// ----------------------------------------------------------------------------- +// AknPopupUtils::Position +// ----------------------------------------------------------------------------- +// +EXPORT_C TPoint AknPopupUtils::Position( const TSize& aSize, + CCoeControl* aControl ) + { + TBool softkeys = EFalse; + + if ( aControl ) + { + CEikCba* cba = aControl->MopGetObjectNoChaining( cba ); + + if ( cba ) + { + softkeys = ( cba->IsVisible() && !cba->IsEmpty() ); + } + } + + return Position( aSize, softkeys ); + } + +// End of file +