widgetmodel/alfwidgetmodel/src/alflayoutmanagerimpl.cpp
changeset 0 e83bab7cf002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgetmodel/alfwidgetmodel/src/alflayoutmanagerimpl.cpp	Thu Dec 17 08:56:02 2009 +0200
@@ -0,0 +1,460 @@
+/*
+* 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:  layoutmanager implementation class with focus handling in 1D (next/previous)
+*
+*/
+
+
+#include <alf/ialfwidgetcontrol.h>
+#include "alf/ialfattributeowner.h"
+#include "alf/alfattribute.h"
+#include <alf/alfvisual.h>
+#include <alf/alfenv.h>
+#include "alf/alfwidget.h"
+#include <alf/alfvisualfactory.h>
+#include <alf/alfexceptions.h>
+#include <alf/ialflayoutpreferences.h>
+#include <alf/alfwidgetenvextension.h>
+#include <alf/ialfwidgetfactory.h>
+#include <osn/osnnew.h>
+#include <libc/assert.h>
+#include <alf/attrproperty.h>
+#include "alflayoutmanagerimpl.h"
+
+
+
+namespace Alf
+    {
+
+//ifdef to prevent compiler warning: className not used.
+#ifdef ALF_DEBUG_EXCEPTIONS
+static const char* const className = "AlfLayoutManagerImpl";
+#endif
+
+// ======== MEMBER FUNCTIONS ========
+    
+// ---------------------------------------------------------------------------
+// layoutmanagerimpl constructor
+// ---------------------------------------------------------------------------
+//    
+AlfLayoutManagerImpl::AlfLayoutManagerImpl(
+    TAlfLayoutType aLayoutType)
+    {
+    mLayoutType = aLayoutType;
+    }
+    
+// ---------------------------------------------------------------------------
+// creates the layout used by the layoutmanager.
+// ---------------------------------------------------------------------------
+//    
+AlfLayoutManagerImpl::~AlfLayoutManagerImpl()
+    {
+    if (mLayout.get())
+        {
+        CAlfLayout* layout = mLayout.release();
+        layout->RemoveAndDestroyAllD();
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// creates the layout used by the layoutmanager.
+// ---------------------------------------------------------------------------
+//    
+void AlfLayoutManagerImpl::createLayout(CAlfWidgetControl& aOwner, 
+    CAlfLayout* aParentLayout, int aLayoutIndex)
+    {
+            
+    //check parameter validity.
+    if (aParentLayout && 
+        (aLayoutIndex < 0 ||aLayoutIndex > aParentLayout->Count()))
+        {
+        ALF_THROW(AlfException, EInvalidArrayIndex, className);
+        }
+        
+    //create layout
+    CAlfLayout* layout = 0;
+    TRAPD(err, layout = aOwner.AppendLayoutL(mLayoutType, aParentLayout));
+        
+	if(!layout || err != KErrNone)
+	    {
+	    ALF_THROW(AlfVisualException, ECanNotCreateVisual, className);
+	    }
+
+    //reorder, if needed.
+    if (aParentLayout && aLayoutIndex != aParentLayout->Count() - 1)
+        {
+        aParentLayout->Reorder(*layout, aLayoutIndex);
+        }
+        
+    mLayout.reset(layout);
+    }
+    
+// ---------------------------------------------------------------------------
+// returns the layout used by the layoutmanager.
+// ---------------------------------------------------------------------------
+//    
+CAlfLayout& AlfLayoutManagerImpl::getLayout() const
+    {
+    checkLayout();
+    return *mLayout.get();
+    }
+    
+// ---------------------------------------------------------------------------
+// updates the main layout
+// ---------------------------------------------------------------------------
+//
+void AlfLayoutManagerImpl::updateMainLayout()
+    {
+    checkLayout();
+    
+    const IAlfLayoutPreferences* layoutPrefs = 
+        getLayoutPreferences(getControl(*mLayout.get()));
+    if (layoutPrefs)
+        {
+        TAlfXYMetric prefSize;
+        if (layoutPrefs->getPreferredSize(prefSize))
+            {
+            TAlfRealPoint p(prefSize.iX.iMagnitude, 
+                            prefSize.iY.iMagnitude);
+            mLayout->SetSize(p);
+            }
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// notifies the layout manager, that the control's has been
+// removed from the layout.
+// ---------------------------------------------------------------------------
+//
+void AlfLayoutManagerImpl::childRemoved(CAlfWidgetControl* /*aControl*/)
+    {
+    checkLayout();
+    mLayout->UpdateChildrenLayout();
+    }
+    
+// ---------------------------------------------------------------------------
+// returns the owner control of the layoutmanager.
+// ---------------------------------------------------------------------------
+//
+CAlfWidgetControl& AlfLayoutManagerImpl::owner() const
+    {
+    checkLayout();
+    CAlfWidgetControl* widgetControl = 0;
+    
+    /* The owner is always a AlfWidgetControl.
+       So a static_cast is safe. see AlfLayoutManagerImpl::createLayout() */ 
+    widgetControl = static_cast<CAlfWidgetControl*>(
+                                     &mLayout->Owner());
+   
+    return *widgetControl;
+    }
+
+// ---------------------------------------------------------------------------
+// from IAlfLayoutPreferences
+// Returns the minimum area that this layout manager can occupy by observing
+// the minimum sizes of the child UI elements in the layout
+// ---------------------------------------------------------------------------
+//
+bool AlfLayoutManagerImpl::getMinimumSize( TAlfXYMetric& /*aMinSize*/ ) const
+	{
+	return false;
+	}
+
+// ---------------------------------------------------------------------------
+// from IAlfLayoutPreferences
+// Returns the maximum area that this layout manager can occupy by observing
+// the maximum sizes of the child UI elements in the layout
+// ---------------------------------------------------------------------------
+//
+bool AlfLayoutManagerImpl::getMaximumSize( TAlfXYMetric& /*aMaxSize*/ ) const
+	{
+	return false;
+	}
+
+// ---------------------------------------------------------------------------
+// Combines and returns the preferred sizes of all child UI elements according
+// to the layouting rules.
+// ---------------------------------------------------------------------------
+//
+bool AlfLayoutManagerImpl::getPreferredSize(TAlfXYMetric& /*aPreferredSize*/) const
+	{
+	return false;
+	}
+ 
+// ---------------------------------------------------------------------------
+// from IAlfLayoutPreferences
+// At the moment doesn't do anything since preferred size is being queried
+// from the child UI elements added to this layout manager.
+// ---------------------------------------------------------------------------
+//
+void AlfLayoutManagerImpl::setPreferredSize( const TAlfXYMetric& /*aPreferredSize*/ )
+	{
+	
+	}
+
+// ---------------------------------------------------------------------------
+// From class IAlfInterfaceBase.
+// Getter for interfaces provided by the element.
+// ---------------------------------------------------------------------------
+//
+IAlfInterfaceBase* AlfLayoutManagerImpl::makeInterface(const IfId& aType)
+    {
+    UString param(aType.mImplementationId);
+    if (param == IAlfLayoutPreferences::type().mImplementationId)
+        {
+        return static_cast<IAlfLayoutPreferences*>(this);
+        }      
+    
+    return 0;
+    }
+
+// ---------------------------------------------------------------------------
+// gets control at aIndex position in the layout.
+// ---------------------------------------------------------------------------
+//    
+CAlfWidgetControl* AlfLayoutManagerImpl::getControl(int aIndex) const
+    {
+    CAlfWidgetControl* control = 0;
+    CAlfLayout* layout = mLayout.get();
+    if (layout)
+        {
+        CAlfVisual& visual = layout->Visual(aIndex);
+        control = getControl(visual);
+        }
+    return control;
+    }
+    
+// ---------------------------------------------------------------------------
+// returns the control, which owns the visual
+// ---------------------------------------------------------------------------
+//     
+void AlfLayoutManagerImpl::doUpdateChildLayout(CAlfWidgetControl* aControl)
+    {
+    const IAlfLayoutPreferences* layoutPrefs = 
+        getLayoutPreferences(aControl);
+        
+    if (layoutPrefs)
+        {
+        TAlfXYMetric prefSize;
+        if (layoutPrefs->getPreferredSize(prefSize))
+            {
+            CAlfVisual* v = findRootVisual(aControl);
+            if (v)
+                {
+                v->SetSize(TAlfRealPoint(prefSize.iX.iMagnitude,
+                prefSize.iY.iMagnitude));
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// returns the size of the widget.
+// ---------------------------------------------------------------------------
+//
+bool AlfLayoutManagerImpl::controlRect(CAlfWidgetControl& aControl, 
+    TAlfRealRect& aRect)
+    {
+    CAlfVisual* v = findRootVisual(&aControl);
+    if (v != 0)
+        {
+        TAlfRealPoint size(v->Size().Target());
+        TAlfRealPoint pos(v->Pos().Target());
+        aRect.iTl = pos;
+        aRect.iBr.iX = pos.iX + size.iX;
+        aRect.iBr.iY = pos.iY + size.iY;
+        return true;
+        }
+        
+    return false;
+    }
+    
+// ---------------------------------------------------------------------------
+// set the size and position to the widget.
+// ---------------------------------------------------------------------------
+//
+void AlfLayoutManagerImpl::setWidgetRect(IAlfWidget& aWidget, const TAlfRealRect &aRect)
+    {
+    const UString widthName(layoutattributes::KWidth);
+    const UString heightName(layoutattributes::KHeight);
+    const UString posX(layoutattributes::KPositionX);
+    const UString posY(layoutattributes::KPositionY);
+    
+    IAlfAttributeOwner* attrOwner = 
+        IAlfInterfaceBase::makeInterface<IAlfAttributeOwner>(&aWidget);
+    if (attrOwner)
+        {
+    	auto_ptr<AlfAttributeValueType> w(
+    	    new (EMM) AlfAttributeValueType(aRect.Width()));
+    	auto_ptr<AlfAttributeValueType> h(
+    	    new (EMM) AlfAttributeValueType(aRect.Height()));
+    	auto_ptr<AlfAttributeValueType> x(
+    	    new (EMM) AlfAttributeValueType(aRect.iTl.iX));
+    	auto_ptr<AlfAttributeValueType> y(
+    	    new (EMM) AlfAttributeValueType(aRect.iTl.iY));
+    	attrOwner->setAttribute(heightName, h.get());
+    	attrOwner->setAttribute(widthName, w.get());
+    	attrOwner->setAttribute(posX, x.get());
+    	attrOwner->setAttribute(posY, y.get());
+    	
+    	h.release();
+    	w.release();
+    	x.release();
+    	y.release();
+        }
+    }  
+    
+// ---------------------------------------------------------------------------
+// set the position for the widget.
+// ---------------------------------------------------------------------------
+//
+void AlfLayoutManagerImpl::setWidgetPosition(IAlfWidget& aWidget, 
+    const TAlfRealPoint &aPos)
+    {
+    const UString posX(layoutattributes::KPositionX);
+    const UString posY(layoutattributes::KPositionY);
+    
+    IAlfAttributeOwner* attrOwner = 
+        IAlfInterfaceBase::makeInterface<IAlfAttributeOwner>(&aWidget);
+    if (attrOwner)
+        {
+    	auto_ptr<AlfAttributeValueType> x(
+    	    new (EMM) AlfAttributeValueType(aPos.iX));
+    	auto_ptr<AlfAttributeValueType> y(
+    	    new (EMM) AlfAttributeValueType(aPos.iY));
+    	attrOwner->setAttribute(posX, x.get());
+    	attrOwner->setAttribute(posY, y.get());
+    	x.release();
+    	y.release();
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// set the size for the widget.
+// ---------------------------------------------------------------------------
+//
+void AlfLayoutManagerImpl::setWidgetSize(IAlfWidget& aWidget, const TAlfRealPoint &aSize)
+    {
+    const UString widthName(layoutattributes::KWidth);
+    const UString heightName(layoutattributes::KHeight);
+    IAlfAttributeOwner* attrOwner = 
+        IAlfInterfaceBase::makeInterface<IAlfAttributeOwner>(&aWidget);
+    if (attrOwner)
+        {
+    	auto_ptr<AlfAttributeValueType> w(
+    	    new (EMM) AlfAttributeValueType(aSize.iX));
+    	auto_ptr<AlfAttributeValueType> h(
+    	    new (EMM) AlfAttributeValueType(aSize.iY));
+    	attrOwner->setAttribute(heightName, h.get());
+    	attrOwner->setAttribute(widthName, w.get());
+    	h.release();
+    	w.release();
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// updates widget size and position properties for all the children
+// to correct sizes and positions of the root visuals.
+// ---------------------------------------------------------------------------
+//    
+void AlfLayoutManagerImpl::updateAllWidgetRects()
+    {
+    const int childCount = mLayout->Count();
+    TAlfRealRect rect;
+    for (int i = 0; i < childCount; i++)
+        {
+        CAlfWidgetControl* control = getControl(i);
+        controlRect(*control, rect); //returns the real rect(of the root visual)
+        AlfWidget* widget = control->widget();
+        if(widget)
+            {
+            const char* name = widget->widgetName(); 
+            IAlfWidget* ownerwidget = AlfWidgetEnvExtension::widgetFactory(control->Env()).findWidget(name); 
+            if (ownerwidget)
+                {
+                setWidgetRect(*ownerwidget, rect); //sets the rect using widget properties.
+                }
+            }
+        }
+    
+    }
+    
+// ---------------------------------------------------------------------------
+// returns the child visual count
+// ---------------------------------------------------------------------------
+//
+int AlfLayoutManagerImpl::count() const
+    {
+    return getLayout().Count();
+    }    
+
+// ---------------------------------------------------------------------------
+// returns the control, which owns the visual
+// ---------------------------------------------------------------------------
+//      
+CAlfWidgetControl* AlfLayoutManagerImpl::getControl(CAlfVisual& aVisual) const
+    {
+    CAlfWidgetControl* temp = 0;
+    temp = dynamic_cast<CAlfWidgetControl*>(&aVisual.Owner());
+    return temp;
+    }
+    
+// ---------------------------------------------------------------------------
+// returns the control, which owns the visual
+// ---------------------------------------------------------------------------
+//      
+const IAlfLayoutPreferences* AlfLayoutManagerImpl::getLayoutPreferences(
+    CAlfWidgetControl* aControl) const
+    {
+    IAlfLayoutPreferences* layoutPrefs = 0;
+    if (aControl)
+        {
+        layoutPrefs = 
+            CAlfWidgetControl::makeInterface<IAlfLayoutPreferences>(aControl);
+        }
+        
+    return layoutPrefs;
+    }
+   
+// ---------------------------------------------------------------------------
+// finds the root visual for a control.
+// ---------------------------------------------------------------------------
+//    
+CAlfVisual* AlfLayoutManagerImpl::findRootVisual(CAlfWidgetControl* aControl) const
+    {
+    CAlfVisual* root = 0;
+    if (aControl->VisualCount() > 0)
+        {
+        //take first visual, 
+        //go up in layout hierarchy until the control is not owner anymore.
+        for (root = &aControl->Visual(0); 
+             root && root->Layout() && &root->Layout()->Owner() == aControl;
+             root = root->Layout()){}
+        }
+    return root;
+    }
+
+// ---------------------------------------------------------------------------
+// throws an exception, if layout is not created.
+// ---------------------------------------------------------------------------
+//    
+void AlfLayoutManagerImpl::checkLayout() const
+    {
+    if (!mLayout.get())
+        {
+        ALF_THROW(AlfVisualException, EInvalidVisual, className);
+        }
+    }
+
+ } // Alf