phonebookui/Phonebook2/UIControls/src/CPbk2ContactInfoControl.cpp
changeset 0 e686773b3f54
child 21 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/UIControls/src/CPbk2ContactInfoControl.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,1379 @@
+/*
+* 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 contact info view control.
+*
+*/
+
+
+// INCLUDE FILES
+
+#include <CPbk2ContactInfoControl.h>
+
+// Phonebook 2
+#include "CPbk2ContactInfoListBox.h"
+#include "CPbk2ContactInfoDataSwapper.h"
+#include "CPbk2ContactFieldDynamicProperties.h"
+#include "CPbk2ThumbnailLoader.h"
+#include "Pbk2TitlePanePictureFactory.h"
+#include <Pbk2UIControls.rsg>
+#include <Pbk2UIControls.hrh>
+#include <CPbk2IconArray.h>
+#include <MPbk2ContactNameFormatter.h>
+#include <CPbk2ViewState.h>
+#include <MPbk2ControlObserver.h>
+#include <CPbk2PresentationContact.h>
+#include <CPbk2PresentationContactField.h>
+#include <CPbk2PresentationContactFieldCollection.h>
+#include <CPbk2FieldPropertyArray.h>
+#include <Pbk2MenuFilteringFlags.hrh>
+#include <MPbk2ContactNavigation.h>
+#include <CPbk2StorePropertyArray.h>
+#include <CPbk2StoreSpecificFieldPropertyArray.h>
+#include <MPbk2Command.h>
+#include <Pbk2Profile.h>
+
+// Virtual Phonebook
+#include <MVPbkContactOperationBase.h>
+#include <CVPbkContactManager.h>
+#include <MVPbkContactLink.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkStoreContactField.h>
+#include <MVPbkStoreContactFieldCollection.h>
+#include <MVPbkContactStore.h>
+#include <MVPbkContactStoreProperties.h>
+#include <MVPbkContactFieldSelector.h>
+#include <MVPbkFieldType.h>
+#include <CVPbkFieldTypeSelector.h>
+#include <CVPbkContactStoreUriArray.h>
+#include <MVPbkContactFieldTextData.h>
+#include <VPbkEng.rsg>
+
+// System includes
+#include <akntitle.h>
+#include <AknsConstants.h>
+#include <avkon.hrh>
+#include <barsread.h>
+#include <bautils.h>
+
+// Debugging headers
+#include <Pbk2Debug.h>
+
+
+/// Unnamed namespace for local definitions
+namespace {
+
+// LOCAL CONSTANTS AND MACROS
+
+const TInt KNumberOfControls = 1;
+const TInt KNoContacts = 0;
+const TInt KNumberOfContacts = 1;
+const TInt KDefaultTitleFormat = MPbk2ContactNameFormatter::EUseSeparator;
+
+#ifdef _DEBUG
+enum TPanicCode
+    {
+    EPanicPreCond_FocusedField = 1,
+    EPanicLogic_FocusedField,
+    EPanicPreCond_FocusedFieldIndex,
+    EPanicPostCond_FocusedFieldIndex,
+    EPanicPreCond_FieldPos,
+    EPanicPreCond_OfferKeyEventL,
+    EPanicPreCond_SizeChanged,
+    EPanicPreCond_CountComponentControls,
+    EPanicPreCond_ComponentControl
+    };
+
+void Panic(TInt aReason)
+    {
+    _LIT(KPanicText, "CPbk2ContactInfoControl");
+    User::Panic(KPanicText, aReason);
+    }
+#endif // _DEBUG
+
+} /// namespace
+
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::CPbk2ContactInfoControl
+// --------------------------------------------------------------------------
+//
+CPbk2ContactInfoControl::CPbk2ContactInfoControl(
+        CVPbkContactManager& aManager,
+        MPbk2ContactNameFormatter& aNameFormatter,
+        MPbk2FieldPropertyArray& aFieldProperties,
+        CPbk2StorePropertyArray& aStoreProperties,
+        MPbk2ContactNavigation* aNavigator ) :
+    iContactManager( aManager ),
+    iNameFormatter( aNameFormatter ),
+    iNavigator( aNavigator ),
+    iFieldProperties( aFieldProperties ),
+    iStoreProperties( aStoreProperties ),
+    iFocusedFieldIndex( KErrNotFound )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::~CPbk2ContactInfoControl
+// --------------------------------------------------------------------------
+//
+CPbk2ContactInfoControl::~CPbk2ContactInfoControl()
+    {
+    if( iTitlePane )
+        {
+        iTitlePane->SetSmallPicture( NULL, NULL, EFalse );
+        }
+    if (iCommand)
+        {
+        // inform the command that the control is deleted
+        iCommand->ResetUiControl(*this);
+        }
+    iObservers.Reset();
+    delete iThumbnailLoader;
+    delete iListBox;
+    delete iContact;
+    delete iStoreContact;
+    delete iRetriever;
+    delete iContactLink;
+    delete iSpecificFieldProperties;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ConstructL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2ContactInfoControl::ConstructL(
+        const CCoeControl* aContainer)
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactInfoControl::ConstructL begin"));
+
+    SetContainerWindowL(*aContainer);
+
+    // Create the listbox
+    iListBox = CPbk2ContactInfoListBox::NewL(
+        *this, R_PBK2_CONTACT_INFO_CONTROL, iContactManager);
+    iListBox->SetObserver(this);
+    iListBox->SetScrollEventObserver( this );
+    iListBox->SetListBoxObserver( this );
+
+    // Get flags from listbox
+    iFlags = iListBox->Flags();
+
+    // Create thumbnail loader
+    iThumbnailLoader = CPbk2ThumbnailLoader::NewL( iContactManager );
+
+    CEikStatusPane* statusPane = iEikonEnv->AppUiFactory()->StatusPane();
+    if( statusPane && statusPane->
+        PaneCapabilities( TUid::Uid( EEikStatusPaneUidTitle ) ).IsPresent() )
+        {
+        iTitlePane = static_cast<CAknTitlePane*>(
+            statusPane->ControlL( TUid::Uid( EEikStatusPaneUidTitle ) ) );
+        }
+
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactInfoControl::ConstructL end"));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::NewL
+// --------------------------------------------------------------------------
+//
+EXPORT_C CPbk2ContactInfoControl* CPbk2ContactInfoControl::NewL
+        ( const CCoeControl* aContainer,
+          CVPbkContactManager& aManager,
+          MPbk2ContactNameFormatter& aNameFormatter,
+          MPbk2FieldPropertyArray& aFieldProperties,
+          CPbk2StorePropertyArray& aStoreProperties,
+          MPbk2ContactNavigation* aNavigator )
+    {
+    CPbk2ContactInfoControl* self = new ( ELeave ) CPbk2ContactInfoControl
+        ( aManager, aNameFormatter, aFieldProperties, aStoreProperties,
+          aNavigator );
+    CleanupStack::PushL( self );
+    self->ConstructL( aContainer );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::AddObserverL
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2ContactInfoControl::AddObserverL
+        (MPbk2ControlObserver& aObserver)
+    {
+    User::LeaveIfError(iObservers.Append(&aObserver));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::RemoveObserver
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CPbk2ContactInfoControl::RemoveObserver
+        (MPbk2ControlObserver& aObserver)
+    {
+    const TInt index = iObservers.Find(&aObserver);
+    if (index >= 0)
+        {
+        iObservers.Remove(index);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ParentControl
+// --------------------------------------------------------------------------
+//
+MPbk2ContactUiControl* CPbk2ContactInfoControl::ParentControl() const
+    {
+    // Contact info control has no parent control
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::NumberOfContacts
+// --------------------------------------------------------------------------
+//
+TInt CPbk2ContactInfoControl::NumberOfContacts() const
+    {
+    return KNumberOfContacts;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FocusedContactL
+// --------------------------------------------------------------------------
+//
+const MVPbkBaseContact* CPbk2ContactInfoControl::FocusedContactL() const
+    {
+    return iContact;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FocusedViewContactL
+// --------------------------------------------------------------------------
+//
+const MVPbkViewContact* CPbk2ContactInfoControl::FocusedViewContactL() const
+    {
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FocusedStoreContact
+// --------------------------------------------------------------------------
+//
+const MVPbkStoreContact* CPbk2ContactInfoControl::FocusedStoreContact() const
+    {
+    return iStoreContact;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetFocusedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetFocusedContactL(
+        const MVPbkBaseContact& aContact)
+    {
+    // Load the new contact
+    delete iContactLink;
+    iContactLink = NULL;
+    iContactLink = aContact.CreateLinkLC();
+    CleanupStack::Pop(); // iContactLink
+
+    RetrieveContactL( *iContactLink );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetFocusedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetFocusedContactL(
+        const MVPbkContactBookmark& /*aContactBookmark*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetFocusedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetFocusedContactL(
+        const MVPbkContactLink& aContactLink )
+    {
+    // Load the new contact
+    delete iContactLink;
+    iContactLink = NULL;
+    iContactLink = aContactLink.CloneLC();
+    CleanupStack::Pop(); // iContactLink
+
+    RetrieveContactL( *iContactLink );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FocusedContactIndex
+// --------------------------------------------------------------------------
+//
+TInt CPbk2ContactInfoControl::FocusedContactIndex() const
+    {
+    return KErrNotSupported;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetFocusedContactIndexL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetFocusedContactIndexL( TInt /*aIndex*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::NumberOfContactFields
+// --------------------------------------------------------------------------
+//
+TInt CPbk2ContactInfoControl::NumberOfContactFields() const
+    {
+    return iContact->Fields().FieldCount();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FocusedField
+// --------------------------------------------------------------------------
+//
+const MVPbkBaseContactField* CPbk2ContactInfoControl::FocusedField() const
+    {
+    // PreCond:
+    __ASSERT_DEBUG(iListBox && iFields, Panic(EPanicPreCond_FocusedField));
+
+    const MVPbkBaseContactField* ret = NULL;
+    const TInt fieldsCount = iFields->FieldCount();
+    const TInt index = iListBox->CurrentItemIndex();
+    TInt numberOfVisibleFields = 0;
+    if (index >= 0)
+        {
+        __ASSERT_DEBUG(index < iFields->FieldCount(),
+            Panic(EPanicLogic_FocusedField));
+        
+        // Field collection may have hidden fields, so find visible field
+        // corresponding to the focused field in the listbox.
+        for ( TInt i = 0; i < fieldsCount && ret == NULL; i++ )
+            {
+            if ( iFields->At( i ).IsVisibleInDetailsView() && 
+                iFields->At( i ).DynamicVisibility() )
+                {
+                numberOfVisibleFields++;
+                }
+            if ( numberOfVisibleFields - 1 == index )
+                {
+                ret = &iFields->FieldAt( i );
+                }
+            }
+        }
+
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FocusedFieldIndex
+// --------------------------------------------------------------------------
+//
+TInt CPbk2ContactInfoControl::FocusedFieldIndex() const
+    {
+    // PreCond:
+    __ASSERT_DEBUG(iContact, Panic(EPanicPreCond_FocusedFieldIndex));
+
+    return iListBox->CurrentItemIndex();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetFocusedFieldIndex
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetFocusedFieldIndex(
+        TInt aIndex )
+    {
+    iFocusedFieldIndex = aIndex;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ContactsMarked
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactInfoControl::ContactsMarked() const
+    {
+    // This control does not support contacts marking
+    return EFalse;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SelectedContactsL
+// --------------------------------------------------------------------------
+//
+MVPbkContactLinkArray* CPbk2ContactInfoControl::SelectedContactsL() const
+    {
+    // No selection support in contact info control
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SelectedContactsOrFocusedContactL
+// --------------------------------------------------------------------------
+//
+MVPbkContactLinkArray*
+        CPbk2ContactInfoControl::SelectedContactsOrFocusedContactL() const
+    {
+    CVPbkContactLinkArray* array = CVPbkContactLinkArray::NewLC();
+    const MVPbkBaseContact* focusedContact = FocusedContactL();
+    if ( focusedContact )
+        {
+        MVPbkContactLink* link = focusedContact->CreateLinkLC();
+        CleanupStack::Pop(); // link
+        array->AppendL( link );
+        }
+    CleanupStack::Pop(); // array
+
+    return array;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SelectedContactsIteratorL
+// --------------------------------------------------------------------------
+//
+MPbk2ContactLinkIterator*
+    CPbk2ContactInfoControl::SelectedContactsIteratorL() const
+    {
+    // No selection support in contact info control
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SelectedContactStoresL
+// --------------------------------------------------------------------------
+//
+CArrayPtr<MVPbkContactStore>*
+        CPbk2ContactInfoControl::SelectedContactStoresL() const
+    {
+    // This is not a contact store control
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ClearMarks
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::ClearMarks()
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetSelectedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetSelectedContactL(
+        TInt /*aIndex*/,
+        TBool /*aSelected*/)
+    {
+    // Not supported in Contact Info
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetSelectedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetSelectedContactL(
+        const MVPbkContactBookmark& /*aContactBookmark*/,
+        TBool /*aSelected*/ )
+    {
+    // Not supported
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetSelectedContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetSelectedContactL(
+        const MVPbkContactLink& /*aContactLink*/,
+        TBool /*aSelected*/ )
+    {
+    // Not supported
+    }
+
+TInt CPbk2ContactInfoControl::CommandItemCount() const
+	{
+	return 0; // No command items.
+	}
+
+const MPbk2UiControlCmdItem& CPbk2ContactInfoControl::CommandItemAt(
+	TInt /*aIndex*/ ) const
+	{
+	// There are no command items in this control
+	__ASSERT_ALWAYS( EFalse, User::Panic( _L("Pbk2"), 4)); //TODO
+	MPbk2UiControlCmdItem* item = NULL; // For compiler only
+	return *item; // For compiler only
+	}
+
+const MPbk2UiControlCmdItem* CPbk2ContactInfoControl::FocusedCommandItem() const
+	{
+	return NULL;
+	}
+
+void CPbk2ContactInfoControl::DeleteCommandItemL( TInt /*aIndex*/ )
+	{
+	// Do nothing
+	}
+
+void CPbk2ContactInfoControl::AddCommandItemL(MPbk2UiControlCmdItem* /*aCommand*/, TInt /*aIndex*/)
+	{	
+	//Do nothing, since there shouldn't be any command items in this state.
+	}
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::DynInitMenuPaneL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::DynInitMenuPaneL(
+        TInt /*aResourceId*/,
+        CEikMenuPane* /*aMenuPane*/) const
+    {
+    // Nothing to do
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ProcessCommandL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::ProcessCommandL(
+        TInt /*aCommandId*/) const
+    {
+    // Nothing to do
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::UpdateAfterCommandExecution
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::UpdateAfterCommandExecution()
+    {
+    if( iCommand )
+        {
+        /// Reset command pointer, command has completed
+        iCommand->ResetUiControl(*this);
+        iCommand = NULL;
+        }
+    iListBox->DrawDeferred();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::GetMenuFilteringFlagsL
+// --------------------------------------------------------------------------
+//
+TInt CPbk2ContactInfoControl::GetMenuFilteringFlagsL() const
+    {
+    TInt ret = KPbk2MenuFilteringFlagsNone;
+
+    const TInt fieldCount = FieldCount();
+    User::LeaveIfError( fieldCount );
+    if ( fieldCount > KNoContacts )
+        {
+        ret |= KPbk2ListContainsItems;
+        }
+
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ControlStateL
+// --------------------------------------------------------------------------
+//
+CPbk2ViewState* CPbk2ContactInfoControl::ControlStateL() const
+    {
+    CPbk2ViewState* state = CPbk2ViewState::NewLC();
+    const MVPbkBaseContact* contact = FocusedContactL();
+
+    if ( contact )
+        {
+        MVPbkContactLink* link = contact->CreateLinkLC();
+        state->SetFocusedContact(link);
+        CleanupStack::Pop(); // link
+        link = NULL; // state has the ownership
+
+        if ( iListBox->Model()->NumberOfItems() > 0 )
+            {
+            state->SetFocusedFieldIndex( FocusedFieldIndex() );
+            const TInt topIndex = iListBox->TopItemIndex();
+            if ( topIndex >= 0 )
+                {
+                const MVPbkStoreContactField& topField =
+                    iFields->FieldAt( topIndex );
+                state->SetTopFieldIndex( iContact->PresentationFields().
+                    FindFieldIndex( topField ) );
+                }
+            }
+        }
+
+    CleanupStack::Pop(); // state
+    return state;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::RestoreControlStateL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::RestoreControlStateL(
+        CPbk2ViewState* aState )
+    {
+    const TInt numItems = iListBox->Model()->NumberOfItems();
+    const TInt currentItemIndex = iListBox->CurrentItemIndex();
+
+    TInt topFieldIndex( KErrNotFound );
+    if ( aState )
+        {
+        if ( iFocusedFieldIndex == KErrNotFound )
+            {
+            iFocusedFieldIndex = aState->FocusedFieldIndex();
+            topFieldIndex = aState->TopFieldIndex();
+            }
+        }
+
+    if ( iFocusedFieldIndex >= 0 &&
+         iFocusedFieldIndex < numItems )
+        {
+        iListBox->SetCurrentItemIndex(iFocusedFieldIndex);
+        if ( topFieldIndex >= 0 )
+            {
+            iListBox->SetTopItemIndex( topFieldIndex );
+            }
+        iListBox->UpdateScrollBarsL();
+        }
+    else
+        {
+        iListBox->Reset();
+
+         // Get the field type
+        TResourceReader resReader;
+        CCoeEnv::Static()->CreateResourceReaderLC
+            (resReader, R_PHONEBOOK2_SIP_MSISDN_SELECTOR );
+
+        CVPbkFieldTypeSelector* selector =
+            CVPbkFieldTypeSelector::NewL(resReader, iContactManager.FieldTypes());
+        CleanupStack::PopAndDestroy(); // resReader
+        CleanupStack::PushL( selector );
+
+        const TInt count( iFields->FieldCount() );
+        for ( TInt i( 0 ); i < count; ++i )
+            {
+            const MVPbkFieldType* field = iFields->At( i ).BestMatchingFieldType();
+            if ( selector->IsFieldTypeIncluded( *field ) )
+                {
+                iListBox->SetCurrentItemIndex( i );
+                iFocusedFieldIndex = i;
+                iListBox->UpdateScrollBarsL();
+                break;
+                }
+            }
+        CleanupStack::PopAndDestroy( selector );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FindTextL
+// --------------------------------------------------------------------------
+//
+const TDesC& CPbk2ContactInfoControl::FindTextL()
+    {
+    // No find box in this control
+    return KNullDesC;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ResetFindL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::ResetFindL()
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ShowThumbnail
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::ShowThumbnail()
+    {
+    if (iThumbnailLoader && IsFocused() )
+        {
+        iThumbnailLoader->LoadThumbnail
+            ( iStoreContact, iListBox, ELocationUpDown );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::HideThumbnail
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::HideThumbnail()
+    {
+    if (iThumbnailLoader)
+        {
+        iThumbnailLoader->HideThumbnail();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetBlank
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetBlank(TBool /*aBlank*/)
+    {
+    // This control does not support blanking
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::RegisterCommand
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::RegisterCommand(
+        MPbk2Command* aCommand)
+    {
+    iCommand = aCommand;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SetTextL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SetTextL( const TDesC& aText )
+    {
+    iListBox->View()->SetListEmptyTextL( aText );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ContactUiControlExtension
+// --------------------------------------------------------------------------
+//
+TAny* CPbk2ContactInfoControl::ContactUiControlExtension(TUid aExtensionUid )
+	{
+     if( aExtensionUid == KMPbk2ContactUiControlExtension2Uid )
+        { 
+		return static_cast<MPbk2ContactUiControl2*>( this );
+		}
+		
+    return NULL;
+    }
+
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::UpdateL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::UpdateL(
+        MVPbkStoreContact* aContact)
+    {
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateL);
+
+    // Update specific field properties first
+    delete iSpecificFieldProperties;
+    iSpecificFieldProperties = NULL;
+
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLCreateStoreSpecificFieldProps);
+    iSpecificFieldProperties = CPbk2StoreSpecificFieldPropertyArray::NewL(
+        iFieldProperties,
+        iStoreProperties,
+        iContactManager.FieldTypes(),
+        aContact->ParentStore());
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLCreateStoreSpecificFieldProps);
+
+    // Create an presentation contact from the store contact
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLCreatePresentationContact);
+    CPbk2PresentationContact* presentation =
+        CPbk2PresentationContact::NewL(*aContact, *iSpecificFieldProperties);
+    CleanupStack::PushL(presentation);
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLCreatePresentationContact);
+    
+    // Create title pane picture
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLCreateTitlePanePicture);
+    CEikImage* image = Pbk2TitlePanePictureFactory::
+        CreateTitlePanePictureLC( aContact, iStoreProperties );
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLCreateTitlePanePicture);
+
+    // Instantiate a helper object
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLCreateSwapper);
+    CPbk2ContactInfoDataSwapper* swapper =
+        new(ELeave) CPbk2ContactInfoDataSwapper;
+    CleanupStack::PushL(swapper);
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLCreateSwapper);
+
+    // Store the members which are to be swapped
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLStorePanes);
+    StorePanesL(*swapper, presentation);
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLStorePanes);
+
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLCreateDynamicFieldProperties);
+    CPbk2ContactFieldDynamicProperties* filter =
+        CreateDynamicFieldPropertiesLC( *presentation );
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLCreateDynamicFieldProperties);
+
+    // Prepare listbox for state transitition
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLPrepareForUpdate);
+    iListBox->PrepareForUpdateL
+        ( *swapper, presentation->PresentationFields(),
+            *iSpecificFieldProperties, filter );
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLPrepareForUpdate);
+
+    CleanupStack::Pop();  // filter
+
+    // All code that might leave has been executed succesfully, change state
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLSetTitlePane);
+    if( iTitlePane )
+        {
+        // Set title pane text
+        if( swapper->iTitlePaneText )
+            {
+            iTitlePane->SetText(swapper->iTitlePaneText);
+            swapper->iTitlePaneText = NULL;
+            }
+        // Set title pane picture
+        // picture ownership is transfered to title pane
+        image->SetPictureOwnedExternally( ETrue );
+        iTitlePane->SetSmallPicture(
+            image->Bitmap(), image->Mask(), image->Bitmap() != NULL );
+        }
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLSetTitlePane);
+
+    // Update listbox
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLUpdateListbox);
+    TRAPD(err, iListBox->DoUpdateL(*swapper, *aContact));
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLUpdateListbox);
+
+    // Cleanup and change state
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLCleanupState);
+    CleanupStack::PopAndDestroy(swapper);
+    // bitmap and mask from image were transfered to title pane,
+    // so image can be destroyed now
+    CleanupStack::PopAndDestroy( image );
+    CleanupStack::Pop(presentation);
+    delete iContact;
+    iContact = presentation;
+    iFields = &presentation->PresentationFields();
+    User::LeaveIfError(err);
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLCleanupState);
+
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLSetIndex);
+    if ( iFocusedFieldIndex >= 0 &&
+         iFocusedFieldIndex < iListBox->Model()->NumberOfItems() )
+        {
+        iListBox->SetCurrentItemIndex(iFocusedFieldIndex);
+        }
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLSetIndex);
+
+    // Update navigators
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLUpdateNavigators);
+    if ( iNavigator )
+        {
+        MVPbkContactLink* contactLink = aContact->CreateLinkLC();
+        if ( contactLink )
+            {
+            iNavigator->UpdateNaviIndicatorsL(*contactLink);
+            }
+        CleanupStack::PopAndDestroy(); // contactLink
+        }
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLUpdateNavigators);
+
+    DrawDeferred();
+
+    // To avoid double deletion, the store contact ownership
+    // is transferred after everything that can leave has been
+    // executed
+    delete iStoreContact;
+    iStoreContact = aContact;
+            
+    // Notify control readiness
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoControlUpdateLSendEvents);
+    TRAPD( error, SendEventToObserversL( TPbk2ControlEvent::EReady ) );
+    if ( error != KErrNone )
+        {
+        // When function leaves the aContact will be
+        // deleted through CleanupStack by calling function.
+        iStoreContact = NULL;
+        User::Leave( error );
+        }
+
+    SetFocus( ETrue );
+    
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateLSendEvents);
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoControlUpdateL);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FieldCount
+// --------------------------------------------------------------------------
+//
+TInt CPbk2ContactInfoControl::FieldCount() const
+    {
+    TInt ret = KErrNotReady;
+    if ( iFields )
+        {
+        ret = iFields->FieldCount();
+        }
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FieldPos
+// --------------------------------------------------------------------------
+//
+TInt CPbk2ContactInfoControl::FieldPos(
+        const MVPbkStoreContactField& aField) const
+    {
+    // PreCond:
+    __ASSERT_DEBUG(iListBox && iFields, Panic(EPanicPreCond_FieldPos));
+
+    TInt ret = KErrNotFound;
+    const TInt count(iFields->FieldCount());
+    for (TInt i = 0; i < count; ++i)
+        {
+        if (iFields->At(i).IsSame(aField))
+            {
+            ret = i;
+            break;
+            }
+        }
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::VPbkSingleContactOperationComplete
+// --------------------------------------------------------------------------
+//
+
+void CPbk2ContactInfoControl::VPbkSingleContactOperationComplete(
+        MVPbkContactOperationBase& aOperation,
+        MVPbkStoreContact* aContact)
+    {
+    if (aContact && &aOperation == iRetriever)
+        {
+        // contact loading completed, update control data
+        TRAPD(err, UpdateL(aContact));
+        if (err != KErrNone)
+            {
+            delete aContact;
+            CCoeEnv::Static()->HandleError(err);
+            }
+
+        delete iRetriever;
+        iRetriever = NULL;
+        delete iContactLink;
+        iContactLink = NULL;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::VPbkSingleContactOperationFailed
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::VPbkSingleContactOperationFailed(
+        MVPbkContactOperationBase& /*aOperation*/,
+        TInt aError)
+    {
+    CCoeEnv::Static()->HandleError(aError);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FocusedItemPointed
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactInfoControl::FocusedItemPointed()
+    {
+    return iListBox->FocusedItemPointed();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FocusableItemPointed
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactInfoControl::FocusableItemPointed()
+    {
+    return iListBox->FocusableItemPointed();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SearchFieldPointed
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactInfoControl::SearchFieldPointed()
+    {
+    return iListBox->SearchFieldPointed();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::OfferKeyEventL
+// --------------------------------------------------------------------------
+//
+TKeyResponse CPbk2ContactInfoControl::OfferKeyEventL(
+        const TKeyEvent& aKeyEvent,
+        TEventCode aType)
+    {
+    __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_OfferKeyEventL));
+
+    if ( aType == EEventKey )
+        {
+        // Reset iFocusedFieldIndex
+        // UpdateL method called after editor is closed and correct field
+        // is focused. Focus jump, if user same time than UpdateL method is
+        // called, scrolling fields. That's why this iFocusedFieldIndex
+        // reseting.
+        iFocusedFieldIndex = KErrNotFound;
+        }
+
+    // Forward all key events to the list box
+    TKeyResponse response = iListBox->OfferKeyEventL(aKeyEvent,aType);
+    
+    // Ignore Send Key up and down events to prevent Dialer appearance
+    // on top of Phonebook application.
+    if ( response == EKeyWasNotConsumed && IsFocused() )
+        {
+        if ( ( aType == EEventKeyDown || aType == EEventKeyUp )
+            && aKeyEvent.iScanCode == EStdKeyYes )
+            {
+            response = EKeyWasConsumed;
+            }
+        }
+        
+/*
+HandleControlEventL does this already...no need for double update...plus the HandleControlEventL works also for touch...
+    // Let the listbox first handle the key event before drawing the
+    // thumbnail.
+    if ( iThumbnailLoader && aType == EEventKey &&
+        (aKeyEvent.iScanCode == EStdKeyUpArrow ||
+        aKeyEvent.iScanCode == EStdKeyDownArrow ))
+        {
+        RDebug::Print( _L("### info view: OfferKeyEventL!") );
+        iThumbnailLoader->Refresh();
+        }
+*/
+    return response;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SizeChanged
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SizeChanged()
+    {
+    __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_SizeChanged));
+    // Listbox occupies whole area of this control
+    iListBox->SetRect(Rect());
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::CountComponentControls
+// --------------------------------------------------------------------------
+//
+TInt CPbk2ContactInfoControl::CountComponentControls() const
+    {
+    __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_CountComponentControls));
+    
+    // Always only one child control: the list box.
+    return KNumberOfControls;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::ComponentControl
+// --------------------------------------------------------------------------
+//
+CCoeControl* CPbk2ContactInfoControl::ComponentControl(
+        TInt PBK2_DEBUG_ONLY(aIndex)) const
+    {
+    __ASSERT_DEBUG(iListBox && aIndex==0,
+        Panic(EPanicPreCond_ComponentControl));
+
+    // Return the one and only child control
+    return iListBox;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::FocusChanged
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::FocusChanged(
+        TDrawNow aDrawNow )
+    {
+    if ( iListBox )
+        {
+        iListBox->SetFocus( IsFocused(), aDrawNow );
+        }
+
+    if ( IsFocused() )
+        {
+        ShowThumbnail();
+        }
+    else
+        {
+        HideThumbnail();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::HandleResourceChange
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::HandleResourceChange(
+        TInt aType)
+    {
+    CCoeControl::HandleResourceChange(aType);
+    TRAP_IGNORE(DoHandleResourceChangeL(aType));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::HandlePointerEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::HandlePointerEventL(
+    const TPointerEvent& aPointerEvent )
+    {
+    CCoeControl::HandlePointerEventL( aPointerEvent );
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        switch( aPointerEvent.iType )
+            {
+            case TPointerEvent::EButton1Up:
+                {
+                if ( iListBox != NULL && iListBox->Rect().Contains(
+                    aPointerEvent.iPosition ) )
+                    {
+                    iFocusedFieldIndex = iListBox->CurrentItemIndex();
+                    }
+                break;
+                }
+
+            default:
+                {
+                break;
+                }
+            };
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::HandleControlEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::HandleControlEventL(
+        CCoeControl* aControl,
+        TCoeEvent aEventType)
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactInfoControl::HandleControlEventL(0x%x,0x%x,%d)"),
+        this, aControl, aEventType);
+    if ( iThumbnailLoader && (aControl == iListBox) && IsFocused() )
+        {
+        iThumbnailLoader->Refresh();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::StorePanesL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2ContactInfoControl::StorePanesL(
+        CPbk2ContactInfoDataSwapper& aSwapper,
+        const CPbk2PresentationContact* aContact)
+    {
+    if( iFlags & KPbk2ContactInfoControlUpdateStatusPane )
+        {
+        if( (iFlags & KPbk2ContactInfoControlUpdateTitlePane) && iTitlePane )
+            {
+            // Store title pane text
+            if (aContact)
+                {
+                aSwapper.iTitlePaneText = iNameFormatter.GetContactTitleL(
+                    aContact->Fields(), KDefaultTitleFormat);
+                }
+            }
+        if( iFlags & KPbk2ContactInfoControlUpdateContextPane )
+            {
+            if (aContact)
+				{
+	            iThumbnailLoader->LoadThumbnail(&aContact->StoreContact(),
+	                                            iListBox,
+	                                            ELocationUpDown);
+				}
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::SendEventToObserversL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::SendEventToObserversL(
+        const TPbk2ControlEvent& aEvent)
+    {
+    // Loop backwards in case some observer destroys itself in the
+    // event handler
+    for (TInt i = iObservers.Count()-1; i >= 0; --i)
+        {
+        iObservers[i]->HandleControlEventL(*this, aEvent);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::CreateDynamicFieldPropertiesLC
+// --------------------------------------------------------------------------
+//
+CPbk2ContactFieldDynamicProperties*
+    CPbk2ContactInfoControl::CreateDynamicFieldPropertiesLC(
+        CPbk2PresentationContact& aContact )
+    {
+    CPbk2ContactFieldDynamicProperties* filter =
+        CPbk2ContactFieldDynamicProperties::NewLC();
+    // Check is there ringtone field and if there is, check that file is still
+    // available. If not, hide the field.
+    TInt fieldCount( aContact.Fields().FieldCount() );
+    for ( TInt i = 0; i < fieldCount; ++i )
+        {
+        const MVPbkStoreContactField& field = aContact.Fields().FieldAt( i );
+        TInt resId( field.BestMatchingFieldType()->FieldTypeResId() );
+        if ( resId == R_VPBK_FIELD_TYPE_RINGTONE )
+            {
+            TPtrC filename =
+                MVPbkContactFieldTextData::Cast( field.FieldData() ).Text();
+            if ( !BaflUtils::FileExists(
+                CCoeEnv::Static()->FsSession(),
+                filename ) )
+                {
+                filter->AddHiddenFieldResourceId( resId );
+                aContact.PresentationFields().At( i ).
+                    SetDynamicVisibility( EFalse );
+                break;
+                }
+            }
+        }
+
+    return filter;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::DoHandleResourceChangeL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::DoHandleResourceChangeL(
+        TInt aType)
+    {
+    if (iListBox)
+        {
+        iListBox->DoHandleResourceChangeL(aType);
+        }
+/*  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("### InfoControl::HandleResourceChangeL - show") );
+            ShowThumbnail();
+            }
+        else
+            {
+            RDebug::Print( _L("### InfoControl::HandleResourceChangeL - hide") );
+            HideThumbnail();
+            }
+        }*/
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::RetrieveContactL
+// --------------------------------------------------------------------------
+//    
+void CPbk2ContactInfoControl::RetrieveContactL( 
+        const MVPbkContactLink& aContactLink )
+    {
+    delete iRetriever;
+    iRetriever = NULL;
+    iRetriever = iContactManager.RetrieveContactL( aContactLink, *this );
+    }
+
+// --------------------------------------------------------------------------
+// 
+// --------------------------------------------------------------------------
+//    
+void CPbk2ContactInfoControl::HandleScrollEventL(CEikScrollBar* /*aScrollBar*/, TEikScrollEvent aEventType)
+    {
+
+
+    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 )
+                {
+                ShowThumbnail();
+                iDidMove = EFalse;
+                }
+            break;
+            }
+
+        default:
+            {
+            iDidMove= EFalse;
+            if( iThumbnailLoader )
+                {
+                iThumbnailLoader->Refresh();
+                }
+            }
+        }
+    }
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoControl::HandleListBoxEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoControl::HandleListBoxEventL(
+    CEikListBox* /*aListBox*/, TListBoxEvent aEventType )
+    {
+    switch ( aEventType )
+        {
+        case EEventItemDoubleClicked:
+            SendEventToObserversL( TPbk2ControlEvent::EContactDoubleTapped );
+            break;
+        case EEventItemSingleClicked:
+            SendEventToObserversL( TPbk2ControlEvent::EContactTapped );
+            break;   
+        case EEventEnterKeyPressed:
+            SendEventToObserversL( TPbk2ControlEvent::EControlEnterKeyPressed );
+            break;  
+        default:
+            ;
+        }
+    }
+
+
+//  End of File