widgetmodel/alfwidgetmodel/src/alfwidgetcontrol.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:23:18 +0100
branchRCL_3
changeset 26 0e9bb658ef58
parent 0 e83bab7cf002
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* 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