diff -r 4ea6f81c838a -r 0e9bb658ef58 widgetmodel/alfwidgetmodel/src/alfwidget.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widgetmodel/alfwidgetmodel/src/alfwidget.cpp Wed Sep 01 12:23:18 2010 +0100 @@ -0,0 +1,498 @@ +/* +* 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 widgets. +* +*/ + + +#include +#include "alf/alfwidget.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "alf/alfattribute.h" +#include "alf/alfattributevaluetype.h" +#include "alf/ialfattributeowner.h" +#include +#include +#include +#include +#include +#include + +#include "alfwidgetimpl.h" +#include "alfwidgetattributeownerimpl.h" +#include "ialfhostapi.h" + +namespace Alf + { + +// ======== MEMBER FUNCTIONS ======== + +OSN_EXPORT AlfWidget::AlfWidget() + { + } + +OSN_EXPORT AlfWidget::AlfWidget(const char* aWidgetName) + { + mImpl.reset(new (EMM) AlfWidgetImpl()); + mImpl->setWidgetName(UString(aWidgetName)); + addCommonWidgetProperties(); + } + +OSN_EXPORT AlfWidget::AlfWidget(const char* aWidgetName, IAlfContainerWidget& aContainer, CAlfEnv& aEnv) + { + mImpl.reset(new (EMM) AlfWidgetImpl()); + mImpl->setWidgetName(UString(aWidgetName)); + addCommonWidgetProperties(); + + // Create default control for the widget so that widget containment hierarchy can be + // created. + if(!control()) + { + auto_ptr control(new (EMM) CAlfWidgetControl(aEnv)); + setControl(control.get(), false); + control.release(); + } + + // Add this widget to the container widget + aContainer.addWidget(*this); + } + +void AlfWidget::addCommonWidgetProperties() + { + } + +void AlfWidget::removeReferenceFromControl() + { + // Make sure that the widget's control is not pointing to this widget anymore + if(control() && (control()->widget() == this)) + { + control()->setOwnerWidget(0); + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +OSN_EXPORT AlfWidget::~AlfWidget() + { + + if( control() && control()->Host() ) + { + CAlfWidgetControl* parentControl = + dynamic_cast( control()->Host() ); + + if (control()->Focus()) + { + control()->CAlfWidgetControl::RelinquishFocus(); + } + + // This widget is now deleted and it needs to be removed from the + // container to avoid double deletion. + if (parentControl) + { + AlfWidget* widget = parentControl->widget(); + if (widget) + { + widget->removeWidget( *this ); + } + } + } + + // Delete and remove all the connected child widgets. + // AlfWidgetFactory::destroyWidget causes ~AlfWidget to be called for + // the child widget so this works recursively. Note that it also + // then removes the connection to the container widget in the beginning + // of ~AlfWidget destructor call. + + IAlfWidgetFactory& factory = AlfWidgetEnvExtension::widgetFactory(*(CAlfEnv::Static())); + + while ( widgetCount() ) + { + // Destroy the child widget and also remove it from the child widget + // array to make sure that this loop terminates. + // Normally also ~AlfWidget of the child widget removes the destroyed widget + // from this widget's child array, but that might not be the case + // if the child widget has not been added in the CAlfEnv + // (all widgets should always be added there). + // If not added in the env, destroyWidget does not delete the widget! + + IAlfWidget* child = mImpl->getWidget( 0 ); + + removeWidget( *child ); + IAlfWidget* actual = factory.findWidget( child->widgetName() ); + if( actual ) + { + factory.destroyWidget(actual); + } + } + + // Ensure that the control is not pointing back to this widget + removeReferenceFromControl(); + } + + +OSN_EXPORT CAlfWidgetControl* AlfWidget::control() const + { + return mImpl->control(); + } + +// --------------------------------------------------------------------------- +// return the parent container +// --------------------------------------------------------------------------- +// +OSN_EXPORT IAlfContainerWidget* AlfWidget::parent() const + { + CAlfWidgetControl* ctrl = control(); + assert(ctrl); //should always be set. + + IAlfContainerWidget* containerWidget = 0; + CAlfWidgetControl* parentControl = + dynamic_cast(ctrl->Host()); + IAlfWidgetFactory& factory = AlfWidgetEnvExtension::widgetFactory(*(CAlfEnv::Static())); + if (parentControl) + { + IAlfWidget* widget = parentControl->widget(); + if (widget) + { + //control->widget may return wrong instance, temporary fix, + // find widget from the CAlfEnv. + const char* name = widget->widgetName(); + IAlfWidget* w = factory.findWidget(name); + containerWidget = + IAlfWidget::makeInterface(w); + assert(containerWidget); + } + } + + return containerWidget; + } + +// --------------------------------------------------------------------------- +// Sets the new control for this widget. The control will be automatically +// added as an observer for the model, and notified about any +// model changes (e.g., modelChangedL()). +// --------------------------------------------------------------------------- +// +OSN_EXPORT void AlfWidget::setControl(CAlfWidgetControl* aControl, bool aDeletePreviousControl) + { + CAlfWidgetControl* myControl = control(); + if(aControl && (aControl != myControl)) + { + // Throw exception if the set control is still a control of another widget + if(aControl->widget()) + { + ALF_THROW(AlfException, EInvalidArgument, "AlfWidget::setControl() - Control is already set to another widget."); + } + + // Append control to widget's control group + if(myControl) + { + assert(myControl->ControlGroup() != 0); + aControl->resetControlGroup(*myControl->ControlGroup()); + + // Move connections from old control to new control + IAlfHostAPI& oldHostApi = myControl->hostAPI(); + IAlfHostAPI& newHostApi = aControl->hostAPI(); + + // Move old controls children under new control + int childCount = oldHostApi.getConnectionCount(); + while(childCount > 0) + { + newHostApi.setConnection(*oldHostApi.getConnection(0), EChild); + childCount--; + } + + //relinquishfocus or else pointer is left in roster, even though memory for it + //might be released. Must be called before connection removed. + if (myControl->Focus()) + { + myControl->RelinquishFocus(); + } + + // Move new control under the old control's parent and remove old control from the parent. + if(myControl->Host()) + { + CAlfWidgetControl* parent = dynamic_cast(myControl->Host()); + if(parent) + { + IAlfHostAPI& parentHostApi = parent->hostAPI(); + parentHostApi.setConnection(*aControl, EChild); + parentHostApi.removeConnection(*myControl); + } + } + } + + // Set the owner widget of the control to point to this widget + aControl->setOwnerWidget(this); + + // Remove reference to this widget from the previous control + removeReferenceFromControl(); + } + mImpl->setControl(aControl, aDeletePreviousControl); + } + +OSN_EXPORT IAlfModel* AlfWidget::model() + { + return mImpl->model(); + } + +// --------------------------------------------------------------------------- +// Sets the new model for this widget. If a control exists, it is automatically +// added as an observer for the model and notified for the model change. +// The old model is released. +// --------------------------------------------------------------------------- +// +OSN_EXPORT void AlfWidget::setModel( IAlfModel* aModel,bool aTakeOwnerShip) + { + mImpl->setModel( aModel ,aTakeOwnerShip); + } + + +OSN_EXPORT const char* AlfWidget::widgetName() const + { + return mImpl->widgetName().getUtf8(); + } + +// --------------------------------------------------------------------------- +// From class MAlfInterfaceBase. +// Static getter for interfaces provided by the widget, the control, or the model. +// --------------------------------------------------------------------------- +// +OSN_EXPORT IAlfInterfaceBase* AlfWidget::makeInterface( AlfWidget* aWidget, const IfId& aType ) + { + if ( !aWidget ) + { + return NULL; + } + else + { + return aWidget->makeInterface( aType ); + } + } + +// --------------------------------------------------------------------------- +// From class IAlfInterfaceBase. +// Getter for interfaces provided by the widget. +// --------------------------------------------------------------------------- +// +OSN_EXPORT IAlfInterfaceBase* AlfWidget::makeInterface( const IfId& aType ) + { + UString param(aType.mImplementationId); + if ( param == IAlfWidget::type().mImplementationId ) + { + return static_cast(this); + } + else if (param == IAlfAttributeOwner::type().mImplementationId ) + { + return static_cast(mImpl->getAttributeOwner()); + } + else if (param == IAlfContainerWidget::type().mImplementationId ) + { + return static_cast(this); + } + IAlfInterfaceBase* result = NULL; + if (control()) + { + result = control()->makeInterface(aType); + } + if (!result && model()) + { + result = model()->makeInterface(aType); + } + return result; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +OSN_EXPORT int AlfWidget::widgetCount() const + { + return mImpl->widgetCount(); + } + +// --------------------------------------------------------------------------- +// From class IAlfContainerWidget +// --------------------------------------------------------------------------- +OSN_EXPORT void AlfWidget::addWidget(IAlfWidget& aWidget) + { + // There should never be a situation where add widget is called on a + // widget without a control. + assert(aWidget.control() != 0); + assert(control() != 0); + assert(control()->ControlGroup() != 0); + + // Throw an exception if widget is added to itself. + IAlfWidget* self = static_cast(this); + if(self == &aWidget) + { + ALF_THROW(AlfException, EInvalidArgument, "Tried to add a widget to itself."); + } + + // Throw an exception if added widget is a view widget. + IAlfViewWidget* view = aWidget.makeInterface(&aWidget); + if(view != 0) + { + ALF_THROW(AlfException, EInvalidArgument, "Attempted to add a view widget into a container widget."); + } + + // Bail out if the given widget is already added in this widget. + if(mImpl->findWidget(static_cast(&aWidget)) != -1) + { + return; + } + + // Append the added widget and its children to widget's control group. + aWidget.control()->resetHierarchyControlGroup(*control()->ControlGroup()); + + // Append widget to widget array and remove widget from previous container's widget array. + mImpl->addWidget(static_cast(&aWidget)); + CAlfWidgetControl* parentControl = dynamic_cast(aWidget.control()->Host()); + if( parentControl ) + { + parentControl->widget()->removeWidget(aWidget); + } + + // Set connection to added widget's control + CAlfWidgetControl* cntrl = control(); + if (cntrl) + { + IAlfHostAPI& hostApi = cntrl->hostAPI(); + try + { + hostApi.setConnection(*aWidget.control(), EChild); + } + catch (AlfException &e) + { + removeWidget(aWidget); + // Attempt to add it back to the old. + if(parentControl) + { + parentControl->widget()->mImpl->addWidget(static_cast(&aWidget)); + hostApi.setConnection(*parentControl, EChild); + } + throw(e); + } + } + } + +OSN_EXPORT IAlfWidget* AlfWidget::getWidget(int aIndex) const + { + return mImpl->getWidget(aIndex); + } + +OSN_EXPORT int AlfWidget::getWidgetIndex(IAlfWidget& aWidget) const + { + return mImpl->findWidget(static_cast(&aWidget)); + } + +OSN_EXPORT void AlfWidget::removeWidget(int aIndex) + { + IAlfWidget* widget = getWidget(aIndex); //get the widget + CAlfWidgetControl* cntrl = control(); + if (widget && cntrl) + { + CAlfWidgetControl* childcontrol = widget->control(); + if(childcontrol) + { + if (childcontrol->Focus()) + { + try + { + childcontrol->RelinquishFocus(); + } + catch(...) + { + // ignore any problems with getting rid of focus + } + } + else if(childcontrol->isContainer()) + { + CAlfWidgetControl* focused = + dynamic_cast(childcontrol->FocusedConnection()); + if(focused) + { + try + { + control()->processEvent(TAlfEvent(EEventFocusNextWidget)); + } + catch(...) + { + // cannot fail because of event processing to get rid of focus + } + } + } + IAlfHostAPI& hostApi = cntrl->hostAPI(); + hostApi.removeConnection(*childcontrol); //remove from hierarchy + } + } + mImpl->removeWidget(aIndex); //remove it from array + } + +OSN_EXPORT void AlfWidget::applyLayout(IAlfLayoutManager& aLayout) + { + CAlfWidgetControl* cntrl = control(); + if (cntrl) + { + IAlfHostAPI& hostApi = cntrl->hostAPI(); + + //remove connections first + for (int i=0 ; i< widgetCount() ; i++) + { + IAlfWidget* widget = getWidget(i); + hostApi.removeConnection(*widget->control()); + } + + hostApi.setBaseLayout(aLayout); + + //add connections again, when new layout has been set. + for (int i=0 ; i< widgetCount() ; i++) + { + IAlfWidget* widget = getWidget(i); + hostApi.setConnection(*(widget->control()),EChild); + } + } + } + +OSN_EXPORT void AlfWidget::setChildFocus(bool /*aFocus*/) + { + + } + +OSN_EXPORT void AlfWidget::setPresentation(const char* /*aFilePath*/) + { + } + + +OSN_EXPORT void AlfWidget::removeWidget(IAlfWidget& aWidget) + { + for(int i = 0; i < mImpl->widgetCount(); ++i) + { + if(mImpl->getWidget(i) == &aWidget) + { + mImpl->removeWidget(i); + break; + } + } + } + + }//namespace Alf + +