widgetmodel/alfwidgetmodel/src/alfflowlayoutpreferencesimpl.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:56:02 +0200
changeset 0 e83bab7cf002
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* 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:  layoutpreferences implementation for flowlayoutmanager.
*
*/


#include <assert.h>
#include <alf/ialfwidgetcontrol.h>
#include "alf/alfwidget.h"
#include <alf/alfexceptions.h>
#include <alf/ialflayoutpreferences.h>
#include <alf/alfflowlayoutmanager.h>
#include <alf/ialfflowlayoutpolicy.h>
#include <osn/osnnew.h>

//stl
#include <algorithm> //for min & max
#include "alfflowlayoutpreferencesimpl.h"

using namespace Alf;

namespace Alf
    {
// ======== MEMBER FUNCTIONS ========

AlfFlowLayoutPreferencesImpl::AlfFlowLayoutPreferencesImpl(
    AlfFlowLayoutManager& aFlowLayoutManager) : 
    mFlowLayoutManager(aFlowLayoutManager), mPreferredSize(TAlfMetric(0))
    {
    }
// ---------------------------------------------------------------------------
// 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 AlfFlowLayoutPreferencesImpl::getMinimumSize(TAlfXYMetric& aMinSize) const
	{
    return calculateChildSizes(aMinSize, 
        flowLayoutPolicy().flowDirection(), ESizeMin);
	}

// ---------------------------------------------------------------------------
// 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 AlfFlowLayoutPreferencesImpl::getMaximumSize(TAlfXYMetric& aMaxSize) const
	{
    return calculateChildSizes(aMaxSize, 
        flowLayoutPolicy().flowDirection(), ESizeMax);
	}

// ---------------------------------------------------------------------------
// Combines and returns the preferred sizes of all child UI elements according
// to the layouting rules.
// ---------------------------------------------------------------------------
//
bool AlfFlowLayoutPreferencesImpl::getPreferredSize(TAlfXYMetric& aPreferredSize) const
    {
    bool b = false;
    bool manualSet = (mPreferredSize.iX.iMagnitude > 0 && 
                      mPreferredSize.iY.iMagnitude > 0);
    
    if (manualSet)
        {
        aPreferredSize = mPreferredSize;
        b = true;
        }
    else
        {
        b = calculateChildSizes(aPreferredSize, 
            flowLayoutPolicy().flowDirection(), ESizePreferred);
        }
    return b;
	}
 
// ---------------------------------------------------------------------------
// 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 AlfFlowLayoutPreferencesImpl::setPreferredSize( 
    const TAlfXYMetric& aPreferredSize )
	{
	mPreferredSize = aPreferredSize;
    mFlowLayoutManager.owner().updateParentLayout();
	}
    
// ---------------------------------------------------------------------------
// From class IAlfInterfaceBase.
// Getter for interfaces provided by the element.
// ---------------------------------------------------------------------------
//
IAlfInterfaceBase* AlfFlowLayoutPreferencesImpl::makeInterface(
    const IfId& aType)
    {
    UString param(aType.mImplementationId);
    IAlfInterfaceBase* ret = 0;
    if (param == IAlfLayoutPreferences::type().mImplementationId)
        {
        ret = static_cast<IAlfLayoutPreferences*>(this);
        }
    
    return ret;    
    }
    
// ---------------------------------------------------------------------------
// calculate the min-, preferred-, or max- sizes from the children. 
// ---------------------------------------------------------------------------
//    
bool AlfFlowLayoutPreferencesImpl::calculateChildSizes(
    TAlfXYMetric& aSize,  
    enum IAlfFlowLayoutPolicy::flowDirection aFlowDirection, 
    enum AlfFlowLayoutPreferencesImpl::sizeType aSizeType) const
    {
	bool ret = false; 
	TAlfXYMetric resultSize(TAlfMetric(0), TAlfMetric(0));
	
    // Iterate through all the child controls, and get their
    // preferred sizes.
    int childCount = mFlowLayoutManager.count();
    for (int i = 0; i < childCount; i++)
        {
        CAlfWidgetControl* childWidgetControl = mFlowLayoutManager.getControl(i);
        
        TAlfXYMetric size;
        if (getSize(childWidgetControl, size, aSizeType))
            {
            TAlfRealSize pixelSize = sizeInPixels(size);
            
            if (aFlowDirection == IAlfFlowLayoutPolicy::EFlowVertical)
                {
                //total width = max preferred width of child widgets.
                //total height = sum of the preferred heights of child widgets.
            	if(pixelSize.iWidth > resultSize.iX.iMagnitude)
            		{
            		resultSize.iX.iMagnitude = pixelSize.iWidth;
            		}
        		resultSize.iY.iMagnitude += pixelSize.iHeight;
        		ret = true;
                }
            else
                {
                //horizontal flow direction
                //total height = max preferred height of child widgets.
                //total width = sum of the preferred widths of child widgets.
            	if(pixelSize.iHeight > resultSize.iY.iMagnitude)
            		{
            		resultSize.iY.iMagnitude = pixelSize.iHeight;
            		}
        		resultSize.iX.iMagnitude += pixelSize.iWidth;
        		ret = true;
                }
            }
        }
	
    aSize = resultSize;
	return ret;
    }
    
// ---------------------------------------------------------------------------
// fetches the size from the IAlfLayoutPreferences-interface of the aControl.
// ---------------------------------------------------------------------------
//    
bool AlfFlowLayoutPreferencesImpl::getSize(
    CAlfWidgetControl* aControl,
    TAlfXYMetric& aSize,
    enum AlfFlowLayoutPreferencesImpl::sizeType aSizeType) const
    {
    bool ret = false;
    
    if (aControl)
        {
        const IAlfLayoutPreferences* layoutPrefs = 
            mFlowLayoutManager.getLayoutPreferences(aControl);
        
        if (layoutPrefs)
            {
            switch(aSizeType)
                {
                case AlfFlowLayoutPreferencesImpl::ESizePreferred:
                    ret = layoutPrefs->getPreferredSize(aSize);
                    break;
                case AlfFlowLayoutPreferencesImpl::ESizeMin:
                    ret = layoutPrefs->getMinimumSize(aSize);
                    break;
                case AlfFlowLayoutPreferencesImpl::ESizeMax:
                    ret = layoutPrefs->getMaximumSize(aSize);
                    break;
                }
            }
        }
        
    return ret;
    }
    
// ---------------------------------------------------------------------------
// get the flowlayoutpolicy-interface.
// ---------------------------------------------------------------------------
//    
const IAlfFlowLayoutPolicy& AlfFlowLayoutPreferencesImpl::flowLayoutPolicy() const
    {
	AlfFlowLayoutManager* man = 
	    const_cast<AlfFlowLayoutManager*>(&mFlowLayoutManager);
	IAlfFlowLayoutPolicy* policy = 
	    IAlfInterfaceBase::makeInterface<IAlfFlowLayoutPolicy>(man);
    assert(policy);
    return *policy;
    }
// ---------------------------------------------------------------------------
// converts size in metrics to size in pixels.
// implementation missing!
// ---------------------------------------------------------------------------
//    
TAlfRealSize AlfFlowLayoutPreferencesImpl::sizeInPixels(
    const TAlfXYMetric& aSize)
    {
    TAlfRealSize s;

    if(aSize.iX.iUnit == EAlfUnitPixel)
    	{
    	s.iWidth = aSize.iX.iMagnitude;
    	}
    if(aSize.iY.iUnit == EAlfUnitPixel)
        {
        s.iHeight = aSize.iY.iMagnitude;
        }

    return s;
    }
} // Alf