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