diff -r 000000000000 -r e686773b3f54 phonebookui/Phonebook/View/src/CPbkContactViewListControl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook/View/src/CPbkContactViewListControl.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,1917 @@ +/* +* Copyright (c) 2002 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: +* Provides methods for phonebook contact view list control. +* +*/ + + +// INCLUDE FILES +#include // This class +#include // TResourceReader +#include // CColumnListBoxData +#include // CAknSearchField +#include // AknListBoxUtils +#include +#include +#include +#include +#include // KEikDynamicLayoutVariantSwitch +#include + + +// PbkView classes +#include +#include "CPbkViewState.h" +#include "CPbkThumbnailPopup.h" +#include +#include +#include "PbkFindPrimitivesFactory.h" +#include "PbkContactViewListModelFactory.h" +#include "MPbkFetchDlgSelection.h" + +// PbkEng classes +#include +#include +#include + +// PbkExt classes +#include +#include +#include +#include + +// Phonebook common include files +#include // Phonebook debugging support + + +// Unnamed namespace for local definitions +namespace { + +// LOCAL CONSTANTS AND MACROS + +/// Listbox model's entry cache size +const TInt KCacheSize = 32; + +const TUint16 KZwsChar = 0x200b; +const TUint16 KZwnjChar = 0x200c; + +enum TPanicCode + { + EPanicPostCond_Constructor = 1, + EPanicPreCond_ConstructFromResourceL, + EPanicInvalidListBoxType_ConstructFromResourceL, + EPanicPostCond_ConstructFromResource, + EPanicPreCond_ConstructL, + EPanicPostCond_ConstructL, + EPanicListBoxNull, + EPanicLogic_ComponentControl, + EPanicPostCond_EnableFindBoxL, + EPanicPostCond_DisableFindBoxL, + EPanicLogic_FindTextL, + EPanicPre_SetControlExtensionL + }; + + +// MODULE DATA STRUCTURES + +NONSHARABLE_CLASS(TCleanupEnableListBoxViewRedraw) + { + public: // Interface + inline TCleanupEnableListBoxViewRedraw(CListBoxView& aListBoxView) + : iCleanupItem(CleanupOp,&aListBoxView) + { + } + + inline operator TCleanupItem() const + { + return iCleanupItem; + } + + private: // Implementation + static void CleanupOp(TAny* aPtr); + + private: // Data + TCleanupItem iCleanupItem; + }; + +// ==================== LOCAL FUNCTIONS ==================== + +/** + * Returns index of aValue in aArray or KErrNotFound. + */ +template +TInt Find(const CArrayFix& aArray, const T& aValue) + { + const TInt count = aArray.Count(); + for (TInt i = 0; i < count; ++i) + { + if (aArray[i] == aValue) + { + return i; + } + } + return KErrNotFound; + } + +/** + * Returns CPbkIconArray icon array from aListBox. + */ +inline CPbkIconArray* IconArray(CEikColumnListBox& aListBox) + { + return static_cast + (aListBox.ItemDrawer()->ColumnData()->IconArray()); + } + +/** + * Sets aIconArray as aListBox'es icon array. + */ +inline void SetIconArray + (CEikColumnListBox& aListBox, CPbkIconArray* aIconArray) + { + aListBox.ItemDrawer()->ColumnData()->SetIconArray(aIconArray); + } + +void Panic(TPanicCode aReason) + { + _LIT(KPanicText, "CPbkContactViewListControl"); + User::Panic(KPanicText, aReason); + } + +/** + * Returns ETrue, if a character is to be included in the search string + */ +inline TBool IsSearchableChar( const TChar aChar ) + { + switch (aChar) + { + case KZwsChar: // FALLTHROUGH + case KZwnjChar: + { + return EFalse; + } + } + return ETrue; + } + +// MACROS + +/// Define this to print find performance data to debug output +#ifdef PBK_BENCHMARK_FIND + #pragma message("Warning: PBK_BENCHMARK_FIND is set") +#endif + +// MODULE DATA STRUCTURES + +#ifdef PBK_BENCHMARK_FIND + +/// Benchmarking helper class. +template +NONSHARABLE_CLASS(TRunningTimes) + { + public: // Interface + /** + * Constructor. + */ + inline TRunningTimes() + { + Reset(); + } + /** + * () operator. + */ + inline NumT operator()() const + { + return iTotal; + } + + inline void Start() + { + iStart.UniversalTime(); + } + inline void Stop() + { + iStop.UniversalTime(); + const TInt timeDiff = + I64LOW(iStop.MicroSecondsFrom(iStart).Int64()) / 1000; + iTotal += timeDiff; + iCount++; + } + + inline TInt Count() const + { + return iCount; + } + + /** + * Returns total time + */ + inline NumT Total() const + { + return iTotal; + } + + /** + * Reset. + */ + inline void Reset() + { + iTotal=0; iCount=0; + } + + private: // Data + TTime iStart; + TTime iStop; + /// Own: count + TInt iCount; + /// Own: total time + NumT iTotal; + }; + +#endif // PBK_BENCHMARK_FIND + +} // namespace + + +// ================= MEMBER FUNCTIONS ======================= + +// +// CPbkContactViewListControl +// +inline CEikColumnListBox& CPbkContactViewListControl::ListBox() const + { + __ASSERT_DEBUG(iListBox, Panic(EPanicListBoxNull)); + return(*iListBox); + } + +inline MPbkContactViewListModel& CPbkContactViewListControl::Model() const + { + return(*static_cast + (iListBox->Model()->ItemTextArray())); + } + +inline TBool CPbkContactViewListControl::PostCond_Constructor() + { + return + (!iListBox && !iFindBox && !iFindTextBuf && !iBaseView && !iView && + !iResourceData.iUnnamedText && !iResourceData.iFindEmptyText && + !iMarkedItemsArray && !iThumbnailPopup); + } + +inline TBool CPbkContactViewListControl::PostCond_ConstructFromResource() + { + return + (iListBox && !iFindBox && !iFindTextBuf && + iResourceData.iUnnamedText && !iMarkedItemsArray); + } + +EXPORT_C CPbkContactViewListControl* CPbkContactViewListControl::NewL + (CPbkContactEngine& aEngine, + CContactViewBase& aView, + TInt aResourceId, + const CCoeControl* aParent) + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING("CPbkContactViewListControl::NewL()")); + CPbkContactViewListControl* self = new(ELeave) CPbkContactViewListControl(); + CleanupStack::PushL(self); + self->ConstructL(aEngine, aView, aResourceId, aParent); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CPbkContactViewListControl::CPbkContactViewListControl() : + iLastFocusId(KNullContactId), + iChangedIndexes(1 /*allocation granularity*/) + { + // CBase::operator new(TLeave) resets other members + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::CPbkContactViewListControl(0x%x)"), + this); + __ASSERT_DEBUG(PostCond_Constructor(), Panic(EPanicPostCond_Constructor)); + } + +void CPbkContactViewListControl::ConstructFromResourceL + (TResourceReader& aReader) + { + __ASSERT_DEBUG(PostCond_Constructor(), + Panic(EPanicPreCond_ConstructFromResourceL)); + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::ConstructFromResourceL(0x%x)"),this); + + // emptyText + TPtrC emptyText = aReader.ReadTPtrC(); + // unnamedText + iResourceData.iUnnamedText = aReader.ReadHBufCL(); + // flags + iResourceData.iFlags = aReader.ReadUint32(); + + // Empty text in find state + TResourceReader rr; + iEikonEnv->CreateResourceReaderLC(rr, R_AVKON_FIND_NO_MATCHES); + iResourceData.iFindEmptyText = rr.ReadHBufCL(); + CleanupStack::PopAndDestroy(); // rr + + // listboxType + TInt listBoxType = aReader.ReadInt16(); + iListBox = static_cast + (EikControlFactory::CreateByTypeL(listBoxType).iControl); + __ASSERT_ALWAYS(iListBox, Panic + (EPanicInvalidListBoxType_ConstructFromResourceL)); + iListBox->SetContainerWindowL(*this); + // listbox + iListBox->ConstructFromResourceL(aReader); + iListBox->View()->SetListEmptyTextL(emptyText); + iListBox->CreateScrollBarFrameL(ETrue); + iListBox->ScrollBarFrame()->SetScrollBarVisibilityL + (CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto); + iListBox->SetObserver(this); + iListBox->MakeVisible(EFalse); + + // iconArray, use granularity of 4 + + CPbkIconArray* iconArray = new(ELeave) CPbkIconArray(4); + CleanupStack::PushL(iconArray); + const TInt iconArrayRes = aReader.ReadInt32(); + iconArray->ConstructFromResourceL(iconArrayRes); + + // get extension factory for setting extension icons + CPbkExtGlobals* extGlobal = CPbkExtGlobals::InstanceL(); + extGlobal->PushL(); + MPbkExtensionFactory& factory = extGlobal->FactoryL(); + factory.AddPbkFieldIconsL(NULL, iconArray); + CleanupStack::PopAndDestroy(extGlobal); + + CleanupStack::Pop(iconArray); + + SetIconArray(*iListBox,iconArray); + + // emptyIconId + iResourceData.iEmptyIconId = + static_cast(aReader.ReadInt16()); + // defaultIconId + iResourceData.iDefaultIconId = + static_cast(aReader.ReadInt16()); + + // Preallocate space for the one required integer + iChangedIndexes.AppendL(-1); + + __ASSERT_DEBUG(PostCond_ConstructFromResource(), + Panic(EPanicPostCond_ConstructFromResource)); + } + +EXPORT_C void CPbkContactViewListControl::ConstructL + (CPbkContactEngine& aEngine, + CContactViewBase& aView) + { + // Check that ConstructFromResourceL is executed + __ASSERT_DEBUG(PostCond_ConstructFromResource() && !iBaseView && !iView, + Panic(EPanicPreCond_ConstructL)); + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::ConstructL(0x%x)"),this); + + iFindPrimitives = PbkFindPrimitivesFactory::CreateL( + aEngine.ContactNameFormat()); + iBaseView = &aView; + iView = CPbkContactFindView::NewL( + aEngine, *iBaseView, *this, *iFindPrimitives); + + // Set aParams for MPbkContactViewListModel + PbkContactViewListModelFactory::TParams params; + params.iEngine = &aEngine; + params.iView = iView; + params.iCacheSize = KCacheSize; + params.iIconArray = IconArray(*iListBox); + params.iEmptyId = iResourceData.iEmptyIconId; + params.iDefaultId = iResourceData.iDefaultIconId; + + // Listbox model + MPbkContactViewListModel* model = PbkContactViewListModelFactory:: + CreateL(params); + model->SetUnnamedText(iResourceData.iUnnamedText); + iListBox->Model()->SetItemTextArray(model); + iListBox->Model()->SetOwnershipType(ELbmOwnsItemArray); + + // thumbnail handler + if (iResourceData.iFlags & KPbkContactViewListControlUpdateContextPane) + { + iThumbnailPopup = CPbkThumbnailPopup::NewL(aEngine); + } + + // Sets up TLS, must be done before FeatureManager is used. + FeatureManager::InitializeLibL(); + // iEngine != NULL means that Featuremanager has been initialized + iEngine = &aEngine; + + __ASSERT_DEBUG(PostCond_ConstructFromResource() && iBaseView && iView && + iThumbnailPopup || !(iResourceData.iFlags & + KPbkContactViewListControlUpdateContextPane), + Panic(EPanicPostCond_ConstructL)); + } + +CPbkContactViewListControl::~CPbkContactViewListControl() + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::~CPbkContactViewListControl(0x%x)"), + this); + + // This should be done before listbox delete + // (which deletes dummy control extension) + Release(iControlExtension); + + // Fetch dialog pages might delay calling ConstructL and thus Feature + // manager might not be initialized if destructing early. + if (iEngine) + { + // iEngine != NULL means that Featuremanager has been initialized + FeatureManager::UnInitializeLib(); + } + + delete iOriginalEmptyText; + iObservers.Reset(); + delete iFindTextBuf; + if (iView) + { + iView->Close(*this); + } + delete iFindPrimitives; + delete iThumbnailPopup; + delete iMarkedItemsArray; + delete iFindBox; + delete iListBox; + delete iResourceData.iFindEmptyText; + delete iResourceData.iUnnamedText; + } + +EXPORT_C TContactItemId CPbkContactViewListControl::ContactIdAtL + (TInt aIndex) const + { + return iView->AtL(aIndex); + } + +EXPORT_C TInt CPbkContactViewListControl::FindContactIdL + (TContactItemId aId) const + { + return iView->FindL(aId); + } + +EXPORT_C TInt CPbkContactViewListControl::CurrentItemIndex() const + { + return ListBox().CurrentItemIndex(); + } + +EXPORT_C void CPbkContactViewListControl::SetCurrentItemIndex(TInt aIndex) + { + if (ListBox().CurrentItemIndex() != aIndex) + { + ListBox().SetCurrentItemIndex(aIndex); + HandleFocusChange(); + } + } + +EXPORT_C void CPbkContactViewListControl::SetCurrentItemIndexAndDraw + (TInt aIndex) + { + if (ListBox().CurrentItemIndex() != aIndex) + { + ListBox().SetCurrentItemIndexAndDraw(aIndex); + HandleFocusChange(); + } + } + +EXPORT_C void CPbkContactViewListControl::HandleMarkableListProcessCommandL + (TInt aCommandId) + { + AknSelectionService::HandleMarkableListProcessCommandL + (aCommandId, &ListBox()); + } + +EXPORT_C void CPbkContactViewListControl::HandleMarkableListDynInitMenuPane + (TInt aResourceId, + CEikMenuPane *aMenu) + { + AknSelectionService::HandleMarkableListDynInitMenuPane + (aResourceId, aMenu, &ListBox()); + } + +EXPORT_C void + CPbkContactViewListControl::HandleMarkableListUpdateAfterCommandExecution() + { + AknSelectionService::HandleMarkableListUpdateAfterCommandExecution + (&ListBox()); + } + +EXPORT_C const TDesC& CPbkContactViewListControl::FindTextL() const + { + // Initial minimum size for the find text buffer + const TInt KInitialBufSize = 8; + + if (iFindBox) + { + const TInt findBoxTextLength = iFindBox->TextLength(); + if (findBoxTextLength > 0) + { + TInt bufCapacity = 0; + if (iFindTextBuf) + { + bufCapacity = iFindTextBuf->Des().MaxLength(); + } + if (bufCapacity < findBoxTextLength) + { + // Allocate a new buffer of at least KInitialBufSize + // characters or twice as large as the previous one + const TInt newBufSize = Max(Max(KInitialBufSize,2*bufCapacity), + findBoxTextLength); + HBufC* newBuf = HBufC::NewL(newBufSize); + delete iFindTextBuf; + iFindTextBuf = newBuf; + } + TPtr bufPtr = iFindTextBuf->Des(); + __ASSERT_DEBUG + (bufPtr.MaxLength()>=KInitialBufSize && bufPtr.MaxLength()>=findBoxTextLength, + Panic(EPanicLogic_FindTextL)); + iFindBox->GetSearchText(bufPtr); + // Strip from search string all unwanted characters that e.g. Hindi input places there + for( TInt i = bufPtr.Length()-1; i >= 0; --i ) + { + if (!IsSearchableChar(bufPtr[i])) + { + bufPtr.Delete( i, 1 ); + } + } + return(*iFindTextBuf); + } + } + return KNullDesC; + } + +EXPORT_C void CPbkContactViewListControl::ResetFindL() + { + if (iFindBox && iFindBox->TextLength() > 0) + { + iFindBox->ResetL(); + UpdateFindResultL(); + iFindBox->DrawDeferred(); + } + } + +EXPORT_C TBool CPbkContactViewListControl::ItemMarked(TInt aIndex) const + { + const CListBoxView::CSelectionIndexArray* selections = + ListBox().View()->SelectionIndexes(); + return (selections ? Find(*selections,aIndex)!=KErrNotFound : EFalse); + } + +EXPORT_C TInt CPbkContactViewListControl::NextUnmarkedIndexFromFocus() const + { + const TInt focus = ListBox().CurrentItemIndex(); + TInt index = focus; + const CListBoxView::CSelectionIndexArray* selections = + ListBox().SelectionIndexes(); + if (selections && selections->Count() > 0) + { + const TInt count = iListBox->Model()->NumberOfItems(); + for (index = focus; index < count; ++index) + { + if (Find(*selections,index) == KErrNotFound) + { + return index; + } + } + for (index = focus; index >= 0; --index) + { + if (Find(*selections,index) == KErrNotFound) + { + return index; + } + } + } + return index; + } + +EXPORT_C void CPbkContactViewListControl::MarkItemL + (TContactItemId aContactId, + TBool aMark) + { + const TInt index = FindContactIdL(aContactId); + if (index >= 0) + { + if (aMark) + { + ListBox().View()->SelectItemL(index); + } + else + { + ListBox().View()->DeselectItem(index); + } + } + } + +EXPORT_C void CPbkContactViewListControl::ClearMarks() + { + if (ItemsMarked()) + { + CListBoxView& listBoxView = *ListBox().View(); + listBoxView.SetDisableRedraw(ETrue); + ListBox().ClearSelection(); + listBoxView.SetDisableRedraw(EFalse); + Redraw(); + } + } + +EXPORT_C CPbkViewState* CPbkContactViewListControl::GetStateL + (TBool aSaveMarks/*=ETrue*/) const + { + CPbkViewState* state = GetStateLC(aSaveMarks); + CleanupStack::Pop(); // state + return state; + } + +EXPORT_C CPbkViewState* CPbkContactViewListControl::GetStateLC + (TBool aSaveMarks/*=ETrue*/) const + { + // Create a state object + CPbkViewState* state = CPbkViewState::NewLC(); + + // Init the state object + if (NumberOfItems() > 0) + { + TInt index; + if ((index = ListBox().TopItemIndex()) >= 0) + { + state->SetTopContactId(ContactIdAtL(index)); + } + if ((index = ListBox().CurrentItemIndex()) >= 0) + { + state->SetFocusedContactId(ContactIdAtL(index)); + } + if (aSaveMarks && ItemsMarked()) + { + state->SetMarkedContactIds(CContactIdArray::NewL(&MarkedItemsL())); + } + } + + // Return the state object + return state; + } + +EXPORT_C void CPbkContactViewListControl::RestoreStateL(const CPbkViewState* aState) + { + PBK_DEBUG_PRINT( + PBK_DEBUG_STRING("CPbkContactViewListControl::RestoreStateL(0x%x,0x%x)"), + this, aState); + + if (!aState || !iStateFlags.IsSet(EReady)) + { + return; + } + + CEikColumnListBox& listBox = ListBox(); + TBool redraw = EFalse; + if (aState->Flags() & CPbkViewState::EInitialized) + { + // Find box is recreated because default input language needs to + // be reset here if Always on feature is enabled for Phonebook + delete iFindBox; + iFindBox=NULL; + + // Do not enable the find box if there does not exist any contacts + if (iBaseView->CountL() > 0) + { + EnableFindBoxL(); + } + + listBox.Reset(); + redraw = ETrue; + } + else + { + if (iBaseView->CountL() > 0) + { + if (aState->Flags() & CPbkViewState::EFocusFirst) + { + listBox.SetTopItemIndex(0); + } + else if (aState->Flags() & CPbkViewState::EFocusLast) + { + listBox.SetCurrentItemIndex(listBox.Model()->NumberOfItems()); + } + else + { + // Restore top item + if (aState->TopContactId() != KNullContactId) + { + const TInt index = FindContactIdL(aState->TopContactId()); + if (index >= 0) + { + const TInt prevIndex = listBox.TopItemIndex(); + listBox.SetTopItemIndex(index); + FixTopItemIndex(); + if (index != prevIndex) + { + redraw = ETrue; + } + } + } + + // Restore focus + if (aState->FocusedContactId() != KNullContactId) + { + const TInt index = FindContactIdL(aState->FocusedContactId()); + if (index >= 0) + { + const TInt prevIndex = listBox.CurrentItemIndex(); + listBox.SetCurrentItemIndex(index); + if (index != prevIndex) + { + redraw = ETrue; + } + } + } + + } + // Restore selections + const CContactIdArray* markedContactIds = aState->MarkedContactIds(); + if (RestoreMarkedItemsL(markedContactIds)) + { + redraw = ETrue; + } + } + } + + if (redraw) + { + Redraw(); + iListBox->UpdateScrollBarsL(); + HandleFocusChange(); + } + } + +void CPbkContactViewListControl::ShowThumbnail(TContactItemId aContactId) + { + if (!iThumbnailPopup && iEngine) + { + TRAP_IGNORE(iThumbnailPopup = CPbkThumbnailPopup::NewL( *iEngine )); + } + + if (iThumbnailPopup && aContactId!=KNullContactId && IsReadyToDraw() && + !iStateFlags.IsSet(EBlank)) + { + iThumbnailPopup->Load(aContactId, iListBox); + } + else if (iThumbnailPopup) + { + iThumbnailPopup->CancelLoading(); + } + } + +EXPORT_C void CPbkContactViewListControl::ShowThumbnailL() + { + if (!iThumbnailPopup && iEngine) + { + iThumbnailPopup = CPbkThumbnailPopup::NewL( *iEngine ); + } + + if (iLastFocusId!=KNullContactId && IsReadyToDraw() && + !iStateFlags.IsSet(EBlank)) + { + iThumbnailPopup->Load(iLastFocusId, iListBox); + } + else + { + iThumbnailPopup->CancelLoading(); + } + } + +EXPORT_C void CPbkContactViewListControl::HideThumbnail() + { + if (iThumbnailPopup) + { + iThumbnailPopup->CancelLoading(); + } + } + +EXPORT_C void CPbkContactViewListControl::AddObserverL + (MPbkContactViewListControlObserver& aObserver) + { + User::LeaveIfError(iObservers.Append(&aObserver)); + } + +EXPORT_C void CPbkContactViewListControl::RemoveObserver + (MPbkContactViewListControlObserver& aObserver) + { + const TInt index = iObservers.Find(&aObserver); + if (index >= 0) + { + iObservers.Remove(index); + } + } + +EXPORT_C TBool CPbkContactViewListControl::IsReady() const + { + return (iStateFlags.IsSet(EReady)); + } + +void CPbkContactViewListControl::SetDisableRedraw(TBool aDisableRedraw) + { + ListBox().View()->SetDisableRedraw(aDisableRedraw); + } + +void CPbkContactViewListControl::DisableRedrawEnablePushL() + { + CListBoxView& listBoxView = *ListBox().View(); + listBoxView.SetDisableRedraw(ETrue); + CleanupStack::PushL(TCleanupEnableListBoxViewRedraw(listBoxView)); + } + +EXPORT_C void CPbkContactViewListControl::SetBlank(TBool aBlank) + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::SetBlank(0x%x,%d)"),this,aBlank); + + if ((iStateFlags.IsSet(EBlank) && aBlank) || + (!iStateFlags.IsSet(EBlank) && !aBlank)) + { + // No change in state + return; + } + + // Set the EBlank flag + iStateFlags.Assign(EBlank,aBlank); + + // Hide/unhide component controls + MakeComponentsVisible(!aBlank); + Redraw(); + } + +EXPORT_C void CPbkContactViewListControl::SetEntryLoader + (MPbkContactEntryLoader& aContactEntryLoader) + { + Model().SetEntryLoader(aContactEntryLoader); + } + + +void CPbkContactViewListControl::SetSelectionAccepter(MPbkFetchDlgSelection* aAccepter) + { + iSelectionAccepter = aAccepter; + } + +TInt CPbkContactViewListControl::NumberOfItems() const + { + return ListBox().Model()->NumberOfItems(); + } + +TBool CPbkContactViewListControl::ItemsMarked() const + { + const CListBoxView::CSelectionIndexArray* selections = + ListBox().View()->SelectionIndexes(); + return (selections && selections->Count()>0); + } + +const CContactIdArray& CPbkContactViewListControl::MarkedItemsL() const + { + if (!iMarkedItemsArray) + { + iMarkedItemsArray = CContactIdArray::NewL(); + } + + // Remove old contents of array (use Remove instead of Reset to keep the + // array buffer) + iMarkedItemsArray->Remove(0,iMarkedItemsArray->Count()); + + // Get the list boxes marked items index array + const CListBoxView::CSelectionIndexArray* selArray = + ListBox().SelectionIndexes(); + + if (selArray && selArray->Count() > 0) + { + // Initialize the marked contact id array using selArray + CContactViewBase::TVirtualFunction1Params params + (selArray, iMarkedItemsArray); + + iView->CContactViewBase_Reserved_1 + (CContactViewBase::ECContactViewBaseVirtualFunction1, ¶ms); + } + else + { + // No items marked, add the focused contact to the array + iMarkedItemsArray->AddL(FocusedContactIdL()); + } + + return *iMarkedItemsArray; + } + +TContactItemId CPbkContactViewListControl::FocusedContactIdL() const + { + TContactItemId retId(KNullContactId); + + const TInt focusIndex = ListBox().CurrentItemIndex(); + if (focusIndex >= 0) + { + retId = iView->AtL(focusIndex); + } + return retId; + } + +const TPbkContactItemField* CPbkContactViewListControl::FocusedField() const + { + // This control does not support field level focus + return NULL; + } + +MObjectProvider* CPbkContactViewListControl::ObjectProvider() + { + return this; + } + +TKeyResponse CPbkContactViewListControl::OfferKeyEventL + (const TKeyEvent& aKeyEvent,TEventCode aType) + { + if (!iStateFlags.IsSet(EReady) || iStateFlags.IsSet(EBlank)) + { + // Don't handle any keys when not ready or blanked + return EKeyWasNotConsumed; + } + + TKeyResponse result = EKeyWasNotConsumed; + + if (iFindBox) + { + // Find box is active, offer key first to it + result = iFindBox->OfferKeyEventL(aKeyEvent, aType); + } + + if (result == EKeyWasNotConsumed && iListBox) + { + // Find box didn't consume the event -> offer it to the list box + const TInt focusIndex = iListBox->CurrentItemIndex(); + const TBool markedBefore = ItemMarked(focusIndex); + + // If selection key was pressed and the focused contact was earlier + // unselected, then first check from selection accepter if this item + // can be selected + // Also do the acception-check if there are no selected items and + // OK-softkey was pressed (causing focused item to be selected and + // closing the dialog + TBool checkSelection = EFalse; + const CListBoxView::CSelectionIndexArray* selArray = + ListBox().SelectionIndexes(); + + + const TInt selectionKeyPressed(aKeyEvent.iCode == EKeyDevice3); + + // AVKON may create EKeyApplicationF key event + // when list item is selected. + const TInt avkonSelectionKeyNotification( + aKeyEvent.iCode == EKeyApplicationF); + + const TBool noSelectionMade(!selArray||selArray->Count() == 0 ); + + const TBool validNewFocusedItem( + !markedBefore && focusIndex >= KErrNone); + + if ((selectionKeyPressed || (avkonSelectionKeyNotification && noSelectionMade)) + && validNewFocusedItem) + { + checkSelection = ETrue; + } + + const CListBoxView::CSelectionIndexArray* selections = + ListBox().SelectionIndexes(); + TInt selCount = selections ? selections->Count() : 0; + + if (!checkSelection || !iSelectionAccepter || + focusIndex != KErrNotFound && + iSelectionAccepter->ContactSelectionAcceptedL( + ContactIdAtL(focusIndex), selCount)) + { + result = iListBox->OfferKeyEventL(aKeyEvent, aType); + + if (result == EKeyWasConsumed) + { + const TBool markedAfter = ItemMarked(focusIndex); + if (markedAfter != markedBefore) + { + TPbkContactViewListControlEvent + event(TPbkContactViewListControlEvent::EContactSelected); + event.iInt = focusIndex; + event.iContactId = ContactIdAtL(focusIndex); + if (!markedAfter) + { + event.iEventType = + TPbkContactViewListControlEvent::EContactUnselected; + } + SendEventToObserversL(event); + } + } + } + else + { + result = EKeyWasConsumed; + } + } + return result; + } + +void CPbkContactViewListControl::HandlePointerEventL( + const TPointerEvent& aPointerEvent ) + { + if ( AknLayoutUtils::PenEnabled() ) + { + if ( iFindBox ) + { + iFindBox->HandlePointerEventL( aPointerEvent ); + } + + if ( iListBox ) + { + switch ( aPointerEvent.iType ) + { + case TPointerEvent::EButton1Down: + { + iPrevIndex = iListBox->CurrentItemIndex(); + iListBox->HandlePointerEventL( aPointerEvent ); + break; + } + case TPointerEvent::EButton1Up: + { + TInt focusIndex; + TBool focusableContactPointed = + iListBox->View()->XYPosToItemIndex( + aPointerEvent.iPosition, focusIndex ); + if (!focusableContactPointed || focusIndex < 0) + { + // Nothing special to do when tapping empty space + iListBox->HandlePointerEventL( aPointerEvent ); + } + else + { + // Send contact tap events + TPbkContactViewListControlEvent event( + TPbkContactViewListControlEvent::EContactTapped ); + event.iInt = focusIndex; + event.iContactId = ContactIdAtL( focusIndex ); + if ( iPrevIndex == iListBox->CurrentItemIndex() ) + { + event.iEventType = + TPbkContactViewListControlEvent::EContactDoubleTapped; + } + SendEventToObserversL( event ); + + // Do markings + const TBool markedBefore = ItemMarked(focusIndex); + const CListBoxView::CSelectionIndexArray* selections = + ListBox().SelectionIndexes(); + TInt selCount = selections ? selections->Count() : 0; + + if ( markedBefore || // can unmark always + !iSelectionAccepter || // no select restrictions + iSelectionAccepter->ContactSelectionAcceptedL( + ContactIdAtL(focusIndex), selCount) ) + { + // Handle the pointer event to list box to fix the problem that items in multiple + // fetch dialog can't be select with touch screen. + iListBox->HandlePointerEventL( aPointerEvent ); + + const TBool markedAfter = ItemMarked( focusIndex ); + if ( markedAfter != markedBefore ) + { + event.iEventType = + TPbkContactViewListControlEvent::EContactSelected; + event.iInt = focusIndex; + event.iContactId = ContactIdAtL(focusIndex); + if (!markedAfter) + { + event.iEventType = + TPbkContactViewListControlEvent::EContactUnselected; + } + SendEventToObserversL(event); + } + } + } + break; + } + default: + { + iListBox->HandlePointerEventL( aPointerEvent ); + } + } + } + } + } + +void CPbkContactViewListControl::MakeVisible(TBool aVisible) + { + PBK_DEBUG_PRINT( + PBK_DEBUG_STRING("CPbkContactViewListControl::MakeVisible(0x%x,%d)"), + this, aVisible); + + CCoeControl::MakeVisible(aVisible); + MakeComponentsVisible(aVisible); + } + +void CPbkContactViewListControl::UpdateContact(TContactItemId aContactId) + { + TInt listBoxRow = -1; + TRAPD(err, listBoxRow = FindContactIdL(aContactId) ); + if (err) + { + iEikonEnv->NotifyIdleErrorWhileRedrawing(err); + } + if (listBoxRow >= 0) + { + // if visible + if (listBoxRow >= ListBox().TopItemIndex() && + listBoxRow <= ListBox().BottomItemIndex() ) + { + ListBox().DrawItem(listBoxRow); + } + } + } + +TInt CPbkContactViewListControl::CountComponentControls() const + { + TInt controls = 0; + if (iListBox) + { + ++controls; + } + if (iFindBox) + { + ++controls; + } + return controls; + } + +CCoeControl* CPbkContactViewListControl::ComponentControl(TInt aIndex) const + { + switch (aIndex) + { + case 0: + { + __ASSERT_DEBUG(iListBox, Panic(EPanicLogic_ComponentControl)); + return iListBox; + } + case 1: + { + __ASSERT_DEBUG(iFindBox, Panic(EPanicLogic_ComponentControl)); + return iFindBox; + } + default: + { + // Illegal state + __ASSERT_DEBUG(EFalse, Panic(EPanicLogic_ComponentControl)); + return NULL; + } + } + } + +void CPbkContactViewListControl::FocusChanged(TDrawNow aDrawNow) + { + const TBool focused = IsFocused(); + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::FocusChanged(0x%x,%d),focused=%d"), + this, aDrawNow, focused ? ETrue : EFalse); + + if (focused) + { + ShowThumbnail(iLastFocusId); + } + else + { + HideThumbnail(); + } + + const TInt count = CountComponentControls(); + for (TInt i=0; i < count; ++i) + { + CCoeControl* componentControl = ComponentControl(i); + // Don't try to focus non-focusing controls + if (!componentControl->IsNonFocusing()) + { + componentControl->SetFocus(focused,aDrawNow); + } + } + } + +void CPbkContactViewListControl::SizeChanged() + { + const TRect rect(Rect()); + PBK_DEBUG_PRINT( + PBK_DEBUG_STRING("CPbkContactViewListControl::SizeChanged(0x%x), rect=(%d,%d,%d,%d)"), + this, rect.iTl.iX, rect.iTl.iY, rect.iBr.iX, rect.iBr.iY); + + if (iListBox && iFindBox) + { + AknLayoutUtils::LayoutControl(iListBox, rect, + AKN_LAYOUT_WINDOW_list_gen_pane(1)); + AknLayoutUtils::LayoutControl(iFindBox, rect, + AKN_LAYOUT_WINDOW_find_pane); + if (iFindBox->IsVisible() && iListBox->IsVisible()) + { + // The correct line position to use is 2, which corresponds + // EABColumn in Avkon (not a public enumeration, + // hence hard-coding used here) + const TInt KSeparatorLinePos = 2; + iFindBox->SetLinePos(KSeparatorLinePos); + } + } + else if (iListBox) + { + AknLayoutUtils::LayoutControl(iListBox, rect, + AKN_LAYOUT_WINDOW_list_gen_pane(0)); + } + } + +void CPbkContactViewListControl::Draw(const TRect& aRect) const + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING( + "CPbkContactViewListControl::Draw(0x%x, TRect(%d,%d,%d,%d)), iStateFlags=0x%x"), + this, aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY, iStateFlags.iFlags); + + if (!iStateFlags.IsSet(EReady) || iStateFlags.IsSet(EBlank)) + { + // If control is not ready or blanked draw a blank background + CWindowGc& gc = SystemGc(); + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext(iListBox); + if ( !AknsDrawUtils::Background(skin, cc, iListBox, gc, aRect) ) + { + // blank background if no skin present + gc.SetPenStyle(CGraphicsContext::ENullPen); + gc.SetBrushStyle(CGraphicsContext::ESolidBrush); + gc.DrawRect(aRect); + } + } + } + +void CPbkContactViewListControl::HandleControlEventL + (CCoeControl* aControl, + TCoeEvent aEventType) + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::HandleControlEventL(0x%x,0x%x,%d)"), + this, aControl, aEventType); + + if (aEventType == EEventStateChanged) + { + if (aControl == iListBox) + { + HandleFocusChange(); + // Forward listbox state change events to this control's + // observers + ReportEventL(MCoeControlObserver::EEventStateChanged); + } + else if (aControl == iFindBox) + { + UpdateFindResultL(); + } + } + } + +void CPbkContactViewListControl::HandleContactViewEvent + (const CContactViewBase& aView,const TContactViewEvent& aEvent) + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::HandleContactViewEvent(0x%x,0x%x,%d)"), + this, &aView, aEvent.iEventType); + + if (&aView == iView) + { + TRAPD(err, DoHandleContactViewEventL(aView,aEvent)); + if (err != KErrNone) + { + iEikonEnv->HandleError(err); + } + } + } + +/** + * Called from HandleContactViewEvent(). + */ +void CPbkContactViewListControl::DoHandleContactViewEventL + (const CContactViewBase& /*aView*/,const TContactViewEvent& aEvent) + { + switch (aEvent.iEventType) + { + case TContactViewEvent::EReady: + { + iStateFlags.Set(EReady); + MakeComponentsVisible(IsVisible()); + iListBox->Reset(); + UpdateFindBoxL(); + iListBox->UpdateScrollBarsL(); + Redraw(); + HandleFocusChange(); + SendEventToObserversL(TPbkContactViewListControlEvent::EReady); + break; + } + + case TContactViewEvent::ESortOrderChanged: + { + Model().FlushCache(); + Model().RefreshSortOrderL(); + iStateFlags.Set(EReady); + MakeComponentsVisible(IsVisible()); + iListBox->Reset(); + UpdateFindBoxL(); + iListBox->UpdateScrollBarsL(); + Redraw(); + HandleFocusChange(); + // Send EReady event + SendEventToObserversL(TPbkContactViewListControlEvent::EReady); + break; + } + + case TContactViewEvent::EItemAdded: + { + HandleItemAdditionL(aEvent.iInt); + TPbkContactViewListControlEvent event + (TPbkContactViewListControlEvent::EItemAdded); + event.iInt = aEvent.iInt; + event.iContactId = aEvent.iContactId; + SendEventToObserversL(event); + break; + } + + case TContactViewEvent::EItemRemoved: + { + Model().PurgeEntry(aEvent.iContactId); + HandleItemRemovalL(aEvent.iInt); + TPbkContactViewListControlEvent event + (TPbkContactViewListControlEvent::EItemRemoved); + event.iInt = aEvent.iInt; + event.iContactId = aEvent.iContactId; + SendEventToObserversL(event); + break; + } + + case TContactViewEvent::EUnavailable: + { + iStateFlags.Clear(EReady); + MakeComponentsVisible(EFalse); + SendEventToObserversL + (TPbkContactViewListControlEvent::EUnavailable); + break; + } + + case TContactViewEvent::ESortError: //FALLTHROUGH + case TContactViewEvent::EServerError: //FALLTHROUGH + case TContactViewEvent::EIndexingError: + { + iStateFlags.Clear(EReady); + MakeComponentsVisible(EFalse); + iEikonEnv->HandleError(aEvent.iInt); + iListBox->Reset(); + DisableFindBoxL(); + TPbkContactViewListControlEvent event + (TPbkContactViewListControlEvent::EUnavailable); + event.iInt = aEvent.iInt; + SendEventToObserversL(event); + break; + } + + default: + { + break; + } + } + } + +void CPbkContactViewListControl::SendEventToObserversL + (const TPbkContactViewListControlEvent& aEvent) + { + // Loop backwards in case some observer destroys itself in the + // event handler + for (TInt i=iObservers.Count()-1; i>=0; --i) + { + iObservers[i]->HandleContactViewListControlEventL(*this,aEvent); + } + } + +void CPbkContactViewListControl::ConstructL + (CPbkContactEngine& aEngine, + CContactViewBase& aView, + TInt aResourceId, + const CCoeControl* aParent) + { + if (aParent) + { + SetContainerWindowL(*aParent); + } + else + { + CreateWindowL(); + } + ConstructFromResourceL(aResourceId); + ConstructL(aEngine, aView); + CreateControlExtensionL(aEngine); + } + +void CPbkContactViewListControl::ConstructFromResourceL + (TInt aResourceId) + { + TResourceReader resReader; + iCoeEnv->CreateResourceReaderLC(resReader,aResourceId); + ConstructFromResourceL(resReader); + CleanupStack::PopAndDestroy(); // resReader + } + +void CPbkContactViewListControl::FixTopItemIndex() + { + CEikListBox& listBox = ListBox(); + TInt index = listBox.TopItemIndex(); + const TInt height = listBox.View()->NumberOfItemsThatFitInRect + (iListBox->View()->ViewRect()); + const TInt numItems = listBox.Model()->NumberOfItems(); + if (index + height > numItems) + { + index += numItems - (height + index); + if (index < 0) + { + index = 0; + } + if (index != listBox.TopItemIndex()) + { + listBox.SetTopItemIndex(index); + } + } + } + +/** + * Redraws this control using DrawDeferred(). + */ +void CPbkContactViewListControl::Redraw() + { + if (iStateFlags.IsSet(EReady) && !iStateFlags.IsSet(EBlank)) + { + DrawDeferred(); + } + } + +void CPbkContactViewListControl::MakeComponentsVisible(TBool aVisible) + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::MakeComponentsVisible(0x%x,%d)"), + this, aVisible); + + if (aVisible && (!iStateFlags.IsSet(EReady) || iStateFlags.IsSet(EBlank))) + { + // Never make components visible if this control is not ready or in + // blank state + return; + } + + if (iListBox) + { + iListBox->MakeVisible(aVisible); + } + + if (iFindBox) + { + iFindBox->SetFocus(aVisible); + iFindBox->MakeVisible(aVisible); + } + + // Hide/show thumbnail + if (aVisible) + { + ShowThumbnail(iLastFocusId); + } + else + { + HideThumbnail(); + } + } + +void CPbkContactViewListControl::HandleItemAdditionL(TInt aIndex) + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::HandleItemAdditionL(0x%x, %d)"), + this, aIndex); + + UpdateFindBoxL(); + + // Update listbox + iChangedIndexes[0] = aIndex; + iListBox->HandleItemAdditionL(iChangedIndexes); + + // Maintain focus + const TInt index = iView->FindL(iLastFocusId); + if ( index >= 0 && + index < iListBox->Model()->NumberOfItems() && + index != iListBox->CurrentItemIndex() ) + { + iListBox->SetCurrentItemIndex(index); + } + Redraw(); + HandleFocusChange(); + } + +void CPbkContactViewListControl::HandleItemRemovalL(TInt aIndex) + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactViewListControl::HandleItemRemovalL(0x%x, %d)"), + this, aIndex); + + // Deselect item + CListBoxView& listBoxView = *ListBox().View(); + listBoxView.SetDisableRedraw(ETrue); + listBoxView.DeselectItem(aIndex); + listBoxView.SetDisableRedraw(EFalse); + + UpdateFindBoxL(); + + // Update listbox + TInt focusIndex = iListBox->CurrentItemIndex(); + TInt topIndex = iListBox->TopItemIndex(); + iChangedIndexes[0] = aIndex; + iListBox->HandleItemRemovalL(iChangedIndexes); + + // Maintain focus + const TInt lastIndex = iListBox->Model()->NumberOfItems() - 1; + if (lastIndex == KNullContactId) + { + iListBox->Reset(); + } + else + { + if (aIndex < focusIndex) + { + --focusIndex; + } + if (focusIndex > lastIndex || focusIndex < 0) + { + focusIndex = lastIndex; + } + const TInt numVisibleItems = + iListBox->View()->NumberOfItemsThatFitInRect + (iListBox->View()->ViewRect()); + if (topIndex + numVisibleItems > lastIndex) + { + topIndex = Max(lastIndex - numVisibleItems + 1, 0); + } + if (topIndex >= 0) + { + iListBox->SetTopItemIndex(topIndex); + } + if (focusIndex >= 0) + { + iListBox->SetCurrentItemIndex(focusIndex); + } + } + Redraw(); + HandleFocusChange(); + } + +/** + * Hides or displays the find box depending on control state. + */ +void CPbkContactViewListControl::UpdateFindBoxL() + { + if ((iResourceData.iFlags & KPbkContactViewListControlFindBox) && + iBaseView->CountL() > 0) + { + EnableFindBoxL(); + } + else + { + DisableFindBoxL(); + } + } + +void CPbkContactViewListControl::EnableFindBoxL() + { + if (!iFindBox) + { + // Create a find box + iFindBox = CAknSearchField::NewL + (*this, CAknSearchField::ESearch, NULL, + CPbkConstants::SearchFieldLength()); + + iFindBox->SetObserver(this); + iFindBox->SetFocus(ETrue); + iFindBox->ResetL(); + + // Set default input mode to Katakana if current UI language is Japanese + if (FeatureManager::FeatureSupported(KFeatureIdJapanese) && + (User::Language() == ELangJapanese)) + { + CEikEdwin& findEditor = iFindBox->Editor(); + findEditor.SetAknEditorInputMode(EAknEditorKatakanaInputMode); + } + + // Inform list box that find is visible again + static_cast(iListBox->View()) + ->SetFindEmptyListState(ETrue); + SetFindEmptyTextL(); + + // Relayout view + SizeChanged(); + UpdateFindResultL(); + } + __ASSERT_DEBUG(iFindBox, Panic(EPanicPostCond_EnableFindBoxL)); + } + +void CPbkContactViewListControl::DisableFindBoxL() + { + if (iFindBox) + { + // Important to set the find box non-focusing before + // deleting it, otherwise the focus changes triggered + // by the removal of the control from stack will focus + // the find box which is under deletion + iFindBox->SetNonFocusing(); + delete iFindBox; + iFindBox = NULL; + // Inform list box that find is hidden + static_cast(iListBox->View()) + ->SetFindEmptyListState(EFalse); + RemoveFindEmptyTextL(); + + // Relayout view + SizeChanged(); + UpdateFindResultL(); + } + __ASSERT_DEBUG(!iFindBox, Panic(EPanicPostCond_DisableFindBoxL)); + } + +/** + * Updates find result. + * @return ETrue if there was a change in find result set. + */ +TBool CPbkContactViewListControl::UpdateFindResultL() + { + TBool result = EFalse; + const CContactIdArray* markedItems = NULL; + const TInt countBefore = iView->CountL(); + + if (ItemsMarked()) + { + markedItems = &MarkedItemsL(); + } + TRAPD( err, + result = iView->SetFindTextL(FindTextL(), markedItems) ); + if (err != KErrNone) + { + iEikonEnv->HandleError(err); + } + + const TInt countAfter = iView->CountL(); + + if (err) + { + // Error (possibly OOM), only redraw what remains in the screen + SizeChanged(); + Redraw(); + } + else if (result) + { + iListBox->DrawDeferred(); + if (countAfter > countBefore) + { + iListBox->HandleItemAdditionL(); + } + else if (countAfter < countBefore) + { + iListBox->HandleItemRemovalL(); + } + + if (markedItems) + { + // Restore item marks + CListBoxView& listBoxView = *iListBox->View(); + listBoxView.SetDisableRedraw(ETrue); + CleanupStack::PushL(TCleanupEnableListBoxViewRedraw(listBoxView)); + listBoxView.ClearSelection(); + const TInt count = markedItems->Count(); + #ifdef PBK_BENCHMARK_FIND + TRunningTimes timer; + #endif + for (TInt i=0; i < count; ++i) + { + const TContactItemId contactId = (*markedItems)[i]; + #ifdef PBK_BENCHMARK_FIND + timer.Start(); + #endif + const TInt index =iView->FindL(contactId); + #ifdef PBK_BENCHMARK_FIND + timer.Stop(); + #endif + listBoxView.SelectItemL(index); + } + #ifdef PBK_BENCHMARK_FIND + RDebug::Print(_L( + "CPbkContactViewListControl::UpdateFindResultL FindL calls %d tot %d"), + timer.Count(), timer.Total()); + #endif + CleanupStack::PopAndDestroy(); //TCleanupEnableListBoxViewRedraw + } + + // This event is send to observers, + // if contact set of the control is changed + TPbkContactViewListControlEvent + event(TPbkContactViewListControlEvent::EContactSetChanged); + SendEventToObserversL(event); + } + + TInt focusIndex = iView->IndexOfFirstFindMatchL(); + if (focusIndex < 0) + { + if (countAfter > 0) + { + focusIndex = 0; + } + } + if (focusIndex >= 0 && focusIndex != iListBox->CurrentItemIndex()) + { + iListBox->SetCurrentItemIndexAndDraw(focusIndex); + } + HandleFocusChange(); + + return result; + } + +void CPbkContactViewListControl::SetFindEmptyTextL() + { + if (!iOriginalEmptyText) + { + iOriginalEmptyText = iListBox->View()->EmptyListText()->AllocL(); + } + iListBox->View()->SetListEmptyTextL(*iResourceData.iFindEmptyText); + } + +void CPbkContactViewListControl::RemoveFindEmptyTextL() + { + if (iOriginalEmptyText) + { + iListBox->View()->SetListEmptyTextL(*iOriginalEmptyText); + } + } + +void CPbkContactViewListControl::HandleFocusChange() + { + TRAP_IGNORE(HandleFocusChangeL()); + } + +void CPbkContactViewListControl::HandleFocusChangeL() + { + const TInt index = ListBox().CurrentItemIndex(); + TContactItemId newFocusId = KNullContactId; + if (index >= 0 && index < iView->CountL()) + { + newFocusId = iView->AtL(index); + } + if (newFocusId != iLastFocusId) + { + iLastFocusId = newFocusId; + HideThumbnail(); + ShowThumbnail(newFocusId); + } + } + +/** + * Marks specified contacts in the listbox. + * + * @param aMarkedContactIds contacts to mark. + * @return true if any contacts were marked in the list. + */ +TBool CPbkContactViewListControl::RestoreMarkedItemsL + (const CContactIdArray* aMarkedContactIds) + { + CEikListBox& listBox = ListBox(); + TBool result = EFalse; + DisableRedrawEnablePushL(); + listBox.ClearSelection(); + if (aMarkedContactIds) + { + const TInt count = aMarkedContactIds->Count(); + for (TInt i=0; i < count; ++i) + { + const TInt index = FindContactIdL((*aMarkedContactIds)[i]); + if (index >= 0) + { + listBox.View()->SelectItemL(index); + result = ETrue; + } + } + } + CleanupStack::PopAndDestroy(); // DisableRedrawEnablePushL + return result; + } + +/** + * Creates control extension for a model, appends new icons + * and sets this object as control updator for the extension. + * + * @param aEngine provided for control extension + */ +void CPbkContactViewListControl::CreateControlExtensionL + (CPbkContactEngine& aEngine) + { + __ASSERT_DEBUG(&Model(), Panic(EPanicPre_SetControlExtensionL)); + __ASSERT_DEBUG(!iControlExtension, Panic(EPanicPre_SetControlExtensionL)); + + CPbkExtGlobals* extGlobal = CPbkExtGlobals::InstanceL(); + extGlobal->PushL(); + iControlExtension = extGlobal->FactoryL(). + CreatePbkUiControlExtensionL(aEngine); + CleanupStack::PopAndDestroy(extGlobal); + + Model().SetContactUiControlExtension(*iControlExtension); + + TInt arrayInfoId = 0; + TInt arrayId = 0; + iControlExtension->IconArrayResourceId(arrayInfoId, arrayId); + if ( arrayInfoId != 0 ) + { + IconArray(*iListBox)->AppendIconsFromResourceL(arrayInfoId, arrayId); + } + + iControlExtension->SetContactUiControlUpdate(this); + } + +void CPbkContactViewListControl::HandleResourceChange(TInt aType) + { + CPbkContactListControlBase::HandleResourceChange(aType); + + TRAP_IGNORE(DoHandleResourceChangeL(aType)); + } + +void CPbkContactViewListControl::RefreshIconArrayL() + { + // Control extension may be NULL when skin is changed at run-time + if (iControlExtension) + { + CPbkIconArray* iconArray = IconArray(*iListBox); + if (iconArray) + { + // refresh the main pbk icon array + iconArray->RefreshL(R_PBK_ICON_INFO_ARRAY); + // also refresh the control extension icon array + TInt arrayInfoId = 0; + TInt arrayId = 0; + iControlExtension->IconArrayResourceId(arrayInfoId, arrayId); + if (arrayInfoId != 0) + { + iconArray->RefreshL(arrayInfoId); + } + } + } + } + +void CPbkContactViewListControl::DoHandleResourceChangeL(TInt aType) + { + if (aType == KAknsMessageSkinChange) + { + RefreshIconArrayL(); + } + else if (aType == KEikDynamicLayoutVariantSwitch) + { + RefreshIconArrayL(); + SizeChanged(); + const TBool focused( IsFocused() ); + const TBool nonFocusing( IsNonFocusing() ); + if ( focused && !nonFocusing ) + { + ShowThumbnailL(); + } + DrawNow(); + } + } + + +// TCleanupEnableListBoxViewRedraw +void TCleanupEnableListBoxViewRedraw::CleanupOp(TAny* aPtr) + { + static_cast(aPtr)->SetDisableRedraw(EFalse); + } + +EXPORT_C void CPbkContactViewListControl::DeleteThumbnail() + { + delete iThumbnailPopup; + iThumbnailPopup = NULL; + } + +void CPbkContactViewListControl::EnableMSKObserver( TBool aEnable ) + { + iListBox->EnableMSKObserver(aEnable); + } + +TInt CPbkContactViewListControl::ItemCount() + { + return Model().MdcaCount(); + } + +// End of File +