diff -r d189ee25cf9d -r 3533d4323edc emailuis/emailui/src/ncspopuplistbox.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emailuis/emailui/src/ncspopuplistbox.cpp Wed Sep 01 12:28:57 2010 +0100 @@ -0,0 +1,934 @@ +/* +* Copyright (c) 2007 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: This file implements classes CNcsPopupListBox, CNcsListItemDrawer. +* +*/ + + +// INCLUDE FILES +#include "emailtrace.h" +#include +#include +#include // R_FSE_EDITOR_ADDRESS_LIST_REMOTE_LOOKUP_SEARCH +#include // StringLoader +#include +#include +#include +#include +#include + +#include "ncspopuplistbox.h" +#include "ncsemailaddressobject.h" // CNcsEmailAddressObject +#include "ncsconstants.h" +#include "ncsheadercontainer.h" // CNcsHeaderContainer +#include "FreestyleEmailUiContactHandler.h" // CFSEmailUiClsListsHandler +#include "ncsutility.h" +#include "FreestyleEmailUiUtilities.h" +#include "FreestyleEmailUiAppui.h" +#include "FreestyleEmailUiLayoutHandler.h" +#include "FSDelayedLoader.h" +#include "FreestyleEmailUiCLSItem.h" + +const TInt KHighlightFrameWidth = 2; + +// ========================= MEMBER FUNCTIONS ================================== + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::NewL +// ----------------------------------------------------------------------------- +CNcsPopupListBox* CNcsPopupListBox::NewL( const CCoeControl* aParent, + CFSMailBox& aMailBox, + CNcsHeaderContainer& aHeaderContainer, + TBool aRemoteLookupSupported ) + { + FUNC_LOG; + CNcsPopupListBox* self = new (ELeave) CNcsPopupListBox( aHeaderContainer, + aRemoteLookupSupported, aMailBox ); + CleanupStack::PushL( self ); + self->ConstructL( aParent ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::CNcsPopupListBox +// ----------------------------------------------------------------------------- +CNcsPopupListBox::CNcsPopupListBox( CNcsHeaderContainer& aHeaderContainer, + TBool aRemoteLookupSupported, + CFSMailBox& aMailBox) + : iHeaderContainer( aHeaderContainer ), + iMailBox( aMailBox ), + iRemoteLookupSupported( aRemoteLookupSupported ), + iCachingInProgress( EFalse ), + iAppUi( static_cast( iEikonEnv->AppUi() ) ) + { + FUNC_LOG; + iPopupMaxRect = TRect( 100, 100, 100, 100 ); + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::ConstructL +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::ConstructL( const CCoeControl* aParent ) + { + FUNC_LOG; + CEikTextListBox::ConstructL( NULL, CEikListBox::EPopout ); + SetMopParent( const_cast( aParent ) ); + User::LeaveIfError( SetParent( const_cast( aParent ) ) ); + + CEikScrollBarFrame* frame = CreateScrollBarFrameL( EFalse, EFalse, ETrue ); + + CEikTextListBox::SetBorder( TGulBorder::ENone ); + + const CFont* font = AknLayoutUtils::FontFromId( EAknLogicalFontPrimarySmallFont ); + CEikTextListBox::SetItemHeightL( font->FontMaxHeight() + 12 ); + + iBackgroundContext = CAknsFrameBackgroundControlContext::NewL( + KAknsIIDQsnFrPopupSub, Rect(), Rect(), EFalse ); + UpdateTextColors(); + + iContactHandler = CFsDelayedLoader::InstanceL()->GetContactHandlerL(); + if ( !iContactHandler->IsLanguageSupportedL() ) + { + iContactHandler = NULL; + } + + SetListBoxObserver( this ); + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::InitAndSearchL +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::InitAndSearchL( const TDesC& aText, TInt aMode ) + { + FUNC_LOG; + SetSearchTextL( aText, aMode ); + RPointerArray emptyArray; + CleanupClosePushL( emptyArray ); + OperationCompleteL( ESearchContacts, emptyArray ); + CleanupStack::PopAndDestroy( &emptyArray ); + } + +// --------------------------------------------------------------------------- +// CNcsPopupListBox::~CNcsPopupListBox +// --------------------------------------------------------------------------- +CNcsPopupListBox::~CNcsPopupListBox() + { + FUNC_LOG; + delete iBackgroundContext; + delete iItemTextsArray; + delete iCurrentSearchText; + iMatchingItems.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::CreateItemDrawerL +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::CreateItemDrawerL() + { + FUNC_LOG; + iItemDrawer = new (ELeave) CNcsListItemDrawer( *this ); + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::MopSupplyObject +// ----------------------------------------------------------------------------- +TTypeUid::Ptr CNcsPopupListBox::MopSupplyObject(TTypeUid aId) + { + FUNC_LOG; + if ( aId.iUid == MAknsControlContext::ETypeId ) + { + return MAknsControlContext::SupplyMopObject( aId, iBackgroundContext ); + } + return CCoeControl::MopSupplyObject( aId ); + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::SizeChanged +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::SizeChanged() + { + FUNC_LOG; + const TRect outerRect = Rect(); + + TAknLayoutRect subpane; + subpane.LayoutRect( outerRect, + AknLayoutScalable_Avkon::bg_popup_sub_pane_g1() ); + const TRect innerRect = subpane.Rect(); + + iBackgroundContext->SetFrameRects( outerRect, innerRect ); + + SetViewRectFromClientRect( innerRect ); + TRAP_IGNORE( HandleViewRectSizeChangeL() ); + } + +void CNcsPopupListBox::HandleResourceChange( TInt aType ) + { + FUNC_LOG; + if ( aType == KAknsMessageSkinChange ) + { + UpdateTextColors(); + } + } + +void CNcsPopupListBox::HandlePointerEventL( const TPointerEvent& aPointerEvent ) + { + CEikTextListBox::HandlePointerEventL( aPointerEvent ); + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::OfferKeyEventL +// ----------------------------------------------------------------------------- +// +TKeyResponse CNcsPopupListBox::OfferKeyEventL( const TKeyEvent& aKeyEvent, + TEventCode aType ) + { + FUNC_LOG; + TKeyResponse ret( EKeyWasNotConsumed ); + if( aKeyEvent.iCode == EKeyDownArrow ) + { + MoveRemoteLookupItemL( ERemoteLookupItemDown ); + iView->MoveCursorL( CListBoxView::ECursorNextItem, CListBoxView::ENoSelection ); + ret = EKeyWasConsumed; + } + else if( aKeyEvent.iCode == EKeyUpArrow ) + { + TBool stay = EFalse; + // Move cursor separator line over + if ( CurrentItemIndex() - 1 > 0 && CurrentItemIndex() - 1 == iRemoteLookupItemPos ) + { + MoveRemoteLookupItemL( ERemoteLookupItemUp ); + iView->MoveCursorL( CListBoxView::ECursorPreviousItem, CListBoxView::ENoSelection ); + stay = ETrue; + } + + MoveRemoteLookupItemL( ERemoteLookupItemUp ); + iView->MoveCursorL( CListBoxView::ECursorPreviousItem, CListBoxView::ENoSelection ); + if( stay ) + { + MoveRemoteLookupItemL( ERemoteLookupItemDown ); + + iView->MoveCursorL( CListBoxView::ECursorNextItem, CListBoxView::ENoSelection ); + } + + + ret = EKeyWasConsumed; + } + + if( ret == EKeyWasNotConsumed ) + { + ret = CEikListBox::OfferKeyEventL( aKeyEvent, aType ); + } + // call HandleItemAdditionL just in case. There might be changes on remote lookup item place. + // The call is here, because we don't want to have extra redraw events when the popuplist + // is not fully updated. + HandleItemAdditionL(); + return ret; + } + +// --------------------------------------------------------------------------- +// CNcsPopupListBox::HandleListBoxEventL +// --------------------------------------------------------------------------- +// +void CNcsPopupListBox::HandleListBoxEventL( CEikListBox* /*aListBox*/, + TListBoxEvent aEventType ) + { + if ( aEventType == EEventItemClicked || + aEventType == EEventItemSingleClicked ) + { + iHeaderContainer.DoPopupSelectL(); + } + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::OperationComplete +// ----------------------------------------------------------------------------- +// +void CNcsPopupListBox::OperationCompleteL( TContactHandlerCmd /*aCmd*/, + const RPointerArray& aMatchingItems ) + { + FUNC_LOG; + iMatchingItems.ResetAndDestroy(); + // Replace old matcing items. + + for ( TInt ii = 0; ii < aMatchingItems.Count(); ++ii ) + { + if ( aMatchingItems[ii] ) + { + CFSEmailUiClsItem* item = aMatchingItems[ii]->CloneLC(); + iMatchingItems.AppendL( item ); + CleanupStack::Pop( item ); + } + } + + UpdateListL(); + } + +void CNcsPopupListBox::OperationErrorL( TContactHandlerCmd aCmd, TInt aError ) + { + FUNC_LOG; + + if ( aCmd == ESearchContacts ) + { + // KerrNotReady --> caching in progress, KErrNotFound --> caching not started yet + if ( (aError == KErrNotReady) || (aError == KErrNotFound) ) + { + if(!iAppUi->AppUiExitOngoing()) // + TFsEmailUiUtility::ShowInfoNoteL( R_FSE_EDITOR_INFO_BUILDING_CACHE ); + iCachingInProgress = ETrue; + } + if ( aError == KErrNone && iCachingInProgress ) + { + if(!iAppUi->AppUiExitOngoing()) // + TFsEmailUiUtility::ShowInfoNoteL( R_FSE_EDITOR_INFO_CACHING_COMPLETED ); + iCachingInProgress = EFalse; + } + } + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::SetSearchTextL +// ----------------------------------------------------------------------------- +// +void CNcsPopupListBox::SetSearchTextL( const TDesC& aText, TInt aMode ) + { + FUNC_LOG; + delete iCurrentSearchText; + iCurrentSearchText = NULL; + iCurrentSearchText = aText.AllocL(); + if ( !iCachingInProgress ) + { + if ( iContactHandler ) + { + iContactHandler->SearchMatchesL( aText, this, &iMailBox, aMode ); + } + } + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::ReturnCurrentEmailAddressLC +// ----------------------------------------------------------------------------- +// +CNcsEmailAddressObject* CNcsPopupListBox::ReturnCurrentEmailAddressLC() + { + FUNC_LOG; + CNcsEmailAddressObject* addressObject = NULL; + + if ( iMatchingItems.Count() ) + { + CFSEmailUiClsItem* clsItem = NULL; + if ( iRemoteLookupSupported ) + { + // calculate index of item + TInt index = (CurrentItemIndex() > iRemoteLookupItemPos ? CurrentItemIndex() - 1 : CurrentItemIndex()); + clsItem = iMatchingItems[index]; + } + else + { + clsItem = iMatchingItems[CurrentItemIndex()]; // no iRemoteLookupItemPos + } + + addressObject= CNcsEmailAddressObject::NewL( clsItem->DisplayName(), clsItem->EmailAddress() ); + CleanupStack::PushL( addressObject ); + if ( clsItem->MultipleEmails() ) + { + addressObject->SetDisplayFull( ETrue ); + } + } + + return addressObject; + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::SetPopupMaxRect +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::SetPopupMaxRect( const TRect& aPopupMaxRect ) + { + FUNC_LOG; + iPopupMaxRect = aPopupMaxRect; + + SetPopupRect(); + TRAP_IGNORE( UpdateScrollBarsL() ); + TRAP_IGNORE( SetScrollBarVisibilityL() ); + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::IsPopupEmpty +// ----------------------------------------------------------------------------- +TBool CNcsPopupListBox::IsPopupEmpty() const + { + FUNC_LOG; + if ( Model()->NumberOfItems() > 0 ) + return EFalse; + else + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::IsRemoteLookupItemSelected +// ----------------------------------------------------------------------------- +TBool CNcsPopupListBox::IsRemoteLookupItemSelected() const + { + FUNC_LOG; + if ( CurrentItemIndex() == iRemoteLookupItemPos && iRemoteLookupSupported ) + return ETrue; + else + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::CurrentPopupClsItemsArray +// ----------------------------------------------------------------------------- +const RPointerArray& CNcsPopupListBox::CurrentPopupClsItemsArray() const + { + return iMatchingItems; + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::RemoteLookupItemPos +// ----------------------------------------------------------------------------- +TInt CNcsPopupListBox::RemoteLookupItemPos() const + { + FUNC_LOG; + return iRemoteLookupItemPos; + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::LayoutHandler +// ----------------------------------------------------------------------------- +CFSEmailUiLayoutHandler& CNcsPopupListBox::LayoutHandler() const + { + FUNC_LOG; + return *iAppUi->LayoutHandler(); + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::SetListItemsFromArrayL +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::SetListItemsFromArrayL() + { + FUNC_LOG; + // reset the cursor to point to the first item + //iView->MoveCursorL( CListBoxView::ECursorFirstItem, CListBoxView::ENoSelection); + Reset(); + + // Create totally new text array + CreateTextArrayAndSetToTheListboxL( ETrue ); + + // append texts to text array + for( TInt i=0; i < iMatchingItems.Count(); i++ ) + { + iItemTextsArray->AppendL( iMatchingItems[i]->FullTextL() ); + } + + // Update rmlu item + SetRemoteLookupItemFirstToTheListL(); + + SetPopupRect(); + SetScrollBarVisibilityL(); + HandleItemAdditionL(); + + if ( iItemTextsArray && iItemTextsArray->Count() > 0 ) + { + SetCurrentItemIndex( 0 ); + } + + if ( IsVisible() ) + { + DrawDeferred(); + } + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::RoundToItemHeight +// ----------------------------------------------------------------------------- +TInt CNcsPopupListBox::RoundToItemHeight(const TInt aPopupHeight) const + { + TReal fullItems; // number of full visible items in window + TInt err = Math::Round(fullItems, (aPopupHeight / ItemHeight()), 0); + if (err == KErrNone) + { + return (TInt)(fullItems * ItemHeight()); + } + return aPopupHeight; // in case of error + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::SetPopupRect +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::SetPopupRect() + { + FUNC_LOG; + // The popup width and horizontal position is adjusted so that it + // will be within the area specified in both layout data and the set + // maximum rect. + TAknLayoutRect editorPane; + editorPane.LayoutRect( iAppUi->ClientRect(), + TAknWindowComponentLayout::Compose( + TAknWindowComponentLayout::Compose( + AknLayoutScalable_Apps::list_cmail_pane(), + AknLayoutScalable_Apps::list_single_cmail_header_detail_pane( 0 ) ), + AknLayoutScalable_Apps::list_single_cmail_header_editor_pane_bg( 4 ) ) ); + TRect editorPaneRect = editorPane.Rect(); + + TRect newRect = iPopupMaxRect; + newRect.iTl.iX = Max( iPopupMaxRect.iTl.iX, editorPaneRect.iTl.iX ); + newRect.iBr.iX = Min( iPopupMaxRect.iBr.iX, editorPaneRect.iBr.iX ); + + // Thhe popup height and vertical position is adjusted based on the + // available space below and above the cursor and the number of items + // in the list. + const TRect rect = iPopupMaxRect; + TAknLayoutRect subpane; + subpane.LayoutRect( rect, AknLayoutScalable_Avkon::bg_popup_sub_pane_g1() ); + const TRect subpaneRect = subpane.Rect(); + + const TInt frameHeights = iPopupMaxRect.Height() - subpaneRect.Height(); + + // This is the total height in pixels needed to show all items + TInt minimumHeight = frameHeights + + CalcHeightBasedOnNumOfItems( Model()->NumberOfItems() ); + + CCoeControl* container = Parent()->Parent(); + TInt containerTop = container->PositionRelativeToScreen().iY; + TInt containerHeight = container->Rect().Height(); + TInt containerCenter = containerTop + containerHeight / 2; + + // Get height of one line in Address field + CNcsHeaderContainer* headerObj = static_cast(Parent()); + TInt toLineHeight = headerObj->GetToLineHeight(); // height of one line height + if ( toLineHeight == 0 ) + { + toLineHeight = ItemHeight(); + } + + TInt newHeight = minimumHeight; // default window height + + // latch listbox on the bottom of the editor field + if ( newRect.iTl.iY <= containerCenter ) + { + TInt maxHeight = containerHeight - ( newRect.iTl.iY - containerTop ); + newHeight = RoundToItemHeight( maxHeight - frameHeights ) + frameHeights; + if ( newHeight > minimumHeight ) + { + newHeight = minimumHeight; // shrink window (if needed) + } + } + // latch listbox on the top of the editor field + else + { + TInt yOffset = -minimumHeight - toLineHeight; // how much up + TInt newTlY = newRect.iTl.iY + yOffset; // new Top Left Y coordinate + if ( newTlY >= containerTop ) + { + newRect.Move( 0, yOffset ); + } + else + { + // shrink height to visible area and move + TInt maxHeight = newRect.iTl.iY - toLineHeight - containerTop; + newHeight = RoundToItemHeight( maxHeight - frameHeights ) + frameHeights; + newRect.Move( 0, -newHeight - toLineHeight ); + } + } + newRect.SetHeight( newHeight ); // set new height + SetRect( newRect ); + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::SetScrollBarVisibilityL +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::SetScrollBarVisibilityL() + { + FUNC_LOG; + // This is the total height in pixels needed to show all items + TInt minimumHeight = CalcHeightBasedOnNumOfItems( Model()->NumberOfItems() ); + + // Show scroll bar if there is more items we can show at once. + if( iPopupMaxRect.Height() > minimumHeight ) + { + ScrollBarFrame()->SetScrollBarVisibilityL( + CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOff ); + } + else + { + ScrollBarFrame()->SetScrollBarVisibilityL( + CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOn ); + } + } + + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::SetRemoteLookupItemFirstToTheListL +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::SetRemoteLookupItemFirstToTheListL() + { + FUNC_LOG; + if( iRemoteLookupSupported ) + { + HBufC* rmluText = StringLoader::LoadLC( + R_FSE_EDITOR_ADDRESS_LIST_REMOTE_LOOKUP_SEARCH, *iCurrentSearchText ); + + iItemTextsArray->InsertL( 0, *rmluText ); + CleanupStack::PopAndDestroy( rmluText ); + iRemoteLookupItemPos = 0; + } + else + { + iRemoteLookupItemPos = -1; + } + } + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::MoveRemoteLookupItemL +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::MoveRemoteLookupItemL( TRemoteLookupItemMoveDirection aDirection ) + { + FUNC_LOG; + if( iRemoteLookupSupported ) + { + TInt newRMLUItemIndex = -1; + TInt newCurrentItem = -1; + if( aDirection == ERemoteLookupItemUp && + iView->CurrentItemIndex() == iView->TopItemIndex() ) + { + newRMLUItemIndex = iRemoteLookupItemPos - 1; + newCurrentItem = CurrentItemIndex() - 1; + } + else if( aDirection == ERemoteLookupItemDown && + iView->CurrentItemIndex() == iView->BottomItemIndex() ) + { + newRMLUItemIndex = iRemoteLookupItemPos + 1; + newCurrentItem = CurrentItemIndex() + 1; + } + + + if( ItemExists ( newCurrentItem ) && newRMLUItemIndex != -1 ) + { + iItemTextsArray->Delete( iRemoteLookupItemPos ); + + HBufC* rmluText = StringLoader::LoadLC( R_FSE_EDITOR_ADDRESS_LIST_REMOTE_LOOKUP_SEARCH, *iCurrentSearchText ); + + iItemTextsArray->InsertL( newRMLUItemIndex, *rmluText ); + CleanupStack::PopAndDestroy( rmluText ); + iRemoteLookupItemPos = newRMLUItemIndex; + } + } + } + + +// ----------------------------------------------------------------------------- +// CNcsPopupListBox::CreateTextArrayAndSetToTheListboxL +// ----------------------------------------------------------------------------- +void CNcsPopupListBox::CreateTextArrayAndSetToTheListboxL( const TBool& aResetIfExists ) + { + FUNC_LOG; + if( !iItemTextsArray ) + { + iItemTextsArray = new ( ELeave ) CDesCArraySeg( 8 ); + // Set the popup list data + Model()->SetItemTextArray( iItemTextsArray ); + Model()->SetOwnershipType( ELbmDoesNotOwnItemArray ); + } + + if( aResetIfExists ) + { + delete iItemTextsArray; + iItemTextsArray = NULL; + CreateTextArrayAndSetToTheListboxL( EFalse ); + } + } + + +// ----------------------------------------------------------------------------- +// CNcsListItemDrawer::CNcsListItemDrawer +// ----------------------------------------------------------------------------- +CNcsListItemDrawer::CNcsListItemDrawer( const CNcsPopupListBox& aListBox ) +:CListItemDrawer(), iListBox( aListBox ) + { + FUNC_LOG; + // Store a GC for later use + iGc = &CCoeEnv::Static()->SystemGc(); + SetGc(iGc); + } + +// ----------------------------------------------------------------------------- +// CNcsListItemDrawer::DrawActualItem +// ----------------------------------------------------------------------------- +void CNcsListItemDrawer::DrawActualItem(TInt aItemIndex, + const TRect& aActualItemRect, TBool aItemIsCurrent, + TBool /*aViewIsEmphasized*/, TBool /*aViewIsDimmed*/, + TBool /*aItemIsSelected*/) const + { + FUNC_LOG; + iGc->DiscardFont(); + + // Get reference to curren popup cls item list. + const RPointerArray& clsItemArray = + iListBox.CurrentPopupClsItemsArray(); + TInt rmluPosition = iListBox.RemoteLookupItemPos(); + + // Sets all the attributes, like font, text color and background color. + const CFont* font = AknLayoutUtils::FontFromId( EAknLogicalFontPrimarySmallFont ); + iGc->UseFont( font ); + iGc->SetPenStyle( CGraphicsContext::ESolidPen ); + iGc->SetBrushStyle( CGraphicsContext::ENullBrush ); + + TRect itemRect = aActualItemRect; + { + // temporary const_cast to get the scrollbar width + CNcsPopupListBox& tmpListBox = const_cast( iListBox ); + const TInt scrollbarBreadth = tmpListBox.ScrollBarFrame()-> + ScrollBarBreadth( CEikScrollBar::EVertical ); + if ( scrollbarBreadth > 0 ) + { + if ( AknLayoutUtils::LayoutMirrored() ) + { + itemRect.iTl.iX = iListBox.Rect().iTl.iX + scrollbarBreadth; + } + else + { + itemRect.iBr.iX = iListBox.Rect().iBr.iX - scrollbarBreadth; + } + } + } + + TRect textRect = itemRect; + textRect.Shrink( KHighlightFrameWidth, KHighlightFrameWidth ); + + // Get skin instance. + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + + // Draw background using the control context from the list box. + MAknsControlContext* cc = AknsDrawUtils::ControlContext( &iListBox ); + if ( cc ) + { + AknsDrawUtils::Background( skin, cc, *iGc, aActualItemRect ); + } + else + { + iGc->Clear( aActualItemRect ); + } + + // Draw the highlight, when necessary. + if ( aItemIsCurrent ) + { + AknsDrawUtils::DrawFrame( skin, *iGc, itemRect, textRect, + KAknsIIDQsnFrList, KAknsIIDQsnFrListCenter ); + } + + // Get text color. + TRgb textColor = TextColor(); + if ( aItemIsCurrent ) + { + textColor = HighlightedTextColor(); + } + + iGc->SetPenColor( textColor ); + TInt topToBaseline = ( textRect.Height() - font->FontMaxHeight() ) / 2 + + font->FontMaxAscent(); + + TPtrC itemText = iListBox.Model()->ItemText( aItemIndex ); + + // Construct bidirectional text object + // Removed leave from non-leaving function. + TBidiText* bidiText = NULL; + TRAPD( err, bidiText = TBidiText::NewL( itemText, 1 ) ); + if ( err == KErrNone ) + { + bidiText->WrapText( textRect.Width(), *font, NULL ); + } + + TPoint leftBase = textRect.iTl + TPoint( 0, topToBaseline ); + + if ( err != KErrNone ) + { + bidiText = NULL; // to be on the safe side + } + + // check if we are drawing remote lookup item or contact match + else if ( rmluPosition == aItemIndex ) + { + iGc->SetUnderlineStyle( EUnderlineOff ); + bidiText->DrawText( *iGc, leftBase ); + } + else + { + // if list has rmlu item change item index right + if ( rmluPosition >= 0 && aItemIndex > rmluPosition ) + { + aItemIndex--; + } + + // Change text transparency if match doesn't have email address. + if ( clsItemArray[aItemIndex]->EmailAddress().Compare( KNullDesC ) == 0 ) + { + const TInt KTransparency = + iListBox.LayoutHandler().PcsPopupDimmedFontTransparency(); + textColor.SetAlpha( KTransparency ); + iGc->SetPenColor( textColor ); + } + + // For now, we support underlining the matching part only if the + // text is written completely with left-to-right script + + // We know the text contains RTL script if the display string is not just + // truncated version of the original string. + TPtrC dispText = bidiText->DisplayText(); + TInt compLength = dispText.Length() - 1; // -1 to omit the truncation character + TBool textContainsRtl = + ( itemText.Left(compLength) != dispText.Left(compLength) ); + + const RArray& underlines = clsItemArray[aItemIndex]->Highlights(); + + if ( underlines.Count() > 0 && !textContainsRtl ) + { + TInt i = 0; + TBool partsLeft = ETrue; + TInt currentTextStart = 0; + TInt currentTextLength = 0; + + while ( partsLeft ) + { + if ( currentTextStart < underlines[i].index ) + { + // draw letters to the start of the underlined part + currentTextLength = underlines[i].index - currentTextStart; + DrawPartOfItem( textRect, *font, currentTextStart, currentTextLength, itemText, + EFalse, topToBaseline ); + } + else if ( currentTextStart == underlines[i].index ) + { + // draw underlined letters + currentTextLength = underlines[i].length; + + DrawPartOfItem( textRect, *font, currentTextStart, currentTextLength, itemText, + ETrue, topToBaseline ); + i++; + } + else + { + // This is here, because PCS Engine might give you duplicate match entries, + // in this case we're not advancing text but we'll skip that match + currentTextLength = 0; + i++; + } + // update text start point + currentTextStart += currentTextLength; + + if ( i >= underlines.Count() ) + { + partsLeft = EFalse; + // draw rest of the letters, if there are any after the last underlined part + if ( currentTextStart < itemText.Length() ) + { + currentTextLength = itemText.Length() - currentTextStart; + DrawPartOfItem( textRect, *font, currentTextStart, currentTextLength, itemText, + EFalse, topToBaseline ); + } + } + + } + } + else + { + iGc->SetUnderlineStyle( EUnderlineOff ); + bidiText->DrawText( *iGc, leftBase ); + } + } + + delete bidiText; + bidiText = NULL; + } + +// ----------------------------------------------------------------------------- +// CNcsListItemDrawer::DrawPartOfItem +// ----------------------------------------------------------------------------- +void CNcsListItemDrawer::DrawPartOfItem( const TRect& aItemRect, const CFont& aFont, + TInt aStartPos, TInt aLength, const TDesC& aDes, + TBool aUnderlined, TInt aBaselineOffsetFromTop ) const + { + FUNC_LOG; + if( aUnderlined ) + { + iGc->SetUnderlineStyle( EUnderlineOn ); + } + else + { + iGc->SetUnderlineStyle( EUnderlineOff ); + } + TRect currentTextRect( aItemRect ); + TInt pixels = aFont.TextWidthInPixels( aDes.Left( aStartPos ) ); + currentTextRect.iTl.iX = currentTextRect.iTl.iX + pixels; + iGc->DrawText( aDes.Mid( aStartPos, aLength ), + currentTextRect, aBaselineOffsetFromTop ); + } + + +void CNcsPopupListBox::UpdateListL() + { + FUNC_LOG; + SetListItemsFromArrayL(); + + // Close the popup if it's empty and make sure it's visible if it's not empty. + if ( IsPopupEmpty() ) + { + iHeaderContainer.ClosePopupContactListL(); + } + else + { + MakeVisible( ETrue ); + UpdateScrollBarsL(); + iHeaderContainer.ShowPopupMenuBarL( ETrue ); + } + } + +void CNcsPopupListBox::UpdateTextColors() + { + if ( iItemDrawer ) + { + // Get skin instance. + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + + // Get color for popup text from current skin. + TRgb textColor = KRgbBlack; + AknsUtils::GetCachedColor( skin, textColor, KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG20 ); + iItemDrawer->SetTextColor( textColor ); + + // Get text color for highlighted list item from current skin. + AknsUtils::GetCachedColor( skin, textColor, KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG10 ); + iItemDrawer->SetHighlightedTextColor( textColor ); + } + } + +void CNcsPopupListBox::Draw( const TRect& /*aRect*/ ) const + { + CWindowGc& gc = SystemGc(); + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + if ( iBackgroundContext ) + { + AknsDrawUtils::DrawBackground( skin, iBackgroundContext, this, gc, + Rect().iTl, Rect(), KAknsDrawParamNoClearUnderImage ); + } + else + { + gc.Clear( Rect() ); + } + CEikListBox::Draw( Rect() ); + } + +// End of File +