--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/widgetmodel/alfwidgetmodel/src/alfwidget.cpp Thu Dec 17 08:56:02 2009 +0200
@@ -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 <alf/alfenv.h>
+#include "alf/alfwidget.h"
+#include <alf/alfwidgetcontrol.h>
+#include <alf/ialfmodel.h>
+#include <alf/ialfviewwidget.h>
+#include <alf/alfcontrolgroup.h>
+#include <osn/ustring.h>
+#include <alf/alfvarianttype.h>
+#include <alf/alfexceptions.h>
+#include <alf/alflayout.h>
+#include "alf/alfattribute.h"
+#include "alf/alfattributevaluetype.h"
+#include "alf/ialfattributeowner.h"
+#include <alf/ialfwidgetfactory.h>
+#include <alf/alfevent.h>
+#include <alf/alfwidgetevents.h>
+#include <alf/alfwidgetenvextension.h>
+#include <osn/osnnew.h>
+#include <assert.h>
+
+#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<CAlfWidgetControl> 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<CAlfWidgetControl*>( 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<CAlfWidgetControl*>(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<IAlfContainerWidget>(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<CAlfWidgetControl*>(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<IAlfWidget*>(this);
+ }
+ else if (param == IAlfAttributeOwner::type().mImplementationId )
+ {
+ return static_cast<IAlfAttributeOwner*>(mImpl->getAttributeOwner());
+ }
+ else if (param == IAlfContainerWidget::type().mImplementationId )
+ {
+ return static_cast<IAlfContainerWidget*>(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<IAlfWidget*>(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<IAlfViewWidget>(&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<AlfWidget*>(&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<AlfWidget*>(&aWidget));
+ CAlfWidgetControl* parentControl = dynamic_cast<CAlfWidgetControl*>(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<AlfWidget*>(&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<AlfWidget*>(&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<CAlfWidgetControl*>(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
+
+