uiacceltk/hitchcock/coretoolkit/src/HuiGridLayout.cpp
changeset 0 15bf7259bb7c
child 18 1801340c26a2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiGridLayout.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,839 @@
+/*
+* Copyright (c) 2006-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:   ?Description
+*
+*/
+
+
+
+#include "uiacceltk/HuiGridLayout.h"  // Class definition
+#include "uiacceltk/HuiControl.h"
+#include "uiacceltk/HuiPanic.h"
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/huimetric.h"
+
+#include <AknUtils.h>
+
+
+#define FLOOR(x) (TReal32(TInt(TReal32(x))))
+#define FLOOR_INT(x) (TInt((x)))
+
+// Symbian does not have a native ceil() implementation, we need to use "near enough" rounding.
+#define CEIL(x) (TReal32(TInt(TReal32(x)+0.999f)))
+#define CEIL_INT(x) (TInt(TReal32(x)+0.999f))
+
+// Fractional part of real
+#define FRAC(x) (TReal32(x)-FLOOR(x))
+
+//
+// Private structures
+//
+
+struct TAxis
+    {
+    
+    /** Array of block weights. Used to calculate relative sizes of lines of blocks. */
+    RArray<THuiMetric> iWeights;
+    TUint iLayoutFlags;    
+    };
+
+/*
+ * grid weights
+ */
+struct CHuiGridLayout::TGridLayoutPrivateData
+    {
+public:
+    TGridLayoutPrivateData();
+public:
+    RArray<TAxis> iAxes;
+    
+    /** Sets the grid dimensions to automatically expand to store more content */
+    TInt iExpansionFlags;
+    };
+
+CHuiGridLayout::TGridLayoutPrivateData::TGridLayoutPrivateData()
+    : 
+    iExpansionFlags(0) 
+    {
+    
+    }
+
+
+//
+// class CHuiGridLayout
+//
+
+EXPORT_C CHuiGridLayout* CHuiGridLayout::AddNewL(CHuiControl& aOwnerControl, 
+                                                 TInt aColumns, TInt aRows,
+                                                 CHuiLayout* aParentLayout)
+    {
+    CHuiGridLayout* grid = STATIC_CAST(CHuiGridLayout*,
+        aOwnerControl.AppendLayoutL(EHuiLayoutTypeGrid, aParentLayout));
+    grid->SetColumnsL(aColumns);
+    grid->SetRowsL(aRows);
+
+    return grid;
+    }
+
+
+EXPORT_C CHuiGridLayout::CHuiGridLayout(MHuiVisualOwner& aOwner)
+        : CHuiLayout(aOwner)
+    {
+    }
+
+
+EXPORT_C void CHuiGridLayout::ConstructL()
+    {    
+    CHuiLayout::ConstructL();
+    iGridLayoutData = new(ELeave) TGridLayoutPrivateData;
+    for(TInt ii = EHuiGridColumn; ii <= EHuiGridRow; ii++)
+        {
+        TAxis axis;
+        axis.iLayoutFlags = 0;
+        
+        iGridLayoutData->iAxes.AppendL(axis);
+        }
+    SetColumnsL(1);
+    SetRowsL(1);
+    }
+
+	
+EXPORT_C CHuiGridLayout::~CHuiGridLayout()
+    {    
+    if ( iGridLayoutData )
+        {
+        for(TInt ii = EHuiGridColumn; ii <= EHuiGridRow; ii++)
+            {
+            TAxis& axis = iGridLayoutData->iAxes[ii];
+            axis.iWeights.Reset();
+            }
+
+        iGridLayoutData->iAxes.Reset();
+        }
+
+    delete iGridLayoutData;
+    iGridLayoutData = 0;
+    }
+
+
+EXPORT_C TInt CHuiGridLayout::ChildOrdinal(TInt aIndex)
+    {
+    // Use the visual index as ordinal.
+    return EffectiveLayoutOrdinal(Visual(aIndex));
+    }
+
+
+EXPORT_C TPoint CHuiGridLayout::OrdinalToBlock(TInt aOrdinal) const
+    {
+    TPoint block(0,0);
+    TInt cols = ColumnCount();
+    TInt rows = RowCount();
+    
+    if (cols && rows)
+        {
+        if ( iGridLayoutData->iExpansionFlags & EExpandHorizontally )
+            {
+            block.iX = aOrdinal / rows;
+            block.iY = aOrdinal % rows;
+            }
+        else
+            {
+            // By default the flow is vertically
+            block.iX = aOrdinal % cols;
+            block.iY = aOrdinal / cols;
+            }
+        }
+        
+    return block;    
+    }
+
+EXPORT_C void CHuiGridLayout::SetSize(const THuiRealSize& aSize, TInt aTransitionTime)
+    {
+    CHuiLayout::SetSize(aSize, aTransitionTime);
+    UpdateChildrenLayout(aTransitionTime);    
+    }
+
+EXPORT_C TBool CHuiGridLayout::ChildSize(TInt aOrdinal, TSize& aSize)
+    {
+    TBool result(EFalse);
+    THuiRealRect rect;
+    TInt childRectStatus(THuiLayoutChildRectUpdateNotNeeded);
+    childRectStatus = ChildRect(aOrdinal, rect);
+    if(childRectStatus != THuiLayoutChildRectNotImplemented)
+        {
+        result = (childRectStatus & THuiLayoutChildRectSizeUpdateNeeded);
+        if(result)
+            {
+            THuiRealPoint size(rect.Width(), rect.Height());
+            aSize = LocalPointInPixels(size).AsSize();
+            }
+        }
+    return result;
+    }
+    
+EXPORT_C TBool CHuiGridLayout::ChildPos(TInt aOrdinal, TPoint& aPos)
+    {
+    TBool result(EFalse);
+    THuiRealRect rect;
+    TInt childRectStatus(THuiLayoutChildRectUpdateNotNeeded);
+    childRectStatus = ChildRect(aOrdinal, rect);
+    if(childRectStatus != THuiLayoutChildRectNotImplemented)
+        {
+        result = (childRectStatus & THuiLayoutChildRectPosUpdateNeeded);
+        if(result)
+            {
+            aPos = LocalPointInPixels(rect.iTl);
+            }
+        }
+    return result;
+    }
+    
+    
+EXPORT_C TInt CHuiGridLayout::ChildRect(TInt aOrdinal, THuiRealRect& aPos)
+    {        
+    if (!ColumnCount() || !RowCount())
+        {
+        return THuiLayoutChildRectUpdateNotNeeded;
+        }
+        
+    // @todo refactorize with CHuiLayout::InnerSize
+    THuiRealRect paddingPx = PaddingInPixels(EHuiReferenceStateTarget);
+
+    // find the inner border and remove the inner paddings
+    THuiRealPoint innerSizePx = LocalPointInPixels(Size().RealTarget(), EHuiReferenceStateTarget);
+    innerSizePx.iX -= paddingPx.iTl.iX + paddingPx.iBr.iX;
+    innerSizePx.iY -= paddingPx.iTl.iY + paddingPx.iBr.iY;
+
+    // subtract the inner padding (space between each child).
+    THuiRealPoint innerPaddingPx = MetricToPixels(InnerPadding(), EHuiReferenceStateTarget);
+     
+    THuiRealPoint availablePx(innerSizePx.iX - ((ColumnCount() - 1) * innerPaddingPx.iX),
+                              innerSizePx.iY - ((RowCount() - 1) * innerPaddingPx.iY));
+
+    TPoint blockLogical = OrdinalToBlock(aOrdinal);
+    TPoint blockPosPx;
+    TSize blockSizePx;
+
+    CalculateCellInPixels(EHuiGridColumn, blockLogical.iX, availablePx.iX, blockPosPx.iX, blockSizePx.iWidth);
+    CalculateCellInPixels(EHuiGridRow, blockLogical.iY, availablePx.iY, blockPosPx.iY, blockSizePx.iHeight);    
+
+    // now add back in the inner paddings and the padding
+    blockPosPx.iX += HUI_ROUND_FLOAT_TO_INT( paddingPx.iTl.iX + (blockLogical.iX * innerPaddingPx.iX) );
+    blockPosPx.iY += HUI_ROUND_FLOAT_TO_INT( paddingPx.iTl.iY + (blockLogical.iY * innerPaddingPx.iY) );
+
+    // get metric reference, for converting between base units of this layout (from the child visual's perspective) and pixels
+    THuiRealPoint layoutRefPx = MetricReferenceForLayoutInPixels(BaseUnit().Abs()); // always target reference
+
+    // Convert the result back into child relative coordinates
+    THuiXYMetric blockPosChildMetric = BaseUnit();
+    THuiXYMetric blockSizeChildMetric = BaseUnit();
+
+    ConvertPixelsToMetricLength(blockPosChildMetric.iX, TReal32(blockPosPx.iX), layoutRefPx.iX);
+    ConvertPixelsToMetricLength(blockPosChildMetric.iY, TReal32(blockPosPx.iY), layoutRefPx.iY);
+    ConvertPixelsToMetricLength(blockSizeChildMetric.iX, TReal32(blockSizePx.iWidth), layoutRefPx.iX);
+    ConvertPixelsToMetricLength(blockSizeChildMetric.iY, TReal32(blockSizePx.iHeight), layoutRefPx.iY);
+
+    aPos.iTl.iX =  blockPosChildMetric.iX.iMagnitude;
+    aPos.iTl.iY =  blockPosChildMetric.iY.iMagnitude;
+    aPos.iBr.iX = aPos.iTl.iX + blockSizeChildMetric.iX.iMagnitude;
+    aPos.iBr.iY = aPos.iTl.iY + blockSizeChildMetric.iY.iMagnitude;
+    
+    return THuiLayoutChildRectLayoutUpdateNeeded;
+    }
+   
+   
+EXPORT_C void CHuiGridLayout::SetColumnsL(TInt aColumnCount)
+    {
+    THuiMetric defaultWeight(1.f, EHuiUnitWeight);
+    FillWeightsL(EHuiGridColumn, aColumnCount, defaultWeight);    
+    }
+   
+    
+EXPORT_C void CHuiGridLayout::SetRowsL(TInt aRowCount)
+    {
+    THuiMetric defaultWeight(1.f, EHuiUnitWeight);
+    FillWeightsL(EHuiGridRow, aRowCount, defaultWeight);    
+    }
+   
+
+EXPORT_C void CHuiGridLayout::SetColumnsL(const RArray<TInt>& aWeights)
+    {
+    TAxis& axis = iGridLayoutData->iAxes[EHuiGridColumn];
+    axis.iWeights.Reset();
+    for(TInt i = 0; i < aWeights.Count(); ++i)
+        {
+        THuiMetric weight(TReal32(aWeights[i]), EHuiUnitWeight);
+        User::LeaveIfError(axis.iWeights.Append(weight));
+        }
+    }
+    
+EXPORT_C void CHuiGridLayout::SetRowsL(const RArray<TInt>& aWeights)
+    {
+    TAxis& axis = iGridLayoutData->iAxes[EHuiGridRow];
+    axis.iWeights.Reset();
+    for(TInt i = 0; i < aWeights.Count(); ++i)
+        {
+        THuiMetric weight(TReal32(aWeights[i]), EHuiUnitWeight);
+        User::LeaveIfError(axis.iWeights.Append(weight));
+        }
+    }
+
+EXPORT_C void CHuiGridLayout::FillWeightsL(THuiGridDimension aDim, TInt aCount, const THuiMetric& aWeight)
+    {
+    if(aDim <= EHuiGridRow)
+        {
+        TAxis& axis = iGridLayoutData->iAxes[aDim];
+        axis.iWeights.Reset();
+        for(TInt i = 0; i < aCount; ++i)
+            {
+            User::LeaveIfError(axis.iWeights.Append(aWeight));
+            }
+        }
+    }
+    
+EXPORT_C void CHuiGridLayout::AppendWeightL(THuiGridDimension aDim, const THuiMetric& aWeight)
+    {
+    if(aDim <= EHuiGridRow)
+        {
+        TAxis& axis = iGridLayoutData->iAxes[aDim];
+        User::LeaveIfError(axis.iWeights.Append(aWeight));
+        }
+    }
+    
+EXPORT_C void CHuiGridLayout::InsertWeightL(THuiGridDimension aDim, const THuiMetric& aWeight, TInt aPos)
+    {
+    if(aDim <= EHuiGridRow)
+        {
+        TAxis& axis = iGridLayoutData->iAxes[aDim];
+        if(aPos < 0 || aPos >= axis.iWeights.Count())
+            {
+            User::Leave(KErrArgument);
+            }
+        else
+            {
+            User::LeaveIfError(axis.iWeights.Insert(aWeight, aPos));
+            }
+        }
+    }
+    
+EXPORT_C void CHuiGridLayout::ReplaceWeightL(THuiGridDimension aDim, const THuiMetric& aWeight, TInt aPos)
+    {
+    if(aDim <= EHuiGridRow)
+        {
+        TAxis& axis = iGridLayoutData->iAxes[aDim];
+        if(aPos < 0 || aPos >= axis.iWeights.Count())
+            {
+            User::Leave(KErrArgument);
+            }
+        else
+            {
+            axis.iWeights[aPos] = aWeight;
+            }
+        }
+    }
+    
+EXPORT_C void CHuiGridLayout::RemoveWeightL(THuiGridDimension aDim, TInt aPos)
+    {
+    if(aDim <= EHuiGridRow)
+        {
+        TAxis& axis = iGridLayoutData->iAxes[aDim];
+        if(aPos < 0 || aPos >= axis.iWeights.Count())
+            {
+            User::Leave(KErrArgument);
+            }
+        else
+            {
+            axis.iWeights.Remove(aPos);
+            }
+        }
+    }
+    
+EXPORT_C THuiMetric CHuiGridLayout::Weight(THuiGridDimension aDim, TInt aPos) const
+    {
+    THuiMetric metric(0.f, EHuiUnitWeight); 
+    if(aDim <= EHuiGridRow)
+        {
+        TAxis& axis = iGridLayoutData->iAxes[aDim];
+        if(aPos < 0 || aPos >= axis.iWeights.Count())
+            {
+            // use empty weight
+            }
+        else
+            {
+            metric = axis.iWeights[aPos];
+            }
+        }
+    return metric;
+    }
+    
+EXPORT_C TInt CHuiGridLayout::DimensionCount(THuiGridDimension aDim) const
+    {
+    TInt count = 0;
+    if(aDim <= EHuiGridRow)
+        {
+        count = iGridLayoutData->iAxes[aDim].iWeights.Count();
+        }
+    return count;
+    }
+
+EXPORT_C void CHuiGridLayout::SetExpanding(TInt aFlags)
+    {
+    iGridLayoutData->iExpansionFlags = aFlags;    
+    }
+    
+// ---------------------------------------------------------------------------
+// Function that determines if the filling order.
+// ---------------------------------------------------------------------------
+//
+TBool CHuiGridLayout::UseRightToLeftFillingOrder() const
+    {
+    return CHuiStatic::LayoutMirrored();
+    }
+
+EXPORT_C void CHuiGridLayout::GetClassName(TDes& aName) const
+    {
+    aName = _L("CHuiGridLayout");
+    }
+
+EXPORT_C THuiXYMetric CHuiGridLayout::BaseUnit() const
+    {
+    return CHuiLayout::BaseUnit();
+    }
+
+EXPORT_C CHuiVisual* CHuiGridLayout::FindTag(const TDesC8& aTag)
+    {
+    return CHuiLayout::FindTag(aTag);
+    }
+    
+EXPORT_C TInt CHuiGridLayout::Count() const
+    {
+    return CHuiLayout::Count();
+    }
+    
+EXPORT_C CHuiVisual& CHuiGridLayout::Visual(TInt aIndex) const
+    {
+    return CHuiLayout::Visual(aIndex);
+    }
+    
+EXPORT_C void CHuiGridLayout::SetPos(const THuiRealPoint& aPos, TInt aTransitionTime)
+    {
+    CHuiLayout::SetPos(aPos, aTransitionTime);
+    }
+    
+EXPORT_C void CHuiGridLayout::UpdateChildrenLayout(TInt aTransitionTime)
+    {
+    CHuiLayout::UpdateChildrenLayout(aTransitionTime);
+    }
+    
+EXPORT_C TBool CHuiGridLayout::PrepareDrawL()
+    {
+    return CHuiLayout::PrepareDrawL();
+    }
+    
+EXPORT_C void CHuiGridLayout::Draw(CHuiGc& aGc) const
+    {
+    CHuiLayout::Draw(aGc);
+    }
+    
+EXPORT_C void CHuiGridLayout::DrawSelf(CHuiGc& aGc, const TRect& aDisplayRect) const
+    {
+    CHuiLayout::DrawSelf(aGc, aDisplayRect);
+    }
+    
+EXPORT_C TBool CHuiGridLayout::Changed() const
+    {
+    return CHuiLayout::Changed();
+    }
+    
+EXPORT_C void CHuiGridLayout::ReportChanged()
+    {
+    CHuiLayout::ReportChanged();
+    }
+    
+EXPORT_C void CHuiGridLayout::ClearChanged()
+    {
+    CHuiLayout::ClearChanged();
+    }
+    
+EXPORT_C void CHuiGridLayout::NotifySkinChangedL()
+    {
+    CHuiLayout::NotifySkinChangedL();
+    }
+    
+EXPORT_C void CHuiGridLayout::ExpandRectWithContent(TRect& aRect) const
+    {
+    CHuiLayout::ExpandRectWithContent(aRect); 
+    }
+    
+EXPORT_C void CHuiGridLayout::VisualExtension(const TUid& aExtensionUid, TAny** aExtensionParams)
+    {
+    CHuiLayout::VisualExtension(aExtensionUid, aExtensionParams);
+    }
+    
+EXPORT_C void CHuiGridLayout::DumpTree() const
+    {
+    CHuiLayout::DumpTree();
+    }
+    
+EXPORT_C void CHuiGridLayout::GetInstanceName(TDes& aName) const
+    {
+    CHuiLayout::GetInstanceName(aName);
+    }
+
+EXPORT_C void CHuiGridLayout::RemoveAndDestroyAllD()
+    {
+    CHuiLayout::RemoveAndDestroyAllD();
+    }
+
+HUI_SESSION_OBJECT_IMPL_EXPORT(CHuiGridLayout, ETypeVisual)
+
+
+EXPORT_C TInt CHuiGridLayout::RowCount() const
+    {
+    return iGridLayoutData->iAxes[EHuiGridRow].iWeights.Count();
+    }
+
+EXPORT_C TInt CHuiGridLayout::ColumnCount() const
+    {
+    return iGridLayoutData->iAxes[EHuiGridColumn].iWeights.Count();
+    }
+
+   
+EXPORT_C void CHuiGridLayout::SetLayoutModeFlags(THuiGridDimension aDim, TUint aGridLayoutModeFlags)
+    {
+    if(aDim <= EHuiGridRow)
+        {
+        TAxis& axis = iGridLayoutData->iAxes[aDim];
+        TUint oldFlags = axis.iLayoutFlags;
+        
+
+        // The following flags are mutually exclusive, clear existing flags first
+        if (aGridLayoutModeFlags&EHuiGridIncreaseInnerPadding)
+            {
+            axis.iLayoutFlags &= ~EHuiGridDecreaseInnerPadding;
+            }
+        
+        if (aGridLayoutModeFlags&EHuiGridDecreaseInnerPadding)
+            {
+            axis.iLayoutFlags &= ~EHuiGridIncreaseInnerPadding;
+            }        
+
+        if (aGridLayoutModeFlags&EHuiGridIncreaseOuterPadding)
+            {
+            axis.iLayoutFlags &= ~EHuiGridDecreaseOuterPadding;
+            }
+        
+        if (aGridLayoutModeFlags&EHuiGridDecreaseOuterPadding)
+            {
+            axis.iLayoutFlags &= ~EHuiGridIncreaseOuterPadding;
+            }   
+        
+        axis.iLayoutFlags |= aGridLayoutModeFlags;
+        
+        if((oldFlags != axis.iLayoutFlags) && !(Flags() & EHuiVisualFlagFreezeLayout))
+            {
+            UpdateChildrenLayout(0);
+            }          
+        }             
+    }
+  
+EXPORT_C void CHuiGridLayout::ClearLayoutModeFlags(THuiGridDimension aDim, TUint aGridLayoutModeFlags)
+    {
+    if(aDim <= EHuiGridRow)
+        {
+        TAxis& axis = iGridLayoutData->iAxes[aDim];
+        TUint oldFlags = axis.iLayoutFlags;      
+        axis.iLayoutFlags &= ~aGridLayoutModeFlags;
+        
+        if((oldFlags != axis.iLayoutFlags) && !(Flags() & EHuiVisualFlagFreezeLayout))
+            {
+            UpdateChildrenLayout(0);
+            }                         
+        }          
+    }
+
+EXPORT_C TUint CHuiGridLayout::LayoutModeFlags(THuiGridDimension aDim)
+    {
+    if(aDim <= EHuiGridRow)
+        {
+        TAxis& axis = iGridLayoutData->iAxes[aDim];
+        return axis.iLayoutFlags;
+        }
+        
+    return 0;
+    }
+
+void CHuiGridLayout::CalculateCellInPixels(
+    THuiGridDimension aDim, 
+    TInt aIndex, 
+    TReal32 aAvailablePixels, 
+    TInt& aPos, 
+    TInt& aSize) const
+    {
+    ASSERT(aDim < EHuiGridSize);
+    
+    TAxis& axis = iGridLayoutData->iAxes[aDim]; 
+    TInt numItems = (aDim==EHuiGridColumn)?ColumnCount():RowCount();    
+    TInt itemIntegerWidths = 0;
+    TInt itemCeilingedIntegerWidths = 0;
+    TReal32 realPos;
+    TReal32 realSize;
+    TInt sumIntegerWidths;            
+    TInt sumCeilingIntegerWidths;
+    TReal32 layoutWidthPx;
+    TReal32 layoutSizePx;    
+            
+    CalculateCellInPixelsReal(aDim, aIndex, aAvailablePixels, realPos, realSize, itemIntegerWidths, itemCeilingedIntegerWidths);
+    
+    TReal32 innerPadPos = realPos;
+    
+    // Decide what to do with pixel error based on flags
+    if (axis.iLayoutFlags&EHuiGridDecreaseInnerPadding)
+        {
+        // Allow every item to grow out into the padding, this will make the padding appear smaller.
+        realSize = CEIL(realSize);             
+        }
+    else if (axis.iLayoutFlags&EHuiGridIncreaseInnerPadding)
+        {
+        // Allow every item to be floored, this will make the padding appear bigger.
+        realSize = FLOOR(realSize);             
+        }
+    else
+        {
+        // For PC-lint
+        }
+
+    if (axis.iLayoutFlags&EHuiGridIncreaseOuterPadding)            
+        {
+        // Ignore accumulated error, simply increase outer padding by the total error for the entire layout.
+        
+        // Ignore the rounded positions we have calculated, we get the pos by summing the integer widths,
+        realPos = itemIntegerWidths-FLOOR_INT(realSize);
+        
+        CalculateCellInPixelsReal(aDim, numItems-1, aAvailablePixels, layoutWidthPx, layoutSizePx, sumIntegerWidths, sumCeilingIntegerWidths);            
+        realPos += (aAvailablePixels-sumIntegerWidths)/2;
+        realSize = FLOOR(realSize);
+        }
+    else if (axis.iLayoutFlags&EHuiGridDecreaseOuterPadding)
+        {
+        // Ignore accumulated error, simply decrease outer padding by the total error for the entire layout.
+        
+        // Ignore the rounded positions we have calculated, we get the pos by summing the integer widths,
+        realPos = itemCeilingedIntegerWidths-CEIL_INT(realSize);
+        
+        CalculateCellInPixelsReal(aDim, numItems-1, aAvailablePixels, layoutWidthPx, layoutSizePx, sumIntegerWidths, sumCeilingIntegerWidths);
+        realPos += (aAvailablePixels-sumCeilingIntegerWidths)/2;   
+        realSize = CEIL(realSize);
+        }
+    else
+        {
+        // For PC-lint
+        }
+
+    realPos = ProportionalInnerOuterPadding(aDim, innerPadPos, realPos);
+    
+    aPos = TInt(realPos);
+    aSize = TInt(realSize);
+    }
+
+TReal32 CHuiGridLayout::ProportionalInnerOuterPadding(  
+    THuiGridDimension aDim,
+    TReal32 aInnerPadPos,
+    TReal32 aOuterPadPos) const
+    {
+    THuiRealPoint innerPaddingPx = MetricToPixels(InnerPadding(), EHuiReferenceStateTarget);
+    THuiRealRect outerPaddingPx = PaddingInPixels(EHuiReferenceStateTarget);
+    TAxis& axis = iGridLayoutData->iAxes[aDim]; 
+    TUint flag = axis.iLayoutFlags;    
+    TReal32 totalPadding;
+    TReal32 meanOuterPadding;
+    
+    if ( HuiUtil::RealCompare( aInnerPadPos, aOuterPadPos ) )
+        {
+        // Same pos, nothing to do.
+        return aOuterPadPos;
+        }
+    
+    if (aDim==EHuiGridColumn)
+        {
+        meanOuterPadding = (outerPaddingPx.iTl.iX+outerPaddingPx.iBr.iX)/2.0f;
+        totalPadding = innerPaddingPx.iX+meanOuterPadding;
+        }
+    else
+        {
+        meanOuterPadding = (outerPaddingPx.iTl.iY+outerPaddingPx.iBr.iY)/2.0f;
+        totalPadding = innerPaddingPx.iY+meanOuterPadding;            
+        }
+    
+    if (totalPadding && ((flag&EHuiGridIncreaseInnerPadding) && (flag&EHuiGridIncreaseOuterPadding))
+                     || ((flag&EHuiGridIncreaseInnerPadding) && (flag&EHuiGridDecreaseOuterPadding))
+                     || ((flag&EHuiGridDecreaseInnerPadding) && (flag&EHuiGridIncreaseOuterPadding))
+                     || ((flag&EHuiGridDecreaseInnerPadding) && (flag&EHuiGridDecreaseOuterPadding)))
+        {
+        // Both inner and outer padding flags are active, linearly interpolate between them based on ratio.    
+        if (aDim==EHuiGridColumn)
+            {
+            return ((innerPaddingPx.iX*aInnerPadPos + meanOuterPadding*aOuterPadPos)/totalPadding);            
+            }
+        else
+            {
+            return ((innerPaddingPx.iY*aInnerPadPos + meanOuterPadding*aOuterPadPos)/totalPadding);            
+            }
+        }
+        
+    return aOuterPadPos;
+    }  
+    
+    
+void CHuiGridLayout::CalculateCellInPixelsReal(
+    THuiGridDimension aDim, 
+    TInt aIndex, 
+    TReal32 aAvailablePixels, 
+    TReal32& aPos, 
+    TReal32& aSize,
+    TInt& aFloorPixelPos,
+    TInt& aCeilingPixelPos) const
+    {
+    // note that we will add in the inner padding later
+    // total up the pixels or weights on either side of the target block, so that we know what
+    // the total size is that we're sharing out by weight. 
+    // while we're at it we can remember the size of the target block as well (call it "mid")
+    TReal32 totalWeightsValid(0.f);
+    TReal32 totalPixelsValid(0.f);  
+    TReal32 error(0.f);     
+    TInt pixelWeight;
+    TReal32 weightWeight;    
+    
+    TAxis& axis = iGridLayoutData->iAxes[aDim];
+    TInt weightCount = axis.iWeights.Count();
+    
+    aPos = 0;
+    aSize = 0;
+    aFloorPixelPos = 0;
+    aCeilingPixelPos = 0;
+    
+    // First pass to get total weights and pixels.
+    for(TInt ii = 0; ii < weightCount; ii++)
+        {    
+        THuiMetric& weight = axis.iWeights[ii];
+                    
+        WeightFromMetric(aDim, weight, weightWeight, pixelWeight);
+        totalPixelsValid += pixelWeight;
+        totalWeightsValid += weightWeight;
+        }
+
+    // All the fixed-pixel items have been accounted for, this is
+    // what's left for distribution between the variable, weighted items.    
+    TReal32 remainderPixels = aAvailablePixels - totalPixelsValid;
+
+    // Second pass to calculate size and pos
+    for(TInt ii = 0; ii <= aIndex; ii++)
+        {
+        TReal32 nextWeight(0.f);
+        TReal32 nextPixels(0.f);
+
+        // Child visuals that are outside of the specified range of blocks 
+        // should take the weight of the last specified block.
+        THuiMetric weight(1.f, EHuiUnitWeight);
+        if(ii < weightCount)
+            {
+            weight = axis.iWeights[ii];
+            }
+        else if( weightCount ) // return weight of last element
+            {
+            weight = axis.iWeights[weightCount-1];
+            }
+        else
+            {
+            // For PC-lint
+            }
+
+        WeightFromMetric(aDim, weight, nextWeight, pixelWeight);
+        nextPixels += pixelWeight;
+
+        TReal32 width;
+        if(totalWeightsValid != 0)
+            {
+            width = (nextWeight / totalWeightsValid) * remainderPixels;
+            }
+        else
+            {
+            width = 0;
+            }
+        
+        aFloorPixelPos += FLOOR_INT(width);
+        aCeilingPixelPos += CEIL_INT(width);     
+        aFloorPixelPos += nextPixels;
+        aCeilingPixelPos += nextPixels;             
+        
+        error += FRAC(width);
+
+        if ((axis.iLayoutFlags == 0))
+            {
+            if (error >= 0.5)
+                {
+                // There is a rounding error here, so increase size if no flags forcing exact-size are set
+                error--;
+                width = CEIL(width);
+                }
+            else
+                {
+                width = FLOOR(width);
+                }
+            }
+            
+        if(ii < aIndex)
+            {
+            aPos += width;            
+            aPos += nextPixels;
+            }
+        else
+            {
+            aSize += width;
+            aSize += nextPixels;
+            }                    
+        }
+    }
+
+void CHuiGridLayout::WeightFromMetric(THuiGridDimension aDim, THuiMetric& aMetric, TReal32& aWeight, TInt& aPix) const
+    {
+    aWeight = 0.0f;
+    aPix = 0;
+    
+    switch(aMetric.iUnit)
+        {
+        case EHuiUnitWeight:
+            {
+            aWeight = aMetric.iMagnitude;
+            break;
+            }
+        case EHuiUnitPixel:
+            {
+            // slight optimization here as we know it's pixels
+            aPix = HUI_ROUND_FLOAT_TO_INT(aMetric.iMagnitude);
+            break;
+            }
+        case EHuiUnitNormalized:
+        case EHuiUnitRelativeToDisplay:
+        case EHuiUnitRelativeToMySize:
+        case EHuiUnitS60:
+            {
+            THuiRealPoint refPx = MetricToPixels(THuiXYMetric(aMetric), EHuiReferenceStateTarget);
+            aPix = (aDim == EHuiGridColumn) ? HUI_ROUND_FLOAT_TO_INT(refPx.iX) : HUI_ROUND_FLOAT_TO_INT(refPx.iY);
+            break;
+            }
+        default:
+            break;
+        }
+    }