widgetmodel/alfwidgetmodel/src/alfwidget.cpp
branchRCL_3
changeset 26 0e9bb658ef58
parent 0 e83bab7cf002
equal deleted inserted replaced
25:4ea6f81c838a 26:0e9bb658ef58
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  The base class for all widgets.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <alf/alfenv.h>
       
    20 #include "alf/alfwidget.h"
       
    21 #include <alf/alfwidgetcontrol.h>
       
    22 #include <alf/ialfmodel.h>
       
    23 #include <alf/ialfviewwidget.h>
       
    24 #include <alf/alfcontrolgroup.h>
       
    25 #include <osn/ustring.h>
       
    26 #include <alf/alfvarianttype.h>
       
    27 #include <alf/alfexceptions.h>
       
    28 #include <alf/alflayout.h>
       
    29 #include "alf/alfattribute.h"
       
    30 #include "alf/alfattributevaluetype.h"
       
    31 #include "alf/ialfattributeowner.h"
       
    32 #include <alf/ialfwidgetfactory.h>
       
    33 #include <alf/alfevent.h>
       
    34 #include <alf/alfwidgetevents.h>
       
    35 #include <alf/alfwidgetenvextension.h>
       
    36 #include <osn/osnnew.h>
       
    37 #include <assert.h>
       
    38 
       
    39 #include "alfwidgetimpl.h"
       
    40 #include "alfwidgetattributeownerimpl.h"
       
    41 #include "ialfhostapi.h"
       
    42 
       
    43 namespace Alf
       
    44     {
       
    45 
       
    46 // ======== MEMBER FUNCTIONS ========
       
    47 
       
    48 OSN_EXPORT AlfWidget::AlfWidget()
       
    49     {
       
    50     }
       
    51 
       
    52 OSN_EXPORT AlfWidget::AlfWidget(const char* aWidgetName)
       
    53 	{
       
    54     mImpl.reset(new (EMM) AlfWidgetImpl());
       
    55     mImpl->setWidgetName(UString(aWidgetName));
       
    56     addCommonWidgetProperties();	
       
    57 	}
       
    58 
       
    59 OSN_EXPORT AlfWidget::AlfWidget(const char* aWidgetName, IAlfContainerWidget& aContainer, CAlfEnv& aEnv)    
       
    60     {    
       
    61     mImpl.reset(new (EMM) AlfWidgetImpl());
       
    62     mImpl->setWidgetName(UString(aWidgetName));
       
    63     addCommonWidgetProperties();    
       
    64     
       
    65     // Create default control for the widget so that widget containment hierarchy can be
       
    66     // created.
       
    67     if(!control())
       
    68         {
       
    69         auto_ptr<CAlfWidgetControl> control(new (EMM) CAlfWidgetControl(aEnv));
       
    70         setControl(control.get(), false);
       
    71         control.release();
       
    72         }
       
    73     
       
    74     // Add this widget to the container widget
       
    75     aContainer.addWidget(*this);
       
    76     }
       
    77 
       
    78 void AlfWidget::addCommonWidgetProperties()
       
    79     {
       
    80     }
       
    81 
       
    82 void AlfWidget::removeReferenceFromControl()
       
    83     {
       
    84     // Make sure that the widget's control is not pointing to this widget anymore
       
    85     if(control() && (control()->widget() == this))
       
    86     	{
       
    87     	control()->setOwnerWidget(0);
       
    88     	}	
       
    89     }
       
    90 
       
    91 // ---------------------------------------------------------------------------
       
    92 // ---------------------------------------------------------------------------
       
    93 //
       
    94 OSN_EXPORT AlfWidget::~AlfWidget()
       
    95     {
       
    96 
       
    97     if( control() && control()->Host() )
       
    98         {
       
    99         CAlfWidgetControl* parentControl =
       
   100             dynamic_cast<CAlfWidgetControl*>( control()->Host() );
       
   101         
       
   102         if (control()->Focus())
       
   103             {
       
   104             control()->CAlfWidgetControl::RelinquishFocus();
       
   105             }
       
   106          
       
   107          // This widget is now deleted and it needs to be removed from the
       
   108         // container to avoid double deletion.
       
   109         if (parentControl)
       
   110             {
       
   111             AlfWidget* widget = parentControl->widget();
       
   112             if (widget)
       
   113                 {
       
   114                 widget->removeWidget( *this );
       
   115                 }
       
   116             }
       
   117         }
       
   118             
       
   119     // Delete and remove all the connected child widgets.
       
   120     // AlfWidgetFactory::destroyWidget causes ~AlfWidget to be called for
       
   121     // the child widget so this works recursively. Note that it also
       
   122     // then removes the connection to the container widget in the beginning
       
   123     // of ~AlfWidget destructor call.
       
   124     
       
   125     IAlfWidgetFactory& factory = AlfWidgetEnvExtension::widgetFactory(*(CAlfEnv::Static()));
       
   126     
       
   127     while ( widgetCount() )
       
   128         {
       
   129         // Destroy the child widget and also remove it from the child widget
       
   130         // array to make sure that this loop terminates.
       
   131         // Normally also ~AlfWidget of the child widget removes the destroyed widget
       
   132         // from this widget's child array, but that might not be the case
       
   133         // if the child widget has not been added in the CAlfEnv
       
   134         // (all widgets should always be added there).
       
   135         // If not added in the env, destroyWidget does not delete the widget!
       
   136         
       
   137         IAlfWidget* child = mImpl->getWidget( 0 );
       
   138 
       
   139         removeWidget( *child );        
       
   140         IAlfWidget* actual = factory.findWidget( child->widgetName() );
       
   141         if( actual )
       
   142         	{
       
   143         	factory.destroyWidget(actual);
       
   144         	}              
       
   145         }
       
   146  
       
   147     // Ensure that the control is not pointing back to this widget
       
   148     removeReferenceFromControl();
       
   149     }
       
   150 
       
   151 
       
   152 OSN_EXPORT CAlfWidgetControl* AlfWidget::control() const
       
   153     {
       
   154     return mImpl->control();
       
   155     }
       
   156     
       
   157 // ---------------------------------------------------------------------------
       
   158 // return the parent container
       
   159 // ---------------------------------------------------------------------------
       
   160 //
       
   161 OSN_EXPORT IAlfContainerWidget* AlfWidget::parent() const
       
   162     {
       
   163     CAlfWidgetControl* ctrl = control();
       
   164     assert(ctrl); //should always be set.
       
   165     
       
   166     IAlfContainerWidget* containerWidget = 0;
       
   167     CAlfWidgetControl* parentControl =
       
   168         dynamic_cast<CAlfWidgetControl*>(ctrl->Host());
       
   169     IAlfWidgetFactory& factory = AlfWidgetEnvExtension::widgetFactory(*(CAlfEnv::Static()));
       
   170     if (parentControl)
       
   171         {
       
   172         IAlfWidget* widget = parentControl->widget();
       
   173         if (widget)
       
   174             {
       
   175             //control->widget may return wrong instance, temporary fix,
       
   176             // find widget from the CAlfEnv.
       
   177             const char* name = widget->widgetName();
       
   178             IAlfWidget* w = factory.findWidget(name);
       
   179             containerWidget = 
       
   180                 IAlfWidget::makeInterface<IAlfContainerWidget>(w);
       
   181             assert(containerWidget);
       
   182             }
       
   183         }
       
   184         
       
   185     return containerWidget;
       
   186     }
       
   187 
       
   188 // ---------------------------------------------------------------------------
       
   189 // Sets the new control for this widget. The control will be automatically
       
   190 // added as an observer for the model, and notified about any
       
   191 // model changes (e.g., modelChangedL()).
       
   192 // ---------------------------------------------------------------------------
       
   193 //
       
   194 OSN_EXPORT void AlfWidget::setControl(CAlfWidgetControl* aControl, bool aDeletePreviousControl)
       
   195     { 
       
   196     CAlfWidgetControl* myControl = control();
       
   197     if(aControl && (aControl != myControl))
       
   198         {
       
   199         // Throw exception if the set control is still a control of another widget
       
   200         if(aControl->widget())
       
   201             {
       
   202             ALF_THROW(AlfException, EInvalidArgument, "AlfWidget::setControl() - Control is already set to another widget.");
       
   203             }
       
   204         
       
   205         // Append control to widget's control group
       
   206         if(myControl)
       
   207             {
       
   208             assert(myControl->ControlGroup() != 0);
       
   209             aControl->resetControlGroup(*myControl->ControlGroup());
       
   210         
       
   211             // Move connections from old control to new control
       
   212             IAlfHostAPI& oldHostApi = myControl->hostAPI();
       
   213             IAlfHostAPI& newHostApi = aControl->hostAPI();
       
   214             
       
   215             // Move old controls children under new control
       
   216             int childCount = oldHostApi.getConnectionCount();
       
   217             while(childCount > 0)
       
   218                 {
       
   219                 newHostApi.setConnection(*oldHostApi.getConnection(0), EChild);
       
   220                 childCount--;
       
   221                 }
       
   222                 
       
   223 	        //relinquishfocus or else pointer is left in roster, even though memory for it
       
   224 	        //might be released. Must be called before connection removed.
       
   225             if (myControl->Focus())
       
   226                 {
       
   227                 myControl->RelinquishFocus();
       
   228                 }
       
   229                 
       
   230             // Move new control under the old control's parent and remove old control from the parent.
       
   231             if(myControl->Host())
       
   232                 {
       
   233                 CAlfWidgetControl* parent = dynamic_cast<CAlfWidgetControl*>(myControl->Host());
       
   234                 if(parent)
       
   235                     {
       
   236                     IAlfHostAPI& parentHostApi = parent->hostAPI();
       
   237                     parentHostApi.setConnection(*aControl, EChild);
       
   238                     parentHostApi.removeConnection(*myControl);
       
   239                     }
       
   240                 }                
       
   241             }
       
   242                 
       
   243         // Set the owner widget of the control to point to this widget
       
   244         aControl->setOwnerWidget(this);
       
   245         
       
   246         // Remove reference to this widget from the previous control
       
   247         removeReferenceFromControl();               
       
   248         }
       
   249     mImpl->setControl(aControl, aDeletePreviousControl);
       
   250     }
       
   251 
       
   252 OSN_EXPORT IAlfModel* AlfWidget::model()
       
   253     {
       
   254     return  mImpl->model();
       
   255     }
       
   256 
       
   257 // ---------------------------------------------------------------------------
       
   258 // Sets the new model for this widget. If a control exists, it is automatically
       
   259 // added as an observer for the model and notified for the model change.
       
   260 // The old model is released.
       
   261 // ---------------------------------------------------------------------------
       
   262 //
       
   263 OSN_EXPORT void AlfWidget::setModel( IAlfModel* aModel,bool aTakeOwnerShip)
       
   264     {
       
   265     mImpl->setModel( aModel ,aTakeOwnerShip);
       
   266     }
       
   267 
       
   268 
       
   269 OSN_EXPORT const char* AlfWidget::widgetName() const
       
   270     {
       
   271     return mImpl->widgetName().getUtf8();
       
   272     }
       
   273 
       
   274 // ---------------------------------------------------------------------------
       
   275 // From class MAlfInterfaceBase.
       
   276 // Static getter for interfaces provided by the widget, the control, or the model.
       
   277 // ---------------------------------------------------------------------------
       
   278 //
       
   279 OSN_EXPORT IAlfInterfaceBase* AlfWidget::makeInterface( AlfWidget* aWidget, const IfId& aType )
       
   280     {
       
   281     if ( !aWidget )
       
   282         {
       
   283         return NULL;
       
   284         }
       
   285     else
       
   286         {
       
   287         return aWidget->makeInterface( aType );
       
   288         }
       
   289     }
       
   290 
       
   291 // ---------------------------------------------------------------------------
       
   292 // From class IAlfInterfaceBase.
       
   293 // Getter for interfaces provided by the widget.
       
   294 // ---------------------------------------------------------------------------
       
   295 //
       
   296 OSN_EXPORT IAlfInterfaceBase* AlfWidget::makeInterface( const IfId& aType )
       
   297     {
       
   298     UString param(aType.mImplementationId);
       
   299     if ( param == IAlfWidget::type().mImplementationId )
       
   300         {
       
   301         return static_cast<IAlfWidget*>(this);
       
   302         }
       
   303     else if (param == IAlfAttributeOwner::type().mImplementationId )
       
   304         {
       
   305         return static_cast<IAlfAttributeOwner*>(mImpl->getAttributeOwner());
       
   306         }
       
   307     else if (param == IAlfContainerWidget::type().mImplementationId )
       
   308         {
       
   309         return static_cast<IAlfContainerWidget*>(this);
       
   310         }
       
   311     IAlfInterfaceBase* result = NULL;
       
   312     if (control())
       
   313         {
       
   314         result = control()->makeInterface(aType);
       
   315         }
       
   316     if (!result && model())
       
   317         {
       
   318         result = model()->makeInterface(aType);
       
   319         }
       
   320     return result;
       
   321     }
       
   322 
       
   323 // ---------------------------------------------------------------------------
       
   324 // ---------------------------------------------------------------------------
       
   325 //
       
   326 OSN_EXPORT int AlfWidget::widgetCount() const
       
   327     {
       
   328     return mImpl->widgetCount();
       
   329     }
       
   330 
       
   331 // ---------------------------------------------------------------------------
       
   332 // From class IAlfContainerWidget
       
   333 // ---------------------------------------------------------------------------
       
   334 OSN_EXPORT void AlfWidget::addWidget(IAlfWidget& aWidget)
       
   335     {
       
   336     // There should never be a situation where add widget is called on a
       
   337     // widget without a control.
       
   338     assert(aWidget.control() != 0);
       
   339     assert(control() != 0);
       
   340     assert(control()->ControlGroup() != 0);
       
   341 
       
   342     // Throw an exception if widget is added to itself.
       
   343     IAlfWidget* self = static_cast<IAlfWidget*>(this);
       
   344     if(self == &aWidget)
       
   345         {
       
   346         ALF_THROW(AlfException, EInvalidArgument, "Tried to add a widget to itself.");
       
   347         }
       
   348 
       
   349     // Throw an exception if added widget is a view widget.
       
   350     IAlfViewWidget* view = aWidget.makeInterface<IAlfViewWidget>(&aWidget);
       
   351     if(view != 0)
       
   352         {
       
   353         ALF_THROW(AlfException, EInvalidArgument, "Attempted to add a view widget into a container widget.");
       
   354         }        
       
   355 
       
   356     // Bail out if the given widget is already added in this widget.
       
   357     if(mImpl->findWidget(static_cast<AlfWidget*>(&aWidget)) != -1)
       
   358         {
       
   359         return;
       
   360         }
       
   361 
       
   362     // Append the added widget and its children to widget's control group.
       
   363     aWidget.control()->resetHierarchyControlGroup(*control()->ControlGroup());
       
   364 
       
   365     // Append widget to widget array and remove widget from previous container's widget array.
       
   366     mImpl->addWidget(static_cast<AlfWidget*>(&aWidget));
       
   367     CAlfWidgetControl* parentControl = dynamic_cast<CAlfWidgetControl*>(aWidget.control()->Host());
       
   368     if( parentControl )
       
   369         {
       
   370         parentControl->widget()->removeWidget(aWidget);
       
   371         }
       
   372 
       
   373     // Set connection to added widget's control
       
   374     CAlfWidgetControl* cntrl = control();
       
   375     if (cntrl)
       
   376         {
       
   377         IAlfHostAPI& hostApi = cntrl->hostAPI();
       
   378         try
       
   379             {
       
   380             hostApi.setConnection(*aWidget.control(), EChild);
       
   381             }
       
   382         catch (AlfException &e)
       
   383             {
       
   384             removeWidget(aWidget);
       
   385             // Attempt to add it back to the old.
       
   386             if(parentControl)
       
   387                 {
       
   388                 parentControl->widget()->mImpl->addWidget(static_cast<AlfWidget*>(&aWidget));
       
   389                 hostApi.setConnection(*parentControl, EChild);
       
   390                 }
       
   391             throw(e);
       
   392             }
       
   393         }
       
   394     }
       
   395 	
       
   396 OSN_EXPORT IAlfWidget* AlfWidget::getWidget(int aIndex) const
       
   397     {
       
   398     return mImpl->getWidget(aIndex);
       
   399     }
       
   400     
       
   401 OSN_EXPORT int AlfWidget::getWidgetIndex(IAlfWidget& aWidget) const
       
   402     {
       
   403     return mImpl->findWidget(static_cast<AlfWidget*>(&aWidget));
       
   404     }
       
   405 
       
   406 OSN_EXPORT void AlfWidget::removeWidget(int aIndex)
       
   407     {
       
   408     IAlfWidget* widget = getWidget(aIndex); //get the widget
       
   409     CAlfWidgetControl* cntrl = control();
       
   410     if (widget && cntrl)
       
   411         {
       
   412         CAlfWidgetControl* childcontrol = widget->control();
       
   413         if(childcontrol)
       
   414             {
       
   415             if (childcontrol->Focus())
       
   416                 {
       
   417                 try
       
   418                     {
       
   419                     childcontrol->RelinquishFocus();
       
   420                     }
       
   421                  catch(...)
       
   422                     {
       
   423                     // ignore any problems with getting rid of focus
       
   424                     }
       
   425                 }
       
   426             else if(childcontrol->isContainer())
       
   427                 {
       
   428                 CAlfWidgetControl* focused = 
       
   429                         dynamic_cast<CAlfWidgetControl*>(childcontrol->FocusedConnection());                    
       
   430                 if(focused)
       
   431                     {
       
   432                     try
       
   433                         {
       
   434                         control()->processEvent(TAlfEvent(EEventFocusNextWidget));
       
   435                         }
       
   436                     catch(...)
       
   437                         {
       
   438                         // cannot fail because of event processing to get rid of focus
       
   439                         }
       
   440                     }
       
   441                 }
       
   442             IAlfHostAPI& hostApi = cntrl->hostAPI();
       
   443             hostApi.removeConnection(*childcontrol); //remove from hierarchy
       
   444             }
       
   445         }
       
   446     mImpl->removeWidget(aIndex); //remove it from array
       
   447     }
       
   448 
       
   449 OSN_EXPORT void AlfWidget::applyLayout(IAlfLayoutManager& aLayout)
       
   450     {
       
   451     CAlfWidgetControl* cntrl = control();
       
   452     if (cntrl)
       
   453         {
       
   454         IAlfHostAPI& hostApi = cntrl->hostAPI();
       
   455       
       
   456         //remove connections first
       
   457         for (int i=0 ; i< widgetCount() ; i++)
       
   458             {
       
   459             IAlfWidget* widget = getWidget(i);
       
   460             hostApi.removeConnection(*widget->control());
       
   461             }
       
   462 
       
   463         hostApi.setBaseLayout(aLayout);    
       
   464         
       
   465         //add connections again, when new layout has been set.
       
   466         for (int i=0 ; i< widgetCount() ; i++)
       
   467             {
       
   468             IAlfWidget* widget = getWidget(i);
       
   469             hostApi.setConnection(*(widget->control()),EChild);
       
   470             }
       
   471         }
       
   472     }
       
   473 
       
   474 OSN_EXPORT void AlfWidget::setChildFocus(bool /*aFocus*/)
       
   475     {
       
   476 
       
   477     }
       
   478     
       
   479 OSN_EXPORT void AlfWidget::setPresentation(const char* /*aFilePath*/)
       
   480     {
       
   481     }
       
   482     
       
   483     
       
   484 OSN_EXPORT void AlfWidget::removeWidget(IAlfWidget& aWidget)
       
   485     {
       
   486     for(int i = 0; i < mImpl->widgetCount(); ++i)
       
   487         {
       
   488         if(mImpl->getWidget(i) == &aWidget)
       
   489             {
       
   490             mImpl->removeWidget(i);
       
   491             break;
       
   492             }
       
   493         }
       
   494     }
       
   495     
       
   496     }//namespace Alf
       
   497 
       
   498