phonebookui/Phonebook2/UIControls/src/CPbk2NamesListControl.cpp
branchRCL_3
changeset 20 f4a778e096c2
child 21 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/UIControls/src/CPbk2NamesListControl.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,2779 @@
+/*
+* Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Phonebook 2 names list control.
+*
+*/
+
+
+// INCLUDE FILES
+#include "CPbk2NamesListControl.h"
+
+// Phonebook 2
+#include "CPbk2NamesListStateFactory.h"
+#include "CPbk2ContactViewListBox.h"
+#include "CPbk2ThumbnailLoader.h"
+#include "cpbk2filteredviewstack.h"
+#include "MPbk2NamesListState.h"
+#include "MPbk2ControlObserver.h"
+#include "MPbk2UiControlEventSender.h"
+#include <CPbk2ControlContainer.h>
+#include <CPbk2ViewState.h>
+#include <Pbk2UIControls.hrh>
+#include <MPbk2Command.h>
+#include <MPbk2ContactUiControlExtension.h>
+#include <pbk2contactuicontroldoublelistboxextension.h>
+#include <MPbk2UIExtensionFactory.h>
+#include <CPbk2UIExtensionManager.h>
+#include "MPbk2FilteredViewStack.h"
+#include "cpbk2predictiveviewstack.h"
+#include <Pbk2Commands.hrh>
+#include <Pbk2InternalUID.h>
+#include "CPbk2PredictiveSearchFilter.h"
+#include "cpbk2contactviewdoublelistbox.h"
+#include <CPbk2ThumbnailManager.h>
+#include <Pbk2CommonUi.rsg>
+#include <Pbk2UIControls.rsg>
+#include "CPbk2AppUi.h"
+
+// Virtual Phonebook
+#include <MVPbkContactViewBase.h>
+#include <MVPbkViewContact.h>
+#include <MVPbkContactLink.h>
+#include <CVPbkContactLinkArray.h>
+
+// System includes
+#include <barsread.h>
+#include <aknsfld.h>
+#include <AknPriv.hrh>
+#include <featmgr.h>
+#include <AknWaitDialog.h>
+
+// Debugging headers
+#include <Pbk2Debug.h>
+
+
+/// Unnamed namespace for local definitions
+namespace {
+
+/**
+ * Handles errors.
+ *
+ * @param aErrorCode    Error code.
+ */
+void HandleError( TInt aErrorCode )
+    {
+    if ( aErrorCode != KErrNone )
+        {
+        // Display standard error message
+        CEikonEnv::Static()->HandleError( aErrorCode );
+        }
+    }
+
+#ifdef _DEBUG
+enum TPanicCode
+    {
+    EPanicLogic_ComponentControl = 1,
+    };
+
+void Panic(TPanicCode aReason)
+    {
+    _LIT(KPanicText, "CPbk2NamesListControl");
+    User::Panic(KPanicText, aReason);
+    }
+#endif // _DEBUG
+
+} /// namespace
+
+/**
+ * A helper class for sending control events.
+ */
+NONSHARABLE_CLASS( CPbk2UiControlEventSender ) : public CBase,
+                                                public MPbk2UiControlEventSender
+    {
+    public: // Construction and destruction
+
+        /**
+         * Creates a new instance of this class.
+         *
+         * @param aControl      Control.
+         * @param aObservers    Observers.
+         * @return  A new instance of this class.
+         */
+        static CPbk2UiControlEventSender* NewL(
+                CPbk2NamesListControl& aControl,
+                RPointerArray<MPbk2ControlObserver>& aObservers );
+
+        /**
+         * Destructor.
+         */
+       ~CPbk2UiControlEventSender();
+
+    public: /// From MPbk2UiControlEventSender
+        TBool SendEventToObserversL(
+                const TPbk2ControlEvent& aEvent );
+        void Reset();
+
+    private: // Implementation
+        CPbk2UiControlEventSender(
+                CPbk2NamesListControl& aControl,
+                RPointerArray<MPbk2ControlObserver>& aObservers );
+        void ConstructL();
+        TBool SendEvent(
+                const TPbk2ControlEvent& aEvent );
+
+    private: // Data
+        /// Ref: Control
+        CPbk2NamesListControl& iControl;
+        /// Ref: Observers
+        RPointerArray<MPbk2ControlObserver>& iObservers;
+        /// Own: Indicates has the ready event been sent
+        TBool iReadyEventSend;
+    };
+
+/**
+ * A helper class for hiding inheritance of MPbk2FilteredViewStackObserver
+ * from CPbk2NamesListControl.
+ */
+class CPbk2FilteredViewStackObserver  : public CBase,
+                                                      public MPbk2FilteredViewStackObserver
+    {
+    public: /// Typedefs
+        typedef void( CPbk2NamesListControl::* TopViewChangedFuncPtr )
+            ( MVPbkContactViewBase& aOldView );
+        typedef void( CPbk2NamesListControl::* ViewStackErrorFuncPtr )
+            ( TInt aError );
+        typedef void( CPbk2NamesListControl::* ContactAddedToBaseViewFuncPtr )
+            ( MVPbkContactViewBase& aBaseView,
+              TInt aIndex, const MVPbkContactLink& aContactLink );
+        typedef void( CPbk2NamesListControl::* TopViewUpdatedFuncPtr )();
+        typedef void( CPbk2NamesListControl::* BaseViewChangedFuncPtr )();
+
+    public: // Construction and destruction
+
+        /**
+         * Creates a new instance of this class.
+         *
+         * @param aControl                          Control.
+         * @param aViewStack                        View stack.
+         * @param aTopViewChangedFuncPtr            Top view changed function pointer.
+         * @param aTopViewUpdatedFuncPtr            Top view updated function pointer.
+         * @param aBaseViewChangedFuncPtr           Base view changed function pointer.
+         * @param aViewStackErrorFuncPtr            View stack error function pointer.
+         * @param aContactAddedToBaseViewFuncPtr    Contact added to base view function pointer.
+         * @return  A new instance of this class.
+         */
+        static CPbk2FilteredViewStackObserver* NewL(
+                CPbk2NamesListControl& aControl,
+                TopViewChangedFuncPtr aTopViewChangedFuncPtr,
+                TopViewUpdatedFuncPtr aTopViewUpdatedFuncPtr,
+                BaseViewChangedFuncPtr aBaseViewChangedFuncPtr,
+                ViewStackErrorFuncPtr aViewStackErrorFuncPtr,
+                ContactAddedToBaseViewFuncPtr aContactAddedToBaseViewFuncPtr );
+
+        /**
+         * Destructor.
+         */
+       ~CPbk2FilteredViewStackObserver();
+
+    private: // From MPbk2FilteredViewStackObserver
+        void TopViewChangedL(
+                MVPbkContactViewBase& aOldView );
+        void TopViewUpdatedL();
+        void BaseViewChangedL();
+        void ViewStackError(
+                    TInt aError );
+        void ContactAddedToBaseView(
+                    MVPbkContactViewBase& aBaseView,
+                    TInt aIndex,
+                    const MVPbkContactLink& aContactLink );
+
+    private: // Implementation
+        CPbk2FilteredViewStackObserver(
+                CPbk2NamesListControl& aControl,
+                TopViewChangedFuncPtr aTopViewChangedFuncPtr,
+                TopViewUpdatedFuncPtr aTopViewUpdatedFuncPtr,
+                BaseViewChangedFuncPtr aBaseViewChangedFuncPtr,
+                ViewStackErrorFuncPtr aViewStackErrorFuncPtr,
+                ContactAddedToBaseViewFuncPtr aContactAddedToBaseViewFuncPtr );
+        void ConstructL();
+
+    private: // Data
+        /// Ref: Control
+        CPbk2NamesListControl& iControl;
+        /// Ref: Top view changed function pointer
+        TopViewChangedFuncPtr iTopViewChangedFuncPtr;
+        /// Ref: Top view updated function pointer
+        TopViewUpdatedFuncPtr iTopViewUpdatedFuncPtr;
+        /// Ref: Base view changed function pointer
+        BaseViewChangedFuncPtr iBaseViewChangedFuncPtr;
+        /// Ref: View stack error function pointer
+        ViewStackErrorFuncPtr iViewStackErrorFuncPtr;
+        /// Ref: Contact added to base view function pointer
+        ContactAddedToBaseViewFuncPtr iContactAddedToBaseViewFuncPtr;
+    };
+
+/**
+ * An observer for list box selections. Sends control events
+ * when the list box enters to or from the selection mode.
+ */
+NONSHARABLE_CLASS( CPbk2ListBoxSelectionObserver ) :  public CBase,
+                                                        private MListBoxSelectionObserver
+    {
+    public: // Interface
+
+        /**
+         * Creates a new instance of this class.
+         *
+         * @param aListBox      The list box that is observed.
+         * @param aEventSender  An event sender for sending control
+         *                      events.
+         * @return  A new instance of this class.
+         */
+        static CPbk2ListBoxSelectionObserver* NewL(
+                CPbk2NamesListControl& aControl,
+                CEikListBox& aListBox,
+                MPbk2UiControlEventSender& aEventSender );
+
+        /**
+         * Destructor
+         */
+        ~CPbk2ListBoxSelectionObserver();
+
+    private: /// From MListBoxSelectionObserver
+        void SelectionModeChanged(
+                CEikListBox* aListBox,
+                TBool aSelectionModeEnabled );
+
+    private: // Implementation
+        CPbk2ListBoxSelectionObserver(
+                CPbk2NamesListControl& aControl,
+                CEikListBox& aListBox,
+                MPbk2UiControlEventSender& aEventSender );
+        void ConstructL();
+
+    private: // Data
+        /// Ref: Control
+        CPbk2NamesListControl& iControl;
+        /// Ref: List box
+        CEikListBox& iListBox;
+        /// Ref: Event sender
+        MPbk2UiControlEventSender& iEventSender;
+    };
+
+
+/**
+ * Background Task Handler.
+ */
+NONSHARABLE_CLASS(CPbk2NamesListControlBgTask) : public CActive
+    {
+
+    public:
+        CPbk2NamesListControlBgTask( CPbk2NamesListControl& aControl );
+        ~CPbk2NamesListControlBgTask();
+
+        void AddEvent( CPbk2NamesListControl::TPbk2NamesListBgEvents aEvent );
+        void ClearAllEvents();
+        void RemoveEvent( CPbk2NamesListControl::TPbk2NamesListBgEvents aEvent );
+
+    private: // From CActive
+        void DoCancel();
+        void RunL();
+        TInt RunError(TInt aError);
+
+    private:
+        //Owns
+        RArray <CPbk2NamesListControl::TPbk2NamesListBgEvents> iEventQueue;
+
+        //doesnt Own
+        CPbk2NamesListControl& iControl;
+    };
+
+/**
+ * A helper class for mass update cases.
+ */
+NONSHARABLE_CLASS( CPbk2HandleMassUpdate ) : public CBase
+    {
+    public: // Construction and destruction
+        /**
+         * Creates new instance of this class.
+         * @return new instance of this class.
+         */
+        static CPbk2HandleMassUpdate* NewL(CEikListBox& iListBox);
+
+        /**
+         * Destructor.
+         */
+       ~CPbk2HandleMassUpdate();
+
+    public:
+        /**
+         * Call this function after each update event.
+         * @return  ETrue if this event is part of a mass update.
+         */
+       TBool MassUpdateCheckThis();
+
+        /**
+         * Call this function to check if mass update process is ongoing.
+         * @return  ETrue if mass update process is ongoing.
+         */
+       TBool MassUpdateDetected();
+       
+       /**
+        * Call this function to skip the showing of blocking progress note.
+        * When done MassUpdateSkipProgressNote( EFalse ) must be called to reset.
+        */
+      void MassUpdateSkipProgressNote( TBool aSkip );       
+
+    private:
+        CPbk2HandleMassUpdate(CEikListBox& iListBox);
+        void ConstructL();
+        TBool HandleMassUpdateCheckL();
+        void HandleMassUpdateBurstL(
+            const TTimeIntervalMicroSeconds aFromFirst, 
+            const TInt64 aDeltaMax64);        
+        void HandleMassUpdateResetCounters();
+        void HandleMassUpdateDone();
+        static TInt HandleMassUpdateTimerCallBack(TAny* aAny);
+
+    private:
+        CEikListBox& iListBox;
+        TBool iHandleMassUpdateDetected;
+        TTime iHandleMassUpdateFirst;
+        TTime iHandleMassUpdatePrev;
+        TInt  iHandleMassUpdateCount;
+        TBool iHandleMassUpdateSkipDialog;        
+        CPeriodic* iHandleMassUpdateTimer;
+        CAknWaitDialog*  iHandleMassUpdateDialog;
+    };
+
+// --------------------------------------------------------------------------
+// CPbk2UiControlEventSender::CPbk2UiControlEventSender
+// --------------------------------------------------------------------------
+//
+CPbk2UiControlEventSender::CPbk2UiControlEventSender
+        ( CPbk2NamesListControl& aControl,
+          RPointerArray<MPbk2ControlObserver>& aObservers ) :
+            iControl( aControl ),
+            iObservers( aObservers )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2UiControlEventSender::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2UiControlEventSender* CPbk2UiControlEventSender::NewL(
+        CPbk2NamesListControl& aControl,
+        RPointerArray<MPbk2ControlObserver>& aObservers )
+    {
+    CPbk2UiControlEventSender* self =
+        new ( ELeave ) CPbk2UiControlEventSender( aControl, aObservers );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2UiControlEventSender::~CPbk2UiControlEventSender
+// --------------------------------------------------------------------------
+//
+CPbk2UiControlEventSender::~CPbk2UiControlEventSender()
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2UiControlEventSender::SendEventToObserversL
+// Sends control observer events in reverse order to disable the possibility
+// of crash if aObserver is changed during the loop.
+// --------------------------------------------------------------------------
+//
+TBool CPbk2UiControlEventSender::SendEventToObserversL(
+        const TPbk2ControlEvent& aEvent )
+    {
+    // Loop backwards in case some observer destroys itself in the
+    // event handler
+    TBool okToSendEvent( SendEvent( aEvent ) );
+    for ( TInt i = iObservers.Count() - 1; i >= 0 && okToSendEvent; --i )
+        {
+        iObservers[i]->HandleControlEventL( iControl, aEvent );
+        }
+
+    return okToSendEvent;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2UiControlEventSender::Reset
+// Resets event sender
+// --------------------------------------------------------------------------
+//
+void CPbk2UiControlEventSender::Reset()
+    {
+    iReadyEventSend = EFalse;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2UiControlEventSender::SendEvent
+// Makes sure that ready event is send only ones and reset the status
+// if control goes unavailable
+// --------------------------------------------------------------------------
+//
+TBool CPbk2UiControlEventSender::SendEvent
+        ( const TPbk2ControlEvent& aEvent )
+    {
+    TBool ret( ETrue );
+    if ( aEvent.iEventType == TPbk2ControlEvent::EUnavailable )
+        {
+        iReadyEventSend = EFalse;
+        }
+    else if ( aEvent.iEventType == TPbk2ControlEvent::EReady )
+        {
+        if ( iReadyEventSend )
+            {
+            ret = EFalse;
+            }
+        else
+            {
+            iReadyEventSend = ETrue;
+            }
+        }
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStackObserver::CPbk2FilteredViewStackObserver
+// --------------------------------------------------------------------------
+//
+CPbk2FilteredViewStackObserver::CPbk2FilteredViewStackObserver(
+        CPbk2NamesListControl& aControl,
+        TopViewChangedFuncPtr aTopViewChangedFuncPtr,
+        TopViewUpdatedFuncPtr aTopViewUpdatedFuncPtr,
+        BaseViewChangedFuncPtr aBaseViewChangedFuncPtr,
+        ViewStackErrorFuncPtr aViewStackErrorFuncPtr,
+        ContactAddedToBaseViewFuncPtr aContactAddedToBaseViewFuncPtr ) :
+            iControl( aControl ),
+            iTopViewChangedFuncPtr( aTopViewChangedFuncPtr ),
+            iTopViewUpdatedFuncPtr( aTopViewUpdatedFuncPtr ),
+            iBaseViewChangedFuncPtr( aBaseViewChangedFuncPtr ),
+            iViewStackErrorFuncPtr( aViewStackErrorFuncPtr ),
+            iContactAddedToBaseViewFuncPtr( aContactAddedToBaseViewFuncPtr )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStackObserver::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2FilteredViewStackObserver* CPbk2FilteredViewStackObserver::NewL(
+        CPbk2NamesListControl& aControl,
+        TopViewChangedFuncPtr aTopViewChangedFuncPtr,
+        TopViewUpdatedFuncPtr aTopViewUpdatedFuncPtr,
+        BaseViewChangedFuncPtr aBaseViewChangedFuncPtr,
+        ViewStackErrorFuncPtr aViewStackErrorFuncPtr,
+        ContactAddedToBaseViewFuncPtr aContactAddedToBaseViewFuncPtr )
+    {
+    CPbk2FilteredViewStackObserver* self =
+        new ( ELeave ) CPbk2FilteredViewStackObserver( aControl,
+            aTopViewChangedFuncPtr,
+            aTopViewUpdatedFuncPtr,
+            aBaseViewChangedFuncPtr,
+            aViewStackErrorFuncPtr,
+            aContactAddedToBaseViewFuncPtr );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStackObserver::ConstructL
+// --------------------------------------------------------------------------
+//
+void CPbk2FilteredViewStackObserver::ConstructL()
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStackObserver::~CPbk2FilteredViewStackObserver
+// --------------------------------------------------------------------------
+//
+CPbk2FilteredViewStackObserver::~CPbk2FilteredViewStackObserver()
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStackObserver::TopViewChangedL
+// --------------------------------------------------------------------------
+//
+void CPbk2FilteredViewStackObserver::TopViewChangedL(
+        MVPbkContactViewBase& aOldView )
+    {
+    ( iControl.*iTopViewChangedFuncPtr )( aOldView );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStackObserver::TopViewUpdatedL
+// --------------------------------------------------------------------------
+//
+void CPbk2FilteredViewStackObserver::TopViewUpdatedL()
+    {
+    ( iControl.*iTopViewUpdatedFuncPtr )();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStackObserver::BaseViewChangedL
+// --------------------------------------------------------------------------
+//
+void CPbk2FilteredViewStackObserver::BaseViewChangedL()
+    {
+    ( iControl.*iBaseViewChangedFuncPtr )();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStackObserver::ViewStackError
+// --------------------------------------------------------------------------
+//
+void CPbk2FilteredViewStackObserver::ViewStackError( TInt aError )
+    {
+    ( iControl.*iViewStackErrorFuncPtr )( aError );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2FilteredViewStackObserver::ContactAddedToBaseView
+// --------------------------------------------------------------------------
+//
+void CPbk2FilteredViewStackObserver::ContactAddedToBaseView(
+        MVPbkContactViewBase& aBaseView, TInt aIndex,
+        const MVPbkContactLink& aContactLink )
+    {
+    ( iControl.*iContactAddedToBaseViewFuncPtr )( aBaseView,
+         aIndex, aContactLink );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ListBoxSelectionObserver::CPbk2ListBoxSelectionObserver
+// --------------------------------------------------------------------------
+//
+CPbk2ListBoxSelectionObserver::CPbk2ListBoxSelectionObserver(
+        CPbk2NamesListControl& aControl, CEikListBox& aListBox,
+        MPbk2UiControlEventSender& aEventSender )
+        :   iControl( aControl ),
+            iListBox( aListBox ),
+            iEventSender( aEventSender )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ListBoxSelectionObserver::ConstructL
+// --------------------------------------------------------------------------
+//
+void CPbk2ListBoxSelectionObserver::ConstructL()
+    {
+    iListBox.AddSelectionObserverL( this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ListBoxSelectionObserver::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2ListBoxSelectionObserver* CPbk2ListBoxSelectionObserver::NewL(
+        CPbk2NamesListControl& aControl,
+        CEikListBox& aListBox,
+        MPbk2UiControlEventSender& aEventSender )
+    {
+    CPbk2ListBoxSelectionObserver* self =
+        new( ELeave ) CPbk2ListBoxSelectionObserver( aControl, aListBox,
+            aEventSender );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ListBoxSelectionObserver::~CPbk2ListBoxSelectionObserver
+// --------------------------------------------------------------------------
+//
+CPbk2ListBoxSelectionObserver::~CPbk2ListBoxSelectionObserver()
+    {
+    iListBox.RemoveSelectionObserver( this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ListBoxSelectionObserver::SelectionModeChanged
+// --------------------------------------------------------------------------
+//
+void CPbk2ListBoxSelectionObserver::SelectionModeChanged(
+        CEikListBox* aListBox, TBool aSelectionModeEnabled )
+    {
+    if ( &iListBox == aListBox )
+        {
+        TPbk2ControlEvent event(
+            TPbk2ControlEvent::EControlEntersSelectionMode );
+        if ( !aSelectionModeEnabled )
+            {
+            event.iEventType =
+                TPbk2ControlEvent::EControlLeavesSelectionMode;
+            }
+        TRAPD( res, iEventSender.SendEventToObserversL( event ) );
+        HandleError( res );
+        if ( res != KErrNone )
+            {
+            iControl.Reset();
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2HandleMassUpdate* CPbk2HandleMassUpdate::NewL(CEikListBox& aListBox)
+    {
+    CPbk2HandleMassUpdate* self =
+        new( ELeave ) CPbk2HandleMassUpdate(aListBox);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::~CPbk2HandleMassUpdate
+// --------------------------------------------------------------------------
+//
+CPbk2HandleMassUpdate::~CPbk2HandleMassUpdate()
+    {
+    delete iHandleMassUpdateDialog;
+    delete iHandleMassUpdateTimer;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::CPbk2HandleMassUpdate
+// --------------------------------------------------------------------------
+//
+CPbk2HandleMassUpdate::CPbk2HandleMassUpdate(CEikListBox& aListBox) :
+    iListBox(aListBox)
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::ConstructL
+// --------------------------------------------------------------------------
+//
+void CPbk2HandleMassUpdate::ConstructL()
+    {
+    iHandleMassUpdateTimer = CPeriodic::NewL( CActive::EPriorityIdle );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::HandleMassUpdateCheckThis
+//
+// Functionality to detect mass updates done to contact database and to prevent
+// e.g nameslist flickering when constant updates are happening in background
+// when pc sync etc is adding hundreds of contacts in line
+// --------------------------------------------------------------------------
+//
+TBool CPbk2HandleMassUpdate::MassUpdateCheckThis()
+    {
+    TBool ret(EFalse);
+    const TInt KNbrUpdBeforeMassCheck(5);
+    iHandleMassUpdateTimer->Cancel();
+
+    if( iHandleMassUpdateCount > KNbrUpdBeforeMassCheck )
+        {
+        //candidates to be checked are they continual of a mass update
+        TRAP_IGNORE(ret = HandleMassUpdateCheckL());
+        }
+    else if( iHandleMassUpdateCount > 0 )
+        {
+        //Subsequent updates that are handled normally even if
+        // they would be first ones in a mass update burst
+        iHandleMassUpdateCount++;
+        iHandleMassUpdatePrev.UniversalTime();
+        }
+    else
+        {
+        //very first update, reset time & counter
+        HandleMassUpdateResetCounters();
+        }
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::MassUpdateDetected
+// --------------------------------------------------------------------------
+//
+TBool CPbk2HandleMassUpdate::MassUpdateDetected()
+    {
+    return iHandleMassUpdateDetected;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::MassUpdateSkipProgressNote
+// --------------------------------------------------------------------------
+//
+void CPbk2HandleMassUpdate::MassUpdateSkipProgressNote( TBool aSkip )
+    {
+    iHandleMassUpdateSkipDialog = aSkip;
+    HandleMassUpdateResetCounters();        
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::HandleMassUpdateCheckL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2HandleMassUpdate::HandleMassUpdateCheckL()
+    {
+    //KDeltaAverage time per update to be considered as mass
+    //update. One occasional update can take KDeltaMax time as long as
+    //average time not exeeded (therefore timeout for the very first updates in
+    //practice is also KDeltaAverage).
+    const TInt64 KDeltaAverage(2000000);
+    const TInt64 KDeltaMax(KDeltaAverage * 2);
+    const TTimeIntervalMicroSeconds KMaxPrev(KDeltaMax);
+    TBool ret(EFalse);
+
+    TTime now;
+    now.UniversalTime();
+    TTimeIntervalMicroSeconds fromFirst = 
+            now.MicroSecondsFrom(iHandleMassUpdateFirst);
+    TTimeIntervalMicroSeconds fromPrev = 
+            now.MicroSecondsFrom(iHandleMassUpdatePrev);
+    TTimeIntervalMicroSeconds maxCumu(KDeltaAverage * iHandleMassUpdateCount);
+
+    if( fromFirst < maxCumu && fromPrev < KMaxPrev )
+        {
+        //mass update burst ongoing
+        HandleMassUpdateBurstL(fromFirst, KDeltaMax);    
+        ret = ETrue;    
+        }
+    else if(iHandleMassUpdateDetected)
+        {
+        //mass update burst ended
+        HandleMassUpdateDone();
+        ret = ETrue;
+        }
+    else
+        {
+        //just normal update so reset counters
+        HandleMassUpdateResetCounters();
+        }
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::HandleMassUpdateBurstL
+// --------------------------------------------------------------------------
+//
+void CPbk2HandleMassUpdate::HandleMassUpdateBurstL(
+    const TTimeIntervalMicroSeconds aFromFirst,
+    const TInt64 aDeltaMax64)
+    {
+    const TInt64 KMinWaitBeforeBlockUi(1500000);    
+    const TTimeIntervalMicroSeconds KWait(KMinWaitBeforeBlockUi);    
+    
+    //mass update burst ongoing, nameslist behaviour can be altered
+    iHandleMassUpdateDetected=ETrue;
+    iHandleMassUpdateCount++;
+    iHandleMassUpdatePrev.UniversalTime();
+    iListBox.UpdateScrollBarsL();
+
+    if( !iHandleMassUpdateDialog && 
+        !iHandleMassUpdateSkipDialog && 
+        aFromFirst > KWait)        
+        {
+        //mass update burst ongoing, ok also to block ui
+        iHandleMassUpdateDialog = new(ELeave) CAknWaitDialog
+            (reinterpret_cast<CEikDialog**>(&iHandleMassUpdateDialog), EFalse);
+        iHandleMassUpdateDialog->SetTone(CAknNoteDialog::ENoTone);
+        iHandleMassUpdateDialog->ExecuteLD(R_QTN_GEN_NOTE_SYNCHRONIZING_PROGRESS);
+        //ExecuteLD above handles validity of pointer iHandleMassUpdateDialog plus
+        //cleanupstack
+        }
+    else if( iHandleMassUpdateDialog && iHandleMassUpdateSkipDialog)
+        {
+        //burst ongoing but do not not block ui
+        TRAP_IGNORE(iHandleMassUpdateDialog->ProcessFinishedL());
+        delete iHandleMassUpdateDialog;
+        iHandleMassUpdateDialog = NULL;        
+        }
+
+    TCallBack callback(HandleMassUpdateTimerCallBack, this);
+    TTimeIntervalMicroSeconds32 delta32(aDeltaMax64);
+    iHandleMassUpdateTimer->Start( delta32, delta32, callback );
+    }
+
+// ----------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::HandleMassUpdateResetCounters
+// ----------------------------------------------------------------------------
+//
+void CPbk2HandleMassUpdate::HandleMassUpdateResetCounters()
+    {
+    iHandleMassUpdateCount = 1;  //set as first candidate for next burst
+    iHandleMassUpdateFirst.UniversalTime();
+    iHandleMassUpdatePrev=iHandleMassUpdateFirst;
+    }
+
+// ----------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::HandleMassUpdateTimerCallBack
+// ----------------------------------------------------------------------------
+//
+TInt CPbk2HandleMassUpdate::HandleMassUpdateTimerCallBack(TAny* aAny)
+    {
+    CPbk2HandleMassUpdate* self = static_cast<CPbk2HandleMassUpdate*>( aAny );
+    self->iHandleMassUpdateTimer->Cancel();
+    self->HandleMassUpdateDone();
+    return KErrNone;
+    }
+
+// ----------------------------------------------------------------------------
+// CPbk2HandleMassUpdate::HandleMassUpdateDone
+// ----------------------------------------------------------------------------
+//
+void CPbk2HandleMassUpdate::HandleMassUpdateDone()
+    {
+    if( iHandleMassUpdateDialog )
+        {
+        TRAP_IGNORE(iHandleMassUpdateDialog->ProcessFinishedL());
+        //The below 2 lines just in case... ProcessFinishedL already took care of these
+        delete iHandleMassUpdateDialog;
+        iHandleMassUpdateDialog = NULL;
+        }
+
+    iHandleMassUpdateDetected = EFalse;
+    HandleMassUpdateResetCounters();
+    iListBox.SetCurrentItemIndex(0);
+    iListBox.SetTopItemIndex(0);
+
+    //Update the items of listbox in NameListView
+    iListBox.DrawDeferred();
+    }
+
+///////////////////////// End of helper classes /////////////////////////////
+
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::CPbk2NamesListControl
+// --------------------------------------------------------------------------
+//
+EXPORT_C CPbk2NamesListControl::CPbk2NamesListControl
+            (const CCoeControl* aContainer,
+            CVPbkContactManager& aManager,
+            MVPbkContactViewBase& aView,
+            MPbk2ContactNameFormatter& aNameFormatter,
+            CPbk2StorePropertyArray& aStoreProperties) :
+                iContactManager( aManager ),
+                iBaseView( &aView ),
+                iContainer( aContainer ),
+                iNameFormatter( aNameFormatter ),
+                iStoreProperties( aStoreProperties ),
+                iAllowPointerEvents( ETrue ),
+                iOpeningCca( EFalse ),
+                iMarkingModeOn( EFalse )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::CPbk2NamesListControl
+// --------------------------------------------------------------------------
+//
+CPbk2NamesListControl::CPbk2NamesListControl
+            (const CCoeControl* aContainer,
+            CVPbkContactManager& aManager,
+            MVPbkContactViewBase& aView,
+            MPbk2ContactNameFormatter& aNameFormatter,
+            CPbk2StorePropertyArray& aStoreProperties,
+            CPbk2ThumbnailManager* aThumbManager) :
+                iContactManager( aManager ),
+                iBaseView( &aView ),
+                iContainer( aContainer ),
+                iNameFormatter( aNameFormatter ),
+                iStoreProperties( aStoreProperties ),
+                iAllowPointerEvents( ETrue ),                
+                iThumbManager( aThumbManager ),
+                iOpeningCca( EFalse )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::~CPbk2NamesListControl
+// --------------------------------------------------------------------------
+//
+CPbk2NamesListControl::~CPbk2NamesListControl()
+    {
+    ClearMarkedContactsInfo();
+
+    if (iBgTask)
+        {
+        delete iBgTask;
+        iBgTask = NULL;
+        }
+
+    if ( iViewStack && iStackObserver )
+        {
+        iViewStack->RemoveStackObserver( *iStackObserver );
+        }
+
+    if( iThumbManager )
+        {
+        TRAP_IGNORE( iThumbManager->SetContactViewL( NULL ) );
+        iThumbManager->RemoveObserver();
+        }
+
+    if (iCommand)
+        {
+        // inform the command that the control is deleted
+        iCommand->ResetUiControl(*this);
+        }
+    iObservers.Reset();
+    iCommandItems.ResetAndDestroy();
+    delete iCheckMassUpdate;
+    delete iListBoxSelectionObserver;
+    delete iStateFactory;
+    delete iListBox;
+    delete iFindBox;
+    delete iThumbnailLoader;
+    delete iEventSender;
+    delete iStackObserver;
+    delete iUiExtension;
+    delete iViewStack;
+    delete iSearchFilter;
+    if( iOwnThumbManager )
+        {
+        delete iThumbManager;
+        }
+    if (iOwnBaseView)
+        {
+        delete iBaseView;
+        }
+    if(iFeatureManagerInitilized)
+        {
+        FeatureManager::UnInitializeLib();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::NewL
+// --------------------------------------------------------------------------
+//
+EXPORT_C CPbk2NamesListControl* CPbk2NamesListControl::NewL(
+            TInt aResourceId,
+            const CCoeControl* aContainer,
+            CVPbkContactManager& aManager,
+            MVPbkContactViewBase& aView,
+            MPbk2ContactNameFormatter& aNameFormatter,
+            CPbk2StorePropertyArray& aStoreProperties )
+    {
+    CPbk2NamesListControl* self = new (ELeave) CPbk2NamesListControl(
+            aContainer, aManager, aView, aNameFormatter, aStoreProperties );
+    CleanupStack::PushL(self);
+    self->ConstructL( aResourceId);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::NewL
+// --------------------------------------------------------------------------
+//
+EXPORT_C CPbk2NamesListControl* CPbk2NamesListControl::NewL(
+               TInt aResourceId,
+               const CCoeControl* aContainer,
+               CVPbkContactManager& aManager,
+               MVPbkContactViewBase& aView,
+               MPbk2ContactNameFormatter& aNameFormatter,
+               CPbk2StorePropertyArray& aStoreProperties,
+               CPbk2ThumbnailManager* aThumbManager )
+    {
+    CPbk2NamesListControl* self = new (ELeave) CPbk2NamesListControl(
+            aContainer, aManager, aView, aNameFormatter, aStoreProperties, aThumbManager );
+    CleanupStack::PushL(self);
+    self->ConstructL( aResourceId);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ConstructL
+//
+// Note that NewL (and hence ConstructL) will not be called when custom control  
+// constructed. Instead public constructor and ConstructFromResourceL are 
+// called (happens when ServerApp launches custom fetch dialog)
+// --------------------------------------------------------------------------
+//
+inline void CPbk2NamesListControl::ConstructL(
+    TInt aResourceId)
+    {
+    if (!iContainer)
+        {
+        User::Leave(KErrGeneral);
+        }
+
+    // First set container
+    SetContainerWindowL(*iContainer);
+
+    TResourceReader resReader;
+    CCoeEnv::Static()->CreateResourceReaderLC(resReader, aResourceId);
+    ConstructFromResourceL(resReader);
+    CleanupStack::PopAndDestroy(); // resReader
+    FeatureManager::InitializeLibL();
+    iFeatureManagerInitilized = ETrue;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ConstructFromResourceL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2NamesListControl::ConstructFromResourceL
+        ( TResourceReader& aReader )
+    {
+    iSearchFilter = CPbk2PredictiveSearchFilter::NewL();
+
+    if(FeatureManager::FeatureSupported(KFeatureIdFfContactsPredictiveSearch))
+
+        {
+        iViewStack = CPbk2PredictiveViewStack::NewL( *iBaseView, *iSearchFilter,
+                                iNameFormatter  );
+        }
+    else
+        {
+        iViewStack = CPbk2FilteredViewStack::NewL( *iBaseView );
+        }
+
+    iViewStack->AddObserverL( *this );
+
+    iStackObserver = CPbk2FilteredViewStackObserver::NewL
+        ( *this,
+          &CPbk2NamesListControl::HandleTopViewChangedL,
+          &CPbk2NamesListControl::HandleTopViewUpdatedL,
+          &CPbk2NamesListControl::HandleBaseViewChangedL,
+          &CPbk2NamesListControl::HandleViewStackError,
+          &CPbk2NamesListControl::HandleContactAddedToBaseView );
+    iEventSender = CPbk2UiControlEventSender::NewL( *this, iObservers );
+    iViewStack->AddStackObserverL( *iStackObserver );
+
+
+    CPbk2UIExtensionManager* extManager =
+        CPbk2UIExtensionManager::InstanceL();
+    extManager->PushL();
+
+    iUiExtension = extManager->FactoryL()->CreatePbk2UiControlExtensionL
+        ( iContactManager );
+
+    CleanupStack::PopAndDestroy(); // extManager
+
+    // peek listbox type from resource
+    TInt flags = aReader.ReadInt32();
+    aReader.Rewind( sizeof( TInt32 ) );
+
+    // Create the listbox and its model
+    if( flags & KPbk2ContactViewListControlDoubleRow )
+        {
+        if( !iThumbManager )
+            {
+            iThumbManager = CPbk2ThumbnailManager::NewL( iContactManager );
+            iOwnThumbManager = ETrue;
+            }
+
+        iDoubleListBox = CPbk2ContactViewDoubleListBox::NewL
+            ( *this, aReader, iContactManager,
+            *iViewStack, iNameFormatter, iStoreProperties,
+            iUiExtension, *iSearchFilter, *iThumbManager );
+
+        iThumbManager->SetObserver( *iDoubleListBox );
+        iThumbManager->SetContactViewL( iViewStack );
+
+        iListBox = iDoubleListBox;
+        }
+    else
+        {
+        iListBox = CPbk2ContactViewListBox::NewL
+            ( *this, aReader, iContactManager,
+            *iViewStack, iNameFormatter, iStoreProperties,
+            iUiExtension, *iSearchFilter );
+
+        if( iThumbManager )
+            {
+            iThumbManager->RemoveObserver();
+            }
+        iDoubleListBox = NULL;
+        }
+
+    iListBox->SetObserver( this );
+    iListBox->SetScrollEventObserver( this );
+    iListBox->SetListBoxObserver(this);
+    
+    iListBox->SetMarkingModeObserver( this );
+    
+    iUiExtension->SetContactUiControlUpdate( this );
+    // set command item updater
+    TAny* ext = iUiExtension->ContactUiControlExtensionExtension(
+        TUid::Uid( KPbk2ContactUiControlExtensionExtensionUID ) );
+    if( ext )
+        {
+        static_cast<MPbk2ContactUiControlDoubleListboxExtension*>(ext)->
+            SetCommandItemUpdater( this );
+        }
+
+    if ( iListBox->Flags() & KPbk2ContactViewListControlFindBox )
+        {
+        // Create a find box
+        if ( iSearchFilter->IsPredictiveActivated() )
+            {
+            iFindBox = CAknSearchField::NewL
+            (*this, CAknSearchField::ESearch, NULL, KSearchFieldLength);
+            }
+        else
+            {
+            iFindBox = CAknSearchField::NewL
+                        (*this, CAknSearchField::EAdaptiveSearch, NULL, KSearchFieldLength);
+            }
+
+        iSearchFilter->SetAknSearchFieldL( iFindBox );
+
+        iFindBox->MakeVisible( EFalse );
+        iFindBox->SetObserver( this );
+        iFindBox->AddAdaptiveSearchTextObserverL( this );
+        }
+
+    // If list box supports selection then construct an observer that
+    // handles the event sending when the selection mode changes.
+    if ( iListBox->IsSelectionListBox() )
+        {
+        iListBoxSelectionObserver = CPbk2ListBoxSelectionObserver::NewL(
+            *this, *iListBox, *iEventSender );
+        }
+
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::ConstructL find box created"));
+
+    // Instantiate the state factory
+    iStateFactory = CPbk2NamesListStateFactory::NewL( *this, *iListBox,
+        *iViewStack, iFindBox, *iThumbnailLoader, *iEventSender,
+        iNameFormatter, iCommandItems, *iSearchFilter );
+
+    // Create the initial state
+    iCurrentState = &iStateFactory->ActivateStartupStateL( iCurrentState );
+
+    iBgTask = new (ELeave) CPbk2NamesListControlBgTask( *this );
+    iCheckMassUpdate = CPbk2HandleMassUpdate::NewL(*iListBox); //iListbox created above    
+    
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::ConstructFromResourceL end"));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::AddObserverL
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2NamesListControl::AddObserverL
+        ( MPbk2ControlObserver& aObserver )
+    {
+    User::LeaveIfError(iObservers.Append(&aObserver));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::RemoveObserver
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2NamesListControl::RemoveObserver
+        ( MPbk2ControlObserver& aObserver )
+    {
+    const TInt index = iObservers.Find(&aObserver);
+    if (index >= 0)
+        {
+        iObservers.Remove(index);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::Reset
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2NamesListControl::Reset()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING("CPbk2NamesListControl::Reset(0x%x) - IN"),
+        this );
+
+    // Reset find box
+    TRAP_IGNORE( ResetFindL() );
+    // Destroy all the filtered views from the stack
+    iViewStack->Reset();
+    // Refresh observer to get the view state
+    iViewStack->RemoveObserver( *this );
+    // Shouldn't leave because the observer was first removed.
+    // The control updates its state when the asynchronous Virtual Phonebook
+    // view event arrives.
+    TRAP_IGNORE( iViewStack->AddObserverL( *this ) );
+
+    const TInt firstContactIndex = 0;
+    // Best effort: try to reset the focus.
+    TRAP_IGNORE( iCurrentState->SetFocusedContactIndexL( firstContactIndex ) );
+    //scroll listbox into beginning (ignore focus that may be below promotion items)
+    iListBox->SetTopItemIndex(firstContactIndex);
+    
+    //cancel the marking mode
+    iListBox->SetMarkingMode( EFalse );
+
+    // Switch to the background state. This enables the next state to avtivate fully (ActivateStateL()) once phonebook
+    // comes from the background.
+    TRAP_IGNORE( iCurrentState = &iStateFactory->ActivateHiddenStateL( iCurrentState ); );
+
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING("CPbk2NamesListControl::Reset() - OUT"));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetViewL
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2NamesListControl::SetViewL( MVPbkContactViewBase& aView )
+    {
+    // Control will receive a view event asynchronously from the stack
+    iViewStack->SetNewBaseViewL( aView );
+
+    if (iOwnBaseView)
+        {
+        delete iBaseView;
+        iBaseView = NULL;
+        }
+
+    iBaseView = &aView;
+    iOwnBaseView = EFalse;
+
+    iEventSender->Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::GiveViewL
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2NamesListControl::GiveViewL( MVPbkContactViewBase* aView )
+    {
+    SetViewL( *aView );
+    iOwnBaseView = ETrue;
+    }
+
+EXPORT_C void CPbk2NamesListControl::AllowPointerEvents( TBool aAllow )
+    {
+    iAllowPointerEvents = aAllow;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetCurrentGroupLinkL
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2NamesListControl::SetCurrentGroupLinkL( MVPbkContactLink* aGroupLinktoSet)
+    {
+    // This is used only when predictive search is enabled
+    if(FeatureManager::FeatureSupported(KFeatureIdFfContactsPredictiveSearch))
+        {
+        static_cast<CPbk2PredictiveViewStack*> (iViewStack)->SetCurrentGroupLinkL(aGroupLinktoSet);
+        }
+    return;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::MassUpdateSkipProgressNote
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2NamesListControl::MassUpdateSkipProgressNote( TBool aSkip )
+    {
+    iCheckMassUpdate->MassUpdateSkipProgressNote( aSkip ); 
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::View
+// --------------------------------------------------------------------------
+//
+MVPbkContactViewBase& CPbk2NamesListControl::View()
+    {
+    return *iViewStack;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::MakeVisible
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::MakeVisible(TBool aVisible)
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2NamesListControl::MakeVisible(0x%x,%d)"),
+        this, aVisible);
+
+    CCoeControl::MakeVisible(aVisible);
+    iCurrentState->MakeComponentsVisible(aVisible);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ActivateL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ActivateL()
+    {
+    // First, call base class implementation
+    CCoeControl::ActivateL();
+    // Then do own initialization
+    iCurrentState->ActivateL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::OfferKeyEventL
+// --------------------------------------------------------------------------
+//
+TKeyResponse CPbk2NamesListControl::OfferKeyEventL
+        ( const TKeyEvent& aKeyEvent, TEventCode aType )
+    {
+    if(FeatureManager::FeatureSupported(KFeatureIdFfContactsPredictiveSearch))
+        {
+        if( iCurrentState->NamesListState() == EStateReady ||
+            iCurrentState->NamesListState() == EStateFiltered )
+            {
+            iSearchFilter->FilterL( aKeyEvent, aType, iFindBox );
+            }
+        }
+
+    TKeyResponse result = iSearchFilter->OfferKeyEventL( aKeyEvent, aType );
+
+    if ( result == EKeyWasNotConsumed )
+        {
+        result = iCurrentState->OfferKeyEventL( aKeyEvent, aType );
+        }
+
+    // Ignore Send Key up and down events to prevent Dialer appearance
+    // on top of Phonebook application.
+    if ( result == EKeyWasNotConsumed && iListBox->NumberOfItems() != 0 )
+        {
+        if ( ( aType == EEventKeyDown || aType == EEventKeyUp )
+            && aKeyEvent.iScanCode == EStdKeyYes )
+            {
+            result = EKeyWasConsumed;
+            }
+        }
+
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::CountComponentControls
+// --------------------------------------------------------------------------
+//
+TInt CPbk2NamesListControl::CountComponentControls() const
+    {
+    return iCurrentState->CountComponentControls();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ComponentControl
+// --------------------------------------------------------------------------
+//
+CCoeControl* CPbk2NamesListControl::ComponentControl(TInt aIndex) const
+    {
+    // This is not forwarded to the states because these controls are
+    // always existing. It does not matter what is the state.
+    switch (aIndex)
+        {
+        case 0:
+            {
+            return iListBox;
+            }
+        case 1:
+            {
+            return iFindBox;
+            }
+        default:
+            {
+            // Illegal state
+            __ASSERT_DEBUG( EFalse, Panic( EPanicLogic_ComponentControl ) );
+            return NULL;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FocusChanged
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::FocusChanged( TDrawNow aDrawNow )
+    {
+    if ( iListBox )
+        {
+        iListBox->SetFocus( IsFocused(), aDrawNow );
+        }
+
+    if ( iFindBox && iFindBox->IsVisible() )
+        {
+        iFindBox->SetFocus( IsFocused(), aDrawNow );
+        if ( aDrawNow == EDrawNow && IsFocused() )
+            {
+            iFindBox->DrawDeferred();
+            }
+        }
+
+    if (iCurrentState && IsNonFocusing())
+        {
+        iCurrentState->CoeControl().SetFocus(IsFocused(), aDrawNow);
+        }
+    if ( IsFocused() )
+        {
+        ShowThumbnail();
+        }
+    else
+        {
+        HideThumbnail();
+        }
+    TRAP_IGNORE(ReportEventL( MCoeControlObserver::EEventStateChanged ));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SizeChanged
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SizeChanged()
+    {
+    iCurrentState->SizeChanged();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::Draw
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::Draw(const TRect& aRect) const
+    {
+    CWindowGc& gc = SystemGc();
+    iCurrentState->Draw(aRect, gc);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleResourceChange
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleResourceChange(TInt aType)
+    {
+    CCoeControl::HandleResourceChange(aType);
+    if ( iFindBox != NULL && aType == KAknMessageFocusLost )
+        {
+        iFindBox->DrawDeferred();
+        }
+
+/*  This is useless...no need to show or hide thumbnail on layout/skin change...thumbnail will handle it's own resouce change event
+    if ( aType == KEikDynamicLayoutVariantSwitch ||
+         aType == KAknsMessageSkinChange )
+        {
+        if ( IsFocused() )
+            {
+            RDebug::Print( _L("### NamesList::HandleResourceChangeL - show") );
+            ShowThumbnail();
+            }
+        else
+            {
+            RDebug::Print( _L("### NamesList::HandleResourceChangeL - hide") );
+            HideThumbnail();
+            }
+        }*/
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandlePointerEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandlePointerEventL(
+    const TPointerEvent& aPointerEvent )
+    {
+    if( !iAllowPointerEvents )
+        {
+        //Passing event to listbox needed even if iCurrentState would be skipped (fix for ou1cimx1#316139)
+        iListBox->HandlePointerEventL( aPointerEvent ); 
+        return;
+        }
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        iCurrentState->HandlePointerEventL( aPointerEvent );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ParentControl
+// --------------------------------------------------------------------------
+//
+MPbk2ContactUiControl* CPbk2NamesListControl::ParentControl() const
+    {
+    // Name list controls has no parent
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::NumberOfContacts
+// --------------------------------------------------------------------------
+//
+TInt CPbk2NamesListControl::NumberOfContacts() const
+    {
+    TInt ret( iCurrentState->NumberOfContacts() );
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FocusedContactL
+// --------------------------------------------------------------------------
+//
+const MVPbkBaseContact* CPbk2NamesListControl::FocusedContactL() const
+    {
+    return iCurrentState->FocusedContactL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FocusedViewContactL
+// --------------------------------------------------------------------------
+//
+const MVPbkViewContact* CPbk2NamesListControl::FocusedViewContactL() const
+    {
+    return iCurrentState->FocusedViewContactL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FocusedStoreContact
+// --------------------------------------------------------------------------
+//
+const MVPbkStoreContact* CPbk2NamesListControl::FocusedStoreContact() const
+    {
+    return iCurrentState->FocusedStoreContact();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetFocusedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetFocusedContactL
+        ( const MVPbkBaseContact& aContact )
+    {
+    iCurrentState->SetFocusedContactL(aContact);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetFocusedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetFocusedContactL(
+        const MVPbkContactBookmark& aContactBookmark )
+    {
+    iCurrentState->SetFocusedContactL( aContactBookmark );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetFocusedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetFocusedContactL(
+        const MVPbkContactLink& aContactLink )
+    {
+    iCurrentState->SetFocusedContactL( aContactLink );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FocusedContactIndex
+// --------------------------------------------------------------------------
+//
+TInt CPbk2NamesListControl::FocusedContactIndex() const
+    {
+    return iCurrentState->FocusedContactIndex();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetFocusedContactIndexL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetFocusedContactIndexL( TInt aIndex )
+    {
+    iCurrentState->SetFocusedContactIndexL( aIndex );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::NumberOfContactFields
+// --------------------------------------------------------------------------
+//
+TInt CPbk2NamesListControl::NumberOfContactFields() const
+    {
+    return iCurrentState->NumberOfContactFields();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FocusedField
+// --------------------------------------------------------------------------
+//
+const MVPbkBaseContactField* CPbk2NamesListControl::FocusedField() const
+    {
+    return iCurrentState->FocusedField();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FocusedFieldIndex
+// --------------------------------------------------------------------------
+//
+TInt CPbk2NamesListControl::FocusedFieldIndex() const
+    {
+    return iCurrentState->FocusedFieldIndex();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetFocusedFieldIndex
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetFocusedFieldIndex( TInt /*aIndex*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ContactsMarked
+// --------------------------------------------------------------------------
+//
+TBool CPbk2NamesListControl::ContactsMarked() const
+    {
+    return iCurrentState->ContactsMarked();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SelectedContactsL
+// --------------------------------------------------------------------------
+//
+MVPbkContactLinkArray*
+        CPbk2NamesListControl::SelectedContactsL() const
+    {
+    return iCurrentState->SelectedContactsL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SelectedContactsOrFocusedContactL
+// --------------------------------------------------------------------------
+//
+MVPbkContactLinkArray*
+        CPbk2NamesListControl::SelectedContactsOrFocusedContactL() const
+    {
+    return iCurrentState->SelectedContactsOrFocusedContactL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SelectedContactsIteratorL
+// --------------------------------------------------------------------------
+//
+MPbk2ContactLinkIterator*
+        CPbk2NamesListControl::SelectedContactsIteratorL() const
+    {
+    return iCurrentState->SelectedContactsIteratorL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SelectedContactStoresL
+// --------------------------------------------------------------------------
+//
+CArrayPtr<MVPbkContactStore>*
+        CPbk2NamesListControl::SelectedContactStoresL() const
+    {
+    // This is not a contact store control
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ClearMarks
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ClearMarks()
+    {
+    iCurrentState->ClearMarks();
+    ClearMarkedContactsInfo();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetSelectedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetSelectedContactL
+        ( TInt aIndex, TBool aSelected )
+    {
+    iCurrentState->SetSelectedContactL( aIndex, aSelected );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetSelectedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetSelectedContactL(
+        const MVPbkContactBookmark& aContactBookmark,
+        TBool aSelected )
+    {
+    iCurrentState->SetSelectedContactL( aContactBookmark, aSelected );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetSelectedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetSelectedContactL(
+        const MVPbkContactLink& aContactLink,
+        TBool aSelected )
+    {
+    iCurrentState->SetSelectedContactL( aContactLink, aSelected );
+    }
+TInt CPbk2NamesListControl::CommandItemCount() const
+    {
+    MPbk2ContactUiControl2* tempCurrentState =
+        reinterpret_cast<MPbk2ContactUiControl2*>
+            (iCurrentState->ContactUiControlExtension
+                (KMPbk2ContactUiControlExtension2Uid ));
+    return tempCurrentState->CommandItemCount();
+    }
+
+const MPbk2UiControlCmdItem&
+CPbk2NamesListControl::CommandItemAt( TInt aIndex ) const
+    {
+    MPbk2ContactUiControl2* tempCurrentState =
+        reinterpret_cast<MPbk2ContactUiControl2*>
+            (iCurrentState->ContactUiControlExtension
+                (KMPbk2ContactUiControlExtension2Uid ));
+    return tempCurrentState->CommandItemAt( aIndex );
+    }
+
+const MPbk2UiControlCmdItem* CPbk2NamesListControl::FocusedCommandItem() const
+    {
+    MPbk2ContactUiControl2* tempCurrentState =
+        reinterpret_cast<MPbk2ContactUiControl2*>
+            (iCurrentState->ContactUiControlExtension
+                (KMPbk2ContactUiControlExtension2Uid ));
+    return tempCurrentState->FocusedCommandItem();
+    }
+
+void CPbk2NamesListControl::DeleteCommandItemL( TInt aIndex )
+    {
+    iCommandItems.Remove(aIndex);
+    iCurrentState->HandleCommandEventL(MPbk2NamesListState::EItemRemoved, aIndex);
+    }
+
+void CPbk2NamesListControl::AddCommandItemL(MPbk2UiControlCmdItem* aCommand, TInt aIndex)
+    {
+    // Fix ETKI-7NADZC
+    DeleteIfAlreadyAdded(aCommand);
+
+    // add aCommand to iCommandItems
+    if (aIndex > iCommandItems.Count())
+        {
+        aIndex = iCommandItems.Count();
+        }
+    iCommandItems.Insert(aCommand, aIndex);
+    iCurrentState->HandleCommandEventL(MPbk2NamesListState::EItemAdded, aIndex);
+    }
+
+void CPbk2NamesListControl::DeleteIfAlreadyAdded(const MPbk2UiControlCmdItem* aCommand)
+    {
+    for ( TInt n = 0; n < iCommandItems.Count(); ++n)
+        {
+        MPbk2UiControlCmdItem* cmd = iCommandItems[n];
+        if(cmd->CommandId() == aCommand->CommandId())
+            {
+            iCommandItems.Remove(n);
+            delete cmd;
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::DynInitMenuPaneL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::DynInitMenuPaneL(
+        TInt aResourceId, CEikMenuPane* aMenuPane) const
+    {
+    iCurrentState->DynInitMenuPaneL(aResourceId, aMenuPane);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ProcessCommandL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ProcessCommandL( TInt aCommandId ) const
+    {
+    iCurrentState->ProcessCommandL(aCommandId);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::UpdateAfterCommandExecution
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::UpdateAfterCommandExecution()
+    {
+    if( iCommand )
+        {
+        /// Reset command pointer, command has completed
+        iCommand->ResetUiControl(*this);
+        iCommand = NULL;
+        }
+    TRAP_IGNORE( ProcessCommandL( EAknUnmarkAll); );
+    if( iSearchFilter )
+        {
+        TRAP_IGNORE( iSearchFilter->ReDrawL(ETrue); );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::GetMenuFilteringFlagsL
+// --------------------------------------------------------------------------
+//
+TInt CPbk2NamesListControl::GetMenuFilteringFlagsL() const
+    {
+    return iCurrentState->GetMenuFilteringFlagsL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ControlStateL
+// --------------------------------------------------------------------------
+//
+CPbk2ViewState* CPbk2NamesListControl::ControlStateL() const
+    {
+    CPbk2ViewState* state = CPbk2ViewState::NewLC();
+    const MVPbkBaseContact* focusedContact = FocusedContactL();
+    if (focusedContact)
+        {
+        MVPbkContactLink* link = focusedContact->CreateLinkLC();
+        if (link)
+            {
+            CleanupStack::Pop(); // link
+            state->SetFocusedContact(link);
+            }
+        }
+
+    const MVPbkViewContact* topContact = iCurrentState->TopContactL();
+    if ( topContact )
+        {
+        MVPbkContactLink* link = topContact->CreateLinkLC();
+        if (link)
+            {
+            CleanupStack::Pop(); // link
+            state->SetTopContact( link );
+            }
+        }
+
+    if (ContactsMarked())
+        {
+        state->SetMarkedContacts(SelectedContactsL());
+        }
+    CleanupStack::Pop(); // state
+    return state;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::RestoreControlStateL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::RestoreControlStateL(CPbk2ViewState* aState)
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::RestoreControlStateL(0x%x,0x%x)"),
+        this, aState);
+
+    if (aState)
+        {
+        iCurrentState->RestoreControlStateL(aState);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FindTextL
+// --------------------------------------------------------------------------
+//
+const TDesC& CPbk2NamesListControl::FindTextL()
+    {
+    return iCurrentState->FindTextL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ResetFindL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ResetFindL()
+    {
+    iCurrentState->ResetFindL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ShowThumbnail
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ShowThumbnail()
+    {
+    iCurrentState->ShowThumbnail();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HideThumbnail
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HideThumbnail()
+    {
+    iCurrentState->HideThumbnail();
+    }
+
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetBlank
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetBlank(TBool aBlank)
+    {
+    MakeVisible( !aBlank );
+
+    // The focus status of CAknSearchField* iFindBox is expected to be
+    // consistent with CPbk2NamesListControl when setting blank.
+
+    if ( iFindBox )
+        {
+        if ( iFindBox->IsVisible() )
+            {
+            iFindBox->SetFocus( IsFocused() );
+            }
+        }
+
+    iCurrentState->SetBlank( aBlank );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::RegisterCommand
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::RegisterCommand(
+        MPbk2Command* aCommand)
+    {
+    iCommand = aCommand;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SetTextL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SetTextL( const TDesC& aText )
+    {
+    iCurrentState->SetTextL( aText );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ContactUiControlExtension
+// --------------------------------------------------------------------------
+//
+TAny* CPbk2NamesListControl::ContactUiControlExtension(TUid aExtensionUid )
+    {
+     if( aExtensionUid == KMPbk2ContactUiControlExtension2Uid )
+        {
+        return static_cast<MPbk2ContactUiControl2*>( this );
+        }
+
+    return NULL;
+
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ContactViewReady
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ContactViewReady
+        ( MVPbkContactViewBase& aView )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::ContactViewReady(0x%x)"), this );
+    TRAPD( error, DoHandleContactViewReadyL( aView ) );
+    HandleError( error );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ContactViewUnavailable
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ContactViewUnavailable
+        ( MVPbkContactViewBase& aView )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::ContactViewUnavailable(0x%x)"), this);
+
+    if ( &aView == iViewStack )
+        {
+        TRAPD( err, iCurrentState =
+            &iStateFactory->ActivateNotReadyStateL( iCurrentState ) );
+        HandleError( err );
+        RelayoutControls();
+        TRAP( err, iEventSender->SendEventToObserversL(
+                TPbk2ControlEvent::EUnavailable ) );
+        HandleError( err );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ContactAddedToView
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ContactAddedToView(
+        MVPbkContactViewBase& aView,
+        TInt aIndex,
+        const MVPbkContactLink& /*aContactLink*/)
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::ContactAddedToView()"));
+
+    if (&aView == iViewStack)
+        {
+        if( !iCheckMassUpdate->MassUpdateDetected() )
+            {
+            TRAPD(err, DoHandleContactAdditionL(aIndex));
+            HandleError(err);
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ContactRemovedFromView
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ContactRemovedFromView(
+        MVPbkContactViewBase& aView,
+        TInt aIndex,
+        const MVPbkContactLink& /*aContactLink*/ )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::ContactRemovedFromView()"));
+
+    if (&aView == iViewStack)
+        {
+        TRAPD(err, DoHandleContactRemovalL(aIndex));
+        HandleError(err);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ContactViewError
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ContactViewError(
+        MVPbkContactViewBase& /*aView*/,
+        TInt aError,
+        TBool /*aErrorNotified*/)
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::ContactViewError(%d)"), aError);
+
+    // Error comes from the active view or from find view stack.
+    // Actions are same in both cases. Show error note by forwarding
+    // the error to CCoeEnv and try to reset control. Do reset asychronously
+    // because the ContactViewError can be coming from view that is
+    // destroyed when the control is reset.
+    HandleError(aError);
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::ContactViewObserverExtension
+// --------------------------------------------------------------------------
+//
+TAny* CPbk2NamesListControl::ContactViewObserverExtension( TUid aExtensionUid )
+    {
+    if( aExtensionUid == KVPbkContactViewObserverExtension2Uid )
+        {
+        return static_cast<MVPbkContactViewObserverExtension*>( this );
+        }
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FilteredContactRemovedFromView
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::FilteredContactRemovedFromView(
+        MVPbkContactViewBase& /*aView*/ )
+    {    
+    DrawDeferred();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FocusedItemPointed
+// --------------------------------------------------------------------------
+//
+TBool CPbk2NamesListControl::FocusedItemPointed()
+    {
+    return iCurrentState->FocusedItemPointed();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::FocusableItemPointed
+// --------------------------------------------------------------------------
+//
+TBool CPbk2NamesListControl::FocusableItemPointed()
+    {
+    return iCurrentState->FocusableItemPointed();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SearchFieldPointed
+// --------------------------------------------------------------------------
+//
+TBool CPbk2NamesListControl::SearchFieldPointed()
+    {
+    return iCurrentState->SearchFieldPointed();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleControlEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleControlEventL
+        ( CCoeControl* aControl, TCoeEvent aEventType )
+    {
+    iCurrentState->HandleControlEventL( aControl, aEventType, 0 );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::UpdateContact
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::UpdateContact
+        ( const MVPbkContactLink& aContactLink )
+    {
+    TInt listBoxRow = KErrNotFound;
+
+    TRAPD( err, listBoxRow = iViewStack->IndexOfLinkL( aContactLink ) );
+    if ( err )
+        {
+        iEikonEnv->NotifyIdleErrorWhileRedrawing( err );
+        }
+
+    MPbk2ContactUiControl2* tempCurrentState =
+        reinterpret_cast<MPbk2ContactUiControl2*>
+            (iCurrentState->ContactUiControlExtension
+                (KMPbk2ContactUiControlExtension2Uid ));
+
+      if(tempCurrentState)
+          {
+        listBoxRow += tempCurrentState->CommandItemCount();
+        }
+    if ( listBoxRow >= 0 )
+        {
+        // If visible
+        if ( listBoxRow >= iListBox->TopItemIndex() &&
+             listBoxRow <= iListBox->BottomItemIndex() )
+            {
+            iListBox->RedrawItem( listBoxRow );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::UpdateCommandItem
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::UpdateCommandItem( TInt aCommandId )
+    {
+    const TInt count = CommandItemCount();
+    const TInt top = iListBox->TopItemIndex();
+    const TInt bottom = iListBox->BottomItemIndex();
+
+    for( TInt i = 0; i < count; ++i )
+        {
+        if( Rng( top, i, bottom ) ) // is in visible range
+            {
+            if( CommandItemAt( i ).CommandId() == aCommandId )
+                {
+                iListBox->RedrawItem( i );
+                break; // only one command with same id
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::Redraw
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::Redraw()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING(
+        "CPbk2NamesListControl(0x%x)::Redraw"), this );
+
+    // Do not use DrawNow because:
+    // 1) DrawNow will draw the control everytime it's called. This can
+    //    cause flickering in list box focus e.g. when the application view
+    //    is restoring the control state.
+    // 2) Avoid unnecessary drawing because DrawDeferred can be called many
+    //    times in short interval but it will draw the control only once.
+    DrawDeferred();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::DoHandleContactViewReadyL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::DoHandleContactViewReadyL
+        ( MVPbkContactViewBase& /*aView*/ )
+    {
+    // Change state
+    SelectAndChangeReadyStateL();
+
+    //When contact view is ready, state is activated. If there are multiple stores
+    //state doesn't get event when other stores are ready. EContactViewUpdated event is
+    //sent when contact view is ready, so after state activation, state can get multiple
+    //contact view updated events.
+    iCurrentState->HandleContactViewEventL( MPbk2NamesListState::EContactViewUpdated, 0 );
+
+    // Check that there is still focus in list
+    // Focus may be lost if for example store goes unavailable
+    iListBox->CheckFocusIndex();
+    // Control is ready and visible, inform observers
+    TBool eventSent = iEventSender->SendEventToObserversL(
+        TPbk2ControlEvent::EReady );
+    // If Ready-event has been already sent, send
+    // ContactSetChanged-event instead.
+    if ( !eventSent )
+        {
+        iEventSender->SendEventToObserversL( TPbk2ControlEvent::
+            EContactSetChanged );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::DoHandleContactAdditionL
+//
+// NOTE: See also CPbk2FilteredViewStackObserver::ContactAddedToBaseView and
+//       CPbk2NamesListControl::DoContactAddedToBaseView
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::DoHandleContactAdditionL( TInt aIndex )
+    {
+    //Prevent messing with focus with always-on when Phonebook hidden in
+    //reseted state. Otherwise background-added contacts will change focus.
+    //This would cause Phonebook not to look like freshly started when opened again.
+    //And also make sure foreground-added contact will show the new contact
+    //even though the focus is not seen.
+    if( (static_cast<CPbk2AppUi*>(
+            CEikonEnv::Static()->AppUi()))->IsForeground() )
+        {
+        SelectAndChangeReadyStateL();
+        }
+
+    if( !iCheckMassUpdate->MassUpdateDetected() )
+        {
+        iCurrentState->HandleContactViewEventL
+            ( MPbk2NamesListState::EItemAdded, aIndex );
+        }
+
+    // At least names list view needs control event about contact addition,
+    // so it knows to update CBAs
+    iEventSender->SendEventToObserversL( TPbk2ControlEvent::EItemAdded );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::DoHandleContactRemovalL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::DoHandleContactRemovalL( TInt aIndex )
+    {
+    iCurrentState->HandleContactViewEventL
+        ( MPbk2NamesListState::EItemRemoved, aIndex );
+    SelectAndChangeReadyStateL();
+    iEventSender->SendEventToObserversL( TPbk2ControlEvent::EItemRemoved );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::SelectAndChangeReadyStateL
+// Changes between ready states (ready, empty, filtered).
+// Can't handle a change to unavailable state
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::SelectAndChangeReadyStateL()
+    {
+    if ( iViewStack->ContactCountL() == 0 )
+        {
+        if ( iViewStack->Level() > 0 )
+            {
+            // If view was filtered beyond matches, activate filtered state
+            iCurrentState = &iStateFactory->ActivateFilteredStateL
+                ( iCurrentState );
+            }
+        else
+            {
+            // Empty state used only if there are no contacts
+            // in the base view
+            iCurrentState = &iStateFactory->ActivateEmptyStateL
+                ( iCurrentState );
+            }
+        }
+    else
+        {
+        iCurrentState =
+            &iStateFactory->ActivateReadyStateL( iCurrentState );
+        }
+
+    // Controls have to be relayouted always. Relayouting only when
+    // state was changed is not enough, it results to drawing problems.
+    // Calling only Redraw() is not enough also.
+    RelayoutControls();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::RelayoutControls
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::RelayoutControls()
+    {
+    SizeChanged();
+    MakeVisible( IsVisible() );
+    Redraw();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleTopViewChangedL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleTopViewChangedL
+        ( MVPbkContactViewBase& aOldView )
+    {
+    SelectAndChangeReadyStateL();
+
+    iCurrentState->TopViewChangedL( aOldView );
+
+    // Inform observers
+    iEventSender->SendEventToObserversL(
+            TPbk2ControlEvent::EContactSetChanged );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleTopViewUpdatedL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleTopViewUpdatedL()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::HandleTopViewUpdatedL(0x%x)"), this );
+
+    SelectAndChangeReadyStateL();
+
+    iCurrentState->TopViewUpdatedL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleBaseViewChangedL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleBaseViewChangedL()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::HandleBaseViewChangedL(0x%x)"), this );
+
+    SelectAndChangeReadyStateL();
+
+    iCurrentState->BaseViewChangedL();
+
+    iEventSender->SendEventToObserversL(
+            TPbk2ControlEvent::EContactSetChanged );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleViewStackError
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleViewStackError( TInt aError )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2NamesListControl::HandleBaseViewChangedL(0x%x, %d)"),
+            this, aError );
+
+    HandleError( aError );
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleContactAddedToBaseView
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleContactAddedToBaseView
+        ( MVPbkContactViewBase& /*aBaseView*/,
+          TInt /*aIndex*/, const MVPbkContactLink& /*aContactLink*/ )
+    {
+    // The find box must be reset when new items are added to
+    // the list box. When find text is reset, the possible filter
+    // result (subset of contacts) of the previous find criteria must be
+    // reset too. So, we reset both the find box and the view stack.
+    TRAPD( res,
+        {
+        // This will reset back to base view, however retain original view
+        //when opening CCA
+        if( !iOpeningCca ) 
+            {
+            iCurrentState->ResetFindL(); 
+            }
+        });
+    HandleError( res );
+
+    if( !iCheckMassUpdate->MassUpdateCheckThis() )
+        {
+        // If it is the first time to goto a contat's cca card, then in cca we 
+        // will set a defualt number to that contact by CmsSetVoiceCallDefault.
+        // Then db item changed event is notified to ui layer and names list control 
+        // updated accordingly. But to end user that is not allowed, so use this 
+        // flag to avoid this reset of ui control.
+        if( iOpeningCca )
+            {
+            if( iCurrentState->NamesListState() == EStateEmpty )
+                {
+                SelectAndChangeReadyStateL();
+                }
+            }
+        else
+            {              
+            if( !iMarkingModeOn )
+                {
+                Reset();
+                }
+            }
+        }
+
+    // Do not handle contact addition here (DoHandleContactAdditionL),
+    // ContactAddedToView to notification is sent separately
+    }
+
+// --------------------------------------------------------------------------
+//
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleScrollEventL(CEikScrollBar* aScrollBar, TEikScrollEvent aEventType)
+    {
+//    iDidMove= EFalse ;
+
+    switch( aEventType )
+        {
+        // drag events -> hide thumbnail
+        // AL: this isn't very efficient way of doing this...
+        // ...thumbnail loader interface should be extended to
+        // enable thumbnail window to be hidden/shown without
+        // destroying and reloading the bitmaps...
+        case EEikScrollThumbDragHoriz:
+        case EEikScrollThumbDragVert:
+            {
+            iDidMove = ETrue;
+            HideThumbnail();
+            break;
+            }
+
+        // release events
+        case EEikScrollThumbReleaseHoriz:
+        case EEikScrollThumbReleaseVert:
+            {
+            // AL: this isn't very efficient way of doing this...
+            // ...thumbnail loader interface should be extended to
+            // enable thumbnail window to be hidden/shown without
+            // destroying and reloading the bitmaps...
+            if( iDidMove )
+                {
+                iDidMove = EFalse;
+                ShowThumbnail();
+                }
+            break;
+            }
+
+        default:
+            {
+            iDidMove= EFalse ;
+
+            if( iThumbnailLoader )
+                {
+                iThumbnailLoader->Refresh();
+                }
+
+
+            }
+        }
+
+    // To avoid slow redraw of the scrollbar, make sure it gets drawn. Fixes MJAA-7ZGHRH.
+    aScrollBar->DrawNow();
+    }
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleListBoxEventL
+// Deal with the Panning/Flick event from listbox
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleListBoxEventL( CEikListBox* /*aListBox*/, TListBoxEvent aEventType )
+    {
+    switch( aEventType )
+        {
+        case EEventPanningStarted:
+        case EEventFlickStarted:
+            {
+            // Hide Thumbnial as the listbox is
+            // Panning/Flicking
+            HideThumbnail();
+            break;
+            }
+
+        case EEventPanningStopped:
+        case EEventFlickStopped:
+            {
+            // Show Thumbnial after the listbox
+            // Panned/Flicked
+            ShowThumbnail();
+            break;
+            }
+        case EEventItemSingleClicked:
+        case EEventItemDoubleClicked:
+            {
+            iEventSender->SendEventToObserversL(
+                TPbk2ControlEvent::EContactDoubleTapped );
+            break;
+            }
+
+        default:
+            break;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::AdaptiveSearchTextChanged
+//
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::AdaptiveSearchTextChanged( CAknSearchField* aSearchField )
+    {
+    //send event to current state
+    //ETrue means that the event came from adaptvie search grid.
+    TRAP_IGNORE(iCurrentState->HandleControlEventL( aSearchField, MCoeControlObserver::EEventStateChanged, ETrue));
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPbk2NamesListControl::MarkingModeStatusChanged
+// -----------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::MarkingModeStatusChanged( TBool /*aActivated*/ )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CPbk2NamesListControl::ExitMarkingMode
+// Called by avkon, if the return value is ETrue, 
+// the Marking mode will be canceled after any operation, 
+// otherwise the Marking mode keep active.
+// -----------------------------------------------------------------------------
+//
+TBool CPbk2NamesListControl::ExitMarkingMode() const
+    {
+    return ETrue;
+    }
+    
+// --------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleForegroundEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::HandleForegroundEventL(TBool aForeground)
+    {
+    if ( iSearchFilter )
+        {
+        iSearchFilter->HandleForegroundEventL( aForeground );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControl::StoreMarkedContactsAndResetViewL
+// ---------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::StoreMarkedContactsAndResetViewL()
+    {
+    delete iSelectedLinkArray;
+    iSelectedLinkArray = NULL;
+
+    iSelectedLinkArray = iCurrentState->SelectedContactsL();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControl::RestoreMarkedContactsL
+// ---------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::RestoreMarkedContactsL()
+    {
+    //Set the Marked Contacts
+    if ( iSelectedLinkArray )
+        {
+        for ( TInt index = 0; index<iSelectedLinkArray->Count(); index++ )
+            {
+            iCurrentState->SetSelectedContactL( iSelectedLinkArray->At(index), ETrue );
+            }
+        }
+
+    delete iSelectedLinkArray;
+    iSelectedLinkArray = NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControl::ClearMarkedContactsInfo
+// ---------------------------------------------------------------------------
+//
+void CPbk2NamesListControl::ClearMarkedContactsInfo()
+    {
+    if ( iBgTask )
+        {
+        iBgTask->ClearAllEvents();
+        }
+    delete iSelectedLinkArray;
+    iSelectedLinkArray = NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControl::HandleViewForegroundEventL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2NamesListControl::HandleViewForegroundEventL( TBool aForeground )
+    {
+    if ( aForeground )
+        {
+        if ( iBgTask )
+            {
+            iBgTask->AddEvent( CPbk2NamesListControl::EStateRestoreMarkedContacts );
+            }
+        }
+    else
+        {
+        if ( iBgTask )
+            {
+            iBgTask->AddEvent( CPbk2NamesListControl::EStateSaveMarkedContacts );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControl::SetOpeningCca
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2NamesListControl::SetOpeningCca( TBool aIsOpening )
+    {
+    iOpeningCca = aIsOpening;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControlBgTask::CPbk2NamesListControlBgTask
+// ---------------------------------------------------------------------------
+//
+CPbk2NamesListControlBgTask::CPbk2NamesListControlBgTask( CPbk2NamesListControl& aControl ) :
+    CActive(CActive::EPriorityStandard),
+    iControl( aControl )
+    {
+    CActiveScheduler::Add(this);
+    iEventQueue.Append(CPbk2NamesListControl::EStateBgTaskEmpty);
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControlBgTask::~CPbk2NamesListControlBgTask
+// ---------------------------------------------------------------------------
+//
+CPbk2NamesListControlBgTask::~CPbk2NamesListControlBgTask()
+    {
+    Cancel();
+    iEventQueue.Reset();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControlBgTask::DoCancel
+// ---------------------------------------------------------------------------
+//
+void CPbk2NamesListControlBgTask::DoCancel()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControlBgTask::RunL
+// ---------------------------------------------------------------------------
+//
+void CPbk2NamesListControlBgTask::RunL()
+    {
+
+    if ( iEventQueue.Count() )
+        {
+        switch ( iEventQueue[0] )
+            {
+            case CPbk2NamesListControl::EStateSaveMarkedContacts:
+                iControl.StoreMarkedContactsAndResetViewL();
+                iEventQueue.Remove( 0 );
+                break;
+
+            case CPbk2NamesListControl::EStateRestoreMarkedContacts:
+                iControl.RestoreMarkedContactsL();
+                iEventQueue.Remove( 0 );
+                break;
+
+            case CPbk2NamesListControl::EStateBgTaskEmpty :
+            default:
+                iControl.ClearMarkedContactsInfo();
+                break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControlBgTask::RunError
+// ---------------------------------------------------------------------------
+//
+TInt CPbk2NamesListControlBgTask::RunError(TInt /*aError*/)
+    {
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControlBgTask::AddEvent
+// ---------------------------------------------------------------------------
+//
+void CPbk2NamesListControlBgTask::AddEvent( CPbk2NamesListControl::TPbk2NamesListBgEvents aEvent )
+    {
+    iEventQueue.Insert( aEvent, iEventQueue.Count() - 1 );
+    if ( !IsActive() )
+        {
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete(status, KErrNone);
+        SetActive();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControlBgTask::RemoveEvent
+// ---------------------------------------------------------------------------
+//
+void CPbk2NamesListControlBgTask::RemoveEvent( CPbk2NamesListControl::TPbk2NamesListBgEvents aEvent )
+    {
+    for ( TInt index = 0; index < iEventQueue.Count(); index++ )
+        {
+        if ( aEvent == iEventQueue[index] )
+            {
+            iEventQueue.Remove( index );
+            if ( 0 == index )
+                {
+                Cancel();
+                }
+            break;
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CPbk2NamesListControlBgTask::ClearAllEvents
+// ---------------------------------------------------------------------------
+//
+void CPbk2NamesListControlBgTask::ClearAllEvents()
+    {
+    iEventQueue.Reset();
+    iEventQueue.Append( CPbk2NamesListControl::EStateBgTaskEmpty );
+    Cancel();
+    }
+
+//  End of File