widgetmodel/alfwidgetmodel/src/alfwidgetcontrol.cpp
branchRCL_3
changeset 26 0e9bb658ef58
parent 0 e83bab7cf002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgetmodel/alfwidgetmodel/src/alfwidgetcontrol.cpp	Wed Sep 01 12:23:18 2010 +0100
@@ -0,0 +1,1954 @@
+/*
+* 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 base class for all widget controls.
+*
+*/
+
+
+#include <alf/alfevent.h>
+
+#include "alf/alfwidget.h"
+#include <alf/alfwidgetcontrol.h>
+#include <alf/alfmodel.h>
+#include <alf/alfwidgeteventhandler.h>
+#include "alf/alfelement.h"
+#include <alf/alfvarianttype.h>
+#include "alf/alfmodeloperation.h"
+#include <osn/ustring.h>
+#include <osn/alfptrvector.h>
+#include <alf/alfexceptions.h>
+#include <alf/alfenv.h>
+#include <alf/alfcontrolgroup.h>
+#include <alf/ialflayoutmanager.h>
+#include <alf/alfwidgetevents.h>
+#include "alf/ialfattributeowner.h"
+#include <osn/osnnew.h>
+#include <assert.h>
+
+#include "alfhostapiimpl.h"
+#include "alfwidgetcontroleventfilter.h"
+
+using namespace osncore;
+
+namespace Alf
+    {
+// ======== INTERNAL DATA TYPES ========
+
+// Forward declared inside the Alf namespace
+
+
+//Internal Class to Store the Element Data
+class ElementData
+    {
+public:
+    //Default constructor
+    ElementData():mElement(0)
+        {
+        }
+    //Destructor
+    ~ElementData()
+        {
+        delete mElement;
+        }
+    /**
+     * The element. Own.
+     */
+    IAlfElement* mElement;
+
+    /**
+     * The data id range for the element.
+     */
+    uint mDataIdRange;
+    };
+
+class AlfWidgetControlImpl
+    {
+
+public:
+    AlfWidgetControlImpl():mWidget(0),mEventFilter(0),mAlfHostAPIImpl(0)
+        {
+
+        }
+    ~AlfWidgetControlImpl()
+        {
+
+        }
+public:
+    /**
+     * The element data. Elements are owned by the control.
+     */
+    AlfPtrVector<ElementData> mElementArray;
+
+    /**
+     * The event handlers. Event handlers are owned by the control.
+     */
+    AlfPtrVector<IAlfWidgetEventHandler> mEventHandlerArray;
+
+    /**
+     * The owner widget.
+     */
+    AlfWidget* mWidget;
+    
+    /**
+     * PointerUp Event Filter.
+     */
+    AlfWidgetControlEventFilter *mEventFilter;
+    
+    /**
+     * The state of the control.
+     * The state is a combination of binary state flags.
+     */
+    uint mState;
+    /**
+     * AlfAPIImpl auto pointer.
+     * This will be used to provide container control's functionality by 
+     * widget control.Owned.
+     */
+    auto_ptr<AlfHostAPIImpl> mAlfHostAPIImpl;
+    };
+
+// ======== MEMBER FUNCTIONS ========
+
+OSN_EXPORT CAlfWidgetControl::CAlfWidgetControl(CAlfEnv& aEnv)
+    {
+    construct(aEnv);
+    }
+
+OSN_EXPORT CAlfWidgetControl::CAlfWidgetControl()
+    {
+    }
+
+OSN_EXPORT void* CAlfWidgetControl::operator new(
+                 size_t aSize, newarg /*aEnumVal*/)  throw (std::bad_alloc)
+    { 
+    void* ret = 0;
+    TRAPD(err, ret = CBase::operator new((TUint)aSize, ELeave));
+    if(err != KErrNone)
+        {
+        throw std::bad_alloc();
+        }
+    return ret;         
+    } 
+
+OSN_EXPORT void CAlfWidgetControl::construct(
+    CAlfEnv& aEnv)
+    {
+    mWdgtControlData.reset( new (EMM) AlfWidgetControlImpl() );
+    mWdgtControlData->mWidget = 0;
+    //by default control is focusable and enabled
+    mWdgtControlData->mState = IAlfWidgetControl::Focusable |
+        IAlfWidgetControl::Enabled;
+
+    // Call CAlfControl second phase constructor
+    TRAPD(err, CAlfControl::ConstructL( aEnv ));
+    if(err != KErrNone)
+        {
+        ALF_THROW(AlfException, err, "CAlfWidgetControl::construction failed.");
+        }
+    mWdgtControlData->mElementArray.setAutoDelete(true);
+    mWdgtControlData->mEventHandlerArray.setAutoDelete(true);
+    mWdgtControlData->mAlfHostAPIImpl.reset(0);
+
+    // Instatiate Event filter
+    mWdgtControlData->mEventFilter = 
+        new (EMM) AlfWidgetControlEventFilter();
+    addEventHandler(mWdgtControlData->mEventFilter);
+    }
+
+OSN_EXPORT CAlfWidgetControl::~CAlfWidgetControl()
+    {
+    //release all connections
+    while (this->ConnectionCount())
+        {
+        this->RemoveConnection(&(this->Connection(0)));
+        }
+    mWdgtControlData->mElementArray.setAutoDelete(true);
+    
+    for(int i = 0; i < mWdgtControlData->mElementArray.count(); ++i)
+        {
+        // Fetch the element
+        IAlfElement *element = mWdgtControlData->mElementArray[i]->mElement;
+
+        // If the element is also an event handler
+        IAlfWidgetEventHandler* eventHandler =
+        IAlfInterfaceBase::makeInterface<IAlfWidgetEventHandler>( element );
+        int eventHandlerIndex = 
+            mWdgtControlData->mEventHandlerArray.findRef( eventHandler );
+        if ( eventHandler && eventHandlerIndex != KErrNotFound )
+            {
+             //cache auto delete state.
+            bool autoDeleteState = 
+                mWdgtControlData->mEventHandlerArray.autoDelete();
+            mWdgtControlData->mEventHandlerArray.setAutoDelete(false);
+            mWdgtControlData->mEventHandlerArray.remove( eventHandlerIndex );
+             //restore auto delete state.
+            mWdgtControlData->mEventHandlerArray.setAutoDelete(
+                                                     autoDeleteState);
+            }
+        }
+    
+    mWdgtControlData->mElementArray.clear();
+        
+    mWdgtControlData->mEventHandlerArray.setAutoDelete(true);
+    mWdgtControlData->mEventHandlerArray.clear(); 
+    	 
+    if(mWdgtControlData->mWidget)
+        {
+        // false: don't delete twice
+        mWdgtControlData->mWidget->setControl(0, false);
+        mWdgtControlData->mWidget = 0;
+        }
+    }
+
+OSN_EXPORT uint CAlfWidgetControl::state() const
+    {
+    // Verify that the internal state stored in the member variable
+    // is in sync with the CAlfWidget state. This might not be the case
+    // if someone has called CAlfWidget APIs, e.g. AcquireFocus(), directly.
+    
+    if ( Focus() )
+        {
+        mWdgtControlData->mState |= IAlfWidgetControl::Focused;
+        }
+    else
+        {
+        mWdgtControlData->mState &= ~IAlfWidgetControl::Focused;
+        }
+
+    return mWdgtControlData->mState;
+    }
+
+OSN_EXPORT void CAlfWidgetControl::setState( uint aState )
+    {
+     // Checks the state invariants. Throws exceptions if not OK
+    checkStateInvariants(aState);
+    
+    // Visible
+    if ( aState & IAlfWidgetControl::Visible )
+        {
+        enableStateVisible();
+        }
+    else
+        {
+        disableStateVisible();
+        }
+
+    // Enabled
+    if ( aState & IAlfWidgetControl::Enabled )
+        {
+        enableStateEnabled();
+        }
+    else
+        {
+        disableStateEnabled();
+        }
+
+    // Focused
+    if ( aState & IAlfWidgetControl::Focused )
+        {
+        enableStateFocused();
+        }
+    else
+        {
+        disableStateFocused();
+        }        
+
+    // Focusable
+    if ( aState & IAlfWidgetControl::Focusable )
+        {
+        enableStateFocusable();
+        }
+    else
+        {
+        disableStateFocusable();
+        }        
+    }
+
+OSN_EXPORT void CAlfWidgetControl::enableState( uint aState )
+    {
+    // Predicts the state and checks the state invariants.
+    // Throws exceptions if not OK
+    predictAndCheckStateInvariants(aState, true);
+
+    // Visible
+    if ( aState & IAlfWidgetControl::Visible )
+        {
+        enableStateVisible();
+        }
+
+    // Enabled
+    if ( aState & IAlfWidgetControl::Enabled )
+        {
+        enableStateEnabled();
+        }
+
+    // Set Focusable. This is done first, before putting on fucus
+    if ( aState & IAlfWidgetControl::Focusable )
+        {
+        enableStateFocusable();
+        }
+        
+    // Focused
+    if ( aState & IAlfWidgetControl::Focused )
+        {
+        enableStateFocused();
+        }
+
+    }
+
+OSN_EXPORT void CAlfWidgetControl::disableState( uint aState )
+    {
+    // Predicts the state and checks the state invariants.
+    // Throws exceptions if not OK
+    predictAndCheckStateInvariants(aState, false);
+
+    // Visible
+    if ( aState & IAlfWidgetControl::Visible )
+        {
+        disableStateVisible();
+        }
+
+    // Enabled
+    if ( aState & IAlfWidgetControl::Enabled )
+        {
+        disableStateEnabled();
+        }
+
+    // Focused
+    if ( aState & IAlfWidgetControl::Focused )
+        {
+        disableStateFocused();
+        }
+
+    // Focusable
+    if ( aState & IAlfWidgetControl::Focusable )
+        {
+        disableStateFocusable();
+        }
+    }
+
+OSN_EXPORT bool CAlfWidgetControl::checkState( uint aState ) const
+    {
+    return ( state() & aState );
+    }
+
+OSN_EXPORT int CAlfWidgetControl::numEventHandlers() const
+    {
+    return mWdgtControlData->mEventHandlerArray.count();
+    }
+
+OSN_EXPORT IAlfWidgetEventHandler& CAlfWidgetControl::eventHandler(
+    int aIndex )
+    {
+    return *mWdgtControlData->mEventHandlerArray[aIndex];
+    }
+
+OSN_EXPORT int CAlfWidgetControl::eventHandlerIndex(
+    IAlfWidgetEventHandler& aEventHandler ) const
+    {
+    for ( int i = 0; i < mWdgtControlData->mEventHandlerArray.count(); ++i )
+        {
+        if ( mWdgtControlData->mEventHandlerArray[i] == &aEventHandler )
+            {
+            return i;
+            }
+        }
+    return -1;
+    }
+
+OSN_EXPORT IAlfWidgetEventHandler* CAlfWidgetControl::findEventHandler(
+    const TAlfEvent& aEvent )
+    {
+    for ( int i = 0; i < mWdgtControlData->mEventHandlerArray.count(); ++i )
+        {
+        if ( mWdgtControlData->mEventHandlerArray[i]->accept( *this, aEvent ) )
+            {
+            return mWdgtControlData->mEventHandlerArray[i];
+            }
+        }
+    return 0;
+    }
+
+OSN_EXPORT void CAlfWidgetControl::addEventHandler(
+    IAlfWidgetEventHandler* aEventHandler, int aIndex )
+    {
+    try
+        {
+        if ( mWdgtControlData->mEventHandlerArray.findRef( aEventHandler ) == 
+             KErrNotFound )
+            {
+            if ( aIndex == -1 )
+                {
+                mWdgtControlData->mEventHandlerArray.resize(
+                    mWdgtControlData->mEventHandlerArray.count()+1);
+                mWdgtControlData->mEventHandlerArray.insert(
+                    mWdgtControlData->mEventHandlerArray.count(),
+                    aEventHandler );
+                }
+            else
+                {
+                mWdgtControlData->mEventHandlerArray.resize(
+                    mWdgtControlData->mEventHandlerArray.count()+1);
+                mWdgtControlData->mEventHandlerArray.insert( aIndex,
+                                                         aEventHandler);
+                }
+            }
+        }
+    catch (...)
+        {
+        ALF_THROW(AlfWidgetException,ECommonError,"CAlfWidgetControl: Adding event handler failed.")
+        }
+    }
+
+OSN_EXPORT void CAlfWidgetControl::removeAndDestroyEventHandler(
+    IAlfWidgetEventHandler& aEventHandler )
+    {
+
+    for (int i =0; i<mWdgtControlData->mEventHandlerArray.count();i++)
+        {
+        if (mWdgtControlData->mEventHandlerArray[i] == &aEventHandler)
+            {
+            IAlfWidgetEventHandler *handler = 
+                mWdgtControlData->mEventHandlerArray[i];
+            //check if it is an eventhandler associated with presentation 
+            if(handler->eventHandlerType() == 
+               IAlfWidgetEventHandler::EPresentationEventHandler)
+                {
+                ElementData* elementData = 0;
+                // if the event handller is also an element, remove the 
+                // corresponding element data from mEventHandlerArray
+                elementData = removePesentationElementData(*handler);
+                // if the element data does not exist, remove the event handler
+                // from mEventHandlerArray and destroy it 
+                if(!elementData)
+                    {
+                    mWdgtControlData->mEventHandlerArray.remove( i );
+                    }
+                // remove the event hanlder from the array but dont destroy it,
+                // and then delete element data which in turn will destroy the
+                // element and thus the event handler
+                else
+                    {
+                    // cache auto delete state.
+                    bool autoDeleteState = 
+                        mWdgtControlData->mEventHandlerArray.autoDelete(); 
+                    mWdgtControlData->mEventHandlerArray.setAutoDelete(false);
+                    mWdgtControlData->mEventHandlerArray.remove( i );
+                    // restore auto delete state.
+                    mWdgtControlData->mEventHandlerArray.setAutoDelete(
+                                                             autoDeleteState);
+                    delete elementData;
+                    }
+                }
+            else
+                {
+                mWdgtControlData->mEventHandlerArray.remove( i );
+                }
+            return;
+            }
+
+        }
+
+    }
+
+OSN_EXPORT void CAlfWidgetControl::removeEventHandler(
+    IAlfWidgetEventHandler& aEventHandler )
+    {
+    for (int i =0; i<mWdgtControlData->mEventHandlerArray.count();i++)
+        {
+        if (mWdgtControlData->mEventHandlerArray[i] == &aEventHandler)
+            {
+            // cache auto delete state.
+            bool autoDeleteState = 
+                mWdgtControlData->mEventHandlerArray.autoDelete();
+            mWdgtControlData->mEventHandlerArray.setAutoDelete(false);
+            mWdgtControlData->mEventHandlerArray.remove( i );
+            // restore auto delete state.
+            mWdgtControlData->mEventHandlerArray.setAutoDelete(
+                                                     autoDeleteState);
+            return;
+            }
+        }
+    }
+
+OSN_EXPORT void CAlfWidgetControl::removeAndDestroyEventHandler(
+    const UString& aHandlerId )
+    {
+    for (int i =0; i<mWdgtControlData->mEventHandlerArray.count();i++)
+        {
+        IAlfWidgetEventHandler* handler = 
+            mWdgtControlData->mEventHandlerArray[i];
+        AlfWidgetEventHandlerInitData* eventData = handler->eventHandlerData();
+        if(eventData != 0)
+            {
+            //check for the event id/name
+            if (!aHandlerId.compare(eventData->mWidgetEventHandlerId))
+                {
+                //check if it is an eventhandler associated with presentation 
+                if(handler->eventHandlerType() == 
+                   IAlfWidgetEventHandler::EPresentationEventHandler)
+                    {
+                    ElementData* elementData = 0;
+                    // if the event handller is also an element, remove the 
+                    // corresponding element data from mEventHandlerArray
+                    elementData = removePesentationElementData(*handler);
+                    // if the element data does not exist, remove the event 
+                    // handler from mEventHandlerArray and destroy it 
+                    if(!elementData)
+                        {
+                        // removes and destoys the event handler
+                        mWdgtControlData->mEventHandlerArray.remove( i );
+                        }
+                    // remove the event hanlder from the array but dont destroy
+                    // it, and then delete element data which in turn will 
+                    // destroy the element and thus the event handler      
+                    else
+                        {
+                        // cache auto delete state.
+                        bool autoDeleteState = 
+                            mWdgtControlData->mEventHandlerArray.autoDelete();
+                        mWdgtControlData->mEventHandlerArray.setAutoDelete(
+                                                                 false);
+                        mWdgtControlData->mEventHandlerArray.remove( i );
+                        // restore auto delete state.
+                        mWdgtControlData->mEventHandlerArray.setAutoDelete(
+                                                             autoDeleteState);
+                        //delete element data
+                        delete elementData;
+                        }
+                    }
+                else
+                    {
+                    mWdgtControlData->mEventHandlerArray.remove( i );
+                    }
+                return;
+                }
+            }
+        
+        }
+    }
+    
+OSN_EXPORT void CAlfWidgetControl::removeAndDestroyPresentationEventHandlers()
+    {
+    int i=0;
+    while(i<mWdgtControlData->mEventHandlerArray.count())
+        {
+        IAlfWidgetEventHandler* handler = 
+                                    mWdgtControlData->mEventHandlerArray[i];
+        
+        //check if it is an eventhandler associated with presentation 
+        if(handler->eventHandlerType() == 
+               IAlfWidgetEventHandler::EPresentationEventHandler)
+            {
+            ElementData* elementData = 0;
+            // if the event handller is also an element, remove the 
+            // corresponding element data from mEventHandlerArray
+            elementData = removePesentationElementData(*handler);
+            // if the element data does not exist, remove the event handler
+            // from mEventHandlerArray and destroy it 
+            if(!elementData)
+                {
+                mWdgtControlData->mEventHandlerArray.remove( i );
+                }
+            // remove the event hanlder from the array but dont destroy it,
+            // and then delete element data which in turn will destroy the
+            // element and thus the event handler    
+            else
+                {
+                // cache auto delete state.
+                bool autoDeleteState = 
+                    mWdgtControlData->mEventHandlerArray.autoDelete();
+                mWdgtControlData->mEventHandlerArray.setAutoDelete(false);
+                mWdgtControlData->mEventHandlerArray.remove( i );
+                // restore auto delete state.
+                mWdgtControlData->mEventHandlerArray.setAutoDelete(
+                                                         autoDeleteState);
+                //delete element data
+                delete elementData;
+                }
+            }
+        else
+            {
+            i++;
+            }
+        }
+    
+    }
+    
+OSN_EXPORT void CAlfWidgetControl::removePresentationEventHandlers()
+    {
+    int i=0;
+    // cache auto delete state.
+    bool autoDeleteState = mWdgtControlData->mEventHandlerArray.autoDelete();
+    mWdgtControlData->mEventHandlerArray.setAutoDelete(false);
+    while(i<mWdgtControlData->mEventHandlerArray.count())
+        {
+        IAlfWidgetEventHandler* handler = 
+                                    mWdgtControlData->mEventHandlerArray[i];
+        //check if it is an eventhandler associated with presentation 
+        if(handler->eventHandlerType() == 
+           IAlfWidgetEventHandler::EPresentationEventHandler)
+            {
+            mWdgtControlData->mEventHandlerArray.remove( i );
+            }
+        else
+            {
+            i++;
+            }
+        }
+    // restore auto delete state.    
+    mWdgtControlData->mEventHandlerArray.setAutoDelete(autoDeleteState);
+    }
+
+ElementData* CAlfWidgetControl::removePesentationElementData( 
+    IAlfWidgetEventHandler& aEventHandler )
+    {
+    IAlfElement* element =
+        IAlfInterfaceBase::makeInterface<IAlfElement>( &aEventHandler );
+        
+    for ( int i = 0; i < mWdgtControlData->mElementArray.count(); ++i )
+        {
+        if ( mWdgtControlData->mElementArray[i]->mElement == element )
+            {
+            // cache auto delete state.
+            bool autoDeleteState = 
+                mWdgtControlData->mElementArray.autoDelete();
+            mWdgtControlData->mElementArray.setAutoDelete(false);
+            // Store the Element Data which is to be removed.
+            // This pointer will be returned to the caller
+            ElementData* elementData = mWdgtControlData->mElementArray[i];
+            mWdgtControlData->mElementArray.remove( i );
+            // restore auto delete state.
+            mWdgtControlData->mElementArray.setAutoDelete(autoDeleteState);
+            return elementData;;
+            }
+        }
+    return 0;
+    }
+
+OSN_EXPORT int CAlfWidgetControl::numElements() const
+    {
+    return mWdgtControlData->mElementArray.count();
+    }
+
+OSN_EXPORT IAlfElement& CAlfWidgetControl::element( int aIndex )
+    {
+    return *(mWdgtControlData->mElementArray[aIndex]->mElement);
+    }
+
+OSN_EXPORT IAlfElement* CAlfWidgetControl::findElement( const char* aName )
+    {
+    UString name(aName);
+    for ( int i = 0; i < mWdgtControlData->mElementArray.count(); ++i )
+        {
+        IAlfElement* element = mWdgtControlData->mElementArray[i]->mElement;
+        if (name == UString(element->name()))
+            {
+            return element;
+            }
+        }
+    return 0;
+    }
+
+OSN_EXPORT void CAlfWidgetControl::addElement( IAlfElement* aElement )
+    {
+    for ( int i = 0; i < mWdgtControlData->mElementArray.count(); ++i )
+        {
+        if ( mWdgtControlData->mElementArray[i]->mElement == aElement )
+            {
+            return; // Already exists
+            }
+        }
+    auto_ptr<ElementData> elemData( new (EMM) ElementData() );
+    elemData->mElement = aElement;
+    elemData->mDataIdRange = 0xFFFFFFFF;
+    try
+        {
+        mWdgtControlData->mElementArray.resize(
+                              mWdgtControlData->mElementArray.count()+1);
+        mWdgtControlData->mElementArray.insert(
+                              mWdgtControlData->mElementArray.count(),
+                              elemData.get() );
+        elemData.release(); // ownership transferred
+        }
+    catch (...)
+        {
+        // change the element of element data to 0.
+        // this will ensure that the element does not get deleted when the 
+        // elemData gets out of scope, since elemData was not successfully 
+        // added to the array
+        elemData->mElement = 0;
+        ALF_THROW(AlfException,ECommonError,"AlfWidgetControl: Adding the element failed.")
+        }    
+    }
+
+OSN_EXPORT void CAlfWidgetControl::removeAndDestroyElement(
+    const IAlfElement& aElement )
+    {
+    for ( int i = 0; i < mWdgtControlData->mElementArray.count(); ++i ) 
+        {
+        if (mWdgtControlData->mElementArray[i])
+            {
+            if ( mWdgtControlData->mElementArray[i]->mElement == &aElement )
+                {
+                // Remove the element
+                IAlfElement *element = 
+                                mWdgtControlData->mElementArray[i]->mElement;
+
+                // If the element is also an event handler
+                IAlfWidgetEventHandler* eventHandler =
+                    IAlfInterfaceBase::makeInterface<IAlfWidgetEventHandler>(
+                                           element );
+                int eventHandlerIndex = 
+                    mWdgtControlData->mEventHandlerArray.findRef(
+                                          eventHandler );
+                if ( eventHandler && eventHandlerIndex != KErrNotFound )
+                    {
+                    // cache auto delete state.
+                    bool autoDeleteState = 
+                        mWdgtControlData->mEventHandlerArray.autoDelete();
+                    mWdgtControlData->mEventHandlerArray.setAutoDelete(false);
+                    mWdgtControlData->mEventHandlerArray.remove(
+                                                         eventHandlerIndex );
+                    // restore auto delete state.
+                    mWdgtControlData->mEventHandlerArray.setAutoDelete(
+                                                             autoDeleteState);
+                    }
+                // remove and destroy the element
+                mWdgtControlData->mElementArray.remove( i );
+                return;
+                }
+
+            }
+        }
+    }
+    
+OSN_EXPORT void CAlfWidgetControl::removeElement(const IAlfElement& aElement )
+    {
+    for ( int i = 0; i < mWdgtControlData->mElementArray.count(); ++i ) 
+        {
+        if (mWdgtControlData->mElementArray[i])
+            {
+            if ( mWdgtControlData->mElementArray[i]->mElement == &aElement )
+                {
+                // make the element pointer of elementData null, and then 
+                // destroy elementData. This will ensure that the memory
+                // allocated for the elementData is freed but the element
+                // is not destroyed
+                mWdgtControlData->mElementArray[i]->mElement = 0;
+                mWdgtControlData->mElementArray.remove(i);
+                return;
+                }
+            }
+        }
+    }    
+
+OSN_EXPORT uint CAlfWidgetControl::elementDataId(
+    const IAlfElement& aElement,
+    uint aIndex,
+    uint aParentDataId )
+    {
+    uint range = dataIdRange( aElement );
+
+    if ( aIndex >= range )
+        {
+        }
+    // In hierarchical element structures this may overflow
+    return aParentDataId * range + aIndex;
+    }
+
+OSN_EXPORT uint CAlfWidgetControl::parentElementDataId(
+    const IAlfElement& aElement,
+    uint aDataId )
+    {
+    uint dataIdRng = dataIdRange( aElement );
+    if (0 == dataIdRng) return(0xFFFFFFFF);
+    else
+        return (uint)( aDataId / dataIdRange( aElement ) );
+    }
+
+OSN_EXPORT uint CAlfWidgetControl::dataIdToIndex( 
+    const IAlfElement& aElement,
+    uint aDataId )
+    {
+    uint dataIdRng = dataIdRange( aElement );
+    if (0 == dataIdRng) return(0xFFFFFFFF);
+    else
+        return aDataId % dataIdRange( aElement );
+    }
+
+OSN_EXPORT IAlfVariantType* CAlfWidgetControl::elementData(
+    const IAlfElement& aElement, uint aDataId )
+    {
+    if (!mWdgtControlData->mWidget)
+        {
+        return 0;	
+        }
+    IAlfModel* widgetModel = mWdgtControlData->mWidget->model();
+    if ( !widgetModel )
+        {
+    	return 0;
+        }
+    IAlfVariantType* modelData = widgetModel->data();
+    if ( !modelData || modelData->type() != IAlfVariantType::EMap )
+        {
+    	return 0;
+        }
+        
+    IAlfMap* map = modelData->map();
+
+    // Use "current" to traverse elements from the root to the leaf
+    const IAlfElement* last = 0;
+    while ( last != &aElement )
+        {
+        int currentDataId = aDataId;
+        const IAlfElement* current;
+        for ( current = &aElement ;
+                current->parentElement() != last ;
+                current = current->parentElement() )
+            {
+            currentDataId = parentElementDataId( *current, currentDataId );
+            }
+        int index = dataIdToIndex( *current, currentDataId );
+        last = current;
+
+        IAlfVariantType* data = map->item( UString(current->name()) );
+        if ( data->type() == IAlfVariantType::EContainer )
+            {
+            data = data->container()->item( index );
+            }
+        if ( current == &aElement )
+            {
+            return data;
+            }
+        if ( data->type() == IAlfVariantType::EBranch )
+            {
+            // Continue with the child data
+            map = data->branch()->childData();
+            continue;
+            }
+        if ( data->type() == IAlfVariantType::EMap )
+            {
+            map = data->map();
+            }
+        else
+            {
+            return 0;
+            }
+        }
+
+    return 0;
+    }
+
+OSN_EXPORT void CAlfWidgetControl::setDataIdRange(
+    const IAlfElement& aElement, uint aRange )
+    {
+    for ( int i = 0; i < mWdgtControlData->mElementArray.count(); ++i )
+        {
+        if ( mWdgtControlData->mElementArray[i]->mElement == &aElement )
+            {
+            mWdgtControlData->mElementArray[i]->mDataIdRange = aRange;
+            return;
+            }
+        }
+    }
+
+OSN_EXPORT uint CAlfWidgetControl::dataIdRange( const IAlfElement& aElement )
+    {
+    for ( int i = 0; i < mWdgtControlData->mElementArray.count(); ++i )
+        {
+        if ( mWdgtControlData->mElementArray[i]->mElement == &aElement )
+            {
+            return mWdgtControlData->mElementArray[i]->mDataIdRange;
+            }
+        }
+    return 0;
+    }
+
+OSN_EXPORT void CAlfWidgetControl::updatePresentation()
+    {
+    if ( !mWdgtControlData->mWidget || !mWdgtControlData->mWidget->model() ||
+            !mWdgtControlData->mWidget->model()->data() ||
+            mWdgtControlData->mWidget->model()->data()->type() != 
+            IAlfVariantType::EMap )
+        {
+        return;
+        }
+    IAlfMap* map = mWdgtControlData->mWidget->model()->data()->map();
+    for ( int i = 0; i < map->count(); ++i )
+        {
+        IAlfElement* element = findElement( map->name( i ).getUtf8() );
+        if ( element )
+            {
+
+            int childInd = childIndex( *map, i, 0, true );
+            IAlfVariantType* data = map->item( i );
+            try
+                {
+                if ( data->type() == IAlfVariantType::EMap ||
+                        data->type() == IAlfVariantType::EBranch)
+                    {
+                    // Data for a single presentation instance (visual tree)
+                    element->createVisualTree( *data,
+                        elementDataId( *element, childInd, 0 ),
+                        element->defaultParentLayout( 0 ), childInd );
+                    }
+                else if ( data->type() == IAlfVariantType::EContainer )
+                    {
+
+                    // Data for multiple presentation instances (visual trees)
+                    IAlfContainer* container = data->container();
+                    for ( int j = 0; j < container->count(); ++j )
+                        {
+                        element->createVisualTree( *container->item( j ),
+                            elementDataId( *element, childInd + j, 0 ),
+                            element->defaultParentLayout( 0 ), childInd + j );
+                        }
+                    }
+                }
+            catch (...)
+                {
+                ALF_THROW(AlfVisualException,ECanNotCreateVisual,"CAlfWidgetControl::updatePresentation failed")
+                }
+
+            }
+
+        }
+    }
+
+OSN_EXPORT void CAlfWidgetControl::destroyPresentation( int aTimeMilliseconds )
+    {
+    (void)aTimeMilliseconds;
+
+    for ( int i = 0; i < mWdgtControlData->mElementArray.count(); ++i )
+        {
+        mWdgtControlData->mElementArray[i]->mElement->removeAndDestroyVisuals(
+                                                          aTimeMilliseconds );
+        }
+    processEvent(TAlfEvent(EEventWidgetPresentationDestroyed));
+    }
+    
+OSN_EXPORT void CAlfWidgetControl::destroyVisualsAndElements(
+    int aTimeMilliseconds )
+    {
+    (void)aTimeMilliseconds;
+
+    // destroy visual trees from elements
+    for( int i = 0; i < mWdgtControlData->mElementArray.count(); ++i )
+        {
+        mWdgtControlData->mElementArray[i]->mElement->removeAndDestroyVisuals(
+                                                          aTimeMilliseconds );
+        }
+    // destroy elements
+    while( numElements() )
+        {
+        removeAndDestroyElement( element(numElements()-1) );
+        }	
+	
+    // destroy presentation related event handlers
+    removeAndDestroyPresentationEventHandlers();
+	
+    // send notification
+    processEvent(TAlfEvent(EEventWidgetPresentationDestroyed));		
+    }
+    
+OSN_EXPORT void CAlfWidgetControl::updateParentLayout()
+    {
+    //get the parent control
+    CAlfWidgetControl* parent = dynamic_cast<CAlfWidgetControl*>(Host());
+    if (parent)
+        {
+        IAlfLayoutManager* layoutManager = 
+            CAlfWidgetControl::makeInterface<IAlfLayoutManager>(parent);
+        if (layoutManager)
+            {
+            layoutManager->updateChildLayout(this);
+            }
+        }
+    }
+    
+OSN_EXPORT bool CAlfWidgetControl::isContainer() const
+    {
+    IAlfHostAPI* api = mWdgtControlData->mAlfHostAPIImpl.get();
+    return (api && api->getConnectionCount() > 0);
+    }
+    
+OSN_EXPORT bool CAlfWidgetControl::isFocusable() const
+    {
+    return checkState(IAlfWidgetControl::Enabled) && 
+           checkState(IAlfWidgetControl::Focusable);
+    }
+
+void CAlfWidgetControl::setOwnerWidget( AlfWidget* aWidget )
+    {
+    mWdgtControlData->mWidget = aWidget;
+    }
+
+OSN_EXPORT AlfWidget* CAlfWidgetControl::widget()
+    {
+    return mWdgtControlData->mWidget;
+    }
+
+OSN_EXPORT AlfEventStatus CAlfWidgetControl::handleEvent(
+    const TAlfEvent& aEvent )
+    {
+    AlfEventStatus ret = EEventNotHandled;
+    if(isContainer())
+        {
+        CAlfWidgetControl* focused = 
+                    dynamic_cast<CAlfWidgetControl*>(FocusedConnection());
+        if(focused && aEvent.IsKeyEvent())
+            {
+            ret = focused->processEvent(aEvent);
+            }
+        else if ( aEvent.IsCustomEvent() )
+            {
+            int eventId = aEvent.CustomParameter();
+            switch(eventId)
+                {
+                case EEventFocusNextWidget:
+                    {
+                      if( handleFocusNext() )
+                          {
+                          ret = EEventConsumed;
+                          }
+                    }
+                    break;
+                case EEventFocusPreviousWidget:
+                    {
+                      if( handleFocusPrevious() )
+                          {
+                          ret = EEventConsumed;
+                          }
+                    }
+                    break;
+                }
+            }
+        }
+    return ret;
+
+    }
+
+
+OSN_EXPORT TBool CAlfWidgetControl::OfferEventL( const TAlfEvent& aEvent )
+    {
+    TBool ret(EFalse);
+    try
+        {
+        ret = processEvent(aEvent);  
+        }
+    catch(AlfException& ae)
+        {
+        int reason = ae.errorCode();
+        User::Leave( reason );
+        }
+    
+    return ret;
+    }
+    
+    
+    
+    
+ OSN_EXPORT AlfEventStatus CAlfWidgetControl::processEvent(
+    const TAlfEvent& aEvent )
+    {
+    AlfEventStatus ret(EEventNotHandled);
+    
+    /* If the event is not a custom event, stop execution if the widget is
+       not in enabled state. For custom event continue execution anyway. */
+    if(!(mWdgtControlData->mState & IAlfWidgetControl::Enabled) &&
+          !(aEvent.IsCustomEvent()))
+        {
+        return EEventNotHandled;    
+        }
+    
+    // Go through tunneling phase event handlers.
+    AlfEventStatus ret2 = ProcessEventHandlingPhase( tunneling, aEvent );
+    
+    if( ret2 == EEventConsumed )  
+        {
+        return EEventConsumed;  
+        }
+    else if ( ret2 == EEventHandled )     
+        {
+        ret = EEventHandled;
+        }
+
+    // Execute business logic.
+    if(aEvent.IsPointerEvent())
+        {
+        if (aEvent.PointerDown() && isFocusable() && !Focus())
+             {
+             AcquireFocus();  
+             }
+        }
+    
+    ret2 = handleEvent( aEvent );
+    
+    if( ret2 == EEventConsumed )  
+        {
+        return EEventConsumed;  
+        }
+    else if ( ret2 == EEventHandled )     
+        {
+        ret = EEventHandled;
+        }
+    
+    // Go through bubbling phase event handlers.
+    ret2 = ProcessEventHandlingPhase( bubbling, aEvent );
+    
+    if( ret2 == EEventConsumed )  
+        {
+        return EEventConsumed;  
+        }
+    else if ( ret2 == EEventHandled )     
+        {
+        ret = EEventHandled;
+        }
+        
+    return ret;
+    }
+
+AlfEventStatus CAlfWidgetControl::ProcessEventHandlingPhase(
+    int aPhase, const TAlfEvent& aEvent )
+    {
+    // *** Implementation note ***
+    //
+    // offerEvent implementations may remove event handlers from the array that is
+    // being gone through. So that needs to be taken in consideration in the
+    // loop implementation.
+
+    AlfEventStatus ret = EEventNotHandled;
+
+    AlfPtrVector<IAlfWidgetEventHandler>& eventHandlerArray =
+        mWdgtControlData->mEventHandlerArray;    
+    
+    for (int i=0; i < eventHandlerArray.count() ; ++i)
+        {
+        IAlfWidgetEventHandler* eventHandler = 
+            mWdgtControlData->mEventHandlerArray[i];
+        
+        int phase = eventHandler->eventExecutionPhase();
+        
+        bool matchingPhase = false;
+        if ( aPhase == bubbling )
+            {
+            if ( phase == IAlfWidgetEventHandler::
+                              EBubblingPhaseEventHandler || 
+                 phase == IAlfWidgetEventHandler::
+                              ETunnellingAndBubblingPhaseEventHandler )
+                {
+                matchingPhase = true;
+                }
+            }
+        else if ( aPhase == tunneling )
+            {
+            if ( phase == IAlfWidgetEventHandler::
+                              ETunnellingPhaseEventHandler || 
+                 phase == IAlfWidgetEventHandler::
+                              ETunnellingAndBubblingPhaseEventHandler )
+                {
+                matchingPhase = true;
+                }            
+            }
+        
+        if ( matchingPhase )
+            {
+            // This is preparation for the situation where event handlers are
+            // removed or added during offerEvent call.
+            // Store pointer to the event handler at next index.
+            IAlfWidgetEventHandler* nextHandler = 0;
+            
+            if ( i+1 < eventHandlerArray.count() )
+                {
+                nextHandler = eventHandlerArray[i+1];
+                }
+            
+            // Call offerEvent            
+            AlfEventStatus ret2 = eventHandler->offerEvent(*this, aEvent);
+            
+            // Update status in the function return value.
+            if( ret2 == EEventConsumed )  
+                {
+                ret = EEventConsumed;
+                break;  
+                }
+            else if ( ret2 == EEventHandled )
+	            {
+	            ret = EEventHandled;
+	            }            
+            
+            // Now check whether next handler in the event handler array still
+            // matches with the stored pointer.
+            if ( nextHandler )
+                {
+                // Check whether the event handler at index i+1 is still the 
+                // same as before calling offerEvent. If not, the array has 
+                // been modified and the variable i needs to be set again. 
+                if ( i+1 >= eventHandlerArray.count() ||
+                     (i+1 < eventHandlerArray.count() && 
+                     eventHandlerArray[i+1] != nextHandler) )
+                    {
+                    // Array has changed in offerEvent, the handler at index 
+                    // 'i+1' is not the same any more. Find the index of the 
+                    // current event handler again in the array and fix the
+                    // loop variable 'i' point to that and continue.
+                    int newCount = eventHandlerArray.count();
+                    for ( int j = 0 ; j < newCount ; j++ )
+                        {
+                        if ( eventHandlerArray[j] == eventHandler )
+                            {
+                            i = j;
+                            break;
+                            }
+                        }
+                    
+                    }
+                }                        
+            }
+        }
+        
+    return ret;
+    }
+
+// from base class IAlfModelChangeObserver
+
+OSN_EXPORT void CAlfWidgetControl::modelChanged( IAlfModel& aModel )
+    {
+    (void)aModel;
+    // This way the model change animation is customizable using event handlers
+    // The default event handler could implement this:
+    destroyPresentation( 0 );
+    updatePresentation();
+    updateParentLayout();
+    }
+
+OSN_EXPORT void CAlfWidgetControl::dataChanging(
+    const AlfPtrVector<AlfModelOperation>& aOperations )
+    {
+    for ( int i = 0; i < aOperations.count(); ++i )
+        {
+        dataChanging( *aOperations[i] );
+        }
+    }
+
+OSN_EXPORT void CAlfWidgetControl::dataChanging(
+    const AlfModelOperation& aOperation )
+    {
+    int numIndices = aOperation.numContainerIndices();
+    if ( !mWdgtControlData->mWidget->model() || numIndices <= 0 )
+        {
+        return;
+        }
+    uint dataId = 0, parentDataId = 0;
+    IAlfElement* element = 0;
+    IAlfElement* parentElement = 0;
+    IAlfVariantType* data = mWdgtControlData->mWidget->model()->data();
+    if(data == 0)
+        {
+        return;
+        }
+    IAlfBranch* parentBranch = 0;
+    // Traverse the data hierarchy to find the data, dataId and the element
+    for ( int i = 0; i < numIndices; ++i )
+        {
+        int index = aOperation.containerIndex( i );
+        if ( data->type() == IAlfVariantType::EMap  &&
+                index >= 0 && index < data->map()->count() )
+            {
+            parentElement = element;
+            element = findElement( data->map()->name( index ).getUtf8() );
+            if ( element == 0 )
+                {
+                return; // Not found
+                }
+            IAlfMap* map = data->map();
+            data = data->map()->item( index );
+
+            if ( data->type() == IAlfVariantType::EContainer )
+                {
+                ++i;
+                int containerIndex = aOperation.containerIndex( i );
+                if ( containerIndex < 0 || 
+                       containerIndex >= data->container()->count() )
+                    {
+                    break; // Not found
+                    }
+                int childInd = 
+                    childIndex( *map, index, containerIndex, i == 1 );
+                parentDataId = dataId;
+                dataId = elementDataId( *element, childInd, parentDataId );
+                data = data->container()->item( containerIndex );
+                }
+            else
+                {
+                int childInd = childIndex( *map, index, 0, i == 0 );
+                parentDataId = dataId;
+                dataId = elementDataId( *element, childInd, parentDataId );
+                }
+            }
+        else if ( data->type() == IAlfVariantType::EBranch &&
+                  index == 0 && i == numIndices - 1 )
+            {
+            // Changing the parent data
+            data = data->branch()->data();
+            }
+        else if ( data->type() == IAlfVariantType::EBranch && index == 1 )
+            {
+            parentBranch = data->branch();
+            data = data->branch()->childData();
+            }
+        else
+            {
+            return; // Not found
+            }
+        }
+
+    // Perform the operation
+    if ( aOperation.operation() == AlfModelOperation::EOperationAdd )
+        {
+        if ( parentBranch )
+            {
+            // The parent is responsible for it's children
+            parentElement->createChildVisualTree( 
+                               element, aOperation.newData(),
+                               *parentBranch,aOperation.index(),
+                               parentDataId );
+            }
+        else
+            {
+            if(element)
+                {
+                // Data added to a root element
+                try
+                    {
+                    element->createVisualTree(
+                                 aOperation.newData(), dataId,
+                                 element->defaultParentLayout( parentDataId ),
+                                 aOperation.index() );
+                    }
+                catch (...)
+                    {
+                    ALF_THROW(AlfVisualException,ECanNotCreateVisual,"CAlfWidgetControl::dataChanging failed")
+                    }               
+                }
+            else
+                {
+                ALF_THROW(AlfVisualException,ECanNotCreateVisual,"CAlfWidgetControl::dataChanging failed")
+                }
+
+            }
+        }
+    else if ( aOperation.operation() == AlfModelOperation::EOperationRemove )
+        {
+        if ( parentBranch )
+            {
+            // The parent is responsible for it's children
+            parentElement->removeChildVisualTree(
+                element, *parentBranch, aOperation.index(), parentDataId );
+            }
+        else
+            {
+            if(element)
+                {
+                // Data removed from a root element
+                element->removeVisualTree( *data, dataId );
+                }
+            }
+        }
+    else if ( aOperation.operation() == AlfModelOperation::EOperationUpdate )
+        {
+        if(element)
+            {
+            element->updateVisualTree( aOperation.newData(), *data, dataId );            
+            }
+        }
+    }
+
+OSN_EXPORT void CAlfWidgetControl::dataChanged()
+    {
+    // The default implementation is empty.
+    }
+
+uint CAlfWidgetControl::childIndex(
+    IAlfMap& aMap, uint aMapIndex,
+    uint aContainerIndex, bool aRoot )
+    {
+    // This method is only used internally
+    const UString& elementName = aMap.name( aMapIndex );
+    int index = 0;
+    for ( int i = 0; i < aMapIndex && i < aMap.count(); ++i )
+        {
+        if ( !aRoot || elementName == aMap.name( i ) )
+            {
+            IAlfVariantType* data = aMap.item( i );
+            if ( data->type() == IAlfVariantType::EMap ||
+                    data->type() == IAlfVariantType::EBranch)
+                {
+                index++;
+                }
+            else if ( data->type() == IAlfVariantType::EContainer )
+                {
+                index += data->container()->count();
+                }
+            }
+        }
+    return index + aContainerIndex;
+    }
+
+// ---------------------------------------------------------------------------
+// From class IAlfInterfaceBase.
+// Getter for interfaces provided by the control.
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT IAlfInterfaceBase* CAlfWidgetControl::makeInterface(
+    const IfId& aType )
+    {
+    IAlfInterfaceBase* interface = 0;
+    UString param(aType.mImplementationId);
+    if ( param == IAlfWidgetControl::type().mImplementationId )
+        {
+        return static_cast<IAlfWidgetControl*>( this );
+        }
+    else if (param == IAlfAttributeOwner::type().mImplementationId)
+        {
+        return 0; // control does not have AttributeOwner instance
+        		  // and do not try get IF from elements in control
+        }
+    // Let the layout manager create the interface that is queried.
+    else if(mWdgtControlData->mAlfHostAPIImpl.get())
+    	{
+    	IAlfLayoutManager* layoutManager = 
+    	    mWdgtControlData->mAlfHostAPIImpl->getBaseLayout();
+    	if(layoutManager)
+    		{
+    		interface = layoutManager->makeInterface(aType);
+    		}
+    	}
+
+    if(interface == 0)
+    	{
+        //go through all the elements    
+        for (int i = 0; i < numElements() && !interface; i++)
+            {
+            IAlfElement& ele = element(i);
+            interface = ele.makeInterface(aType);
+            }
+    	}
+
+    return interface;
+    }
+
+
+OSN_EXPORT CAlfLayout* CAlfWidgetControl::ContainerLayout(
+    const CAlfControl* /*aConnected*/) const
+    {
+    if(mWdgtControlData->mAlfHostAPIImpl.get() != 0)
+        {
+        IAlfLayoutManager* layoutManager = 
+            mWdgtControlData->mAlfHostAPIImpl->getBaseLayout();
+        if(layoutManager != 0)
+        	{
+        	return &layoutManager->getLayout();
+        	}
+        }
+    return 0;
+    }
+
+    
+OSN_EXPORT void CAlfWidgetControl::AcquireFocus()
+    {
+    if (!FocusedConnection() && isFocusable())
+        {
+        if (isContainer())
+            {
+            IAlfHostAPI& hostApi = hostAPI();
+            //select the first connection.
+            
+            CAlfWidgetControl* firstChild = nextFocusableControl(0);
+            if (firstChild)
+                {
+                firstChild->AcquireFocus();
+                }
+            }
+        else
+            {
+            CAlfControl::AcquireFocus();
+            }
+        }
+    }
+    
+OSN_EXPORT void CAlfWidgetControl::RelinquishFocus()
+    {
+    if (Focus())
+        {
+        if (isContainer())
+            {
+            handleFocusNext();
+            }
+        else
+            {
+            //get parent control, check if it can focus next control.
+            CAlfWidgetControl* parent = 
+                dynamic_cast<CAlfWidgetControl*>(Host());
+            if (parent)
+                {
+                parent->handleFocusNext();
+                }
+                
+            CAlfControl::RelinquishFocus();
+            }
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// return hostapi. create instance if needed.
+// ---------------------------------------------------------------------------
+//
+IAlfHostAPI& CAlfWidgetControl::hostAPI()
+    {
+    if (!mWdgtControlData->mAlfHostAPIImpl.get()) // was it already created?
+        {
+        //late creation
+        mWdgtControlData->mAlfHostAPIImpl.reset( new (EMM) AlfHostAPIImpl() ); 
+        mWdgtControlData->mAlfHostAPIImpl->setHostControl(*this);
+        }
+        
+    return *mWdgtControlData->mAlfHostAPIImpl.get();
+    }
+    
+OSN_EXPORT bool CAlfWidgetControl::handleFocusNext()
+    {
+    bool focusChanged = false;
+    if (isContainer())
+        {
+        CAlfWidgetControl* focused = 
+            dynamic_cast<CAlfWidgetControl*>(FocusedConnection());
+        if (focused)
+            {
+            CAlfWidgetControl* nextChild = nextFocusableControl(focused);
+                
+            if (!nextChild)
+                {
+                //no next child, change focus to upper level, if that fails,
+                //loop to first connection. 
+                CAlfWidgetControl* parent = 
+                    dynamic_cast<CAlfWidgetControl*>(Host());
+                if (parent)
+                    {
+                    focusChanged = parent->handleFocusNext();
+                    }
+                if (!focusChanged)
+                    {
+                    //loop to first connection. 
+                    nextChild = nextFocusableControl(0);
+                    }
+                }
+                
+            //go deeper down the widget hierarchy, until a no-container widget
+            // is found
+            while(nextChild && nextChild->isContainer())
+                {
+                nextChild = nextChild->nextFocusableControl(0);
+                }
+                
+            if (nextChild)
+                {
+                nextChild->AcquireFocus();
+                focusChanged = true;
+                }
+            }
+        }
+    return focusChanged;
+    }
+    
+OSN_EXPORT bool CAlfWidgetControl::handleFocusPrevious()
+    {
+    bool focusChanged = false;
+    if (isContainer())
+        {
+
+        CAlfWidgetControl* focused = 
+            dynamic_cast<CAlfWidgetControl*>(FocusedConnection());
+        if (focused)
+            {
+            CAlfWidgetControl* prevChild = previousFocusableControl(
+                focused);
+
+            if (!prevChild)
+                {
+                // no previous child, change focus to upper level, if that 
+                // fails, loop to last connection.
+                CAlfWidgetControl* parent = 
+                    dynamic_cast<CAlfWidgetControl*>(Host());
+                if (parent)
+                    {
+                    focusChanged = parent->handleFocusPrevious();
+                    }
+                if (!focusChanged)
+                    {                    
+                    //loop to last connection.
+                    prevChild = previousFocusableControl(0);
+                    }
+                }
+            //go deeper down the widget hierarchy, until a no-container widget
+            //is found. 
+            while(prevChild && prevChild->isContainer())
+                {
+                //in each level, select the last focused widget.
+                prevChild = prevChild->previousFocusableControl(0);
+                }
+                
+            if (prevChild)
+                {
+                prevChild->AcquireFocus();
+                focusChanged = true;
+                }
+            }
+        }
+        
+    return focusChanged;
+    }
+        
+OSN_EXPORT CAlfWidgetControl* CAlfWidgetControl::getFirstFocusable(
+    IAlfContainerWidget& aContainer)
+    {
+    CAlfWidgetControl* control = 0;
+    if (aContainer.widgetCount() > 0)
+        {
+        control = aContainer.getWidget(0)->control();
+        }
+    return control;
+    }
+
+OSN_EXPORT CAlfWidgetControl* CAlfWidgetControl::getLastFocusable(
+    IAlfContainerWidget& aContainer)
+    {
+    CAlfWidgetControl* control = 0;
+    if (aContainer.widgetCount() > 0)
+        {
+        IAlfWidget* w = aContainer.getWidget(aContainer.widgetCount()-1);
+        control = w->control();
+        }
+    return control;
+    }
+    
+OSN_EXPORT CAlfWidgetControl* CAlfWidgetControl::getFocusableAfter(
+    IAlfContainerWidget& aContainer,
+    CAlfWidgetControl& aControl)
+    {
+    CAlfWidgetControl* control = 0;
+    int ind = aContainer.getWidgetIndex(*aControl.widget());
+    if (ind >= 0)
+        {
+        ind++;
+        if (ind < aContainer.widgetCount())
+            {
+            IAlfWidget* w = aContainer.getWidget(ind);
+            control = w->control();
+            }
+        }
+        
+    return control;
+    }
+
+OSN_EXPORT CAlfWidgetControl* CAlfWidgetControl::getFocusableBefore(
+    IAlfContainerWidget& aContainer, CAlfWidgetControl& aControl)
+    {
+    CAlfWidgetControl* control = 0;
+    int ind = aContainer.getWidgetIndex(*aControl.widget());
+    ind--;
+    if (ind >= 0)
+        {
+        IAlfWidget* w = aContainer.getWidget(ind);
+        control = w->control();
+        }
+        
+    return control;
+    }
+    
+void CAlfWidgetControl::resetControlGroup(CAlfControlGroup& aControlGroup)
+    {
+    // If control group is already set and its same than the control group
+    // given as a parameter there's nothing we need to do.
+    if(!ControlGroup() || (ControlGroup() != &aControlGroup))
+        {
+        // Remove control from previous control group
+        if(ControlGroup())
+            {
+            ControlGroup()->Remove(this);
+            }
+        // Append control to the new control group
+        TRAPD(err, aControlGroup.AppendL(this));
+        if(err != KErrNone)
+            {
+            ALF_THROW(AlfException, err, "CAlfWidgetControl::resetControlGroup - Appending control to a new control group failed.");
+            }                    
+        }
+    }
+
+void CAlfWidgetControl::resetHierarchyControlGroup(
+    CAlfControlGroup& aControlGroup)
+    {
+    // Append this control to the new control group
+    resetControlGroup(aControlGroup);
+        
+    // Call this recursively to all connected controls
+    AlfHostAPIImpl* hostApi = mWdgtControlData->mAlfHostAPIImpl.get();
+    if(hostApi != 0)
+        {
+        for(int i = 0; i < hostApi->getConnectionCount(); ++i)
+            {
+            CAlfWidgetControl* connectedControl = hostApi->getConnection(i);
+            if(connectedControl)
+                {
+                connectedControl->resetHierarchyControlGroup(aControlGroup);
+                }
+            }
+        }    
+    }
+    
+    
+OSN_EXPORT void CAlfWidgetControl::FocusChanged(
+    CAlfDisplay& /*aDisplay*/,
+    TBool aFocused)
+    {
+    // Ensure that the state bit remains synched to the toolkit's version
+    if (aFocused)
+        {
+        mWdgtControlData->mState |= IAlfWidgetControl::Focused;
+        }
+    else
+        {
+        mWdgtControlData->mState &=~ IAlfWidgetControl::Focused;
+        }
+
+    if (aFocused)
+        {
+        processEvent(TAlfEvent(EEventWidgetGainedFocus));
+        }
+    else
+        {
+        processEvent(TAlfEvent(EEventWidgetLostFocus));
+        }
+    }
+    
+OSN_EXPORT CAlfWidgetControl* CAlfWidgetControl::nextFocusableControl(
+    CAlfWidgetControl* aControl)
+    {
+    CAlfWidgetControl* control = 0;
+    
+    if (isContainer())
+        {
+        IAlfContainerWidget* container = 
+            IAlfInterfaceBase::makeInterface<IAlfContainerWidget>(widget());
+        
+        assert(container);
+        
+        if (!aControl)
+            {
+            control = getFirstFocusable(*container);
+            }
+        else
+            {
+            control = getFocusableAfter(*container, *aControl);
+            }
+            
+        while(control && !control->isFocusable())
+            {
+            control = control->getFocusableAfter(*container, *control);
+            }
+        }
+        
+    return control;
+    }
+    
+OSN_EXPORT CAlfWidgetControl* CAlfWidgetControl::previousFocusableControl(
+    CAlfWidgetControl* aControl)
+    {
+    CAlfWidgetControl* control = 0;
+    
+    if (isContainer())
+        {
+        IAlfContainerWidget* container = 
+            IAlfInterfaceBase::makeInterface<IAlfContainerWidget>(widget());
+        
+        assert(container);
+        
+        if (!aControl)
+            {
+            control = getLastFocusable(*container);
+            }
+        else
+            {
+            control = getFocusableBefore(*container, *aControl);
+            }
+            
+        while(control && !control->isFocusable())
+            {
+            control = control->getFocusableBefore(*container, *control);
+            }
+        }
+        
+    return control;
+    }
+
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void CAlfWidgetControl::enableStateVisible()
+    {
+    // Only take action if the current state is different
+    if ( !(mWdgtControlData->mState & IAlfWidgetControl::Visible) )
+        {
+        // Update the new state in member variable
+        mWdgtControlData->mState |= IAlfWidgetControl::Visible;
+
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void CAlfWidgetControl::disableStateVisible()
+    {
+    // Only take action if the current state is different
+    if ( mWdgtControlData->mState & IAlfWidgetControl::Visible )
+        {
+        // Update the new state in member variable
+        mWdgtControlData->mState &= ~IAlfWidgetControl::Visible;
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void CAlfWidgetControl::enableStateEnabled()
+    {
+    // Only take action if the current state is different
+    if ( !(mWdgtControlData->mState & IAlfWidgetControl::Enabled) )
+        {
+        // Update the new state in member variable
+        mWdgtControlData->mState |= IAlfWidgetControl::Enabled;
+        }        
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void CAlfWidgetControl::disableStateEnabled()
+    {
+    // Only take action if the current state is different
+    if ( mWdgtControlData->mState & IAlfWidgetControl::Enabled )
+        {
+        // Update the new state in member variable
+        mWdgtControlData->mState &= ~IAlfWidgetControl::Enabled;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void CAlfWidgetControl::enableStateFocused()
+    {
+    // Only take action if the current state is different
+    if ( !(mWdgtControlData->mState & IAlfWidgetControl::Focused) )
+        {
+        // Set the new state
+        AcquireFocus();
+        
+        // Update the new state in member variable
+        mWdgtControlData->mState |= IAlfWidgetControl::Focused;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void CAlfWidgetControl::disableStateFocused()
+    {
+    // Only take action if the current state is different
+    if ( mWdgtControlData->mState & IAlfWidgetControl::Focused )
+        {
+        // Set the new state
+        RelinquishFocus();
+        
+        // Update the new state in member variable
+        mWdgtControlData->mState &= ~IAlfWidgetControl::Focused;
+        }        
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void CAlfWidgetControl::enableStateFocusable()
+    {
+    // Only take action if the current state is different
+    if ( !(mWdgtControlData->mState & IAlfWidgetControl::Focusable) )
+        {
+        // Update the new state in member variable
+        mWdgtControlData->mState |= IAlfWidgetControl::Focusable;
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void CAlfWidgetControl::disableStateFocusable()
+    {
+    // Only take action if the current state is different
+    if ( mWdgtControlData->mState & IAlfWidgetControl::Focusable )
+        {
+        // Update the new state in member variable
+        mWdgtControlData->mState &= ~IAlfWidgetControl::Focusable;
+        }    
+    }
+
+void CAlfWidgetControl::checkStateInvariants(uint aState)
+    {
+    // To be focused, it needs to be focusable (Focus -> Focusable)
+    if(aState & IAlfWidgetControl::Focused 
+    &&  !(aState & IAlfWidgetControl::Focusable)  )
+        {
+        ALF_THROW(AlfException, EInvalidArgument, "AlfWidgetControl() - state changing operation. Illegal state would result.");
+        }
+
+    // To be focusable, it needs to be enabled (Focusable -> Enabled)
+    if(aState & IAlfWidgetControl::Focusable 
+    &&  !(aState & IAlfWidgetControl::Enabled)  )
+        {
+        ALF_THROW(AlfException, EInvalidArgument, "AlfWidgetControl() - state changing operation. Illegal state would result.");
+        }
+    }
+
+void CAlfWidgetControl::predictAndCheckStateInvariants(
+    uint aChangePattern,
+    bool aEnabling) const
+    {
+    uint predictedState(mWdgtControlData->mState);
+    if(aEnabling)
+        {
+        predictedState |= aChangePattern;
+        }
+    else
+        {
+        predictedState &= ~aChangePattern;
+        }
+    checkStateInvariants(predictedState);
+    }
+
+
+} // namespace Alf
+