diff -r 5b6f26637ad3 -r f4a778e096c2 phonebookui/Phonebook2/UIControls/src/cpbk2contactviewcustomlistboxdata.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/UIControls/src/cpbk2contactviewcustomlistboxdata.cpp Wed Sep 01 12:29:52 2010 +0100 @@ -0,0 +1,4248 @@ +/* +* Copyright (c) 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: PhoneBook2 custom control. Code has been modified to +* suit PhoneBook2 requirements. See CColumnListBoxData +* in EIKCLBD.CPP. +* Ensure that this piece of code is in sync with Avkon EIKCLBD.CPP(CColumnListBoxData) +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef RD_UI_TRANSITION_EFFECTS_LIST +#include +#include +#endif //RD_UI_TRANSITION_EFFECTS_LIST + +#include + +//Start of Code Added for PhoneBook2 +#include "cpbk2contactviewcustomlistboxdata.h" +#include "CPbk2ContactViewListBoxModel.h" +#include +#include +#include +#include "CPbk2ContactViewListBox.h" + +//from PCS engine +#include +#include +#include +#include "CPbk2PredictiveSearchFilter.h" +//End of Code Added for PhoneBook2 + +const TInt KColumnListBoxGranularity=4; +const TInt KNoActualColumnFont=-1; +const TInt KMaxColumn = 6; + +// colored tick marks support +const TInt KColorIconFlag = -1; +const TInt KColorIconIdx = 0; + +//Start of Code Added for PhoneBook2 +/// Unnamed namespace for local definitions +namespace { + +#ifdef _DEBUG +enum TPanicCode + { + EPanicPreCond_OutOfRangeListBoxData = 1, + EPanicColumnListInvalidBitmapIndexListBoxData, + EPanicNullPointerListBoxData, + EPanicColumnListLayoutErrorListBoxData + }; +#endif // _DEBUG + +#ifdef _DEBUG +void Panic(TPanicCode aReason) + { + _LIT(KPanicText, "CPbk2ContactViewCustomListBoxData"); + User::Panic(KPanicText, aReason); + } +#endif // _DEBUG +} + + +TInt CompareByStartIndex( const TPsMatchLocation& aFirst, const TPsMatchLocation& aSecond ) + { + return aFirst.index - aSecond.index; + } +//End of Code Added for PhoneBook2 + + +//Note: +//**** +//PBK2_AVKON_TOUCH_MARKINGMODE_CHANGES +//Define this Flag once Pbk2 decides to implement the MarkingMode changes that has been implemented for Avkon Lists + +/** +* About animation usage: +* All animation usage is implemented in this class. Animation is eye candy and +* low priority when it comes to resources -> on resource failures animation +* fails fast to release resources for more critical functionality. Also, no +* attempt to (re)construct failed animation is made. +* +* User inactivity is not being observed. Only one animation is used. Extension +* is CActive to make it possible to postpone animation deletion on animation +* failure. +*/ +NONSHARABLE_CLASS(CPbk2ContactViewCustomListBoxDataExtension) : + public CActive, + public MAknPictographAnimatorCallBack, + public MCoeForegroundObserver, + public MAknsEffectAnimObserver, + public MListBoxItemChangeObserver + { +public: + enum TFlag + { + // Set if current item background should be copied to animation as + // input layer. + EFlagUpdateBg = 0, + + // Set if animation has been resized at least once + EFlagHasLayers = 1, + + // Set if foreground has been gained. + EFlagHasForeground = 2 + }; + enum TSubCellType + { + EEikSLGraphic, + EEikSLText, + EEikSLNumeric + }; + +public: + CPbk2ContactViewCustomListBoxDataExtension(); + void ConstructL( CPbk2ContactViewCustomListBoxData* aListBoxData, + const TAknsItemID& aAnimationIID ); + ~CPbk2ContactViewCustomListBoxDataExtension(); + static TInt RedrawEvent(TAny* aControl); + TBool IsMarqueeOn(); + struct SRowAndColumn + { + TInt iIndex; // 24 bits for row and 8 bits for column + const CFont* iFont; + }; + SRowAndColumn& At(TInt aArrayIndex); + const SRowAndColumn& At(TInt aArrayIndex) const; + void AddRowAndColumnL(TInt aRow,TInt aColumn); + TInt FindRowAndColumnIndex(TInt& aArrayIndex,TInt aRow,TInt aColumn) const; + void FindRowAndColumnIndexOrAddL(TInt& aArrayIndex,TInt aRow,TInt aColumn); + + inline void NoAnimIfError( TInt aError ); + void TryCreateAnimation(); + TBool SyncAnim( const TSize& aSize ); + TBool SyncAndDrawAnim( CBitmapContext& aGc, const TRect& aRect ); + MAknsControlContext* SkinBackgroundContext() const; + void DeleteAnim(); + void FocusGained(); + void FocusLost(); + void SkinChangedL(); + void SkinChanged(); + void SetControl( CCoeControl* aControl ); + + // Implementation of MCoeForegroundObserver + void HandleGainingForeground(); + void HandleLosingForeground(); + + // Implementation of MAknsEffectAnimObserver + void AnimFrameReady( TInt aError, TInt ); + + // Implementation of MListBoxItemChangeObserver + void ListBoxItemsChanged(CEikListBox* aListBox); + + // Overloads CActive::DoCancel + void DoCancel(); + // Overloads CActive::RunL + void RunL(); + + void Play(); + void CreateColorBitmapsL(); + + TBool DrawPressedDownEffect( MAknsSkinInstance* aInstance, + CWindowGc& aGc, + const TRect& aOutRect, + const TRect& aInnerRect ) const; + + void LoadMarkingIconsL(); + +public: //for handling column alignment + struct TColumnExt + { + TInt iColumn; // Must be first entry + TBool iLayoutAlign;//is layout alignment or Set by client + }; + TInt AddColumnExtL(TInt aColumn); + void FindColumnExtIndexOrAddL(TInt& aArrayIndex,TInt aColumn); + void SetColumnLayoutAlignmentL(TInt aColumn); + + + TBool FindColumnExtIndex(TInt& aArrayIndex,TInt aColumn) const; + TBool ColumnLayoutAlignment(TInt aColumn) const; + +public: // new list layout system + struct SRowAndSubCell + { + TInt iIndex; // 24 bits for row and 8 bits for subcell + const CFont* iFont; + }; + struct SSLSubCell + { + TInt iSubCell; // Must be first entry + TAknTextLineLayout iTextLayout; + TAknWindowLineLayout iGraphicLayout; + TInt iSubCellType; + TInt iConditionValue; // used with conditional layouts for not always drawn subcells + }; + + SSLSubCell& AtSL(TInt aArrayIndex); + const SSLSubCell& AtSL(TInt aArrayIndex) const; + void AddSLSubCellL(TInt aSubCell); + TInt FindSLSubCellIndex(TInt& aArrayIndex, TInt aSubCell) const; + void FindSLSubCellIndexOrAddL(TInt& aArrayIndex, TInt aSubCell); + void ResetSLSubCellArray(); + + +private: // New internal methods + TBool DrawHighlightBackground( CFbsBitGc& aGc ); + void PostDeleteAnimation(); + void CreateAnimationL(); + void DoResizeL( const TSize& aHighlightSize, TBool aAboutToStart ); + +private: // from MAknPictographAnimatorCallback + void DrawPictographArea(); + +public: + CArrayPtr* iIconArray; + CCoeControl *iControl; // not owned + CAknsListBoxBackgroundControlContext* iSkinControlContext; + const TAknsItemID *iSkinHighlightFrameId; + const TAknsItemID *iSkinHighlightFrameCenterId; + TBool iSkinEnabled; + CAknPictographInterface* iPictoInterface; + CAknMarqueeControl* iMarquee; + CAknMarqueeControl* i2ndLineMarquee; + TInt iCurrentItem; // Marquee: + TInt iCurrentRow; // Current list row being drawn. + CArrayFix* iRowAndColumnArray; + TSize iSubCellIconSize[6]; // Store icon sizes for each column + TAknSeparatorLinePosition iSeparatorLinePosition; + CAknsEffectAnim* iAnimation; + /** + * Stored flags are explained in enumeration TFlags. + */ + TBitFlags32 iAnimFlags; + CPbk2ContactViewCustomListBoxData* iListBoxData; + TRgb iHighlightedTextColor; + TRgb iTextColor; + + TAknsItemID iAnimIID; + MColumnListBoxAnimBackgroundDrawer* iHighlightBgDrawer; + TSize iAnimSize; // TODO Deprecating old style anim API and removing this + TBool iUnderlineFlagSet; // underlining support for more than + TBitFlags32 iUnderlineFlags; // one text subcell + TBool iUseLayoutData; + TBool iStretchingEnabled; + CArrayFix* iRowAndSubCellArray; + CArrayFix* iSLSubCellArray; + TBool iSubCellsMightIntersect; + TRect iParent; // parent for size calculations + + // colorskin highlight icons + CFbsBitmap* iColorBmp; + CFbsBitmap* iHiliBmp; + TRgb iIconColor; + TRgb iHiliIconColor; + TInt iConditionalCells; + + // which columns of highlighted item have clipped text ? + TUint32 iClippedColumns; + + TBool iKineticScrolling; + + + + CArrayFix* iColumnExtArray; //for column alignment + TRect iMarginRect; + + CAknIconArray* iMarkingIconArray; + }; + +/** +* High priority is well argumented because running the active object will +* result in animation deletion -> results in freeing resources. +*/ +CPbk2ContactViewCustomListBoxDataExtension::CPbk2ContactViewCustomListBoxDataExtension(): + CActive( EPriorityHigh ) + {} + +void CPbk2ContactViewCustomListBoxDataExtension::ConstructL( + CPbk2ContactViewCustomListBoxData* aListBoxData, + const TAknsItemID& aAnimationIID ) + { + ASSERT( aListBoxData ); + iListBoxData = aListBoxData; + iRowAndColumnArray=new(ELeave) CArrayFixFlat(4); + + iSeparatorLinePosition = ENoLine; + + iAnimIID = aAnimationIID; + CActiveScheduler::Add( this ); + TryCreateAnimation(); // Animations are created by default + + // try to set ESS text colors here so that they will be set at least somewhere... + iTextColor = NULL; // just in case + iHighlightedTextColor = NULL; // just in case + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + TRgb color; + + // set ESS text color + TInt error = AknsUtils::GetCachedColor( skin, + color, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG6 ); + if ( !error ) + { + iTextColor = color; + } + + // set ESS highlighted text color + error = AknsUtils::GetCachedColor( skin, + color, + KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG10 ); + if ( !error ) + { + iHighlightedTextColor = color; + } + + iRowAndSubCellArray=new(ELeave) CArrayFixFlat(4); + + iSLSubCellArray=new(ELeave) CArrayFixFlat(4); + + iColumnExtArray = new(ELeave) CArrayFixFlat(KColumnListBoxGranularity); + +#ifdef RD_LIST_STRETCH + // check list stretching from cenrep + CRepository* cenRep = CRepository::NewL( KCRUidAvkon ); + cenRep->Get( KAknAutomaticListStretching, iStretchingEnabled ); + delete cenRep; +#endif // RD_LIST_STRETCH + + + iKineticScrolling = CAknPhysics::FeatureEnabled(); + + LoadMarkingIconsL(); + + } + +CPbk2ContactViewCustomListBoxDataExtension::~CPbk2ContactViewCustomListBoxDataExtension() + { + + Cancel(); + + // Stop receiving foreground events + CCoeEnv* env = CCoeEnv::Static(); + env->RemoveForegroundObserver( *this ); + + delete iRowAndColumnArray; + iRowAndColumnArray = NULL; + delete iSkinControlContext; + delete iPictoInterface; + delete iMarquee; + delete i2ndLineMarquee; + delete iAnimation; + delete iRowAndSubCellArray; + delete iSLSubCellArray; + delete iColorBmp; + delete iHiliBmp; + delete iColumnExtArray; + if ( iMarkingIconArray ) + { + iMarkingIconArray->ResetAndDestroy(); + } + + delete iMarkingIconArray; + } + +MAknsControlContext* CPbk2ContactViewCustomListBoxDataExtension::SkinBackgroundContext() const + { + if ( iSkinEnabled ) + { + return iSkinControlContext; + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::NoAnimIfError +// ----------------------------------------------------------------------------- +// +inline void CPbk2ContactViewCustomListBoxDataExtension::NoAnimIfError( TInt aError ) + { + if( KErrNone != aError ) + { + DeleteAnim(); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::TryCreateAnimation +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::TryCreateAnimation() + { + if( !iControl ) + { + return; + } + +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + CEikListBox* list = static_cast( iControl ); + CListBoxView* view = list->View(); + if ( !view || !view->ItemDrawer() ) + { + return; + } + CWindowGc* gc = view->ItemDrawer()->Gc(); + MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( gc ); + if ( transApi && transApi->VerifyKml() == KErrNone ) + { + return; + } +#endif //RD_UI_TRANSITION_EFFECTS_LIST + + // Ideally we should not create animation if the list has zero items. + // Unfortunately, this will cause problems elsewhere as setting item text + // array to list requires not calling HandleItemAddition (or similar + // method) -> in some situations animation would not be created at all as + // we don't receive item change event. Fortunately, creating animation to + // empty list doesn't carry much overhead as layer creation is delayed to + // first render. + + if( !iAnimation ) + { + // This must be the first call because animation does not exist. + // Animation layers are created when the animation is rendered for the + // first time. + TRAPD( err, CreateAnimationL() ); + NoAnimIfError( err ); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::SyncAnim +// ----------------------------------------------------------------------------- +// +TBool CPbk2ContactViewCustomListBoxDataExtension::SyncAnim( const TSize& aSize ) + { + if( !iAnimation || aSize.iWidth <= 0 || aSize.iHeight <= 0 ) + { + return EFalse; + } + + if( iAnimation->Size() != aSize || iAnimation->NeedsInputLayer() ) + { + // Resizing will update animation background + iAnimFlags.Clear( EFlagUpdateBg ); + + // Animation exists but its size is out of sync or input layers have + // been released + TRAPD( err, DoResizeL( aSize, iAnimFlags.IsSet( EFlagHasForeground ) ) ); + + if( err ) + { + DeleteAnim(); + return EFalse; + } + iAnimFlags.Set( EFlagHasLayers ); + } + + // Highlight animation background needs update (current item has changed) + if( iAnimFlags.IsSet( EFlagUpdateBg ) ) + { + iAnimFlags.Clear( EFlagUpdateBg ); + + if( iAnimation->InputRgbGc() ) + { + DrawHighlightBackground( *iAnimation->InputRgbGc() ); + // We need to update the output frame (otherwise the highlight + // would drawn with the old output before the next new animation + // frame). + NoAnimIfError( iAnimation->UpdateOutput() ); + if( !iAnimation ) + { + return EFalse; + } + } + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::SyncAndDrawAnim +// ----------------------------------------------------------------------------- +// +TBool CPbk2ContactViewCustomListBoxDataExtension::SyncAndDrawAnim( + CBitmapContext& aGc, const TRect& aRect ) + { + if( iAnimation ) + { + // When application loses foreground or has not yet gained foreground + // animation is in stopped state and input layers are not present. It + // is possible that list is repainted in this situation. Calling + // SyncAnim will create the non-present layers -> WSERV flush -> + // flicker. To prevent flickering we just render the existing frame. + // This can lead to incorrect draw if the current item index is changed + // when the app has no foreground (very unlikely). If EFlagHasLayers is + // not set we need to do SyncAnim because it is the first call to draw + // (and flicker is not an issue). + if( EAknsAnimStateStopped == iAnimation->State() && + !iAnimFlags.IsSet( EFlagHasForeground ) && + iAnimFlags.IsSet( EFlagHasLayers ) && + !iAnimFlags.IsSet( EFlagUpdateBg ) ) + { + return iAnimation->Render( aGc, aRect ); + } + } + + if( SyncAnim( aRect.Size() ) ) + { + return iAnimation->Render( aGc, aRect ); + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::DeleteAnim +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::DeleteAnim() + { + // Stop receiving foreground events + CCoeEnv* env = CCoeEnv::Static(); + env->RemoveForegroundObserver( *this ); + + delete iAnimation; + iAnimation = NULL; + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::FocusGained +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::FocusGained() + { + Play(); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::FocusLost +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::FocusLost() + { + if( iAnimation ) + { + NoAnimIfError( iAnimation->Pause() ); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::SkinChangedL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::SkinChangedL() + { + DeleteAnim(); + TryCreateAnimation(); + CreateColorBitmapsL(); + LoadMarkingIconsL(); + } +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::SkinChanged +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::SkinChanged() + { + DeleteAnim(); + TryCreateAnimation(); + TRAP_IGNORE( CreateColorBitmapsL() ); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::SetControl +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::SetControl( CCoeControl* aControl ) + { + if( iControl ) + { + CEikListBox* list = (CEikListBox*) iControl; + list->RemoveItemChangeObserver( this ); + } + + iControl = aControl; + + if( iControl ) + { + CEikListBox* list = (CEikListBox*) iControl; + TRAP_IGNORE( list->AddItemChangeObserverL(this) ); + + if( !iAnimation ) + { + TryCreateAnimation(); + } + + if( iAnimation ) + { + Play(); + } + } + else + { + DeleteAnim(); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::HandleGainingForeground +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::HandleGainingForeground() + { + // Most of the time focus focus events happen between foreground events. + // Unfortunately, there are embedded app related cases where this does not + // always hold (it is possible to focus in non-foreground application or + // gain foreground without getting a focus gained). Therefore animations + // must be started here. This causes potential problem case: foreground + // events are broadcasted to all animations, if there are multiple lists + // that have focus the result will be multiple animations running at the + // same time. + iAnimFlags.Set( EFlagHasForeground ); + + if( iAnimation ) + { + // Because we are gaining foreground we must restore input layers + // (which are released when animation stops to reduce memory usage). + SyncAnim( iAnimation->Size() ); + } + + if( iControl ) + { + if( iControl->IsFocused() ) + { + Play(); + } + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::HandleLosingForeground +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::HandleLosingForeground() + { + iAnimFlags.Clear( EFlagHasForeground ); + if( iAnimation ) + { + NoAnimIfError( iAnimation->Stop() ); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::AnimFrameReady +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::AnimFrameReady( TInt aError, TInt ) + { + if( KErrNone != aError ) + { + // Animation has failed to run -> schedule the animation for + // deletion to fall back to normal rendering. + PostDeleteAnimation(); + return; + } + + // This situation should never happen because we start/stop animation when + // the extension's control is set. + if( !iControl ) + return; + + // From now on, we have a valid control pointer + CEikColumnListBox* list = static_cast( iControl ); + CListBoxView* view = list->View(); + + if( !view ) + return; + + // We should not run animation when control is in certain states. When + // control is in these states we idle the animation until the control state + // becomes valid again. + TBool invalid = !iControl->IsVisible() || + iControl->IsDimmed() || + (view->ItemDrawer()->Flags() & CListItemDrawer::EDisableHighlight); + + // Check for idling + if( iAnimation->IsIdling() ) + { + if( invalid ) + { + // We are idling and the control is still invalid -> keep on + // idling. + return; + } + else + { + // Control is in valid state, animation should be continued + TInt err = iAnimation->Continue(); + if( err ) + PostDeleteAnimation(); + return; + } + } + else if( invalid ) // Not idling and invalid control -> start idling + { + iAnimation->SetIdling( KAknsEffectAnimDefaultIdleInterval ); + // If the highlight has been disabled, render once to clear the + // highlight (not returning in that case). + if( !(view->ItemDrawer()->Flags() & CListItemDrawer::EDisableHighlight) ) + return; + } + + // No items, no drawing + if( list->Model()->NumberOfItems() == 0 ) + { + return; + } + + // Column array is not ready yet + if( iListBoxData->LastColumn() < 0 ) + { + return; + } + + // Repaint the highlighted cell only + view->DrawItem( view->CurrentItemIndex() ); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::ListBoxItemsChanged + +// we get here from: +// - CEikListBox::Reset() +// - CEikListBox::HandleItemRemoval{WithoutSelections}L() +// - CEikListBox::HandleItemAdditionL() +// - CEikListBox::FireItemChange() +// In all cases: +// - feedback areas might be invalid +// - application is responsible for redrawing the listbox. +// +// since re-drawing listbox fixes feedback areas, those can be reset here. + +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::ListBoxItemsChanged( + CEikListBox* aListBox) + { + TInt items = aListBox->Model()->NumberOfItems(); + + if( iAnimation ) + { + if( 0 == items ) + { + DeleteAnim(); + } + else + { + Play(); + } + } + else if( !iAnimation ) + { + // Animation doesn't exist and we have > 0 items + TryCreateAnimation(); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::DoCancel +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::DoCancel() + { + // Required method, but not needed + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::RunL +// Postponed animation deletion is done here. +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::RunL() + { + DeleteAnim(); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::Play +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::Play() + { + if( !iAnimation ) + { + return; + } + + // No need to start running/finished animation + if( EAknsAnimStateRunning == iAnimation->State() || + EAknsAnimStateFinished == iAnimation->State() ) + { + return; + } + + // Check that application is on foreground because there are cases where + // focus changes are done after foreground is lost -> potentially leads to + // multiple running animations. + if( !iAnimFlags.IsSet( EFlagHasForeground ) ) + { + return; + } + + // Animation cannot run if we don't have control (nowhere to draw) + if( !iControl ) + { + return; + } + + // The control must also have the focus + if( !iControl->IsFocused() ) + { + return; + } + + // Don't animate empty list + CEikColumnListBox* list = static_cast( iControl ); + if( list->Model()->NumberOfItems() == 0 ) + { + return; + } + + // All preconditions are met: we have animation, foreground, focus, more + // than zero items and animation is either paused or stopped. Invisibility, + // dimming and disabled highlight are handled by idling the animation (see + // AnimFrameReady). + + if( EAknsAnimStatePaused == iAnimation->State() ) + { + NoAnimIfError( iAnimation->Continue() ); + } + else if( EAknsAnimStateStopped == iAnimation->State() ) + { + NoAnimIfError( iAnimation->Start() ); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::DrawHighlightBackground +// ----------------------------------------------------------------------------- +// +TBool CPbk2ContactViewCustomListBoxDataExtension::DrawHighlightBackground( CFbsBitGc& aGc ) + { + if( iHighlightBgDrawer ) // Bg drawing is done externally (in derived class) + { + return iHighlightBgDrawer->DrawHighlightAnimBackground( aGc ); + } + + // Draw the background under the current highlight. This is simplified + // drawing, we only grab a piece from the list background bitmap. + CEikColumnListBox* list = + static_cast( iControl ); + CListBoxView* view = list->View(); + TRect itemRect; + TInt index = view->CurrentItemIndex(); + + // It is possible that the animation is constructed when the list is + // empty. In this case draw the first element background (drawing works ok + // even if the list has no items). + if( list->Model()->NumberOfItems() == 0 ) + { + index = 0; + } + + itemRect.SetRect( view->ItemPos( index ), iAnimation->Size() ); + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext( iControl ); + + if( !cc ) + cc = SkinBackgroundContext(); + + return AknsDrawUtils::DrawBackground( skin, cc, iControl, aGc, TPoint(0,0), + itemRect, KAknsDrawParamBottomLevelRGBOnly ); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::PostDeleteAnimation +// Schedules the animation for deletion by activating the extension itself. +// Deletion is postponed because in many error/failure occasions the caller has +// been animation and direct deletion is possibly not safe (because function +// stack would return through the deleted object). +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::PostDeleteAnimation() + { + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrNone ); + SetActive(); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::CreateAnimationL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::CreateAnimationL() + { + DeleteAnim(); + + // Check if derived class wants to disable highligh animation + if( KAknsIIDNone == iAnimIID ) + { + return; + } + + // Create animation + CCoeEnv* env = CCoeEnv::Static(); + env->AddForegroundObserverL( *this ); + + iAnimation = CAknsEffectAnim::NewL( this ); + TBool ok = iAnimation->ConstructFromSkinL( iAnimIID ); + + if( !ok ) // Animation for the ID was not found from the skin + { + User::Leave( KErrNotFound ); + } + + // Sync the local foreground flag state. Foreground state is stored locally + // because calling AppUi::IsForeground causes WSERV flush (shocking) and + // therefore it cannot be used in draw routines. + CAknAppUi* aui = static_cast(CEikonEnv::Static()->AppUi()); + iAnimFlags.Assign( EFlagHasForeground, aui->IsForeground() ); + + Play(); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::DoResizeL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::DoResizeL( + const TSize& aHighlightSize, TBool aAboutToStart ) + { + iAnimation->BeginConfigInputLayersL( aHighlightSize, aAboutToStart ); + + if( iAnimation->InputRgbGc() ) + { + DrawHighlightBackground( *iAnimation->InputRgbGc() ); + } + + iAnimation->EndConfigInputLayersL(); + } + +void CPbk2ContactViewCustomListBoxDataExtension::DrawPictographArea() + { + iControl->DrawNow(); + } + +TInt CPbk2ContactViewCustomListBoxDataExtension::RedrawEvent(TAny* aControl) + { + if (!((CCoeControl*)aControl)->IsVisible()) + { + return EFalse; + } + CEikColumnListBox* listBox = + (CEikColumnListBox*)aControl; + + // HWET-7BDDD4 + CListBoxView* view = listBox->View(); + TInt index = listBox->CurrentItemIndex(); + if ( view->ItemIsVisible( index ) ) + { + listBox->DrawItem( index ); + } + return ETrue; + } + +TBool CPbk2ContactViewCustomListBoxDataExtension::IsMarqueeOn() + { + TBool isOn = EFalse; + if (iMarquee) + isOn = iMarquee->IsMarqueeOn(); + return isOn; + } +void CPbk2ContactViewCustomListBoxDataExtension::AddSLSubCellL(TInt aSubCell) + { + SSLSubCell subcell; + subcell.iSubCell = aSubCell; + subcell.iTextLayout = NULL; + subcell.iGraphicLayout = NULL; + subcell.iSubCellType = 0; + subcell.iConditionValue = -1; + + TKeyArrayFix key(0,ECmpTInt32); + iSLSubCellArray->InsertIsqL(subcell,key); + } + +void +CPbk2ContactViewCustomListBoxDataExtension::AddRowAndColumnL(TInt aRow,TInt aColumn) + { + SRowAndColumn column; + column.iIndex = (aRow << 8) | (aColumn & 0xff); + TKeyArrayFix key(0,ECmpTInt32); + iRowAndColumnArray->InsertIsqL(column,key); + } + + +CPbk2ContactViewCustomListBoxDataExtension::SRowAndColumn& +CPbk2ContactViewCustomListBoxDataExtension::At(TInt aArrayIndex) + { + __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndexCount(),Panic(EPanicPreCond_OutOfRangeListBoxData)); + return(iRowAndColumnArray->At(aArrayIndex)); + } + +const CPbk2ContactViewCustomListBoxDataExtension::SRowAndColumn& +CPbk2ContactViewCustomListBoxDataExtension::At(TInt aArrayIndex) const + { + __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndexCount(),Panic(EPanicPreCond_OutOfRangeListBoxData)); + return(iRowAndColumnArray->At(aArrayIndex)); + } + +TInt CPbk2ContactViewCustomListBoxDataExtension::FindRowAndColumnIndex(TInt& aArrayIndex, + TInt aRow, + TInt aColumn) const + { + if (iRowAndColumnArray->Count()==0) + return(KErrNotFound); + TKeyArrayFix key(0,ECmpTInt32); + SRowAndColumn rowAndColumn; + rowAndColumn.iIndex = (aRow << 8) | (aColumn & 0xff); + return(iRowAndColumnArray->FindIsq(rowAndColumn,key,aArrayIndex)); + } + +void CPbk2ContactViewCustomListBoxDataExtension::FindRowAndColumnIndexOrAddL(TInt& aArrayIndex, + TInt aRow, + TInt aColumn) + { + if (FindRowAndColumnIndex(aArrayIndex,aRow,aColumn)!=0) //==KErrNotFound) + { + AddRowAndColumnL(aRow,aColumn); + FindRowAndColumnIndex(aArrayIndex,aRow,aColumn); + } + } + +/////////////handling TColumnExt,start + +TInt CPbk2ContactViewCustomListBoxDataExtension::AddColumnExtL(TInt aColumn) + { + TColumnExt column; + column.iColumn=aColumn; + column.iLayoutAlign = ETrue; + TKeyArrayFix key(0,ECmpTInt); + return iColumnExtArray->InsertIsqL(column,key); + } +void CPbk2ContactViewCustomListBoxDataExtension::FindColumnExtIndexOrAddL(TInt& aArrayIndex,TInt aColumn) + { + if (!FindColumnExtIndex(aArrayIndex,aColumn)) + { + aArrayIndex = AddColumnExtL(aColumn); + + } + } + +void CPbk2ContactViewCustomListBoxDataExtension::SetColumnLayoutAlignmentL(TInt aColumn) + { + TInt index; + FindColumnExtIndexOrAddL(index,aColumn); + iColumnExtArray->At(index).iLayoutAlign = EFalse; + } + + +TBool CPbk2ContactViewCustomListBoxDataExtension::FindColumnExtIndex(TInt& aArrayIndex,TInt aColumn) const + { + if (aColumn<0 || iColumnExtArray->Count()==0) + return EFalse; + TKeyArrayFix key(0,ECmpTInt); + TColumnExt column; + column.iColumn=aColumn; + + // Returns zero if key was found, otherwise non-zero + TInt ret = iColumnExtArray->FindIsq(column,key,aArrayIndex); + return (ret == 0); + } + +TBool CPbk2ContactViewCustomListBoxDataExtension::ColumnLayoutAlignment(TInt aColumn) const + { + TInt index; + if (!FindColumnExtIndex(index,aColumn)) + return(ETrue); + return(iColumnExtArray->At(index).iLayoutAlign); + } + +/////////////handling TColumnExt,end +CPbk2ContactViewCustomListBoxDataExtension::SSLSubCell& +CPbk2ContactViewCustomListBoxDataExtension::AtSL(TInt aArrayIndex) + { + __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndexCount(),Panic(EPanicPreCond_OutOfRangeListBoxData)); + return(iSLSubCellArray->At(aArrayIndex)); + } + +const CPbk2ContactViewCustomListBoxDataExtension::SSLSubCell& +CPbk2ContactViewCustomListBoxDataExtension::AtSL(TInt aArrayIndex) const + { + __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndexCount(),Panic(EPanicPreCond_OutOfRangeListBoxData)); + return(iSLSubCellArray->At(aArrayIndex)); + } + +TInt CPbk2ContactViewCustomListBoxDataExtension::FindSLSubCellIndex(TInt& aArrayIndex, + TInt aSubCell) const + { + if (iSLSubCellArray->Count()==0) + return(KErrNotFound); + TKeyArrayFix key(0,ECmpTInt32); + SSLSubCell SLSubCell; + SLSubCell.iSubCell = aSubCell; + return(iSLSubCellArray->FindIsq(SLSubCell,key,aArrayIndex)); + } + +void CPbk2ContactViewCustomListBoxDataExtension::FindSLSubCellIndexOrAddL(TInt& aArrayIndex, + TInt aSubCell) + { + if (FindSLSubCellIndex(aArrayIndex, aSubCell)!=0) //==KErrNotFound) + { + AddSLSubCellL(aSubCell); + FindSLSubCellIndex(aArrayIndex,aSubCell); + } + } + +void CPbk2ContactViewCustomListBoxDataExtension::ResetSLSubCellArray() + { + iSLSubCellArray->Reset(); + iRowAndSubCellArray->Reset(); + } + +TBool CPbk2ContactViewCustomListBoxDataExtension::DrawPressedDownEffect( MAknsSkinInstance* aInstance, + CWindowGc& aGc,const TRect& aOutRect, + const TRect& aInnerRect ) const + { + return AknsDrawUtils::DrawFrame( aInstance, + aGc, + aOutRect, + aInnerRect, + KAknsIIDQsnFrListPressed, + KAknsIIDQsnFrListCenterPressed ); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxDataExtension::LoadMarkingIconsL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxDataExtension::LoadMarkingIconsL() + { + if ( !iMarkingIconArray ) + { + iMarkingIconArray = new ( ELeave ) CAknIconArray( 2 ); + } + else + { + iMarkingIconArray->ResetAndDestroy(); + } + + CGulIcon* icon = AknsUtils::CreateGulIconL( AknsUtils::SkinInstance(), + KAknsIIDQgnPropCheckboxOn, + AknIconUtils::AvkonIconFileName(), + EMbmAvkonQgn_prop_checkbox_on, + EMbmAvkonQgn_prop_checkbox_on_mask ); + + CleanupStack::PushL( icon ); + iMarkingIconArray->AppendL( icon ); + CleanupStack::Pop( icon ); + + icon = AknsUtils::CreateGulIconL( AknsUtils::SkinInstance(), + KAknsIIDQgnPropCheckboxOff, + AknIconUtils::AvkonIconFileName(), + EMbmAvkonQgn_prop_checkbox_off, + EMbmAvkonQgn_prop_checkbox_off_mask ); + + CleanupStack::PushL( icon ); + iMarkingIconArray->AppendL( icon ); + CleanupStack::Pop( icon ); + } + +CCoeControl *CPbk2ContactViewCustomListBoxData::Control() const + { + return iExtension->iControl; + } + +void CPbk2ContactViewCustomListBoxData::SetControl(CCoeControl *aControl) + { + iExtension->SetControl( aControl ); + } + + +MAknsControlContext* CPbk2ContactViewCustomListBoxData::SkinBackgroundContext() const + { + if (iExtension->iSkinEnabled) + { + return iExtension->iSkinControlContext; + } + + return NULL; + } + +void CPbk2ContactViewCustomListBoxData::SetSkinBackgroundContext(CAknsListBoxBackgroundControlContext *aContext) + { + delete iExtension->iSkinControlContext; + iExtension->iSkinControlContext = aContext; + } + +void CPbk2ContactViewCustomListBoxData::CreatePictographInterfaceL() + { + if ( !iExtension->iPictoInterface ) + { + iExtension->iPictoInterface = CAknPictographInterface::NewL( + *iExtension->iControl, *iExtension ); + } + } + +void CPbk2ContactViewCustomListBoxData::SetSkinHighlightFrame(const TAknsItemID *aFrameId, const TAknsItemID *aFrameCenterId) + { + iExtension->iSkinHighlightFrameId = aFrameId; + iExtension->iSkinHighlightFrameCenterId = aFrameCenterId; + } + +void CPbk2ContactViewCustomListBoxData::SetSkinEnabledL(TBool aEnabled) + { + CListBoxData::SetSkinEnabledL(aEnabled); + iExtension->iSkinEnabled = aEnabled; + } + +void CPbk2ContactViewCustomListBoxData::SetSkinStyle(const TAknsItemID *aId, const TRect &aTileRect) + { + if (iExtension->iSkinControlContext) + { + iExtension->iSkinControlContext->SetTiledBitmap(*aId); + iExtension->iSkinControlContext->SetTiledRect(aTileRect); + } + } + +void CPbk2ContactViewCustomListBoxData::SetListEndSkinStyle(const TAknsItemID *aId, const TRect &aTileRect) + { + if (iExtension->iSkinControlContext) + { + iExtension->iSkinControlContext->SetBottomBitmap(*aId); + iExtension->iSkinControlContext->SetBottomRect(aTileRect); + } + } + +void CPbk2ContactViewCustomListBoxData::CreateMarqueeControlL() + { + if ( !iExtension->iMarquee ) + { + iExtension->iMarquee = CAknMarqueeControl::NewL(); + } + + if ( !iExtension->i2ndLineMarquee ) + { + iExtension->i2ndLineMarquee = CAknMarqueeControl::NewL(); + } + + TCallBack callBack(CPbk2ContactViewCustomListBoxDataExtension::RedrawEvent, + iExtension->iControl); + iExtension->iMarquee->SetRedrawCallBack(callBack); + iExtension->i2ndLineMarquee->SetRedrawCallBack(callBack); + } + +void CPbk2ContactViewCustomListBoxData::ResetMarquee() + { + if (iExtension->iMarquee) + { + iExtension->iMarquee->Reset(); + } + if (iExtension->i2ndLineMarquee) + { + iExtension->i2ndLineMarquee->Reset(); + } + } + +TInt CPbk2ContactViewCustomListBoxData::CurrentMarqueeItemIndex() + { + return iExtension->iCurrentItem; + } + +void CPbk2ContactViewCustomListBoxData::SetCurrentMarqueeItemIndex(TInt aIndex) + { + iExtension->iCurrentItem = aIndex; + } + +// +// Enables or disables marquee. +// +void CPbk2ContactViewCustomListBoxData::EnableMarqueeL(TBool aEnable) + { + // CreateMarqueeControlL does nothing if marquee already exists, + // so let's just call it just in case. + CreateMarqueeControlL(); + iExtension->iMarquee->EnableMarquee(aEnable); + iExtension->i2ndLineMarquee->EnableMarquee(aEnable); + } + +void CPbk2ContactViewCustomListBoxData::SetSeparatorLinePosition(TAknSeparatorLinePosition aPosition) + { + if (iExtension) + iExtension->iSeparatorLinePosition = aPosition; + } +TAknSeparatorLinePosition CPbk2ContactViewCustomListBoxData::SeparatorLinePosition() const + { + if (iExtension) + return iExtension->iSeparatorLinePosition; + else + return ENoLine; + } +CAknLayoutData *CPbk2ContactViewCustomListBoxData::LayoutData() const + { + return NULL; + } + +TBool CPbk2ContactViewCustomListBoxData::LayoutInit() const + { + return EFalse; + } + +void CPbk2ContactViewCustomListBoxData::SetLayoutInit(TBool /*aValue*/) const + { + } + + +// +// Class CPbk2ContactViewCustomListBoxData::TColors +// + +/** + * Constructs and intialises the data colors to blacks and whites. + */ +CPbk2ContactViewCustomListBoxData::TColors::TColors() + : iText(KRgbBlack), iBack(KRgbWhite), iHighlightedText(KRgbWhite), iHighlightedBack(KRgbBlack) + { + } + +// +// Class CPbk2ContactViewCustomListBoxData +// + +CPbk2ContactViewCustomListBoxData* CPbk2ContactViewCustomListBoxData::NewL( + CPbk2PredictiveSearchFilter &aSearchFilter ) +// +// Public c'tor +// + { + CPbk2ContactViewCustomListBoxData* self=new(ELeave) + CPbk2ContactViewCustomListBoxData( aSearchFilter ); + self->ConstructLD(); + return(self); + } + +CPbk2ContactViewCustomListBoxData::CPbk2ContactViewCustomListBoxData( + CPbk2PredictiveSearchFilter &aSearchFilter ) + : CListBoxData(), iSearchFilter( aSearchFilter ) +// +// Protected c'tor +// + { + + } + +CPbk2ContactViewCustomListBoxData::~CPbk2ContactViewCustomListBoxData() +// +// D'tor +// + { + delete iColumnArray; + if (IconArray()) + { + IconArray()->ResetAndDestroy(); + if (iExtension) + delete iExtension->iIconArray; + } + delete iExtension; + } + +void CPbk2ContactViewCustomListBoxData::ConstructLD() + { + TRAPD( err, DoConstructL( KAknsIIDQsnAnimList ) ); + if( err ) + { + delete(this); + User::Leave( err ); + } + } + +void CPbk2ContactViewCustomListBoxData::ConstructLD( + const TAknsItemID& aAnimationIID ) + { + TRAPD( err, DoConstructL( aAnimationIID ) ); + if( err ) + { + delete(this); + User::Leave( err ); + } + } + +void CPbk2ContactViewCustomListBoxData::DoConstructL( const TAknsItemID& aAnimationIID ) + { + iColumnArray = new(ELeave) CArrayFixFlat(KColumnListBoxGranularity); + iExtension = new(ELeave) CPbk2ContactViewCustomListBoxDataExtension; + + iExtension->iSkinEnabled = AknsUtils::AvkonSkinEnabled(); + SetupSkinContextL(); + + iExtension->ConstructL( this, aAnimationIID ); + + CListBoxData::SetSkinBackgroundControlContextL(iExtension->iSkinControlContext); + + // preallocate columns so that we dont need to leave on + // SizeChanged(). + // AddColumnL(0); + // AddColumnL(1); + // AddColumnL(2); + // AddColumnL(3); + // AddColumnL(4); + } + +TInt CPbk2ContactViewCustomListBoxData::LastColumn() const +// +// The last column defined +// + { + TInt count=iColumnArray->Count(); + if (!count) + return(KErrNotFound); + return(At(count-1).iColumn); + } + +TInt CPbk2ContactViewCustomListBoxData::ColumnWidthPixel(TInt aColumn) const +// +// Return the width for a column +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(0); + return(At(index).iWidth); + } + +void CPbk2ContactViewCustomListBoxData::SetColumnWidthPixelL(TInt aColumn,TInt aWidth) +// +// Set a columns width +// + { + TInt index; + FindColumnIndexOrAddL(index,aColumn); + At(index).iWidth=aWidth; + if ( iExtension && iExtension->iUseLayoutData ) + { + iExtension->iUseLayoutData = EFalse; + CListBoxView* view = static_cast( iExtension->iControl )->View(); + MAknListBoxTfxInternal* transApi = + CAknListLoader::TfxApiInternal( view->ItemDrawer()->Gc() ); + if ( transApi ) + { + transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, TPoint( 0, 0 ) ); + transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin, TPoint( 0, 0 ) ); + } + } + } + +TInt CPbk2ContactViewCustomListBoxData::ColumnHorizontalGap(TInt aColumn) const +// +// Return the vertical for a column +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(0); + return(At(index).iVerticalCap); + } + +void CPbk2ContactViewCustomListBoxData::SetColumnHorizontalGapL(TInt aColumn,TInt aGap) +// +// Set a columns vertical cap +// + { + TInt index; + FindColumnIndexOrAddL(index,aColumn); + At(index).iVerticalCap=aGap; + } + + +TInt +CPbk2ContactViewCustomListBoxData::ColumnTextClipGap(TInt aColumnIndex) const + { + TInt index; + if (!FindColumnIndex(index,aColumnIndex)) + return TInt(0); + return(iColumnArray->At(index).iTextClipGap); + } + +void +CPbk2ContactViewCustomListBoxData::SetColumnTextClipGapL(TInt aColumnIndex, TInt aGap) + { + TInt index; + FindColumnIndexOrAddL(index,aColumnIndex); + At(index).iTextClipGap=aGap; + } + +TInt CPbk2ContactViewCustomListBoxData::ColumnBaselinePos(TInt aColumn) const +// +// Return the vertical for a column +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(0); + return(At(index).iBaseline); + } + +void CPbk2ContactViewCustomListBoxData::SetColumnBaselinePosL(TInt aColumn,TInt aPos) +// +// Set a columns baseline position +// + { + TInt index; + FindColumnIndexOrAddL(index,aColumn); + At(index).iBaseline=aPos; + + // can not be nicely supported by new drawing system + // --> revert to Symbian style drawing + if ( iExtension && iExtension->iUseLayoutData ) + { + iExtension->iUseLayoutData = EFalse; + CListBoxView* view = static_cast( iExtension->iControl )->View(); + MAknListBoxTfxInternal* transApi = + CAknListLoader::TfxApiInternal( view->ItemDrawer()->Gc() ); + if ( transApi ) + { + transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, TPoint( 0, 0 ) ); + transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin, TPoint( 0, 0 ) ); + } + } + } + +TMargins CPbk2ContactViewCustomListBoxData::ColumnMargins(TInt aColumn) const +// +// Return the vertical for a column +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + { + TMargins m = {0,0,0,0}; + return m; + } + return(At(index).iMargins); + } + +void CPbk2ContactViewCustomListBoxData::SetColumnMarginsL(TInt aColumn,TMargins aMargins) +// +// Set a columns vertical cap +// + { + TInt index; + FindColumnIndexOrAddL(index,aColumn); + At(index).iMargins=aMargins; + + // can not be nicely supported by new drawing system + // --> revert to Symbian style drawing + if ( iExtension && iExtension->iUseLayoutData ) + { + iExtension->iUseLayoutData = EFalse; + CListBoxView* view = static_cast( iExtension->iControl )->View(); + MAknListBoxTfxInternal* transApi = + CAknListLoader::TfxApiInternal( view->ItemDrawer()->Gc() ); + if ( transApi ) + { + transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, TPoint( 0, 0 ) ); + transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin, TPoint( 0, 0 ) ); + } + } + } + + +TInt CPbk2ContactViewCustomListBoxData::ColumnX(TInt aColumn) const + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + { + return 0; + + } + return(At(index).iX); + } + +void CPbk2ContactViewCustomListBoxData::SetColumnXL(TInt aColumn,TInt aX) const + { + TInt index; + MUTABLE_CAST(CPbk2ContactViewCustomListBoxData*,this)->FindColumnIndexOrAddL(index,aColumn); + MUTABLE_CAST(TInt&,At(index).iX)=aX; + } + + +TInt CPbk2ContactViewCustomListBoxData::ColumnEndX(TInt aColumn) const + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + { + return 0; + } + return(At(index).iEndX); + } + +void CPbk2ContactViewCustomListBoxData::SetColumnEndXL(TInt aColumn,TInt aEndX) const + { + TInt index; + MUTABLE_CAST(CPbk2ContactViewCustomListBoxData*,this)->FindColumnIndexOrAddL(index,aColumn); + MUTABLE_CAST(TInt&,At(index).iEndX)=aEndX; + } + +const CFont* CPbk2ContactViewCustomListBoxData::ColumnFont(TInt aColumn) const +// +// Return the font for a column +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(NULL); + return(iColumnArray->At(index).iBaseFont); + } + +void CPbk2ContactViewCustomListBoxData::SetColumnFontL(TInt aColumn,const CFont* aFont) +// +// Set a font for a column +// + { +// This corrects error report KBAA-53GEQ5. +#if NOT_NEEDED_IN_SERIES60 + TInt columns=iColumnArray->Count(); +#endif + TInt index; + FindColumnIndexOrAddL(index,aColumn); + if (!At(index).iBaseFont) + { +// This corrects error report KBAA-53GEQ5. +#if NOT_NEEDED_IN_SERIES60 + TInt actualFontIndex=0; + TRAPD(err, actualFontIndex=AddActualFontL(aFont)); + if (err) + { + if (columns!=iColumnArray->Count()) + { + iColumnArray->Delete(index); + } + User::Leave(err); + } + At(index).iActualFontIndex=actualFontIndex; +#endif + // TPFIX(moved down) At(index).iBaseFont=aFont; + } + At(index).iBaseFont=aFont; + } + +CGraphicsContext::TTextAlign CPbk2ContactViewCustomListBoxData::ColumnAlignment(TInt aColumn) const +// +// Return a columns alignment +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(CGraphicsContext::ELeft); + return(iColumnArray->At(index).iAlign); + } + +void CPbk2ContactViewCustomListBoxData::SetColumnAlignmentL(TInt aColumn,CGraphicsContext::TTextAlign aAlign) +// +// Set a columns alignment +// + { + TInt index; + FindColumnIndexOrAddL(index,aColumn); + At(index).iAlign=aAlign; + iExtension->SetColumnLayoutAlignmentL( aColumn); + } + + +CGraphicsContext::TPenStyle CPbk2ContactViewCustomListBoxData::ColumnSeparatorStyle(TInt aColumn) const +// +// Return a columns separator style +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(CGraphicsContext::ENullPen); + return(iColumnArray->At(index).iSeparator); + } + +void CPbk2ContactViewCustomListBoxData::SetColumnSeparatorStyleL(TInt aColumn,CGraphicsContext::TPenStyle aSeparator) +// +// Set a columns separator style +// + { + TInt index; + FindColumnIndexOrAddL(index,aColumn); + At(index).iSeparator=aSeparator; + } + + +TBool CPbk2ContactViewCustomListBoxData::ColumnIsGraphics(TInt aColumn) const +// +// Return true if the column contains graphics +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(EFalse); + return(iColumnArray->At(index).iGraphics); + } + +void CPbk2ContactViewCustomListBoxData::SetGraphicsColumnL(TInt aColumn,TBool aIsGraphics) +// +// Sets whether a column shows graphics +// + { + TInt index; + FindColumnIndexOrAddL(index,aColumn); + At(index).iGraphics=aIsGraphics; + } + +TBool CPbk2ContactViewCustomListBoxData::ColumnIsNumber(TInt aColumn) const +// +// Return true if the column contains graphics +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(EFalse); + return(iColumnArray->At(index).iNumberColumn); + } + +void CPbk2ContactViewCustomListBoxData::SetNumberColumnL(TInt aColumn,TBool aIsNumber) +// +// Sets whether a column shows graphics +// + { + TInt index; + FindColumnIndexOrAddL(index,aColumn); + At(index).iNumberColumn=aIsNumber; + } + + +TBool CPbk2ContactViewCustomListBoxData::ColumnIsOptional(TInt aColumn) const +// +// Return true if the column contains graphics +// + { + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(EFalse); + return(iColumnArray->At(index).iOptional); + } + +void CPbk2ContactViewCustomListBoxData::SetOptionalColumnL(TInt aColumn,TBool aIsOptional) +// +// Sets whether a column shows graphics +// + { + TInt index; + FindColumnIndexOrAddL(index,aColumn); + At(index).iOptional=aIsOptional; + } + +CArrayPtr* CPbk2ContactViewCustomListBoxData::IconArray() const +// +// Return the list of icons +// + { + if (iExtension) + return iExtension->iIconArray; + else + return 0; + } + +void CPbk2ContactViewCustomListBoxData::SetIconArray(CArrayPtr* aArray) +// +// Passes ownership of the icon list aArray (assumes any previous list has been deleted by the caller) +// + { + if (iExtension) + iExtension->iIconArray=aArray; + else + { + aArray->ResetAndDestroy(); + delete aArray; + } + } + +CFont* CPbk2ContactViewCustomListBoxData::Font(const TListItemProperties& /*aItemProperties*/, TInt aColumn) const + { + return const_cast(this->ColumnFont(aColumn)); +#if NOT_NEEDED_IN_SERIES60 + TInt index; + if (!FindColumnIndex(index,aColumn)) + return(NULL); + TInt actualFontIndex=iColumnArray->At(index).iActualFontIndex; + if (actualFontIndex==KNoActualColumnFont) + return(NULL); + if ((aItemProperties.IsBold()) && (aItemProperties.IsItalics())) + { + return iBoldItalicFont.iFonts->At(actualFontIndex); + } + else if (aItemProperties.IsBold()) + { + return iBoldFont.iFonts->At(actualFontIndex); + } + else if (aItemProperties.IsItalics()) + { + return iItalicFont.iFonts->At(actualFontIndex); + } + else return iNormalFont.iFonts->At(actualFontIndex); +#endif + } + +void CPbk2ContactViewCustomListBoxData::DrawHighLight( CWindowGc& aGc, const TRect& aRect, TBool aHighlight, MAknsSkinInstance* aSkin ) const + { + // SERIES60 Highlight drawing. + if( aHighlight ) + { + // same as CFormattedCellListBoxData::DrawDefaultHighlight + CListBoxView* view = static_cast( iExtension->iControl )->View(); + TBool pressedDown = view->ItemDrawer()->Flags() & CListItemDrawer::EPressedDownState; + +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( &aGc ); + if ( transApi ) + { + transApi->Invalidate(MAknListBoxTfxInternal::EListHighlight ); // This will remove the old bitmap + transApi->BeginRedraw( MAknListBoxTfxInternal::EListHighlight, aRect ); + transApi->StartDrawing( MAknListBoxTfxInternal::EListHighlight ); + aGc.SetClippingRect( view->ViewRect() ); + } +#endif //RD_UI_TRANSITION_EFFECTS_LIST + // Try drawing the animated highlight + TBool highlightDrawn = EFalse; + if ( iExtension->iAnimation ) + { +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi && transApi->VerifyKml() == KErrNone ) + { + iExtension->DeleteAnim(); + } + else + { +#endif + TAknLayoutRect topLeft; + topLeft.LayoutRect(aRect, SkinLayout::List_highlight_skin_placing__general__Line_2()); + + TAknLayoutRect bottomRight; + bottomRight.LayoutRect(aRect, SkinLayout::List_highlight_skin_placing__general__Line_5()); + + TRect outerRect(topLeft.Rect().iTl, bottomRight.Rect().iBr); + + aGc.SetPenStyle(CGraphicsContext::ENullPen); + highlightDrawn = iExtension->SyncAndDrawAnim( aGc, outerRect ); +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + } +#endif + } + + if (!highlightDrawn) + { + // Animated highlight was not available, use normal skinned + // rendering. + MAknsControlContext *cc = AknsDrawUtils::ControlContext( Control() ); + if (!cc) cc = SkinBackgroundContext(); + if (cc) + { + TAknLayoutRect topLeft; + topLeft.LayoutRect(aRect, SkinLayout::List_highlight_skin_placing__general__Line_2()); + + TAknLayoutRect bottomRight; + bottomRight.LayoutRect(aRect, SkinLayout::List_highlight_skin_placing__general__Line_5()); + + TRect outerRect(topLeft.Rect().iTl, bottomRight.Rect().iBr); + TRect innerRect(topLeft.Rect().iBr, bottomRight.Rect().iTl); + aGc.SetPenStyle(CGraphicsContext::ENullPen); + + + if ( pressedDown ) + { + highlightDrawn = iExtension->DrawPressedDownEffect( aSkin, aGc, outerRect, innerRect ); + //view->ItemDrawer()->ClearFlags( CListItemDrawer::EItemPressedDown ); + } + else + { + highlightDrawn = AknsDrawUtils::DrawFrame( aSkin, + aGc, + outerRect, + innerRect, + *iExtension->iSkinHighlightFrameId, + *iExtension->iSkinHighlightFrameCenterId ); + } + } + } + + // Both animated highlight and normal highlight drawing have failed. + if (!highlightDrawn) + { + TAknLayoutRect highlightshadow; + TAknLayoutRect highlight; + highlightshadow.LayoutRect(aRect, AKN_LAYOUT_WINDOW_List_pane_highlight_graphics__various__Line_1(aRect)); + highlight.LayoutRect(aRect, AKN_LAYOUT_WINDOW_List_pane_highlight_graphics__various__Line_2(aRect)); + highlightshadow.DrawRect(aGc); + highlight.DrawRect(aGc); + } +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi ) + { + aGc.CancelClippingRect(); + transApi->StopDrawing(); + transApi->EndRedraw( MAknListBoxTfxInternal::EListHighlight ); + } +#endif // RD_UI_TRANSITION_EFFECTS_LIST + } + } + + +void CPbk2ContactViewCustomListBoxData::BitBltColored( CWindowGc& aGc, + TBool aHighlight, + const CGulIcon* aIcon, + TInt aSubcell, + TBool aColorIcon, + const TRect& aGraphicRect ) const + { + // see also eikfrlbd.cpp ( sigh ). + CFbsBitmap* bitmap( aIcon->Bitmap() ); + CFbsBitmap* mask( aIcon->Mask() ); + + // possibly colorskinnable icon. Check must be after SetSize() + TBool bw( bitmap->DisplayMode() == EGray2 ); + + // center graphics + TSize size=bitmap->SizeInPixels(); + TInt yDiff = ( aGraphicRect.Height() - size.iHeight ) / 2; + TInt xDiff = ( aGraphicRect.Width() - size.iWidth ) / 2; + TPoint posInBitmap( 0,0 ); + + if (xDiff < 0) // icon's width bigger than subcell's width + { // possible, if icon is not a aknicon + posInBitmap.iX = -xDiff; + xDiff = 0; + } + + if (yDiff < 0) // icon's height bigger than subcell's height + { + posInBitmap.iY = -yDiff; + yDiff = 0; + } + + TPoint bmpPos( aGraphicRect.iTl + TPoint( xDiff, yDiff ) ); + TRect sourcerect( posInBitmap, aGraphicRect.Size() ); + + if ( mask ) + { + TInt i( 0x01 ); + i = i << aSubcell; + if ( ((i & iExtension->iConditionalCells) && bw) || aColorIcon ) + { + aGc.BitBltMasked( bmpPos, + aHighlight ? iExtension->iHiliBmp : iExtension->iColorBmp, + TRect(posInBitmap, size), mask, ETrue ); + } + else + { + aGc.BitBltMasked( bmpPos, bitmap, sourcerect, mask, ETrue ); + } + } + else + { + aGc.BitBlt( bmpPos, bitmap ,sourcerect ); + } + } + +void CPbk2ContactViewCustomListBoxData::DrawSimpleL( const TListItemProperties& aItemProperties, + CWindowGc& aGc, + const TDesC* aText, + const TRect& aRect, + TBool aHighlight, + const TColors& aColors, + TInt aItemIndex ) const + { + + CEikListBox* listbox = static_cast( iExtension->iControl ); + if ( listbox && !listbox->View()->ViewRect().Intersects( aRect ) ) + { + // outside of the clipping rect -> don't process this item + return; + } + + TInt lastColumn = Min( LastColumn(), KMaxColumn ); + TInt column=0; + TPtrC text; + TPtrC tempText; + + TRgb aTextColor = aHighlight ? aColors.iHighlightedText : aColors.iText; + + TBool markingMode = EFalse; + TRect itemRect( aRect ); + + if ( listbox->View() && listbox->View()->ItemDrawer() ) + { + if ( listbox->View()->ItemDrawer()->Flags() + & CListItemDrawer::EMarkingModeEnabled + && iExtension->iMarkingIconArray + && iExtension->iMarkingIconArray->Count() == 2 ) + { + markingMode = ETrue; + itemRect.iTl.iX += + AknLayoutScalable_Avkon::list_single_graphic_pane_t1( 0 ).LayoutLine().il; + } + } + + MAknsSkinInstance *skin = AknsUtils::SkinInstance(); + MAknsControlContext *cc = AknsDrawUtils::ControlContext( Control() ); + if (!cc) + { + cc = SkinBackgroundContext(); + } + + TAknTextLineLayout textLines[KMaxColumn]; + TBool rectClipped[KMaxColumn]; + + Mem::FillZ( &rectClipped[0], KMaxColumn * sizeof( TBool ) ); + + if ( iExtension->iSubCellsMightIntersect ) + { + CheckIfSubCellsIntersectL( &textLines[0], &rectClipped[0], *aText, itemRect ); + } +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( &aGc ); +#endif // RD_UI_TRANSITION_EFFECTS_LIST + + if ( !listbox || !listbox->BackgroundDrawingSuppressed() ) + { +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi ) + { + transApi->StartDrawing( MAknListBoxTfxInternal::EListView ); + } +#endif // RD_UI_TRANSITION_EFFECTS_LIST + + aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); + aGc.SetPenStyle(CGraphicsContext::ESolidPen); + + if ( listbox ) + { + AknsDrawUtils::Background( skin, cc, listbox, aGc, aRect ); + } + else + { + aGc.Clear(aRect); + } + +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi ) + { + transApi->StopDrawing(); + } +#endif // RD_UI_TRANSITION_EFFECTS_LIST + } + + CEikListBox* list = static_cast( iExtension->iControl ); + if ( iExtension->iCurrentRow < list->BottomItemIndex() ) + { + AknListUtils::DrawSeparator( aGc, aRect, aColors.iText, skin ); + } + DrawHighLight( aGc, aRect, aHighlight, skin ); + + if ( markingMode && !aItemProperties.IsSelectionHidden() ) + { + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( aRect, + AknLayoutScalable_Avkon::list_single_graphic_pane_g1( 0 ) ); + + aGc.SetPenColor( aColors.iText ); + aGc.SetPenStyle( CGraphicsContext::ESolidPen ); + + CGulIcon* icon = (*iExtension->iMarkingIconArray)[1]; // unchecked + + if ( listbox->View()->ItemIsSelected( iExtension->iCurrentRow ) ) + { + icon = (*iExtension->iMarkingIconArray)[0]; + } + + CFbsBitmap* bitmap = icon->Bitmap(); + + if ( bitmap ) + { + TSize size( bitmap->SizeInPixels() ); // set size if not already + TSize targetSize( layoutRect.Rect().Size() ); + + if ( size.iWidth != targetSize.iWidth && size.iHeight != targetSize.iHeight ) + { + AknIconUtils::SetSize( bitmap, targetSize, + EAspectRatioPreservedAndUnusedSpaceRemoved ); + } + + aGc.BitBltMasked( layoutRect.Rect().iTl, bitmap, TRect( layoutRect.Rect().Size() ), icon->Mask(), EFalse ); + } + + } + + // The column draw loop + column = 0; + TInt subCellIndex = 0; + // Whether need to redraw the PopupCharacter + TBool redrawPopup = EFalse; + + if ( !iExtension ) { return; } + +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi ) + { + transApi->StartDrawing( MAknListBoxTfxInternal::EListItem ); + CListBoxView* view = static_cast( iExtension->iControl )->View(); + aGc.SetClippingRect( view->ViewRect() ); + } +#endif // RD_UI_TRANSITION_EFFECTS_LIST + + for( column = 0; column <= lastColumn; column++ ) + { + TextUtils::ColumnText( text, column, aText ); + if ( text == KNullDesC ) { continue; } + + if ( iExtension->FindSLSubCellIndex( subCellIndex, column )!=0 ) { continue; } + + CGraphicsContext::TTextAlign align=ColumnAlignment(column); + TBool isLayoutAlignment = iExtension->ColumnLayoutAlignment(column); + + if ( iExtension->AtSL(subCellIndex).iSubCellType == CPbk2ContactViewCustomListBoxDataExtension::EEikSLText ) + { + aGc.SetBrushStyle(CGraphicsContext::ENullBrush); + + TRgb textColor( aTextColor ); + + if (aHighlight) + { + textColor = aColors.iHighlightedText; + aGc.SetBrushColor(aColors.iHighlightedBack); + } + if (AknsUtils::AvkonSkinEnabled()) + { + if (iExtension->iTextColor != NULL) + { + textColor = iExtension->iTextColor; + } + + if (aHighlight && iExtension->iHighlightedTextColor != NULL) + { + textColor = iExtension->iHighlightedTextColor; + } + } + + const CFont* rowAndColFont=RowAndColumnFont(iExtension->iCurrentRow,column); + const CFont* colFont=Font(aItemProperties, column); + const CFont* tempFont=(colFont) ? colFont : NULL; + const CFont* usedFont=(rowAndColFont) ? rowAndColFont : tempFont; + + TAknTextLineLayout textLineLayout = NULL; + + if ( rectClipped[column] ) + { + textLineLayout = textLines[column]; + } + else + { + // check if there are icons affecting this text layout + TInt gSC = iExtension->AtSL(subCellIndex).iConditionValue; // graphical subcell which might affect this text subcell + + if (gSC > -1) + { + TInt tempIndex; + while (gSC > -1) // when gSC == -1, we have found our graphical subcell + { + if (iExtension->FindSLSubCellIndex(tempIndex,gSC)!=0) break; + TextUtils::ColumnText(tempText,gSC, aText); + if (tempText != KNullDesC) + { + textLineLayout = iExtension->AtSL(tempIndex).iTextLayout; + break; + } + gSC = iExtension->AtSL(tempIndex).iConditionValue; + } + } + + if (gSC == -1) // no affecting icons -> use default layout + { + textLineLayout = iExtension->AtSL(subCellIndex).iTextLayout; + } + } + + + if( !isLayoutAlignment ) + { + switch(align) + { + case CGraphicsContext::ELeft : + { + textLineLayout.iJ = ELayoutAlignLeft; + } + break; + case CGraphicsContext::ECenter: + { + textLineLayout.iJ = ELayoutAlignCenter; + } + break; + case CGraphicsContext::ERight: + { + textLineLayout.iJ = ELayoutAlignRight; + } + break; + default: break; + }; + } + + TAknLayoutText textLayout; + textLayout.LayoutText( itemRect, textLineLayout, usedFont ); + TRect layoutedRect( itemRect); + + // *2 == leave some room for marquee + const TInt maxlen( KMaxColumnDataLength * 2 ); + TBuf convBuf = text.Left(maxlen); + + // Note that this potentially modifies the text so its lenght in pixels + // might increase. Therefore, this should always be done before + // wrapping/clipping text. In some cases, WordWrapListItem is called + // before coming here. Is it certain that it is not done for number subcells? + + // Do number conversion if required. + if ( ColumnIsNumber( column ) ) + { + AknTextUtils::LanguageSpecificNumberConversion( convBuf ); + } + + // Check whether logical to visual conversion should be done here or not. + TBool bidiConv = ETrue; // TODO + +// if (ColumnIsNumber(column)) +// { +// AknTextUtils::LanguageSpecificNumberConversion( convBuf ); +// } + + // marquee & clipping detection + TBool doesNotFit( aHighlight && + textLayout.Font()->TextWidthInPixels( convBuf ) > textLayout.TextRect().Width() ); + + // iClippedColumns was cleared in ::Draw() so no need to + // clear anything here + if ( doesNotFit ) + { + iExtension->iClippedColumns |= ( 1 << column ); + } + + TBool marqueeDisabled = ETrue; + if ( listbox ) + { + marqueeDisabled = listbox->View()->ItemDrawer()->Flags() + & CListItemDrawer::EDisableMarquee; + } + + if ( iExtension->IsMarqueeOn() && doesNotFit && !marqueeDisabled ) + { + iExtension->iMarquee->UseLogicalToVisualConversion( bidiConv ); + + if ( iExtension->iMarquee->DrawText( aGc, itemRect, textLineLayout, convBuf, usedFont, textColor ) ) + { + // all the loops have been executed + textLayout.DrawText( aGc, convBuf, bidiConv, textColor ); + } + } + else + { + if ( iExtension->iMarquee && marqueeDisabled ) + { + iExtension->iMarquee->Stop(); + } + +//Start of Code Added for PhoneBook2 + TBool isContactItem = IsContactAtListboxIndex( aItemIndex ); + if ( iSearchFilter.IsPredictiveActivated() && isContactItem ) + { + DrawEnhancedTextL( aItemProperties, aGc, aRect, convBuf, text, + textLayout, textLineLayout, bidiConv, usedFont, textColor ); + } + else + { + textLayout.DrawText( aGc, convBuf, bidiConv, textColor ); + } + +//End of Code Added for PhoneBook2 + } + + if ( iExtension->iPictoInterface ) + { + TRect pictoRect = textLayout.TextRect(); + pictoRect.Normalize(); + if ( convBuf.Length() && bidiConv ) + { + TInt maxWidth = pictoRect.Size().iWidth; + TInt charsCanBeDisplayed = textLayout.Font()->TextCount( + convBuf, maxWidth ); + if ( charsCanBeDisplayed < convBuf.Length() ) + { + TInt clipCharWidth = textLayout.Font()->CharWidthInPixels( + KEllipsis /*aClipChar*/ ); + // Check how many characters fit in given space with truncation char. + charsCanBeDisplayed = textLayout.Font()->TextCount( + convBuf, maxWidth - clipCharWidth ); + + // This is "avkon rule": should not insert ellipsis right after a space. + if ( charsCanBeDisplayed > 1 && + convBuf[charsCanBeDisplayed - 1] == ' ' && + convBuf[charsCanBeDisplayed - 2] != ' ' ) + { + charsCanBeDisplayed--; + } + + TInt pictoRectWidth = textLayout.Font()->TextWidthInPixels( + convBuf.Left( charsCanBeDisplayed ) ); + pictoRect.SetWidth( pictoRectWidth ); + } + } + + + iExtension->iPictoInterface->Interface()->DrawPictographsInText( + aGc, *usedFont, convBuf, + pictoRect, + usedFont->AscentInPixels(), + textLayout.Align(), 0 ); + } + + aGc.SetUnderlineStyle(EUnderlineOff); // disable underline after first text. + } + else if ( iExtension->AtSL(subCellIndex).iSubCellType == CPbk2ContactViewCustomListBoxDataExtension::EEikSLGraphic ) + { + TLex lex(text); + TInt index(0); + TInt err( lex.Val(index) ); + __ASSERT_DEBUG(err == KErrNone,Panic(EPanicColumnListInvalidBitmapIndexListBoxData)); + + TBool colorIcon( EFalse ); + if ( index == KColorIconFlag ) + { + if ( iExtension->iColorBmp && iExtension->iHiliBmp ) + { + colorIcon = ETrue; + } + index = KColorIconIdx; + } + + if ( !IconArray() ) + { + continue; + } + + if (aHighlight && (index > 0xffff)) + { + index = index >> 16; // we have different icon for highlight + } + + index = index & 0xffff; // mask off possible highlight icon + __ASSERT_DEBUG((index>=0 && indexCount()),Panic(EPanicColumnListInvalidBitmapIndexListBoxData)); + + TAknWindowLineLayout graphicLayout = iExtension->AtSL(subCellIndex).iGraphicLayout; + TAknLayoutRect graphicRect; + + graphicRect.LayoutRect( itemRect,graphicLayout ); + TSize graphicSize( graphicRect.Rect().Size() ); + + if (index>=0 && IconArray()) + { + CGulIcon* icon=(*IconArray())[index]; + CFbsBitmap* bitmap=icon->Bitmap(); + // Sometimes we get fake bitmap... + if ( bitmap ) + { + TSize size( bitmap->SizeInPixels() ); + + if (size.iWidth != graphicSize.iWidth && + size.iHeight != graphicSize.iHeight ) + { + AknIconUtils::SetSize( bitmap, + graphicSize, + EAspectRatioPreservedAndUnusedSpaceRemoved ); + } + + BitBltColored( aGc, aHighlight, icon, column, colorIcon, graphicRect.Rect() ); + } + } + aGc.SetPenStyle(CGraphicsContext::ESolidPen); + } + if ( !redrawPopup && column > 1 ) + { + // column > 1 means that this contact has more than + // one column information to show, for excample name + // and phonenumber. In this case, perhaps need to + // redraw the popupCharacter + redrawPopup = ETrue; + } + } +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi ) + { + aGc.CancelClippingRect(); + transApi->StopDrawing(); + } +#endif //RD_UI_TRANSITION_EFFECTS_LIST + + // When scroll name list quickly using scroll bar, the popup charcter + // will be overlaped by redraw of usrs' phonenumbers, to fix this, + // show the popup charcter after the refresh + if ( redrawPopup ) + { + CPbk2ContactViewListBox* contactViewListBox = static_cast( iExtension->iControl ); + if ( contactViewListBox ) + { + contactViewListBox->HandlePopupCharacter(&aGc, aRect); + } + } + } + + +void CPbk2ContactViewCustomListBoxData::Draw( const TListItemProperties& aItemProperties, + CWindowGc& aGc, + const TDesC* aText, + const TRect& aRect, + TBool aHighlight, + const TColors& aColors, + TInt aItemIndex ) const + { + if ( aHighlight ) + { + iExtension->iClippedColumns = 0; + } + + if ( UsesScalableLayoutData() ) + { + TRAP_IGNORE ( DrawSimpleL( aItemProperties, aGc, aText, aRect, aHighlight, aColors, aItemIndex ) ); + return; + } + + const CFont* font=ColumnFont(0); + CEikonEnv* eikonEnv=CEikonEnv::Static(); + if (font==NULL) + { + font=eikonEnv->NormalFont(); + } + + TInt lastColumn=LastColumn(); + if (lastColumn==KErrNotFound) + { + if ( font ) + { + // use draw text so that dont need to change pen color/style + aGc.UseFont( font ); + aGc.DrawText(TPtrC(),aRect,0); + aGc.DiscardFont(); + } + return; + } + + CEikListBox* listbox = static_cast( iExtension->iControl ); + TBool markingMode = EFalse; + TRect itemRect( aRect ); + + if ( listbox->View() && listbox->View()->ItemDrawer() ) + { + if ( listbox->View()->ItemDrawer()->Flags() + & CListItemDrawer::EMarkingModeEnabled && + iExtension->iMarkingIconArray && + iExtension->iMarkingIconArray->Count() == 2 ) + { + markingMode = ETrue; + itemRect.iTl.iX += + AknLayoutScalable_Avkon::list_single_graphic_pane_t1( 0 ).LayoutLine().il; + } + } + + TInt extraVerticalSpace=(aRect.Height()-font->HeightInPixels()); + TInt baseLineOffset=extraVerticalSpace/2+font->AscentInPixels(); + TRect textRect( itemRect ); + TRect textMRect; // textrect with margins. + textRect.iBr.iX = itemRect.iTl.iX; + TInt column=0; + TPtrC text; + + TRgb aTextColor = aHighlight ? aColors.iHighlightedText : aColors.iText; + + // Turned the drawing to multipass algorithm, because optionalcolumns drawing will + // be too difficult to do without - and this is cleaner solution. + + // pass 1, figures out x-coordinates for columns. + TInt x = itemRect.iTl.iX; + + TBool mirror = AknLayoutUtils::LayoutMirrored(); + if (mirror) + { + x = itemRect.iBr.iX; + } + TInt maxx = x; + while(column <= lastColumn) + { + // order of instructions is important here, do not change. + if (!ColumnIsOptional(column)) + { + TRAP_IGNORE(SetColumnXL(column,maxx)); + + if (!mirror) + x = maxx + ColumnWidthPixel(column); + else + x = maxx - ColumnWidthPixel(column); + + maxx = x; + } + else + { + if (!mirror) + x -= ColumnWidthPixel(column); + else + x += ColumnWidthPixel(column); + + TRAP_IGNORE(SetColumnXL(column,x)); + } + column++; + } + + // pass 2, figures out the end x coordinates + column = 0; + TInt endx; + TInt tmpcolumn; + while(column <= lastColumn) + { + if (!mirror) + endx = ColumnX(column) + ColumnWidthPixel(column); + else + endx = ColumnX(column) - ColumnWidthPixel(column); + + if (!ColumnIsOptional(column)) + { + tmpcolumn = column+1; + while(ColumnIsOptional(tmpcolumn)) + { + TextUtils::ColumnText(text,tmpcolumn,aText); + if (text!=KNullDesC) endx = ColumnX(tmpcolumn); + tmpcolumn++; + } + } + if (!mirror) + { + __ASSERT_DEBUG(ColumnX(column)endx,Panic(EPanicColumnListLayoutErrorListBoxData)); + } + TRAP_IGNORE(SetColumnEndXL(column,endx)); + + column++; + } + + // pass 3 drawing + + // SERIES60 Background drawing. + MAknsSkinInstance *skin = AknsUtils::SkinInstance(); + MAknsControlContext *cc = AknsDrawUtils::ControlContext( Control() ); + if (!cc) + { + cc = SkinBackgroundContext(); + } + +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + + MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( &aGc ); + +#endif // RD_UI_TRANSITION_EFFECTS_LIST + + if ( !listbox || !listbox->BackgroundDrawingSuppressed() ) + { +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi ) + { + transApi->StartDrawing( MAknListBoxTfxInternal::EListView ); + } +#endif // RD_UI_TRANSITION_EFFECTS_LIST + + aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); + aGc.SetPenStyle(CGraphicsContext::ESolidPen); + + if ( listbox ) + { + AknsDrawUtils::Background( skin, cc, listbox, aGc, aRect ); + } + else + { + aGc.Clear(aRect); + } + +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi ) + { + transApi->StopDrawing(); + } +#endif // RD_UI_TRANSITION_EFFECTS_LIST + } + + if ( iExtension->iCurrentRow < listbox->BottomItemIndex() ) + + { + AknListUtils::DrawSeparator( aGc, aRect, aColors.iText, skin ); + } + + // LISTBOX LINES NEED TO BE DRAWN HERE. + DrawHighLight( aGc, aRect, aHighlight, skin ); + +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi ) + { + transApi->StartDrawing( MAknListBoxTfxInternal::EListItem ); + CListBoxView* view = static_cast( iExtension->iControl )->View(); + aGc.SetClippingRect( view->ViewRect() ); + } +#endif // RD_UI_TRANSITION_EFFECTS_LIST + + if ( markingMode && !aItemProperties.IsSelectionHidden() ) + { + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( + aRect, + AknLayoutScalable_Avkon::list_single_graphic_pane_g1( 0 ) ); + + aGc.SetPenColor( aColors.iText ); + aGc.SetPenStyle( CGraphicsContext::ESolidPen ); + + CGulIcon* icon = (*iExtension->iMarkingIconArray)[1]; // unchecked + + if ( listbox->View()->ItemIsSelected( iExtension->iCurrentRow ) ) + { + icon = (*iExtension->iMarkingIconArray)[0]; + } + + CFbsBitmap* bitmap = icon->Bitmap(); + + if ( bitmap ) + { + TSize size( bitmap->SizeInPixels() ); // set size if not already + TSize targetSize( layoutRect.Rect().Size() ); + + if ( size.iWidth != targetSize.iWidth && + size.iHeight != targetSize.iHeight ) + { + AknIconUtils::SetSize( + bitmap, + targetSize, + EAspectRatioPreservedAndUnusedSpaceRemoved ); + } + + aGc.BitBltMasked( layoutRect.Rect().iTl, + bitmap, + TRect( layoutRect.Rect().Size() ), + icon->Mask(), + EFalse ); + } + } + + // The column draw loop + column = 0; + FOREVER + { + if (column > lastColumn) break; + + if (!mirror) + { + textRect.iTl.iX = ColumnX(column); + textRect.iBr.iX = ColumnEndX(column); + } + else + { + textRect.iBr.iX = ColumnX(column); + textRect.iTl.iX = ColumnEndX(column); + } + + TextUtils::ColumnText(text,column,aText); + + TBool exit_condition = textRect.iBr.iX==textRect.iTl.iX; + if (ColumnIsOptional(column) && text == KNullDesC) + { + exit_condition = ETrue; + } + + if (!exit_condition) + { + // Margins support. + TMargins m = ColumnMargins(column); + textMRect.SetRect(textRect.iTl+TSize(m.iLeft,m.iTop),textRect.Size()-TSize(m.iRight+m.iLeft,m.iBottom+m.iTop)); + // end of margins support. + + CGraphicsContext::TTextAlign align=ColumnAlignment(column); + + if (!ColumnIsGraphics(column)) + { + + //if (align == CGraphicsContext::ECenter || align == CGraphicsContext::ERight) + // { + // textMRect.iTl.iX+=1; + // textMRect.iBr.iX+=1; + // } + aGc.SetBrushStyle(CGraphicsContext::ENullBrush); + aGc.SetPenStyle(CGraphicsContext::ESolidPen); + aGc.SetPenColor(aTextColor); + SetUnderlineStyle( aItemProperties, aGc, column ); + + if (aHighlight) + { + aGc.SetPenColor(aColors.iHighlightedText); + aGc.SetBrushColor(aColors.iHighlightedBack); + } + + if (AknsUtils::AvkonSkinEnabled() && iExtension) + { + if (iExtension->iTextColor != NULL) + { + aGc.SetPenColor(iExtension->iTextColor); + } + + if (aHighlight && iExtension->iHighlightedTextColor != NULL) + { + aGc.SetPenColor(iExtension->iHighlightedTextColor); + } + } + + const CFont* rowAndColFont=RowAndColumnFont(iExtension->iCurrentRow,column); + const CFont* colFont=Font(aItemProperties, column); + const CFont* tempFont=(colFont) ? colFont : font; + const CFont* usedFont=(rowAndColFont) ? rowAndColFont : tempFont; + + aGc.UseFont(usedFont); + + // baseline calc needed for each column because of margins. + baseLineOffset = ColumnBaselinePos(column); + if (!baseLineOffset) + { + baseLineOffset = (textMRect.Size().iHeight-usedFont->HeightInPixels())/2 + usedFont->AscentInPixels(); + } + baseLineOffset -= m.iTop; + + // SERIES60 LAF + TBuf<200+KAknBidiExtraSpacePerLine> clipbuf; + + TInt clipgap = ColumnTextClipGap(column); + + TBool clipped = AknBidiTextUtils::ConvertToVisualAndClip( + text.Left(200), + clipbuf, + *usedFont, + textMRect.Size().iWidth, + textMRect.Size().iWidth+clipgap); + + if (clipped) + { + if (!mirror) + { + textMRect.iBr.iX+=clipgap; + } + else + { + textMRect.iTl.iX-=clipgap; + } + + if ( aHighlight ) + { + iExtension->iClippedColumns |= ( 1 << column ); + } + } + + if (ColumnIsNumber(column)) + { + AknTextUtils::LanguageSpecificNumberConversion(clipbuf); + } + + // end of SERIES60 LAF + + CAknMarqueeControl* marquee = + column == 1 || column == 3 ? iExtension->iMarquee : + iExtension->i2ndLineMarquee; + + TBool marqueeDisabled = + listbox->View()->ItemDrawer()->Flags() & CListItemDrawer::EDisableMarquee; + + if ( iExtension->IsMarqueeOn() && aHighlight && clipped && !marqueeDisabled ) + { + // Bidi conversion has already been done. + marquee->UseLogicalToVisualConversion( EFalse ); + + if ( marquee->DrawText( aGc, textMRect, text, baseLineOffset, align, *usedFont ) ) + { + // All the loops have been executed -> the text needs to be truncated. + aGc.DrawText( clipbuf, textMRect, baseLineOffset, align, 0 ); + } + } + else + { + if ( marquee && marqueeDisabled ) + { + marquee->Stop(); + } + + aGc.DrawText( clipbuf, textMRect, baseLineOffset, align, 0 ); + } + + if ( iExtension->iPictoInterface ) + { + iExtension->iPictoInterface->Interface()->DrawPictographsInText( + aGc, *usedFont, clipbuf, textMRect, baseLineOffset, align, 0 ); + } + + aGc.SetUnderlineStyle(EUnderlineOff); // disable underline after first text. + } + else + { + aGc.SetBrushStyle(CGraphicsContext::ENullBrush); + if (aHighlight /*&& (LastColumn()==0) */ ) + { + aGc.SetBrushColor(aColors.iHighlightedBack); + } + + TLex lex(text); + TInt index; + TInt err = lex.Val(index); + __ASSERT_DEBUG(err==KErrNone,Panic(EPanicColumnListInvalidBitmapIndexListBoxData)); + + if ( index == KColorIconFlag ) + { + index = KColorIconIdx; + } + + if ( !err ) + { + if ( !IconArray() ) + { + ++column; + continue; + } + + __ASSERT_DEBUG((index>=0 && indexCount()),Panic(EPanicColumnListInvalidBitmapIndexListBoxData)); + TRect bmpRect; + bmpRect.iTl=textMRect.iTl; + if (index>=0 && IconArray()) + { + CGulIcon* icon=(*IconArray())[index]; + + if ( iExtension + && iExtension->iSubCellIconSize[column] != TSize(0,0) ) + { + TSize wanted( iExtension->iSubCellIconSize[column] ); + TSize got( icon->Bitmap()->SizeInPixels() ); + + // correct w or h is enough + if ( wanted.iWidth != got.iWidth + && wanted.iHeight != got.iHeight ) + { + AknIconUtils::SetSize( icon->Bitmap(), + wanted, + EAspectRatioPreservedAndUnusedSpaceRemoved ); + } + } + + CFbsBitmap* bitmap=icon->Bitmap(); + + TSize size(bitmap->SizeInPixels()); + + // next two lines are SERIES60 additions + if (size.iWidth>textMRect.Size().iWidth) size.iWidth = textMRect.Size().iWidth; + if (size.iHeight>textMRect.Size().iHeight) size.iHeight = textMRect.Size().iHeight; + + TPoint bmpPos(textMRect.iTl); // was aRect, I dunno why + bmpPos.iY+=(textMRect.Height()-size.iHeight)>>1; // was aRect too... + switch (align) + { + case ELeft: + break; + case ECenter: + bmpPos.iX+=(textMRect.Width()-size.iWidth)>>1; + break; + case ERight: + bmpPos.iX=textMRect.iBr.iX-size.iWidth; + break; + } + bmpRect.SetRect(bmpPos,size); + TPoint posInBitmap; + posInBitmap += bitmap->SizeInPixels() - textMRect.Size(); + posInBitmap.iX >>= 1; + posInBitmap.iY >>= 1; + if (posInBitmap.iX < 0) posInBitmap.iX = 0; + if (posInBitmap.iY < 0) posInBitmap.iY = 0; + TRect rect(posInBitmap,textMRect.Size()); + + + if (icon->Mask()) + { + aGc.BitBltMasked( bmpPos, bitmap, rect, icon->Mask(), ETrue ); + } + else + { + aGc.BitBlt(bmpPos, bitmap,rect); + } + } + aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); + aGc.SetPenStyle(CGraphicsContext::ESolidPen); + } + } + } + + ++column; + } + +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + if ( transApi ) + { + aGc.CancelClippingRect(); + transApi->StopDrawing(); + } +#endif //RD_UI_TRANSITION_EFFECTS_LIST + } + + +void CPbk2ContactViewCustomListBoxData::AddColumnL(TInt aColumn) +// +// Add a column's worth of data +// + { + SColumn column; + column.iColumn=aColumn; + column.iWidth=0; + TMargins m = {0,0,0,0}; + column.iMargins=m; + column.iBaseFont=NULL; + column.iActualFontIndex=KNoActualColumnFont; + column.iGraphics=EFalse; + column.iNumberColumn = EFalse; + column.iOptional=EFalse; + column.iBaseline = 0; + column.iAlign=CGraphicsContext::ELeft; + column.iSeparator=CGraphicsContext::ENullPen; + column.iTextClipGap = 0; + TKeyArrayFix key(0,ECmpTInt); + iColumnArray->InsertIsqL(column,key); + } + +CPbk2ContactViewCustomListBoxData::SColumn& CPbk2ContactViewCustomListBoxData::At(TInt aArrayIndex) +// +// Return a column of data +// + { + __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndexCount(),Panic(EPanicPreCond_OutOfRangeListBoxData)); + return(iColumnArray->At(aArrayIndex)); + } + +const CPbk2ContactViewCustomListBoxData::SColumn& CPbk2ContactViewCustomListBoxData::At(TInt aArrayIndex) const +// +// Return a column of data +// + { + __ASSERT_DEBUG(aArrayIndex>=0 && aArrayIndexCount(),Panic(EPanicPreCond_OutOfRangeListBoxData)); + return(iColumnArray->At(aArrayIndex)); + } + +TBool CPbk2ContactViewCustomListBoxData::FindColumnIndex(TInt& aArrayIndex,TInt aColumn) const +// +// Find a column if it has been set +// + { + if (aColumn<0 || iColumnArray->Count()==0) + return EFalse; + TKeyArrayFix key(0,ECmpTInt); + SColumn column; + column.iColumn=aColumn; + + // Returns zero if key was found, otherwise non-zero + TInt ret = iColumnArray->FindIsq(column,key,aArrayIndex); + return (ret ? EFalse: ETrue); + } + +void CPbk2ContactViewCustomListBoxData::FindColumnIndexOrAddL(TInt& aArrayIndex,TInt aColumn) +// +// Find a column or add it +// + { + if (!FindColumnIndex(aArrayIndex,aColumn)) + { + AddColumnL(aColumn); + FindColumnIndex(aArrayIndex,aColumn); + } + } + +TInt CPbk2ContactViewCustomListBoxData::AddActualFontL(const CFont* aBaseFont) + { + if (!iNormalFont.iFonts) + { + iNormalFont.iFonts=new (ELeave) CArrayPtrFlat (1); + iBoldFont.iFonts=new (ELeave) CArrayPtrFlat (1); + iItalicFont.iFonts=new (ELeave) CArrayPtrFlat (1); + iBoldItalicFont.iFonts=new (ELeave) CArrayPtrFlat (1); + } + + // Reserves extra space for each font array. + TInt fontCount=iNormalFont.iFonts->Count()+1; + iNormalFont.iFonts->SetReserveL(fontCount); + iBoldFont.iFonts->SetReserveL(fontCount); + iItalicFont.iFonts->SetReserveL(fontCount); + iBoldItalicFont.iFonts->SetReserveL(fontCount); + + // Add Fonts. + TFontStyle style=aBaseFont->FontSpecInTwips().iFontStyle; + ConstructFontL(aBaseFont, style, iNormalFont); + ConstructFontL(aBaseFont, style, iBoldFont); + ConstructFontL(aBaseFont, style, iItalicFont); + ConstructFontL(aBaseFont, style, iBoldItalicFont); + + return fontCount-1; + } + +TBool CPbk2ContactViewCustomListBoxData::MakeColumnRect( TInt aColumn, TRect& aRect ) + // Returns given column rect + { + TInt lastColumn = LastColumn(); + if ( ( aColumn < 0 ) || ( aColumn > lastColumn ) ) return EFalse; + + TRect colRect(aRect); // we need to save original item rect + for ( TInt column=0; columnFindRowAndColumnIndexOrAddL(index,aRow,aColumn); + iExtension->At(index).iFont=aFont; + } + +const CFont* +CPbk2ContactViewCustomListBoxData::RowAndColumnFont(TInt aRow,TInt aColumn) const + { + if (!iExtension) return 0; + TInt index = 0; + if (iExtension->FindRowAndColumnIndex(index,aRow,aColumn)!=0) + return 0; + return(iExtension->At(index).iFont); + } + +void CPbk2ContactViewCustomListBoxData::SetCurrentItemIndex(TInt aIndex) + { + if( iExtension->iCurrentRow != aIndex ) + { + iExtension->iAnimFlags.Set( CPbk2ContactViewCustomListBoxDataExtension::EFlagUpdateBg ); + } + iExtension->iCurrentRow = aIndex; + } + + +// --------------------------------------------------------------------------- +// Wraps the text drawing functinality with & without marquee into one +// function, so that inherited classes can modify their own drawing +// behaviour more easily. +// --------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::DrawText( + CWindowGc& aGc, + const TRect& aTextRect, + const TDesC& aText, + const TDesC& aClippedText, + const TInt aBaselineOffset, + const CGraphicsContext::TTextAlign aAlign, + const CFont& aFont, + const TBool aHighlight, + const TBool aIsTextClipped ) const + { + TBool marqueeDisabled = + static_cast( + Control() )->View()->ItemDrawer()->Flags() & CListItemDrawer::EDisableMarquee; + + if ( iExtension->IsMarqueeOn() && aHighlight && aIsTextClipped && !marqueeDisabled ) + { + if ( iExtension->iMarquee->DrawText( aGc, aTextRect, aText, aBaselineOffset, aAlign, aFont ) ) + { + // All the loops have been executed -> the text needs to be truncated. + aGc.DrawText( aClippedText, aTextRect, aBaselineOffset, aAlign, 0 ); + } + } + else + { + if ( iExtension->iMarquee && marqueeDisabled ) + { + iExtension->iMarquee->Stop(); + } + + aGc.DrawText( aClippedText, aTextRect, aBaselineOffset, aAlign, 0 ); + } + } + + +void CPbk2ContactViewCustomListBoxData::SetMarqueeParams(const TInt aLoops, const TInt aScrollAmount, const TInt aScrollDelay) + { + if ( iExtension->iMarquee ) + { + iExtension->iMarquee->SetLoops( aLoops ); + iExtension->iMarquee->SetSpeedInPixels( aScrollAmount ); + iExtension->iMarquee->SetDelay( aScrollDelay ); + } + if ( iExtension->i2ndLineMarquee ) + { + iExtension->i2ndLineMarquee->SetLoops( aLoops ); + iExtension->i2ndLineMarquee->SetSpeedInPixels( aScrollAmount ); + iExtension->i2ndLineMarquee->SetDelay( aScrollDelay ); + } + } + +void CPbk2ContactViewCustomListBoxData::SetMarqueeParams(const TInt aLoops, const TInt aScrollAmount, + const TInt aScrollDelay, const TInt aInterval) + { + if ( iExtension->iMarquee ) + { + iExtension->iMarquee->SetInterval( aInterval ); + iExtension->i2ndLineMarquee->SetInterval( aInterval ); + SetMarqueeParams( aLoops, aScrollAmount, aScrollDelay ); + } + } + + + +void CPbk2ContactViewCustomListBoxData::SetSubCellIconSize(TInt aIndex, TSize aSize) + { + if (iExtension && aIndex < 6 && aIndex >= 0) + { + iExtension->iSubCellIconSize[aIndex] = aSize; + } + } + +TSize CPbk2ContactViewCustomListBoxData::GetSubCellIconSize(TInt aIndex) + { + if (iExtension && aIndex < 6 && aIndex >= 0) + { + return iExtension->iSubCellIconSize[aIndex]; + } + return TSize(0,0); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::HighlightAnim +// ----------------------------------------------------------------------------- +// +const CAknsEffectAnim* CPbk2ContactViewCustomListBoxData::HighlightAnim() const + { + if( iExtension ) + return iExtension->iAnimation; + return NULL; + } + +// ----------------------------------------------------------------------------- +// AboutToDrawHighlightAnim +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::AboutToDrawHighlightAnim() const + { + if( !iExtension ) + { + return; + } + if( !iExtension->iAnimation || !iExtension->iControl ) + { + return; + } + + CEikListBox* list = static_cast( iExtension->iControl ); + CListBoxView* view = list->View(); + if( !view ) + { + return; + } + + if( view->CurrentItemIndex() != iExtension->iCurrentRow ) + { + iExtension->iAnimFlags.Set( CPbk2ContactViewCustomListBoxDataExtension::EFlagUpdateBg ); + iExtension->iCurrentRow = view->CurrentItemIndex(); + } + + iExtension->SyncAnim( iExtension->iAnimSize ); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetHighlightAnimBackgroundDrawer +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::SetHighlightAnimBackgroundDrawer( + MColumnListBoxAnimBackgroundDrawer* aDrawer ) + { + if( iExtension ) + { + iExtension->iHighlightBgDrawer = aDrawer; + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetItemCellSize +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::SetItemCellSize( const TSize& aSizeInPixels ) + { + if( iExtension ) + { + if( iExtension->iAnimSize != aSizeInPixels ) + { + iExtension->Play(); + } + iExtension->iAnimSize = aSizeInPixels; + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::HasHighlightAnim +// ----------------------------------------------------------------------------- +// +TBool CPbk2ContactViewCustomListBoxData::HasHighlightAnim() const + { + if( !iExtension ) + return EFalse; + if( !iExtension->iAnimation ) + return EFalse; + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::DrawHighlightAnim +// ----------------------------------------------------------------------------- +// +TBool CPbk2ContactViewCustomListBoxData::DrawHighlightAnim( + CBitmapContext& aGc, const TRect& aRect ) const + { + if( !iExtension ) + return EFalse; + + if( !iExtension->iAnimation ) + return EFalse; + + return iExtension->SyncAndDrawAnim( aGc, aRect ); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::FocusGained +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::FocusGained() + { + iExtension->FocusGained(); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::FocusLost +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::FocusLost() + { + iExtension->FocusLost(); + } + +void CPbk2ContactViewCustomListBoxData::HandleResourceChange( TInt aType ) + { + // Animation is skin dependent, whenever skin changes animation changes + // too. + if( KAknsMessageSkinChange == aType ) + { + TRAP_IGNORE( iExtension->SkinChangedL() ); + + } + else if(aType == KEikDynamicLayoutVariantSwitch) + { + // What is under highlight may have changed -> we need to update + // highlight background to animation. + iExtension->iAnimFlags.Set( CPbk2ContactViewCustomListBoxDataExtension::EFlagUpdateBg ); + } + } + +void CPbk2ContactViewCustomListBoxData::SetupSkinContextL() + { + __ASSERT_DEBUG( iExtension, Panic( EPanicNullPointerListBoxData )); + + TRect mainPane; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPane ); + + TRect mainPaneRect( mainPane.Size() ); + + if ( !iExtension->iSkinControlContext ) + { + iExtension->iSkinControlContext = CAknsListBoxBackgroundControlContext::NewL( + KAknsIIDQsnBgAreaMainListGene, + mainPaneRect, + EFalse, + KAknsIIDQsnBgColumnA, + mainPaneRect ); + + iExtension->iSkinHighlightFrameId = &KAknsIIDQsnFrList; + iExtension->iSkinHighlightFrameCenterId = &KAknsIIDQsnFrListCenter; + } + else + { + iExtension->iSkinControlContext->SetRect( mainPaneRect ); + } + } + +void CPbk2ContactViewCustomListBoxData::SetESSTextColor(TRgb aTextColor) + { + if (iExtension) + iExtension->iTextColor = aTextColor; + } + +void CPbk2ContactViewCustomListBoxData::SetESSHighlightedTextColor(TRgb aHighlightedTextColor) + { + if (iExtension) + iExtension->iHighlightedTextColor = aHighlightedTextColor; + } + +void CPbk2ContactViewCustomListBoxData::SetColumnUnderlined( TBitFlags32 aUnderlinedColumns ) + { + if ( iExtension ) + { + iExtension->iUnderlineFlagSet = ETrue; + iExtension->iUnderlineFlags = aUnderlinedColumns; + } + } + +void CPbk2ContactViewCustomListBoxData::SetUnderlineStyle( TListItemProperties aProperties, + CWindowGc& aGc, + TInt aColumn ) const + { + if ( !iExtension ) + { + return; + } + + if ( !iExtension->iUnderlineFlagSet ) + { + // underlining is already either on or off and + // hardcoded off turning will ensure old style + // behaviour + return; + } + + if ( aProperties.IsUnderlined() + && iExtension->iUnderlineFlagSet + && iExtension->iUnderlineFlags.IsSet( aColumn ) ) + { + aGc.SetUnderlineStyle( EUnderlineOn ); + } + else + { + aGc.SetUnderlineStyle( EUnderlineOff ); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::ResetSLSubCellArray +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::ResetSLSubCellArray() + { + if ( !iExtension ) + { + return; + } + + iExtension->iMarginRect = TRect::EUninitialized; + if ( iExtension && iExtension->iUseLayoutData ) + { + iExtension->iUseLayoutData = EFalse; + CListBoxView* view = static_cast( iExtension->iControl )->View(); + MAknListBoxTfxInternal* transApi = + CAknListLoader::TfxApiInternal( view->ItemDrawer()->Gc() ); + if ( transApi ) + { + transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, TPoint( 0, 0 ) ); + transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin, TPoint( 0, 0 ) ); + } + } + iExtension->ResetSLSubCellArray(); + // This function gets called always when size changes, so here is called + // SetupSkinContextL to update the layout rect of the background skin + // context (mainpane rect can change for example if toolbar is hidden. + TRAP_IGNORE( SetupSkinContextL() ); + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetGraphicSubCellL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::SetGraphicSubCellL(TInt aSubCell, + const TAknWindowLineLayout &aGraphicLayout) + { + if (!iExtension) return; + TInt index = 0; + iExtension->FindSLSubCellIndexOrAddL(index,aSubCell); + iExtension->AtSL(index).iTextLayout=NULL; + iExtension->AtSL(index).iGraphicLayout=aGraphicLayout; + iExtension->AtSL(index).iSubCellType=CPbk2ContactViewCustomListBoxDataExtension::EEikSLGraphic; + + // needed for compatibility + CEikColumnListBox* list = static_cast( iExtension->iControl ); + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( list->View()->ItemDrawer()->ItemCellSize(), aGraphicLayout ); + TRect rect( layoutRect.Rect() ); + + SetSubCellIconSize( aSubCell, rect.Size() ); + SetColumnWidthPixelL( aSubCell, rect.Width() ); + SetGraphicsColumnL( aSubCell, ETrue ); + SetColumnXL( aSubCell, rect.iTl.iX ); + SetColumnEndXL( aSubCell, rect.iBr.iX ); + iExtension->iUseLayoutData=ETrue; // might go to own method... + if ( iExtension->iMarginRect == TRect::EUninitialized ) + { + iExtension->iMarginRect = rect; + } + else + { + iExtension->iMarginRect.BoundingRect( rect ); + } +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + MAknListBoxTfxInternal* transApi = + CAknListLoader::TfxApiInternal( list->View()->ItemDrawer()->Gc() ); + if ( transApi ) + { + transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, iExtension->iMarginRect.iTl ); + TSize size = list->View()->ItemDrawer()->ItemCellSize(); + TPoint br( size.AsPoint() - iExtension->iMarginRect.iBr ); + transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin, + br ); + } +#endif + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetTextSubCellL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::SetTextSubCellL(TInt aSubCell, + const TAknTextLineLayout &aTextLayout) + { + if (!iExtension) return; + TInt index = 0; + iExtension->FindSLSubCellIndexOrAddL(index,aSubCell); + iExtension->AtSL(index).iTextLayout=aTextLayout; + iExtension->AtSL(index).iGraphicLayout=NULL; + iExtension->AtSL(index).iSubCellType=CPbk2ContactViewCustomListBoxDataExtension::EEikSLText; + + // needed for compatibility + CEikColumnListBox* list = static_cast( iExtension->iControl ); + TAknLayoutText textLayout; + textLayout.LayoutText( list->View()->ItemDrawer()->ItemCellSize(), aTextLayout ); + TRect rect( textLayout.TextRect() ); + + SetColumnWidthPixelL( aSubCell, rect.Width() ); + SetColumnFontL( aSubCell, textLayout.Font() ); + SetColumnXL( aSubCell, rect.iTl.iX ); + SetColumnEndXL( aSubCell, rect.iBr.iX ); + SetColumnBaselinePosL( aSubCell, aTextLayout.iB ); + iExtension->iUseLayoutData=ETrue; // might go to own method... + if ( iExtension->iMarginRect == TRect::EUninitialized ) + { + iExtension->iMarginRect = rect; + } + else + { + iExtension->iMarginRect.BoundingRect( rect ); + } +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + MAknListBoxTfxInternal* transApi = + CAknListLoader::TfxApiInternal( list->View()->ItemDrawer()->Gc() ); + if ( transApi ) + { + transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, iExtension->iMarginRect.iTl ); + TSize size = list->View()->ItemDrawer()->ItemCellSize(); + TPoint br( size.AsPoint() - iExtension->iMarginRect.iBr ); + transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin, + br ); + } +#endif + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetConditionalSubCellL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::SetConditionalSubCellL(TInt aSubCell, + const TAknTextLineLayout &aTextLayout, + TInt aAffectedSubCell) + { + // iConditionValue of affected subcell (=text subcell, which has different layouts) + // contains index of graphical subcell, which existence should be checked first. + // This graphical subcell has in iConditionValue index of graphical subcell, + // which existence should be checked second etc. Each graphical subcell can + // affect only to 1 text subcell (or none). + + // for compabitility - needed at least for text wrapping + SetOptionalColumnL( aSubCell, ETrue ); + if (!iExtension) return; + + TInt i = 0x01; + i = i << aSubCell; + iExtension->iConditionalCells = iExtension->iConditionalCells | i; + + TInt graphicalIndex = 0; + if (iExtension->FindSLSubCellIndex(graphicalIndex, aSubCell)!=0) return; // subcell not found + // conditional layoutline can be only added to graphical subcells + if (iExtension->AtSL(graphicalIndex).iSubCellType!=CPbk2ContactViewCustomListBoxDataExtension::EEikSLGraphic) return; + + TInt textIndex = 0; // index of affected subcell + if (iExtension->FindSLSubCellIndex(textIndex, aAffectedSubCell)!=0) return; // subcell not found + // affected subcell can only be text subcell + if (iExtension->AtSL(textIndex).iSubCellType==CPbk2ContactViewCustomListBoxDataExtension::EEikSLGraphic) return; + + TInt gSC = iExtension->AtSL(textIndex).iConditionValue; // text subcell to be added in priority chain + + while (gSC > -1) + { + if (iExtension->FindSLSubCellIndex(textIndex, gSC)!=0) return; // subcell not found + gSC = iExtension->AtSL(textIndex).iConditionValue; + } + iExtension->AtSL(textIndex).iConditionValue = aSubCell; // add next subcell to chain + iExtension->AtSL(graphicalIndex).iTextLayout=aTextLayout; + iExtension->CreateColorBitmapsL(); + + CEikColumnListBox* list = static_cast( iExtension->iControl ); + TAknLayoutText textLayout; + textLayout.LayoutText( list->View()->ItemDrawer()->ItemCellSize(), aTextLayout ); + + if ( iExtension->iMarginRect == TRect::EUninitialized ) + { + iExtension->iMarginRect = textLayout.TextRect(); + } + else + { + iExtension->iMarginRect.BoundingRect( textLayout.TextRect() ); + } +#ifdef RD_UI_TRANSITION_EFFECTS_LIST + MAknListBoxTfxInternal* transApi = + CAknListLoader::TfxApiInternal( list->View()->ItemDrawer()->Gc() ); + if ( transApi ) + { + transApi->SetPosition( MAknListBoxTfxInternal::EListTLMargin, iExtension->iMarginRect.iTl ); + TSize size = list->View()->ItemDrawer()->ItemCellSize(); + TPoint br( size.AsPoint() - iExtension->iMarginRect.iBr ); + transApi->SetPosition( MAknListBoxTfxInternal::EListBRMargin, + br ); + } +#endif + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetStretchableGraphicSubCellL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::SetStretchableGraphicSubCellL( + TInt aSubCell, + const TAknWindowComponentLayout& aNormalLayout, + const TAknWindowComponentLayout& aStretchedLayout ) + { + if ( Layout_Meta_Data::IsLandscapeOrientation() && + Layout_Meta_Data::IsListStretchingEnabled() && + StretchingEnabled() ) + { + SetGraphicSubCellL( aSubCell, aStretchedLayout.LayoutLine() ); + } + else + { + SetGraphicSubCellL( aSubCell, aNormalLayout.LayoutLine() ); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetStretchableTextSubCellL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::SetStretchableTextSubCellL( + TInt aSubCell, + const TAknTextComponentLayout& aNormalLayout, + const TAknTextComponentLayout& aStretchedLayout ) + { + if ( Layout_Meta_Data::IsLandscapeOrientation() && + Layout_Meta_Data::IsListStretchingEnabled() && + StretchingEnabled() ) + { + SetTextSubCellL( aSubCell, aStretchedLayout.LayoutLine() ); + } + else + { + SetTextSubCellL( aSubCell, aNormalLayout.LayoutLine() ); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetStretchableConditionalSubCellL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::SetStretchableConditionalSubCellL( + TInt aSubCell, + const TAknTextComponentLayout& aNormalLayout, + const TAknTextComponentLayout& aStretchedLayout, + TInt aNormalSubCell, + TInt aStretchedSubCell ) + { + if ( Layout_Meta_Data::IsLandscapeOrientation() && + Layout_Meta_Data::IsListStretchingEnabled() && + StretchingEnabled() ) + { + SetConditionalSubCellL( aSubCell, aStretchedLayout.LayoutLine(), aStretchedSubCell ); + } + else + { + SetConditionalSubCellL( aSubCell, aNormalLayout.LayoutLine(), aNormalSubCell ); + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::UsesScalableLayoutData +// ----------------------------------------------------------------------------- +// +TBool CPbk2ContactViewCustomListBoxData::UsesScalableLayoutData() const + { + if (iExtension) + return iExtension->iUseLayoutData; + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::EnableStretching +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::EnableStretching( const TBool aEnabled ) + { + if ( !iExtension ) + { + return; + } + + iExtension->iStretchingEnabled = aEnabled; + } + +#ifdef RD_LIST_STRETCH +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::StretchingEnabled +// ----------------------------------------------------------------------------- +// +TBool CPbk2ContactViewCustomListBoxData::StretchingEnabled() const + { + if ( !iExtension ) + { + return EFalse; + } + + return iExtension->iStretchingEnabled; + } + +#else +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::StretchingEnabled +// ----------------------------------------------------------------------------- +// +TBool CPbk2ContactViewCustomListBoxData::StretchingEnabled() const + { + return EFalse; + } + +#endif // RD_LIST_STRETCH + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::CheckIfSubCellsIntersectL +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::CheckIfSubCellsIntersectL( + TAknTextLineLayout* aLayouts, + TBool* aResults, + const TDesC& aText, + const TRect& aItemRect ) const + { + TInt column = 0; + TInt column2; + TInt subCellIndex; + TInt subCellIndex2; + TInt lastColumn = Min( LastColumn(), KMaxColumn ); + TPtrC text; + TBool isEmpty[KMaxColumn]; + + // cache the empty text states + while ( ETrue ) + { + if ( column > lastColumn ) + { + break; + } + + TextUtils::ColumnText( text, column, &aText ); + + if ( text == KNullDesC || ColumnIsOptional( column ) ) + { + isEmpty[column] = ETrue; + } + else + { + isEmpty[column] = EFalse; + } + + ++column; + } + + column = 0; + + while ( ETrue ) + { + if ( column > lastColumn ) + { + break; + } + + if ( iExtension->FindSLSubCellIndex( subCellIndex, column ) != 0 ) + { + break; + } + + if ( isEmpty[column] ) + { + ++column; + continue; + } + + TRect bRect( ColumnX( column ), 0, ColumnEndX( column ), 10 ); + + for ( column2 = column + 1; column2 <= lastColumn; column2++ ) + { + if ( isEmpty[column2] ) + { + continue; + } + + if ( iExtension->FindSLSubCellIndex( subCellIndex2, column2 ) != 0 ) + { + break; + } + + TRect bRect2( ColumnX( column2 ), 0, ColumnEndX( column2 ), 10 ); + + if ( bRect.Intersects( bRect2 ) ) + { + aResults[column] = ETrue; + + if ( !AknLayoutUtils::LayoutMirrored() ) + { + bRect.iBr.iX = bRect2.iTl.iX; + } + else + { + bRect.iTl.iX = bRect2.iBr.iX; + } + } + } + + if ( aResults[column] ) + { + if ( iExtension->AtSL( subCellIndex ).iSubCellType == CPbk2ContactViewCustomListBoxDataExtension::EEikSLText ) + { + TAknTextLineLayout textLine = iExtension->AtSL( subCellIndex ).iTextLayout; + + textLine.iW = bRect.Width(); + + if ( !AknLayoutUtils::LayoutMirrored() ) + { + textLine.ir = aItemRect.iBr.iX - bRect.iBr.iX; + } + else + { + textLine.il = bRect.iTl.iX - aItemRect.iTl.iX; + } + + aLayouts[column] = textLine; + } + } + + ++column; + } + } + +// ----------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SubCellsMightIntersect +// ----------------------------------------------------------------------------- +// +void CPbk2ContactViewCustomListBoxData::SubCellsMightIntersect( const TBool aMightIntersect ) + { + iExtension->iSubCellsMightIntersect = aMightIntersect; + } + +void CPbk2ContactViewCustomListBoxDataExtension::CreateColorBitmapsL() + { + /* size calculation relies on fact, that currently all additional + * icons in column lists are same size. Size could be calculated + * from sizes availble in setconditionalsubcelll(), but that would + * be too unreliable. And there is no way to calculate size of + * icons created by symbian's old api. + */ + TRect mainPane; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPane ); + TAknLayoutRect r; + r.LayoutRect( mainPane, AknLayoutScalable_Avkon::listscroll_gen_pane(0) ); + r.LayoutRect( r.Rect(), AknLayoutScalable_Avkon::list_gen_pane(0) ); + r.LayoutRect( r.Rect(), AknLayoutScalable_Avkon::list_single_pane(0) ); + r.LayoutRect( r.Rect(), AknLayoutScalable_Avkon::list_single_pane_g1(0) ); + TSize aSize = r.Rect().Size(); + + TRgb color, hiliColor; + TInt error; + // icon #13 main area additional list icons #215 + // icon #16 list highlight additional list iconsform checkbox, radio button #215 + + error = AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), + color, + KAknsIIDQsnIconColors, + EAknsCIQsnIconColorsCG13 ); + if ( error ) + { + return; + } + error = AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), + hiliColor, + KAknsIIDQsnIconColors, + EAknsCIQsnIconColorsCG16 ); + if ( error ) + { + return; + } + + if ( iColorBmp && iColorBmp->SizeInPixels() == aSize + && color == iIconColor && hiliColor == iHiliIconColor ) + { + return; + } + + iIconColor = color; + iHiliIconColor = hiliColor; + + if ( !iColorBmp ) + { + iColorBmp = new( ELeave ) CFbsBitmap(); + iColorBmp->Create( aSize, CCoeEnv::Static()->ScreenDevice()->DisplayMode() ); + } + else if ( iColorBmp->SizeInPixels() != aSize ) + { + iColorBmp->Resize( aSize ); + } + if ( !iHiliBmp ) + { + iHiliBmp = new( ELeave ) CFbsBitmap(); + iHiliBmp->Create( aSize, CCoeEnv::Static()->ScreenDevice()->DisplayMode() ); + } + else if ( iHiliBmp->SizeInPixels() != aSize ) + { + iHiliBmp->Resize( aSize ); + } + + CFbsBitGc* fbsBitGc = CFbsBitGc::NewL(); + CleanupStack::PushL( fbsBitGc ); + + CFbsBitmapDevice* bmpDevice = CFbsBitmapDevice::NewL( iColorBmp ); + CleanupStack::PushL( bmpDevice ); + fbsBitGc->Activate( bmpDevice ); + fbsBitGc->SetPenStyle(CGraphicsContext::ENullPen); + fbsBitGc->SetBrushStyle(CGraphicsContext::ESolidBrush); + fbsBitGc->SetBrushColor( color ); + fbsBitGc->Clear(); + CleanupStack::PopAndDestroy( bmpDevice ); + bmpDevice = NULL; + + bmpDevice = CFbsBitmapDevice::NewL( iHiliBmp ); + CleanupStack::PushL( bmpDevice ); + fbsBitGc->Activate( bmpDevice ); + fbsBitGc->SetPenStyle(CGraphicsContext::ENullPen); + fbsBitGc->SetBrushStyle(CGraphicsContext::ESolidBrush); + fbsBitGc->SetBrushColor( hiliColor ); + fbsBitGc->Clear(); + CleanupStack::PopAndDestroy( bmpDevice ); + bmpDevice = NULL; + + CleanupStack::PopAndDestroy( fbsBitGc ); + } + + +TUint32 CPbk2ContactViewCustomListBoxData::CurrentItemTextWasClipped() const + { + return iExtension ? iExtension->iClippedColumns : 0; + } + +TBool CPbk2ContactViewCustomListBoxData::KineticScrollingEnabled() const + { + if ( iExtension ) + { + return iExtension->iKineticScrolling; + } + return EFalse; + } + +//Start of Code Added for PhoneBook2 +// --------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetDataModel, sets the internal PCS data model. +// --------------------------------------------------------------------------- +void CPbk2ContactViewCustomListBoxData::SetDataModel(CPbk2ContactViewListBoxModel* aDataModel) + { + iDataModel = aDataModel; + iPsHandler = iDataModel->PSHandler(); + } + +// --------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::DrawEnhancedTextL, sets the internal PCS data model. +// --------------------------------------------------------------------------- +void CPbk2ContactViewCustomListBoxData::DrawEnhancedTextL( + const TListItemProperties& aItemProperties, + CWindowGc& aGc, + const TRect& aRect, + const TDesC& aTextToDraw, + const TPtrC& aText, + TAknLayoutText &aTextLayout, + TAknTextLineLayout &aTextLineLayout, + TBool aUseLogicalToVisualConversion, + const CFont* aUsedFont, + TRgb aTextColor + ) const + { + TRect layoutedRect( aRect ); + RArray searchMatches; + TInt currentChar(0); + TInt charactersToNextMatch(0); + TBool mirroredInput( EFalse ); + HBufC* visualBuf = NULL; + TPtrC text( aTextToDraw ); + TBool textClipped (EFalse); + TPtrC textForPSEngine (aTextToDraw); + + // Get current matches + // Data model should be always initialized in not NULL value + // This query supports bidirectional order + CPsQuery* queryData = NULL; + TRAP_IGNORE(queryData = const_cast(iDataModel->LastPCSQuery()) ); + if (queryData && queryData->Count() > 0) + { + + //Find the clipped text that will fit into the layout + //we need to perform our underline operation on this clipped text + if ( aTextToDraw.Length() ) + { + visualBuf = HBufC::NewLC( aTextToDraw.Length() + KAknBidiExtraSpacePerLine ); + + // In OOM, logical to visual conversion is not performed... + + if ( visualBuf ) + { + *visualBuf = aTextToDraw; // copy + TPtr ptr = visualBuf->Des(); + TInt maxWidth = aTextLayout.TextRect().Size().iWidth; + + // Logical to visual conversion. + textClipped = AknBidiTextUtils::ConvertToVisualAndClip( + aText, + ptr, + *aUsedFont, + maxWidth, + maxWidth ); + + if ( textClipped ) + { + //Remove the ellipsis and pass the text to the PS Engine + text.Set( ptr.Left( ptr.Length() - 1 ) ); + } + else + { + text.Set( ptr ); + } + } + } + + // Check if we have mirrored input + // It is possible to have mixed input in search string. Always ask repository file to get + // correct input language + TInt inputLang = 0; + CRepository* centRep = NULL; + TRAPD(leavecode, centRep = CRepository::NewL( KCRUidAknFep ) ); + if( leavecode == KErrNone) + { + centRep->Get( KAknFepInputTxtLang, inputLang ); + } + delete centRep; + + mirroredInput = ( inputLang == ELangArabic || + inputLang == ELangHebrew || + inputLang == ELangFarsi); + + // We will suggest that memory is enough + if (mirroredInput) + { + // temporary solution + // PCS LookupLmethod doesn't work correctly for + // bidirectional languages + iDataModel->GetMatchingPartsL(text, searchMatches); + } + else + { + CDesCArray* matchSeq = new( ELeave ) CDesCArrayFlat(2); + TRAP_IGNORE(iPsHandler->LookupL( *queryData, text, *matchSeq, searchMatches) ); + delete matchSeq; + } + if( searchMatches.Count() ) + { + TLinearOrder byStartIndex( CompareByStartIndex ); + searchMatches.Sort( byStartIndex ); + } + + + if( mirroredInput ) + { + currentChar = text.Length(); //aTextToDraw.Length(); + //TInt originalLayoutTlX( textMRect.iTl.iX ) + layoutedRect.iTl.iX = layoutedRect.iBr.iX; + for( TInt i = 0 ; i < searchMatches.Count(); i++ ) + { + #ifdef _DEBUG + TPsMatchLocation& location = searchMatches[i]; + RDebug::Print(_L("%S: searchMatch[%d] = (%d,%d), direction %d"), &text, i, + location.index, + location.length, location.direction ); + #endif //_DEBUG + searchMatches[i].index = Min( text.Length(), searchMatches[i].index ); + searchMatches[i].length = Min( text.Length() - searchMatches[i].index, + searchMatches[i].length); + } + if( !aItemProperties.IsSelectionHidden() ) + { + for( TInt i=searchMatches.Count()-1 ; i>=0 ; i-- ) + { + charactersToNextMatch = currentChar - ( searchMatches[i].index + searchMatches[i].length ); + if( charactersToNextMatch > 0 ) + { + layoutedRect.iTl.iX -= AknBidiTextUtils::MeasureTextBoundsWidth( *aUsedFont, + text.Mid( currentChar-charactersToNextMatch, + charactersToNextMatch ), + CFont::TMeasureTextInput::EFVisualOrder ); + //aGc.DrawText(convBuf.Mid(currentChar - charactersToNextMatch, charactersToNextMatch),layoutedRect,baseLineOffset, align, 0); + aTextLayout.LayoutText( layoutedRect, aTextLineLayout, aUsedFont ); + aTextLayout.DrawText( aGc, text.Mid(currentChar - charactersToNextMatch, charactersToNextMatch), aUseLogicalToVisualConversion, aTextColor ); + currentChar -= charactersToNextMatch; + } + layoutedRect.iTl.iX -= AknBidiTextUtils::MeasureTextBoundsWidth( *aUsedFont, + text.Mid( searchMatches[i].index, + searchMatches[i].length ), + CFont::TMeasureTextInput::EFVisualOrder ); + aTextLayout.LayoutText( layoutedRect, aTextLineLayout, aUsedFont ); + aGc.SetUnderlineStyle( EUnderlineOn ); + //aGc.DrawText(convBuf.Mid(searchMatches[i].index, searchMatches[i].length),layoutedRect,baseLineOffset, align, 0); + aTextLayout.DrawText( aGc, text.Mid(searchMatches[i].index, searchMatches[i].length), aUseLogicalToVisualConversion, aTextColor ); + aGc.SetUnderlineStyle( EUnderlineOff ); + currentChar -= searchMatches[i].length; + } + } + if( currentChar >= 0 ) + { + layoutedRect.iTl.iX -= AknBidiTextUtils::MeasureTextBoundsWidth( *aUsedFont, + text.Left(currentChar), + CFont::TMeasureTextInput::EFVisualOrder ); + //aGc.DrawText(convBuf.Left(currentChar),layoutedRect,baseLineOffset, align, 0); + aTextLayout.LayoutText( layoutedRect, aTextLineLayout, aUsedFont ); + aTextLayout.DrawText( aGc, text.Left(currentChar), aUseLogicalToVisualConversion, aTextColor ); + } + } + else // mirroredInput + { + if( !aItemProperties.IsSelectionHidden() ) + { + for( TInt i=0 ; i 0 ) + { + aTextLayout.DrawText( aGc, text.Mid(currentChar, charactersToNextMatch), aUseLogicalToVisualConversion, aTextColor ); + //aGc.DrawText(convBuf.Mid(currentChar, charactersToNextMatch),layoutedRect,baseLineOffset, CGraphicsContext::ELeft); + layoutedRect.iTl.iX += AknBidiTextUtils::MeasureTextBoundsWidth( *aUsedFont, + text.Mid( currentChar,charactersToNextMatch ), + CFont::TMeasureTextInput::EFVisualOrder ); + + aTextLayout.LayoutText( layoutedRect, aTextLineLayout, aUsedFont ); + currentChar+=charactersToNextMatch; + } + aGc.SetUnderlineStyle( EUnderlineOn ); + //aGc.DrawText(convBuf.Mid(searchMatches[i].index, searchMatches[i].length),layoutedRect,baseLineOffset, CGraphicsContext::ELeft); + aTextLayout.DrawText( aGc, text.Mid(searchMatches[i].index, searchMatches[i].length), aUseLogicalToVisualConversion, aTextColor ); + aGc.SetUnderlineStyle( EUnderlineOff ); + layoutedRect.iTl.iX += AknBidiTextUtils::MeasureTextBoundsWidth( *aUsedFont, + text.Mid( searchMatches[i].index, + searchMatches[i].length ), + CFont::TMeasureTextInput::EFVisualOrder ); + + aTextLayout.LayoutText( layoutedRect, aTextLineLayout, aUsedFont ); + currentChar+=searchMatches[i].length; + } + } + if( currentChar buffer; + buffer.Append( KEllipsis ); + aTextLayout.DrawText( aGc, buffer, EFalse, aTextColor ); + } + searchMatches.Reset(); + + if ( visualBuf ) + { + CleanupStack::PopAndDestroy(); //visualBuf + } + } + else + { + aTextLayout.DrawText( aGc, aTextToDraw, aUseLogicalToVisualConversion, aTextColor ); + } + } + +// --------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::SetListCommands +// --------------------------------------------------------------------------- +void CPbk2ContactViewCustomListBoxData::SetListCommands( + const RPointerArray* aCommands ) + { + iCommandItems = aCommands; + } + +// -------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::IsContactAtListboxIndex +// Tells whether the listbox line contains a contact or not. +// Does not check that the aListboxIndex is within range of listbox. +// -------------------------------------------------------------------------- +// +TBool CPbk2ContactViewCustomListBoxData::IsContactAtListboxIndex( TInt aListboxIndex ) const + { + // There can be command items at the top of the list. + // The command items are not contacts. + const TInt enabledCommandCount = CommandItemCount(); + return aListboxIndex >= enabledCommandCount; + } + +// -------------------------------------------------------------------------- +// CPbk2ContactViewCustomListBoxData::CommandItemCount +// -------------------------------------------------------------------------- +// +TInt CPbk2ContactViewCustomListBoxData::CommandItemCount() const + { + // Some of the commands might be disabled. Don't count those. + TInt enabledCommandCount = 0; + if ( iCommandItems ) + { + for ( TInt n = 0; n < iCommandItems->Count(); ++n ) + { + const MPbk2UiControlCmdItem& cmd = *(*iCommandItems)[n]; + if ( cmd.IsEnabled() ) + { + enabledCommandCount++; + } + } + } + return enabledCommandCount; + } + +//End of Code Added for PhoneBook2 + +// End of File