mpx/viewframework/viewutility/src/mpxviewutilityimp.cpp
changeset 0 a2952bb97e68
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpx/viewframework/viewutility/src/mpxviewutilityimp.cpp	Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,1012 @@
+/*
+* Copyright (c) 2006 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:  Implementation of view utility
+*
+*/
+
+
+// INCLUDE FILES
+#include <eikenv.h>
+#include <eikapp.h>
+#include <eikappui.h>
+#include <centralrepository.h>
+#include <mpxprivatecrkeys.h>
+
+#include "mpxviewutilitycommanddef.h"
+#include "mpxviewhistory.h"
+#include "mpxviewutilityhelper.h"
+#include "mpxviewutilityimp.h"
+#include "mpxviewpluginhandler.h"
+#include "mpxlog.h"
+
+// CONSTANTS
+_LIT( KMPXDelimiter, ";" );
+const TInt KMPXMaxHistoryLength( 255 );
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CMPXViewUtilityImp::CMPXViewUtilityImp()
+    {
+    // Do nothing
+    }
+
+// ---------------------------------------------------------------------------
+// By default Symbian 2nd phase constructor is private.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::ConstructL()
+    {
+    iPluginManager = CMPXViewPluginHandler::NewL( this, *this );
+    iCurrentView = CMPXViewHistory::NewL();
+    ConstructDefaultViewHistoryL();
+    }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CMPXViewUtilityImp* CMPXViewUtilityImp::NewL()
+    {
+    CMPXViewUtilityImp* self = new ( ELeave ) CMPXViewUtilityImp();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMPXViewUtilityImp::~CMPXViewUtilityImp()
+    {
+    delete iPreviousView;
+    delete iCurrentView;
+    delete iDefaultView;
+    delete iPluginManager;
+    iDefaultHistoryPath.ResetAndDestroy();
+    iCurrentHistoryPath.ResetAndDestroy();
+
+    iObservers.Reset();
+    }
+
+// ---------------------------------------------------------------------------
+// Retrieves view utility from TLS. Creates if it's not there.
+// ---------------------------------------------------------------------------
+//
+MMPXViewUtility* CMPXViewUtilityImp::UtilityL()
+    {
+    MPX_FUNC( "CMPXViewUtilityImp::UtilityL" );
+    MMPXViewUtility* utility = reinterpret_cast<MMPXViewUtility*>( Dll::Tls() );
+    if ( !utility )
+        {
+        utility = CMPXViewUtilityImp::NewL();
+        StoreViewUtility( utility );
+        }
+
+    static_cast<CMPXViewUtilityImp*>( utility )->iRefCount++;
+    return utility;
+    }
+
+// ---------------------------------------------------------------------------
+// Store view utility to TLS.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::StoreViewUtility( MMPXViewUtility* aUtility )
+    {
+    Dll::SetTls( aUtility );
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// This method must be called when the client no longer needs this instance.
+// This object will be destroyed when no one is using it.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::Close()
+    {
+    ASSERT( iRefCount > 0 );
+    MPX_FUNC_EX( "CMPXViewUtilityImp::Close" );
+    MPX_DEBUG2( "CMPXViewUtilityImp::Close ref count = %d", iRefCount );
+    if ( --iRefCount == 0 )
+        {
+        MPX_DEBUG1( "CMPXViewUtilityImp::Close deleting this" );
+        // last client released
+        StoreViewUtility( NULL );
+        delete this;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Activate view by resolving passed uid.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::ActivateViewL(
+    const TUid& aUid,
+    const TDesC* aParam )
+    {
+    RArray<TUid> array;
+    CleanupClosePushL( array );
+    array.AppendL( aUid );
+    ActivateViewL( array, EFalse, EFalse, aParam );
+    CleanupStack::PopAndDestroy( &array );
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Activate view by resolving passed uids.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::ActivateViewL(
+    const RArray<TUid>& aUids,
+    const TDesC* aParam )
+    {
+    ActivateViewL( aUids, EFalse, EFalse, aParam );
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Activate view as default view, does not bring to foreground.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::SetAsDefaultViewL( const TUid& aUid )
+    {
+    RArray<TUid> array;
+    CleanupClosePushL( array );
+    array.AppendL( aUid );
+    SetAsDefaultViewL( array );
+    CleanupStack::PopAndDestroy( &array );
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Activate view by resolving passed uids.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::SetAsDefaultViewL( const RArray<TUid>& aUids )
+    {
+    TInt count = iCurrentHistoryPath.Count();
+    if ( count > 0 )
+        {
+        User::Leave( KErrAlreadyExists );
+        }
+    else
+        {
+        TUid pluginType( KNullUid );
+        TUid pluginImpUid( KNullUid );
+        CMPXViewPlugin* plugin(
+            iPluginManager->ResolvePluginL( aUids, pluginType, pluginImpUid ) );
+
+        MPX_DEBUG4( "CMPXViewUtilityImp::SetAsDefaultViewL adding type: 0x%x, impUid: 0x%x, address: 0x%x to current view history",
+            pluginType.iUid, pluginImpUid.iUid, plugin );
+        CMPXViewHistory* viewHistory = CMPXViewHistory::NewL( aUids, pluginType, pluginImpUid, plugin );
+        iCurrentHistoryPath.Append( viewHistory ); // iCurrentHistoryPath takes ownership
+        delete iCurrentView;
+        iCurrentView = NULL;
+        iCurrentView = CMPXViewHistory::NewL( viewHistory );
+        delete iDefaultView;
+        iDefaultView = NULL;
+        iDefaultView = CMPXViewHistory::NewL( viewHistory );
+
+        NotifyObservers( ActiveViewType(), PreviousViewType() );
+
+        MPX_DEBUG2( "CMPXViewUtilityImp::SetAsDefaultViewL activating 0x%x as default view", pluginType.iUid );
+        TRAPD( err, plugin->SetAsDefaultViewL() );
+        if ( err != KErrNone )
+            {
+            MPX_DEBUG2( "CMPXViewUtilityImp::SetAsDefaultViewL error duing SetAsDefaultViewL, leaving with code %d", err );
+            // error during activation, clean up view history
+            MarkViewAsClosedL( plugin );
+            User::Leave( err );
+            }
+        else if ( ActiveViewType() != pluginType )
+            {
+            // notify observers again if the view type has changed
+            // possibily because ActivateViewL of the plugin is sync
+            // and the plugin exited already
+            MPX_DEBUG1( "CMPXViewUtilityImp::SetAsDefaultViewL notifying observers again" );
+            NotifyObservers( ActiveViewType(), PreviousViewType() );
+            }
+        else
+            {
+            // nothing to do
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Activate previous view.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::ActivatePreviousViewL()
+    {
+    // if can't find default history in cenrep, don't use default history
+    if ( iCurrentHistoryPath.Count() > 1 )
+        {
+        TBool jump( EFalse );
+        // previousViewType contains a list of view types that needs to be checked
+        TUid previousViewType = KNullUid;
+        if ( iDefaultHistoryPath.Count() > 0 )
+            {
+            // default path exist, check that
+            TUid currentViewType(
+                iCurrentHistoryPath[ iCurrentHistoryPath.Count() - 1 ]->iPluginType );
+            TInt count( iDefaultHistoryPath.Count() );
+
+            // loop starts at one, since there's no previous view in index 0
+            for ( TInt i = 1; i < count && previousViewType == KNullUid; i++ )
+                {
+                if ( iDefaultHistoryPath[ i ]->iPluginType == currentViewType )
+                    {
+                    previousViewType = iDefaultHistoryPath[ i - 1 ]->iPluginType;
+                    }
+                }
+
+            if ( previousViewType != KNullUid )
+                {
+                jump = ETrue;
+                // if previousViewType exist in iCurrentHistoryPath, it's not a jump
+                count = iCurrentHistoryPath.Count();
+                for ( TInt i = 0; ( ( i < count ) && ( jump ) ); i++ )
+                    {
+                    if ( iCurrentHistoryPath[ i ]->iPluginType == previousViewType )
+                        {
+                        jump = EFalse;
+                        }
+                    }
+                MPX_DEBUG2( "CMPXViewUtilityImp::ActivatePreviousViewL activating jump = %d", jump );
+                }
+#ifdef _DEBUG
+            else
+                {
+                // current UID doesn't exist in default path, just follow the current path
+                MPX_DEBUG1( "CMPXViewUtilityImp::ActivatePreviousViewL activating current UID doesn't exist in default path" );
+                }
+#endif // _DEBUG
+            }
+#ifdef _DEBUG
+        else
+            {
+            // default path doesn't exist, just use current history path
+            MPX_DEBUG1( "CMPXViewUtilityImp::ActivatePreviousViewL activating without default history" );
+            }
+#endif // _DEBUG
+        RArray<TUid> array;
+        CleanupClosePushL( array );
+        TInt lastIndex( iCurrentHistoryPath.Count() - 1 );
+        TBool updatePreviousView( EFalse );
+        TBool activatingPreviousView( EFalse );
+        UpdatePreviousViewInfoL( lastIndex );
+        if ( jump )
+            {
+            if ( previousViewType != KNullUid )
+                {
+                MPX_DEBUG2( "CMPXViewUtilityImp::ActivatePreviousViewL activating 0x%x jumped", previousViewType.iUid );
+                updatePreviousView = ETrue;
+                array.AppendL( previousViewType );
+                }
+            }
+        else
+            {
+            TInt count = iCurrentHistoryPath[ lastIndex - 1 ]->iUids.Count();
+            MPX_DEBUG2( "CMPXViewUtilityImp::ActivatePreviousViewL activating not jumped iUid.Count %d", count );
+            for ( TInt i = 0; i < count; i++ )
+                {
+                TUid u = iCurrentHistoryPath[ lastIndex - 1 ]->iUids[ i ];
+                MPX_DEBUG2( "CMPXViewUtilityImp::ActivatePreviousViewL activating not jumped, appending 0x%x", u.iUid );
+                array.AppendL( u );
+                }
+            activatingPreviousView = ETrue;
+            }
+        // last index is current view, previous view is at last index - 1
+        delete iCurrentHistoryPath[ lastIndex ];
+        iCurrentHistoryPath.Remove( lastIndex );
+        iCurrentHistoryPath.Compress();
+        ActivateViewL( array, activatingPreviousView, updatePreviousView );
+        CleanupStack::PopAndDestroy( &array );
+        }
+    else
+        {
+        // no history
+        User::Leave( KErrNotFound );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Pre-load view plug-ins that have KMPXVpFeaturePreLoaded flag set.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::PreLoadViewsL()
+    {
+    MPX_FUNC( "CMPXViewUtilityImp::PreLoadViewsL" );
+	PreLoadViewsL( KNullUid );
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Pre-load view plug-ins that have KMPXVpFeaturePreLoaded flag set and also by resolving UID
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::PreLoadViewsL( const TUid& aUid )
+    {
+    MPX_DEBUG2( "CMPXViewUtilityImp::PreLoadViewsL aUid: 0x%x", aUid );
+    RArray<TUid> array;
+    CleanupClosePushL( array );
+
+    // Get list of plug-ins that need to be pre-loaded
+   	iPluginManager->GetPreLoadPluginsL( array, aUid );
+
+    for ( TInt i = array.Count(); --i >= 0; )
+        {
+        MPX_DEBUG2( "CMPXViewUtilityImp::PreLoadViewsL loading UID: 0x%x", array[i] );
+        CMPXViewPlugin* plugin = iPluginManager->PluginL( array[i] );
+        plugin->CreateViewL();
+        }
+
+    CleanupStack::PopAndDestroy( &array );
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Pre-load view plug-in by resolving passed uid.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::PreLoadViewL( const TUid& aUid )
+    {
+    TUid pluginType( KNullUid );
+    TUid pluginImpUid( KNullUid );
+    CMPXViewPlugin* plugin(
+        iPluginManager->ResolvePluginL( aUid, pluginType, pluginImpUid ) );
+    plugin->CreateViewL();
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Get a reference to view plugin manager.
+// ---------------------------------------------------------------------------
+//
+MMPXViewPluginManager& CMPXViewUtilityImp::ViewPluginManager()
+    {
+    return *iPluginManager;
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXViewUtility
+// Constructs default view history
+// ---------------------------------------------------------------------------
+//
+TUid CMPXViewUtilityImp::ConstructDefaultViewHistoryL()
+    {
+    iDefaultHistoryPath.ResetAndDestroy();
+    delete iDefaultView;
+    iDefaultView = NULL;
+
+    CRepository* cenRepository = CRepository::NewLC( KCRUidMPXSettings );
+    TBool isEmbedded = CEikonEnv::Static()->StartedAsServerApp();
+    MPX_DEBUG2( "CMPXViewUtilityImp::ConstructDefaultViewHistoryL isEmbedded: %d", isEmbedded );
+
+    // check if embeded mode, if embeded mode use host application uid
+    // CAiwGenericParamList
+    // if not embeded mode, use app uid
+
+    // get default paths
+    TUid settingsUid( KNullUid );
+    if ( isEmbedded )
+        {
+        // TO-DO: get host UID
+        }
+    else
+        {
+        CEikAppUi* appUi = CEikonEnv::Static()->EikAppUi();
+        if ( appUi )
+            {
+            CEikApplication* app = appUi->Application();
+            if ( app )
+                {
+                settingsUid = app->AppDllUid();
+                }
+            }
+        }
+    TInt ret ( KErrGeneral );
+    HBufC* defaultPath = HBufC::NewLC( KMPXMaxHistoryLength );
+    MPX_DEBUG2( "CMPXViewUtilityImp::ConstructDefaultViewHistoryL trying to read default history from uid 0x%x", settingsUid.iUid );
+    TPtr dPathPtr = defaultPath->Des();
+    ret = cenRepository->Get( settingsUid.iUid, dPathPtr );
+    if ( ret == KErrNone )
+        {
+        TPtrC defaultPathPtr( *defaultPath );
+        TInt nextLoc = defaultPathPtr.Find( KMPXDelimiter );
+        TBool defaultSet( EFalse );
+        while ( nextLoc != KErrNotFound )
+            {
+            TPtrC currentPath = defaultPathPtr.Left( nextLoc );
+            AddToDefaultViewHistoryL( currentPath );
+            if ( !defaultSet && iDefaultHistoryPath.Count() == 1 )
+                {
+                // first entry is the default view
+                iDefaultView = CMPXViewHistory::NewL( iDefaultHistoryPath[0] );
+                defaultSet = ETrue;
+                }
+            defaultPathPtr.Set( defaultPathPtr.Mid( nextLoc + 1 ) );
+            nextLoc = defaultPathPtr.Find( KMPXDelimiter );
+            }
+        if ( defaultPathPtr.Length() > 0 )
+            {
+            AddToDefaultViewHistoryL( defaultPathPtr );
+            }
+        }
+    else
+        {
+        // get default view
+        HBufC* defaultView = HBufC::NewLC( KMPXMaxHistoryLength );
+        TPtr dViewPtr = defaultView->Des();
+        ret = cenRepository->Get( KMPXVUCurrentDefaultView, dViewPtr );
+        if ( ret == KErrNone )
+            {
+            TPtrC defaultViewPtr( *defaultView );
+            if ( defaultViewPtr.Length() > 0 )
+                {
+                TInt nextPos( 0 );
+                TInt err(
+                    CMPXViewUtilityHelper::ExtractNum( defaultViewPtr, nextPos, ret ) );
+                if ( err == KErrNone )
+                    {
+                    iDefaultView = CMPXViewHistory::NewL();
+                    iDefaultView->iPluginType = TUid::Uid( ret );
+                    if ( iDefaultHistoryPath.Count() > 0 )
+                        {
+                        TRAP( ret, AddToDefaultViewHistoryL( defaultViewPtr, 0 ) );
+                        }
+                    }
+
+                if ( iDefaultHistoryPath.Count() == 0 && err != KErrNone )
+                    {
+                    ret = err;
+                    }
+                }
+            }
+        CleanupStack::PopAndDestroy( defaultView );
+        }
+    CleanupStack::PopAndDestroy( defaultPath );
+
+    // clean up duplicate entries
+    TInt count( iDefaultHistoryPath.Count() );
+    TUid previousUid( KNullUid );
+    for ( TInt i = count - 1; i >= 0; i-- )
+        {
+        if ( iDefaultHistoryPath[ i ]->iPluginType == previousUid )
+            {
+            MPX_DEBUG3( "CMPXViewUtilityImp::ConstructDefaultViewHistoryL removing duplicate entry 0x%x at %d", iDefaultHistoryPath[ i ]->iPluginType.iUid, i );
+            // duplicate entry, remove
+            delete iDefaultHistoryPath[ i ];
+            iDefaultHistoryPath.Remove( i );
+            }
+        else
+            {
+            previousUid = iDefaultHistoryPath[ i ]->iPluginType;
+            }
+        }
+    iDefaultHistoryPath.Compress();
+    MPX_DEBUG2( "CMPXViewUtilityImp::ConstructDefaultViewHistoryL after clean up, default path contains %d elements", iDefaultHistoryPath.Count() );
+
+    CleanupStack::PopAndDestroy( cenRepository );
+    return DefaultViewUid();
+    }
+
+// ---------------------------------------------------------------------------
+// Push default history to view history
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::PushDefaultHistoryL()
+    {
+    MPX_FUNC( "CMPXViewUtilityImp::PushDefaultHistoryL" );
+    TInt count( iDefaultHistoryPath.Count() );
+    iCurrentHistoryPath.ResetAndDestroy();
+    delete iPreviousView;
+    iPreviousView = NULL;
+    if ( count > 0 )
+        {
+        for ( TInt i = 0; i < count; i++ )
+            {
+            CMPXViewHistory* viewHistory = CMPXViewHistory::NewL();
+            CleanupStack::PushL( viewHistory );
+            TUid pluginType( iDefaultHistoryPath[ i ]->iPluginType );
+            viewHistory->iPluginType = pluginType;
+            viewHistory->iUids.Append( pluginType );
+            viewHistory->iPlugin = NULL;
+            iCurrentHistoryPath.Append( viewHistory );
+            CleanupStack::Pop( viewHistory );
+            }
+        }
+#ifdef _DEBUG
+    else
+        {
+        MPX_DEBUG1( "CMPXViewUtilityImp::PushDefaultHistoryL default history is not defined, FAILED" );
+        }
+#endif
+    }
+
+// ---------------------------------------------------------------------------
+// Gets default view's UID
+// ---------------------------------------------------------------------------
+//
+TUid CMPXViewUtilityImp::DefaultViewUid()
+    {
+#ifdef _DEBUG
+    if ( iDefaultView )
+        {
+        MPX_DEBUG2( "CMPXViewUtilityImp::DefaultViewUid = 0x%x", iDefaultView->iPluginType.iUid );
+        }
+#endif // _DEBUG
+    return iDefaultView ? iDefaultView->iPluginType : KNullUid;
+    }
+
+// ---------------------------------------------------------------------------
+// Returns the current history depth
+// ---------------------------------------------------------------------------
+//
+TInt CMPXViewUtilityImp::ViewHistoryDepth()
+    {
+#ifdef _DEBUG
+    TInt count( iCurrentHistoryPath.Count() );
+    for ( TInt i = 0; i < count; i++ )
+        {
+        TUid currentPluginType = iCurrentHistoryPath[ i ]->iPluginType;
+        CMPXViewPlugin* plugin = iCurrentHistoryPath[ i ]->iPlugin;
+        MPX_DEBUG4( "CMPXViewUtilityImp::ViewHistoryDepth (%d) type = 0x%x, address = 0x%x", i, currentPluginType.iUid, plugin );
+        }
+#endif
+    return iCurrentHistoryPath.Count();
+    }
+
+// ---------------------------------------------------------------------------
+// Returns the last activated view type
+// ---------------------------------------------------------------------------
+//
+TUid CMPXViewUtilityImp::PreviousViewType()
+    {
+#ifdef _DEBUG
+    if ( iPreviousView )
+        {
+        MPX_DEBUG2( "CMPXViewUtilityImp::PreviousViewType = 0x%x", iPreviousView->iPluginType.iUid );
+        }
+#endif // _DEBUG
+    return iPreviousView ? iPreviousView->iPluginType : KNullUid;
+    }
+
+// ---------------------------------------------------------------------------
+// Returns the current activated view type
+// ---------------------------------------------------------------------------
+//
+TUid CMPXViewUtilityImp::ActiveViewType()
+    {
+#ifdef _DEBUG
+    if ( iCurrentView )
+        {
+        MPX_DEBUG2( "CMPXViewUtilityImp::ActiveViewType = 0x%x", iCurrentView->iPluginType.iUid );
+        }
+#endif // _DEBUG
+    return iCurrentView ? iCurrentView->iPluginType : KNullUid;
+    }
+
+// ---------------------------------------------------------------------------
+// Returns the current activated view type
+// ---------------------------------------------------------------------------
+//
+TUid CMPXViewUtilityImp::ActiveViewImplementationUid()
+    {
+#ifdef _DEBUG
+    MPX_DEBUG1( "-->CMPXViewUtilityImp::ActiveViewImplementationUid" );
+    if( iCurrentView &&
+        ( iCurrentView->iPluginImplementationUid != KNullUid ) )
+        {
+        MPX_DEBUG2( "CMPXViewUtilityImp::ActiveViewImplementationUid = 0x%x",
+            iCurrentView->iPluginImplementationUid.iUid );
+        }
+    else
+        {
+        MPX_DEBUG1( "CMPXViewUtilityImp::ActiveViewImplementationUid - active view implementation uid not resolved yet" );
+        }
+    MPX_DEBUG1( "<--CMPXViewUtilityImp::ActiveViewImplementationUid" );
+#endif // _DEBUG
+    return iCurrentView ? iCurrentView->iPluginImplementationUid : KNullUid;
+    }
+
+// ---------------------------------------------------------------------------
+// Add observer.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::AddObserverL(
+    MMPXViewActivationObserver* aObserver )
+    {
+    if ( aObserver )
+        {
+        iObservers.AppendL( aObserver );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Remove observer.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::RemoveObserver(
+    MMPXViewActivationObserver* aObserver )
+    {
+    TInt index = iObservers.Find( aObserver );
+    ASSERT( index >= 0 );
+    if ( index >= 0 )
+        {
+        iObservers.Remove( index );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Handle custom commands.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::HandleCustomCommand(
+    const TUid& aUid,
+    const TInt aCommand,
+    const TDesC8& aData )
+    {
+    MPX_FUNC( "CMPXViewUtilityImp::HandleCustomCommand" );
+    if ( aUid.iUid == KMPXViewUtilityCustomCommand )
+        {
+        switch ( aCommand )
+            {
+            case EMPXViewUtilCmdViewActivated:
+                {
+                // TO-DO
+                break;
+                }
+            case EMPXViewUtilCmdViewDeActivated:
+                {
+                MPX_DEBUG1( "CMPXViewUtilityImp::HandleCustomCommand EMPXViewUtilCmdViewDeActivated" );
+                // aData contains the pointer to the view
+                if ( aData.Length() > 0 )
+                    {
+                    TPckgBuf<TInt> buf( KErrNotFound );
+                    buf.Copy( aData );
+                    TInt viewPtr = buf();
+                    MPX_DEBUG2( "CMPXViewUtilityImp::HandleCustomCommand EMPXViewUtilCmdViewDeActivated address = 0x%x", viewPtr );
+                    CMPXViewPlugin* piPtr = reinterpret_cast<CMPXViewPlugin*>( viewPtr );
+                    TRAP_IGNORE( MarkViewAsClosedL( piPtr ) );
+                    }
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMPXViewUtilityImp::HandlePluginHandlerEvent
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::HandlePluginHandlerEvent(
+    TPluginHandlerEvents aEvent,
+    const TUid& aPluginUid,
+    TInt aLoaded,
+    TInt aData)
+    {
+    MPX_FUNC("CMPXViewUtilityImp::HandlePluginHandlerEvent");
+
+    switch (aEvent)
+        {
+        case EPluginAdd:
+            {
+            NotifyViewUpdate(aPluginUid, MMPXViewActivationObserver::EViewPluginAdd,
+                aLoaded, aData);
+            break;
+            }
+        case EPluginUpdateStart:
+            {
+            NotifyViewUpdate(aPluginUid, MMPXViewActivationObserver::EViewPluginUpdate,
+                aLoaded, aData);
+            break;
+            }
+        case EPluginRemove:
+            {
+            NotifyViewUpdate(aPluginUid, MMPXViewActivationObserver::EViewPluginRemove,
+                aLoaded, aData);
+            break;
+            }
+        case EPluginUpdateEnd:
+            {
+            // do nothing
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Activate view by resolving passed uids.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::ActivateViewL(
+    const RArray<TUid>& aUids,
+    TBool aIsActivatingPreviousView,
+    TBool aUpdatedPreviousView,
+    const TDesC* aParam )
+    {
+    TUid pluginType( KNullUid );
+    TUid pluginImpUid( KNullUid );
+    CMPXViewPlugin* plugin(
+        iPluginManager->ResolvePluginL( aUids, pluginType, pluginImpUid ) );
+    CMPXViewPlugin* currentPlugin( NULL );
+
+    // if the resolved view is already activated
+    TInt count = iCurrentHistoryPath.Count();
+    TUid currentPluginType( KNullUid );
+    if ( count > 0 )
+        {
+        currentPluginType = iCurrentHistoryPath[ count - 1 ]->iPluginType;
+        currentPlugin = iCurrentHistoryPath[ count - 1 ]->iPlugin;
+        }
+
+    if ( ( currentPluginType != pluginType ) || ( currentPlugin != plugin ) ||
+        ( aIsActivatingPreviousView ) )
+        {
+        if ( ( pluginType != KNullUid ) && ( !aIsActivatingPreviousView ) )
+            {
+            if ( !aUpdatedPreviousView )
+                {
+                if ( count > 0 )
+                    {
+                    UpdatePreviousViewInfoL( KErrNotFound );
+                    }
+                }
+
+            // check if the view has been activated before
+            TInt index( FindCurrentHistoryEntryByTypeL( pluginType ) );
+            if ( index != KErrNotFound )
+                {
+                // cleanup, count down
+                for ( TInt i = count - 1; i > index; i-- )
+                    {
+                    MPX_DEBUG2( "CMPXViewUtilityImp::ActivateViewL removing entry %d", i );
+                    delete iCurrentHistoryPath[ i ];
+                    iCurrentHistoryPath.Remove( i );
+                    }
+                iCurrentHistoryPath.Compress();
+
+                // update the uids used to activate this view
+                CMPXViewHistory* vh( iCurrentHistoryPath[ index ] );
+                vh->iPlugin = plugin;
+                vh->iUids.Reset();
+                TInt uidCount( aUids.Count() );
+                for ( TInt i = 0; i < uidCount; i++ )
+                    {
+                    TUid u = aUids[ i ];
+                    vh->iUids.Append( u );
+                    }
+                }
+            else
+                {
+                MPX_DEBUG3( "CMPXViewUtilityImp::ActivateViewL adding type: 0x%x, address: 0x%x to current view history", pluginType.iUid, plugin );
+                CMPXViewHistory* viewHistory = CMPXViewHistory::NewL();
+                CleanupStack::PushL( viewHistory );
+                TInt uidCount( aUids.Count() );
+                for ( TInt i = 0; i < uidCount; i++ )
+                    {
+                    TUid u = aUids[ i ];
+                    viewHistory->iUids.Append( u );
+                    }
+                viewHistory->iPlugin = plugin;
+                viewHistory->iPluginType = pluginType;
+                viewHistory->iPluginImplementationUid = pluginImpUid;
+                iCurrentHistoryPath.Append( viewHistory );
+                CleanupStack::Pop( viewHistory );
+                }
+            }
+        MPX_DEBUG2( "CMPXViewUtilityImp::ActivateViewL activating 0x%x", pluginType.iUid );
+
+        if ( plugin != iCurrentView->iPlugin )
+            {
+            delete iCurrentView;
+            iCurrentView = NULL;
+            iCurrentView = CMPXViewHistory::NewL( aUids, pluginType, pluginImpUid, plugin );
+            // Notify observers for view activation, ActivateViewL maybe sync
+            // and won't return until the view is closed
+            NotifyObservers( ActiveViewType(), PreviousViewType() );
+            TRAPD( err, plugin->ActivateViewL( aParam ) );
+            if ( err != KErrNone )
+                {
+                MPX_DEBUG2( "CMPXViewUtilityImp::ActivateViewL error duing ActivateViewL, leaving with code %d", err );
+                // error during view activation, clean up view history
+                MarkViewAsClosedL( plugin );
+                User::Leave( err );
+                }
+            }
+        else
+            {
+            MPX_DEBUG2( "CMPXViewUtilityImp::ActivateViewL view 0x%x already activated, ignoring", pluginType.iUid );
+            }
+        }
+    else
+        {
+        MPX_DEBUG2( "CMPXViewUtilityImp::ActivateViewL view 0x%x already activated, ignoring", pluginType.iUid );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Marks the view closed.  This does not actually close the view.
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::MarkViewAsClosedL( CMPXViewPlugin* aPlugin )
+    {
+    MPX_DEBUG2( "CMPXViewUtilityImp::MarkViewAsClosedL called 0x%x", aPlugin );
+    TInt count = iCurrentHistoryPath.Count();
+    TBool removed( EFalse );
+    // Count down, counting up and removing items is bad
+    for ( TInt i = count - 1; i >= 0 && !removed ; i-- )
+        {
+        if ( iCurrentHistoryPath[ i ]->iPlugin == aPlugin )
+            {
+            MPX_DEBUG2( "CMPXViewUtilityImp::MarkViewAsClosedL removing location %d", i );
+            UpdatePreviousViewInfoL( i );
+
+            delete iCurrentView;
+            iCurrentView = NULL;
+            if ( i > 0 )
+                {
+                iCurrentView = CMPXViewHistory::NewL(
+                    iCurrentHistoryPath[ ( i != count - 1 ) ? count - 1 : i - 1 ] );
+                }
+
+            // match found, remove it from history
+            delete iCurrentHistoryPath[ i ];
+            iCurrentHistoryPath.Remove( i );
+            removed = ETrue;
+
+            // Notify observers for view activation, ActivateViewL maybe sync
+            // and won't return until the view is closed
+            NotifyObservers( ActiveViewType(), PreviousViewType() );
+            }
+        }
+    if ( removed )
+        {
+        iCurrentHistoryPath.Compress();
+        }
+#ifdef _DEBUG
+    else
+        {
+        MPX_DEBUG1( "CMPXViewUtilityImp::MarkViewAsClosedL Nothing removed" );
+        }
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// Notify observers for view activation
+// -----------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::NotifyObservers(
+    const TUid& aCurrentViewType,
+    const TUid& aPreviousViewType )
+    {
+    MPX_FUNC( "CMPXViewUtilityImp::NotifyObservers" );
+    MPX_DEBUG3( "CMPXViewUtilityImp::NotifyObservers current: 0x%x, previous: 0x%x", aCurrentViewType.iUid, aPreviousViewType.iUid );
+    TInt count( iObservers.Count() );
+    for ( TInt i = 0; i < count; i++ )
+        {
+        iObservers[i]->HandleViewActivation(
+            aCurrentViewType,
+            aPreviousViewType );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Notify observers of a view update event
+// -----------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::NotifyViewUpdate(
+    const TUid& aViewUid,
+    MMPXViewActivationObserver::TViewUpdateEvent aUpdateEvent,
+    TBool aLoaded,
+    TInt aVersion /* = 0 */)
+    {
+    MPX_FUNC( "CMPXViewUtilityImp::NotifyViewUpdate" );
+
+    TInt count(iObservers.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        iObservers[i]->HandleViewUpdate(aViewUid, aUpdateEvent, aLoaded, aVersion);
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Insert/Append to default view history array
+// ---------------------------------------------------------------------------
+//
+TInt CMPXViewUtilityImp::AddToDefaultViewHistoryL(
+    const TDesC& aData, TInt aLoc )
+    {
+    TInt result( KErrGeneral );
+    TInt nextPos( 0 );
+    User::LeaveIfError( CMPXViewUtilityHelper::ExtractNum( aData, nextPos, result ) );
+    CMPXViewHistory* viewHistory = CMPXViewHistory::NewL();
+    CleanupStack::PushL( viewHistory );
+    viewHistory->iPluginType.iUid = result;
+    if ( aLoc == -1 )
+        {
+        MPX_DEBUG2( "CMPXViewUtilityImp::AddToDefaultViewHistoryL Appending 0x%x to default view history", result );
+        User::LeaveIfError( iDefaultHistoryPath.Append( viewHistory ) );
+        }
+    else
+        {
+        MPX_DEBUG3( "CMPXViewUtilityImp::AddToDefaultViewHistoryL Inserting 0x%x to default view history at %d", result, aLoc );
+        User::LeaveIfError( iDefaultHistoryPath.Insert( viewHistory, aLoc ) );
+        }
+    CleanupStack::Pop( viewHistory );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Updates previous view info
+// ---------------------------------------------------------------------------
+//
+void CMPXViewUtilityImp::UpdatePreviousViewInfoL( TInt aIndex )
+    {
+    MPX_FUNC( "CMPXViewUtilityImp::UpdatePreviousViewInfoL" );
+    delete iPreviousView;
+    iPreviousView = NULL;
+    if ( aIndex != KErrNotFound )
+        {
+        TInt currentHistoryCount = iCurrentHistoryPath.Count();
+        if ( ( currentHistoryCount > aIndex ) && ( aIndex >= 0 ) )
+            {
+            iPreviousView = CMPXViewHistory::NewL( iCurrentHistoryPath[ aIndex ] );
+            iPreviousView->iPlugin = NULL;
+            MPX_DEBUG2( "CMPXViewUtilityImp::UpdatePreviousViewInfoL previous view type 0x%x", iPreviousView->iPluginType.iUid );
+            }
+        }
+    else
+        {
+        delete iPreviousView;
+        iPreviousView = NULL;
+        iPreviousView = CMPXViewHistory::NewL( iCurrentView );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Find if the view exist in current history
+// ---------------------------------------------------------------------------
+//
+TInt CMPXViewUtilityImp::FindCurrentHistoryEntryByTypeL( const TUid aType )
+    {
+    TInt count = iCurrentHistoryPath.Count();
+    TInt index = KErrNotFound;
+    for ( TInt i = 0; i < count && index == KErrNotFound; i++ )
+        {
+        if ( iCurrentHistoryPath[ i ]->iPluginType == aType )
+            {
+            index = i;
+            }
+        }
+    return index;
+    }
+
+//  End of File