widgetmodel/alfwidgetmodel/src/alfelement.cpp
branchRCL_3
changeset 26 0e9bb658ef58
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgetmodel/alfwidgetmodel/src/alfelement.cpp	Wed Sep 01 12:23:18 2010 +0100
@@ -0,0 +1,636 @@
+/*
+* Copyright (c) 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:  The basic implementation for presentation elements.
+*
+*/
+
+
+#include "alf/alfelement.h"
+#include <alf/alfwidgetcontrol.h>
+#include <alf/alfvarianttype.h>
+#include "alf/ialfvisualtemplate.h"
+#include "alf/alfreferencetovisual.h"
+//#include "alf/alfperf.h"
+#include <alf/alfexceptions.h>
+
+#include "alfelementattributeownerimpl.h"
+
+namespace Alf
+    {
+
+class  AlfVisualData
+    {
+public:
+    AlfVisualData( CAlfVisual* aVisualTree, uint aDataID ) :
+            mVisualTree( aVisualTree ), mDataID( aDataID )
+        {
+        }
+    CAlfVisual *mVisualTree;
+    uint mDataID;
+    ~AlfVisualData()
+        {
+
+        }
+
+    };
+
+class AlfElementImpl
+    {
+public:
+    AlfElementImpl()
+        {
+        mControl = 0;
+        mVisualTemplate = 0;
+        mParentElement = 0;
+ 	    mParentLayout = 0;
+        }
+    ~AlfElementImpl()
+        {
+        if (mVisualTemplate)
+            {
+            delete mVisualTemplate;
+            mVisualTemplate = 0;
+            }
+        if (mParentLayout)
+            {
+            delete mParentLayout;
+            mParentLayout = 0;
+            }
+
+        mVisualTreeArray.clear();
+        }
+    /**
+     * The control. Not own.
+     */
+    CAlfWidgetControl* mControl;
+
+    /**
+     * The element name.
+     */
+    UString mName;
+
+    /**
+     * The visual template for creating visual trees. Own.
+     */
+    IAlfVisualTemplate* mVisualTemplate;
+
+    /*
+     * Parent element. NULL for root elements. Not own.
+     */
+    IAlfElement *mParentElement;
+
+    /*
+     * Array of created visual trees with the associated data IDs.
+     */
+    AlfPtrVector<AlfVisualData>mVisualTreeArray; //RArray<TAlfVisualData> mVisualTreeArray;
+
+    /*
+     * Reference to the default parent layout. Own.
+     */
+    AlfReferenceToVisual *mParentLayout;
+    
+    /*
+     * IAlfAttributeOwner implementation. Own.
+     */
+    auto_ptr<AlfElementAttributeOwnerImpl> mAttributeOwnerImpl;
+    };
+
+// ======== MEMBER FUNCTIONS ========
+
+OSN_EXPORT AlfElement::AlfElement()
+    {
+    }
+
+OSN_EXPORT void AlfElement::construct( CAlfWidgetControl& aControl, const char* aName )
+    {
+    mData.reset(new (EMM) AlfElementImpl());
+
+    mData->mControl = &aControl;
+    mData->mName = UString(aName);
+    mData->mParentLayout=NULL;
+    mData->mParentElement=NULL;
+    mData->mVisualTemplate=NULL;
+    mData->mVisualTreeArray.setAutoDelete(true);
+    mData->mAttributeOwnerImpl.reset(new (EMM) AlfElementAttributeOwnerImpl(*this, 
+        *mData->mControl));
+    aControl.addElement(this);
+    }
+
+
+OSN_EXPORT AlfElement::AlfElement(CAlfWidgetControl& aControl, const char* aName)
+    {
+    construct( aControl, aName );
+
+    }
+
+OSN_EXPORT AlfElement::~AlfElement()
+    {
+    }
+
+OSN_EXPORT const char* AlfElement::name() const
+    {
+    return mData->mName.getUtf8();
+    }
+
+OSN_EXPORT void AlfElement::createChildVisualTree(
+    IAlfElement* aElement, IAlfVariantType& aChildData,
+    IAlfBranch& aData, int aIndex, uint aDataID )
+    {
+    // Pass directly to the child element CreateVisualTree, no need
+    // to do anything else. Derived classes may need additional steps here.
+//    ALF_PERF_START( perfdata, "AlfElement-createVisualTree-createChildVisualTree")
+    aElement->createVisualTree( aChildData, aData, aIndex, aDataID,
+                                aElement->defaultParentLayout( aDataID ),
+                                aIndex );
+//    ALF_PERF_STOP( perfdata, "AlfElement-createVisualTree-createChildVisualTree")
+    }
+
+OSN_EXPORT CAlfVisual* AlfElement::createVisualTree(
+    IAlfVariantType& aData, IAlfBranch& aParentData, int aIndex,
+    uint aParentDataID, CAlfLayout* aParentLayout, int aLayoutIndex )
+    {
+    if ( aIndex >= 0 && aIndex <= aParentData.childrenCount() )
+        {
+        // Update data IDs of all visual trees after the new visual tree
+        // Start from the aIndex, and increase all indices by one
+        updateDataIDs( aParentData, aIndex, 1, aParentDataID, aParentDataID );
+
+        // Create the new visual tree
+        uint dataID = control().elementDataId( *this, aIndex, aParentDataID );
+        return createVisualTree( aData, dataID, aParentLayout, aLayoutIndex );
+        }
+    ALF_THROW(AlfElementException,EInvalidElement,"AlfElement")
+    }
+
+OSN_EXPORT CAlfVisual* AlfElement::createVisualTree(
+    IAlfVariantType& aData, uint aDataID, CAlfLayout* aParentLayout, int aLayoutIndex )
+    {
+    CAlfVisual *retVisual = NULL;
+    IAlfMap* currentData = NULL;
+    IAlfBranch* branch = NULL;
+    if ( aData.type()== IAlfVariantType::EMap )
+        {
+        currentData = aData.map();
+        }
+    else if (aData.type()== IAlfVariantType::EBranch)
+        {
+        branch = aData.branch();
+        currentData = aData.branch()->data();
+        }
+
+    if ( currentData && mData->mVisualTemplate )
+        {
+        //Find the visual tree with data id
+        int index = findFromArray( aDataID );
+        if ( index < 0 )
+            {
+            // Create a new visual tree
+            try
+                {
+                retVisual = mData->mVisualTemplate->createVisualTree(*mData->mControl,
+                            currentData, aParentLayout, aLayoutIndex);
+                }
+            catch (...)
+                {
+                ALF_THROW(AlfVisualException,ECanNotCreateVisual,"AlfElement")
+                }
+            // Append the visual into the array
+            mData->mVisualTreeArray.resize(mData->mVisualTreeArray.count()+1);
+            mData->mVisualTreeArray.insert(mData->mVisualTreeArray.count(),(new (EMM) AlfVisualData(retVisual, aDataID)));
+            }
+        else
+            {
+            ALF_THROW(AlfVisualException,EInvalidElement,"AlfElement")
+            }
+        }
+
+    if ( branch )
+        {
+        // Pass to children
+        int count = branch->childrenCount();
+        for ( int i = 0; i < count; ++i )
+            {
+            IAlfElement* element = mData->mControl->findElement(
+                                       branch->childName( i ).getUtf8() );
+            if ( element )
+                {
+                createChildVisualTree(
+                    element, *branch->childData( i ), *branch, i, aDataID );
+                }
+            }
+        }
+
+    return retVisual;
+    }
+
+OSN_EXPORT void AlfElement::removeChildVisualTree(
+    IAlfElement* aElement, IAlfBranch& aData, int aIndex, uint aDataID )
+    {
+    // Pass directly to the child element RemoveVisualTree, no need
+    // to do anything else. Derived classes may need additional steps here.
+    aElement->removeVisualTree( aData, aIndex, aDataID );
+    }
+
+OSN_EXPORT void AlfElement::removeVisualTree( IAlfBranch& aParentData,
+        int aIndex, uint aParentDataID )
+    {
+    if ( aIndex < aParentData.childrenCount() )
+        {
+        IAlfVariantType* data = aParentData.childData( aIndex );
+        uint dataID = control().elementDataId( *this, aIndex, aParentDataID );
+
+        removeVisualTree( *data, dataID );
+
+        // Update data IDs of all visual trees after the removed visual tree
+        // Start from the aIndex + 1, and decrease all indices by one
+        updateDataIDs( aParentData, aIndex + 1, -1, aParentDataID, aParentDataID );
+        }
+    else
+        ALF_THROW(AlfVisualException,EInvalidElement,"AlfElement")
+        }
+
+OSN_EXPORT void AlfElement::removeVisualTree( IAlfVariantType& aData, uint aDataID )
+    {
+    if ( aData.type() == IAlfVariantType::EBranch )
+        {
+        // Pass to children
+        IAlfBranch* branch = aData.branch();
+        int count = branch->childrenCount();
+        for ( int i = 0; i < count; ++i )
+            {
+            IAlfElement* element = mData->mControl->findElement( branch->childName( i ).getUtf8() );
+            if ( element )
+                {
+                removeChildVisualTree( element, *branch, i, aDataID );
+                }
+            }
+        }
+
+    // Remove visual tree from this element
+    int index = findFromArray( aDataID );
+    if (index >= 0)
+        {
+        CAlfVisual* visual = mData->mVisualTreeArray[index]->mVisualTree;
+        visual->RemoveAndDestroyAllD();
+        mData->mVisualTreeArray.remove( index );
+        }
+    else
+        {
+        ALF_THROW(AlfVisualException,EInvalidElement,"AlfElement")
+        }
+    }
+
+OSN_EXPORT void AlfElement::updateVisualTree(
+    IAlfVariantType& aNewData, IAlfVariantType& aOldData, uint aDataID )
+    {
+    IAlfMap* currentNewData = NULL;
+    IAlfMap* currentOldData = NULL;
+    IAlfBranch* branch = NULL;
+    IAlfBranch* oldBranch = NULL;
+
+    if ( aNewData.type()== IAlfVariantType::EMap )
+        {
+        currentNewData = aNewData.map();
+        }
+    else if (aNewData.type()== IAlfVariantType::EBranch)
+        {
+        branch = aNewData.branch();
+        currentNewData = branch->data();
+        }
+
+    if (&aOldData)
+        {
+        if (aOldData.type()== IAlfVariantType::EMap)
+            {
+            currentOldData = aOldData.map();
+            }
+        else if (aOldData.type()== IAlfVariantType::EBranch)
+            {
+            oldBranch = aOldData.branch();
+            currentOldData = aOldData.branch()->data();
+            }
+        }
+
+    if ( currentNewData && mData->mVisualTemplate )
+        {
+        //Find the visual tree with data id
+        int index = findFromArray( aDataID );
+        if (index >= 0)
+            {
+            // Update the contents of the visual tree
+            CAlfVisual* visual = mData->mVisualTreeArray[index]->mVisualTree;
+            //ALF_PERF_START( perfdata, "AlfElement-updateVisualTree-VTUpdateVisualTree")
+            mData->mVisualTreeArray[index]->mVisualTree =
+                mData->mVisualTemplate->updateVisualTree(
+                    currentNewData, currentOldData, *visual );
+            //ALF_PERF_STOP( perfdata, "AlfElement-UpdateVisualTree-VTUpdateVisualTree")
+            }
+        }
+
+    if ( branch )
+        {
+        // Pass to children
+        int count = branch->childrenCount();
+        for ( int i = 0; i < count; ++i )
+            {
+            IAlfElement* element = mData->mControl->findElement( branch->childName( i ).getUtf8() );
+            if ( element )
+                {
+                IAlfVariantType* oldData = NULL;
+                if (oldBranch)
+                    {
+                    oldData = oldBranch->childData( i );
+                    }
+
+                element->updateVisualTree( *branch->childData( i ), *oldData,
+                                           mData->mControl->elementDataId( *element, i, aDataID ) );
+                }
+            }
+        }
+    }
+
+OSN_EXPORT void AlfElement::addVisualTree(CAlfVisual* aVisualTree, uint aDataID)
+    {
+    int index = findFromArray( aDataID );
+    if ( index >= 0 || aVisualTree == NULL )
+        {
+        ALF_THROW(AlfVisualException,EInvalidElement,"AlfElement")
+        }
+    // Append the visual with the assiciated data id into the array
+
+    mData->mVisualTreeArray.resize(mData->mVisualTreeArray.count()+1);
+    mData->mVisualTreeArray.insert(mData->mVisualTreeArray.count(),(new (EMM) AlfVisualData(aVisualTree, aDataID)));
+    }
+
+OSN_EXPORT void AlfElement::replaceVisualTree( IAlfVariantType& aData, uint aDataID, uint aOldDataID )
+    {
+    IAlfVariantType* oldData = control().elementData(*this, aOldDataID );
+
+    int index = findFromArray( aOldDataID );
+    if ( index < 0 )
+        {
+        ALF_THROW(AlfVisualException,EInvalidElement,"AlfElement")
+        }
+    mData->mVisualTreeArray[index]->mDataID = aDataID;
+
+    // Update the contents of the visual tree with the new data
+    updateVisualTree( aData, *oldData, aDataID );
+    }
+
+OSN_EXPORT void AlfElement::updateDataIDs(
+    IAlfBranch& aParentBranch, int aStartIndex,
+    int aOffset, uint /*aOldParentDataId*/, uint aParentDataID )
+    {
+
+    for ( int i = 0; i < mData->mVisualTreeArray.count(); ++i )
+        {
+        uint oldDataID = mData->mVisualTreeArray[i]->mDataID;
+        uint index = control().dataIdToIndex( *this, oldDataID );
+        uint newDataID = control().elementDataId(
+                             *this, index + aOffset, aParentDataID );
+        if ( index >= aStartIndex && oldDataID != newDataID )
+            {
+            // Update the data ID
+            mData->mVisualTreeArray[i]->mDataID = newDataID;
+            // The old data ID was used to calculate the child element data IDs
+            // We need to update the visual trees in child elements
+            IAlfVariantType* data = aParentBranch.childData( index );
+            if ( data != NULL )
+                {
+                if ( data->type() == IAlfVariantType::EBranch )
+                    {
+                    IAlfBranch* branch = data->branch();
+                    for ( int j = 0; j < branch->childrenCount(); ++j )
+                        {
+                        IAlfElement* childElement =
+                            mData->mControl->findElement( branch->childName( j ).getUtf8() );
+                        if ( childElement )
+                            {
+                            childElement->updateDataIDs(
+                                *branch, 0, 0, oldDataID, newDataID );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+OSN_EXPORT CAlfLayout* AlfElement::defaultParentLayout(uint aParentDataID)
+    {
+    if (mData->mParentLayout)
+        {
+        CAlfVisual* visual=NULL;
+        try
+            {
+            visual = mData->mParentLayout->resolve(*mData->mControl, aParentDataID);
+            }
+        catch (...)
+            {
+            ALF_THROW(AlfVisualException,EInvalidVisual,"AlfElement")
+            }
+        return (CAlfLayout *)visual;
+        }
+    return NULL;
+    }
+
+OSN_EXPORT void AlfElement::setDefaultParentLayout(AlfReferenceToVisual* aReference)
+    {
+    if (mData->mParentLayout)
+        {
+        delete mData->mParentLayout;
+        mData->mParentLayout = 0;
+        }
+    mData->mParentLayout = aReference;
+    }
+
+OSN_EXPORT void AlfElement::setVisualTemplate(IAlfVisualTemplate& aTemplate) throw()
+    {
+    // Remove the visual template from its previous owner
+    if(aTemplate.owner())
+        {
+        aTemplate.owner()->removeVisualTemplate();
+        }
+    
+    // Set the visual template to this element
+    mData->mVisualTemplate = &aTemplate;
+    mData->mVisualTemplate->setOwner(this);
+    }
+
+OSN_EXPORT IAlfVisualTemplate* AlfElement::getVisualTemplate() const throw()
+    {
+    return mData->mVisualTemplate;
+    }
+
+OSN_EXPORT void AlfElement::destroyVisualTemplate() throw()
+    {
+    if (mData->mVisualTemplate)
+        {
+        delete mData->mVisualTemplate;
+        mData->mVisualTemplate = 0;
+        }    
+    }
+
+OSN_EXPORT IAlfVisualTemplate* AlfElement::removeVisualTemplate() throw()
+    {
+    IAlfVisualTemplate* ret = mData->mVisualTemplate;
+    
+    // Set owner to NULL in removed visual template
+    if(mData->mVisualTemplate)
+        {
+        mData->mVisualTemplate->setOwner(0);
+        }    
+    mData->mVisualTemplate = 0;
+
+    return ret;
+    }
+
+OSN_EXPORT CAlfVisual* AlfElement::findVisual(const char* aName, uint aDataID)
+    {
+    int index = findFromArray( aDataID );
+    if ( index < 0 )
+        {
+        return NULL;
+        }
+    return mData->mVisualTreeArray[index]->mVisualTree->FindTag(TPtrC8((unsigned char*)aName));//Alf dependency
+    }
+
+OSN_EXPORT CAlfVisual* AlfElement::findVisual(uint aDataID)
+    {
+    int index = findFromArray( aDataID );
+    if ( index < 0 )
+        {
+        return NULL;
+        }
+    return mData->mVisualTreeArray[index]->mVisualTree;
+    }
+
+OSN_EXPORT uint AlfElement::dataID( const CAlfVisual& aVisual ) const
+    {
+    for ( int i = 0; i < mData->mVisualTreeArray.count(); ++i )
+        {
+        if ( mData->mVisualTreeArray[i]->mVisualTree == &aVisual )
+            {
+            return mData->mVisualTreeArray[i]->mDataID;
+            }
+        }
+    return 0;
+    }
+
+int AlfElement::findFromArray( uint aDataID ) const
+    {
+    for ( int i = 0; i < mData->mVisualTreeArray.count(); ++i )
+        {
+        if ( mData->mVisualTreeArray[i]->mDataID == aDataID )
+            {
+            return i;
+            }
+        }
+    return -1;
+    }
+
+OSN_EXPORT const IAlfElement* AlfElement::parentElement() const
+    {
+    return mData->mParentElement;
+    }
+
+OSN_EXPORT void AlfElement::setParentElement(IAlfElement& aParent)
+    {
+    mData->mParentElement = &aParent;
+    }
+
+OSN_EXPORT  CAlfWidgetControl& AlfElement::control()
+    {
+    return *mData->mControl;
+    }
+
+OSN_EXPORT  void AlfElement::removeAndDestroyVisuals( int aTimeMilliseconds )
+    {
+    //remove child elements
+    for (int i = 0; i<control().numElements(); i++)
+        {
+        IAlfElement& element = control().element(i);
+        if (element.parentElement() == this)
+            {
+            element.removeAndDestroyVisuals(aTimeMilliseconds);
+            }
+        }
+    
+    //remove visual trees and elements, that are linked 
+    //to this element with parentlayout.
+    for (int i = 0 ; i < mData->mVisualTreeArray.count(); i++)
+        {
+        AlfVisualData* vData = mData->mVisualTreeArray[i];
+        CAlfVisual* visual = vData->mVisualTree;
+        if(visual)
+            {
+            CAlfLayout* layout = dynamic_cast<CAlfLayout*>(visual);
+            if (layout)
+                {
+                for (int j = 0; j<control().numElements(); j++)
+                    {
+                    IAlfElement& element = control().element(j);
+                    CAlfLayout* parent = element.defaultParentLayout(vData->mDataID);
+                    if (parent && contains(*parent))
+                        {
+                        element.removeAndDestroyVisuals(aTimeMilliseconds);
+                        }
+                    }
+                }
+            visual->RemoveAndDestroyAllD();
+            vData->mVisualTree = NULL;
+            }
+        }
+        
+    mData->mVisualTreeArray.clear();
+    }
+
+
+//From IAlfElement
+OSN_EXPORT bool AlfElement::contains(CAlfVisual& aVisual) const
+    {
+    CAlfVisual* visual = &aVisual;
+    //traverse back to the root parent
+    while (visual)
+        {
+        for (int i = 0 ; i < mData->mVisualTreeArray.count(); i++)
+            {
+            if (visual == mData->mVisualTreeArray[i]->mVisualTree)//is this visual parent of passed visual?
+                return true;
+            }
+        visual = visual->Layout();
+        }
+    return false; //referred visual is not part of this element.
+    }
+
+// ---------------------------------------------------------------------------
+// From class IAlfInterfaceBase.
+// Getter for interfaces provided by the element.
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT IAlfInterfaceBase* AlfElement::makeInterface( const IfId& aType )
+    {
+    UString param(aType.mImplementationId);
+    if (param == IAlfElement::type().mImplementationId)
+        {
+        return static_cast<IAlfElement*>(this);
+        }
+    else if (param == IAlfAttributeOwner::type().mImplementationId)
+        {
+    	return static_cast<IAlfAttributeOwner*>(mData->mAttributeOwnerImpl.get());
+        }
+    return NULL;
+    }
+    
+    } // Alf