uiacceltk/hitchcock/coretoolkit/src/HuiLayout.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiLayout.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,1254 @@
+/*
+* 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:   Implementation of CHuiLayout class. Layouts are visuals that 
+*                manage the placement of a set of child visuals.
+*
+*/
+
+
+
+#include <AknUtils.h>
+
+#include "uiacceltk/HuiLayout.h"  // Class definition
+#include "uiacceltk/HuiControl.h"
+#include "uiacceltk/HuiDrawing.h"
+#include "uiacceltk/HuiDisplay.h"
+#include "uiacceltk/HuiPanic.h"
+#include "uiacceltk/HuiUtil.h"
+#include "HuiRosterImpl.h"
+#include "huilayoutdata.h"
+
+#include "HuiFxEffect.h"
+#include "HuiRenderPlugin.h"
+#include "huicanvasgc.h"
+#include "Matrix.h"
+// 
+// methods
+//
+
+EXPORT_C CHuiLayout* CHuiLayout::AddNewL(CHuiControl& aOwnerControl,
+                                         CHuiLayout* aParentLayout)
+    {
+    CHuiLayout* layout = aOwnerControl.AppendLayoutL(EHuiLayoutTypeLayout,
+                                                     aParentLayout);
+    return layout;
+    }
+
+
+EXPORT_C CHuiLayout::CHuiLayout(MHuiVisualOwner& aOwner)
+        : CHuiVisual(aOwner)
+    {
+    }
+
+
+EXPORT_C void CHuiLayout::ConstructL()
+    {
+    CHuiVisual::ConstructL();
+    iHuiLayoutPrivateData = new (ELeave) THuiLayoutPrivateData;
+    CHuiRenderPlugin& renderplugin = CHuiStatic::Renderer();
+    iHuiLayoutPrivateData->iGc = renderplugin.CreateCanvasGcL();
+    }
+
+
+EXPORT_C CHuiLayout::~CHuiLayout()
+    {
+    if ( iHuiLayoutPrivateData ) // a Fix for OOM situations, tried to dereference NULL pointer
+    	{
+	    delete iHuiLayoutPrivateData->iScroll;
+	
+	    // Remove children in reverse order.
+	    for(TInt i = Count() - 1; i >= 0; --i)
+	        {
+	        Remove(iHuiLayoutPrivateData->iChildren[i]);
+	        }
+	    iHuiLayoutPrivateData->iChildren.Reset();
+	    delete iHuiLayoutPrivateData->iGc;
+	    delete iHuiLayoutPrivateData;
+    	}
+    }
+
+
+EXPORT_C void CHuiLayout::RemoveAndDestroyAllD()
+    {
+    // Make sure we do not re-layout during destruction
+    SetFlag( EHuiVisualFlagFreezeLayout );
+    
+    for(TInt i = Count() - 1; i >= 0; --i)
+        {
+        iHuiLayoutPrivateData->iChildren[i]->RemoveAndDestroyAllD();
+        }
+    iHuiLayoutPrivateData->iChildren.Reset();
+
+    CHuiVisual::RemoveAndDestroyAllD();
+    }
+
+
+EXPORT_C void CHuiLayout::AppendL(CHuiVisual* aVisual, TInt aLayoutTransitionTime)
+    {
+    ASSERT(aVisual != NULL);
+    __ASSERT_ALWAYS( iHuiLayoutPrivateData->iChildren.Find(aVisual) == KErrNotFound,
+                     THuiPanic::Panic(THuiPanic::ELayoutDuplicateVisual) );
+
+    User::LeaveIfError( iHuiLayoutPrivateData->iChildren.Append(aVisual) );
+    
+    CHuiLayout* oldLayout = aVisual->Layout();
+    if (oldLayout != NULL)
+    	{
+    	// If this visual is already a member of another layout, remove it from the old one first.
+    	oldLayout->Remove(aVisual);
+	    }
+	else
+	    {
+	    // if the visual is a showing as root visual before, remove it from the roster
+	    if ( aVisual->Display() )
+	        {
+	        aVisual->Display()->Roster().HideVisual( aVisual );
+	        }
+	    }
+    
+    aVisual->SetLayout(this);
+
+    // Update the visual's layout immediately.
+    if(!(Flags() & EHuiVisualFlagFreezeLayout))
+        {
+        UpdateChildrenLayout(aLayoutTransitionTime);
+        }
+
+    SetChanged();
+    }
+
+
+EXPORT_C void CHuiLayout::InsertL(CHuiVisual* aVisual, TInt aPosition, TInt aLayoutTransitionTime)
+    {
+    ASSERT(aVisual != NULL);
+    __ASSERT_ALWAYS( iHuiLayoutPrivateData->iChildren.Find(aVisual) == KErrNotFound,
+                     THuiPanic::Panic(THuiPanic::ELayoutDuplicateVisual) );
+    ASSERT((aPosition >= 0) && aPosition <= Count());
+    
+    iHuiLayoutPrivateData->iChildren.InsertL(aVisual, aPosition);
+    
+    CHuiLayout* oldLayout = aVisual->Layout();
+    if (oldLayout != NULL)
+    	{
+    	// If this visual is already a member of another layout, remove it from the old one first.
+    	oldLayout->Remove(aVisual);
+	    }
+	else
+	    {
+	    // if the visual is a showing as root visual before, remove it from the roster
+	    if ( aVisual->Display() )
+	        {
+	        aVisual->Display()->Roster().HideVisual( aVisual );
+	        }
+	    }
+
+    // Update the visual's layout immediately.
+    aVisual->SetLayout(this);
+    
+    if(!(Flags() & EHuiVisualFlagFreezeLayout))
+        {
+        UpdateChildrenLayout(aLayoutTransitionTime);
+        }
+
+    SetChanged();
+    }
+
+
+EXPORT_C void CHuiLayout::Remove(CHuiVisual* aVisual, TInt aLayoutTransitionTime)
+    {
+    TInt index = iHuiLayoutPrivateData->iChildren.Find(aVisual);
+    /*__ASSERT_DEBUG(index != KErrNotFound,
+                   THuiPanic::Panic(THuiPanic::EInternal));*/
+    if(index != KErrNotFound)
+        {
+        iHuiLayoutPrivateData->iChildren.Remove(index);
+        aVisual->SetLayout(NULL); // defect. this should check if there is a Host()->ContainerLayout()
+        
+        // If the control group of the aVisual is showing in a roster,
+        // we need to add it as the root visual of that roster
+        /*
+        for ( TInt d = 0; d < Env().DisplayCount() ; d ++ )
+            {
+            if ( (Env().Displays())[d]->Roster().Find( aVisual->Owner().ControlGroup() ) != KErrNotFound )
+                {
+                TRAP_IGNORE( (Env().Displays())[d]->Roster().ShowVisualL( aVisual ) );
+                break;
+                }
+            }*/
+
+        // Update the layout of all the children immediately.
+        if(!(Flags() & EHuiVisualFlagFreezeLayout))
+            {
+            UpdateChildrenLayout(aLayoutTransitionTime);
+            }
+
+        SetChanged();
+        }
+    }
+
+
+EXPORT_C TInt CHuiLayout::Count() const
+    {
+    return iHuiLayoutPrivateData->iChildren.Count();
+    }
+
+
+EXPORT_C CHuiVisual& CHuiLayout::Visual(TInt aIndex) const
+    {
+    return *(iHuiLayoutPrivateData->iChildren[aIndex]);
+    }
+
+
+EXPORT_C TInt CHuiLayout::FindVisual(const CHuiVisual* aVisual) const
+    {
+    for(TInt i = 0; i < Count(); ++i)
+        {
+        if(&Visual(i) == aVisual)
+            {
+            return i;
+            }
+        }
+    return KErrNotFound;
+    }
+
+
+THuiRealRect CHuiLayout::BoundingRect() const
+    {
+    THuiRealPoint min;
+    THuiRealPoint max;
+    
+    min.iX = 0;
+    min.iY = 0;
+    max.iX = 0;
+    max.iY = 0;
+    
+    TInt count = Count();
+    if(count > 0) 
+    	{
+    	min = Visual(0).Pos().Target();
+    	max = min + Visual(0).Size().Target();    	
+    	}
+
+    for(TInt i = 1; i < count; ++i)
+        {
+        THuiRealPoint tl = Visual(i).Pos().Target();
+        THuiRealPoint br = tl + Visual(i).Size().Target();
+
+        min.iX = Min(min.iX, tl.iX);
+        min.iY = Min(min.iY, tl.iY);
+        max.iX = Max(max.iX, br.iX);
+        max.iY = Max(max.iY, br.iY);
+        }
+
+    return THuiRealRect(min, max);
+    }
+    
+    
+EXPORT_C THuiRealSize CHuiLayout::InnerSize() const __SOFTFP
+    {
+    // Determine the size of this layout in pixels.
+    THuiRealSize innerSizeChild = Size().RealTarget().AsSize(); // not correct units, but will work as fallback value if base unit is in pixels
+    THuiRealPoint innerSizePx = LocalPointInPixels(Size().RealTarget(), EHuiReferenceStateTarget);
+
+    // Subtract outer paddings.
+    THuiRealRect paddingInPixels = PaddingInPixels(EHuiReferenceStateTarget);
+    innerSizePx.iX -= paddingInPixels.iTl.iX + paddingInPixels.iBr.iX;
+    innerSizePx.iY -= paddingInPixels.iTl.iY + paddingInPixels.iBr.iY;
+    
+    // Convert the result into base units of *this* layout.
+    CHuiVisual* child = 0;
+    if (iHuiLayoutPrivateData->iChildren.Count())
+        {
+        child = iHuiLayoutPrivateData->iChildren[0]; // get the first child, if there isn't one, then nothing to do anyway
+        }
+    if(child)
+        {
+        innerSizeChild = child->PixelPointInUnits(innerSizePx, BaseUnit().Abs(), EHuiReferenceStateTarget).AsSize();
+        }
+
+    return innerSizeChild;    
+    }
+
+
+EXPORT_C THuiRealPoint CHuiLayout::InnerTopLeft() const __SOFTFP
+    {
+    THuiRealPoint topLeftChild(0, 0);
+    CHuiVisual* child = 0;
+    if (iHuiLayoutPrivateData->iChildren.Count())
+        {
+        child = iHuiLayoutPrivateData->iChildren[0]; // get the first child, if there isn't one, then nothing to do anyway
+        }
+    if(child)
+        {
+        topLeftChild = child->PixelPointInUnits(PaddingInPixels().iTl, BaseUnit().Abs(), EHuiReferenceStateTarget);
+        }
+    return topLeftChild;
+    }
+
+
+EXPORT_C void CHuiLayout::SetSize(const THuiRealSize& aSize, TInt aTransitionTime)
+    {
+    CHuiVisual::SetSize(aSize, aTransitionTime);
+
+    // The default layout does not need to update its children.
+    }
+
+
+EXPORT_C void CHuiLayout::UpdateChildrenLayout(TInt aTransitionTime)
+    {
+    // Update the layout of all children.
+    TInt count = Count();
+    for(TInt i = 0; i < count; ++i)
+        {
+        //Ignore inactive child visuals
+        if ( iHuiLayoutPrivateData->iChildren[i]->Flags() & EHuiVisualFlagInactive )
+        	{
+        	continue;
+        	}
+        UpdateChildLayout(i, aTransitionTime);
+        }
+
+    CHuiVisual::UpdateChildrenLayout(aTransitionTime);
+
+    // Report that the layout of this layout visual has been fully updated.
+    ReportLayoutUpdate();
+    }
+
+
+EXPORT_C void CHuiLayout::UpdateChildLayout(TInt aIndex, TInt aTransitionTime)
+    {
+    THuiRealRect rect;
+    TSize size;
+    TPoint pos;
+    TInt ordinal = ChildOrdinal(aIndex);
+    CHuiVisual* child = iHuiLayoutPrivateData->iChildren[aIndex];
+    TInt flags = child->Flags();
+
+    TInt transitionTime = aTransitionTime;
+
+    if(flags & EHuiVisualFlagManualTransitionTime)
+        {
+        // override the parent's transition time with our local one.
+        transitionTime = TransitionTime();
+        }
+
+    // if either flag is missing, call child rect...
+    TBool bothManual = (flags & EHuiVisualFlagManualPosition) && (flags & EHuiVisualFlagManualSize);
+    if(!bothManual)
+        {
+        TInt childRectStatus = ChildRect(ordinal, rect);
+        if(childRectStatus != THuiLayoutChildRectNotImplemented)
+            {
+            if(!(flags & EHuiVisualFlagManualPosition) && (childRectStatus & THuiLayoutChildRectPosUpdateNeeded))
+                {
+                child->SetPos(rect.iTl, transitionTime);
+                }
+            if(!(flags & EHuiVisualFlagManualSize) && (childRectStatus & THuiLayoutChildRectSizeUpdateNeeded))
+                {
+                child->SetSize(rect.Size(), transitionTime);
+                }
+            }
+        else
+            {
+            if(!(flags & EHuiVisualFlagManualPosition) && ChildPos(ordinal, pos))
+                {
+                child->SetPos(pos, transitionTime);
+                }
+            if(!(flags & EHuiVisualFlagManualSize) && ChildSize(ordinal, size))
+                {
+                child->SetSize(size, transitionTime);
+                }
+            }
+        }
+    child->ReportLayoutUpdate();
+    }
+
+
+EXPORT_C TInt CHuiLayout::ChildOrdinal(TInt aIndex)
+    {
+    return aIndex;
+    }
+
+
+EXPORT_C TBool CHuiLayout::ChildSize(TInt /*aOrdinal*/, TSize& /*aSize*/)
+    {
+    // The default layout doesn't constrain the sizes of the children.
+    return EFalse;
+    }
+
+EXPORT_C TBool CHuiLayout::ChildPos(TInt /*aOrdinal*/, TPoint& /*aPos*/)
+    {
+    // The default layout lets the children position themselves.
+    return EFalse;
+    }
+
+EXPORT_C TInt CHuiLayout::ChildRect(TInt /*aOrdinal*/, THuiRealRect& /*aPos*/)
+    {
+    // The default layout lets the children position themselves.
+    return THuiLayoutChildRectNotImplemented;
+    }
+
+
+EXPORT_C void CHuiLayout::SetInnerPadding(const TPoint& aInnerPadding)
+    {
+    iHuiLayoutPrivateData->iInnerPadding.iX = THuiMetric(aInnerPadding.iX, EHuiUnitPixel);
+    iHuiLayoutPrivateData->iInnerPadding.iY = THuiMetric(aInnerPadding.iY, EHuiUnitPixel);
+    SetChanged();
+    }
+
+
+EXPORT_C void CHuiLayout::SetInnerPadding(const THuiXYMetric& aInnerPadding)
+    {
+    iHuiLayoutPrivateData->iInnerPadding = aInnerPadding;
+    SetChanged();
+    }
+
+
+EXPORT_C const THuiXYMetric& CHuiLayout::InnerPadding() const
+    {
+    return iHuiLayoutPrivateData->iInnerPadding;
+    }
+    
+
+EXPORT_C THuiRealPoint CHuiLayout::InnerPaddingInBaseUnits() const __SOFTFP
+    {
+    THuiRealPoint innerPaddingPx = MetricToPixels(iHuiLayoutPrivateData->iInnerPadding, EHuiReferenceStateTarget);
+    return PixelPointInUnits(innerPaddingPx, BaseUnit().Abs(), EHuiReferenceStateTarget);    
+    }
+
+
+EXPORT_C TInt CHuiLayout::HorizontalInnerPadding() const
+    {
+    return 0; //iHuiLayoutPrivateData->iXPadding;
+    }
+
+
+EXPORT_C TInt CHuiLayout::VerticalInnerPadding() const
+    {
+    return 0; //iHuiLayoutPrivateData->iYPadding;
+    }
+    
+
+EXPORT_C TBool CHuiLayout::PrepareDrawL() 
+    {
+    if (Flags() & EHuiVisualFlagDrawOnlyAsExternalContent)
+    	{
+   	    // This is used only as external content visual. Return now if we are not currently drawing
+   	    // external content.
+    	if (!Display() || !Display()->RosterImpl().IsDrawingExternalContent())
+    		{
+			return ETrue;
+    		}
+    	}
+
+    // The layout itself is invisible. Only its children can be seen.
+    TInt count = Count();
+    for(TInt i = 0; i < count; ++i)
+        {
+        CHuiVisual* visual = iHuiLayoutPrivateData->iChildren[i];
+        //Ignore inactive child visuals
+        if ( visual->Flags()& EHuiVisualFlagInactive )
+        	{
+        	continue; 
+        	}
+        TBool successfullyPrepared = ETrue;
+        TRAPD(err, successfullyPrepared = visual->PrepareDrawL());
+        if (err != KErrNone)
+            {
+            // Handle the error by calling the visual owner
+            // errorhandling callback
+            visual->Owner().VisualPrepareDrawFailed(*visual, err);
+            return EFalse;
+            }
+        if (!successfullyPrepared) 
+	        {
+	        // we can stop preparing the rest of the children
+	        // if one prepare failed (we won't be drawing anything 
+	        // anyway)
+	        
+	        // also if the prepare failed but there was not a leave,
+	        // we assume it was already handled 
+	        return EFalse;
+	        }
+        }
+    return ETrue;
+    }
+
+
+EXPORT_C void CHuiLayout::Draw(CHuiGc& aGc) const
+    {
+    if (Flags() & EHuiVisualFlagDrawOnlyAsExternalContent)
+    	{
+   	    // This is used only as external content visual. Return now if we are not currently drawing
+   	    // external content.
+    	if (!Display() || !Display()->RosterImpl().IsDrawingExternalContent())
+    		{
+			return;
+    		}
+    	}
+
+    if(iOpacity.Now() <= EPSILON && (Effect() && !Effect()->IsSemitransparent()))
+        {
+        // This will not be visible due to being completely transparent.
+        return;
+        }
+
+    if (( IsDelayedEffectSource()||Freezed() ) && StoredRenderBuffer())
+        {
+        DrawStoredBitmap(aGc);        
+        return;
+        }
+    if (!HasActiveChilderen() && !Brushes() && !Effect())
+        {
+        // No children, no brushes just return.
+        return;            
+        }
+    
+    
+    /** @todo  Wouldn't it be possible to just extend CHuiVisual::Draw()
+               instead of redefining the entire method? */
+
+    THuiRealRect area = DisplayRect();
+
+    // Apply local transformation.
+    EnterLocalProjection(aGc, ETrue, 0.f, &area);
+    Transform(aGc, ETrue, &area);
+
+    DrawBrushes(aGc, EHuiBrushLayerBackground);
+
+    if(Clipping())
+        {
+        // @todo  Clipping not going to work if there is a transformation?
+        // Layout clipping is not affected by transformation.
+        aGc.Enable(CHuiGc::EFeatureClipping);
+        aGc.PushClip();
+        aGc.Clip(area);
+        }
+
+    // Can we draw effect
+    TBool canUseEffectDrawing = Effect() && !LoadingEffect();
+
+    // Flag to know what we did
+    TBool didDrawEffect = EFalse;
+    
+    if (canUseEffectDrawing)
+        {
+        // Note that EHuiVisualFlagOpaqueHint improves performance a lot in cached effect drawing 
+        TBool transparent = !(Flags() & EHuiVisualFlagOpaqueHint) && iOpacity.Now() < 1.0f;
+        TBool refreshCache = Changed();                
+        didDrawEffect =  Effect()->CachedDraw(aGc, area, refreshCache, !transparent);
+        }
+    
+    if ( !didDrawEffect )
+        {
+        // huilayout does not draw itself, only children.
+        }
+    else
+        {
+        // Effect was drawn, OpenGLES/OpenVG may be in different state than what Gc thinks so we restore it.
+        aGc.RestoreState();        
+        }
+    
+    if ( !didDrawEffect || (didDrawEffect && !EffectIsAppliedToChildren()))
+        {
+        // The layout itself is invisible. Only its children can be seen.
+        TBool afterOthers = EFalse;
+        const TInt count = Count();
+        for(TInt i = 0; i < count; ++i)
+            {
+            CHuiVisual* visual = iHuiLayoutPrivateData->iChildren[i];
+            //Ignore inactive child visuals
+            if ( visual->Flags()& EHuiVisualFlagInactive )
+                {
+                continue; 
+                }
+            if(visual->Flags() & EHuiVisualFlagDrawAfterOthers)
+                {
+                afterOthers = ETrue;
+                continue;
+                }
+
+            // @todo  No need to draw children that won't be visible.
+            visual->Draw(aGc);
+            }       
+        if(afterOthers)
+            {
+            for(TInt i = 0; i < count; ++i)
+                {
+                if(iHuiLayoutPrivateData->iChildren[i]->Flags() & EHuiVisualFlagDrawAfterOthers)
+                    {
+                    iHuiLayoutPrivateData->iChildren[i]->Draw(aGc);        
+                    }
+                }
+            }
+        }
+
+
+    if(Clipping())
+        {
+        // Restore original clipping rectangle.
+        aGc.PopClip();
+        }
+
+
+    DrawBrushes(aGc, EHuiBrushLayerForeground);
+
+    // Restore original transformation.
+    Transform(aGc, EFalse);
+    EnterLocalProjection(aGc, EFalse);
+    }
+
+
+EXPORT_C void CHuiLayout::ReportChanged()
+    {
+    // Report changes in the layout itself.
+    CHuiVisual::ReportChanged();
+
+    // Notify the display that the visual's area should be redrawn.
+    CHuiDisplay* display = NULL;
+
+    // Select active display, fallback to own display.
+    // For scaled tv-out cloning the active display takes care of scaling direty areas too. 
+    if (iOwner && iOwner->Env().CurrentDisplay())
+        {
+        display = iOwner->Env().CurrentDisplay();    
+        }
+    else
+        {
+        display = Display();    
+        }
+
+    if (display && !display->IsDirtyScanNeeded())
+        {
+        return;    
+        }        
+
+    if (display && display->UseTransformedDirtyRegions())
+        {
+        THuiRealRect displayRect = DisplayRect();
+        EnterLocalProjection(*display->Gc(), ETrue, 0.f, &displayRect);
+        Transform(*display->Gc(), ETrue, &displayRect);
+        }
+
+        
+    TInt count = Count();
+    for(TInt i = 0; i < count; ++i)
+        {        
+        if (display && !display->IsDirtyScanNeeded())
+            {
+            break;    
+            }        
+        //Ignore inactive child visuals
+        if ( iHuiLayoutPrivateData->iChildren[i]->Flags()& EHuiVisualFlagInactive )
+        	{
+        	continue;
+        	}
+        iHuiLayoutPrivateData->iChildren[i]->ReportChanged();     
+        }
+        
+    if (display && display->UseTransformedDirtyRegions())
+        {
+        EnterLocalProjection(*display->Gc(), EFalse);
+        Transform(*display->Gc(), EFalse);                
+        }
+    }
+
+
+EXPORT_C TBool CHuiLayout::Changed() const
+    {
+    if(CHuiVisual::Changed())
+        {
+        return ETrue;
+        }
+    if(iHuiLayoutPrivateData->iScroll)
+        {
+        return iHuiLayoutPrivateData->iScroll->iOffset.Changed();
+        }
+    return EFalse;
+    }
+
+
+EXPORT_C void CHuiLayout::ClearChanged()
+    {
+    CHuiVisual::ClearChanged();
+    
+    // Clear the change flags of children as well.
+    TInt count = Count();
+    for(TInt i = 0; i < count; ++i)
+        {
+        if (Flags() & EHuiVisualFlagInactive)
+            {
+            // No need to clear inactive children
+            continue;
+            }
+        iHuiLayoutPrivateData->iChildren[i]->ClearChanged();
+        }
+        
+    if(iHuiLayoutPrivateData->iScroll)
+        {
+        iHuiLayoutPrivateData->iScroll->iOffset.ClearChanged();
+        }
+    }
+
+EXPORT_C void CHuiLayout::SetBaseUnit(const THuiMetric& aBaseUnit)
+    {
+    iHuiLayoutPrivateData->iBaseUnit.iX = aBaseUnit;
+    iHuiLayoutPrivateData->iBaseUnit.iY = aBaseUnit;
+    SetChanged();
+    }
+    
+EXPORT_C void CHuiLayout::SetBaseUnit(const THuiXYMetric& aBaseUnit)
+    {
+    iHuiLayoutPrivateData->iBaseUnit = aBaseUnit;
+    SetChanged();
+    }
+
+
+EXPORT_C THuiXYMetric CHuiLayout::BaseUnit() const
+    {
+    THuiXYMetric metric(iHuiLayoutPrivateData->iBaseUnit);
+    if((Flags() & EHuiVisualFlagAutomaticLocaleMirroringEnabled) && CHuiStatic::LayoutMirrored())
+        {
+        metric.iX.iMagnitude = -metric.iX.iMagnitude;
+        }
+    return metric;
+    }
+
+
+EXPORT_C void CHuiLayout::EnableScrollingL(TBool aScrolling)
+    {
+    if(iHuiLayoutPrivateData->iScroll && !aScrolling)
+        {
+        // Disable scrolling.
+        delete iHuiLayoutPrivateData->iScroll;
+        iHuiLayoutPrivateData->iScroll = NULL;
+        }
+    else if(!iHuiLayoutPrivateData->iScroll && aScrolling)
+        {
+        // Enable scrolling.
+        iHuiLayoutPrivateData->iScroll = new (ELeave) TScrollState();
+        }
+    else
+        {
+        // for PC lint
+        }
+    }
+
+
+EXPORT_C TBool CHuiLayout::Scrolling() const
+    {
+    return iHuiLayoutPrivateData->iScroll != 0;
+    }
+
+
+EXPORT_C THuiTimedPoint& CHuiLayout::ScrollOffset()
+    {
+    __ASSERT_ALWAYS(iHuiLayoutPrivateData->iScroll,
+                    THuiPanic::Panic(THuiPanic::ELayoutNotScrolling));
+    return iHuiLayoutPrivateData->iScroll->iOffset;
+    }
+
+
+EXPORT_C const THuiTimedPoint& CHuiLayout::ScrollOffset() const
+    {
+    __ASSERT_ALWAYS(iHuiLayoutPrivateData->iScroll,
+                    THuiPanic::Panic(THuiPanic::ELayoutNotScrolling));
+    return iHuiLayoutPrivateData->iScroll->iOffset;
+    }
+
+
+EXPORT_C void CHuiLayout::SetScrollOffsetInBaseUnits(const THuiRealPoint& aOffset, TInt aTransitionTime)
+    {
+    // Pass information directly to the scroll offset
+    ScrollOffset().Set(aOffset, aTransitionTime);
+    }
+
+
+EXPORT_C TSize CHuiLayout::VirtualSize() const
+    {
+    __ASSERT_ALWAYS(iHuiLayoutPrivateData->iScroll,
+                    THuiPanic::Panic(THuiPanic::ELayoutNotScrolling));
+    return iHuiLayoutPrivateData->iScroll->iVirtualSize;
+    }
+
+
+EXPORT_C TInt
+CHuiLayout::EffectiveLayoutOrdinal(const CHuiVisual& aVisual) const
+    {
+    TInt ordinal = 0;
+
+    TInt count = Count();
+    for(TInt i = 0; i < count; ++i)
+        {
+        if(iHuiLayoutPrivateData->iChildren[i] == &aVisual)
+            {
+            return ordinal;
+            }
+
+        // The visuals that are laid out completely manually do not affect
+        // the layout ordinal.
+        if((iHuiLayoutPrivateData->iChildren[i]->Flags() & EHuiVisualFlagManualLayout) !=
+           EHuiVisualFlagManualLayout)
+            {
+            ++ordinal;
+            }
+        }
+
+    THuiPanic::Panic(THuiPanic::ELayoutChildVisualNotFound);
+    return 0;
+    }
+
+
+EXPORT_C void CHuiLayout::Reorder(CHuiVisual& aVisual, TInt aPosition, TInt aLayoutTransitionTime)
+    {
+    TInt index = FindVisual(&aVisual);
+    if(index != aPosition)
+        {
+        __ASSERT_ALWAYS( aPosition >= 0 && aPosition < Count(),
+                         THuiPanic::Panic(THuiPanic::ELayoutInvalidChildPosition) );
+        __ASSERT_ALWAYS( index != KErrNotFound, 
+                         THuiPanic::Panic(THuiPanic::ELayoutChildVisualNotFound) );
+
+        // Move the children around in the array, so that aVisual ends up
+        // at aPosition.
+        TInt dir = (aPosition > index? +1 : -1);
+        for(TInt i = index; i != aPosition; i += dir)
+            {
+            iHuiLayoutPrivateData->iChildren[i] = iHuiLayoutPrivateData->iChildren[i + dir];
+            }
+        iHuiLayoutPrivateData->iChildren[aPosition] = &aVisual;        
+        SetChanged();
+        }
+
+    if(!(Flags() & EHuiVisualFlagFreezeLayout))
+        {
+        UpdateChildrenLayout(aLayoutTransitionTime);
+        }    
+    }
+
+
+EXPORT_C void CHuiLayout::MoveVisualToFront(CHuiVisual& aVisual, TInt aLayoutTransitionTime)
+    {
+    Reorder(aVisual, Count() - 1, aLayoutTransitionTime);
+    }
+
+
+EXPORT_C void CHuiLayout::MoveVisualToBack(CHuiVisual& aVisual, TInt aLayoutTransitionTime)
+    {
+    Reorder(aVisual, 0, aLayoutTransitionTime);
+    }
+
+
+EXPORT_C void CHuiLayout::DumpTree() const
+    {
+    // Dump children.
+    TBuf<100> myName;
+    TBuf<100> childName;
+
+    CHuiVisual::DumpTree();
+
+    GetInstanceName(myName);
+
+    TInt count = Count();
+    for(TInt i = 0; i < count; ++i)
+        {
+        iHuiLayoutPrivateData->iChildren[i]->GetInstanceName(childName);
+        CHuiStatic::Printf(_L("%S -> %S;"), &myName, &childName);
+
+        iHuiLayoutPrivateData->iChildren[i]->DumpTree();
+        }
+    }
+
+
+EXPORT_C void CHuiLayout::NotifySkinChangedL()
+    {
+    TInt count = Count();
+    for(TInt i = 0; i < count; ++i)
+        {
+        //Ignore inactive child visuals
+        if ( iHuiLayoutPrivateData->iChildren[i]->Flags()& EHuiVisualFlagInactive )
+        	{
+        	continue; 
+        	}
+        iHuiLayoutPrivateData->iChildren[i]->NotifySkinChangedL();
+        }
+    }
+
+
+EXPORT_C CHuiVisual* CHuiLayout::FindTag(const TDesC8& aTag)
+    {
+    // Check self first.
+    CHuiVisual* result = CHuiVisual::FindTag(aTag);
+    if(result)
+        {
+        return result;
+        }
+
+    // Check children.
+    TInt i;
+    TInt count = Count();
+    for(i = 0; i < count; ++i)
+        {
+        result = iHuiLayoutPrivateData->iChildren[i]->FindTag(aTag);
+        if(result)
+            {
+            return result;
+            }
+        }
+
+    // Could not find it.
+    return NULL;
+    }
+
+
+EXPORT_C void CHuiLayout::SetTransitionTime(TInt aTransitionTime)
+    {
+    iHuiLayoutPrivateData->iTransitionTime = aTransitionTime;
+    }
+
+
+EXPORT_C TInt CHuiLayout::TransitionTime() const
+    {
+    return iHuiLayoutPrivateData->iTransitionTime;
+    }
+
+EXPORT_C THuiRealPoint CHuiLayout::MetricReferenceForLayoutInPixels(const CHuiLayout* /*aLayout*/, const THuiXYMetric& aMetric) const __SOFTFP
+    {
+    return MetricReferenceForLayoutInPixels(aMetric);
+    }
+    
+/*
+ * can be used by a layout to convert a pixel value into
+ * its own units as if from a child visual's frame of reference
+ *
+ * @todo this needs refactoring with CHuiVisual::MetricReferenceInPixels
+ */
+EXPORT_C THuiRealPoint CHuiLayout::MetricReferenceForLayoutInPixels(const THuiXYMetric& aMetric) const __SOFTFP
+    {
+    THuiRealPoint refSizePx(0.f, 0.f);
+    
+    // if weights are used in this context, treat them as normalized units
+    TInt xUnit = (aMetric.iX.iUnit == EHuiUnitWeight) ? EHuiUnitNormalized : aMetric.iX.iUnit;
+    TInt yUnit = (aMetric.iY.iUnit == EHuiUnitWeight) ? EHuiUnitNormalized : aMetric.iY.iUnit;
+    
+    // For normalized units, the reference is the parent size in pixels.
+    if(xUnit == EHuiUnitNormalized || yUnit == EHuiUnitNormalized ||
+       xUnit == EHuiUnitParentWidth || yUnit == EHuiUnitParentWidth ||
+       xUnit == EHuiUnitParentHeight || yUnit == EHuiUnitParentHeight)        
+        {
+        THuiRealPoint sizePx(0.f, 0.f);
+        
+        // Determine the size of this layout in pixels.
+        if(Layout())
+            {
+            // Recursive fun. We don't want to do this more than once.
+            // (LocalPointInPixels => MetricsToPixels => MetricReferenceInPixels => LocalPointInPixels)
+            sizePx = LocalPointInPixels(Size().RealTarget(), EHuiReferenceStateTarget);
+            }
+        else if(Display())
+            {
+            // @todo Jaakko please code review this change!
+//            sizePx = Display()->Size().AsPoint();
+            sizePx = Display()->VisibleArea().Size().AsPoint();
+            }
+        else
+            {
+            // For PC-lint
+            }
+            
+        if(xUnit == EHuiUnitNormalized || xUnit == EHuiUnitParentWidth)
+            {
+            refSizePx.iX = sizePx.iX;
+            }
+        else if(xUnit == EHuiUnitParentHeight)
+            {
+            refSizePx.iX = sizePx.iY;
+            }
+        else
+            {
+            // For PC-lint
+            }
+
+        if(yUnit == EHuiUnitNormalized || yUnit == EHuiUnitParentHeight)
+            {
+            refSizePx.iY = sizePx.iY;
+            }
+        else if(yUnit == EHuiUnitParentWidth)
+            {
+            refSizePx.iY = sizePx.iX;
+            }
+        else
+            {
+            // For PC-lint
+            }
+        }
+
+    // Display-relative units are always relative to the display where the visual is on.
+    if(xUnit == EHuiUnitRelativeToDisplay && Display())
+        {
+        refSizePx.iX = Display()->VisibleArea().Width();
+        }
+    if(yUnit == EHuiUnitRelativeToDisplay && Display())
+        {
+        refSizePx.iY = Display()->VisibleArea().Height();
+        }        
+        
+    // For relative to my size units, the reference is the size of this visual in pixels.
+    if(xUnit == EHuiUnitRelativeToMySize || yUnit == EHuiUnitRelativeToMySize ||
+        xUnit == EHuiUnitMyWidth || yUnit == EHuiUnitMyWidth ||
+        xUnit == EHuiUnitMyHeight || yUnit == EHuiUnitMyHeight ||
+        xUnit == EHuiUnitMyDimensionAverage || yUnit == EHuiUnitMyDimensionAverage)
+        {
+        THuiRealPoint sizePx(0.f, 0.f);
+        if(Layout())
+            {
+            // Recursive fun. We don't want to do this more than once.
+            // (MetricsToPixels => MetricReferenceInPixels)
+            sizePx = MetricToPixels(LocalBaseUnit().Abs() * Size().RealTarget(), EHuiReferenceStateTarget);
+            }
+        else if(Display())
+            {
+            sizePx = Display()->VisibleArea().Size().AsPoint();
+            }
+        else
+            {
+            // For PC-lint
+            }
+        
+        if(xUnit == EHuiUnitRelativeToMySize || xUnit == EHuiUnitMyWidth)
+            {
+            refSizePx.iX = sizePx.iX;
+            }
+        else if(xUnit == EHuiUnitMyHeight)
+            {
+            refSizePx.iX = sizePx.iY;
+            }
+        else
+            {
+            // For PC-lint
+            }
+        
+        if(yUnit == EHuiUnitRelativeToMySize || yUnit == EHuiUnitMyHeight)
+            {
+            refSizePx.iY = sizePx.iY;
+            }
+        else if(yUnit == EHuiUnitMyWidth)
+            {
+            refSizePx.iY = sizePx.iX;
+            }
+        else
+            {
+            // For PC-lint
+            }
+
+        if( xUnit == EHuiUnitMyDimensionAverage ||
+      	    yUnit == EHuiUnitMyDimensionAverage )
+            {
+            TReal32 average = (sizePx.iX + sizePx.iY) / 2;
+            if(xUnit == EHuiUnitMyDimensionAverage)
+      	        {
+                refSizePx.iX = average;
+                }
+            if(yUnit == EHuiUnitMyDimensionAverage)
+                {           
+                refSizePx.iY = average;
+                }
+            }
+        }
+                
+    // S60 platform units are specific to the display where the visual is on.
+    if(xUnit == EHuiUnitS60 && Display())
+        {
+        refSizePx.iX = Display()->UnitValue();
+        }
+    if(yUnit == EHuiUnitS60 && Display())
+        {
+        refSizePx.iY = Display()->UnitValue();
+        }
+
+    return refSizePx;        
+    }
+   
+EXPORT_C void CHuiLayout::ExpandRectWithContent(TRect& aRect) const
+    {
+    // Expand with scroll offset
+    if ( iHuiLayoutPrivateData->iScroll )
+        {
+        const TPoint scrollOffset = LocalPointInPixels(iHuiLayoutPrivateData->iScroll->iOffset.RealNow(), EHuiReferenceStateNow );
+        if ( scrollOffset.iX > 0 )
+            {
+            aRect.iTl.iX -= scrollOffset.iX;
+            }
+        if ( scrollOffset.iX < 0 )
+            {
+            aRect.iBr.iX -= scrollOffset.iX;
+            }
+        if ( scrollOffset.iY > 0 )
+            {
+            aRect.iTl.iY -= scrollOffset.iY;
+            }
+        if ( scrollOffset.iY < 0 )
+            {
+            aRect.iBr.iY -= scrollOffset.iY;
+            }
+        }
+    
+    CHuiVisual::ExpandRectWithContent( aRect );
+    }
+
+EXPORT_C void CHuiLayout::VisualExtension(const TUid& aExtensionUid, TAny** aExtensionParams)
+    {
+    CHuiVisual::VisualExtension(aExtensionUid, aExtensionParams);
+    }
+
+EXPORT_C void CHuiLayout::SetPos(const THuiRealPoint& aPos, TInt aTransitionTime)
+    {
+    CHuiVisual::SetPos(aPos,aTransitionTime);
+    }
+
+void CHuiLayout::DrawStoredBitmap(CHuiGc &aGc) const
+    {
+    if (!Display()) return;
+    CHuiCanvasGc& gc = *iHuiLayoutPrivateData->iGc;
+    gc.SetGc(aGc);
+    gc.SetDefaults();
+    gc.PushTransformationMatrix();
+    
+    //TInt w = displayArea.Width();
+    TRect displayArea = Display()->VisibleArea();
+    TInt h = displayArea.Height();
+
+    // Pixels are upside down in OpenVG canvas render buffer
+    if (CHuiStatic::Env().Renderer() == EHuiRendererVg10)
+        {
+        TInt height = h;
+        //if (relativeOrientation == CHuiGc::EOrientationCW90 || relativeOrientation == CHuiGc::EOrientationCCW90)
+        //    {
+        //    height = w;    
+        //    }            
+        gc.Translate(0.0f, height, 0.0f);            
+        gc.Scale(1.f, -1.f, 1.f);
+        }
+    
+    THuiRealPoint dest_point = DisplayRect().iTl;
+    CHuiCanvasRenderBuffer *stored = StoredRenderBuffer();
+    gc.DrawImage(*stored, dest_point); 
+
+    gc.PopTransformationMatrix();
+
+    }
+
+EXPORT_C void CHuiLayout::DrawSelf(CHuiGc& aGc, const TRect& aDisplayRect) const
+    {
+    if (( IsDelayedEffectSource()||Freezed() ) && StoredRenderBuffer())
+        {
+        DrawStoredBitmap(aGc);        
+        return;
+        }
+
+    if( Effect() && EffectIsAppliedToChildren() )
+        {
+        // The layout itself is invisible. Only its children can be seen.
+        TBool afterOthers = EFalse;
+        const TInt count = Count();
+        for(TInt i = 0; i < count; ++i)
+            {
+            CHuiVisual* visual = iHuiLayoutPrivateData->iChildren[i];
+            //Ignore inactive child visuals
+            if ( visual->Flags()& EHuiVisualFlagInactive )
+                {
+                continue; 
+                }
+            if(visual->Flags() & EHuiVisualFlagDrawAfterOthers)
+                {
+                afterOthers = ETrue;
+                continue;
+                }
+                
+            // @todo  No need to draw children that won't be visible.
+            visual->Draw(aGc);
+            }       
+        if(afterOthers)
+            {
+            for(TInt i = 0; i < count; ++i)
+                {
+                if(iHuiLayoutPrivateData->iChildren[i]->Flags() & EHuiVisualFlagDrawAfterOthers)
+                    {
+                    iHuiLayoutPrivateData->iChildren[i]->Draw(aGc);        
+                    }
+                }
+            }
+        }
+    else
+        {
+        CHuiVisual::DrawSelf(aGc, aDisplayRect);
+        }
+    }
+
+EXPORT_C TReal32 CHuiLayout::BrushOpacity() const __SOFTFP
+    {
+    return CHuiVisual::BrushOpacity();
+    }
+
+EXPORT_C THuiRealRect CHuiLayout::BrushRect() const __SOFTFP
+    {
+    return CHuiVisual::BrushRect();
+    }
+
+
+EXPORT_C CHuiSkin& CHuiLayout::BrushSkin() const
+    {
+    return CHuiVisual::BrushSkin();
+    }
+
+HUI_SESSION_OBJECT_IMPL_EXPORT(CHuiLayout, ETypeVisual)
+
+EXPORT_C void CHuiLayout::GetInstanceName(TDes& aName) const
+    {
+    CHuiVisual::GetInstanceName(aName);
+    }
+
+
+EXPORT_C void CHuiLayout::GetClassName(TDes& aName) const
+    {
+    aName = _L("CHuiLayout");
+    }
+
+TBool CHuiLayout::HasActiveChilderen() const
+    {
+    TBool hasActiveChildren = EFalse;
+    const TInt count = Count();
+    for(TInt i = 0; i < count; ++i)
+        {
+        CHuiVisual* visual = iHuiLayoutPrivateData->iChildren[i];
+        if (!(visual->Flags()& EHuiVisualFlagInactive ))
+            {
+            hasActiveChildren = ETrue;
+            break;
+            }
+        }    
+    return hasActiveChildren;    
+    }
+
+TBool CHuiLayout::EffectIsAppliedToChildren() const
+    {
+    if (Effect() && !LoadingEffect() && !(Effect()->EffectFlags() & KHuiFxEffectExcludeChildrenFlag))
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }    
+    }