phonebookui/Phonebook2/Application/src/CPbk2ContactInfoAppView.cpp
changeset 0 e686773b3f54
child 21 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/Application/src/CPbk2ContactInfoAppView.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,1240 @@
+/*
+* 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 application view.
+*
+*/
+
+// INCLUDE FILES
+#include "CPbk2ContactInfoAppView.h"
+
+// Phonebook 2
+#include "CPbk2AppUi.h"
+#include "CPbk2Document.h"
+#include "CPbk2StartupMonitor.h"
+#include "CPbk2ViewExplorer.h"
+#include "CPbk2ViewActivationTransaction.h"
+#include "Pbk2InternalCommands.hrh"
+#include "CPbk2ViewLoader.h"
+#include <Phonebook2.rsg>
+#include <Pbk2UIControls.rsg>
+#include <Pbk2Commands.rsg>
+#include <CPbk2ViewState.h>
+#include <MPbk2ContactNavigation.h>
+#include <Pbk2NavigatorFactory.h>
+#include <CPbk2ControlContainer.h>
+#include <CPbk2ContactInfoControl.h>
+#include <MPbk2CommandHandler.h>
+#include <MPbk2ContactDetailsControl.h>
+#include <CPbk2StoreConfiguration.h>
+#include <CPbk2MemoryEntryContactLoader.h>
+#include <Pbk2Commands.hrh>
+#include <CPbk2ViewStateTransformer.h>
+#include <TPbk2StoreContactAnalyzer.h>
+#include <CPbk2FieldPropertyArray.h>
+#include <CPbk2SortOrderManager.h>
+#include <CPbk2ViewGraph.h>
+#include <Pbk2UID.h>
+#include <csxhelp/phob.hlp.hrh>
+#include <MPbk2PointerEventInspector.h>
+#include <MPbk2ApplicationServices.h>
+#include <MPbk2ContactViewSupplier.h>
+
+// Virtual Phonebook
+#include <CVPbkContactManager.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkContactLink.h>
+#include <MVPbkContactViewBase.h>
+#include <MVPbkExpandable.h>
+#include <CVPbkContactStoreUriArray.h>
+#include <MVPbkContactStoreList.h>
+#include <TVPbkContactStoreUriPtr.h>
+
+// System includes
+#include <avkon.rsg>
+#include <AiwCommon.hrh>
+#include <eikmenub.h>
+#include <AknUtils.h>
+#include <StringLoader.h>
+
+// Debugging headers
+#include <Pbk2Debug.h>
+#include <Pbk2Profile.h>
+#include <Pbk2Config.hrh>
+
+/// Unnamed namespace for local definitions
+namespace {
+
+#ifdef _DEBUG
+enum TPanicCode
+    {
+    EPanicPreCond_HandleCommandL = 1,
+    EPanicPreCond_HandleCommandKeyL,
+    EPanicPostCond_ConstructL,
+    EPanicPreCond_DynInitMenuPaneL,
+    EPanicPreCond_ContactChangedL,
+    EPanicPreCond_SetNavigatorViewL,
+    EPanicPreCond_GetViewSpecificMenuFilteringFlagsL,
+    EPanicPreCond_NULLPointer,
+    EPanicPreCond_ViewLoaded,
+    EPanicLogic_LoadContactL
+    };
+
+void Panic(TPanicCode aReason)
+    {
+    _LIT( KPanicText, "CPbk2ContactInfoAppView" );
+    User::Panic( KPanicText, aReason );
+    }
+#endif // _DEBUG
+
+} /// namespace
+
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::CPbk2ContactInfoAppView
+// --------------------------------------------------------------------------
+//
+inline CPbk2ContactInfoAppView::CPbk2ContactInfoAppView
+        ( CVPbkContactManager& aContactManager ) :
+            iContactManager( aContactManager )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::~CPbk2ContactInfoAppView
+// --------------------------------------------------------------------------
+//
+CPbk2ContactInfoAppView::~CPbk2ContactInfoAppView()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactInfoAppView(%x)::~CPbk2ContactInfoAppView()"), this);
+
+    delete iViewLoader;
+    delete iControlState;
+    delete iViewActivationTransaction;
+    delete iNavigation;
+    delete iContactLoader;
+    iStoreList.Reset();
+    iStoreList.Close();
+
+    if (iContainer)
+        {
+        AppUi()->RemoveFromViewStack(*this, iContainer);
+        delete iContainer;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2ContactInfoAppView* CPbk2ContactInfoAppView::NewL
+        ( CVPbkContactManager& aContactManager )
+    {
+    CPbk2ContactInfoAppView* self =
+        new ( ELeave ) CPbk2ContactInfoAppView( aContactManager );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ConstructL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2ContactInfoAppView::ConstructL()
+    {
+    // Init base class
+    PBK2_PROFILE_START(Pbk2Profile::EContactInfoViewBaseConstruct);
+    CAknView::BaseConstructL(R_PHONEBOOK2_CONTACTINFO_APPVIEW);
+    PBK2_PROFILE_END(Pbk2Profile::EContactInfoViewBaseConstruct);
+
+    iCommandHandler = Pbk2AppUi()->ApplicationServices().CommandHandlerL();
+    iStoreConfiguration =  &Pbk2AppUi()->ApplicationServices().
+        StoreConfiguration();
+
+    __ASSERT_DEBUG(iCommandHandler,
+        Panic(EPanicPostCond_ConstructL));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::HandleCommandL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::HandleCommandL
+        (TInt aCommandId)
+    {
+    __ASSERT_DEBUG(iControl,
+        Panic(EPanicPreCond_HandleCommandL));
+
+    // If this view has already been deactivated, just return
+    if ( Pbk2AppUi()->ActiveView()->Id() != Phonebook2::KPbk2ContactInfoViewUid )
+        {
+        return;
+        }
+
+    if (EAknCmdHideInBackground == aCommandId)
+        {
+        // Gets a pointer to Nameslist extension view
+        CAknView* pNamesListExtensionView =
+                static_cast<CAknView*> (Pbk2AppUi()->View(
+                        Phonebook2::KPbk2NamesListViewUid));
+
+        // if Nameslist extension view does exists, 
+        // pass EAknCmdHideInBackground to the view, in order to close the CCA.
+        if (pNamesListExtensionView)
+            {
+            pNamesListExtensionView->HandleCommandL(aCommandId);
+            }
+        }
+
+    switch (aCommandId)
+        {
+        case EAknSoftkeyBack:       // FALLTHROUGH
+        case EPbk2CmdOpenPreviousView:
+            {
+            // Set the focused contact according to control state -> NULL
+            ReturnToPreviousViewL( NULL );
+            break;
+            }
+        default:
+            {
+            // No command handling in this class, forward to Commands
+            if ( !iCommandHandler->HandleCommandL
+                    ( aCommandId, *iControl, this ) )
+                {
+                iControl->ProcessCommandL(aCommandId);
+                // Command was not handled in Pbk2Commands,
+                // forward it to AppUi
+                AppUi()->HandleCommandL(aCommandId);
+                if ( aCommandId == EAknCmdHideInBackground )
+                    {
+                    DoDeactivate();
+                    }
+                }
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::DynInitMenuPaneL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::DynInitMenuPaneL
+        (TInt aResourceId, CEikMenuPane* aMenuPane)
+    {
+    __ASSERT_DEBUG(iControl,
+        Panic(EPanicPreCond_DynInitMenuPaneL));
+
+    // Ask the control do control specific filtering
+    iControl->DynInitMenuPaneL(aResourceId, aMenuPane);
+
+    // Phonebook 2 menu filtering happens in Commands
+    iCommandHandler->DynInitMenuPaneL(
+            aResourceId, aMenuPane, *this, *iControl);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::Id
+// --------------------------------------------------------------------------
+//
+TUid CPbk2ContactInfoAppView::Id() const
+    {
+    return Phonebook2::KPbk2ContactInfoViewUid;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::HandleStatusPaneSizeChange
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::HandleStatusPaneSizeChange()
+    {
+    // Resize the container to fill the client rectangle
+    if (iContainer)
+        {
+        iContainer->SetRect(ClientRect());
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::DoActivateL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::DoActivateL
+        ( const TVwsViewId& aPrevViewId,
+          TUid aCustomMessageId, const TDesC8& aCustomMessage )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactInfoAppView(%x)::DoActivateL()"), this);
+
+    //NOTE: this view can be used as external,
+    // DoActivateL can be called for active view
+ 
+    // UpdateViewGraphL only for pbk2 views, 
+    if ( Pbk2AppUi()->Pbk2ViewExplorer()->IsPhonebook2View(aPrevViewId) )
+        {
+        UpdateViewGraphL( aPrevViewId );
+        }
+    else if ( iContainer )
+        {
+        // if the view activated as an external, reset it state
+        delete iControlState;
+        iControlState = NULL;
+        }
+
+    iCommandHandler->RemoveMenuCommandObserver( *this );
+    iCommandHandler->AddMenuCommandObserver( *this );
+    
+    iStoreConfiguration->RemoveObserver( *this );
+    iStoreConfiguration->AddObserverL( *this );
+
+    // Update application-wide state. UI control updates the title pane.
+    delete iViewActivationTransaction;
+    iViewActivationTransaction = NULL;
+    TUint flags (Phonebook2::EUpdateContextPane);
+    if ( !iContainer )
+        {
+        // don't update navipane if it's already active
+        flags |= Phonebook2::EUpdateNaviPane;
+        }
+    iViewActivationTransaction =
+        Pbk2AppUi()->Pbk2ViewExplorer()->HandleViewActivationLC
+            ( Id(), aPrevViewId, NULL, NULL,
+              flags );
+    CleanupStack::Pop(); // iViewActivationTransaction
+
+    if (aCustomMessageId == CPbk2ViewState::Uid() ||
+        aCustomMessageId == TUid::Uid(KPbkViewStateUid))
+        {
+        // Handles both new and legacy view state parameters
+        UpdateViewStateL(aCustomMessageId, aCustomMessage);
+        }
+    else
+        {
+        // No UI state specified, restore in previous state
+        if (!iControlState)
+            {
+            // No previous state
+            User::Leave(KErrArgument);
+            }
+        }
+
+     if ( !iControlState->FocusedContact() )
+        {
+        User::Leave( KErrArgument );
+        }
+     
+    //navigator is created for each DoActiveL, depends on input parameters
+    //navigator is created for each DoActiveL, depends on input parameters
+    ConstructNavigatorL();
+    
+    //if the view is active, its control is reused, only navigator is updated
+    CreateControlsL();
+    AttachAIWProvidersL();
+
+    LoadContactViewL( aPrevViewId );
+    iPreviousViewId = aPrevViewId;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::DoDeactivate
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::DoDeactivate()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactInfoAppView(%x)::DoDeactivate()"), this);
+
+    delete iViewLoader;
+    iViewLoader = NULL;
+
+    iCommandHandler->RemoveMenuCommandObserver( *this );
+
+    iStoreConfiguration->RemoveObserver( *this );
+
+    delete iViewActivationTransaction;
+    iViewActivationTransaction = NULL;
+    delete iNavigation;
+    iNavigation = NULL;
+
+    // Trash the old states
+    delete iControlState;
+    iControlState = NULL;
+
+    // Reset store list
+    iStoreList.Reset();
+
+    if (iContainer)
+        {
+        iContainer->Control()->HideThumbnail();
+
+        // Remove view and its control from the view stack
+        AppUi()->RemoveFromViewStack(*this, iContainer);
+
+        // Store current state, safe to ignore. There's no real harm,
+        // if theres no stored state when activating this view again
+        TRAP_IGNORE(StoreStateL());
+
+        // Destroy the container control
+        delete iContainer;
+        iContainer = NULL;
+        iControl = NULL;
+        }
+
+    delete iContactLoader;
+    iContactLoader = NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::HandleForegroundEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::HandleForegroundEventL( TBool aForeground )
+    {
+    CPbk2AppView::HandleForegroundEventL(aForeground);
+
+    // If this view is gaining foreground, then make sure that thumbnail
+    // gets drawn
+    if (aForeground && iContainer && iContainer->Control())
+        {
+        if ( iContainer->Control()->IsVisible() )
+            {
+            iContainer->Control()->ShowThumbnail();
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ViewStateLC
+// --------------------------------------------------------------------------
+//
+CPbk2ViewState* CPbk2ContactInfoAppView::ViewStateLC() const
+    {
+    __ASSERT_DEBUG( iControl ,Panic(EPanicPreCond_NULLPointer));
+
+    CPbk2ViewState* state = iControl->ControlStateL();
+    CleanupStack::PushL(state);
+    return state;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::HandleCommandKeyL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactInfoAppView::HandleCommandKeyL
+        (const TKeyEvent& aKeyEvent, TEventCode aType)
+    {
+    __ASSERT_DEBUG(iContainer && iNavigation,
+        Panic(EPanicPreCond_HandleCommandKeyL));
+
+    // Pass the key event to the strategy
+    TBool ret = iNavigation->HandleCommandKeyL( aKeyEvent, aType );
+
+    if ( !ret && aType == EEventKey )
+        {
+        switch ( aKeyEvent.iCode )
+            {
+            case EKeyEnter: // FALLTHROUGH
+            case EKeyOK:
+                {
+                LaunchPopupMenuL( R_PHONEBOOK2_CONTACTINFO_CONTEXTBAR );
+                ret = ETrue;
+                break;
+                }
+            case EKeyBackspace:  // Clear key
+                {
+                HandleCommandL(EPbk2CmdDeleteMe);
+                ret = ETrue;
+                break;
+                }
+            case EKeyPhoneSend:
+                {
+                // If focused field is either url or email field
+                // the proper context menu should be launched.
+                if ( IsFocusedFieldTypeL( R_PHONEBOOK2_URL_SELECTOR )
+                    || IsFocusedFieldTypeL( R_PHONEBOOK2_EMAIL_SELECTOR ) )
+                    {
+                    LaunchPopupMenuL( R_PHONEBOOK2_CONTACTINFO_CONTEXTBAR );
+                    }
+                else
+                    {
+                    // Use the EPbk2CmdCall id to identify that
+                    // call is being launched with send key
+                    HandleCommandL( EPbk2CmdCall );
+                    }
+                ret = ETrue;
+                break;
+                }
+            case EKeyPoC:
+                {
+                // Use the EPbk2CmdPoC id to identify that
+                // call is being launched with PoC key
+                HandleCommandL( EPbk2CmdPoC );
+                ret = ETrue;
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+        }
+    return ret;
+    }
+
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::GetViewSpecificMenuFilteringFlagsL
+// --------------------------------------------------------------------------
+//
+TInt CPbk2ContactInfoAppView::GetViewSpecificMenuFilteringFlagsL() const
+    {
+    __ASSERT_DEBUG( iControl,
+        Panic( EPanicPreCond_GetViewSpecificMenuFilteringFlagsL ) );
+
+    return iControl->GetMenuFilteringFlagsL();
+    }
+
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::PrepareForContactChangeL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::PrepareForContactChangeL()
+    {
+    StoreStateL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ContactChangedL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::ContactChangedL( MVPbkStoreContact* aContact )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactInfoAppView(%x)::ContactChangedL() begin"), this);
+
+    if ( !iContainer )
+        {
+        // It is possible that this method get called before
+        // the container and control get constructed.
+        // In that case, ignore the given contact by deleting
+        // it and do not continue the contact changed process.
+        delete aContact;
+
+        // iViewActivationTransaction should not be deleted here
+        // since it is not tied to this ContactChangedL request
+
+        PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+            ("CPbk2ContactInfoAppView(%x)::ContactChangedL() controls not ready"),
+            this);
+        }
+    else
+        {
+        __ASSERT_DEBUG(iViewActivationTransaction,
+            Panic(EPanicPreCond_ContactChangedL));
+        __ASSERT_DEBUG(iNavigation, Panic(EPanicPreCond_ContactChangedL));
+
+        // Update controls
+        if (aContact)
+            {
+            CleanupDeletePushL(aContact);
+            iContainer->Control()->UpdateL(aContact);
+            CleanupStack::Pop(aContact);    // ownership was taken
+            }
+
+        if ( iControlState->FocusedContact() )
+            {
+            if ( !iControlState->FocusedContact()->RefersTo( *aContact ) )
+                {
+                iContainer->Control()->SetFocusedFieldIndex( KErrNotFound );
+                iControlState->SetFocusedFieldIndex( KErrNotFound );
+                }
+            }
+
+        SetEmptyTextL( R_QTN_PHOB_NO_ITEMS );
+
+        iContainer->Control()->RestoreControlStateL(iControlState);
+
+        // Commit application-wide state changes
+        iViewActivationTransaction->Commit();
+
+        // notifies startup monitor of view activation
+        if (Pbk2AppUi()->Pbk2StartupMonitor())
+            {
+            Pbk2AppUi()->Pbk2StartupMonitor()->NotifyViewActivationL(Id());
+            }
+        }
+
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactInfoAppView(%x)::ContactChangedL() end"), this);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ContactChangeFailed
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::ContactChangeFailed()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactInfoAppView(%x)::ContactChangeFailed()"), this);
+
+    TInt err = KErrNone;
+
+    TRAP( err, SetEmptyTextL( R_QTN_PHOB_NO_ITEMS ) );
+    if ( err != KErrNone )
+        {
+        CEikonEnv::Static()->HandleError( err );
+        }
+
+    // Rollback
+    if ( iViewActivationTransaction )
+        {
+        // Rollback by force
+        TRAP( err, iViewActivationTransaction->RollbackL() );
+        delete iViewActivationTransaction;
+        iViewActivationTransaction = NULL;
+
+        if ( err != KErrNone )
+            {
+            CEikonEnv::Static()->HandleError( err );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::Contact
+// --------------------------------------------------------------------------
+//
+const MVPbkStoreContact* CPbk2ContactInfoAppView::Contact() const
+    {
+    const MVPbkStoreContact* result = NULL;
+    if (iControl)
+        {
+        result = iControl->FocusedStoreContact();
+        }
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::HandleControlEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::HandleControlEventL
+        ( MPbk2ContactUiControl& /*aControl*/,
+          const TPbk2ControlEvent& aEvent )
+    {
+    switch (aEvent.iEventType)
+        {
+        case TPbk2ControlEvent::EContactDoubleTapped:
+            {
+            LaunchPopupMenuL( R_PHONEBOOK2_CONTACTINFO_CONTEXTBAR );
+            break;
+            }
+
+        case TPbk2ControlEvent::EReady:
+            {
+            UpdateCbasL();
+            break;
+            }
+
+        default:
+            {
+            // Do nothing
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ConfigurationChanged
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::ConfigurationChanged()
+    {
+    if (iPreviousViewId.iViewUid != KNullUid)
+        {
+        TRAPD(err, LoadContactViewL(iPreviousViewId));
+        if (err != KErrNone)
+            {
+            CCoeEnv::Static()->HandleError(err);
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ConfigurationChangedComplete
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::ConfigurationChangedComplete()
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::PreCommandExecutionL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::PreCommandExecutionL
+        ( const MPbk2Command& /*aCommand*/ )
+    {
+    if (iContainer && iContainer->Control())
+        {
+        iContainer->Control()->HideThumbnail();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::PostCommandExecutionL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::PostCommandExecutionL
+        ( const MPbk2Command& /*aCommand*/ )
+    {
+    if (iContainer && iContainer->Control())
+        {
+        iContainer->Control()->ShowThumbnail();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::CreateControlsL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2ContactInfoAppView::CreateControlsL()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+            ("CPbk2ContactInfoAppView::CreateControlsL()"));
+
+    // if the view is active, recreate control, in order
+    // to use new iNavigation and delete old storecontact
+
+    if ( iContainer && iControl )
+        {
+        iContainer->DestroyControl();
+        iControl = NULL;
+        }
+
+    if (!iContainer)
+        {
+        // Create the container and control
+        CContainer* container = CContainer::NewLC(this, this, *this);
+
+        container->SetHelpContext( TCoeHelpContext( ApplicationUid(),
+                KHLP_CCA_DETAILS ));
+        
+        // Add this view and container to the view stack
+        AppUi()->AddToViewStackL(*this, container);
+        CleanupStack::Pop(container);
+        iContainer = container;
+        }
+
+    if ( !iControl )
+        {
+        CPbk2ContactInfoControl* control = CPbk2ContactInfoControl::NewL
+            ( iContainer, iContactManager,
+              Pbk2AppUi()->ApplicationServices().NameFormatter(),
+              Pbk2AppUi()->ApplicationServices().FieldProperties(),
+              Pbk2AppUi()->ApplicationServices().StoreProperties(),
+              iNavigation );
+        TRect r = ClientRect();
+        iContainer->SetControl(control, r); // takes ownership
+        control->AddObserverL(*this);
+
+        iControl = control;
+        
+        // Assign pointer event inspector
+        iPointerInspector =
+            AknLayoutUtils::PenEnabled() ? control : NULL;
+
+        iContainer->ActivateL();
+        iContainer->Control()->MakeVisible( ETrue );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::HandleNavigationEvent
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::HandleNavigationEvent
+        ( const TEventType& aEventType )
+    {
+    if ( aEventType == MPbk2NavigationObserver::EContactDeleted )
+        {
+        // Contact was deleted which means that we must go back to previous
+        // view. The previous view must know the contact to focus and it
+        // obviously can not be the deleted contact. The navigator works
+        // in a same logic as the focus in the previous view. It knows the
+        // the contact after deletion.
+        TRAPD( err,
+            {
+            MVPbkContactLink* curContact = CurrentContactInNavigatorLC();
+            CleanupStack::Pop(); // curContact
+            // Give ownership of curContact
+            ReturnToPreviousViewL( curContact );
+            });
+        if ( err != KErrNone )
+            {
+            CCoeEnv::Static()->HandleError( err );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ViewLoaded
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::ViewLoaded( MVPbkContactViewBase& aView )
+    {
+    __ASSERT_DEBUG(iContactLoader && iControlState,
+        Panic(EPanicPreCond_ViewLoaded));
+
+    if ( &aView == iContactView )
+        {
+        TRAPD( error, HandleViewLoadedL() );
+        if ( error != KErrNone )
+            {
+            ViewError( aView, error );
+            }
+        }
+    delete iViewLoader;
+    iViewLoader = NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ViewError
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::ViewError
+        ( MVPbkContactViewBase& aView, TInt /*aError*/ )
+    {
+    delete iViewLoader;
+    iViewLoader = NULL;
+
+    if ( &aView == iContactView )
+        {
+        TRAPD( error, iViewActivationTransaction->RollbackL() );
+        if ( error != KErrNone )
+            {
+            CCoeEnv::Static()->HandleError(error);
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::UpdateViewStateL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2ContactInfoAppView::UpdateViewStateL
+        ( const TUid aCustomMessageId,
+          const TDesC8& aCustomMessage )
+    {
+    CPbk2ViewState* viewState = NULL;
+    if (aCustomMessageId == TUid::Uid(KPbkViewStateUid))
+        {
+        // handle legacy view state
+        CPbk2ViewStateTransformer* transformer =
+            CPbk2ViewStateTransformer::NewLC( iContactManager );
+        viewState = transformer->
+                TransformLegacyViewStateToPbk2ViewStateLC( aCustomMessage );
+        CleanupStack::Pop();
+        CleanupStack::PopAndDestroy(transformer);
+        }
+    else if (aCustomMessageId == CPbk2ViewState::Uid())
+        {
+        // Read the desired UI state from aCustomMessage
+        viewState = CPbk2ViewState::NewL(aCustomMessage);
+        }
+    else
+        {
+        // a parameter must be passed to this view
+        User::Leave(KErrNotSupported);
+        }
+
+    if (iControlState)
+        {
+        // Merge parameter view state with the stored state
+        if ( viewState->FocusedContact() &&
+            !viewState->FocusedContact()->IsSame
+                ( *iControlState->FocusedContact() ))
+            {
+            iControlState->SetFocusedContact(
+                    viewState->TakeFocusedContact());
+            iControlState->SetFocusedFieldIndex(KErrNotFound);
+            iControlState->SetTopFieldIndex(KErrNotFound);
+            }
+        if (viewState->FocusedFieldIndex() >= 0)
+            {
+            iControlState->SetFocusedFieldIndex(
+                    viewState->FocusedFieldIndex());
+            }
+        if (viewState->TopFieldIndex() >= 0)
+            {
+            iControlState->SetTopFieldIndex(
+                    viewState->TopFieldIndex());
+            }
+        if ( viewState->ParentContact() )
+            {
+            iControlState->SetParentContact(
+                viewState->TakeParentContact());
+            }
+        // Delete parameter view state
+        delete viewState;
+        }
+    else
+        {
+        // No stored state, use the parameter supplied one
+        iControlState = viewState;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::SetNavigatorViewL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::SetNavigatorViewL()
+    {
+    __ASSERT_DEBUG(iNavigation,
+        Panic(EPanicPreCond_SetNavigatorViewL));
+
+    // Set default navigation
+    iNavigation->SetScrollViewL( iContactView, EFalse );
+
+    // Inspect if the parent contact is set and if the parent
+    // contact is expandable. In that case set the navigation
+    // view to the expandable view.
+    const MVPbkContactLink* parentLink = iControlState->ParentContact();
+    if ( parentLink )
+        {
+        // Find parent index in the contact view
+        const TInt parentIndex =
+            iContactView->IndexOfLinkL( *parentLink );
+        // Get the view contact by view index
+        const MVPbkViewContact& viewContact =
+            iContactView->ContactAtL( parentIndex );
+
+        // Expand the scroll view from the view contact
+        MVPbkExpandable* expandable = viewContact.Expandable();
+        if ( expandable )
+            {
+            MVPbkContactViewBase* scrollView = expandable->ExpandLC
+                ( *iNavigation, Pbk2AppUi()->ApplicationServices().
+                    SortOrderManager().SortOrder() );
+            CleanupStack::Pop(); // scrollView
+
+            // Set the navigation scroll view, transfer ownership
+            iNavigation->SetScrollViewL( scrollView, ETrue );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::StoreStateL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::StoreStateL()
+    {
+    CPbk2ViewState* state = ViewStateLC();
+    CleanupStack::Pop(state);
+
+    // state should be always created, but valid state
+    // has focusedContact
+    if ( state && state->FocusedContact() )
+        {
+        delete iControlState;
+        iControlState = state;
+        }
+    else
+        {
+        delete state;
+        state = NULL;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::IsFocusedFieldTypeL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2ContactInfoAppView::IsFocusedFieldTypeL( TInt aSelectorResId )
+    {
+    TPbk2StoreContactAnalyzer analyzer( iContactManager, NULL );
+    const MVPbkBaseContactField* field = iContainer->Control()->FocusedField();
+
+    if ( field )
+        {
+        return analyzer.IsFieldTypeIncludedL( *field, aSelectorResId );
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::UpdateCbasL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::UpdateCbasL()
+    {
+    if ( iControl )
+        {
+        // Set cba command set "Options - Context Menu - Back"
+        Cba()->SetCommandSetL( R_PBK2_SOFTKEYS_OPTIONS_BACK_CONTEXT );
+        Cba()->DrawDeferred();
+        // Set context menu
+        MenuBar()->SetContextMenuTitleResourceId
+            ( R_PHONEBOOK2_CONTACTINFO_CONTEXTBAR );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::AttachAIWProvidersL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2ContactInfoAppView::AttachAIWProvidersL()
+    {
+        iCommandHandler->RegisterAiwInterestL
+            ( KAiwCmdCall, R_PHONEBOOK2_CALL_MENU,
+            R_PHONEBOOK2_CALLUI_AIW_INTEREST, ETrue );
+    
+        iCommandHandler->RegisterAiwInterestL
+            (KAiwCmdCall, R_PHONEBOOK2_CALL_CONTEXT_MENU,
+            R_PHONEBOOK2_CALLUI_AIW_INTEREST, EFalse);
+    
+        iCommandHandler->RegisterAiwInterestL
+            ( KAiwCmdPoC, R_PHONEBOOK2_POC_MENU,
+            R_PHONEBOOK2_POCUI_AIW_INTEREST, ETrue );
+    
+        iCommandHandler->RegisterAiwInterestL
+            (KAiwCmdPoC, R_PHONEBOOK2_POC_CONTEXT_MENU,
+            R_PHONEBOOK2_POCUI_AIW_INTEREST, EFalse);
+    
+        iCommandHandler->RegisterAiwInterestL
+            (KAiwCmdInfoView, R_PHONEBOOK2_SIND_INFOVIEW_MENU,
+            R_PHONEBOOK2_SIND_INFOVIEW_AIW_INTEREST, EFalse);
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::HandleLongTapEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::HandleLongTapEventL
+        ( const TPoint& /*aPenEventLocation*/,
+          const TPoint& /*aPenEventScreenLocation*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::CurrentContactInNavigatorLC
+// --------------------------------------------------------------------------
+//
+MVPbkContactLink* CPbk2ContactInfoAppView::CurrentContactInNavigatorLC()
+    {
+    if ( iNavigation )
+        {
+        return iNavigation->CurrentContactLC();
+        }
+    else
+        {
+        MVPbkContactLink* link = NULL;
+        // LC semantics also in NULL case.
+        CleanupStack::PushL( link );
+        return link;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ReturnToPreviousViewL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::ReturnToPreviousViewL
+        ( MVPbkContactLink* aFocusedContact ) const
+    {
+    // Ownership of aFocusedContact is taken by this function
+    CleanupDeletePushL( aFocusedContact );
+
+    CPbk2ViewState* state = ViewStateLC();
+    CleanupStack::Pop( state );
+
+    // aFocusedContact contact overwrites the focused contact from control's
+    // state.
+    if ( aFocusedContact )
+        {
+        // state takes the ownership if aFocusedContact
+        state->SetFocusedContact( aFocusedContact );
+        CleanupStack::Pop(); // aFocusedContact
+        }
+    else
+        {
+        CleanupStack::PopAndDestroy(); // aFocusedContact
+        }
+
+    CleanupStack::PushL( state );
+
+    Pbk2AppUi()->Pbk2ViewExplorer()->ActivatePreviousViewL( state );
+    CleanupStack::PopAndDestroy( state );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::LoadContactViewL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::LoadContactViewL
+        ( const TVwsViewId& aPrevViewId )
+    {
+    delete iViewLoader;
+    iViewLoader = NULL;
+
+    if ( Pbk2AppUi()->Pbk2ViewExplorer()->
+            IsPhonebook2View( aPrevViewId ) &&
+            ( aPrevViewId.iViewUid == TUid::Uid
+                ( EPbk2GroupMembersListViewId ) ) )
+        {
+        iContactView = Phonebook2::Pbk2AppUi()->ApplicationServices().
+                ViewSupplier().AllGroupsViewL();
+        }
+    else
+        {
+        iContactView = Phonebook2::Pbk2AppUi()->ApplicationServices().
+                ViewSupplier().AllContactsViewL();
+        }
+
+    iViewLoader = CPbk2ViewLoader::NewL( *iContactView, *this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::HandleViewLoadedL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::HandleViewLoadedL()
+    {
+    SetNavigatorViewL();
+    LoadContactL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::LoadContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::LoadContactL()
+    {
+    const MVPbkContactLink* link = iControlState->FocusedContact();
+    __ASSERT_DEBUG( link, Panic( EPanicLogic_LoadContactL ) );
+    __ASSERT_DEBUG( iContactLoader, Panic( EPanicLogic_LoadContactL ) );
+
+    //ChangeContact can delete iControlState, invalidating link
+    //therefore copy link
+    MVPbkContactLink* inputParameterContact = link->CloneLC();
+    // Load the contact from view state, this is asynchronous
+    iContactLoader->ChangeContactL( *inputParameterContact );
+    CleanupStack::PopAndDestroy(); //inputParameterContact 
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::ConstructNavigatorL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::ConstructNavigatorL()
+    {
+    iStoreList.Reset();
+    CVPbkContactStoreUriArray* uriList =
+        Pbk2AppUi()->ApplicationServices().StoreConfiguration().
+            CurrentConfigurationL();
+    CleanupStack::PushL( uriList );
+    MVPbkContactStoreList& fullStoreList =
+        iContactManager.ContactStoresL();
+    for (TInt i = 0; i < uriList->Count(); ++i)
+        {
+        // Add all the contact stores to the store list
+        TVPbkContactStoreUriPtr uri = (*uriList)[i];
+        MVPbkContactStore* store = fullStoreList.Find(uri);
+        iStoreList.AppendL(store);
+        }
+    CleanupStack::PopAndDestroy( uriList );
+
+    /// Create contact loader and contact info scroll navigator
+    delete iContactLoader;
+    iContactLoader = NULL;
+    iContactLoader = CPbk2MemoryEntryContactLoader::NewL( *this );
+
+    MVPbkContactStore& storeFromState =
+        iControlState->FocusedContact()->ContactStore();
+    TBool storeNotInConfiguration = EFalse;
+    if ( iStoreList.Find( &storeFromState ) == KErrNotFound )
+        {
+        storeNotInConfiguration = ETrue;
+        // Do not add store into list, opening of this lone
+        // store is not navigator's responsibility
+        }
+
+    delete iNavigation;
+    iNavigation = NULL;
+    
+    if ( !storeNotInConfiguration )
+        {
+        iNavigation = Pbk2NavigatorFactory::CreateContactNavigatorL
+            ( Id(), *this, *iContactLoader, iStoreList.Array(),
+              R_QTN_PHOB_NAVI_POS_INDICATOR_CONTACT_INFO_VIEW );
+        }
+    else
+        {
+        // Store was not in configuration --> contact to be shown is not
+        // included in the scroll view --> no point to use sideways
+        // navigation strategy
+        iNavigation = Pbk2NavigatorFactory::CreateVoidNavigatorL
+            ( Id(), *this, *iContactLoader, iStoreList.Array() );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::UpdateViewGraphL
+// Sets previous view node. Previous node should be set dynamically
+// because it could be some extension view.
+// Default is names list view.
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::UpdateViewGraphL
+        ( const TVwsViewId& aPrevViewId )
+    {
+    CPbk2ViewGraph& viewGraph = static_cast<CPbk2ViewExplorer*>
+        ( Pbk2AppUi()->Pbk2ViewExplorer() )->ViewGraph();
+    CPbk2ViewNode* prevNode =
+        viewGraph.FindNodeWithViewId( aPrevViewId.iViewUid );
+    if ( prevNode )
+        {
+        CPbk2ViewNode* thisNode = viewGraph.FindNodeWithViewId( Id() );
+        if ( thisNode )
+            {
+            thisNode->SetPreviousNode( prevNode );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactInfoAppView::SetEmptyTextL
+// Sets empty text for contact info list box from given resource id.
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactInfoAppView::SetEmptyTextL(
+		TInt aResourceId )
+	{
+    HBufC* emptyText = StringLoader::LoadLC( aResourceId );
+    iContainer->Control()->SetTextL( *emptyText );
+    CleanupStack::PopAndDestroy( emptyText );
+	}
+
+
+// End of File