diff -r 000000000000 -r f72a12da539e idlehomescreen/xmluirendering/uiengine/src/xnuiengineimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/idlehomescreen/xmluirendering/uiengine/src/xnuiengineimpl.cpp Thu Dec 17 08:40:49 2009 +0200 @@ -0,0 +1,10024 @@ +/* +* Copyright (c) 2002-2008 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: Layout calculation and UI rendering mechanism implementations. +* +*/ + + +// System includes +#include +#include +#include +#include + +// User includes +#include "xnuiengine.h" +#include "xnuiengineimpl.h" +#include "xnuistatelistener.h" +#include "xnpointerarray.h" +#include "xnodt.h" +#include "xndomlist.h" +#include "xndompropertyvalue.h" +#include "xnmenuadapter.h" +#include "xnpopupcontroladapter.h" +#include "xnviewdata.h" +#include "xnnodebreadthfirstiterator.h" +#include "xntype.h" +#include "xnnodepluginif.h" +#include "xncomponentnodeimpl.h" +#include "xnproperty.h" +#include "xnappuiadapter.h" +#include "xnviewadapter.h" +#include "xnwidgetextensionadapter.h" +#include "xnscrollablecontroladapter.h" +#include "xnkeyeventdispatcher.h" +#include +#include "xuikon_builds_cfg.hrh" +#include "xndomdocument.h" +#include "xndomnode.h" +#include "xneditmode.h" +#include "xnhittest.h" +#include "xnnode.h" +#include "xnpanic.h" +#include "xneffectmanager.h" + +#ifdef _XN_PERFORMANCE_TEST_ +#include "xntimemon.h" +#endif + +// CONSTANTS +const TInt KXnBorderThin = 1; +const TInt KXnBorderMedium = 3; +const TInt KXnBorderThick = 5; +const TInt KXnStackPriorityKeyEventDispatcher = 55; +const TInt KFocusGrowValue = 3; + +_LIT8( KBoxNodeName, "box" ); +_LIT8( KButtonNodeName, "button" ); +_LIT8( KWidgetNodeName, "widget" ); +_LIT8( KWidgetExtensionNodeName, "widgetextension" ); +_LIT8( KScrollableBoxNodeName, "scrollablebox" ); +_LIT8( KMenuBar, "menubar" ); +_LIT8( KPopUpNodeName, "popup" ); + +_LIT8( KPlugin, "plugin" ); + +// LOCAL CONSTANTS AND MACROS +static const TReal KIntConversionConstant = 0.5; +static const TReal KIntPercentageConstant = + static_cast< TReal >( 1 ) / static_cast< TReal >( 100 ); +static const TReal KInchesAsTwips = 1440; +static const TReal KCentimetersAsInches = static_cast< TReal >( 1 ) / 2.54; +static const TReal KCentimetersAsTwips = KCentimetersAsInches * KInchesAsTwips; +static const TReal KMillimetersAsInches = + KCentimetersAsInches / static_cast< TReal >( 10 ); +static const TReal KMillimetersAsTwips = KMillimetersAsInches * KInchesAsTwips; +static const TReal KPointsAsInches = + static_cast< TReal >( 1 ) / static_cast< TReal >( 72 ); +static const TReal KPointsAsTwips = KPointsAsInches * KInchesAsTwips; +static const TReal KPicasAsInches = + KPointsAsInches / static_cast< TReal >( 12 ); +static const TReal KPicasAsTwips = KPicasAsInches * KInchesAsTwips; + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +static TRect AddRect( const TRect& aOriginal, const TRect& aAdded ); +static TRect SubtractRect( const TRect& aOriginal, const TRect& aSubtracter ); +static TSize AutoStaticBTL( CXnNode& aNode, TInt aWidthToFit, + TInt aHeightToFit, RArray< TPtrC8 >& aAutoProperties, + TRect& aParentRect, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); +static TSize AutoStaticLRL( CXnNode& aNode, TInt aWidthToFit, + TInt aHeightToFit, RArray< TPtrC8 >& aAutoProperties, + TRect& aParentRect, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); +static TSize AutoStaticRLL( CXnNode& aNode, TInt aWidthToFit, + TInt aHeightToFit, RArray< TPtrC8 >& aAutoProperties, + TRect& aParentRect, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); +static TSize AutoStaticTBL( CXnNode& aNode, TInt aWidthToFit, + TInt aHeightToFit, RArray< TPtrC8 >& aAutoProperties, + TRect& aParentRect, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); +static void CalculateAbsolutePositionsL( CXnNode& aNode, + TRect& aParentRect, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); +static void CalculateBorderL( CXnNode& aNode, + TRect& aParentRect, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); +static void CalculateMarginL( CXnNode& aParent, CXnNode& aNode, + CXnNode* aPreviousSibling, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels, TInt& aColumnWidth, TInt& aColumnMargin ); +static void CalculatePaddingL( const TRect& aParentRect, CXnNode& aNode, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); + +static void CalculateRectL( CXnNode& aNode, CXnNode& aParent, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); + +static void CalculateRelativePositionsL( const TRect& aRect, CXnNode& aNode, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); +static TSize CalculateSpaceUsedByChildrenL( RPointerArray< CXnNode >& aChildren, + CXnNode& aNode, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, CGraphicsDevice& aScreenDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); + +static TSize CalculateTotalDimensionsL( CXnNode& aNode, TBool aIgnoreAutoValues, + TBool aIgnoreMinSizes, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); +static TBool CutOnePixelFromPercentChildNodeL( CXnNode& aNode, + const TDesC8& aParentBlockProgression ); +static void DetermineBorderWidthsL( CXnProperty* aBorderWidthProperty, + TInt& aBordervertical, TInt& aBorderhorizontal, + TRect& aParentRect, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); +static TInt DisplayedChildrenCountL( CXnNode& aNode, + RPointerArray< CXnNode >* aDisplayedChildren = NULL ); +static CXnNode* DisplayedParentL( CXnNode& aNode ); +static CXnDomPropertyValue* DomPropertyValueFromProperty( + CXnProperty* aProperty ); +static void DropExceedingRectL( const TRect& aParentRect, CXnNode& aNode, + TBool aDropRelativeNode = EFalse ); +static TBool CalculateExceedingArea( CXnNode& aParent, CXnNode& aChild, + TInt& aLeftOffset, TInt& aRightOffset, TInt& aTopOffset, + TInt& aBottomOffset ); +static void AdjustRectsL( CXnNode& aNode, TInt aLeftOffset, TInt aRightOffset, + TInt aTopOffset, TInt aBottomOffset ); +static void ClearRects( CXnNode& aNode, TBool aRecurse = EFalse ); +static void FitChildrenIntoParentL( CXnNode& aNode, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); +static TInt GetPositionL( CXnNode& aNode, + const TDesC8& aParentBlockProgression, const TDesC8& aParentDirection ); +static TInt HasNodeAutoValuesL( CXnNode& aNode ); +static TInt HasNodeHorizontalAutoValuesL( CXnNode& aNode ); +static TInt HasNodeVerticalAutoValuesL( CXnNode& aNode ); +static TBool HasNodeMinSizesL( CXnNode& aNode ); +static TBool HasNodeMaxSizesL( CXnNode& aNode ); +static TInt HorizontalPixelValueL( CXnProperty* aValue, TInt aReferenceValue, + CGraphicsDevice& aScreenDevice, TReal aHorizontalUnitInPixels ); +static TInt HorizontalValueToPixelsL( CXnDomPropertyValue* aValue, + TReal aReferenceValue, CGraphicsDevice& aScreenDevice, + TReal aHorizontalUnitInPixels ); +static void GrowToMinSizeL( CXnNode& aNode, TRect& aParentRect, + CGraphicsDevice& aScreenDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); +static void ShrinkToMaxSizeL( CXnNode& aNode, TRect& aParentRect, + CGraphicsDevice& aScreenDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); +static TBool IsAbsoluteL( CXnNode& aNode ); +static TBool IsLargerThanMaxSizeL( const TRect& aParentRect, CXnNode& aNode, + CGraphicsDevice& aScreenDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); +static TBool IsNodeDisplayedL( CXnNode& aNode ); + +static TBool IsNodeTooltip( CXnNode& aNode ); +static TBool IsPropertyAutoL( CXnProperty& aProperty ); +static TBool IsPropertyNone( CXnProperty& aProperty ); +static TBool IsRelativeL( CXnNode& aNode ); +static TBool IsSmallerThanMinSizeL( const TRect& aParentRect, CXnNode& aNode, + CGraphicsDevice& aScreenDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); +static TBool IsValuePercentageL( CXnProperty& aProperty ); +static TInt PercentageToPixelsL( TReal& aPercentage, TReal aReferenceValue ); +static void PlaceAreasL( CXnNode& aNode, + RPointerArray< CXnNode >& aLaidOutList, + TInt aLayoutPhase, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); +static void PriorizeChildrenL( CXnNode& aNode ); +static void CalculateAutoPropertiesOfNodesL( + RPointerArray< CXnNode >* aAutoNodeArray, TInt& aWidthAutoCount, + TInt& aHeightAutoCount ); +static void ProcessAutoAreasL( CXnNode& aParentNode, + RPointerArray< CXnNode >* aArray, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ); +static void CalculateCollapseMarginsL( RPointerArray< CXnNode >& aChildren, + RArray< TInt >& aCollapsedMarginsWidth, + RArray< TInt >& aCollapsedMarginsHeight, + const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection ); +static TSize CalculateSpaceUsedByAutoChildrenL( + RPointerArray< CXnNode >& aAutoChildren, + RPointerArray< CXnNode >& aCalculatedAutoChildren, + CXnNode& aParent, + const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, + CGraphicsDevice& aScreenDevice ); +static void MoveAutoAreaL( TRect& parentRect, + RPointerArray< CXnNode >& aChildren, + const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection ); +static TSize ScaleAutoAreaL( CXnNode& aNode, TInt aWidthToFit, + TInt aHeightToFit, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); +static void FitAutoChildrenIntoParentL( RPointerArray< CXnNode >& aAutoChildren, + RPointerArray< CXnNode >& aCalculatedAutoChildren, CXnNode& aParent, + const TDesC8& aParentBlockProgression, const TDesC8& aParentDirection, + CGraphicsDevice& aGraphicsDevice ); +static TInt VerticalPixelValueL( CXnProperty* aValue, TInt aReferenceValue, + CGraphicsDevice& aScreenDevice, TReal aVerticalUnitInPixels ); +static TInt VerticalValueToPixelsL( CXnDomPropertyValue* aValue, + TReal aReferenceValue, CGraphicsDevice& aScreenDevice, + TReal aVerticalUnitInPixels ); +static TBool IsStringValueL( CXnProperty& aProperty ); +static TInt HorizontalUnitsToPixelsL( TReal aUnits, + TReal aHorizontalUnitInPixels ); +static TInt VerticalUnitsToPixelsL( TReal aUnits, TReal aVerticalUnitInPixels ); +static void ProcessAdaptiveAreasL( CXnNode& aParent, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); + +static void CalculateAdaptiveSizeL( CXnNode& aNode, + const TDesC8& aParentBlockProgression, const TDesC8& aParentDirection, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ); + +static CXnNode* BuildTriggerNodeLC( CXnUiEngine& aUiEngine, + const TDesC8& aTriggerName ); +static void UpdateInternalUnits( TReal& aHorizontalUnitInPixels, + TReal& aVerticalUnitInPixels, TRect aRect ); +static CXnNode* BuildScreenDeviceChangeTriggerNodeLC( + CXnUiEngine& aUiEngine ); +static void FillFocusCandidatesL( CXnNode* aParent, + RPointerArray< CXnNode >& aArray ); +static TInt DetermineStatusPaneLayout( CXnProperty* aProperty ); +static TBool SetAdaptivesL( CXnNode& aNode ); + +static void FindNodeByClassL( CXnNode* aRootNode, const TDesC8& aClassId, + CXnPointerArray& aArray, const TDesC8& aNamespace ); +static CXnNode* FindNodeByIdL( CXnNode* aRootNode, const TDesC8& aAreaId, + const TDesC8& aNamespace ); + +#ifdef _XN3_DEBUG_ +static void TraceTreeL( CXnNode* aRootNode ); +#endif + +// ============================= LOCAL FUNCTIONS =============================== +// ----------------------------------------------------------------------------- +// GrowIfNeeded() +// When a plugin is focused, the focus is a bit bigger than its control +// (this is a hack fix to get focus visible with WRT widgets). +// Therefore we need to check if focused node is a plugin, +// or focused node has same size with its plugin, and grow dirty rect accordingly. +// ----------------------------------------------------------------------------- +// +static void GrowIfNeeded(CXnNode* aNode, TRect& aRect) + { + CXnNode* focusedNode(NULL); + for( CXnNode* node = aNode; node; node = node->Parent() ) + { + if( node->IsStateSet( XnPropertyNames::style::common::KFocus ) ) + { + if( node->DomNode()->Name() == KPlugin ) + { + CXnControlAdapter* adapter( node->Control() ); + if(adapter) + { + aRect = adapter->Rect(); + aRect.Grow( KFocusGrowValue, KFocusGrowValue ); + } + break; + } + focusedNode = node; + } + else if( node->DomNode()->Name() == KPlugin ) + { + if( focusedNode && focusedNode->MarginRect() == node->Rect() ) + { + CXnControlAdapter* adapter( focusedNode->Control() ); + if(adapter) + { + aRect = adapter->Rect(); + aRect.Grow( KFocusGrowValue, KFocusGrowValue ); + } + } + break; + } + } + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +static TBool IsSrollableBox( CXnNode& aNode ) + { + if( aNode.Type()->Type() == KScrollableBoxNodeName ) + { + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// FindNodeByClassL() +// Finds recursively a node from current view by class +// ----------------------------------------------------------------------------- +// +static void FindNodeByClassL( CXnNode* aRootNode, const TDesC8& aClassId, + CXnPointerArray& aArray, const TDesC8& aNamespace ) + { + ASSERT( aRootNode ); + + if ( aNamespace != KNullDesC8 && aNamespace != aRootNode->Namespace() ) + { + // Recursed to wrong namespace + return; + } + + CXnProperty* prop( aRootNode->ClassL() ); + + if ( prop && prop->StringValue() == aClassId ) + { + // Correct id found + if ( aNamespace == KNullDesC8 ) + { + aArray.Container().AppendL( aRootNode ); + } + else if ( aNamespace == aRootNode->DomNode()->Namespace() ) + { + // Namespace is defined and this node is in that namespace + // -> this is perfect match + aArray.Container().AppendL( aRootNode ); + } + } + + // Recurse children + RPointerArray< CXnNode >& children( aRootNode->Children() ); + + for ( TInt i = 0; i < children.Count(); i++ ) + { + FindNodeByClassL( children[i], aClassId, aArray, aNamespace ); + } + } + +// ----------------------------------------------------------------------------- +// FindNodeByIdL() +// Finds recursively a node from current view by id +// ----------------------------------------------------------------------------- +// +static CXnNode* FindNodeByIdL( CXnNode* aRootNode, const TDesC8& aAreaId, + const TDesC8& aNamespace ) + { + ASSERT( aRootNode ); + + if ( aNamespace != KNullDesC8 && aNamespace != aRootNode->Namespace() ) + { + // Recursed to wrong namespace + return NULL; + } + + CXnProperty* prop( aRootNode->IdL() ); + + if ( prop && prop->StringValue() == aAreaId ) + { + // Correct id found + if ( aNamespace == KNullDesC8 ) + { + // No namespace defined, so this is the first found best match + return aRootNode; + } + else if ( aNamespace == aRootNode->DomNode()->Namespace() ) + { + // Namespace is defined and this node is in that namespace + // -> this is perfect match + return aRootNode; + } + } + + // No match found, recurse children + RPointerArray< CXnNode >& children( aRootNode->Children() ); + + for ( TInt i = 0; i < children.Count(); i++ ) + { + CXnNode* retval( FindNodeByIdL( children[i], aAreaId, aNamespace ) ); + + if ( retval ) + { + return retval; + } + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// AutoStaticVerticalBTL() +// Calculate properties set to AUTO when positioning is static, layout vertical +// and direction right-to-left +// ----------------------------------------------------------------------------- +// +static TSize AutoStaticBTL( CXnNode& aNode, TInt aWidthToFit, TInt aHeightToFit, + RArray< TPtrC8 >& aAutoProperties, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + // Static positioning, vertical, right to left + TBool horizontalMarginProcessed = EFalse; + TBool verticalMarginProcessed = EFalse; + TBool allVerticalValuesProcessed = EFalse; + TBool allHorizontalValuesProcessed = EFalse; + + CXnProperty* maxHeightProperty = aNode.MaxHeightL(); + CXnProperty* maxWidthProperty = aNode.MaxWidthL(); + CXnProperty* minHeightProperty = aNode.MinHeightL(); + CXnProperty* minWidthProperty = aNode.MinWidthL(); + + TRect contentRect( aNode.Rect() ); + TRect paddingRect( aNode.PaddingRect() ); + TRect borderRect( aNode.BorderRect() ); + TRect marginRect( aNode.MarginRect() ); + TRect normalFlowBorderRect( aNode.NormalFlowBorderRect() ); + + TSize size = CalculateTotalDimensionsL( aNode, EFalse, ETrue, aParentRect, + aGraphicsDevice, aHorizontalUnitInPixels, aVerticalUnitInPixels ); + + for ( TInt i = 0; i < aAutoProperties.Count(); i++ ) + { + // search for height property + const TDesC8& attributeName = aAutoProperties[i]; + if ( attributeName == XnPropertyNames::style::common::KHeight ) + { + // height was AUTO, all other vertical auto values are 0 + TInt newHeight = aHeightToFit - size.iHeight; + + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect ( normalFlowBorderRect, + contentRect ) ); + + // grow height to fill the void + contentRect.SetHeight( newHeight ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( contentRect, + normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + + size = TSize( size.iWidth, aHeightToFit ); + } + } + + // if exactly one value is AUTO, value is computed to make equality true + if ( aAutoProperties.Count() == 1 ) + { + if ( !allHorizontalValuesProcessed ) + { + const TDesC8& attributeName = aAutoProperties[0]; + if ( attributeName == XnPropertyNames::style::common::KWidth ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( paddingRect, + contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, + contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, + contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( + normalFlowBorderRect, contentRect ) ); + + // grow width to fill the void + contentRect.SetWidth( remainingWidth ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( contentRect, + normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + + size = TSize( aWidthToFit, size.iHeight ); + } + + if ( attributeName == + XnPropertyNames::style::common::KMarginLeft ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + contentRect.Move( remainingWidth, 0 ); + borderRect.Move( remainingWidth, 0 ); + normalFlowBorderRect.Move( remainingWidth, 0 ); + marginRect.Resize( remainingWidth, 0 ); + paddingRect.Move( remainingWidth, 0 ); + size = TSize( size.iWidth + remainingWidth, size.iHeight ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginRight ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + marginRect.Resize( remainingWidth, 0 ); + size = TSize( size.iWidth + remainingWidth, size.iHeight ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginTop ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + marginRect.Resize( 0, remainingHeight ); + marginRect.Move( 0, -remainingHeight ); + size = TSize( size.iWidth, size.iHeight + remainingHeight ); + } + + if ( attributeName == + XnPropertyNames::style::common::KMarginBottom ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + marginRect.Resize( 0, remainingHeight ); + marginRect.Move( 0, -remainingHeight ); + paddingRect.Move( 0, -remainingHeight ); + borderRect.Move( 0, -remainingHeight ); + normalFlowBorderRect.Move( 0, -remainingHeight ); + contentRect.Move( 0, -remainingHeight ); + size = TSize( size.iWidth, size.iHeight + remainingHeight ); + } + } + } + else + { + for ( TInt i = 0; i < aAutoProperties.Count(); i++ ) + { + const TDesC8& attributeName = aAutoProperties[i]; + if ( attributeName == XnPropertyNames::style::common::KWidth ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( + paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( + borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( + marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( + normalFlowBorderRect, contentRect ) ); + + // grow width to fill the void + contentRect.SetWidth( remainingWidth ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( + contentRect, normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + + size = TSize( aWidthToFit, size.iHeight ); + } + + // several auto properties + if ( attributeName == XnPropertyNames::style::common::KMarginLeft ) + { + if ( !horizontalMarginProcessed ) + { + // is right margin also set to AUTO? + CXnProperty* rightMargin = aNode.MarginRightL(); + if ( rightMargin ) + { + if ( IsPropertyAutoL( *rightMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( ( remainingWidth / 2 ), 0 ); + marginRect.Resize( remainingWidth, 0 ); + borderRect.Move( ( remainingWidth / 2 ), 0 ); + normalFlowBorderRect.Move( ( + remainingWidth / 2 ), 0 ); + paddingRect.Move( remainingWidth / 2, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + else + { + // only left margin set to AUTO + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( ( remainingWidth ), 0 ); + marginRect.Resize( remainingWidth, 0 ); + borderRect.Move( remainingWidth, 0 ); + normalFlowBorderRect.Move( remainingWidth, 0 ); + paddingRect.Move( remainingWidth, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + } + } + } + if ( attributeName == XnPropertyNames::style::common::KMarginRight ) + { + if ( !horizontalMarginProcessed ) + { + // is left margin also set to AUTO? + CXnProperty* leftMargin = aNode.MarginLeftL(); + if ( leftMargin ) + { + if ( IsPropertyAutoL( *leftMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + contentRect.Move( remainingWidth / 2, 0 ); + marginRect.Resize( remainingWidth, 0 ); + borderRect.Move( ( remainingWidth / 2 ), 0 ); + normalFlowBorderRect.Move( ( + remainingWidth / 2 ), 0 ); + paddingRect.Move( remainingWidth / 2, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + else + { + // only right margin set to AUTO + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + marginRect.Resize( remainingWidth, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + } + } + } + if ( attributeName == XnPropertyNames::style::common::KMarginTop ) + { + if ( !verticalMarginProcessed && + !allVerticalValuesProcessed ) + { + // is bottom margin also set to AUTO? + CXnProperty* bottomMargin = aNode.MarginBottomL(); + if ( bottomMargin ) + { + if ( IsPropertyAutoL( *bottomMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + contentRect.Move( 0, remainingHeight / 2 ); + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, ( remainingHeight / 2 ) ); + normalFlowBorderRect.Move( + 0, ( remainingHeight / 2 ) ); + paddingRect.Move( 0, remainingHeight / 2 ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + else + { + // only top margin set to AUTO + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + marginRect.Resize( 0, remainingHeight ); + marginRect.Move( 0, -remainingHeight ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + } + } + } + if ( attributeName == + XnPropertyNames::style::common::KMarginBottom ) + { + if ( !verticalMarginProcessed && !allVerticalValuesProcessed ) + { + // is top margin also set to AUTO? + CXnProperty* topMargin = aNode.MarginTopL(); + if ( topMargin ) + { + if ( IsPropertyAutoL( *topMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + contentRect.Move( 0, -( remainingHeight / 2 ) ); + marginRect.Resize( 0, remainingHeight ); + marginRect.Move( 0, -remainingHeight ); + borderRect.Move( 0, -( remainingHeight / 2 ) ); + normalFlowBorderRect.Move( + 0, -( remainingHeight / 2 ) ); + paddingRect.Move( 0, -( remainingHeight / 2 ) ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + else + { + // only bottom margin set to AUTO + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + contentRect.Move( 0, -remainingHeight ); + marginRect.Resize( 0, remainingHeight ); + marginRect.Move( 0, -remainingHeight ); + borderRect.Move( 0, -remainingHeight ); + normalFlowBorderRect.Move( + 0, -remainingHeight ); + paddingRect.Move( 0, -remainingHeight ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + } + } + } + } + } + aNode.SetRect( contentRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetMarginRect( marginRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + return contentRect.Size(); + } + +// ----------------------------------------------------------------------------- +// AutoStaticLRL() +// Calculate properties set to AUTO when positioning is static, +// layout horizontal +// and direction left-to-right +// ----------------------------------------------------------------------------- +// +static TSize AutoStaticLRL( CXnNode& aNode, TInt aWidthToFit, TInt aHeightToFit, + RArray< TPtrC8 >& aAutoProperties, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + // Static positioning, horizontal, left to right + TBool horizontalMarginProcessed = EFalse; + TBool verticalMarginProcessed = EFalse; + TBool allVerticalValuesProcessed = EFalse; + TBool allHorizontalValuesProcessed = EFalse; + + CXnProperty* maxHeightProperty = aNode.MaxHeightL(); + CXnProperty* maxWidthProperty = aNode.MaxWidthL(); + CXnProperty* minHeightProperty = aNode.MinHeightL(); + CXnProperty* minWidthProperty = aNode.MinWidthL(); + + TRect contentRect = aNode.Rect(); + TRect paddingRect = aNode.PaddingRect(); + TRect borderRect = aNode.BorderRect(); + TRect marginRect = aNode.MarginRect(); + TRect normalFlowBorderRect = aNode.NormalFlowBorderRect(); + TSize size = CalculateTotalDimensionsL( aNode, EFalse, ETrue, aParentRect, + aGraphicsDevice, aHorizontalUnitInPixels, aVerticalUnitInPixels ); + + for ( TInt i = 0; i < aAutoProperties.Count(); i++ ) + { + // search for width property + const TDesC8& attributeName = aAutoProperties[i]; + if ( attributeName == XnPropertyNames::style::common::KWidth ) + { + // width was AUTO, all other vertical auto values are 0 + TInt newWidth = aWidthToFit - size.iWidth; + + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( normalFlowBorderRect, + contentRect ) ); + + // grow width to fill the void + contentRect.SetWidth( newWidth ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( + contentRect, normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + + size = TSize( aWidthToFit, size.iHeight ); + allHorizontalValuesProcessed = ETrue; + } + } + + // if exactly one value is AUTO, value is computed to make equality true + if ( aAutoProperties.Count() == 1 ) + { + if ( !allHorizontalValuesProcessed ) + { + const TDesC8& attributeName = aAutoProperties[0]; + if ( attributeName == XnPropertyNames::style::common::KHeight ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( + paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( + borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( + marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( + normalFlowBorderRect, contentRect ) ); + + // grow height to fill the void + contentRect.SetHeight( remainingHeight ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( + contentRect, normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + size = TSize( size.iWidth, aHeightToFit ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginLeft ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( remainingWidth, 0 ); + paddingRect.Move( remainingWidth, 0 ); + borderRect.Move( remainingWidth, 0 ); + normalFlowBorderRect.Move( remainingWidth, 0 ); + marginRect.Resize( remainingWidth, 0 ); + size = TSize( size.iWidth + remainingWidth, size.iHeight ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginRight ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + marginRect.Resize( remainingWidth, 0 ); + size = TSize( size.iWidth + remainingWidth, size.iHeight ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginTop ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + // move rect right to fill the void + contentRect.Move( 0, remainingHeight / 2 ); + paddingRect.Move( 0, remainingHeight / 2 ); + borderRect.Move( 0, remainingHeight / 2 ); + normalFlowBorderRect.Move( 0, remainingHeight / 2 ); + marginRect.Resize( 0, remainingHeight ); + size = TSize( size.iWidth, size.iHeight + remainingHeight ); + } + + if ( attributeName == + XnPropertyNames::style::common::KMarginBottom ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + marginRect.Resize( 0, remainingHeight ); + size = TSize( size.iWidth, size.iHeight + remainingHeight ); + } + } + } + else + { + for ( TInt i = 0; i < aAutoProperties.Count(); i++ ) + { + const TDesC8& attributeName = aAutoProperties[i]; + if ( attributeName == XnPropertyNames::style::common::KHeight ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( + paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( + borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( + marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( + normalFlowBorderRect, contentRect ) ); + + // grow height to fill the void + contentRect.SetHeight( remainingHeight ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( + contentRect, normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + size = TSize( size.iWidth, aHeightToFit ); + } + + // several auto properties + if ( attributeName == XnPropertyNames::style::common::KMarginLeft ) + { + if ( !horizontalMarginProcessed ) + { + // is right margin also set to AUTO? + CXnProperty* rightMargin = aNode.MarginRightL(); + if ( rightMargin ) + { + if ( IsPropertyAutoL( *rightMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( ( remainingWidth / 2 ), 0 ); + horizontalMarginProcessed = ETrue; + marginRect.Resize( ( remainingWidth ), 0 ); + borderRect.Move( ( remainingWidth / 2 ), 0 ); + normalFlowBorderRect.Move( ( + remainingWidth / 2 ), 0 ); + paddingRect.Move( ( remainingWidth / 2 ), 0 ); + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + else + { + // only left margin set to AUTO + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( remainingWidth, 0 ); + horizontalMarginProcessed = ETrue; + marginRect.Move( remainingWidth, 0 ); + borderRect.Move( remainingWidth, 0 ); + normalFlowBorderRect.Move( remainingWidth, 0 ); + paddingRect.Move( remainingWidth, 0 ); + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + } + } + } + + if ( attributeName == XnPropertyNames::style::common::KMarginRight ) + { + if ( !horizontalMarginProcessed ) + { + // is left margin also set to AUTO? + CXnProperty* leftMargin = aNode.MarginLeftL(); + if ( leftMargin ) + { + if ( IsPropertyAutoL( *leftMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( ( remainingWidth / 2 ), 0 ); + horizontalMarginProcessed = ETrue; + marginRect.Resize( ( remainingWidth ), 0 ); + borderRect.Move( ( remainingWidth / 2 ), 0 ); + normalFlowBorderRect.Move( ( + remainingWidth / 2 ), 0 ); + paddingRect.Move( ( remainingWidth / 2 ), 0 ); + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + else + { + // only right margin set to AUTO + horizontalMarginProcessed = ETrue; + } + } + } + } + if ( attributeName == XnPropertyNames::style::common::KMarginTop ) + { + if ( !verticalMarginProcessed && !allVerticalValuesProcessed ) + { + // is bottom margin also set to AUTO? + CXnProperty* bottomMargin = aNode.MarginBottomL(); + if ( bottomMargin ) + { + if ( IsPropertyAutoL( *bottomMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + contentRect.Move( 0, ( remainingHeight / 2 ) ); + verticalMarginProcessed = ETrue; + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, ( remainingHeight / 2 ) ); + normalFlowBorderRect.Move( + 0, ( remainingHeight / 2 ) ); + paddingRect.Move( 0, ( remainingHeight / 2 ) ); + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + else + { + // only top margin set to AUTO + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + contentRect.Move( 0, remainingHeight ); + verticalMarginProcessed = ETrue; + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, remainingHeight ); + normalFlowBorderRect.Move( 0, remainingHeight ); + paddingRect.Move( 0, remainingHeight ); + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + } + } + } + + if ( attributeName == + XnPropertyNames::style::common::KMarginBottom ) + { + if ( !verticalMarginProcessed && !allVerticalValuesProcessed ) + { + // is top margin also set to AUTO? + CXnProperty* topMargin = aNode.MarginTopL(); + if ( topMargin ) + { + if ( IsPropertyAutoL( *topMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + contentRect.Move( 0, remainingHeight / 2 ); + verticalMarginProcessed = ETrue; + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, remainingHeight / 2 ); + normalFlowBorderRect.Move( + 0, remainingHeight / 2 ); + paddingRect.Move( 0, remainingHeight / 2 ); + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + else + { + // only bottom margin set to AUTO + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + marginRect.Resize( 0, remainingHeight ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + } + } + } + } + } + aNode.SetRect( contentRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetMarginRect( marginRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + return contentRect.Size(); + } + +// ----------------------------------------------------------------------------- +// AutoStaticRLL() +// Calculate properties set to AUTO when positioning is static, +// layout horizontal +// and direction right-to-left. +// ----------------------------------------------------------------------------- +// +static TSize AutoStaticRLL( CXnNode& aNode, TInt aWidthToFit, + TInt aHeightToFit, RArray< TPtrC8 >& aAutoProperties, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + // Static positioning, horizontal, right to left + TBool horizontalMarginProcessed = EFalse; + TBool verticalMarginProcessed = EFalse; + TBool allVerticalValuesProcessed = EFalse; + TBool allHorizontalValuesProcessed = EFalse; + + CXnProperty* maxHeightProperty = aNode.MaxHeightL(); + CXnProperty* maxWidthProperty = aNode.MaxWidthL(); + CXnProperty* minHeightProperty = aNode.MinHeightL(); + CXnProperty* minWidthProperty = aNode.MinWidthL(); + + TRect contentRect( aNode.Rect() ); + TRect paddingRect( aNode.PaddingRect() ); + TRect borderRect( aNode.BorderRect() ); + TRect marginRect( aNode.MarginRect() ); + TRect normalFlowBorderRect( aNode.NormalFlowBorderRect() ); + + TSize size = CalculateTotalDimensionsL( aNode, EFalse, ETrue, aParentRect, + aGraphicsDevice, aHorizontalUnitInPixels, aVerticalUnitInPixels ); + + for ( TInt i = 0; i < aAutoProperties.Count(); i++ ) + { + // search for height property + const TDesC8& attributeName = aAutoProperties[i]; + if ( attributeName == XnPropertyNames::style::common::KWidth ) + { + TInt newWidth = aWidthToFit - size.iWidth; + + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( normalFlowBorderRect, + contentRect ) ); + + // grow width to fill the void + contentRect.SetWidth( newWidth ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( contentRect, + normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + + size = TSize( aWidthToFit, size.iHeight ); + allHorizontalValuesProcessed = ETrue; + } + } + + // if exactly one value is AUTO, value is computed to make equality true + if ( aAutoProperties.Count() == 1 ) + { + if ( !allHorizontalValuesProcessed ) + { + const TDesC8& attributeName = aAutoProperties[0]; + if ( attributeName == XnPropertyNames::style::common::KHeight ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( + paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( + normalFlowBorderRect, contentRect ) ); + + // grow height to fill the void + contentRect.SetHeight( remainingHeight ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( contentRect, + normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + + size = TSize( size.iWidth, aHeightToFit ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginLeft ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( remainingWidth, 0 ); + paddingRect.Move( remainingWidth, 0 ); + borderRect.Move( remainingWidth, 0 ); + normalFlowBorderRect.Move( remainingWidth, 0 ); + marginRect.Resize( remainingWidth, 0 ); + marginRect.Move( -remainingWidth, 0 ); + size = TSize( size.iWidth + remainingWidth, size.iHeight ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginRight ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + contentRect.Move( -remainingWidth, 0 ); + paddingRect.Move( -remainingWidth, 0 ); + borderRect.Move( -remainingWidth, 0 ); + normalFlowBorderRect.Move( -remainingWidth, 0 ); + marginRect.Move( -remainingWidth, 0 ); + marginRect.Resize( remainingWidth, 0 ); + + size = TSize( size.iWidth + remainingWidth, size.iHeight ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginTop ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + contentRect.Move( 0, remainingHeight / 2 ); + paddingRect.Move( 0, remainingHeight / 2 ); + borderRect.Move( 0, remainingHeight / 2 ); + normalFlowBorderRect.Move( 0, remainingHeight / 2 ); + marginRect.Resize( 0, remainingHeight ); + size = TSize( size.iWidth, size.iHeight + remainingHeight ); + } + + if ( attributeName == + XnPropertyNames::style::common::KMarginBottom ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + marginRect.Resize( 0, remainingHeight ); + size = TSize( size.iWidth, size.iHeight + remainingHeight ); + } + } + } + else + { + for ( TInt i = 0; i < aAutoProperties.Count(); i++ ) + { + const TDesC8& attributeName = aAutoProperties[i]; + if ( attributeName == XnPropertyNames::style::common::KHeight ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( + paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( + normalFlowBorderRect, contentRect ) ); + + // grow height to fill the void + contentRect.SetHeight( remainingHeight ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( contentRect, + normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + + size = TSize( size.iWidth, size.iHeight + remainingHeight ); + } + + // several auto properties + if ( attributeName == XnPropertyNames::style::common::KMarginLeft ) + { + if ( !horizontalMarginProcessed ) + { + // is right margin also set to AUTO? + CXnProperty* rightMargin = aNode.MarginRightL(); + if ( rightMargin ) + { + if ( IsPropertyAutoL( *rightMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect left + contentRect.Move( -( remainingWidth / 2 ), 0 ); + marginRect.Resize( remainingWidth, 0 ); + marginRect.Move( -remainingWidth, 0 ); + borderRect.Move( -( remainingWidth / 2 ), 0 ); + normalFlowBorderRect.Move( + -( remainingWidth / 2 ), 0 ); + paddingRect.Move( -( remainingWidth / 2 ), 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + else + { + // only left margin set to AUTO + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect left + contentRect.Move( ( remainingWidth ), 0 ); + marginRect.Resize( remainingWidth, 0 ); + marginRect.Move( remainingWidth, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + } + } + } + + if ( attributeName == XnPropertyNames::style::common::KMarginRight ) + { + if ( !horizontalMarginProcessed ) + { + // is left margin also set to AUTO? + CXnProperty* leftMargin = aNode.MarginLeftL(); + if ( leftMargin ) + { + if ( IsPropertyAutoL( *leftMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + contentRect.Move( -( remainingWidth / 2 ), 0 ); + marginRect.Resize( remainingWidth, 0 ); + marginRect.Move( -remainingWidth, 0 ); + borderRect.Move( -( remainingWidth / 2 ), 0 ); + normalFlowBorderRect.Move( + -( remainingWidth / 2 ), 0 ); + paddingRect.Move( -( remainingWidth / 2 ), 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + else + { + // only right margin set to AUTO + TInt usedWidth = size.iWidth; + TInt remainingWidth = aWidthToFit - usedWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + contentRect.Move( -remainingWidth, 0 ); + marginRect.Resize( remainingWidth, 0 ); + marginRect.Move( -remainingWidth, 0 ); + borderRect.Move( -remainingWidth, 0 ); + normalFlowBorderRect.Move( -remainingWidth, 0 ); + paddingRect.Move( -remainingWidth, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + } + } + } + if ( attributeName == XnPropertyNames::style::common::KMarginTop ) + { + if ( !verticalMarginProcessed && !allVerticalValuesProcessed ) + { + // is bottom margin also set to AUTO? + CXnProperty* bottomMargin = aNode.MarginBottomL(); + if ( bottomMargin ) + { + if ( IsPropertyAutoL( *bottomMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + contentRect.Move( 0, ( remainingHeight / 2 ) ); + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, ( remainingHeight / 2 ) ); + normalFlowBorderRect.Move( + 0, ( remainingHeight / 2 ) ); + paddingRect.Move( 0, ( remainingHeight / 2 ) ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + else + { + // only top margin set to AUTO + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + contentRect.Move( 0, remainingHeight ); + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, remainingHeight ); + normalFlowBorderRect.Move( 0, remainingHeight ); + paddingRect.Move( 0, remainingHeight ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + } + } + } + + if ( attributeName == + XnPropertyNames::style::common::KMarginBottom ) + { + if ( !verticalMarginProcessed && !allVerticalValuesProcessed ) + { + // is top margin also set to AUTO? + CXnProperty* topMargin = aNode.MarginTopL(); + if ( topMargin ) + { + if ( IsPropertyAutoL( *topMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + contentRect.Move( 0, ( remainingHeight / 2 ) ); + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, ( remainingHeight / 2 ) ); + normalFlowBorderRect.Move( + 0, ( remainingHeight / 2 ) ); + paddingRect.Move( 0, ( remainingHeight / 2 ) ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + else + { + // only bottom margin set to AUTO + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + marginRect.Resize( 0, remainingHeight ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + } + } + } + } + } + aNode.SetRect( contentRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetMarginRect( marginRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + return contentRect.Size(); + } + +// ----------------------------------------------------------------------------- +// SubtractRect() +// Calculate the difference of two rectangles and return it as +// ----------------------------------------------------------------------------- +// +static TRect SubtractRect( const TRect& aOriginal, const TRect& aSubtracter ) + { + return TRect( aOriginal.iTl.iX - aSubtracter.iTl.iX, + aOriginal.iTl.iY - aSubtracter.iTl.iY, + aOriginal.iBr.iX - aSubtracter.iBr.iX, + aOriginal.iBr.iY - aSubtracter.iBr.iY ); + } + +// ----------------------------------------------------------------------------- +// AddRect() +// Add two rectangles together and return the result +// ----------------------------------------------------------------------------- +// +static TRect AddRect( const TRect& aOriginal, const TRect& aAdded ) + { + return TRect( aOriginal.iTl.iX + aAdded.iTl.iX, + aOriginal.iTl.iY + aAdded.iTl.iY, + aOriginal.iBr.iX + aAdded.iBr.iX, + aOriginal.iBr.iY + aAdded.iBr.iY ); + } + +// ----------------------------------------------------------------------------- +// AutoStaticTBL() +// Calculate properties set to AUTO when positioning is static, layout vertical +// and direction left-to-right +// ----------------------------------------------------------------------------- +// +static TSize AutoStaticTBL( CXnNode& aNode, TInt aWidthToFit, TInt aHeightToFit, + RArray< TPtrC8 >& aAutoProperties, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + // Static positioning, vertical, left to right + TBool horizontalMarginProcessed( EFalse ); + TBool verticalMarginProcessed( EFalse ); + TBool allVerticalValuesProcessed( EFalse ); + + TRect contentRect( aNode.Rect() ); + TRect paddingRect( aNode.PaddingRect() ); + TRect borderRect( aNode.BorderRect() ); + TRect marginRect( aNode.MarginRect() ); + TRect normalFlowBorderRect( aNode.NormalFlowBorderRect() ); + + TSize size( CalculateTotalDimensionsL( aNode, EFalse, ETrue, aParentRect, + aGraphicsDevice, aHorizontalUnitInPixels, aVerticalUnitInPixels ) ); + + for ( TInt i = 0; i < aAutoProperties.Count(); i++ ) + { + // search for height property + const TDesC8& attributeName = aAutoProperties[i]; + if ( attributeName == XnPropertyNames::style::common::KHeight ) + { + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( normalFlowBorderRect, + contentRect ) ); + + // grow height to fill the void + contentRect.SetHeight( aHeightToFit - size.iHeight ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( + contentRect, normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + size = TSize( size.iWidth, aHeightToFit ); + allVerticalValuesProcessed = ETrue; + } + } + + // if exactly one value is AUTO, value is computed to make equality true + if ( aAutoProperties.Count() == 1 ) + { + if ( !allVerticalValuesProcessed ) + { + const TDesC8& attributeName = aAutoProperties[0]; + if ( attributeName == XnPropertyNames::style::common::KWidth ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( + paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( + normalFlowBorderRect, contentRect ) ); + + // grow width to fill the void + contentRect.SetWidth( remainingWidth ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( contentRect, + normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + size = TSize( aWidthToFit, size.iHeight ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginLeft ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( remainingWidth, 0 ); + paddingRect.Move( remainingWidth, 0 ); + borderRect.Move( remainingWidth, 0 ); + normalFlowBorderRect.Move( remainingWidth, 0 ); + marginRect.Resize( remainingWidth, 0 ); + size = TSize( size.iWidth + remainingWidth, size.iHeight ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginRight ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + marginRect.Resize( remainingWidth, 0 ); + size = TSize( size.iWidth + remainingWidth, size.iHeight ); + } + + if ( attributeName == XnPropertyNames::style::common::KMarginTop ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + contentRect.Move( 0, remainingHeight / 2 ); + paddingRect.Move( 0, remainingHeight / 2 ); + borderRect.Move( 0, remainingHeight / 2 ); + normalFlowBorderRect.Move( 0, remainingHeight / 2 ); + marginRect.Resize( 0, remainingHeight ); + size = TSize( size.iWidth, size.iHeight + remainingHeight ); + } + + if ( attributeName == + XnPropertyNames::style::common::KMarginBottom ) + { + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // set margin rect + marginRect.Resize( 0, remainingHeight ); + size = TSize( size.iWidth, size.iHeight + remainingHeight ); + } + } + } + else + { + for ( TInt i = 0; i < aAutoProperties.Count(); i++ ) + { + const TDesC8& attributeName = aAutoProperties[i]; + if ( attributeName == XnPropertyNames::style::common::KWidth ) + { + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // Calculate the difference so that it can be returned + TRect paddingRectDiff( SubtractRect( + paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( + normalFlowBorderRect, contentRect ) ); + + // grow width to fill the void + contentRect.SetWidth( remainingWidth ); + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + normalFlowBorderRect = AddRect( contentRect, + normalFlowBorderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + size = TSize( aWidthToFit, size.iHeight ); + } + + // several auto properties + if ( attributeName == XnPropertyNames::style::common::KMarginLeft ) + { + if ( !horizontalMarginProcessed ) + { + // is right margin also set to AUTO? + CXnProperty* rightMargin = aNode.MarginRightL(); + if ( rightMargin ) + { + if ( IsPropertyAutoL( *rightMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move(( remainingWidth / 2 ), 0 ); + marginRect.Resize( remainingWidth, 0 ); + borderRect.Move( remainingWidth / 2, 0 ); + normalFlowBorderRect.Move( remainingWidth / 2, 0 ); + paddingRect.Move( remainingWidth / 2, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + else + { + // only left margin set to AUTO + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( remainingWidth, 0 ); + marginRect.Resize( remainingWidth, 0 ); + borderRect.Move( remainingWidth, 0 ); + normalFlowBorderRect.Move( remainingWidth, 0 ); + paddingRect.Move( remainingWidth, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + } + } + } + + if ( attributeName == XnPropertyNames::style::common::KMarginRight ) + { + if ( !horizontalMarginProcessed ) + { + // is left margin also set to AUTO? + CXnProperty* leftMargin = aNode.MarginLeftL(); + if ( leftMargin ) + { + if ( IsPropertyAutoL (*leftMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + contentRect.Move( remainingWidth / 2, 0 ); + marginRect.Resize( remainingWidth, 0 ); + borderRect.Move( remainingWidth / 2, 0 ); + normalFlowBorderRect.Move( remainingWidth / 2, 0 ); + paddingRect.Move( remainingWidth / 2, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + else + { + // only right margin set to AUTO + TInt remainingWidth = aWidthToFit - size.iWidth; + if ( remainingWidth < 0 ) + { + remainingWidth = 0; + } + // move rect right to fill the void + marginRect.Resize( remainingWidth, 0 ); + horizontalMarginProcessed = ETrue; + size = TSize( size.iWidth + remainingWidth, + size.iHeight ); + } + } + } + } + + if ( attributeName == XnPropertyNames::style::common::KMarginTop ) + { + if ( !verticalMarginProcessed && !allVerticalValuesProcessed ) + { + // is bottom margin also set to AUTO? + CXnProperty* bottomMargin = aNode.MarginBottomL(); + if ( bottomMargin ) + { + if ( IsPropertyAutoL( *bottomMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + contentRect.Move( 0, remainingHeight / 2 ); + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, remainingHeight / 2 ); + normalFlowBorderRect.Move( 0, remainingHeight / 2 ); + paddingRect.Move( 0, remainingHeight / 2 ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + else + { + // only top margin set to AUTO + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + contentRect.Move( 0, remainingHeight ); + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, remainingHeight ); + normalFlowBorderRect.Move( 0, remainingHeight ); + paddingRect.Move( 0, remainingHeight ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + } + } + } + + if ( attributeName == + XnPropertyNames::style::common::KMarginBottom ) + { + if ( !verticalMarginProcessed && !allVerticalValuesProcessed ) + { + // is top margin also set to AUTO? + CXnProperty* topMargin = aNode.MarginTopL(); + if ( topMargin ) + { + if ( IsPropertyAutoL( *topMargin ) ) + { + // both margins set to AUTO, values equal + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + TRect normalFlowBorderRect( + aNode.NormalFlowBorderRect() ); + contentRect.Move( 0, remainingHeight / 2 ); + marginRect.Resize( 0, remainingHeight ); + borderRect.Move( 0, remainingHeight / 2 ); + normalFlowBorderRect.Move( 0, remainingHeight / 2 ); + paddingRect.Move( 0, remainingHeight / 2 ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + else + { + // only bottom margin set to AUTO + TInt remainingHeight = aHeightToFit - size.iHeight; + if ( remainingHeight < 0 ) + { + remainingHeight = 0; + } + // move rect right to fill the void + marginRect.Resize( 0, remainingHeight ); + verticalMarginProcessed = ETrue; + size = TSize( size.iWidth, + size.iHeight + remainingHeight ); + } + } + } + } + } + } + aNode.SetRect( contentRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetMarginRect( marginRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + return contentRect.Size(); + } + +// ----------------------------------------------------------------------------- +// CalculateAbsolutePositionsL() +// Move the rect by it's absolute positioning. +// ----------------------------------------------------------------------------- +// +static void CalculateAbsolutePositionsL( CXnNode& aNode, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + CXnProperty* topProperty = aNode.TopL(); + CXnProperty* bottomProperty = aNode.BottomL(); + CXnProperty* leftProperty = aNode.LeftL(); + CXnProperty* rightProperty = aNode.RightL(); + + TBool verticalValuesProcessed = EFalse; + TBool horizontalValuesProcessed = EFalse; + + TInt top = 0; + TInt bottom = 0; + TInt left = 0; + TInt right = 0; + + TRect contentRect( aNode.Rect() ); + TRect paddingRect( aNode.PaddingRect() ); + TRect borderRect( aNode.BorderRect() ); + TRect marginRect( aNode.MarginRect() ); + + if ( HasNodeAutoValuesL( aNode ) ) + { + CXnProperty* marginTopProperty = aNode.MarginTopL(); + CXnProperty* marginBottomProperty = aNode.MarginBottomL(); + CXnProperty* marginLeftProperty = aNode.MarginLeftL(); + CXnProperty* marginRightProperty = aNode.MarginRightL(); + CXnProperty* heightProperty = aNode.HeightL(); + CXnProperty* widthProperty = aNode.WidthL(); + CXnProperty* maxHeightProperty = aNode.MaxHeightL(); + CXnProperty* maxWidthProperty = aNode.MaxWidthL(); + CXnProperty* minHeightProperty = aNode.MinHeightL(); + CXnProperty* minWidthProperty = aNode.MinWidthL(); + + // move auto value node to it's parent's top left corner + TInt offsetx = 0; + TInt offsety = 0; + + offsetx = aParentRect.iTl.iX - marginRect.iTl.iX; + offsety = aParentRect.iTl.iY - marginRect.iTl.iY; + + contentRect.Move( offsetx, offsety ); + paddingRect.Move( offsetx, offsety ); + borderRect.Move( offsetx, offsety ); + marginRect.Move( offsetx, offsety ); + + // get values + if ( topProperty && !IsPropertyAutoL( *topProperty ) && + !IsPropertyNone( *topProperty ) ) + { + top = VerticalPixelValueL( topProperty, aParentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + } + if ( bottomProperty && !IsPropertyAutoL( *bottomProperty ) && + !IsPropertyNone( *bottomProperty ) ) + { + bottom = VerticalPixelValueL( bottomProperty, aParentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + } + if ( leftProperty && !IsPropertyAutoL( *leftProperty ) && + !IsPropertyNone( *leftProperty ) ) + { + left = HorizontalPixelValueL( leftProperty, aParentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + } + if ( rightProperty && !IsPropertyAutoL( *rightProperty ) && + !IsPropertyNone( *rightProperty ) ) + { + right = HorizontalPixelValueL( rightProperty, aParentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + } + // node has auto values + TSize spaceUsed( CalculateTotalDimensionsL( aNode, EFalse, EFalse, + aParentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ) ); + TInt heightToUse = + aParentRect.Height() - spaceUsed.iHeight - top - bottom; + TInt widthToUse = + aParentRect.Width() - spaceUsed.iWidth - left - right; + + if ( heightToUse < 0 ) + { + heightToUse = 0; + } + if ( widthToUse < 0 ) + { + widthToUse = 0; + } + // vertical auto values + // (margin top, margin bottom, height, top, bottom) + if ( IsPropertyAutoL( *heightProperty ) ) + { + contentRect.Resize( 0, heightToUse ); + paddingRect.Resize( 0, heightToUse ); + borderRect.Resize( 0, heightToUse ); + marginRect.Resize( 0, heightToUse ); + + if ( IsLargerThanMaxSizeL( aParentRect, aNode, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ) + { + if ( !IsPropertyNone( *maxHeightProperty ) ) + { + TInt maxheight = HorizontalPixelValueL( maxHeightProperty, + aParentRect.Height(), aGraphicsDevice, + aHorizontalUnitInPixels ); + if ( maxheight < contentRect.Height() ) + { + TInt excessheight = contentRect.Height() - maxheight; + contentRect.Resize( 0, -excessheight ); + paddingRect.Resize( 0, -excessheight ); + borderRect.Resize( 0, -excessheight ); + marginRect.Resize( 0, -excessheight ); + } + } + } + if ( IsSmallerThanMinSizeL( aParentRect, aNode, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ) + { + if ( !IsPropertyNone( *minHeightProperty ) ) + { + TInt minheight = HorizontalPixelValueL( minHeightProperty, + aParentRect.Height(), aGraphicsDevice, + aHorizontalUnitInPixels ); + if ( minheight > contentRect.Height() ) + { + TInt missingheight = minheight - contentRect.Height(); + contentRect.Resize( 0, missingheight ); + paddingRect.Resize( 0, missingheight ); + borderRect.Resize( 0, missingheight ); + marginRect.Resize( 0, missingheight ); + } + } + } + verticalValuesProcessed = ETrue; + } + + if ( !verticalValuesProcessed ) + { + if ( IsPropertyAutoL( *topProperty ) && + IsPropertyAutoL( *bottomProperty ) ) + { + // move the box down + contentRect.Move( 0, heightToUse / 2 ); + paddingRect.Move( 0, heightToUse / 2 ); + borderRect.Move( 0, heightToUse / 2 ); + marginRect.Move( 0, heightToUse / 2 ); + } + if ( IsPropertyAutoL( *topProperty ) && + !IsPropertyAutoL( *bottomProperty ) ) + { + // move the box down + contentRect.Move( 0, heightToUse ); + paddingRect.Move( 0, heightToUse ); + borderRect.Move( 0, heightToUse ); + marginRect.Move( 0, heightToUse ); + } + if ( IsPropertyAutoL( *marginTopProperty ) && + IsPropertyAutoL( *marginBottomProperty ) ) + { + // both margins auto, equal values + marginRect.Resize( 0, heightToUse ); + paddingRect.Move( 0, heightToUse / 2 ); + borderRect.Move( 0, heightToUse / 2 ); + contentRect.Move( 0, heightToUse / 2 ); + } + if ( !IsPropertyAutoL( *marginTopProperty ) && + IsPropertyAutoL( *marginBottomProperty ) ) + { + // only top margin auto + marginRect.Resize( 0, heightToUse ); + paddingRect.Move( 0, heightToUse ); + borderRect.Move( 0, heightToUse ); + contentRect.Move( 0, heightToUse ); + } + if ( IsPropertyAutoL( *marginTopProperty ) && + !IsPropertyAutoL( *marginBottomProperty ) ) + { + // only bottom margin auto + marginRect.Resize( 0, heightToUse ); + } + } + + // horizontal auto values + // (margin left, margin right, width) + if ( IsPropertyAutoL( *widthProperty ) ) + { + contentRect.Resize( widthToUse, 0 ); + paddingRect.Resize( widthToUse, 0 );; + borderRect.Resize( widthToUse, 0 ); + marginRect.Resize( widthToUse, 0 ); + if ( IsLargerThanMaxSizeL( aParentRect, aNode, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ) + { + if ( !IsPropertyNone( *maxWidthProperty ) ) + { + TInt maxwidth = HorizontalPixelValueL( maxWidthProperty, + aParentRect.Width(), aGraphicsDevice, + aHorizontalUnitInPixels ); + if ( maxwidth < contentRect.Width() ) + { + TInt excesswidth = contentRect.Width() - maxwidth; + contentRect.Resize( -excesswidth, 0 ); + paddingRect.Resize( -excesswidth, 0 ); + borderRect.Resize( -excesswidth, 0 ); + marginRect.Resize( -excesswidth, 0 ); + } + } + } + if ( IsSmallerThanMinSizeL( aParentRect, aNode, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ) + { + if ( !IsPropertyNone( *minWidthProperty ) ) + { + TInt minwidth = HorizontalPixelValueL( minWidthProperty, + aParentRect.Width(), aGraphicsDevice, + aHorizontalUnitInPixels ); + if ( minwidth > contentRect.Width() ) + { + TInt missingwidth = minwidth - contentRect.Width(); + contentRect.Resize( missingwidth, 0 ); + paddingRect.Resize( missingwidth, 0 ); + borderRect.Resize( missingwidth, 0 ); + marginRect.Resize( missingwidth, 0 ); + } + } + } + horizontalValuesProcessed = ETrue; + } + if ( !horizontalValuesProcessed ) + { + if ( IsPropertyAutoL( *leftProperty ) && + IsPropertyAutoL( *rightProperty ) ) + { + // move the box left + contentRect.Move( widthToUse / 2, 0 ); + paddingRect.Move( widthToUse / 2, 0 ); + borderRect.Move( widthToUse / 2, 0 ); + marginRect.Move( widthToUse / 2, 0 ); + } + if ( IsPropertyAutoL( *leftProperty ) && + !IsPropertyAutoL( *rightProperty ) ) + { + // move the box left + contentRect.Move( widthToUse, 0 ); + paddingRect.Move( widthToUse, 0 ); + borderRect.Move( widthToUse, 0 ); + marginRect.Move( widthToUse, 0 ); + } + if ( IsPropertyAutoL( *marginLeftProperty ) && + IsPropertyAutoL( *marginRightProperty ) ) + { + // both margins auto, equal values + marginRect.Resize( widthToUse, 0 ); + paddingRect.Move( widthToUse / 2, 0 ); + borderRect.Move( widthToUse / 2, 0 ); + contentRect.Move( widthToUse / 2, 0 ); + } + if ( !IsPropertyAutoL( *marginLeftProperty ) && + IsPropertyAutoL( *marginRightProperty ) ) + { + // only right margin auto + marginRect.Resize( widthToUse, 0 ); + paddingRect.Move( widthToUse, 0 ); + borderRect.Move( widthToUse, 0 ); + contentRect.Move( widthToUse, 0 ); + } + if ( IsPropertyAutoL( *marginLeftProperty ) && + !IsPropertyAutoL( *marginRightProperty ) ) + { + // only left margin auto + marginRect.Resize( widthToUse, 0 ); + } + } + } + + // Move the rect to desired position + if ( topProperty ) + { + if ( !IsPropertyAutoL( *topProperty ) && + !IsPropertyNone( *topProperty ) ) + { + TInt y = VerticalPixelValueL( topProperty, aParentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + contentRect.Move( 0, y ); + paddingRect.Move( 0, y ); + borderRect.Move( 0, y ); + marginRect.Move( 0, y ); + } + } + if ( leftProperty ) + { + if ( !IsPropertyAutoL( *leftProperty ) && + !IsPropertyNone( *leftProperty ) ) + { + TInt x = HorizontalPixelValueL( leftProperty, aParentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + contentRect.Move( x, 0 ); + paddingRect.Move( x, 0 ); + borderRect.Move( x, 0 ); + marginRect.Move( x, 0 ); + } + } + if ( bottomProperty ) + { + if ( !IsPropertyAutoL( *bottomProperty ) && + !IsPropertyNone( *bottomProperty ) ) + { + TInt py = VerticalPixelValueL( bottomProperty, + aParentRect.Height(), aGraphicsDevice, aVerticalUnitInPixels ); + contentRect.Move( 0, -py ); + paddingRect.Move( 0, -py ); + borderRect.Move( 0, -py ); + marginRect.Move( 0, -py ); + } + } + if ( rightProperty ) + { + if ( !IsPropertyAutoL( *rightProperty ) && + !IsPropertyNone( *rightProperty ) ) + { + TInt px = HorizontalPixelValueL( rightProperty, + aParentRect.Width(), aGraphicsDevice, aHorizontalUnitInPixels ); + contentRect.Move( -px, 0 ); + paddingRect.Move( -px, 0 ); + borderRect.Move( -px, 0 ); + marginRect.Move( -px, 0 ); + } + } + + aNode.SetRect( contentRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetMarginRect( marginRect ); + + DropExceedingRectL( aParentRect, aNode ); + } + +// ----------------------------------------------------------------------------- +// CalculateBorderL() +// Move the rect by adding the border. +// ----------------------------------------------------------------------------- +// +static void CalculateBorderL( CXnNode& aNode, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + TInt offsetx = 0; + TInt offsety = 0; + + TInt borderleft = 0; + TInt borderright = 0; + TInt bordertop = 0; + TInt borderbottom = 0; + + CXnProperty* commonBorderStyle = aNode.BorderStyleL(); + CXnProperty* borderImage = aNode.BorderImageL(); + CXnProperty* borderStyle = aNode.BorderLeftStyleL(); + CXnProperty* borderproperty = aNode.BorderLeftL(); + + // if border width is defined + CXnProperty* borderwidthproperty = aNode.BorderWidthL(); + if ( !borderproperty ) + { + borderproperty = borderwidthproperty; + } + + if ( borderwidthproperty && ( ( commonBorderStyle && + !IsPropertyNone( *commonBorderStyle ) ) || + ( borderImage && !IsPropertyNone( *borderImage ) ) ) ) + { + TInt bordervertical = 0; + TInt borderhorizontal = 0; + + DetermineBorderWidthsL( borderwidthproperty, bordervertical, + borderhorizontal, aParentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + + borderleft = borderhorizontal; + borderright = borderhorizontal; + bordertop = bordervertical; + borderbottom = bordervertical; + } + + TInt ignore; + // use border width only if there is valid border style or border image + if ( borderproperty && ( ( borderStyle && + !IsPropertyNone( *borderStyle ) ) || + ( commonBorderStyle && !IsPropertyNone( *commonBorderStyle ) ) || + ( borderImage && !IsPropertyNone( *borderImage ) ) ) ) + { + DetermineBorderWidthsL( borderproperty, ignore, borderleft, + aParentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + } + borderStyle = aNode.BorderRightStyleL(); + borderproperty = aNode.BorderRightL(); + if ( !borderproperty ) + { + borderproperty = borderwidthproperty; + } + if ( borderproperty && ( ( borderStyle && + !IsPropertyNone( *borderStyle ) ) || + ( commonBorderStyle && !IsPropertyNone( *commonBorderStyle ) ) || + ( borderImage && !IsPropertyNone( *borderImage ) ) ) ) + { + DetermineBorderWidthsL( borderproperty, ignore, borderright, + aParentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + } + borderStyle = aNode.BorderTopStyleL(); + borderproperty = aNode.BorderTopL(); + if ( !borderproperty ) + { + borderproperty = borderwidthproperty; + } + if ( borderproperty && ( ( borderStyle && + !IsPropertyNone( *borderStyle ) ) || + ( commonBorderStyle && !IsPropertyNone( *commonBorderStyle ) ) || + ( borderImage && !IsPropertyNone( *borderImage ) ) ) ) + { + DetermineBorderWidthsL( borderproperty, bordertop, ignore, + aParentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + } + borderStyle = aNode.BorderBottomStyleL(); + borderproperty = aNode.BorderBottomL(); + if ( !borderproperty ) + { + borderproperty = borderwidthproperty; + } + if ( borderproperty && ( ( borderStyle && + !IsPropertyNone( *borderStyle ) ) || + ( commonBorderStyle && !IsPropertyNone( *commonBorderStyle ) ) || + ( borderImage && !IsPropertyNone( *borderImage ) ) ) ) + { + DetermineBorderWidthsL( borderproperty, borderbottom, ignore, + aParentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + } + + offsetx = borderleft; // move the client rect of the element this much right + offsety = bordertop; // move the client rect of the element this much down + + TRect newrect( aNode.Rect() ); + newrect.Move( offsetx, offsety ); + aNode.SetRect( newrect ); + // and move the padding rect also, Ari 5.8.2005 + TRect paddingrect = aNode.PaddingRect(); + TPoint origin( paddingrect.iTl ); + paddingrect.Move( offsetx, offsety ); + aNode.SetPaddingRect( paddingrect ); + + TRect borderrect( origin, TSize( + borderleft + borderright + paddingrect.Width(), + bordertop + borderbottom + paddingrect.Height() ) ); + TRect normalFlowBorderRect( origin, TSize( + borderleft + borderright + paddingrect.Width(), + bordertop + borderbottom + paddingrect.Height() ) ); + aNode.SetBorderRect( borderrect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + } + +// ----------------------------------------------------------------------------- +// CalculateAbsoluteMarginL() +// Place child areas to parent rect and calculate margins. +// ----------------------------------------------------------------------------- +// +static void CalculateAbsoluteMarginL( CXnNode& aParent, CXnNode& aNode, + CXnNode* aPreviousSibling, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + TInt previousPosition = 0; + CXnProperty* marginProperty = NULL; + TInt marginLeft = 0; + TInt marginRight = 0; + TInt marginTop = 0; + TInt marginBottom = 0; + + marginProperty = aNode.MarginLeftL(); + + if ( marginProperty ) + { + if ( !IsPropertyAutoL( *marginProperty ) ) + { + marginLeft = HorizontalPixelValueL( marginProperty, + aParentRect.Width(), aGraphicsDevice, aHorizontalUnitInPixels ); + } + } + + marginProperty = aNode.MarginRightL(); + + if ( marginProperty ) + { + if ( !IsPropertyAutoL( *marginProperty ) ) + { + marginRight = HorizontalPixelValueL( marginProperty, + aParentRect.Width(), aGraphicsDevice, aHorizontalUnitInPixels ); + } + } + + marginProperty = aNode.MarginTopL(); + + if ( marginProperty ) + { + if ( !IsPropertyAutoL( *marginProperty ) ) + { + marginTop = VerticalPixelValueL( marginProperty, + aParentRect.Height(), aGraphicsDevice, aVerticalUnitInPixels ); + } + } + + marginProperty = aNode.MarginBottomL(); + + if ( marginProperty ) + { + if ( !IsPropertyAutoL( *marginProperty ) ) + { + marginBottom = VerticalPixelValueL( marginProperty, + aParentRect.Height(), aGraphicsDevice, aVerticalUnitInPixels ); + } + } + + TInt offsetx = 0; + TInt offsety = 0; + + if ( &aParent == &aNode ) + { + aParentRect.Move( -aParentRect.iTl.iX, -aParentRect.iTl.iY ); + } + + // if all properties are defined and block progression is LR, margin right + // is ignored and replaced by remaining + // if block progression is RL, same thing to margin left + + // previous sibling was found, get it's margin and previous coordinate to + // define next child's position + previousPosition = ( aPreviousSibling != NULL ) ? + GetPositionL( *aPreviousSibling, aParentBlockProgression, + aParentDirection ) : 0; + + // Move the rect considering previous child + // Margins are collapsed, larger is used + if ( aParentDirection == XnPropertyNames::style::common::direction::KLTR ) + { + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + // offset to parent rect's top left corner + if ( !aPreviousSibling ) + { + offsetx = aParentRect.iTl.iX; + } + + offsety = aParentRect.iTl.iY + marginTop; + TInt prevMarginRight = 0; + + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + prevMarginRight = + previousMarginRect.iBr.iX - previousBorderRect.iBr.iX; + } + + if ( prevMarginRight > marginLeft ) + { + offsetx += previousPosition + prevMarginRight; + } + else + { + offsetx += previousPosition + marginLeft; + } + } + else // TB or BT + { + // offset to parent rect's top left corner + offsetx = aParentRect.iTl.iX + marginLeft; + + if ( !aPreviousSibling ) + { + offsety = aParentRect.iTl.iY; + } + + TInt prevMarginBottom = 0; + + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + prevMarginBottom = + previousMarginRect.iBr.iY - previousBorderRect.iBr.iY; + } + + if ( prevMarginBottom > marginTop ) + { + offsety += previousPosition + prevMarginBottom; + } + else + { + offsety += previousPosition + marginTop; + } + } + } + else // RTL + { + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + // offset to parent rect's top right corner + if ( !aPreviousSibling ) + { + offsetx = aParentRect.Width() - aNode.BorderRect().Width() + + aParentRect.iTl.iX; + } + else + { + offsetx = previousPosition - aNode.BorderRect().Width(); + } + + offsety = aParentRect.iTl.iY + marginTop; + + TInt prevMarginLeft = 0; + + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + prevMarginLeft = + previousBorderRect.iTl.iX - previousMarginRect.iTl.iX; + } + + if ( prevMarginLeft > marginRight ) + { + offsetx -= prevMarginLeft; + } + else + { + offsetx -= marginRight; + } + } + else // TB or BT + { + // offset to parent rect's bottom left corner + offsetx += aParentRect.iTl.iX + marginRight; + + if ( !aPreviousSibling ) + { + // start from bottom of parent rect + offsety = aParentRect.Height() - aNode.BorderRect().Height(); + } + else + { + offsety = previousPosition - aNode.BorderRect().Height(); + } + + TInt prevMarginTop = 0; + + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + prevMarginTop = + previousBorderRect.iTl.iY - previousMarginRect.iTl.iY; + } + + // collapse margins + if ( prevMarginTop > marginBottom ) + { + offsety -= prevMarginTop; + } + else + { + offsety -= marginBottom; + } + } + } + + TRect borderRect = TRect( aNode.BorderRect() ); + TRect normalFlowBorderRect = TRect( aNode.NormalFlowBorderRect() ); + // this is the top left corner of margin rect + TPoint origin( borderRect.iTl - TPoint( marginLeft, marginTop ) ); + + if ( &aParent != &aNode ) + { + // set content rect + TRect newRect( aNode.Rect() ); + newRect.Move( offsetx, offsety ); + aNode.SetRect( newRect ); + + // set padding rect + TRect paddingRect( aNode.PaddingRect() ); + paddingRect.Move( offsetx, offsety ); + aNode.SetPaddingRect( paddingRect ); + + // set border rect + borderRect.Move( offsetx, offsety ); + normalFlowBorderRect.Move( offsetx, offsety ); + // this is the top left corner of margin rect + origin = TPoint( borderRect.iTl - TPoint( marginLeft, marginTop ) ); + aNode.SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + } + + TRect marginRect( origin, + TSize( marginLeft + marginRight + borderRect.Width(), + marginTop + marginBottom + borderRect.Height() ) ); + + aNode.SetMarginRect( marginRect ); + + // Within this function, the rects are adjusted if the display-priority is 0 + // and margin rect exceeds parent's content rect. + DropExceedingRectL( aParentRect, aNode ); + + if( IsNodeTooltip( aNode ) || aNode.Type()->Type() == KWidgetExtensionNodeName || + aNode.Type()->Type() == KPopUpNodeName ) + { + // because tooltip has it's own window, move margin rect to 0,0 + // and all other rects as much up left + TRect marginRect = aNode.MarginRect(); + + TRect borderRect = aNode.BorderRect(); + TRect paddingRect = aNode.PaddingRect(); + TRect contentRect = aNode.Rect(); + TInt x = marginRect.iTl.iX; + TInt y = marginRect.iTl.iY; + marginRect.Move( -x, -y ); + + borderRect.Move( -x, -y ); + paddingRect.Move( -x, -y ); + contentRect.Move( -x, -y ); + + aNode.SetMarginRect( marginRect ); + + aNode.SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetRect( contentRect ); + } + } + +// ----------------------------------------------------------------------------- +// CalculateAbsoluteMarginL() +// Place child areas to parent rect and calculate margins. +// ----------------------------------------------------------------------------- +// +static void CalculateMarginL( CXnNode& aParent, CXnNode& aNode, + CXnNode* aPreviousSibling, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels, TInt& aColumnWidth, TInt& aColumnMargin ) + { + if( aParent.Control() && aParent.Control()->OwnsWindow() ) + { + aParentRect = TRect( aParentRect.iTl - aParent.MarginRect().iTl, aParentRect.Size() ); + } + + CXnProperty* marginProperty = NULL; + TInt marginLeft = 0; + TInt marginRight = 0; + TInt marginTop = 0; + TInt marginBottom = 0; + + marginProperty = aNode.MarginLeftL(); + if ( marginProperty ) + { + if ( !IsPropertyAutoL( *marginProperty ) ) + { + marginLeft = HorizontalPixelValueL( + marginProperty, aParentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + } + } + + marginProperty = aNode.MarginRightL(); + if ( marginProperty ) + { + if ( !IsPropertyAutoL( *marginProperty ) ) + { + marginRight = HorizontalPixelValueL( + marginProperty, aParentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + } + } + + marginProperty = aNode.MarginTopL(); + if ( marginProperty ) + { + if ( !IsPropertyAutoL( *marginProperty ) ) + { + marginTop = VerticalPixelValueL( + marginProperty, aParentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + } + } + + marginProperty = aNode.MarginBottomL(); + if ( marginProperty ) + { + if ( !IsPropertyAutoL( *marginProperty ) ) + { + marginBottom = VerticalPixelValueL( + marginProperty, aParentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + } + } + + TInt offsetx = 0; + TInt offsety = 0; + + //What's this??? + if ( &aParent == &aNode ) + { + aParentRect.Move( -aParentRect.iTl.iX, -aParentRect.iTl.iY ); + } + + // Move the rect considering previous child + // Margins are collapsed, larger is used + if ( aParentDirection == XnPropertyNames::style::common::direction::KLTR ) + { + // LTR , TB + // ********* + // | 1 | 4 | + // | 2 | 5 | + // | 3 | 6 | + // ********* + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB ) + { + // First we need to know where to layout next sibling + // Try first under the previous sibling... + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + TBool layoutUnderPrevious( EFalse ); + TInt height = aNode.MarginRect().Height(); + TInt prevMarginBottom = + previousMarginRect.iBr.iY - previousBorderRect.iBr.iY; + if ( prevMarginBottom < marginTop ) + { + height -= prevMarginBottom; + } + else + { + height -= marginTop; + } + if(height <= aParentRect.iBr.iY - previousMarginRect.iBr.iY || IsSrollableBox(aNode)) + { + layoutUnderPrevious = ETrue; + } + + // ...then to the next column + if ( !layoutUnderPrevious ) + { + TInt width = + aNode.BorderRect().Width() + marginLeft + marginRight; + if ( aColumnMargin < marginLeft ) + { + width -= aColumnMargin; + } + else + { + width -= marginLeft; + } + if ( width + aColumnWidth <= aParentRect.Width() ) + { + offsety = aParentRect.iTl.iY + marginTop; + if ( aColumnMargin < marginLeft ) + { + offsetx = aParentRect.iTl.iX + aColumnWidth - + aColumnMargin + marginLeft; + } + else + { + offsetx = aParentRect.iTl.iX + aColumnWidth; + } + } + else + { + layoutUnderPrevious = ETrue; + } + } + if ( layoutUnderPrevious ) + { + offsetx = + aPreviousSibling->MarginRect().iTl.iX + marginLeft; + if ( prevMarginBottom > marginTop ) + { + // margin of this node is collapsed + offsety = previousMarginRect.iBr.iY; + } + else + { + // margin of the previous node is collapsed + offsety = previousBorderRect.iBr.iY + marginTop; + } + } + } + else + { + // offset to parent rect's top left corner + offsetx = aParentRect.iTl.iX + marginLeft; + offsety = aParentRect.iTl.iY + marginTop; + } + } + + // LTR , BT + // ********* + // | 3 | 6 | + // | 2 | 5 | + // | 1 | 4 | + // ********* + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + // First we need to know where to layout next sibling + // Try first above the previous sibling... + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + TBool layoutAbovePrevious( EFalse ); + TInt height = + aNode.BorderRect().Height() + marginTop + marginBottom; + TInt prevMarginTop = + previousBorderRect.iTl.iY - previousMarginRect.iTl.iY; + if ( prevMarginTop < marginBottom ) + { + height -= prevMarginTop; + } + else + { + height -= marginBottom; + } + if ( height <= previousMarginRect.iTl.iY - aParentRect.iTl.iY ) + { + layoutAbovePrevious = ETrue; + } + + // ...then to the next column + if ( !layoutAbovePrevious ) + { + TInt width = + aNode.BorderRect().Width() + marginLeft + marginRight; + if ( aColumnMargin < marginLeft ) + { + width -= aColumnMargin; + } + else + { + width -= marginLeft; + } + if ( width + aColumnWidth <= aParentRect.Width() ) + { + offsety = aParentRect.iBr.iY - marginBottom - + aNode.BorderRect().Height(); + if ( aColumnMargin < marginLeft ) + { + offsetx = aParentRect.iTl.iX + aColumnWidth - + aColumnMargin + marginLeft; + } + else + { + offsetx = aParentRect.iTl.iX + aColumnWidth; + } + } + else + { + layoutAbovePrevious = ETrue; + } + } + if ( layoutAbovePrevious ) + { + offsetx = + aPreviousSibling->MarginRect().iTl.iX + marginLeft; + if ( prevMarginTop > marginBottom ) + { + // margin of this node is collapsed + offsety = previousMarginRect.iTl.iY - + aNode.BorderRect().Height(); + } + else + { + // margin of the previous node is collapsed + offsety = previousBorderRect.iTl.iY - marginBottom - + aNode.BorderRect().Height(); + } + } + } + else + { + offsetx = aParentRect.iTl.iX + marginLeft; + offsety = aParentRect.iBr.iY - marginBottom - + aNode.BorderRect().Height(); + } + } + + // LTR , LR + // ********* + // | 5 | 6 | + // | 3 | 4 | + // | 1 | 2 | + // ********* + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR ) + { + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + TBool layoutNextToPrevious( EFalse ); + TInt width = + aNode.BorderRect().Width() + marginRight + marginLeft; + TInt prevMarginRight = + previousMarginRect.iBr.iX - previousBorderRect.iBr.iX; + if ( prevMarginRight < marginLeft ) + { + width -= prevMarginRight; + } + else + { + width -= marginLeft; + } + if ( width <= aParentRect.iBr.iX - previousMarginRect.iBr.iX ) + { + layoutNextToPrevious = ETrue; + } + + if ( !layoutNextToPrevious ) + { + TInt height = aNode.BorderRect().Height() + marginTop + + marginBottom; + if ( aColumnMargin < marginBottom ) + { + height -= aColumnMargin; + } + else + { + height -= marginBottom; + } + if ( height + aColumnWidth <= aParentRect.Height() ) + { + offsetx = aParentRect.iTl.iX + marginLeft; + if ( aColumnMargin < marginTop ) + { + offsety = aParentRect.iBr.iY - aColumnWidth + + aColumnMargin - aNode.BorderRect().Height() - + marginBottom; + } + else + { + offsety = aParentRect.iBr.iY - aColumnWidth - + aNode.BorderRect().Height(); + } + } + else + { + layoutNextToPrevious = ETrue; + } + } + if ( layoutNextToPrevious ) + { + offsety = aPreviousSibling->MarginRect().iBr.iY - + aNode.BorderRect().Height() - marginBottom; + if ( prevMarginRight > marginLeft ) + { + // margin of this node is collapsed + offsetx = previousMarginRect.iBr.iX; + } + else + { + // margin of the previous node is collapsed + offsetx = previousBorderRect.iBr.iX + marginLeft; + } + } + } + else + { + offsetx = aParentRect.iTl.iX + marginLeft; + offsety = aParentRect.iBr.iY - aNode.BorderRect().Height() - + marginBottom; + } + } + + // LTR , RL + // ********* + // | 1 | 2 | + // | 3 | 4 | + // | 5 | 6 | + // ********* + + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + TBool layoutNextToPrevious( EFalse ); + TInt width = + aNode.BorderRect().Width() + marginRight + marginLeft; + TInt prevMarginRight = + previousMarginRect.iBr.iX - previousBorderRect.iBr.iX; + if ( prevMarginRight < marginLeft ) + { + width -= prevMarginRight; + } + else + { + width -= marginLeft; + } + if ( width <= aParentRect.iBr.iX - previousMarginRect.iBr.iX ) + { + layoutNextToPrevious = ETrue; + } + + if ( !layoutNextToPrevious ) + { + TInt height = + aNode.BorderRect().Height() + marginTop + marginBottom; + if ( aColumnMargin < marginTop ) + { + height -= aColumnMargin; + } + else + { + height -= marginTop; + } + if ( height + aColumnWidth <= aParentRect.Height() ) + { + offsetx = aParentRect.iTl.iX + marginLeft; + if ( aColumnMargin < marginTop ) + { + offsety = aParentRect.iTl.iY + aColumnWidth - + aColumnMargin + marginTop; + } + else + { + offsety = aParentRect.iTl.iY + aColumnWidth; + } + } + else + { + layoutNextToPrevious = ETrue; + } + } + if ( layoutNextToPrevious ) + { + offsety = aPreviousSibling->MarginRect().iTl.iY + marginTop; + if ( prevMarginRight > marginLeft ) + { + // margin of this node is collapsed + offsetx = previousMarginRect.iBr.iX; + } + else + { + // margin of the previous node is collapsed + offsetx = previousBorderRect.iBr.iX + marginLeft; + } + } + } + else + { + offsetx = aParentRect.iTl.iX + marginLeft; + offsety = aParentRect.iTl.iY + marginTop; + } + } + } + + else + { + // RTL , TB + // ********* + // | 4 | 1 | + // | 5 | 2 | + // | 6 | 3 | + // ********* + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB ) + { + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + TBool layoutUnderPrevious( EFalse ); + TInt height = aNode.MarginRect().Height(); + TInt prevMarginBottom = + previousMarginRect.iBr.iY - previousBorderRect.iBr.iY; + if ( prevMarginBottom < marginTop ) + { + height -= prevMarginBottom; + } + else + { + height -= marginTop; + } + if ( height <= aParentRect.iBr.iY - previousMarginRect.iBr.iY ) + { + layoutUnderPrevious = ETrue; + } + + if ( !layoutUnderPrevious ) + { + TInt width = + aNode.BorderRect().Width() + marginLeft + marginRight; + if ( aColumnMargin < marginLeft ) + { + width -= aColumnMargin; + } + else + { + width -= marginLeft; + } + if ( width + aColumnWidth <= aParentRect.Width() ) + { + offsety = aParentRect.iTl.iY + marginTop; + if ( aColumnMargin < marginLeft ) + { + offsetx = aParentRect.iBr.iX - aColumnWidth + + aColumnMargin - marginRight - + aNode.BorderRect().Width(); + } + else + { + offsetx = aParentRect.iBr.iX - aColumnWidth - + aNode.BorderRect().Width(); + } + } + else + { + layoutUnderPrevious = ETrue; + } + } + if ( layoutUnderPrevious ) + { + offsetx = aPreviousSibling->MarginRect().iBr.iX - + marginRight - aNode.BorderRect().Width(); + if ( prevMarginBottom > marginTop ) + { + offsety = previousMarginRect.iBr.iY; + } + else + { + offsety = previousBorderRect.iBr.iY + marginTop; + } + } + } + else + { + offsetx = aParentRect.iBr.iX - marginRight - + aNode.BorderRect().Width(); + offsety = aParentRect.iTl.iY + marginTop; + } + } + + // RTL , BT + // ********* + // | 6 | 3 | + // | 5 | 2 | + // | 4 | 1 | + // ********* + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + TBool layoutAbovePrevious( EFalse ); + TInt height = + aNode.BorderRect().Height() + marginTop + marginBottom; + TInt prevMarginTop = + previousBorderRect.iTl.iY - previousMarginRect.iTl.iY; + if ( prevMarginTop < marginBottom ) + { + height -= prevMarginTop; + } + else + { + height -= marginBottom; + } + if ( height <= previousMarginRect.iTl.iY - aParentRect.iTl.iY ) + { + layoutAbovePrevious = ETrue; + } + + if ( !layoutAbovePrevious ) + { + TInt width = + aNode.BorderRect().Width() + marginLeft + marginRight; + if ( aColumnMargin < marginRight ) + { + width -= aColumnMargin; + } + else + { + width -= marginRight; + } + if ( width + aColumnWidth <= aParentRect.Width() ) + { + offsety = aParentRect.iBr.iY - marginBottom - + aNode.BorderRect().Height(); + if ( aColumnMargin < marginLeft ) + { + offsetx = aParentRect.iBr.iX - aColumnWidth + + aColumnMargin - marginRight - + aNode.BorderRect().Width(); + } + else + { + offsetx = aParentRect.iBr.iX - aColumnWidth - + aNode.BorderRect().Width(); + } + } + else + { + layoutAbovePrevious = ETrue; + } + } + if ( layoutAbovePrevious ) + { + offsetx = aPreviousSibling->MarginRect().iBr.iX - + marginRight - aNode.BorderRect().Width(); + if ( prevMarginTop > marginBottom ) + { + // margin of this node is collapsed + offsety = previousMarginRect.iTl.iY - + aNode.BorderRect().Height(); + } + else + { + // margin of the previous node is collapsed + offsety = previousBorderRect.iTl.iY - marginBottom - + aNode.BorderRect().Height(); + } + } + } + else + { + offsetx = aParentRect.iBr.iX - marginRight - + aNode.BorderRect().Width(); + offsety = aParentRect.iBr.iY - marginBottom - + aNode.BorderRect().Height(); + } + } + + // RTL , LR + // ********* + // | 6 | 5 | + // | 4 | 3 | + // | 2 | 1 | + // ********* + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR ) + { + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + TBool layoutNextToPrevious( EFalse ); + TInt width = + aNode.BorderRect().Width() + marginRight + marginLeft; + TInt prevMarginLeft = + previousBorderRect.iTl.iX - previousMarginRect.iTl.iX; + if ( prevMarginLeft < marginRight ) + { + width -= prevMarginLeft; + } + else + { + width -= marginRight; + } + if ( width <= previousMarginRect.iTl.iX - aParentRect.iTl.iX ) + { + layoutNextToPrevious = ETrue; + } + + if ( !layoutNextToPrevious ) + { + TInt height = + aNode.BorderRect().Height() + marginTop + marginBottom; + if ( aColumnMargin < marginBottom ) + { + height -= aColumnMargin; + } + else + { + height -= marginBottom; + } + if ( height + aColumnWidth <= aParentRect.Height() ) + { + offsetx = aParentRect.iBr.iX - marginRight - + aNode.BorderRect().Width(); + if ( aColumnMargin < marginTop ) + { + offsety = aParentRect.iBr.iY - aColumnWidth + + aColumnMargin - aNode.BorderRect().Height() - + marginBottom; + } + else + { + offsety = aParentRect.iBr.iY - aColumnWidth - + aNode.BorderRect().Height(); + } + } + else + { + layoutNextToPrevious = ETrue; + } + } + if ( layoutNextToPrevious ) + { + offsety = aPreviousSibling->MarginRect().iBr.iY - + aNode.BorderRect().Height() - marginBottom; + if ( prevMarginLeft > marginRight ) + { + offsetx = previousMarginRect.iTl.iX - + aNode.BorderRect().Width(); + } + else + { + offsetx = previousBorderRect.iTl.iX - marginRight - + aNode.BorderRect().Width(); + } + } + } + else + { + offsetx = aParentRect.iBr.iX - marginRight - + aNode.BorderRect().Width(); + offsety = aParentRect.iBr.iY - marginBottom - + aNode.BorderRect().Height(); + } + } + + // RTL , RL + // ********* + // | 2 | 1 | + // | 4 | 3 | + // | 6 | 5 | + // ********* + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + if ( aPreviousSibling ) + { + TRect previousMarginRect = aPreviousSibling->MarginRect(); + TRect previousBorderRect = aPreviousSibling->BorderRect(); + TBool layoutNextToPrevious( EFalse ); + TInt width = + aNode.BorderRect().Width() + marginRight + marginLeft; + TInt prevMarginLeft = + previousBorderRect.iTl.iX - previousMarginRect.iTl.iX; + if ( prevMarginLeft < marginRight ) + { + width -= prevMarginLeft; + } + else + { + width -= marginRight; + } + if ( width <= previousMarginRect.iTl.iX - aParentRect.iTl.iX ) + { + layoutNextToPrevious = ETrue; + } + if ( !layoutNextToPrevious ) + { + TInt height = + aNode.BorderRect().Height() + marginTop + marginBottom; + if ( aColumnMargin < marginTop ) + { + height -= aColumnMargin; + } + else + { + height -= marginTop; + } + if ( height + aColumnWidth <= aParentRect.Height() ) + { + offsetx = aParentRect.iBr.iX - marginRight - + aNode.BorderRect().Width(); + if ( aColumnMargin < marginTop ) + { + offsety = aParentRect.iTl.iY + aColumnWidth - + aColumnMargin + marginTop; + } + else + { + offsety = aParentRect.iTl.iY + aColumnWidth; + } + } + else + { + layoutNextToPrevious = ETrue; + } + } + if ( layoutNextToPrevious ) + { + offsety = aPreviousSibling->MarginRect().iTl.iY + marginTop; + if ( prevMarginLeft > marginRight ) + { + offsetx = previousMarginRect.iTl.iX - + aNode.BorderRect().Width(); + } + else + { + offsetx = previousBorderRect.iTl.iX - marginRight - + aNode.BorderRect().Width(); + } + } + } + else + { + offsetx = aParentRect.iBr.iX - marginRight - + aNode.BorderRect().Width(); + offsety = aParentRect.iTl.iY + marginTop; + } + } + } + + TRect borderRect = TRect( aNode.BorderRect() ); + TRect normalFlowBorderRect = TRect( aNode.NormalFlowBorderRect() ); + // this is the top left corner of margin rect + TPoint origin( borderRect.iTl - TPoint( marginLeft, marginTop ) ); + + if ( &aParent != &aNode ) + { + // set content rect + TRect newRect( aNode.Rect() ); + newRect.Move( offsetx, offsety ); + aNode.SetRect( newRect ); + + // set padding rect + TRect paddingRect( aNode.PaddingRect() ); + paddingRect.Move( offsetx, offsety ); + aNode.SetPaddingRect( paddingRect ); + + // set border rect + borderRect.Move( offsetx, offsety ); + normalFlowBorderRect.Move( offsetx, offsety ); + // this is the top left corner of margin rect + origin = TPoint( borderRect.iTl - TPoint( marginLeft, marginTop ) ); + aNode.SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + } + + TRect marginRect( origin, + TSize( marginLeft + marginRight + borderRect.Width(), + marginTop + marginBottom + borderRect.Height() ) ); + + aNode.SetMarginRect( marginRect ); + + // Within this function, the rects are adjusted if the display-priority is + // 0 and margin rect exceeds parent's content rect. + DropExceedingRectL( aParentRect, aNode ); + + // Update column width & column margin width according to block + // progression & direction. + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + TInt newColumnWidth = marginRect.iBr.iY - aParentRect.iTl.iY; + if ( newColumnWidth > aColumnWidth ) + { + aColumnWidth = newColumnWidth; + aColumnMargin = marginRect.iBr.iY - borderRect.iBr.iY; + } + } + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR ) + { + TInt newColumnWidth = aParentRect.iBr.iY - marginRect.iTl.iY; + if ( newColumnWidth > aColumnWidth ) + { + aColumnWidth = newColumnWidth; + aColumnMargin = borderRect.iTl.iY - marginRect.iTl.iY; + } + } + else if ( aParentDirection == + XnPropertyNames::style::common::direction::KLTR ) + { + // same for tb and bt + TInt newColumnWidth = marginRect.iBr.iX - aParentRect.iTl.iX; + if ( newColumnWidth > aColumnWidth ) + { + aColumnWidth = newColumnWidth; + aColumnMargin = marginRect.iBr.iX - borderRect.iBr.iX; + } + } + else if ( aParentDirection == + XnPropertyNames::style::common::direction::KRTL ) + { + // same for tb and bt + TInt newColumnWidth = aParentRect.iBr.iX - marginRect.iTl.iX; + if ( newColumnWidth > aColumnWidth ) + { + aColumnWidth = newColumnWidth; + aColumnMargin = borderRect.iTl.iX - marginRect.iTl.iX; + } + } + + if ( IsNodeTooltip( aNode ) ) + { + // because tooltip has it's own window, move margin rect to 0,0 + // and all other rects as much up left + TRect marginRect = aNode.MarginRect(); + TRect borderRect = aNode.BorderRect(); + TRect paddingRect = aNode.PaddingRect(); + TRect contentRect = aNode.Rect(); + TInt x = marginRect.iTl.iX; + TInt y = marginRect.iTl.iY; + marginRect.Move( -x, -y ); + borderRect.Move( -x, -y ); + paddingRect.Move( -x, -y ); + contentRect.Move( -x, -y ); + aNode.SetMarginRect( marginRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetRect( contentRect ); + } + } + +// ----------------------------------------------------------------------------- +// CalculatePaddingL() +// Move the rect by adding the padding. +// ----------------------------------------------------------------------------- +// +static void CalculatePaddingL( const TRect& aParentRect, CXnNode& aNode, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + TInt offsetx = 0; + TInt offsety = 0; + + TInt paddingleft = 0; + TInt paddingright = 0; + TInt paddingtop = 0; + TInt paddingbottom = 0; + TRect parentRect = aParentRect; + + CXnProperty* paddingproperty = aNode.PaddingLeftL(); + + if ( paddingproperty ) + { + TRAPD( error, paddingleft = HorizontalPixelValueL( paddingproperty, + parentRect.Width(), aGraphicsDevice, aHorizontalUnitInPixels ) ); + + if ( error != KErrNone ) + { + paddingleft = 0; + } + } + + paddingproperty = aNode.PaddingRightL(); + + if ( paddingproperty ) + { + TRAPD( error, paddingright = HorizontalPixelValueL( paddingproperty, + parentRect.Width(), aGraphicsDevice, aHorizontalUnitInPixels ) ); + + if ( error != KErrNone ) + { + paddingright = 0; + } + } + + paddingproperty = aNode.PaddingTopL(); + + if ( paddingproperty ) + { + TRAPD( error, paddingtop = VerticalPixelValueL( paddingproperty, + parentRect.Height(), aGraphicsDevice, aVerticalUnitInPixels ) ); + + if ( error != KErrNone ) + { + paddingtop = 0; + } + } + + paddingproperty = aNode.PaddingBottomL(); + + if ( paddingproperty ) + { + TRAPD( error, paddingbottom = VerticalPixelValueL( paddingproperty, + parentRect.Height(), aGraphicsDevice, aVerticalUnitInPixels ) ); + + if ( error != KErrNone ) + { + paddingbottom = 0; + } + } + + // move the client rect of the element this much right + offsetx = paddingleft; + // move the client rect of the element this much down + offsety = paddingtop; + + TRect newrect( aNode.Rect() ); + TPoint origin( newrect.iTl ); + newrect.Move( offsetx, offsety ); + aNode.SetRect( newrect ); + + // set padding rect + TRect paddingrect( origin, TSize( paddingleft + paddingright + + newrect.Width(), paddingtop + paddingbottom + newrect.Height() ) ); + + aNode.SetPaddingRect( paddingrect ); + } + +// ----------------------------------------------------------------------------- +// CalculateRectL() +// Creates rect for CXnComponent. +// ----------------------------------------------------------------------------- +// +static void CalculateRectL( CXnNode& aNode, CXnNode& aParent, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + TInt width = 0; + TInt height = 0; + TRect parentRect = aParent.Rect(); + CXnProperty* widthproperty = aNode.WidthL(); + + if ( widthproperty ) + { + // if width is auto, it is set to 0 at this point and calculated later + if ( IsPropertyAutoL( *widthproperty ) ) + { + width = 0; + } + else + { + width = HorizontalPixelValueL( widthproperty, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + } + } + + CXnProperty* heightproperty = aNode.HeightL(); + + if ( heightproperty ) + { + // if height is auto, height is set to 0 at this point + // and calculated later + if ( IsPropertyAutoL( *heightproperty ) ) + { + height = 0; + } + else + { + height = VerticalPixelValueL( heightproperty, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + } + } + + // check that rect sizes are in max and min bounds + CXnProperty* maxheightproperty = aNode.MaxHeightL(); + CXnProperty* minheightproperty = aNode.MinHeightL(); + CXnProperty* maxwidthproperty = aNode.MaxWidthL(); + CXnProperty* minwidthproperty = aNode.MinWidthL(); + + if ( maxwidthproperty ) + { + if ( !IsPropertyNone( *maxwidthproperty ) ) + { + TInt maxwidth = HorizontalPixelValueL( + maxwidthproperty, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + + if ( width > maxwidth ) + { + width = maxwidth; + } + } + } + + if ( minwidthproperty ) + { + if ( !IsPropertyNone( *minwidthproperty ) ) + { + TInt minwidth = HorizontalPixelValueL( + minwidthproperty, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + + if ( width < minwidth ) + { + width = minwidth; + } + } + } + + if ( maxheightproperty ) + { + if ( !IsPropertyNone( *maxheightproperty ) ) + { + TInt maxheight = VerticalPixelValueL( + maxheightproperty, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + + if ( height > maxheight ) + { + height = maxheight; + } + } + } + + if ( minheightproperty ) + { + if ( !IsPropertyNone( *minheightproperty ) ) + { + TInt minheight = VerticalPixelValueL( + minheightproperty, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + + if ( height < minheight ) + { + height = minheight; + } + } + } + + if ( aNode.ViewNodeImpl() && height != 0 && width != 0 ) + { + TRect rect( 0, 0, width, height ); + TRect paddingrect( 0, 0, width, height ); + TRect borderrect( 0, 0, width, height ); + TRect normalFlowBorderRect( 0, 0, width, height ); + TRect marginrect( 0, 0, width, height ); + + aNode.SetRect( rect ); + aNode.SetPaddingRect( paddingrect ); + aNode.SetBorderRect( borderrect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + aNode.SetMarginRect( marginrect ); + } + else if ( !aNode.ViewNodeImpl() ) + { + TInt adaptive( aNode.IsAdaptive() ); + + if ( adaptive && ( IsNodeTooltip( aNode ) || IsAbsoluteL( aNode ) ) ) + { + CXnUiEngine* engine( aNode.UiEngine() ); + + TSize maxSize( engine->ClientRect().Size() ); + + if ( adaptive & XnAdaptive::EHeight ) + { + height = maxSize.iHeight; + } + if ( adaptive & XnAdaptive::EWidth ) + { + width = maxSize.iWidth; + } + } + + TRect rect( 0, 0, width, height ); + TRect paddingrect( 0, 0, width, height ); + TRect borderrect( 0, 0, width, height ); + TRect normalFlowBorderRect( 0, 0, width, height ); + TRect marginrect( 0, 0, width, height ); + + aNode.SetRect( rect ); + aNode.SetPaddingRect( paddingrect ); + aNode.SetBorderRect( borderrect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + aNode.SetMarginRect( marginrect ); + } + } + +// ----------------------------------------------------------------------------- +// CalculateRelativePositionL() +// Move the rect by it's relative position. +// ----------------------------------------------------------------------------- +// +static void CalculateRelativePositionsL( const TRect& aParentRect, + CXnNode& aNode, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ) + { + CXnProperty* top = aNode.TopL(); + CXnProperty* bottom = aNode.BottomL(); + CXnProperty* left = aNode.LeftL(); + CXnProperty* right = aNode.RightL(); + + // Move rect by offset + TRect newRect( aNode.Rect() ); + TRect paddingRect( aNode.PaddingRect() ); + TRect borderRect( aNode.BorderRect() ); + TRect marginRect( aNode.MarginRect() ); + + TRect parentRect = aParentRect; + + if ( top && !IsPropertyAutoL( *top ) ) + { + newRect.Move( 0, VerticalPixelValueL( top, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ) ); + paddingRect.Move( 0, VerticalPixelValueL( top, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ) ); + borderRect.Move( 0, VerticalPixelValueL( top, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ) ); + marginRect.Move( 0, VerticalPixelValueL( top, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ) ); + } + if ( bottom && !IsPropertyAutoL( *bottom ) ) + { + newRect.Move( 0, -VerticalPixelValueL( bottom, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ) ); + paddingRect.Move( 0, -VerticalPixelValueL( bottom, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ) ); + borderRect.Move( 0, -VerticalPixelValueL( bottom, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ) ); + marginRect.Move( 0, -VerticalPixelValueL( bottom, parentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ) ); + } + if ( left && !IsPropertyAutoL( *left ) ) + { + newRect.Move( HorizontalPixelValueL( left, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ), 0 ); + paddingRect.Move( HorizontalPixelValueL( left, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ), 0 ); + borderRect.Move( HorizontalPixelValueL( left, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ), 0 ); + marginRect.Move( HorizontalPixelValueL( left, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ), 0 ); + } + if ( right && !IsPropertyAutoL( *right ) ) + { + newRect.Move( -HorizontalPixelValueL( right, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ), 0 ); + paddingRect.Move( -HorizontalPixelValueL( right, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ), 0 ); + borderRect.Move( -HorizontalPixelValueL( right, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ), 0 ); + marginRect.Move( -HorizontalPixelValueL( right, parentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ), 0 ); + } + + aNode.SetRect( newRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetMarginRect( marginRect ); + + DropExceedingRectL( parentRect, aNode, ETrue ); + } + +// ----------------------------------------------------------------------------- +// CalculateSpaceUsedByChildrenL() +// Return space used by node's children. +// ----------------------------------------------------------------------------- +// +static TSize CalculateSpaceUsedByChildrenL( RPointerArray< CXnNode >& aChildren, + CXnNode& aNode, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, CGraphicsDevice& aScreenDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ) + { + TInt usedSiblingHeight( 0 ); + TInt usedSiblingWidth( 0 ); + + TRect rect( aNode.Rect() ); + + TSize largestSize( 0, 0 ); + + for ( TInt i = 0; i < aChildren.Count(); i++ ) + { + CXnNode* node( aChildren[i] ); + + if ( IsNodeDisplayedL( *node ) && !node->IsDropped() && + !IsAbsoluteL( *node ) && !IsNodeTooltip( *node ) ) + { + TSize siblingSize = CalculateTotalDimensionsL( *node, ETrue, + EFalse, rect, aScreenDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + + if ( node->IsAdaptive() ) + { + RPointerArray< CXnNode >& children( node->Children() ); + + CXnProperty* blockProgressionProperty( + node->BlockProgressionL() ); + CXnProperty* directionProperty( node->DirectionL() ); + + const TDesC8* blockProgression( + &XnPropertyNames::style::common::block_progression::KTB() ); + const TDesC8* direction( + &XnPropertyNames::style::common::direction::KLTR() ); + + if ( directionProperty ) + { + direction = &directionProperty->StringValue(); + } + + if ( blockProgressionProperty ) + { + blockProgression = &blockProgressionProperty->StringValue(); + } + + siblingSize += CalculateSpaceUsedByChildrenL( children, aNode, + *blockProgression, *direction, + aScreenDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + } + + if ( siblingSize.iWidth > largestSize.iWidth ) + { + largestSize.iWidth = siblingSize.iWidth; + } + if ( siblingSize.iHeight > largestSize.iHeight ) + { + largestSize.iHeight = siblingSize.iHeight; + } + + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB ) + { + usedSiblingHeight += siblingSize.iHeight; + usedSiblingWidth = largestSize.iWidth; + } + + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + usedSiblingWidth += siblingSize.iWidth; + usedSiblingHeight = largestSize.iHeight; + } + + // collapse margins + if ( aChildren.Count() < i ) + { + CXnNode* next( aChildren[i + 1] ); + + if ( ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR || + aParentBlockProgression == + XnPropertyNames::style::common:: + block_progression::KRL ) && aParentDirection == + XnPropertyNames::style::common::direction::KLTR ) + { + TInt thisSiblingsRightMargin = + node->MarginRect().iBr.iX - node->BorderRect().iBr.iX; + TInt nextSiblingsLeftMargin = + next->BorderRect().iTl.iX - next->MarginRect().iTl.iX; + + if ( nextSiblingsLeftMargin > thisSiblingsRightMargin ) + { + usedSiblingWidth -= thisSiblingsRightMargin; + } + } + + if ( ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL || + aParentBlockProgression == + XnPropertyNames::style::common + ::block_progression::KLR ) && aParentDirection == + XnPropertyNames::style::common::direction::KRTL ) + { + TInt thisSiblingsLeftMargin = + node->MarginRect().iTl.iX - node->BorderRect().iTl.iX; + TInt nextSiblingsRightMargin = + next->BorderRect().iBr.iX - next->MarginRect().iBr.iX; + + if ( nextSiblingsRightMargin > thisSiblingsLeftMargin ) + { + usedSiblingWidth =- thisSiblingsLeftMargin; + } + } + + if ( ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common:: + block_progression::KBT ) && aParentDirection == + XnPropertyNames::style::common::direction::KLTR ) + { + TInt thisSiblingsBottomMargin = + node->MarginRect().iBr.iY - node->BorderRect().iBr.iY; + TInt nextSiblingsTopMargin = + next->BorderRect().iTl.iY - next->MarginRect().iTl.iY; + + if ( nextSiblingsTopMargin > thisSiblingsBottomMargin ) + { + usedSiblingHeight -= thisSiblingsBottomMargin; + } + } + + if ( ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common:: + block_progression::KBT ) && aParentDirection == + XnPropertyNames::style::common::direction::KRTL ) + { + TInt thisSiblingsTopMargin = + node->MarginRect().iTl.iY - node->BorderRect().iTl.iY; + TInt nextSiblingsBottomMargin = + next->BorderRect().iBr.iY - next->MarginRect().iBr.iY; + + if ( nextSiblingsBottomMargin > thisSiblingsTopMargin ) + { + usedSiblingHeight -= thisSiblingsTopMargin; + } + } + } + } + } + + return TSize( usedSiblingWidth, usedSiblingHeight ); + } + +// ----------------------------------------------------------------------------- +// CalculateTotalDimensionsL() +// Scale dimensions for areas that have properties set to AUTO. +// ----------------------------------------------------------------------------- +// +static TSize CalculateTotalDimensionsL( CXnNode& aNode, TBool aIgnoreAutoValues, + TBool aIgnoreMinSizes, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + // AUTO areas return their defined dimensions if not ignored + // if ignored, 0 is returned as area dimensions + CXnProperty* width( aNode.WidthL() ); + CXnProperty* height( aNode.HeightL() ); + TInt adaptive( aNode.IsAdaptive() ); + TBool autoNotFound( EFalse ); + + if ( adaptive ) + { + // Force to measure adaptive size + aIgnoreAutoValues = EFalse; + autoNotFound = ETrue; + } + if ( aIgnoreAutoValues ) + { + TInt horizontalAuto( HasNodeHorizontalAutoValuesL( aNode ) ); + TInt verticalAuto( HasNodeVerticalAutoValuesL( aNode ) ); + if ( horizontalAuto && verticalAuto ) + { + return TSize( 0, 0 ); + } + else if ( horizontalAuto ) + { + TInt h = VerticalPixelValueL( height, aParentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + return TSize( 0, h ); + } + else if ( verticalAuto ) + { + TInt w = HorizontalPixelValueL( width, aParentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + return TSize( w, 0 ); + } + autoNotFound = ETrue; + } + + TInt x( 0 ); + TInt y( 0 ); + + if ( !aIgnoreMinSizes ) + { + if ( !autoNotFound && HasNodeAutoValuesL( aNode ) ) + { + // if auto values, check minimum sizes + if ( height ) + { + if ( IsPropertyAutoL( *height ) ) + { + CXnProperty* minheight( aNode.MinHeightL() ); + if ( minheight ) + { + if ( !IsPropertyNone( *minheight ) ) + { + y += VerticalPixelValueL( minheight, + aParentRect.Height(), aGraphicsDevice, + aVerticalUnitInPixels ); + } + } + } + } + if ( width ) + { + if ( IsPropertyAutoL( *width ) ) + { + CXnProperty* minwidth( aNode.MinWidthL() ); + if ( minwidth ) + { + if ( !IsPropertyNone( *minwidth ) ) + { + x += HorizontalPixelValueL( minwidth, + aParentRect.Width(), aGraphicsDevice, + aHorizontalUnitInPixels ); + } + } + } + } + } + } + + CXnProperty* marginLeft = aNode.MarginLeftL(); + CXnProperty* marginRight = aNode.MarginRightL(); + CXnProperty* borderLeft = aNode.BorderLeftL(); + CXnProperty* borderRight = aNode.BorderRightL(); + CXnProperty* paddingLeft = aNode.PaddingLeftL(); + CXnProperty* paddingRight = aNode.PaddingRightL(); + CXnProperty* marginTop = aNode.MarginTopL(); + CXnProperty* marginBottom = aNode.MarginBottomL(); + CXnProperty* borderTop = aNode.BorderTopL(); + CXnProperty* borderBottom = aNode.BorderBottomL(); + CXnProperty* paddingTop = aNode.PaddingTopL(); + CXnProperty* paddingBottom = aNode.PaddingBottomL(); + CXnProperty* borderWidth = aNode.BorderWidthL(); + CXnProperty* borderStyle = aNode.BorderStyleL(); + CXnProperty* borderImage = aNode.BorderImageL(); + CXnProperty* borderLeftStyle = aNode.BorderLeftStyleL(); + CXnProperty* borderRightStyle = aNode.BorderRightStyleL(); + CXnProperty* borderTopStyle = aNode.BorderTopStyleL(); + CXnProperty* borderBottomStyle = aNode.BorderBottomStyleL(); + + TInt borderWidthValue( 0 ); + TInt borderHeightValue( 0 ); + TInt ignore; + + if ( marginLeft ) + { + if ( autoNotFound || !IsPropertyAutoL( *marginLeft ) ) + { + x += HorizontalPixelValueL( marginLeft, aParentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + } + } + if ( marginRight ) + { + if ( autoNotFound || !IsPropertyAutoL( *marginRight ) ) + { + x += HorizontalPixelValueL( marginRight, aParentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + } + } + if ( paddingLeft ) + { + TRAP_IGNORE( x += HorizontalPixelValueL( paddingLeft, + aParentRect.Width(), aGraphicsDevice, aHorizontalUnitInPixels ) ); + } + if ( paddingRight ) + { + TRAP_IGNORE( x += HorizontalPixelValueL( paddingRight, + aParentRect.Width(), aGraphicsDevice, aHorizontalUnitInPixels ) ); + } + if ( marginTop ) + { + if ( autoNotFound || !IsPropertyAutoL( *marginTop ) ) + { + y += VerticalPixelValueL( marginTop, aParentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + } + } + if ( marginBottom ) + { + if ( autoNotFound || !IsPropertyAutoL( *marginBottom ) ) + { + y += VerticalPixelValueL( marginBottom, aParentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + } + } + if ( paddingTop ) + { + TRAP_IGNORE( y += VerticalPixelValueL( paddingTop, + aParentRect.Height(), aGraphicsDevice, aVerticalUnitInPixels ) ); + } + if ( paddingBottom ) + { + TRAP_IGNORE( y += VerticalPixelValueL( paddingBottom, + aParentRect.Height(), aGraphicsDevice, aVerticalUnitInPixels ) ); + } + // is border image or border style defined? + // if not, borders are ignored + if ( borderWidth ) + { + if ( borderImage || borderStyle ) + { + DetermineBorderWidthsL( borderWidth, borderWidthValue, + borderHeightValue, aParentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + x += ( borderWidthValue * 2 ); + y += ( borderHeightValue * 2 ); + } + } + if ( borderLeft ) + { + if ( borderImage || borderStyle || borderLeftStyle ) + { + x -= borderWidthValue; + TInt borderLeftValue( 0 ); + DetermineBorderWidthsL( borderLeft, ignore, borderLeftValue, + aParentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + x += borderLeftValue; + } + } + if ( borderRight ) + { + if ( borderImage || borderStyle || borderRightStyle ) + { + x -= borderWidthValue; + TInt borderRightValue( 0 ); + DetermineBorderWidthsL( borderRight, ignore, borderRightValue, + aParentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + x += borderRightValue; + } + } + if ( borderTop ) + { + if ( borderImage || borderStyle || borderTopStyle ) + { + y -= borderHeightValue; + TInt borderTopValue( 0 ); + DetermineBorderWidthsL( borderTop, borderTopValue, ignore, + aParentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + y += borderTopValue; + } + } + if ( borderBottom ) + { + if ( borderImage || borderStyle || borderBottomStyle ) + { + y -= borderHeightValue; + TInt borderBottomValue( 0 ); + DetermineBorderWidthsL( borderBottom, borderBottomValue, ignore, + aParentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + y += borderBottomValue; + } + } + + TInt maxHeight( 0 ); + TInt maxWidth( 0 ); + TInt minHeight( 0 ); + TInt minWidth( 0 ); + + if ( HasNodeMinSizesL( aNode ) ) + { + CXnProperty* heightproperty( aNode.HeightL() ); + CXnProperty* widthproperty( aNode.WidthL() ); + if ( heightproperty ) + { + CXnProperty* minheightproperty( aNode.MinHeightL() ); + if ( minheightproperty ) + { + if ( !IsPropertyNone( *minheightproperty ) ) + { + minHeight = VerticalPixelValueL( minheightproperty, + aParentRect.Height(), aGraphicsDevice, + aVerticalUnitInPixels ); + } + } + } + if ( widthproperty ) + { + CXnProperty* minwidthproperty( aNode.MinWidthL() ); + if ( minwidthproperty ) + { + if (!IsPropertyNone( *minwidthproperty ) ) + { + minWidth = HorizontalPixelValueL( minwidthproperty, + aParentRect.Width(), aGraphicsDevice, + aHorizontalUnitInPixels ); + } + } + } + } + if ( HasNodeMaxSizesL( aNode ) ) + { + CXnProperty* heightProperty( aNode.HeightL() ); + CXnProperty* widthProperty( aNode.WidthL() ); + if ( heightProperty ) + { + CXnProperty* maxHeightProperty( aNode.MaxHeightL() ); + if ( maxHeightProperty ) + { + if ( !IsPropertyNone( *maxHeightProperty ) ) + { + maxHeight = VerticalPixelValueL( maxHeightProperty, + aParentRect.Height(), aGraphicsDevice, + aVerticalUnitInPixels ); + } + } + } + if ( widthProperty ) + { + CXnProperty* maxWidthProperty( aNode.MaxWidthL() ); + if ( maxWidthProperty ) + { + if ( !IsPropertyNone( *maxWidthProperty ) ) + { + maxWidth = HorizontalPixelValueL( maxWidthProperty, + aParentRect.Width(), aGraphicsDevice, + aHorizontalUnitInPixels ); + } + } + } + } + if ( width && height ) + { + if ( ( adaptive & XnAdaptive::EWidth ) && + ( adaptive & XnAdaptive::EHeight ) ) + { + TSize available( aParentRect.Size() - TSize( x, y ) ); + if ( available.iWidth > 0 ) + { + if ( available.iWidth > maxWidth && maxWidth > 0 ) + { + available.iWidth = maxWidth; + } + } + if ( available.iHeight > 0 ) + { + if ( available.iHeight > maxHeight && maxHeight > 0 ) + { + available.iHeight = maxHeight; + } + } + TSize size( aNode.MeasureAdaptiveContentL( available ) ); + x += size.iWidth; + y += size.iHeight; + if ( minWidth > x ) + { + x = minWidth; + } + if ( minHeight > y ) + { + y = minHeight; + } + return TSize( x, y ); + } + } + if ( width ) + { + if ( adaptive & XnAdaptive::EWidth ) + { + TSize available( aParentRect.Size() - TSize( x, y ) ); + if ( available.iWidth > 0 ) + { + if ( available.iWidth > maxWidth && maxWidth > 0 ) + { + available.iWidth = maxWidth; + } + x += aNode.MeasureAdaptiveContentL( available ).iWidth; + if ( minWidth > x ) + { + x = minWidth; + } + } + } + else if ( autoNotFound || !IsPropertyAutoL( *width ) ) + { + x += HorizontalPixelValueL( width, aParentRect.Width(), + aGraphicsDevice, aHorizontalUnitInPixels ); + } + } + if ( height ) + { + if ( adaptive & XnAdaptive::EHeight ) + { + TSize available( aParentRect.Size() - TSize( x, y ) ); + if ( available.iHeight > 0 ) + { + if ( available.iHeight > maxHeight && maxHeight > 0 ) + { + available.iHeight = maxHeight; + } + y += aNode.MeasureAdaptiveContentL( available ).iHeight; + if ( minHeight > y ) + { + y = minHeight; + } + } + } + else if ( autoNotFound || !IsPropertyAutoL( *height ) ) + { + y += VerticalPixelValueL( height, aParentRect.Height(), + aGraphicsDevice, aVerticalUnitInPixels ); + } + } + return TSize( x, y ); + } + +// ----------------------------------------------------------------------------- +// CutOnePixelFromPercentChildNodeL() +// If node has a child node with percentace defined sizes, +// one pixel may be cut off from it to fix possible rounding problem. +// ----------------------------------------------------------------------------- +// +static TBool CutOnePixelFromPercentChildNodeL( CXnNode& aNode, + const TDesC8& aParentBlockProgression ) + { + RPointerArray< CXnNode >& children = aNode.Children(); + // find the last percent value node + // possible percent values: + // width + // height + // paddings + // margins + // borders + for ( TInt i = children.Count() -1; i < -1 ; --i ) + { + CXnNode* currentNode = children[i]; + + TInt x = 0; + TInt y = 0; + + CXnProperty* widthHeight; + CXnProperty* paddingTopLeft; + CXnProperty* paddingBottomRight; + CXnProperty* borderTopLeft; + CXnProperty* borderBottomRight; + CXnProperty* marginTopLeft; + CXnProperty* marginBottomRight; + + if ( ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR ) || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + x = -1; + y = 0; + widthHeight = currentNode->WidthL(); + paddingTopLeft = currentNode->PaddingLeftL(); + paddingBottomRight = currentNode->PaddingRightL(); + borderTopLeft = currentNode->BorderLeftL(); + borderBottomRight = currentNode->BorderRightL(); + marginTopLeft = currentNode->MarginLeftL(); + marginBottomRight = currentNode->MarginRightL(); + } + else + { + y = -1; + x = 0; + widthHeight = currentNode->HeightL(); + paddingTopLeft = currentNode->PaddingTopL(); + paddingBottomRight = currentNode->PaddingBottomL(); + borderTopLeft = currentNode->BorderTopL(); + borderBottomRight = currentNode->BorderBottomL(); + marginTopLeft = currentNode->MarginTopL(); + marginBottomRight = currentNode->MarginBottomL(); + } + if ( widthHeight ) + { + if ( IsValuePercentageL( *widthHeight ) ) + { + // shrink width one pixel + TRect rect( currentNode->Rect() ); + rect.Resize( x, y ); + currentNode->SetRect( rect ); + TRect paddingRect( currentNode->PaddingRect() ); + paddingRect.Resize( x, y ); + currentNode->SetPaddingRect( paddingRect ); + TRect borderRect( currentNode->BorderRect() ); + borderRect.Resize( x, y ); + TRect marginRect( currentNode->MarginRect() ); + + marginRect.Resize( x, y ); + + currentNode->SetMarginRect( marginRect ); + + return ETrue; + } + } + if ( paddingTopLeft ) + { + if ( IsValuePercentageL( *paddingTopLeft ) ) + { + // shrink left padding one pixel + TRect rect( currentNode->Rect() ); + rect.Move( x, y ); + currentNode->SetRect( rect ); + TRect paddingRect( currentNode->PaddingRect() ); + paddingRect.Resize( x, y ); + currentNode->SetPaddingRect( paddingRect ); + TRect borderRect( currentNode->BorderRect() ); + TRect normalFlowBorderRect( + currentNode->NormalFlowBorderRect() ); + borderRect.Resize( x, y ); + normalFlowBorderRect.Resize( x, y ); + currentNode->SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + TRect marginRect( currentNode->MarginRect() ); + + marginRect.Resize( x, y ); + + currentNode->SetMarginRect( marginRect ); + + return ETrue; + } + } + if ( paddingBottomRight ) + { + if ( IsValuePercentageL( *paddingBottomRight ) ) + { + // shrink right padding one pixel + TRect paddingRect( currentNode->PaddingRect() ); + paddingRect.Resize( x, y ); + currentNode->SetPaddingRect( paddingRect ); + TRect borderRect( currentNode->BorderRect() ); + TRect normalFlowBorderRect( + currentNode->NormalFlowBorderRect() ); + borderRect.Resize( x, y ); + normalFlowBorderRect.Resize( x, y ); + currentNode->SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + TRect marginRect( currentNode->MarginRect() ); + + marginRect.Resize( x, y ); + + currentNode->SetMarginRect( marginRect ); + + return ETrue; + } + } + if ( borderTopLeft ) + { + if ( IsValuePercentageL( *borderTopLeft ) ) + { + TRect rect( currentNode->Rect() ); + rect.Move( x, y ); + currentNode->SetRect( rect ); + TRect paddingRect( currentNode->PaddingRect() ); + paddingRect.Move( x, y ); + currentNode->SetPaddingRect( paddingRect ); + TRect borderRect( currentNode->BorderRect() ); + TRect normalFlowBorderRect( + currentNode->NormalFlowBorderRect() ); + borderRect.Resize( x, y ); + normalFlowBorderRect.Resize( x, y ); + currentNode->SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + TRect marginRect( currentNode->MarginRect() ); + + marginRect.Resize( x, y ); + + currentNode->SetMarginRect( marginRect ); + + return ETrue; + } + } + if ( borderBottomRight ) + { + if ( IsValuePercentageL( *borderBottomRight ) ) + { + TRect borderRect( currentNode->BorderRect() ); + TRect normalFlowBorderRect( currentNode->BorderRect() ); + borderRect.Resize( x, y ); + normalFlowBorderRect.Resize( x, y ); + currentNode->SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + TRect marginRect( currentNode->MarginRect() ); + + marginRect.Resize( x, y ); + + currentNode->SetMarginRect( marginRect ); + + return ETrue; + } + } + if ( marginTopLeft ) + { + if ( IsValuePercentageL( *marginTopLeft ) ) + { + TRect rect( currentNode->Rect() ); + rect.Move( x, y ); + currentNode->SetRect( rect ); + TRect paddingRect( currentNode->PaddingRect() ); + paddingRect.Move( x, y ); + currentNode->SetPaddingRect( paddingRect ); + TRect borderRect( currentNode->BorderRect() ); + TRect normalFlowBorderRect( + currentNode->NormalFlowBorderRect() ); + borderRect.Move( x, y ); + normalFlowBorderRect.Move( x, y ); + currentNode->SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + TRect marginRect( currentNode->MarginRect() ); + + marginRect.Resize( x, y ); + + currentNode->SetMarginRect( marginRect ); + + return ETrue; + } + } + if ( marginBottomRight ) + { + if ( IsValuePercentageL( *marginBottomRight ) ) + { + TRect marginRect( currentNode->MarginRect() ); + + marginRect.Resize( x, y ); + + currentNode->SetMarginRect( marginRect ); + + return ETrue; + } + } + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// DetermineBorderWidthsL() +// Determine border widths. +// ----------------------------------------------------------------------------- +// +static void DetermineBorderWidthsL( CXnProperty* aBorderWidthProperty, + TInt& aBordervertical, TInt& aBorderhorizontal, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + CXnDomList& propertyValueList = + aBorderWidthProperty->Property()->PropertyValueList(); + for ( TInt i = propertyValueList.Length() - 1; i >= 0; --i ) + { + CXnDomPropertyValue* value = + static_cast< CXnDomPropertyValue* >( propertyValueList.Item( i ) ); + if ( value->PrimitiveValueType() == CXnDomPropertyValue::EString || + value->PrimitiveValueType() == CXnDomPropertyValue::EIdent ) + { + // border width was defined as string + const TDesC8& borderwidth = aBorderWidthProperty->StringValue(); + if ( borderwidth == + XnPropertyNames::style::common::border_width::KThin ) + { + aBordervertical = KXnBorderThin; + aBorderhorizontal = KXnBorderThin; + } + else if ( borderwidth == + XnPropertyNames::style::common::border_width::KMedium ) + { + aBordervertical = KXnBorderMedium; + aBorderhorizontal = KXnBorderMedium; + } + else + { + aBordervertical = KXnBorderThick; + aBorderhorizontal = KXnBorderThick; + } + } + else + { + // border width was defined as int + aBordervertical = VerticalPixelValueL( aBorderWidthProperty, + aParentRect.Height(), aGraphicsDevice, aVerticalUnitInPixels ); + aBorderhorizontal = HorizontalPixelValueL( aBorderWidthProperty, + aParentRect.Width(), aGraphicsDevice, aHorizontalUnitInPixels ); + } + } + } + +// ----------------------------------------------------------------------------- +// DisplayedChildrenCountL() +// Return number of node's displayed children. +// ----------------------------------------------------------------------------- +// +static TInt DisplayedChildrenCountL( CXnNode& aNode, + RPointerArray< CXnNode >* aDisplayedChildren ) + { + RPointerArray< CXnNode >& children = aNode.Children(); + TInt displayedCount( 0 ); + + for ( TInt i = 0; i < children.Count(); i++ ) + { + CXnNode* node( children[i] ); + if ( IsNodeDisplayedL( *node ) && !node->IsDropped() && + !IsAbsoluteL( *node ) && !IsNodeTooltip( *node ) ) + { + if ( aDisplayedChildren ) + { + aDisplayedChildren->AppendL( node ); + } + displayedCount++; + } + } + + return displayedCount; + } + +// ----------------------------------------------------------------------------- +// DisplayedParentL() +// Return node's displayed parent. +// ----------------------------------------------------------------------------- +// +static CXnNode* DisplayedParentL( CXnNode& aNode ) + { + if ( aNode.ViewNodeImpl() ) + { + return &aNode; + } + CXnNode* parent = aNode.Parent(); + return parent; + } + +// ----------------------------------------------------------------------------- +// DomPropertyValueFromProperty() +// Return DOM property value from property. +// ----------------------------------------------------------------------------- +// +static CXnDomPropertyValue* DomPropertyValueFromProperty( + CXnProperty* aProperty ) + { + if ( !aProperty ) + { + return NULL; + } + CXnDomProperty* domProperty = aProperty->Property(); + if ( !domProperty ) + { + return NULL; + } + return static_cast< + CXnDomPropertyValue* >( domProperty->PropertyValueList().Item( 0 ) ); + } + +// ----------------------------------------------------------------------------- +// DomPropertyValueFromProperty() +// Return DOM property value from property. +// ----------------------------------------------------------------------------- +// +static TBool IsChildOfScrollableControl( CXnNode& aNode ) + { + CXnNode* parent = &aNode; + while( parent ) + { + if( IsSrollableBox( *parent ) ) + { + return ETrue; + } + parent = parent->Parent(); + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// DropExceedingRectL() +// Drop node if node's margin rect exceeds it's parent's content rect. +// ----------------------------------------------------------------------------- +// +static void DropExceedingRectL( const TRect& aParentRect, CXnNode& aNode, + TBool aDropRelativeNode ) + { + if( IsChildOfScrollableControl( aNode ) ) + { + return; + } + + if ( IsNodeTooltip( aNode ) ) + { + // tooltip never dropped + return; + } + + CXnProperty* positionProp( aNode.PositionL() ); + + if ( positionProp ) + { + const TDesC8& value( positionProp->StringValue() ); + if ( value == XnPropertyNames::style::common::position::KFloating ) + { + // Don't change floating positioned box dimensions + return; + } + } + + TRect parentRect( aParentRect ); + TRect marginRect( aNode.MarginRect() ); + + // does the margin rect fit in its parent? + TInt parentLeft = parentRect.iTl.iX; + TInt parentRight = parentRect.iBr.iX; + TInt parentTop = parentRect.iTl.iY; + TInt parentBottom = parentRect.iBr.iY; + + TInt rectLeft = marginRect.iTl.iX; + TInt rectRight = marginRect.iBr.iX; + TInt rectTop = marginRect.iTl.iY; + TInt rectBottom = marginRect.iBr.iY; + + TInt priority = 0; + CXnProperty* priorityProperty = aNode.DisplayPriorityL(); + + if ( priorityProperty ) + { + TRAPD( error, priority = priorityProperty->FloatValueL() ); + if ( error != KErrNone ) + { + priority = 0; + } + } + + TInt leftOffset( 0 ); + TInt rightOffset( 0 ); + TInt topOffset( 0 ); + TInt bottomOffset( 0 ); + + if ( priority != 0 ) + { + TBool drop = CalculateExceedingArea( *aNode.Parent(), aNode, + leftOffset, rightOffset, topOffset, bottomOffset ); + if ( drop ) + { + aNode.UiEngine()->SetNodeDroppedL( aNode, XnNodeLayout::EDropped ); + } + } + // If display priority is 0 as much as possible must be shown, but + // parent's content rect must not be exceeded. + else + { + // This must not be done for tracster. It is a special component, + // which takes care + // of its final layout and therefore its children can exceed + // the parent's rect. + CXnNode* parent = aNode.Parent(); + + // If the node is relatively positioned, and this is not called from + // CalculateRelativePositionsL(), then must not be cropped!! + + // Default is static + const TDesC8* value( + &XnPropertyNames::style::common::position::KStatic() ); + + if ( positionProp && positionProp->StringValue() != KNullDesC8 ) + { + value = &positionProp->StringValue(); + } + if ( !aDropRelativeNode && + XnPropertyNames::style::common::position::KRelative() == *value ) + // relative nodes must not be adjusted, if this is not called + // from CalculateRelativePositionsL(). + { + return; + } + if ( rectLeft < parentLeft ) + { + leftOffset = parentLeft - rectLeft; + } + if ( rectRight > parentRight ) + { + rightOffset = rectRight - parentRight; + } + if ( rectTop < parentTop ) + { + topOffset = parentTop - rectTop; + } + if ( rectBottom > parentBottom ) + { + bottomOffset = rectBottom - parentBottom; + } + AdjustRectsL( aNode, leftOffset, rightOffset, topOffset, bottomOffset ); + } + } + +// ----------------------------------------------------------------------------- +// CalculateExceedingArea() +// Calculates how much a dropped node affects to the area of its parent +// that is content based node. +// Returns whether a child's margin rect exceeds its parents content +// rect or not. +// ----------------------------------------------------------------------------- +// +static TBool CalculateExceedingArea( CXnNode& aParent, CXnNode& aChild, + TInt& aLeftOffset, TInt& aRightOffset, TInt& aTopOffset, + TInt& aBottomOffset ) + { + TBool ret( EFalse ); + + TRect parentRect( aParent.Rect() ); + TInt parentLeft = parentRect.iTl.iX; + TInt parentRight = parentRect.iBr.iX; + TInt parentTop = parentRect.iTl.iY; + TInt parentBottom = parentRect.iBr.iY; + + TRect marginRect( aChild.MarginRect() ); + TInt rectLeft = marginRect.iTl.iX; + TInt rectRight = marginRect.iBr.iX; + TInt rectTop = marginRect.iTl.iY; + TInt rectBottom = marginRect.iBr.iY; + + TInt adaptive( aParent.IsAdaptive() ); + + if ( rectLeft < parentLeft ) + { + if ( adaptive & XnAdaptive::EWidth ) + { + aLeftOffset = rectRight - parentLeft; + if ( aLeftOffset < 0 ) + { + aLeftOffset = 0; + } + } + ret = ETrue; + } + if ( rectRight > parentRight ) + { + if ( adaptive & XnAdaptive::EWidth ) + { + aRightOffset = parentRight - rectLeft; + if ( aRightOffset < 0 ) + { + aRightOffset = 0; + } + } + ret = ETrue; + } + if ( rectTop < parentTop ) + { + if ( adaptive & XnAdaptive::EHeight ) + { + aTopOffset = rectBottom - parentTop; + if ( aTopOffset < 0 ) + { + aTopOffset = 0; + } + } + ret = ETrue; + } + if ( rectBottom > parentBottom ) + { + if ( adaptive & XnAdaptive::EHeight ) + { + aBottomOffset = parentBottom - rectTop; + if ( aBottomOffset < 0 ) + { + aBottomOffset = 0; + } + } + ret = ETrue; + } + return ret; + } + +// ----------------------------------------------------------------------------- +// AdjustRectsL() +// Adjust all the rects according to the given offsets. +// ----------------------------------------------------------------------------- +// +static void AdjustRectsL( CXnNode& aNode, TInt aLeftOffset, TInt aRightOffset, + TInt aTopOffset, TInt aBottomOffset ) + { + if ( aLeftOffset || aRightOffset || aTopOffset || aBottomOffset ) + { +#ifdef _XN3_DEBUG_ + CXnProperty* id( aNode.IdL() ); + + if ( id ) + { + TBuf8< 256 > debug; + debug.Append( _L8( "Node id: " ) ); + debug.Append( id->StringValue() ); + debug.Append( _L8( "doesn't fit to parent and will be adjusted" ) ); + + RDebug::RawPrint( debug ); + } +#endif + + // Adjust margin rect + TRect marginRect( aNode.MarginRect() ); + TRect newRect = TRect( marginRect.iTl.iX + aLeftOffset, + marginRect.iTl.iY + aTopOffset, marginRect.iBr.iX - aRightOffset, + marginRect.iBr.iY - aBottomOffset ); + aNode.SetMarginRect( newRect ); + + // Adjust border rect + TRect borderRect( aNode.BorderRect() ); + newRect = TRect( borderRect.iTl.iX + aLeftOffset, + borderRect.iTl.iY + aTopOffset, borderRect.iBr.iX - aRightOffset, + borderRect.iBr.iY - aBottomOffset ); + aNode.SetBorderRect( newRect ); + + // Adjust normal flow border rect + TRect normalFlowBorderRect( aNode.NormalFlowBorderRect() ); + newRect = TRect( normalFlowBorderRect.iTl.iX + aLeftOffset, + normalFlowBorderRect.iTl.iY + aTopOffset, + normalFlowBorderRect.iBr.iX - aRightOffset, + normalFlowBorderRect.iBr.iY - aBottomOffset ); + aNode.SetNormalFlowBorderRect( newRect ); + + // Adjust padding rect + TRect paddingRect( aNode.PaddingRect() ); + newRect = TRect( paddingRect.iTl.iX + aLeftOffset, + paddingRect.iTl.iY + aTopOffset, paddingRect.iBr.iX - aRightOffset, + paddingRect.iBr.iY - aBottomOffset ); + aNode.SetPaddingRect( newRect ); + + // Adjust content rect + TRect contentRect( aNode.Rect() ); + newRect = TRect( contentRect.iTl.iX + aLeftOffset, + contentRect.iTl.iY + aTopOffset, contentRect.iBr.iX - aRightOffset, + contentRect.iBr.iY - aBottomOffset ); + aNode.SetRect( newRect ); + } + } + +// ----------------------------------------------------------------------------- +// ClearRects() +// Sets sizes of the rects to 0. +// ----------------------------------------------------------------------------- +// +static void ClearRects( CXnNode& aNode, TBool aRecurse ) + { + TRect empty; + + aNode.SetRect( empty ); + aNode.SetPaddingRect( empty ); + aNode.SetBorderRect( empty ); + aNode.SetNormalFlowBorderRect( empty ); + aNode.SetMarginRect( empty ); + + CCoeControl* control( aNode.Control() ); + + if ( control ) + { + control->SetRect( empty ); + } + + if ( aRecurse ) + { + RPointerArray< CXnNode >& children( aNode.Children() ); + for ( TInt i = 0; i < children.Count(); i++ ) + { + ClearRects( *children[i], aRecurse ); + } + } + } + +// ----------------------------------------------------------------------------- +// FitChildrenIntoParentL() +// Drop child nodes until they fit into the parent. Also, if node has +// a child node with percentace defined sizes, one pixel may be cut off from it +// to fix possible rounding problem. +// ----------------------------------------------------------------------------- +// +static void FitChildrenIntoParentL( CXnNode& aNode, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + if( IsSrollableBox( aNode ) ) + { + return; + } + RPointerArray< CXnNode >& children( aNode.Children() ); + + if ( children.Count() == 0 ) + { + return; + } + + CXnProperty* blockProgressionProperty( aNode.BlockProgressionL() ); + CXnProperty* directionProperty( aNode.DirectionL() ); + + const TDesC8* blockProgression = NULL; + + if ( !blockProgressionProperty ) + { + // using default + blockProgression = + &XnPropertyNames::style::common::block_progression::KTB(); + } + else + { + blockProgression = &blockProgressionProperty->StringValue(); + } + + const TDesC8* direction( NULL ); + + if ( !directionProperty ) + { + // use default + direction = &XnPropertyNames::style::common::direction::KLTR(); + } + else + { + direction = &directionProperty->StringValue(); + } + + TSize space = CalculateSpaceUsedByChildrenL( children, aNode, + *blockProgression, *direction, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + TSize parentSize( aNode.Rect().Size() ); + + while( ( ( parentSize.iHeight < space.iHeight ) && + ( parentSize.iHeight > 0 ) ) || + ( ( parentSize.iWidth < space.iWidth ) && + ( parentSize.iWidth > 0 ) ) ) + { + // if areas go over just one pixel, + // cut the pixel from a percent sized node + if ( ( parentSize.iHeight == space.iHeight - 1 ) || + ( parentSize.iWidth == space.iWidth - 1 ) ) + { + CutOnePixelFromPercentChildNodeL( aNode, *blockProgression ); + // Childs are now in parent size + return; + } + + TInt childCount( DisplayedChildrenCountL( aNode ) ); + + PriorizeChildrenL( aNode ); + + if ( DisplayedChildrenCountL( aNode ) == childCount ) + { + // cannot drop any more children, but they still don't fit + return; + } + + space = CalculateSpaceUsedByChildrenL( children, aNode, + *blockProgression, *direction, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + } + + return; + } + +// ----------------------------------------------------------------------------- +// GetPositionL() +// Return position coordinate of a CXnComponent. Returned position depends on +// given block progression. +// ----------------------------------------------------------------------------- +// +static TInt GetPositionL( CXnNode& aNode, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection ) + { + TInt returnValue = 0; + if ( aParentDirection == XnPropertyNames::style::common::direction::KLTR ) + { + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + returnValue = aNode.NormalFlowBorderRect().iBr.iY; + } + else // LR or RL + { + returnValue = aNode.NormalFlowBorderRect().iBr.iX; + } + } + else // RTL + { + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + returnValue = aNode.NormalFlowBorderRect().iTl.iY; + } + else // LR or RL + { + returnValue = aNode.NormalFlowBorderRect().iTl.iX; + } + } + return returnValue; + } + +// ----------------------------------------------------------------------------- +// HasNodeAutoValues() +// Check if node has properties set to AUTO. +// ----------------------------------------------------------------------------- +// +static TInt HasNodeAutoValuesL( CXnNode& aNode ) + { + return HasNodeHorizontalAutoValuesL( aNode ) || + HasNodeVerticalAutoValuesL( aNode ); + } + +// ----------------------------------------------------------------------------- +// HasNodeHorizontalValues() +// Check if node has properties set to AUTO. +// ----------------------------------------------------------------------------- +// +static TInt HasNodeHorizontalAutoValuesL( CXnNode& aNode ) + { + TInt autoCount = 0; + + CXnProperty* width = aNode.WidthL(); + + if ( width ) + { + if ( IsPropertyAutoL( *width ) ) + { + autoCount++; + } + } + else + { + // width is auto as default + autoCount++; + } + + CXnProperty* marginleft = aNode.MarginLeftL(); + + if ( marginleft ) + { + if ( IsPropertyAutoL( *marginleft ) ) + { + autoCount++; + } + } + + CXnProperty* marginright = aNode.MarginRightL(); + + if ( marginright ) + { + if ( IsPropertyAutoL( *marginright ) ) + { + autoCount++; + } + } + + if ( !IsAbsoluteL( aNode ) && !IsRelativeL( aNode ) ) + { + return autoCount; + } + + CXnProperty* left = aNode.LeftL(); + + if ( left ) + { + if ( IsPropertyAutoL( *left ) ) + { + autoCount++; + } + } + + CXnProperty* right = aNode.RightL(); + + if ( right ) + { + if ( IsPropertyAutoL( *right ) ) + { + autoCount++; + } + } + + return autoCount; + } + +// ----------------------------------------------------------------------------- +// HasNodeVerticalAutoValues() +// Check if node has properties set to AUTO. +// ----------------------------------------------------------------------------- +// +static TInt HasNodeVerticalAutoValuesL( CXnNode& aNode ) + { + TInt autoCount = 0; + + CXnProperty* height = aNode.HeightL(); + + if ( height ) + { + if ( IsPropertyAutoL( *height ) ) + { + autoCount++; + } + } + else + { + // height is auto as default + autoCount++; + } + + CXnProperty* margintop = aNode.MarginTopL(); + + if ( margintop ) + { + if ( IsPropertyAutoL( *margintop ) ) + { + autoCount++; + } + } + + CXnProperty* marginbottom = aNode.MarginBottomL(); + + if ( marginbottom ) + { + if ( IsPropertyAutoL( *marginbottom ) ) + { + autoCount++; + } + } + + if ( !IsAbsoluteL( aNode ) && !IsRelativeL( aNode ) ) + { + return autoCount; + } + + CXnProperty* top = aNode.TopL(); + + if ( top ) + { + if ( IsPropertyAutoL( *top ) ) + { + autoCount++; + } + } + + CXnProperty* bottom = aNode.BottomL(); + + if ( bottom ) + { + if ( IsPropertyAutoL( *bottom ) ) + { + autoCount++; + } + } + + return autoCount; + } + +// ----------------------------------------------------------------------------- +// HasNodeMinSizesL() +// Check if node has minimum size values. +// ----------------------------------------------------------------------------- +// +static TBool HasNodeMinSizesL( CXnNode& aNode ) + { + CXnProperty* minWidth = aNode.MinWidthL(); + + if ( minWidth ) + { + if ( !IsPropertyNone( *minWidth ) ) + { + return ETrue; + } + } + + CXnProperty* minHeight = aNode.MinHeightL(); + + if ( minHeight ) + { + if ( !IsPropertyNone( *minHeight ) ) + { + return ETrue; + } + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// HasNodeMaxSizesL() +// Check if node has maximum size values. +// ----------------------------------------------------------------------------- +// +static TBool HasNodeMaxSizesL( CXnNode& aNode ) + { + CXnProperty* maxWidth = aNode.MaxWidthL(); + + if ( maxWidth ) + { + if ( !IsPropertyNone( *maxWidth ) ) + { + return ETrue; + } + } + + CXnProperty* maxHeight = aNode.MaxHeightL(); + + if ( maxHeight ) + { + if ( !IsPropertyNone( *maxHeight ) ) + { + return ETrue; + } + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// HorizontalCentimetersToPixelsL() +// Convert horizontal centimeter value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt HorizontalCentimetersToPixelsL( TReal& aCentimeters, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aCentimeters * KCentimetersAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.HorizontalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// HorizontalInchesToPixelsL() +// Convert horizontal inch value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt HorizontalInchesToPixelsL( TReal& aInches, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aInches * KInchesAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.HorizontalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// HorizontalMillimetersToPixelsL() +// Convert horizontal millimeter value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt HorizontalMillimetersToPixelsL( TReal& aMillimeters, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aMillimeters * KMillimetersAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.HorizontalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// HorizontalPicasToPixelsL() +// Convert horizontal pica value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt HorizontalPicasToPixelsL( TReal& aPicas, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aPicas * KPicasAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.HorizontalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// HorizontalPixelValueL() +// Convert horizontal property to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt HorizontalPixelValueL( CXnProperty* aValue, TInt aReferenceValue, + CGraphicsDevice& aScreenDevice, TReal aHorizontalUnitInPixels ) + { + return HorizontalValueToPixelsL( DomPropertyValueFromProperty( aValue ), + static_cast< TReal >( aReferenceValue ), aScreenDevice, + aHorizontalUnitInPixels ); + } + +// ----------------------------------------------------------------------------- +// HorizontalPointsToPixelsL() +// Convert horizontal point value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt HorizontalPointsToPixelsL( TReal& aPoints, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aPoints * KPointsAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.HorizontalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// HorizontalUnitsToPixelsL() +// Convert horizontal unit value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt HorizontalUnitsToPixelsL( TReal aUnits, TReal aUnitInPixels ) + { + TInt pixels = aUnits * aUnitInPixels; + return pixels; + } + +// ----------------------------------------------------------------------------- +// VerticalUnitsToPixelsL() +// Convert vertical unit value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt VerticalUnitsToPixelsL( TReal aUnits, TReal aUnitInPixels ) + { + TInt pixels = aUnits * aUnitInPixels; + return pixels; + } + +// ----------------------------------------------------------------------------- +// HorizontalValueToPixelsL() +// Convert horizontal property value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt HorizontalValueToPixelsL( CXnDomPropertyValue* aValue, + TReal aReferenceValue, CGraphicsDevice& aScreenDevice, TReal aUnitInPixels ) + { + if ( !aValue ) + { + User::Leave( KXnErrHorizontalValueNULL ); + } + CXnDomPropertyValue::TPrimitiveValueType valueType = + aValue->PrimitiveValueType(); + // Handle error cases first, inherit is handled elsewhere, none returns 0 + switch ( valueType ) + { + case CXnDomPropertyValue::EUnknown: + case CXnDomPropertyValue::EEms: + case CXnDomPropertyValue::EExs: + case CXnDomPropertyValue::EDeg: + case CXnDomPropertyValue::ERad: + case CXnDomPropertyValue::EGrad: + case CXnDomPropertyValue::EMs: + case CXnDomPropertyValue::ES: + case CXnDomPropertyValue::EHz: + case CXnDomPropertyValue::EKHz: + case CXnDomPropertyValue::EDimension: + case CXnDomPropertyValue::EString: + case CXnDomPropertyValue::EUri: + case CXnDomPropertyValue::EIdent: + case CXnDomPropertyValue::EAttr: + case CXnDomPropertyValue::ECounter: + case CXnDomPropertyValue::ERect: + case CXnDomPropertyValue::ERgbColor: + case CXnDomPropertyValue::ERgbaColor: + case CXnDomPropertyValue::EFunction: + break; + default: + { + TReal value = aValue->FloatValueL(); + if ( valueType == CXnDomPropertyValue::ENumber || + valueType == CXnDomPropertyValue::EPx ) + { + return static_cast< TInt >( value ); + } + else if ( valueType == CXnDomPropertyValue::EPercentage ) + { + return PercentageToPixelsL( value, aReferenceValue ); + } + else if ( valueType == CXnDomPropertyValue::EIn ) + { + return HorizontalInchesToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::ECm ) + { + return HorizontalCentimetersToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::EMm ) + { + return HorizontalMillimetersToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::EPt ) + { + return HorizontalPointsToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::EPc ) + { + return HorizontalPicasToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::EUnitValue ) + { + return HorizontalUnitsToPixelsL( value, aUnitInPixels ); + } + } + break; + } + + return 0; + } + +// ----------------------------------------------------------------------------- +// IsAbsoluteL() +// Check if node's positioning is absolute. +// ----------------------------------------------------------------------------- +// +static TBool IsAbsoluteL( CXnNode& aNode ) + { + CXnProperty* prop( aNode.PositionL() ); + + if ( prop ) + { + const TDesC8& value( prop->StringValue() ); + if ( value == XnPropertyNames::style::common::position::KAbsolute || + value == XnPropertyNames::style::common::position::KFloating ) + { + return ETrue; + } + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// IsLargerThanMaxSizeL() +// Check if node rect size exceeds it's max sizes. +// ----------------------------------------------------------------------------- +// +static TBool IsLargerThanMaxSizeL( const TRect& aParentRect, CXnNode& aNode, + CGraphicsDevice& aScreenDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + TRect parentRect = aParentRect; + CXnProperty* heightProperty = aNode.HeightL(); + CXnProperty* widthProperty = aNode.WidthL(); + + if ( heightProperty ) + { + CXnProperty* maxHeightProperty = aNode.MaxHeightL(); + if ( maxHeightProperty ) + { + if ( !IsPropertyNone( *maxHeightProperty ) ) + { + TInt maxHeight = VerticalPixelValueL( maxHeightProperty, + parentRect.Height(), aScreenDevice, aVerticalUnitInPixels ); + TInt height = aNode.Rect().Height(); + if ( height > maxHeight ) + { + // height larger than max + return ETrue; + } + } + } + } + + if ( widthProperty ) + { + CXnProperty* maxWidthProperty = aNode.MaxWidthL(); + if ( maxWidthProperty ) + { + if ( !IsPropertyNone( *maxWidthProperty ) ) + { + TInt maxWidth = HorizontalPixelValueL( maxWidthProperty, + parentRect.Width(), aScreenDevice, aHorizontalUnitInPixels ); + TInt width = aNode.Rect().Width(); + if ( width > maxWidth ) + { + // width larger than max + return ETrue; + } + } + } + } + + // width and height within limits + return EFalse; + } + +// ----------------------------------------------------------------------------- +// IsNodeDisplayedL() +// Check if node is able to be displayed. +// ----------------------------------------------------------------------------- +// +static TBool IsNodeDisplayedL( CXnNode& aNode ) + { + if ( !aNode.IsLayoutCapable() ) + { + return EFalse; + } + + // Am I displayed? + CXnProperty* displayProp( aNode.DisplayL() ); + + if ( displayProp ) + { + const TDesC8& display( displayProp->StringValue() ); + + if ( display != XnPropertyNames::style::common::display::KBlock ) + { + return EFalse; + } + } + + CXnNode* parent( aNode.Parent() ); + + // Is my parent displayed? + for ( ; parent; parent = parent->Parent() ) + { + CXnProperty* displayProp( parent->DisplayL() ); + + if ( displayProp ) + { + const TDesC8& display( displayProp->StringValue() ); + + if ( display != XnPropertyNames::style::common::display::KBlock ) + { + return EFalse; + } + } + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// IsNodeTooltip() +// Check if node is a tooltip. +// ----------------------------------------------------------------------------- +// +static TBool IsNodeTooltip( CXnNode& aNode ) + { + _LIT8( tooltip, "tooltip" ); + + if ( aNode.Type()->Type() == tooltip ) + { + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// IsPropertyAutoL() +// Check if property is set to AUTO. +// ----------------------------------------------------------------------------- +// +static TBool IsPropertyAutoL( CXnProperty& aProperty ) + { + if ( &aProperty ) + { + TBool returnValue; + TInt index = 0; + CXnDomProperty* domProperty = aProperty.Property(); + CXnDomPropertyValue* domPropertyValue = + static_cast< CXnDomPropertyValue* >( + domProperty->PropertyValueList().Item( index ) ); + returnValue = domPropertyValue->IsAutoIdent(); + if ( !returnValue ) + { + // if return value is string and not auto or none, + // return ETrue because auto is used as default value + if ( IsStringValueL( aProperty ) && !IsPropertyNone( aProperty ) ) + { + return ETrue; + } + } + return returnValue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// IsPropertyNone() +// Check if property is set to NONE. +// ----------------------------------------------------------------------------- +// +static TBool IsPropertyNone( CXnProperty& aProperty ) + { + if ( &aProperty ) + { + TInt index = 0; + CXnDomProperty* domProperty = aProperty.Property(); + CXnDomPropertyValue* domPropertyValue = + static_cast< CXnDomPropertyValue* >( + domProperty->PropertyValueList().Item( index ) ); + return domPropertyValue->IsNoneIdent(); + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// IsRelativeL() +// Check if node's positioning is absolute. +// ----------------------------------------------------------------------------- +// +static TBool IsRelativeL( CXnNode& aNode ) + { + CXnProperty* positioningProperty = aNode.PositionL(); + if ( positioningProperty ) + { + const TDesC8& positioning = positioningProperty->StringValue(); + if ( positioning == XnPropertyNames::style::common::position::KRelative ) + { + return ETrue; + } + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// IsSmallerThanMinSizeL() +// Check if node rect size is smaller than it's min sizes. +// ----------------------------------------------------------------------------- +// +static TBool IsSmallerThanMinSizeL( const TRect& aParentRect, CXnNode& aNode, + CGraphicsDevice& aScreenDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + TRect parentRect = aParentRect; + CXnProperty* heightproperty = aNode.HeightL(); + CXnProperty* widthproperty = aNode.WidthL(); + + if ( heightproperty ) + { + CXnProperty* minheightproperty = aNode.MinHeightL(); + if ( minheightproperty ) + { + if ( !IsPropertyNone( *minheightproperty ) ) + { + TInt minheight = VerticalPixelValueL( minheightproperty, + parentRect.Height(), aScreenDevice, aVerticalUnitInPixels ); + TInt height = aNode.Rect().Height(); + if ( height < minheight ) + { + // height smaller than minimum + return ETrue; + } + } + } + } + if ( widthproperty ) + { + CXnProperty* minwidthproperty = aNode.MinWidthL(); + if ( minwidthproperty ) + { + if ( !IsPropertyNone( *minwidthproperty ) ) + { + TInt minwidth = HorizontalPixelValueL( minwidthproperty, + parentRect.Width(), aScreenDevice, aHorizontalUnitInPixels ); + TInt width = aNode.Rect().Width(); + if ( width < minwidth ) + { + // width smaller than minimum + return ETrue; + } + } + } + } + // width and height within limits + return EFalse; + } + +// ----------------------------------------------------------------------------- +// IsStringValueL() +// Check if property value is string. +// ----------------------------------------------------------------------------- +// +static TBool IsStringValueL( CXnProperty& aProperty ) + { + CXnDomList& propertyValueList = aProperty.Property()->PropertyValueList(); + CXnDomPropertyValue* value = + static_cast< CXnDomPropertyValue* >( propertyValueList.Item( 0 ) ); + if ( value->PrimitiveValueType() == CXnDomPropertyValue::EString || + value->PrimitiveValueType() == CXnDomPropertyValue::EIdent ) + { + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// IsValuePercentageL() +// Check if property value is percentage. +// ----------------------------------------------------------------------------- +// +static TBool IsValuePercentageL( CXnProperty& aProperty ) + { + CXnDomProperty* domProperty = aProperty.Property(); + CXnDomPropertyValue* domPropertyValue = static_cast< + CXnDomPropertyValue* >( domProperty->PropertyValueList().Item( 0 ) ); + if ( !domPropertyValue ) + { + User::Leave( KXnErrDomPropertyValueNULL ); + } + CXnDomPropertyValue::TPrimitiveValueType valueType = + domPropertyValue->PrimitiveValueType(); + if ( valueType == CXnDomPropertyValue::EPercentage ) + { + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// PercentageToPixelsL() +// Convert percentage value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt PercentageToPixelsL( TReal& aPercentage, TReal aReferenceValue ) + { + TReal value = aReferenceValue * aPercentage * KIntPercentageConstant; + return static_cast< TInt >( value + KIntConversionConstant ); + } + +// ----------------------------------------------------------------------------- +// GetPreviousNodeL() +// ----------------------------------------------------------------------------- +// +static CXnNode* GetPreviousNodeL( CXnNode& aNode ) + { + CXnNode* returnValue = NULL; + CXnNode* parent = aNode.Parent(); + + if ( !parent ) + { + return returnValue; + } + + RPointerArray< CXnNode >& nodes = parent->Children(); + + for ( TInt currentIndex = 0; currentIndex < nodes.Count(); currentIndex++ ) + { + CXnNode* checkNode = nodes[currentIndex]; + if ( &aNode == checkNode && currentIndex > 0 ) + { + for ( TInt candidateIndex = + currentIndex - 1; candidateIndex >= 0; candidateIndex-- ) + { + checkNode = nodes[candidateIndex]; + if ( IsNodeDisplayedL( *checkNode ) && + !checkNode->IsDropped() && !IsAbsoluteL( *checkNode ) && + !IsNodeTooltip( *checkNode ) ) + { + returnValue = nodes[candidateIndex]; + break; + } + } + } + } + + return returnValue; + } + +// ----------------------------------------------------------------------------- +// PlaceAreasL() +// Move the area rects to their places. All positioning is done here. +// ----------------------------------------------------------------------------- +// +static void PlaceAreasL( CXnNode& aNode, RPointerArray< CXnNode >& aLaidOutList, + TInt aLayoutPhase, CGraphicsDevice& aGraphicsDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ) + { + CXnNodeBreadthFirstIterator< CXnNode >* iterator = + CXnNodeBreadthFirstIterator< CXnNode >::NewL( aNode ); + CleanupStack::PushL( iterator ); + + RPointerArray< CXnNode > absoluteNodes; + CleanupClosePushL( absoluteNodes ); + + RPointerArray< CXnNode > relativeNodes; + CleanupClosePushL( relativeNodes ); + + RPointerArray< CXnNode > autoNodes; + CleanupClosePushL( autoNodes ); + + RPointerArray< CXnNode > adaptiveNodes; + CleanupClosePushL( adaptiveNodes ); + + CXnProperty* parentBlockProgressionProperty( NULL ); + CXnProperty* parentDirectionProperty( NULL ); + const TDesC8* parentBlockProgression( NULL ); + const TDesC8* parentDirection( NULL ); + + CXnUiEngine* engine( aNode.UiEngine() ); + TSize maxAvailableSize( engine->ClientRect().Size() ); + + // Start to go through the tree + CXnNode* previous( NULL ); + + CXnNode* parent( NULL ); + TInt columnWidth; + TInt columnMargin; + TRect parentRect; + +#ifdef _XN3_DEBUG_ + RDebug::Print( _L("Xuikon: Layout:") ); + TBuf8< 256 > debug; +#endif + + // Place areas according their parents and positioning + for( CXnNode* node = iterator->Value(); node; node = iterator->NextL() ) + { +#ifdef _XN3_DEBUG_ + debug = node->Type()->Type(); + CXnProperty* id( node->IdL() ); + if ( id ) + { + debug.Append( _L8( ", id: " ) ); + debug.Append( id->StringValue() ); + } +#endif + + if ( node->IsLaidOut() ) + { +#ifdef _XN3_DEBUG_ + debug.Append( _L8( ", already laidout" ) ); + RDebug::RawPrint( debug ); +#endif + + continue; + } + + if ( !IsNodeDisplayedL( *node ) || node->IsDropped() ) + { +#ifdef _XN3_DEBUG_ + debug.Append( _L8( ", not displayed or dropped" ) ); + RDebug::RawPrint( debug ); +#endif + continue; + } + +#ifdef _XN3_DEBUG_ + RDebug::RawPrint( debug ); +#endif + + switch ( aLayoutPhase ) + { + case XnLayoutPhase::ELayout: + if ( aLaidOutList.Find( node ) == KErrNotFound ) + { + aLaidOutList.AppendL( node ); + } + /* flow through */ + case XnLayoutPhase::EMeasure: + if ( node->ViewNodeImpl() ) + { + // check that view's children fit into it + FitChildrenIntoParentL( *node, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + continue; + } + engine->CheckAdaptiveContentL( *node, maxAvailableSize ); + if ( node->IsDropped() ) + { + // Adaptive content check dropped this node + continue; + } + break; + default: + // Should not happen + continue; + } + + if( node->Type()->Type() == KScrollableBoxNodeName ) + { + CXnScrollableControlAdapter* cntrl = node->ScrollableControl(); + if( cntrl ) + { + cntrl->ResetState(); + } + } + + CXnNode* tmpParent( DisplayedParentL( *node ) ); + + // Is parent changed? + if ( tmpParent != parent ) + { + columnWidth = 0; + columnMargin = 0; + if ( parent ) + { + // Process auto areas + ProcessAutoAreasL( *parent, &autoNodes, *parentBlockProgression, + *parentDirection, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + autoNodes.Reset(); + // Pocess relative areas + for ( TInt i = 0; i < relativeNodes.Count(); i++ ) + { + CalculateRelativePositionsL( parentRect, *relativeNodes[i], + aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + } + relativeNodes.Reset(); + // Process absolute areas + for ( TInt i = 0; i < absoluteNodes.Count(); i++ ) + { + CalculatePaddingL( parentRect, *absoluteNodes[i], + aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + CalculateBorderL( *absoluteNodes[i], parentRect, + aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + CalculateAbsoluteMarginL( *parent, *absoluteNodes[i], NULL, + *parentBlockProgression, *parentDirection, parentRect, + aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + CalculateAbsolutePositionsL( *absoluteNodes[i], parentRect, + aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + } + absoluteNodes.Reset(); + previous = NULL; + } + // Get new parent properties + parent = tmpParent; + parentBlockProgressionProperty = parent->BlockProgressionL(); + parentDirectionProperty = parent->DirectionL(); + if ( !parentBlockProgressionProperty ) + { + // block progression default is tb + parentBlockProgression = + &XnPropertyNames::style::common::block_progression::KTB(); + } + else + { + parentBlockProgression = + &parentBlockProgressionProperty->StringValue(); + } + if ( !parentDirectionProperty ) + { + // direction default is ltr + parentDirection = + &XnPropertyNames::style::common::direction::KLTR(); + } + else + { + parentDirection = &parentDirectionProperty->StringValue(); + } + } + + parentRect = parent->Rect(); + + CalculateRectL( *node, *parent, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + + // Which positioning is used? + CXnProperty* positioningProp( node->PositionL() ); + // Static is the default + const TDesC8* positioning( + &XnPropertyNames::style::common::position::KStatic() ); + + if ( positioningProp ) + { + const TDesC8& value( positioningProp->StringValue() ); + if ( value != KNullDesC8 ) + { + positioning = &value; + } + } + // Adaptive nodes' _must_ be collected here + if ( node->IsAdaptive() && adaptiveNodes.Find( node ) == KErrNotFound ) + { + // Postpone adaptive area processing + adaptiveNodes.AppendL( node ); + } + // Tooltips are processed as absolute areas + TBool absolute( IsAbsoluteL( *node ) || IsNodeTooltip( *node ) ); + if ( !node->ViewNodeImpl() && HasNodeAutoValuesL( *node ) && !absolute ) + { + // if area has auto values, process it later + autoNodes.AppendL( node ); + } + if ( absolute ) + { + // Absolute positioning area found, take it out of normal flow + // Because of that, previous node is not set + // Absolute area is put to a array to be processed later + absoluteNodes.AppendL( node ); + continue; + } + // static or relative positioning + CalculatePaddingL( parentRect, *node, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + CalculateBorderL( *node, parentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + previous = GetPreviousNodeL( *node ); + CalculateMarginL( *parent, *node, previous, *parentBlockProgression, + *parentDirection, parentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels, columnWidth, + columnMargin ); + FitChildrenIntoParentL( *node, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + if ( XnPropertyNames::style::common::position::KRelative() == + *positioning ) + { + // Relative positioning area found, add it's offset later + relativeNodes.AppendL( node ); + } + previous = node; + } + + if ( parent ) + { + // Are there auto nodes left? + ProcessAutoAreasL( *parent, &autoNodes, *parentBlockProgression, + *parentDirection, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + // Are there relative nodes left? + for ( TInt i = 0; i < relativeNodes.Count(); i++ ) + { + CalculateRelativePositionsL( parentRect, *relativeNodes[i], + aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + } + // Are there absolute nodes left? + for ( TInt i = 0; i < absoluteNodes.Count(); i++ ) + { + CalculatePaddingL( parentRect, *absoluteNodes[i], aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + CalculateBorderL( *absoluteNodes[i], parentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + CalculateAbsoluteMarginL( *parent, *absoluteNodes[i], NULL, + *parentBlockProgression, *parentDirection, parentRect, + aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + FitChildrenIntoParentL( *absoluteNodes[i], aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + CalculateAbsolutePositionsL( *absoluteNodes[i], parentRect, + aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + } + } + + for ( TInt i = 0; i < adaptiveNodes.Count(); i++ ) + { + // Fix parent size to its childs content size + ProcessAdaptiveAreasL( *adaptiveNodes[i], aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + } + + // close node arrays and destroy iterator + CleanupStack::PopAndDestroy( 5, iterator ); + } + +// ----------------------------------------------------------------------------- +// PriorizeChildrenL() +// Find a child node with highest priority value and drop all +// child nodes with highest priority. +// ----------------------------------------------------------------------------- +// +static void PriorizeChildrenL( CXnNode& aNode ) + { + RPointerArray< CXnNode >& children( aNode.Children() ); + + CXnNode* candidate( NULL ); + TInt highest( 0 ); + + // Find the highest priority value among the children + for ( TInt i = 0; i < children.Count(); i++ ) + { + CXnNode* node( children[i] ); + if ( IsNodeDisplayedL( *node ) && !node->IsDropped() && + !IsAbsoluteL( *node ) && !IsNodeTooltip( *node ) ) + { + CXnProperty* priorityProperty( node->DisplayPriorityL() ); + if ( priorityProperty ) + { + TInt priority( priorityProperty->FloatValueL() ); + if ( priority > highest ) + { + // highest found, set new top priority + highest = priority; + candidate = node; + } + } + } + } + if ( candidate ) + { + aNode.UiEngine()->SetNodeDroppedL( + *candidate, XnNodeLayout::EDropped ); + } + } + +// ----------------------------------------------------------------------------- +// CalculateAutoPropertiesOfNodesL() +// +// ----------------------------------------------------------------------------- +// +static void CalculateAutoPropertiesOfNodesL( + RPointerArray< CXnNode >* aAutoNodeArray, TInt& aWidthAutoCount, + TInt& aHeightAutoCount ) + { + aWidthAutoCount = 0; + aHeightAutoCount = 0; + + // calculate the number of auto properties in each direction + for ( TInt i = 0; i < aAutoNodeArray->Count(); ++i ) + { + CXnNode* tmp = ( *aAutoNodeArray )[i]; + if ( !tmp->IsDropped() ) + { + if ( HasNodeVerticalAutoValuesL( *tmp ) ) + { + ++aHeightAutoCount; + } + if ( HasNodeHorizontalAutoValuesL( *tmp ) ) + { + ++aWidthAutoCount; + } + } + } + if ( aWidthAutoCount == 0 ) + { + aWidthAutoCount = 1; + } + if ( aHeightAutoCount == 0 ) + { + aHeightAutoCount = 1; + } + } + +// ----------------------------------------------------------------------------- +// ProcessAutoAreasL() +// Process nodes with layout properties defined as auto. +// ----------------------------------------------------------------------------- +// +static void ProcessAutoAreasL( CXnNode& aParent, + RPointerArray< CXnNode >* aAutoNodeArray, + const TDesC8& aParentBlockProgression, const TDesC8& aParentDirection, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + TInt autoCount( aAutoNodeArray->Count() ); + + if ( autoCount == 0 ) + { + return; + } + + // Just to be sure, drop others first if needed + FitChildrenIntoParentL( aParent, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + + TInt originalHeightAutoCount( 0 ); + TInt originalWidthAutoCount( 0 ); + + CalculateAutoPropertiesOfNodesL( aAutoNodeArray, originalWidthAutoCount, + originalHeightAutoCount ); + + TInt heightAutoCount( originalHeightAutoCount ); + TInt widthAutoCount( originalWidthAutoCount ); + + // calculate space to use (parent height and width - placed areas) + CXnNode* parent( &aParent ); + TRect parentRect( parent->Rect() ); + + if( parent->Control() && parent->Control()->OwnsWindow() ) + { + parentRect = TRect( parentRect.iTl - parent->MarginRect().iTl, parentRect.Size() ); + } + + TInt parentWidth( parentRect.Width() ); + TInt parentHeight( parentRect.Height() ); + + RPointerArray< CXnNode >& children( parent->Children() ); + + RPointerArray< CXnNode > layoutedAutoNodes; + CleanupClosePushL( layoutedAutoNodes ); + + TBool layoutedAutoNodesAdded( EFalse ); + TBool layoutingHeight( EFalse ); + TBool layoutingWidth( EFalse ); + + TInt displayedChildCount( DisplayedChildrenCountL( aParent ) ); + + do + { + layoutedAutoNodesAdded = EFalse; + + // count the size used by the non auto nodes and + // auto nodes which have been calculated + TSize calculatedAutosize = CalculateSpaceUsedByAutoChildrenL( + *aAutoNodeArray, layoutedAutoNodes, *parent, + aParentBlockProgression, aParentDirection, aGraphicsDevice ); + + TInt usedSiblingHeight( calculatedAutosize.iHeight ); + TInt usedSiblingWidth( calculatedAutosize.iWidth ); + + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + // calculate space for each auto area + parentHeight = parentRect.Height() - usedSiblingHeight; + parentHeight = parentHeight / heightAutoCount; + layoutingHeight = ETrue; + } + else // assume that block progression is LR or RL + { + // calculate space for each auto area + parentWidth = parentRect.Width() - usedSiblingWidth; + parentWidth = parentWidth / widthAutoCount; + layoutingWidth = ETrue; + } + for ( TInt i = 0; i < autoCount; i++ ) + { + CXnNode* node( ( *aAutoNodeArray )[i] ); + if ( layoutedAutoNodes.Find( node ) != KErrNotFound ) + { + // The size has already been calculated and fixed + continue; + } + if ( node->IsDropped() ) + { + // The node is dropped, no need to recalculate + continue; + } + CXnProperty* heightProperty = node->HeightL(); + CXnProperty* widthProperty = node->WidthL(); + CXnProperty* marginLeft = node->MarginLeftL(); + CXnProperty* marginRight = node->MarginRightL(); + CXnProperty* marginTop = node->MarginTopL(); + CXnProperty* marginBottom = node->MarginBottomL(); + TInt freeHeight = parentHeight; + TInt freeWidth = parentWidth; + TBool verticalValuesAuto = IsPropertyAutoL( *heightProperty ) || + IsPropertyAutoL( *marginTop ) || + IsPropertyAutoL( *marginBottom ); + if ( !verticalValuesAuto == !heightProperty ) + { + verticalValuesAuto = ETrue; + } + TBool horizontalValuesAuto = IsPropertyAutoL( *widthProperty ) || + IsPropertyAutoL( *marginLeft ) || + IsPropertyAutoL( *marginRight ); + if ( !horizontalValuesAuto == !widthProperty ) + { + horizontalValuesAuto = ETrue; + } + TInt adaptive( node->IsAdaptive() ); + // I have childs share the available space between them + if ( adaptive & XnAdaptive::EHeight ) + { + // Give all available height to the adaptive node's children + freeHeight = parentRect.Height() - usedSiblingHeight; + } + if ( adaptive & XnAdaptive::EWidth ) + { + // Give all available width to the adaptive node's children + freeWidth = parentRect.Width() - usedSiblingWidth; + } + ScaleAutoAreaL( *node, freeWidth, freeHeight, + aParentBlockProgression, aParentDirection, + parentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + FitChildrenIntoParentL( *node, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + // handle autonodes which had auto width or height, + // but also min or max limit + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + if ( IsPropertyAutoL( *heightProperty ) && + ( freeHeight != node->MarginRect().Height() ) ) + { + if ( layoutedAutoNodes.Find( node ) == KErrNotFound ) + { + // The height has been callculated already + // and it doesn't depend on the expected + // auto size anymore, mark the node as layouted + // and reduce the parent free size + layoutedAutoNodes.AppendL( node ); + heightAutoCount--; + layoutedAutoNodesAdded = ETrue; + } + } + } + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + if ( IsPropertyAutoL( *widthProperty ) && + ( freeWidth != node->MarginRect().Width() ) ) + { + if ( layoutedAutoNodes.Find ( node ) == KErrNotFound ) + { + // The width has been callculated already + // and it doesn't depend on the expected + // auto size anymore, mark the node as layouted + // and reduce the parent free size + layoutedAutoNodes.AppendL( node ); + widthAutoCount--; + layoutedAutoNodesAdded = ETrue; + } + } + } + } + + // drop areas if children don't fit + FitAutoChildrenIntoParentL( *aAutoNodeArray, layoutedAutoNodes, + *parent, aParentBlockProgression, aParentDirection, + aGraphicsDevice ); + + // if something was dropped, reset the layouted auto nodes array + TInt newDisplayedChildCount = DisplayedChildrenCountL( aParent ); + + if ( displayedChildCount != newDisplayedChildCount ) + { + // if nodes with auto values are dropped + // recalculate the auto counts + CalculateAutoPropertiesOfNodesL( aAutoNodeArray, + originalWidthAutoCount, originalHeightAutoCount ); + + // recalculate everything again because something was dropped + layoutedAutoNodes.Reset(); + displayedChildCount = newDisplayedChildCount; + heightAutoCount = originalHeightAutoCount; + widthAutoCount = originalWidthAutoCount; + layoutedAutoNodesAdded = ETrue; + } + + } + while( layoutedAutoNodesAdded && ( ( heightAutoCount && layoutingHeight ) || + ( widthAutoCount && layoutingWidth ) ) ); + + MoveAutoAreaL( parentRect, children, aParentBlockProgression, + aParentDirection ); + + CleanupStack::PopAndDestroy( &layoutedAutoNodes ); + } + +// ----------------------------------------------------------------------------- +// CalculateCollapseMarginsL() +// Return the amount the margins should be collapsed in two list. The list +// element contains the amount of margins collapsed in pixels to the previous +// layoutable, nondropped, static and nontooltip node. +// When calculating the movement of the node, this value should be decreased +// from the movement. +// When calculating the total size of the auto proerety nodes, this value +// should be decreased from the size taken. +// If the children list contains one of the above mentioned type of nodes, +// then the value for those are always 0. +// For example, if there are three children and the middle one has been +// dropped, the the returned list contains two elemnts, first is 0 and +// the second one is the amount of collapsed margins between the first and the +// last node. +// The caller is responsible of releasing the returned arrays. +// ----------------------------------------------------------------------------- +// +static void CalculateCollapseMarginsL( RPointerArray< CXnNode >& aChildren, + RArray< TInt >& aCollapsedMarginsWidth, + RArray< TInt >& aCollapsedMarginsHeight, + const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection ) + { + aCollapsedMarginsWidth.Reset(); + aCollapsedMarginsHeight.Reset(); + + // Find first node which needs to be taken into account + CXnNode* previousNode = NULL; + TInt startIndex = aChildren.Count(); + for ( TInt i = 0; !previousNode && i < aChildren.Count(); i++ ) + { + if ( IsNodeDisplayedL( *aChildren[i] ) && + !aChildren[i]->IsDropped() && + !IsAbsoluteL(*aChildren[i]) && + !IsNodeTooltip(*aChildren[i]) && + aChildren[i]->IsLayoutCapable()) + { + previousNode = aChildren[i]; + startIndex = aChildren.Find( previousNode ) + 1; + } + } + + // Add needed amount of collapsed margins as 0 + for ( TInt i = 1; i < startIndex; i++ ) + { + User::LeaveIfError( aCollapsedMarginsWidth.Append( 0 ) ); + User::LeaveIfError( aCollapsedMarginsHeight.Append( 0 ) ); + } + + // Calculate collapsed for the rest of the nodes, 0 if not needed + for ( TInt i = startIndex; i < aChildren.Count() && previousNode; i++ ) + { + CXnNode* node = aChildren[i]; + TInt collapsedWidth = 0; + TInt collapsedHeight = 0; + + if ( IsNodeDisplayedL( *node ) && + !node->IsDropped() && + !IsAbsoluteL( *node ) && + !IsNodeTooltip( *node ) && + node->IsLayoutCapable() ) + { + if ( ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) && + aParentDirection == + XnPropertyNames::style::common::direction::KLTR ) + { + TInt previousRightMargin = Abs( previousNode-> + MarginRect().iBr.iX - previousNode->BorderRect().iBr.iX ); + TInt nodeLeftMargin = Abs( node->BorderRect().iTl.iX - + node->MarginRect().iTl.iX ); + + collapsedWidth = -( previousRightMargin > nodeLeftMargin ) ? + nodeLeftMargin : previousRightMargin; + } + + if ( ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR ) && + aParentDirection == + XnPropertyNames::style::common::direction::KRTL ) + { + TInt previousLeftMargin = Abs( previousNode-> + MarginRect().iTl.iX - previousNode->BorderRect().iTl.iX ); + TInt nodeRightMargin = Abs( node->BorderRect().iBr.iX - + node->MarginRect().iBr.iX ); + + collapsedWidth = ( previousLeftMargin > nodeRightMargin ) ? + nodeRightMargin : previousLeftMargin; + } + + if ( ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) && + aParentDirection == + XnPropertyNames::style::common::direction::KLTR ) + { + TInt previousBottomMargin = Abs( previousNode-> + MarginRect().iBr.iY - previousNode->BorderRect().iBr.iY ); + TInt nodeTopMargin = Abs( node->BorderRect().iTl.iY - + node->MarginRect().iTl.iY ); + + collapsedHeight = ( previousBottomMargin > nodeTopMargin ) ? + nodeTopMargin : previousBottomMargin; + } + + if ( ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) && + aParentDirection == + XnPropertyNames::style::common::direction::KRTL ) + { + TInt previousTopMargin = Abs( previousNode->\ + MarginRect().iTl.iY - previousNode->BorderRect().iTl.iY ); + TInt nodeBottomMargin = Abs( node->BorderRect().iBr.iY - + node->MarginRect().iBr.iY ); + + collapsedHeight = -( ( previousTopMargin > nodeBottomMargin ) ? + nodeBottomMargin : previousTopMargin ); + } + } + User::LeaveIfError( aCollapsedMarginsWidth.Append( collapsedWidth ) ); + User::LeaveIfError( aCollapsedMarginsHeight.Append( collapsedHeight ) ); + previousNode = node; + } + } + +// ----------------------------------------------------------------------------- +// CalculateSpaceUsedByAutoChildrenL() +// Return space used by node's children including auto nodes which have +// been calculated. +// ----------------------------------------------------------------------------- +// +static TSize CalculateSpaceUsedByAutoChildrenL( + RPointerArray< CXnNode >& aAutoChildren, + RPointerArray< CXnNode >& aCalculatedAutoChildren, + CXnNode& aParent, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, CGraphicsDevice& /*aScreenDevice*/ ) + { + TInt usedSiblingHeight( 0 ); + TInt usedSiblingWidth( 0 ); + + TSize largestSize( 0, 0 ); + + // Calculate collapsed margins + RArray< TInt > collapsedMarginsWidth; + RArray< TInt > collapsedMarginsHeight; + + CleanupClosePushL( collapsedMarginsWidth ); + CleanupClosePushL( collapsedMarginsHeight ); + + RPointerArray< CXnNode >& children( aParent.Children() ); + + CalculateCollapseMarginsL( children, + collapsedMarginsWidth, + collapsedMarginsHeight, + aParentBlockProgression, + aParentDirection ); + + for ( TInt i = 0; i < children.Count(); i++ ) + { + CXnNode* node( children[i] ); + if ( IsNodeDisplayedL( *node ) && !node->IsDropped() && + !IsAbsoluteL( *node ) && !IsNodeTooltip( *node ) ) + { + // Calculate how much does the node takes space, + // 0 is used for auto nodes which have not been calculated + TSize siblingSize( node->MarginRect().Size() ); + if ( aAutoChildren.Find( node ) != KErrNotFound && + aCalculatedAutoChildren.Find( node ) == KErrNotFound ) + { + // Node is auto node and its values have not been fixed yet + // The node may have auto in either direction + // so that must be checked + if ( HasNodeVerticalAutoValuesL( *node ) ) + { + siblingSize.iHeight = 0; + } + if ( HasNodeHorizontalAutoValuesL( *node ) ) + { + siblingSize.iWidth = 0; + } + } + // Update the largets found node rect + if ( siblingSize.iWidth > largestSize.iWidth ) + { + largestSize.iWidth = siblingSize.iWidth; + } + if ( siblingSize.iHeight > largestSize.iHeight ) + { + largestSize.iHeight = siblingSize.iHeight; + } + // Add the used area + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + usedSiblingHeight += siblingSize.iHeight; + usedSiblingWidth = largestSize.iWidth; + } + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + usedSiblingWidth += siblingSize.iWidth; + usedSiblingHeight = largestSize.iHeight; + } + // Find the children index from all children + TInt childrenIndex( children.Find( node ) ); + // No collapsing for just one node + if ( childrenIndex > 0 ) + { + // Take the collapsed margins into account + // (the value is 0 if not collapsed) + usedSiblingWidth -= collapsedMarginsWidth[childrenIndex - 1]; + usedSiblingHeight -= collapsedMarginsHeight[childrenIndex - 1]; + } + } + } + // Collapsed arrays + CleanupStack::PopAndDestroy( 2 ); + + return TSize( usedSiblingWidth, usedSiblingHeight ); + } + +// ----------------------------------------------------------------------------- +// MoveAutoAreaL() +// Move nodes after all auto properties have been handled. +// ----------------------------------------------------------------------------- +// +static void MoveAutoAreaL( TRect& parentRect, + RPointerArray< CXnNode >& aChildren, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection ) + { + // Calculate collapsed margins + RArray< TInt > collapsedMarginsWidth; + RArray< TInt > collapsedMarginsHeight; + + CleanupClosePushL( collapsedMarginsWidth ); + CleanupClosePushL( collapsedMarginsHeight ); + + CalculateCollapseMarginsL( aChildren, collapsedMarginsWidth, + collapsedMarginsHeight, aParentBlockProgression, + aParentDirection ); + + CXnNode* previousNode( NULL ); + TInt startIndex( aChildren.Count() ); + + for ( TInt i = 0; !previousNode && i < aChildren.Count(); i++ ) + { + CXnNode* node( aChildren[i] ); + if ( IsNodeDisplayedL( *node ) && !node->IsDropped() && + !IsAbsoluteL (*node ) && !IsNodeTooltip( *node ) ) + { + previousNode = node; + startIndex = i + 1; + } + } + if ( !previousNode ) + { + // Collapsed arrays + CleanupStack::PopAndDestroy( 2 ); + return; + } + + // Which way are the boxes layouted? + // + // 1) ltr, tb: 2) ltr, bt: 3) ltr, rl: 4) ltr, lr: + // 1 4 3 6 1 2 3 4 5 6 + // 2 5 2 5 4 5 6 1 2 3 + // 3 6 1 4 + // + // 5) rtl, tb: 6) rtl, bt: 7) rtl, rl: 8) rtl, lr: + // 4 1 6 3 3 2 1 6 5 4 + // 5 2 5 2 6 5 4 3 2 1 + // 6 3 4 1 + // + + TInt layoutType( 0 ); + if ( aParentDirection == XnPropertyNames::style::common::direction::KLTR ) + { + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB ) + { + layoutType = 1; + } + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + layoutType = 2; + } + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + layoutType = 3; + } + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR ) + { + layoutType = 4; + } + } + else if ( aParentDirection == + XnPropertyNames::style::common::direction::KRTL ) + { + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB ) + { + layoutType = 5; + } + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + layoutType = 6; + } + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KRL ) + { + layoutType = 7; + } + else if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KLR ) + { + layoutType = 8; + } + } + TRect previousContentRect( previousNode->Rect() ); + TRect previousPaddingRect( previousNode->PaddingRect() ); + TRect previousBorderRect( previousNode->BorderRect() ); + TRect previousMarginRect( previousNode->MarginRect() ); + TRect previousNormalFlowBorderRect( previousNode->NormalFlowBorderRect() ); + TInt widthToMove = 0; + TInt heightToMove = 0; + + // Move the first node to the correct place + switch ( layoutType ) + { + case 1: + { + // Top to parent top + heightToMove = parentRect.iTl.iY - previousMarginRect.iTl.iY; + } + break; + case 2: + { + // Bottom to parent bottom + heightToMove = parentRect.iBr.iY - previousMarginRect.iBr.iY; + } + break; + case 3: + { + // Left to parent left + widthToMove = parentRect.iTl.iX - previousMarginRect.iTl.iX; + } + break; + case 4: + { + heightToMove = parentRect.iBr.iY - previousMarginRect.iBr.iY; + widthToMove = parentRect.iTl.iX - previousMarginRect.iTl.iX; + } + break; + case 5: // flow through + case 7: + { + heightToMove = parentRect.iTl.iY - previousMarginRect.iTl.iY; + widthToMove = parentRect.iBr.iX - previousMarginRect.iBr.iX; + } + break; + case 6: // flow through + case 8: + { + heightToMove = parentRect.iBr.iY - previousMarginRect.iBr.iY; + widthToMove = parentRect.iBr.iX - previousMarginRect.iBr.iX; + } + break; + } + + // Move rects + previousContentRect.Move( widthToMove, heightToMove ); + previousPaddingRect.Move( widthToMove, heightToMove ); + previousBorderRect.Move( widthToMove, heightToMove ); + previousMarginRect.Move( widthToMove, heightToMove ); + previousNormalFlowBorderRect.Move( widthToMove, heightToMove ); + + // Set rects + previousNode->SetRect( previousContentRect ); + previousNode->SetPaddingRect( previousPaddingRect ); + previousNode->SetBorderRect( previousBorderRect ); + previousNode->SetMarginRect( previousMarginRect ); + previousNode->SetNormalFlowBorderRect( previousNormalFlowBorderRect ); + + for ( TInt i = startIndex; i < aChildren.Count() && previousNode; i++ ) + { + CXnNode* node( aChildren[i] ); + + if ( IsNodeDisplayedL( *node ) && !node->IsDropped() && + !IsAbsoluteL( *node ) && !IsNodeTooltip( *node ) ) + { + // Get rects + TRect contentRect( node->Rect() ); + TRect paddingRect( node->PaddingRect() ); + TRect borderRect( node->BorderRect() ); + TRect marginRect( node->MarginRect() ); + TRect normalFlowBorderRect( node->NormalFlowBorderRect() ); + previousMarginRect = previousNode->MarginRect(); + + widthToMove = 0; + heightToMove = 0; + + // Count movements + switch ( layoutType ) + { + case 1: + { + // Move node top to the previous bottom + heightToMove = previousMarginRect.iBr.iY - marginRect.iTl.iY; + heightToMove -= collapsedMarginsHeight[i - 1]; + } + break; + case 2: + { + // Move node bottom to the previous top + heightToMove = previousMarginRect.iTl.iY - marginRect.iBr.iY; + heightToMove += collapsedMarginsHeight[i - 1]; + } + break; + case 3: + { + // Move node left to the previous right + widthToMove = previousMarginRect.iBr.iX - marginRect.iTl.iX; + widthToMove -= collapsedMarginsWidth[i - 1]; + } + break; + case 4: + { + heightToMove = previousMarginRect.iTl.iY - marginRect.iTl.iY; + widthToMove = previousMarginRect.iBr.iX - marginRect.iTl.iX; + widthToMove -= collapsedMarginsWidth[i - 1]; + } + break; + case 5: + { + // Move node top to the previous bottom + heightToMove = previousMarginRect.iBr.iY - marginRect.iTl.iY; + heightToMove -= collapsedMarginsHeight[i - 1]; + widthToMove = previousMarginRect.iTl.iX - marginRect.iTl.iX; + } + break; + case 6: + { + // Move node bottom to the previous top + heightToMove = previousMarginRect.iTl.iY - marginRect.iBr.iY; + heightToMove += collapsedMarginsHeight[i - 1]; + widthToMove = previousMarginRect.iTl.iX - marginRect.iTl.iX; + } + break; + case 7: + { + // Move node left to the previous right + widthToMove = previousMarginRect.iTl.iX - marginRect.iBr.iX; + widthToMove += collapsedMarginsWidth[i - 1]; + } + break; + case 8: + { + heightToMove = previousMarginRect.iTl.iY - marginRect.iTl.iY; + widthToMove = previousMarginRect.iTl.iX - marginRect.iBr.iX; + widthToMove += collapsedMarginsWidth[i - 1]; + } + break; + } + + // Move rects + contentRect.Move( widthToMove, heightToMove ); + paddingRect.Move( widthToMove, heightToMove ); + borderRect.Move( widthToMove, heightToMove ); + marginRect.Move( widthToMove, heightToMove ); + normalFlowBorderRect.Move( widthToMove, heightToMove ); + + // Set rects + node->SetRect( contentRect ); + node->SetPaddingRect( paddingRect ); + node->SetBorderRect( borderRect ); + node->SetMarginRect( marginRect ); + node->SetNormalFlowBorderRect( normalFlowBorderRect ); + + previousNode = node; + } + } + + // Collapsed arrays + CleanupStack::PopAndDestroy( 2 ); + } + +// ----------------------------------------------------------------------------- +// ScaleAutoAreaL() +// Scale dimensions for areas that have properties set to AUTO. +// ----------------------------------------------------------------------------- +// +static TSize ScaleAutoAreaL( CXnNode& aNode, TInt aWidthToFit, + TInt aHeightToFit, const TDesC8& aParentBlockProgression, + const TDesC8& aParentDirection, TRect& aParentRect, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + // if only one value is auto, it is computed from equality + // if width is set to AUTO, all other values become 0 + // if both margin left and right are set to AUTO, their computed + // values are equal + TSize sizeOfAutoArea( 0, 0 ); + + RArray< TPtrC8 > autoArray; + CleanupClosePushL( autoArray ); + + CXnProperty* top = aNode.TopL(); + if ( IsPropertyAutoL( *top ) ) + { + TPtrC8 propertyName = top->Property()->Name(); + autoArray.Append( propertyName ); + } + CXnProperty* bottom = aNode.BottomL(); + if ( IsPropertyAutoL( *bottom ) ) + { + TPtrC8 propertyName = bottom->Property()->Name(); + autoArray.Append( propertyName ); + } + CXnProperty* left = aNode.LeftL(); + if ( IsPropertyAutoL( *left ) ) + { + TPtrC8 propertyName = left->Property()->Name(); + autoArray.Append( propertyName ); + } + CXnProperty* right = aNode.RightL(); + if ( IsPropertyAutoL( *right ) ) + { + TPtrC8 propertyName = right->Property()->Name(); + autoArray.Append( propertyName ); + } + CXnProperty* width = aNode.WidthL(); + if ( IsPropertyAutoL( *width ) ) + { + TPtrC8 propertyName = width->Property()->Name(); + autoArray.Append( propertyName ); + } + if ( !width ) + { + TPtrC8 propertyName = XnPropertyNames::style::common::KWidth(); + autoArray.Append( propertyName ); + } + CXnProperty* height = aNode.HeightL(); + if ( IsPropertyAutoL( *height ) ) + { + TPtrC8 propertyName = height->Property()->Name(); + autoArray.Append( propertyName ); + } + if ( !height ) + { + TPtrC8 propertyName = XnPropertyNames::style::common::KHeight(); + autoArray.Append( propertyName ); + } + CXnProperty* marginTop = aNode.MarginTopL(); + if ( IsPropertyAutoL( *marginTop ) ) + { + TPtrC8 propertyName = marginTop->Property()->Name(); + autoArray.Append( propertyName ); + } + CXnProperty* marginBottom = aNode.MarginBottomL(); + if ( IsPropertyAutoL( *marginBottom ) ) + { + TPtrC8 propertyName = marginBottom->Property()->Name(); + autoArray.Append( propertyName ); + } + CXnProperty* marginLeft = aNode.MarginLeftL(); + if ( IsPropertyAutoL( *marginLeft ) ) + { + TPtrC8 propertyName = marginLeft->Property()->Name(); + autoArray.Append( propertyName ); + } + CXnProperty* marginRight = aNode.MarginRightL(); + if ( IsPropertyAutoL( *marginRight ) ) + { + TPtrC8 propertyName = marginRight->Property()->Name(); + autoArray.Append( propertyName ); + } + + if ( aParentDirection == XnPropertyNames::style::common::direction::KLTR ) + { + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + sizeOfAutoArea = TSize( AutoStaticTBL( aNode, aWidthToFit, + aHeightToFit, autoArray, aParentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ); + } + else // block progression LR + { + sizeOfAutoArea = TSize( AutoStaticLRL( aNode, aWidthToFit, + aHeightToFit, autoArray, aParentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ); + } + } + else // direction RTL + { + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + sizeOfAutoArea = TSize( AutoStaticBTL( aNode, aWidthToFit, + aHeightToFit, autoArray, aParentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ); + } + else // block progression RL + { + sizeOfAutoArea = TSize( AutoStaticRLL( aNode, aWidthToFit, + aHeightToFit, autoArray, aParentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ); + } + } + + // if size not within min&max size limits, resize + // (min-size) + if ( HasNodeMinSizesL( aNode ) ) + { + if ( IsSmallerThanMinSizeL( aParentRect, aNode, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ) + { + GrowToMinSizeL( aNode, aParentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + } + } + + if ( HasNodeMaxSizesL( aNode ) ) + { + if ( IsLargerThanMaxSizeL( aParentRect, aNode, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ) ) + { + ShrinkToMaxSizeL( aNode, aParentRect, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + } + } + + CleanupStack::PopAndDestroy( &autoArray ); + + // Return the context rect size because the min-max + // test might have changed the size of autoarea + return aNode.Rect().Size(); + } + +// ----------------------------------------------------------------------------- +// GrowToMinSizeL() +// +// ----------------------------------------------------------------------------- +// +static void GrowToMinSizeL( CXnNode& aNode, TRect& aParentRect, + CGraphicsDevice& aScreenDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ) + { + // grow to min size + CXnProperty* minWidthProperty = aNode.MinWidthL(); + CXnProperty* minHeightProperty = aNode.MinHeightL(); + + TRect contentRect( aNode.Rect() ); + TRect paddingRect( aNode.PaddingRect() ); + TRect borderRect( aNode.BorderRect() ); + TRect normalFlowBorderRect( aNode.NormalFlowBorderRect() ); + TRect marginRect( aNode.MarginRect() ); + + if ( minWidthProperty ) + { + if ( !IsPropertyNone( *minWidthProperty ) ) + { + TInt minWidth = HorizontalPixelValueL( minWidthProperty, + aParentRect.Width(), aScreenDevice, aHorizontalUnitInPixels ); + if ( contentRect.Width() < minWidth ) + { + TInt widthToGrow = minWidth - contentRect.Width(); + contentRect.Resize( widthToGrow, 0 ); + paddingRect.Resize( widthToGrow, 0 ); + borderRect.Resize( widthToGrow, 0 ); + normalFlowBorderRect.Resize( widthToGrow, 0 ); + marginRect.Resize( widthToGrow, 0 ); + } + } + } + + if ( minHeightProperty ) + { + if ( !IsPropertyNone( *minHeightProperty ) ) + { + TInt minHeight = VerticalPixelValueL( minHeightProperty, + aParentRect.Height(), aScreenDevice, aVerticalUnitInPixels ); + if ( contentRect.Height() < minHeight ) + { + TInt heightToGrow = minHeight - contentRect.Height(); + contentRect.Resize( 0, heightToGrow ); + paddingRect.Resize( 0, heightToGrow ); + borderRect.Resize( 0, heightToGrow ); + normalFlowBorderRect.Resize( 0, heightToGrow ); + marginRect.Resize( 0, heightToGrow ); + } + } + } + + aNode.SetRect( contentRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + aNode.SetMarginRect( marginRect ); + } + +// ----------------------------------------------------------------------------- +// ShrinkToMaxSizeL() +// ----------------------------------------------------------------------------- +// +static void ShrinkToMaxSizeL( CXnNode& aNode, TRect& aParentRect, + CGraphicsDevice& aScreenDevice, + TReal aHorizontalUnitInPixels, TReal aVerticalUnitInPixels ) + { + // grow to min size + CXnProperty* maxWidthProperty = aNode.MaxWidthL(); + CXnProperty* maxHeightProperty = aNode.MaxHeightL(); + + TRect contentRect( aNode.Rect() ); + TRect paddingRect( aNode.PaddingRect() ); + TRect borderRect( aNode.BorderRect() ); + TRect normalFlowBorderRect( aNode.NormalFlowBorderRect() ); + TRect marginRect( aNode.MarginRect() ); + + if ( maxWidthProperty ) + { + if ( !IsPropertyNone( *maxWidthProperty ) ) + { + TInt maxWidth = HorizontalPixelValueL( maxWidthProperty, + aParentRect.Width(), aScreenDevice, aHorizontalUnitInPixels ); + if ( contentRect.Width() > maxWidth ) + { + TInt widthToShrink = contentRect.Width() - maxWidth; + contentRect.Resize( -widthToShrink, 0 ); + paddingRect.Resize( -widthToShrink, 0 ); + borderRect.Resize( -widthToShrink, 0 ); + normalFlowBorderRect.Resize( -widthToShrink, 0 ); + marginRect.Resize( -widthToShrink, 0 ); + } + } + } + + if ( maxHeightProperty ) + { + if ( !IsPropertyNone( *maxHeightProperty ) ) + { + TInt maxHeight = VerticalPixelValueL( maxHeightProperty, + aParentRect.Height(), aScreenDevice, aVerticalUnitInPixels ); + if ( contentRect.Height() > maxHeight ) + { + TInt heightToShrink = contentRect.Height() - maxHeight; + contentRect.Resize( 0, -heightToShrink ); + paddingRect.Resize( 0, -heightToShrink ); + borderRect.Resize( 0, -heightToShrink ); + normalFlowBorderRect.Resize( 0, -heightToShrink ); + marginRect.Resize( 0, -heightToShrink ); + } + } + } + + aNode.SetRect( contentRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + aNode.SetMarginRect( marginRect ); + } + +// ----------------------------------------------------------------------------- +// FitAutoChildrenIntoParentL() +// +// ----------------------------------------------------------------------------- +// +static void FitAutoChildrenIntoParentL( RPointerArray< CXnNode >& aAutoChildren, + RPointerArray< CXnNode >& aCalculatedAutoChildren, CXnNode& aParent, + const TDesC8& aParentBlockProgression, const TDesC8& aParentDirection, + CGraphicsDevice& aGraphicsDevice ) + { + if( IsSrollableBox( aParent ) ) + { + return; + } + + TSize space = CalculateSpaceUsedByAutoChildrenL( aAutoChildren, + aCalculatedAutoChildren, aParent, aParentBlockProgression, + aParentDirection, aGraphicsDevice ); + + TSize parentSize( aParent.Rect().Size() ); + + while( ( ( parentSize.iHeight < space.iHeight ) && + ( parentSize.iHeight > 0 ) ) || + ( ( parentSize.iWidth < space.iWidth ) && + ( parentSize.iWidth > 0 ) ) ) + { + // if areas go over just one pixel, cut the pixel + // from a percent sized node + if ( ( parentSize.iHeight == space.iHeight - 1 ) || + ( parentSize.iWidth == space.iWidth - 1 ) ) + { + CutOnePixelFromPercentChildNodeL( aParent, aParentBlockProgression ); + return; + } + + TInt childCount( DisplayedChildrenCountL( aParent ) ); + + PriorizeChildrenL( aParent ); + + if ( DisplayedChildrenCountL( aParent ) == childCount ) + { + // cannot drop any more children, but they still don't fit + return; + } + + space = CalculateSpaceUsedByAutoChildrenL( aAutoChildren, + aCalculatedAutoChildren, aParent, aParentBlockProgression, + aParentDirection, aGraphicsDevice ); + } + } + +// ----------------------------------------------------------------------------- +// VerticalCentimetersToPixelsL() +// Convert vertical centimeter value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt VerticalCentimetersToPixelsL( TReal& aCentimeters, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aCentimeters * KCentimetersAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.VerticalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// VerticalInchesToPixelsL() +// Convert vertical inch value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt VerticalInchesToPixelsL( TReal& aInches, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aInches * KInchesAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.VerticalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// VerticalMillimetersToPixelsL() +// Convert vertical millimeter value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt VerticalMillimetersToPixelsL( TReal& aMillimeters, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aMillimeters * KMillimetersAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.VerticalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// VerticalPicasToPixelsL() +// Convert vertical pica value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt VerticalPicasToPixelsL( TReal& aPicas, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aPicas * KPicasAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.VerticalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// VerticalPixelValueL() +// Convert vertical property to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt VerticalPixelValueL( CXnProperty* aValue, TInt aReferenceValue, + CGraphicsDevice& aScreenDevice, TReal aVerticalUnitInPixels ) + { + return VerticalValueToPixelsL( DomPropertyValueFromProperty( aValue ), + static_cast< TReal >( aReferenceValue ), aScreenDevice, + aVerticalUnitInPixels ); + } + +// ----------------------------------------------------------------------------- +// VerticalPointsToPixelsL() +// Convert vertical point value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt VerticalPointsToPixelsL( TReal& aPoints, + CGraphicsDevice& aScreenDevice ) + { + TReal twips = aPoints * KPointsAsTwips; + TInt intTwips = static_cast< TInt >( twips + KIntConversionConstant ); + return aScreenDevice.VerticalTwipsToPixels( intTwips ); + } + +// ----------------------------------------------------------------------------- +// VerticalValueToPixelsL() +// Convert vertical property value to pixel value. +// ----------------------------------------------------------------------------- +// +static TInt VerticalValueToPixelsL( CXnDomPropertyValue* aValue, + TReal aReferenceValue, CGraphicsDevice& aScreenDevice, + TReal aVerticalUnitInPixels ) + { + if ( !aValue ) + { + User::Leave( KXnErrDomPropertyValueNULL ); + } + CXnDomPropertyValue::TPrimitiveValueType valueType = + aValue->PrimitiveValueType(); + // Handle error cases first, inherit is handled elsewhere, none returns 0 + switch ( valueType ) + { + case CXnDomPropertyValue::EUnknown: + case CXnDomPropertyValue::EEms: + case CXnDomPropertyValue::EExs: + case CXnDomPropertyValue::EDeg: + case CXnDomPropertyValue::ERad: + case CXnDomPropertyValue::EGrad: + case CXnDomPropertyValue::EMs: + case CXnDomPropertyValue::ES: + case CXnDomPropertyValue::EHz: + case CXnDomPropertyValue::EKHz: + case CXnDomPropertyValue::EDimension: + case CXnDomPropertyValue::EString: + case CXnDomPropertyValue::EUri: + case CXnDomPropertyValue::EIdent: + case CXnDomPropertyValue::EAttr: + case CXnDomPropertyValue::ECounter: + case CXnDomPropertyValue::ERect: + case CXnDomPropertyValue::ERgbColor: + case CXnDomPropertyValue::ERgbaColor: + case CXnDomPropertyValue::EFunction: + break; + default: + { + TReal value = aValue->FloatValueL(); + if ( valueType == CXnDomPropertyValue::ENumber || + valueType == CXnDomPropertyValue::EPx ) + { + return static_cast< TInt >( value ); + } + else if ( valueType == CXnDomPropertyValue::EPercentage ) + { + return PercentageToPixelsL( value, aReferenceValue ); + } + else if ( valueType == CXnDomPropertyValue::EIn ) + { + return VerticalInchesToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::ECm ) + { + return VerticalCentimetersToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::EMm ) + { + return VerticalMillimetersToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::EPt ) + { + return VerticalPointsToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::EPc ) + { + return VerticalPicasToPixelsL( value, aScreenDevice ); + } + else if ( valueType == CXnDomPropertyValue::EUnitValue ) + { + return VerticalUnitsToPixelsL( value, aVerticalUnitInPixels ); + } + } + break; + } + + return 0; + } + +// ----------------------------------------------------------------------------- +// ProcessAdaptiveAreasL() +// Process adaptive areas +// ----------------------------------------------------------------------------- +// +static void ProcessAdaptiveAreasL( CXnNode& aParent, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + CXnProperty* blockProgressionProperty( aParent.BlockProgressionL() ); + CXnProperty* directionProperty( aParent.DirectionL() ); + const TDesC8* blockProgression( + &XnPropertyNames::style::common::block_progression::KTB() ); + const TDesC8* direction( + &XnPropertyNames::style::common::direction::KLTR() ); + + if ( directionProperty ) + { + direction = &directionProperty->StringValue(); + } + + if ( blockProgressionProperty ) + { + blockProgression = &blockProgressionProperty->StringValue(); + } + + CalculateAdaptiveSizeL( aParent, *blockProgression, *direction, + aGraphicsDevice, aHorizontalUnitInPixels, aVerticalUnitInPixels ); + } + +// ----------------------------------------------------------------------------- +// CalculateAdaptiveSizeL() +// Fixes the adaptive node size to its layouted children size +// ----------------------------------------------------------------------------- +// +static void CalculateAdaptiveSizeL( CXnNode& aNode, + const TDesC8& aParentBlockProgression, const TDesC8& /*aParentDirection*/, + CGraphicsDevice& aGraphicsDevice, TReal aHorizontalUnitInPixels, + TReal aVerticalUnitInPixels ) + { + TInt adaptive( aNode.IsAdaptive() ); + CXnNode* parent( aNode.Parent() ); + + if ( !adaptive || !parent ) + { + return; + } + + TInt adaptiveHeight( 0 ); + TInt adaptiveWidth( 0 ); + + RPointerArray< CXnNode > children; + CleanupClosePushL( children ); + + TInt count( DisplayedChildrenCountL( aNode, &children ) ); + + TSize size; + + if ( count == 0 ) + { + TRect parentRect( parent->Rect() ); + if( parent->Control() && parent->Control()->OwnsWindow() ) + { + parentRect = TRect( parentRect.iTl - parent->MarginRect().iTl, parentRect.Size() ); + } + // I don't have any displayed childrens, fix my own size + size = CalculateTotalDimensionsL( aNode, ETrue, EFalse, + parentRect, aGraphicsDevice, aHorizontalUnitInPixels, + aVerticalUnitInPixels ); + adaptiveHeight = size.iHeight; + adaptiveWidth = size.iWidth; + } + else + { + TBool autoHeight( EFalse ); + TBool autoWidth( EFalse ); + TBool sizeKnown( EFalse ); + for ( TInt i = 0; i < children.Count(); i++ ) + { + CXnNode* node( children[i] ); + if ( !IsNodeDisplayedL( *node ) ) + { + continue; + } + CXnProperty* heightProperty( node->HeightL() ); + if ( !( node->IsAdaptive() & XnAdaptive::EHeight ) && + ( adaptive & XnAdaptive::EHeight ) && + IsPropertyAutoL( *heightProperty ) ) + { + adaptiveHeight = node->MarginRect().Size().iHeight; + autoHeight = ETrue; + if ( !( adaptive & XnAdaptive::EWidth ) ) + { + // Height is now known and width is not adaptive + // -> size is now known + sizeKnown = ETrue; + } + } + CXnProperty* widthProperty( node->WidthL() ); + if ( !( node->IsAdaptive() & XnAdaptive::EWidth ) && + ( adaptive & XnAdaptive::EWidth ) && + IsPropertyAutoL( *widthProperty ) ) + { + adaptiveWidth = node->MarginRect().Size().iWidth; + autoWidth = ETrue; + if ( !( adaptive & XnAdaptive::EHeight ) ) + { + // Width is now known and height is not adaptive + // -> size is now known + sizeKnown = ETrue; + } + } + if ( autoWidth && autoHeight ) + { + // Both auto -> size is now known + sizeKnown = ETrue; + } + if ( !sizeKnown ) + { + // Fix adaptive sized child's size first + ProcessAdaptiveAreasL( *node, aGraphicsDevice, + aHorizontalUnitInPixels, aVerticalUnitInPixels ); + TSize marginSize( node->MarginRect().Size() ); + if ( aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KTB || + aParentBlockProgression == + XnPropertyNames::style::common::block_progression::KBT ) + { + if ( !autoHeight && ( adaptive & XnAdaptive::EHeight ) ) + { + adaptiveHeight += marginSize.iHeight; + } + if ( !autoWidth && ( adaptive & XnAdaptive::EWidth ) ) + { + if ( marginSize.iWidth > adaptiveWidth ) + { + adaptiveWidth = marginSize.iWidth; + } + } + } + else if ( aParentBlockProgression == + XnPropertyNames::style::common:: + block_progression::KLR || aParentBlockProgression == + XnPropertyNames::style::common:: + block_progression::KRL ) + { + if ( !autoHeight && ( adaptive & XnAdaptive::EHeight ) ) + { + if ( marginSize.iHeight > adaptiveHeight ) + { + adaptiveHeight = marginSize.iHeight; + } + } + if ( !autoWidth && ( adaptive & XnAdaptive::EWidth ) ) + { + adaptiveWidth += marginSize.iWidth; + } + } + } + } + } + + TRect contentRect( aNode.Rect() ); + TRect paddingRect( aNode.PaddingRect() ); + TRect borderRect( aNode.BorderRect() ); + TRect marginRect( aNode.MarginRect() ); + TRect normalFlowBorderRect( aNode.NormalFlowBorderRect() ); + + TRect paddingRectDiff( SubtractRect( paddingRect, contentRect ) ); + TRect borderRectDiff( SubtractRect( borderRect, contentRect ) ); + TRect marginRectDiff( SubtractRect( marginRect, contentRect ) ); + TRect normalFlowBorderRectDiff( SubtractRect( + normalFlowBorderRect, contentRect ) ); + + TInt dy( 0 ); + TInt dx( 0 ); + + if ( adaptive & XnAdaptive::EHeight ) + { + if ( adaptiveHeight <= 0 ) + { + adaptiveHeight = 0; + } + dy = contentRect.Size().iHeight - adaptiveHeight; + } + if ( adaptive & XnAdaptive::EWidth ) + { + if ( adaptiveWidth <= 0 ) + { + adaptiveWidth = 0; + } + dx = contentRect.Size().iWidth - adaptiveWidth; + } + + contentRect.Resize( -dx, -dy ); + + paddingRect = AddRect( contentRect, paddingRectDiff ); + borderRect = AddRect( contentRect, borderRectDiff ); + marginRect = AddRect( contentRect, marginRectDiff ); + normalFlowBorderRect = AddRect( contentRect, normalFlowBorderRectDiff ); + + aNode.SetRect( contentRect ); + aNode.SetPaddingRect( paddingRect ); + aNode.SetBorderRect( borderRect ); + aNode.SetMarginRect( marginRect ); + aNode.SetNormalFlowBorderRect( normalFlowBorderRect ); + + aNode.FixAdaptiveSizeL( contentRect.Size() ); + + aNode.UiEngine()->CheckAdaptiveContentL( aNode, contentRect.Size() ); + + CleanupStack::PopAndDestroy( &children ); + } + +// ----------------------------------------------------------------------------- +// BuildTriggerNodeLC +// Builds a trigger node +// ----------------------------------------------------------------------------- +// +static CXnNode* BuildTriggerNodeLC( CXnUiEngine& aUiEngine, + const TDesC8& aTriggerName ) + { + CXnNode* node = CXnNode::NewL(); + CleanupStack::PushL( node ); + + CXnType* type = CXnType::NewL( XnPropertyNames::action::KTrigger ); + CleanupStack::PushL( type ); + + CXnNodeImpl* impl = CXnNodeImpl::NewL( type ); + CleanupStack::Pop( type ); + + node->SetImpl( impl ); + node->SetUiEngine( aUiEngine ); + + CXnDomPropertyValue* nameValue = CXnDomPropertyValue::NewL( + aUiEngine.ODT()->DomDocument().StringPool() ); + + CleanupStack::PushL( nameValue ); + + nameValue->SetStringValueL( CXnDomPropertyValue::EString, aTriggerName ); + + CXnProperty* name = CXnProperty::NewL( + XnPropertyNames::action::trigger::KName, + nameValue, aUiEngine.ODT()->DomDocument().StringPool() ); + + CleanupStack::Pop( nameValue ); + + CleanupStack::PushL( name ); + + node->SetPropertyL( name ); + + CleanupStack::Pop( name ); + + //CleanupStack::Pop( node ); + + return node; + } + +// ----------------------------------------------------------------------------- +// UpdateInternalUnits +// Updates UiEngineImpl unit values +// ----------------------------------------------------------------------------- +// +static void UpdateInternalUnits( TReal& aHorizontalUnitInPixels, + TReal& aVerticalUnitInPixels, TRect aRect ) + { + TAknWindowComponentLayout referenceLayout = + AknLayoutScalable_Avkon::aid_value_unit2(); + TRect parent( aRect ); + + TAknLayoutRect rect; + + // TAknWindowLineLayout should go directly + //to LayoutRect/LayoutControl etc. methods + rect.LayoutRect( parent, referenceLayout.LayoutLine() ); + + TReal rectWidth = rect.Rect().Width(); + + if ( rectWidth == 0 ) + { + aHorizontalUnitInPixels = 0; + } + + aHorizontalUnitInPixels = rectWidth / 10; + + TReal rectHeight = rect.Rect().Height(); + + if ( rectHeight == 0 ) + { + aVerticalUnitInPixels = 0; + } + + aVerticalUnitInPixels = rectHeight / 10; + } + +// ----------------------------------------------------------------------------- +// BuildScreenDeviceChangeTriggerNodeLC +// Build trigger node for screen device change event +// ----------------------------------------------------------------------------- +// +static CXnNode* BuildScreenDeviceChangeTriggerNodeLC( CXnUiEngine& aUiEngine ) + { + CXnDomStringPool& sp( aUiEngine.ODT()->DomDocument().StringPool() ); + + CXnNode* node = CXnNode::NewL(); + CleanupStack::PushL( node ); + + CXnType* type = CXnType::NewL( XnPropertyNames::action::KTrigger ); + CleanupStack::PushL( type ); + + CXnNodeImpl* impl = CXnNodeImpl::NewL( type ); + CleanupStack::Pop( type ); + + node->SetImpl( impl ); + node->SetUiEngine( aUiEngine ); + + CXnDomPropertyValue* nameValue = CXnDomPropertyValue::NewL( sp ); + CleanupStack::PushL( nameValue ); + + nameValue->SetStringValueL( CXnDomPropertyValue::EString, + XnPropertyNames::action::trigger::name::KScreenDeviceChange ); + + CXnProperty* name = CXnProperty::NewL( + XnPropertyNames::action::trigger::KName, nameValue, sp ); + CleanupStack::Pop( nameValue ); + CleanupStack::PushL( name ); + + node->SetPropertyL( name ); + CleanupStack::Pop( name ); + + CXnDomPropertyValue* reasonValue = CXnDomPropertyValue::NewL( sp ); + CleanupStack::PushL( reasonValue ); + + const TDesC8* reasonString( NULL ); + + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + reasonString = &XnPropertyNames::action::trigger::name:: + uidefinitionmodification::reason::KLandscape; + } + else + { + reasonString = &XnPropertyNames::action::trigger::name:: + uidefinitionmodification::reason::KPortrait; + } + + reasonValue->SetStringValueL( CXnDomPropertyValue::EString, *reasonString ); + + CXnProperty* reason = CXnProperty::NewL( XnPropertyNames::action::trigger:: + name::uidefinitionmodification::KReason, reasonValue, sp ); + + CleanupStack::Pop( reasonValue ); + + CleanupStack::PushL( reason ); + + node->SetPropertyL( reason ); + + CleanupStack::Pop( reason ); + + return node; + } + +// ----------------------------------------------------------------------------- +// FillFocusCandidatesL +// ----------------------------------------------------------------------------- +// +static void FillFocusCandidatesL( CXnNode* aParent, + RPointerArray< CXnNode >& aArray ) + { + RPointerArray< CXnNode >& children( aParent->Children() ); + + aArray.AppendL( aParent ); + + for ( TInt i = 0; i < children.Count(); i++ ) + { + FillFocusCandidatesL( children[i], aArray ); + } + } + +// ----------------------------------------------------------------------------- +// DetermineStatusPaneLayout +// ----------------------------------------------------------------------------- +// +static TInt DetermineStatusPaneLayout( CXnProperty* aProperty ) + { + TInt spane( KErrNotFound ); + + if ( aProperty ) + { + const TDesC8& value( aProperty->StringValue() ); + + // Currently supported status pane layout + if ( value == XnPropertyNames::view::statuspanelayout::KNone ) + { + spane = R_AVKON_STATUS_PANE_LAYOUT_EMPTY; + } + if ( value == XnPropertyNames::view::statuspanelayout::KBasic ) + { + spane = R_AVKON_STATUS_PANE_LAYOUT_IDLE; + } + else if ( value == XnPropertyNames::view::statuspanelayout::KBasicFlat ) + { + spane = R_AVKON_STATUS_PANE_LAYOUT_IDLE_FLAT; + } + else if ( value == + XnPropertyNames::view::statuspanelayout::KWideScreen ) + { + spane = R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE; + } + else if ( value == + XnPropertyNames::view::statuspanelayout::KWideScreenFlat ) + { + spane = R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT; + } + else if ( value == + XnPropertyNames::view::statuspanelayout:: + KWideScreenFlat3Softkeys ) + { + spane = R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT_NO_SOFTKEYS; + } + } + + return spane; + } + +// ----------------------------------------------------------------------------- +// SetAdaptivesL +// ----------------------------------------------------------------------------- +// +static TBool SetAdaptivesL( CXnNode& aNode ) + { + TBool retval( EFalse ); + + // Check if the node is adaptive + if ( aNode.IsAdaptive( ETrue ) && IsNodeDisplayedL( aNode ) ) + { + retval = ETrue; + // Mark adaptive node to be measured + aNode.SetAdaptiveL( XnAdaptive::EMeasure ); + } + + RPointerArray< CXnNode >& children( aNode.Children() ); + + for ( TInt i = 0; i < children.Count(); i++ ) + { + TBool ret( SetAdaptivesL( *children[i] ) ); + if ( ret ) + { + retval = ret; + } + } + + return retval; + } + +#ifdef _XN3_DEBUG_ +// ----------------------------------------------------------------------------- +// TraceTreeL +// ----------------------------------------------------------------------------- +// +static void TraceTreeL( CXnNode* aRootNode ) + { + CXnDepthFirstTreeIterator< CXnNode >* iterator = + CXnDepthFirstTreeIterator< CXnNode >::NewL( *aRootNode ); + CleanupStack::PushL( iterator ); + + RDebug::Print( _L("Xuikon: UI tree:") ); + + TBuf8< 256 > debug; + + TInt level( 0 ); + + for( CXnNode* node = iterator->Value(); node; + node = iterator->NextL() ) + { + debug = _L8( "Xuikon: " ); + + level = iterator->Level(); + + for ( TInt i = 0; i < level; i++ ) + { + debug.Append( ' ' ); + } + + debug.Append( node->Type()->Type() ); + + CXnProperty* id( node->IdL() ); + + if ( id ) + { + debug.Append( _L8( ", id: " ) ); + debug.Append( id->StringValue() ); + } + + debug.AppendFormat( _L8( ", laidout: %d" ), node->IsLaidOut() ); + debug.AppendFormat( _L8( ", displayed: %d" ), + IsNodeDisplayedL( *node ) ); + + CCoeControl* control( node->Control() ); + + if ( control ) + { + TBool visible( control->IsVisible() ); + TRect rect( control->Rect() ); + TPoint tl( rect.iTl ); + TPoint br( rect.iBr ); + debug.AppendFormat( _L8( ", visible %d:" ), visible ); + debug.AppendFormat( + _L8( ", Tl: %d %d, Br: %d %d" ), tl.iX, tl.iY, br.iX, br.iY ); + } + else + { + debug.Append( _L8( ", no control" ) ); + } + RDebug::RawPrint( debug ); + } + + CleanupStack::PopAndDestroy( iterator ); + } +#endif + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::CXnUiEngineImpl() +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CXnUiEngineImpl::CXnUiEngineImpl( CXnUiEngine& aUiEngine, + CXnAppUiAdapter& aAdapter ) + : iUiEngine( &aUiEngine ), iAppUiAdapter( aAdapter ), + iViewManager( aAdapter.ViewManager() ) + { + iAppUiAdapter.UiStateListener().AddObserver( *this ); + + iViewManager.AddObserver( *this ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::ConstructL() +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::ConstructL() + { + iEditMode = CXnEditMode::NewL( *iUiEngine ); + + iHitTest = CXnHitTest::NewL(); + + iCurrentGraphicsDevice = CCoeEnv::Static()->ScreenDevice(); + + // Update the units here, even the refence client rect is only a quess. + // That is because we don't know the UI furniture yet. Units are + // needed in controls constructions + UpdateInternalUnits( + iHorizontalUnitInPixels, + iVerticalUnitInPixels, + iAppUiAdapter.ClientRect() ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::NewL() +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CXnUiEngineImpl* CXnUiEngineImpl::NewL( CXnUiEngine& aUiEngine, + CXnAppUiAdapter& aAdapter ) + { + return new ( ELeave ) CXnUiEngineImpl( aUiEngine, aAdapter ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::~CXnUiEngineImpl() +// C++ default destructor. +// ----------------------------------------------------------------------------- +// +CXnUiEngineImpl::~CXnUiEngineImpl() + { + iAppUiAdapter.UiStateListener().RemoveObserver( *this ); + + iViewManager.RemoveObserver( *this ); + + delete iEditMode; + delete iHitTest; + + iFocusCandidateList.Reset(); + iRedrawRegions.ResetAndDestroy(); + iDirtyList.Reset(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::AppUiAdapter() +// ----------------------------------------------------------------------------- +// +CXnAppUiAdapter& CXnUiEngineImpl::AppUiAdapter() const + { + return iAppUiAdapter; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::LayoutUIL() +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::LayoutUIL( CXnNode* /*aNode*/ ) + { + if ( IsLayoutDisabled() ) + { + iLayoutControl |= XnLayoutControl::ELayoutUI; + return; + } + + iLayoutControl &= ~XnLayoutControl::ELayoutUI; + + if ( iDirtyList.Count() == 0 ) + { + // Nothing to do, layout is up-to-date + return; + } + + DisableRenderUiLC(); + CXnNode* candidate( StartLayoutFromL() ); + PrepareRunLayoutL(); + iDirtyList.Reset(); + + // Run layout until it is fully calculated + do + { + iLayoutPhase = RunLayoutL( candidate ); + } + while ( iLayoutPhase != XnLayoutPhase::ENone ); + + CXnNode* focused( FocusedNode() ); + + if ( focused && focused->IsDropped() ) + { + // The currently focused node is dropped, run losevisualization + CXnNode* loseVisualisation = + BuildTriggerNodeLC( *iUiEngine, + XnPropertyNames::action::trigger::name::KLoseVisualisation ); + + focused->ReportXuikonEventL( *loseVisualisation ); + CleanupStack::PopAndDestroy( loseVisualisation ); + + if ( FocusedNode() == focused ) + { + // Remove focus as losevisualization trigger didn't + // change focus from dropped node to another one + SetFocusedNodeL( NULL ); + } + } + + if ( !FocusedNode() && iAppUiAdapter.FocusShown() ) + { + // No focus, try if some of the focus candidates can be focused + RootNode()->RunFocusChangeL( iFocusCandidateList ); + } + + iFocusCandidateList.Reset(); + + iAppUiAdapter.EffectManager()->UiLayouted(); + + // Layout is now recalculated + CleanupStack::PopAndDestroy(); // anonymous + } + +// ----------------------------------------------------------------------------- +// PrepareRunLayoutL() +// Set dropped flags of all nodes in the tree to ENone. +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::PrepareRunLayoutL() + { + if ( iLayoutPhase == XnLayoutPhase::ENone ) + { + iLayoutPhase = XnLayoutPhase::ELayout; + + for ( TInt i = 0; i < iDirtyList.Count(); i++ ) + { + CXnNode* dirty( iDirtyList[i] ); + + // Clear dropped flags recursively + SetNodeDroppedL( *dirty, XnNodeLayout::ENone ); + + if ( SetAdaptivesL( *dirty ) ) + { + // Adaptive node causes measure phase + iLayoutPhase = XnLayoutPhase::EMeasure; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::RunLayoutL() +// ----------------------------------------------------------------------------- +// +TInt CXnUiEngineImpl::RunLayoutL( CXnNode* aNode ) + { + TRect clientRect( ClientRect() ); + // Move it to 0, 0 + clientRect.Move( -clientRect.iTl.iX, -clientRect.iTl.iY ); + + RPointerArray< CXnNode > laidOutList; + CleanupClosePushL( laidOutList ); + + if ( IsNodeDisplayedL( *aNode ) ) + { + if ( aNode->ViewNodeImpl() && !aNode ->IsLaidOut() ) + { + aNode->SetMarginRect( clientRect ); + aNode->SetBorderRect( clientRect ); + aNode->SetNormalFlowBorderRect( clientRect ); + aNode->SetPaddingRect( clientRect ); + aNode->SetRect( clientRect ); + } + + // Put areas to place + PlaceAreasL( *aNode, laidOutList, iLayoutPhase, + *iCurrentGraphicsDevice, iHorizontalUnitInPixels, + iVerticalUnitInPixels ); + } + + TInt nextPhase; + + switch ( iLayoutPhase ) + { + case XnLayoutPhase::EMeasure: + nextPhase = XnLayoutPhase::ELayout; + break; + case XnLayoutPhase::ELayout: + // Layout is now calculated + iCurrentView->SetLaidOutL(); + iLayoutControl &= ~XnLayoutControl::EViewDirty; + // Check nodes which dimensions are changed + for ( TInt i = 0; i < laidOutList.Count(); i++ ) + { + CXnNode* node( laidOutList[i] ); + if( IsSrollableBox( *node ) && node->ScrollableControl() ) + { + node->ScrollableControl()->LayoutChangedL(); + } + if ( /*IsNodeTooltip( *node ) ||*/ !node->IsLaidOut() ) + { + continue; + } + CXnControlAdapter* adapter( node->Control() ); + if ( adapter ) + { + TRect rect; + + if ( node->ViewNodeImpl() ) + { + rect = ClientRect(); + + // Move it to 0, 0 + rect.Move( -rect.iTl.iX, -rect.iTl.iY ); + } + else + { + rect = node->BorderRect(); + } + if ( adapter->Rect() != rect ) + { + AddToRedrawListL( node, rect ); + + adapter->SetRect( rect ); + CXnProperty* prop = node->GetPropertyL( + XnPropertyNames::common::KSizeAware ); + if ( prop && prop->StringValue() == + XnPropertyNames::KTrue ) + { + CXnNode* sizeChanged = + BuildTriggerNodeLC( *iUiEngine, + XnPropertyNames::action::trigger::name:: + KSizeChanged ); + node->ReportXuikonEventL( *sizeChanged ); + CleanupStack::PopAndDestroy( sizeChanged ); + } + } + } + } + /* flow through */ + default: + nextPhase = XnLayoutPhase::ENone; + break; + } + CleanupStack::PopAndDestroy( &laidOutList ); + return nextPhase; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::RenderUIL() +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::RenderUIL( CXnNode* /*aNode*/ ) + { + if ( IsLayoutDisabled() ) + { + // Layout is not up-to-date + iLayoutControl |= XnLayoutControl::ERenderUI; + return; + } + +#ifdef _XN3_DEBUG_ + TraceTreeL(iCurrentView ); +#endif + + for( TInt i=0; iiControl; + RRegion& redrawRegion = iRedrawRegions[i]->iRegion; + + if( redrawRegion.CheckError() ) + { + // Mark tree rendered + iCurrentView->SetRenderedL(); + // Error occured during dirty set, redraw whole window + control->DrawNow(); + } + else + { + if( !redrawRegion.IsEmpty() ) + { + // Mark tree rendered + iCurrentView->SetRenderedL(); + TInt count( redrawRegion.Count() ); + + if( count > 2 ) + { + // Make bounding rect over the dirty areas + TRect boundingRect( redrawRegion.BoundingRect() ); + + control->DrawNow( boundingRect ); + } + else + { + for( TInt i = 0; i < count; i++ ) + { + // Draw every dirty area separately + TRect redrawRect( redrawRegion[i] ); + + control->DrawNow( redrawRect ); + } + } + } + } + redrawRegion.Clear(); + } + + RefreshMenuL(); + + if ( iLayoutControl & XnLayoutControl::EFirstPassDraw ) + { + iViewManager.SetFirstPassDrawCompleteL(); + iLayoutControl &= ~XnLayoutControl::EFirstPassDraw; + } + + iLayoutControl &= ~XnLayoutControl::ERenderUI; + + iAppUiAdapter.EffectManager()->UiRendered(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::RootNode() +// ----------------------------------------------------------------------------- +// +CXnNode* CXnUiEngineImpl::RootNode() + { + return iViewManager.RootNode(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::ODT() +// ----------------------------------------------------------------------------- +// +CXnODT* CXnUiEngineImpl::ODT() + { + return iViewManager.ODT(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::FindNodeByIdL() +// ----------------------------------------------------------------------------- +// +CXnNode* CXnUiEngineImpl::FindNodeByIdL( const TDesC& aAreaId, + const TDesC& aNamespace ) + { + HBufC8* id = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aAreaId ); + CleanupStack::PushL( id ); + + HBufC8* ns = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aNamespace ); + CleanupStack::PushL( ns ); + + CXnNode* returnValue( FindNodeByIdL( *id, *ns ) ); + + CleanupStack::PopAndDestroy( ns ); + CleanupStack::PopAndDestroy( id ); + + return returnValue; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::FindNodeByIdL() +// ----------------------------------------------------------------------------- +// +CXnNode* CXnUiEngineImpl::FindNodeByIdL( const TDesC8& aAreaId, + const TDesC8& aNamespace ) + { + // Find the namespace where to start node id look-up + CXnPluginData* pluginData( + iViewManager.ActiveViewData().Plugin( aNamespace ) ); + + if ( !pluginData ) + { + return NULL; + } + + CXnNode* root( pluginData->Node()->LayoutNode() ); + + return ::FindNodeByIdL( root, aAreaId, aNamespace ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::FindNodeByClassL() +// ----------------------------------------------------------------------------- +// +CXnPointerArray* CXnUiEngineImpl::FindNodeByClassL( + const TDesC& aClassId, const TDesC& aNamespace ) + { + HBufC8* classId = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aClassId ); + CleanupStack::PushL( classId ); + + HBufC8* ns = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aNamespace ); + CleanupStack::PushL( ns ); + + CXnPointerArray* returnValue( FindNodeByClassL( *classId, *ns ) ); + + CleanupStack::PopAndDestroy( ns ); + CleanupStack::PopAndDestroy( classId ); + + return returnValue; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::FindNodeByClassL() +// ----------------------------------------------------------------------------- +// +CXnPointerArray* CXnUiEngineImpl::FindNodeByClassL( + const TDesC8& aClassId, const TDesC8& aNamespace ) + { + // Find the namespace where to start node class look-up + CXnPluginData* pluginData( + iViewManager.ActiveViewData().Plugin( aNamespace ) ); + + CXnPointerArray* array = CXnPointerArray::NewL(); + CleanupStack::PushL( array ); + + if ( pluginData ) + { + CXnNode* root( pluginData->Node()->LayoutNode() ); + ::FindNodeByClassL( root, aClassId, *array, aNamespace ); + } + + CleanupStack::Pop( array ); + + return array; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::Resources() +// ----------------------------------------------------------------------------- +// +CArrayPtrSeg< CXnResource >& CXnUiEngineImpl::Resources() + { + return iViewManager.Resources(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::SetFocusedNodeL() +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::SetFocusedNodeL( CXnNode* aFocusedNode, TInt aSource ) + { + iKeyEventDispatcher->SetNodeL( aFocusedNode, aSource ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngine::FocusedNode +// Forwards the call to the ui engine implementation +// ----------------------------------------------------------------------------- +// +CXnNode* CXnUiEngineImpl::FocusedNode() + { + return iKeyEventDispatcher->FocusedNode(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::IsEditMode +// Returns ETrue if the current mode is edit, otherwise EFalse. +// ----------------------------------------------------------------------------- +// +TBool CXnUiEngineImpl::IsEditMode() + { + return ( iEditMode->EditState() != CXnEditMode::ENone ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::NotifyViewActivatedL() +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::NotifyViewActivatedL( const CXnViewData& /*aViewData*/ ) + { + iCurrentView = iViewManager.ViewNode(); + + iControlAdapterList = &iViewManager.Controls(); + iCurrentViewControlAdapter = iCurrentView->Control(); + + iLayoutControl |= XnLayoutControl::EFirstPassDraw; + + iDirtyList.Reset(); + + iRedrawRegions.ResetAndDestroy(); + + // Set status pane layout + CXnProperty* prop( iCurrentView->GetPropertyL( + XnPropertyNames::view::KStatusPaneLayout ) ); + + // Is there status pane declaration available + TInt spane( DetermineStatusPaneLayout( prop ) ); + + if ( spane != KErrNotFound ) + { + CEikStatusPane* sp( iAppUiAdapter.StatusPane() ); + + if ( sp && sp->CurrentLayoutResId() != spane ) + { + sp->SwitchLayoutL( spane ); + sp->ApplyCurrentSettingsL(); + } + } + + // Remove previous menubar and stylus popup node + iMenuNode = NULL; + iStylusPopupNode = NULL; + + iKeyEventDispatcher->ResetMenuNodeL(); + + RPointerArray< CXnNode >& children( iCurrentView->Children() ); + + for ( TInt count = children.Count() - 1; count >= 0 ; --count ) + { + CXnNode* node( children[count] ); + + // Check that the given type of a control is parent + // (or ancestor) of this control + const TDesC8& type( node->Type()->Type() ); + + if ( type == KXnMenuBar ) + { + iMenuNode = node; + XnMenuInterface::MXnMenuInterface* menuIf( NULL ); + XnComponentInterface::MakeInterfaceL( menuIf, node->AppIfL() ); + if ( menuIf ) + { + menuIf->SetObserver( *this ); + } + } + else if ( type == _L8("styluspopup") ) + { + iStylusPopupNode = node; + + static_cast< CXnPopupControlAdapter* > + ( node->Control() )->SetObserver( *this ); + } + } + + // Set menu node even if its NULL, to allow keyevent dispatcher + // to handle no softkeys + iKeyEventDispatcher->SetMenuNodeL( iMenuNode ); + + ReportScreenDeviceChangeL(); + + SetClientRectL( iAppUiAdapter.ClientRect(), EFalse ); + + RootNode()->SetDirtyL(); + iUiEngine->RenderUIL(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::NotifyWidgetAdditionL() +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::NotifyWidgetAdditionL( + const CXnPluginData& /*aPluginData*/ ) + { + iLayoutControl |= XnLayoutControl::EFirstPassDraw; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::DynInitMenuItemL() +// ----------------------------------------------------------------------------- +// +TBool CXnUiEngineImpl::DynInitMenuItemL( CXnNodeAppIf& aMenuItem, + CXnNodeAppIf* aPlugin ) + { + // dynamic menuitem types reserved for HS internal use, + // internal menuitems' origin must be in active view namespace + _LIT( KAddWidget, "hs_add_widget" ); + _LIT( KRemoveWidget, "hs_remove_widget" ); + _LIT( KAddView, "hs_add_view" ); + _LIT( KRemoveView, "hs_remove_view" ); + _LIT( KOnline, "hs_online" ); + _LIT( KOffline, "hs_offline" ); + + CXnProperty* prop( + aMenuItem.GetPropertyL( XnPropertyNames::menu::KItemType ) ); + + TBool retval( EFalse ); + + if( !prop ) + { + // No type defined, declaration error + return retval; + } + + CXnViewData& viewData( iViewManager.ActiveViewData() ); + + TInt viewAmount( iViewManager.ViewAmount() ); + + // Check if the menuitem is in view namespace + TBool internal( aMenuItem.Namespace() == ActiveView()->Namespace() ); + + HBufC* itemType( prop->StringValueL() ); + CleanupStack::PushL( itemType ); + + if ( internal ) + { + if ( *itemType == KAddWidget ) + { + if ( aPlugin ) + { + CXnPluginData& data( viewData.Plugin( &aPlugin->Node() ) ); + + if ( !data.Occupied() ) + { + retval = ETrue; + } + } + } + else if ( *itemType == KRemoveWidget ) + { + CXnNode* node( ( aPlugin ) ? &aPlugin->Node() : FocusedNode() ); + + if ( node ) + { + CXnPluginData& data( viewData.Plugin( node ) ); + + if ( data.Removable() && data.Occupied() ) + { + retval = ETrue; + } + } + } + else if ( *itemType == KAddView ) + { + // checks Max pages value - from RootData + if ( viewAmount < iViewManager.MaxPages() ) + { + retval = ETrue; + } + } + else if ( *itemType == KRemoveView ) + { + if ( viewData.Removable() && viewAmount > 1 ) + { + retval = ETrue; + } + } + else if ( *itemType == KOnline || *itemType == KOffline ) + { + retval = iAppUiAdapter.DynInitMenuItemL( *itemType ); + } + } + else + { + const TDesC8& ns( aMenuItem.Namespace() ); + + CXnPluginData* data( viewData.Plugin( ns ) ); + + if ( data ) + { + RPointerArray< CXnNode > nodes; + CleanupClosePushL( nodes ); + + data->ContentSourceNodesL( nodes ); + + RPointerArray< CXnNodeAppIf > list; + CleanupClosePushL( list ); + + for ( TInt i = 0; i < nodes.Count(); i++ ) + { + list.AppendL( &nodes[i]->AppIfL() ); + } + + retval = iAppUiAdapter.DynInitMenuItemL( *itemType, &list ); + + CleanupStack::PopAndDestroy( 2, &nodes ); // list + } + } + + CleanupStack::PopAndDestroy( itemType ); + + return retval; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::VerticalPixelValueL() +// ----------------------------------------------------------------------------- +// +TInt CXnUiEngineImpl::VerticalPixelValueL( + CXnProperty* aValue, TInt aReferenceValue ) + { + return ::VerticalPixelValueL( aValue, aReferenceValue, + *iCurrentGraphicsDevice, iVerticalUnitInPixels ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::HorizontalPixelValueL() +// ----------------------------------------------------------------------------- +// +TInt CXnUiEngineImpl::HorizontalPixelValueL( + CXnProperty* aValue, TInt aReferenceValue ) + { + return ::HorizontalPixelValueL( aValue, aReferenceValue, + *iCurrentGraphicsDevice, iHorizontalUnitInPixels ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::VerticalTwipValueL() +// ----------------------------------------------------------------------------- +// +TInt CXnUiEngineImpl::VerticalTwipValueL( CXnProperty* aValue, + TInt aReferenceValue ) + { + return iCurrentGraphicsDevice->VerticalPixelsToTwips( + VerticalPixelValueL( aValue, aReferenceValue ) ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::HorizontalTwipValueL() +// ----------------------------------------------------------------------------- +// +TInt CXnUiEngineImpl::HorizontalTwipValueL( CXnProperty* aValue, + TInt aReferenceValue ) + { + return iCurrentGraphicsDevice->HorizontalPixelsToTwips( + HorizontalPixelValueL( aValue, aReferenceValue ) ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::ViewManager() +// ----------------------------------------------------------------------------- +// +CXnViewManager* CXnUiEngineImpl::ViewManager() + { + return &iViewManager; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::ActiveView() +// ----------------------------------------------------------------------------- +// +CXnNode* CXnUiEngineImpl::ActiveView() + { + return iViewManager.ViewNode(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::RefreshMenuL +// Refresh current menu +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::RefreshMenuL() + { + if ( iLayoutControl & XnLayoutControl::ERefreshMenu ) + { + iKeyEventDispatcher->RefreshMenuL(); + iLayoutControl &= ~XnLayoutControl::ERefreshMenu; + } + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::AddDirtyNodeL +// Add a dirty node. This method must be called via CXnNode SetDirtyL +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::AddDirtyNodeL( CXnNode* aNode, TInt aLevel ) + { + CXnViewData& data( iViewManager.ActiveViewData() ); + + if ( !aNode || ( aNode != RootNode() && !data.Plugin( aNode->Namespace() ) ) ) + { + // No node, or node doesn't belong to active view namespace + return; + } + + if ( aNode->Type()->Type() == KMenuBar ) + { + iLayoutControl |= XnLayoutControl::ERefreshMenu; + return; + } + + if ( iLayoutControl & XnLayoutControl::EViewDirty ) + { + // nothing to do + return; + } + + if ( aLevel == XnDirtyLevel::ERender ) + { + if( aNode == RootNode() ) + { + TXnDirtyRegion* dirtyRegion = FindDirtyRegionL( *iCurrentView ); + if( dirtyRegion ) + { + dirtyRegion->iRegion.Clear(); + } + aNode = iCurrentView; + } + + // Add to redraw list + AddToRedrawListL( aNode ); + } + else + { + // Add to dirty list for relayout and redraw + AddToDirtyListL( aNode ); + } + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::ScreenDeviceSize +// Get the size of the current screen device +// ----------------------------------------------------------------------------- +// +TSize CXnUiEngineImpl::ScreenDeviceSize() const + { + if ( iCurrentGraphicsDevice ) + { + return iCurrentGraphicsDevice->SizeInPixels(); + } + + return TSize( 0, 0 ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::IsDialogDisplaying +// Whether the dialog is displaying or not. +// ----------------------------------------------------------------------------- +// +TBool CXnUiEngineImpl::IsDialogDisplaying() + { + return iAppUiAdapter.IsDisplayingControlBetweenPriorities( + ECoeStackPriorityDialog - 1, KXnStackPriorityKeyEventDispatcher - 1 ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::HandleResourceChangeL +// Handles a change to the control's resources of type aType +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::HandleResourceChangeL( TInt aType ) + { + if ( iMenuNode ) + { + CXnControlAdapter* adapter( iMenuNode->Control() ); + + if ( adapter ) + { + adapter->HandleResourceChange( aType ); + } + } + + if ( aType == KEikDynamicLayoutVariantSwitch ) + { + // Must return here if there is no current view or + // controladapterlist. This may occur when the phone + // is booted for the first time and the location/date + // query is visible. + if ( !ActiveView() ) + { + return; + } + + // Update client rect + SetClientRectL( iAppUiAdapter.ClientRect(), EFalse ); + + iEditMode->HandleScreenDeviceChangedL(); + + // Force relayout + DisableRenderUiLC(); + + RootNode()->SetDirtyL(); + + ReportScreenDeviceChangeL(); + + for ( TInt i = 0; i < iControlAdapterList->Count(); i++ ) + { + CXnControlAdapter* adapter( ( *iControlAdapterList )[i] ); + + adapter->HandleScreenDeviceChangedL(); + } + + ForceRenderUIL(); + + CleanupStack::PopAndDestroy(); + } + else if ( aType == KAknsMessageSkinChange ) + { + // Force relayout + DisableRenderUiLC(); + + RootNode()->SetDirtyL(); + + for ( TInt i = 0; i < iControlAdapterList->Count(); i++ ) + { + CXnControlAdapter* adapter( ( *iControlAdapterList )[i] ); + adapter->SkinChanged(); + } + + ForceRenderUIL(); + + CleanupStack::PopAndDestroy(); + } + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::IsMenuDisplaying +// Checks whether the menu is displaying or not. +// ----------------------------------------------------------------------------- +// +TBool CXnUiEngineImpl::IsMenuDisplaying() + { + return iKeyEventDispatcher->IsMenuFocused(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::MenubarNode +// Returns menubar node +// ----------------------------------------------------------------------------- +// +CXnNode* CXnUiEngineImpl::MenuBarNode() const + { + return iMenuNode; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::StylusPopupNode +// Returns stylus popup node +// ----------------------------------------------------------------------------- +// +CXnNode* CXnUiEngineImpl::StylusPopupNode() const + { + return iStylusPopupNode; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::AddPassiveFocusedNode +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::AddPassiveFocusedNodeL( CXnNode* aNode ) + { + iKeyEventDispatcher->AddPassiveFocusedNodeL( aNode ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::RemovePassiveFocusedNode +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::RemovePassiveFocusedNodeL( CXnNode* aNode ) + { + iKeyEventDispatcher->RemovePassiveFocusedNodeL( aNode ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::AddPassiveFocusedNode +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::ClearPassiveFocusedNodesL() + { + iKeyEventDispatcher->ClearPassiveFocusedNodesL(); + } + +// ----------------------------------------------------------------------------- +// SetNodeDroppedL() +// Sets node's dropped state +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::SetNodeDroppedL( CXnNode& aNode, TInt aDropped ) const + { + if ( aDropped != XnNodeLayout::ENone ) + { + CXnNode* parent( aNode.Parent() ); + TInt parentAdaptive( parent->IsAdaptive( ETrue ) ); + + if ( iLayoutPhase == XnLayoutPhase::EMeasure ) + { + if ( !parentAdaptive ) + { + // Only adaptive childs can be dropped during measure phase + return; + } + } + +#ifdef _XN3_DEBUG_ + CXnProperty* id( aNode.IdL() ); + + if ( id ) + { + TBuf8< 256 > debug; + debug.Append( _L8( "Node id: " ) ); + debug.Append( id->StringValue() ); + debug.Append( _L8( " will be set to dropped" ) ); + RDebug::RawPrint( debug ); + } +#endif + + // Node will be dropped + aNode.SetDropped( aDropped ); + + // Get ride of its rects + ClearRects( aNode ); + + if ( parentAdaptive ) + { + // Is there adaptive content left after dropping? + CheckAdaptiveContentL( *parent, parent->Rect().Size() ); + } + } + else + { + // Node is no more dropped + aNode.SetDropped( aDropped ); + } + } + +// ----------------------------------------------------------------------------- +// CheckAdaptiveContentL() +// Checks if node is adaptive, but doesn't have any content +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::CheckAdaptiveContentL( + CXnNode& aNode, TSize aAvailableSize ) const + { + TInt adaptive( aNode.IsAdaptive( ETrue ) ); + TBool isEmpty( EFalse ); + + if ( adaptive ) + { + if ( aAvailableSize == TSize::EUninitialized ) + { + // Use max available size + aAvailableSize = ScreenDeviceSize(); + } + + const TDesC8& name( aNode.Type()->Type() ); + + if ( name == KBoxNodeName || name == KButtonNodeName ) + { + RPointerArray< CXnNode > displayedChildren; + CleanupClosePushL( displayedChildren ); + + TInt displayedCount( DisplayedChildrenCountL( + aNode, &displayedChildren ) ); + + if ( displayedCount == 0 ) + { + isEmpty = ETrue; + } + else + { + for ( TInt i = 0; i < displayedChildren.Count(); i++ ) + { + CheckAdaptiveContentL( *displayedChildren[i], + aAvailableSize ); + } + + if ( DisplayedChildrenCountL( aNode ) == 0 ) + { + isEmpty = ETrue; + } + } + + CleanupStack::PopAndDestroy( &displayedChildren ); + } + + if ( isEmpty ) + { + // No content available, drop adaptive node + SetNodeDroppedL( aNode, XnNodeLayout::EDropped ); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::AddFocusCandidateL +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::AddFocusCandidateL( CXnNode* aNode ) + { + if ( !aNode ) + { + return; + } + TInt index( iFocusCandidateList.Find( aNode ) ); + if ( index == KErrNotFound ) + { + iFocusCandidateList.AppendL( aNode ); + } + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::IsLayoutDisabled +// ----------------------------------------------------------------------------- +// +TBool CXnUiEngineImpl::IsLayoutDisabled() + { + if ( !iCurrentView ) + { + return ETrue; + } + + TBool retval( EFalse ); + if ( iDisableCount > 0 && + !( iLayoutControl & XnLayoutControl::EIgnoreState ) ) + { + retval = ETrue; + } + return retval; + } + +// ----------------------------------------------------------------------------- +// AddToRedrawListL +// Mark Control's appearance to be redrawn +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::AddToRedrawListL( CXnNode* aNode, TRect aRect ) + { + CXnControlAdapter* aAdapter( aNode->Control() ); + + if( !aAdapter ) + { + return; + } + + if( aRect != TRect::EUninitialized ) + { + // This is the new rect which will be set by layout algo + AddRedrawRectL( aRect, *aNode ); + } + + TRect rect( aAdapter->Rect() ); + + if( rect == TRect::EUninitialized ) + { + // Don't add uninitialized rect + return; + } + + /* + if( aNode->IsStateSet( XnPropertyNames::style::common::KFocus ) ) + { + const TDesC8& name( aNode->DomNode()->Name() ); + + if( name == KPlugin ) + { + rect.Grow( KFocusGrowValue, KFocusGrowValue ); + } + else + { + TRect marginRect( aNode->MarginRect() ); + + CXnNode* parent( aNode->Parent() ); + + for( ; parent; parent = parent->Parent() ) + { + if( parent->DomNode()->Name() == KPlugin ) + { + if( parent->Rect() == marginRect ) + { + rect.Grow( KFocusGrowValue, KFocusGrowValue ); + } + + break; + } + } + } + } + */ + GrowIfNeeded(aNode, rect); + AddRedrawRectL( rect, *aNode ); + } + +// ----------------------------------------------------------------------------- +// AddToDirtyListL +// Mark node to dirty list for relayout +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::AddToDirtyListL( CXnNode* aNode ) + { + CXnNode* nodeToRedrawList( aNode ); + CXnNode* nodeToDirtyList( aNode ); + + if ( aNode == RootNode() ) + { + // Force relayout and redraw from current view + iDirtyList.Reset(); + iDirtyList.AppendL( iCurrentView ); + TXnDirtyRegion* dirtyRegion = FindDirtyRegionL( *iCurrentView ); + if( dirtyRegion ) + { + dirtyRegion->iRegion.Clear(); + } + iLayoutControl |= XnLayoutControl::EViewDirty; + nodeToDirtyList = nodeToRedrawList = iCurrentView; + nodeToDirtyList->ClearRenderedAndLaidOut(); + + // Add to draw list for redraw + AddToRedrawListL( nodeToRedrawList ); + } + else + { + if ( !IsAbsoluteL( *aNode ) && !IsNodeTooltip( *aNode ) ) + { + // Check adaptives in normal flow + CXnNode* oldest( NULL ); + CXnNode* adaptive( aNode ); + + if ( !aNode->IsAdaptive( ETrue ) ) + { + adaptive = aNode->Parent(); + } + + for ( ; adaptive && adaptive->IsAdaptive( ETrue ); + adaptive = adaptive->Parent() ) + { + oldest = adaptive; + } + + // Now we have found the oldest adaptive node if present + if ( oldest ) + { + nodeToRedrawList = nodeToDirtyList = adaptive; + } + } + + RPointerArray< CXnNode > dirtyList; + CleanupClosePushL( dirtyList ); + TInt count( iDirtyList.Count() ); + TBool found; + + // first, check that aNode's children are not in the dirty array + for ( TInt i = 0; i < count; ++i ) + { + found = EFalse; + CXnNode* candidate( iDirtyList[i] ); + + for ( CXnNode* node = candidate->Parent(); node && !found; + node = node->Parent() ) + { + if ( nodeToDirtyList == node ) + { + found = ETrue; + } + } + + if ( !found ) + { + // Put candidate back to list as child is not found + dirtyList.AppendL( candidate ); + } + } + + found = EFalse; + + // second, check that aNode's parent is not in dirty array + for ( TInt i = 0; i < count && !found; ++i ) + { + CXnNode* candidate( iDirtyList[i] ); + + for ( CXnNode* node = nodeToDirtyList; node && !found; + node = node->Parent() ) + { + if ( node == candidate ) + { + found = ETrue; + } + } + } + + if ( !found && iDirtyList.Find( nodeToDirtyList ) == KErrNotFound ) + { + // Add node to dirty list as parent is neither found + dirtyList.AppendL( nodeToDirtyList ); + nodeToDirtyList->ClearRenderedAndLaidOut(); + + // Add to draw list for redraw + AddToRedrawListL( nodeToRedrawList ); + } + + // finally update the dirty list + iDirtyList.Reset(); + iDirtyList = dirtyList; + + CleanupStack::Pop( &dirtyList ); + } + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::SetClientRectL +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::SetClientRectL( TRect aRect, TBool aDrawNow ) + { + if ( iClientRect != aRect ) + { + iClientRect = aRect; + + UpdateInternalUnits( iHorizontalUnitInPixels, iVerticalUnitInPixels, + iClientRect ); + + iAppUiAdapter.ViewAdapter().BgControl().SetRect( aRect ); + + if ( aDrawNow ) + { + RootNode()->SetDirtyL(); + iUiEngine->RenderUIL(); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::ClientRect +// ----------------------------------------------------------------------------- +// +TRect CXnUiEngineImpl::ClientRect() const + { + return iClientRect; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::Editor +// ----------------------------------------------------------------------------- +// +CXnEditor* CXnUiEngineImpl::Editor()const + { + return &iViewManager.Editor(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::EditMode +// ----------------------------------------------------------------------------- +// +CXnEditMode* CXnUiEngineImpl::EditMode() + { + return iEditMode; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::StartLayoutFromL +// ----------------------------------------------------------------------------- +// +CXnNode* CXnUiEngineImpl::StartLayoutFromL() + { + if ( iLayoutControl & XnLayoutControl::EViewDirty ) + { + return iCurrentView; + } + + RPointerArray< CXnNode >parentArray; + CleanupClosePushL( parentArray ); + TInt dirtyCount = iDirtyList.Count(); + CXnNode* startNode( NULL ); + + for ( TInt dirtyIndex = 0; dirtyIndex < dirtyCount; dirtyIndex++ ) + { + startNode = iDirtyList[dirtyIndex]; + + for ( ;startNode && startNode != iCurrentView; ) + { + parentArray.Append( startNode->Parent() ); + startNode = startNode->Parent(); + } + } + + TInt parentCount = parentArray.Count(); + + for ( TInt parentIndex = 0; parentIndex < parentCount; parentIndex++ ) + { + TInt parentsFound = 0; + + for ( TInt checkIndex = 0; checkIndex < parentCount; checkIndex++ ) + { + if ( parentArray[parentIndex] == parentArray[checkIndex] ) + { + parentsFound++; + + if ( parentsFound == dirtyCount ) + { + startNode = parentArray[parentIndex]; + CleanupStack::PopAndDestroy( &parentArray ); + return startNode; + } + } + } + } + + CleanupStack::PopAndDestroy( &parentArray ); + + return iCurrentView; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::Plugins +// ----------------------------------------------------------------------------- +// +RPointerArray< CXnNode >* CXnUiEngineImpl::Plugins() + { + return &iViewManager.PluginNodes(); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::ForceRenderUIL +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::ForceRenderUIL( TBool aLayoutOnly ) + { + iLayoutControl |= XnLayoutControl::EIgnoreState; + if ( aLayoutOnly ) + { + LayoutUIL(); + } + else + { + LayoutUIL(); + RenderUIL(); + } + iLayoutControl &= ~XnLayoutControl::EIgnoreState; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::HitTest +// ----------------------------------------------------------------------------- +// +CXnHitTest& CXnUiEngineImpl::HitTest() const + { + return *iHitTest; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::PositionStylusPopupL +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::PositionStylusPopupL( CXnNode& aNode, + CXnNode& aReference, const TPoint& aPosition ) + { + CXnDomStringPool& sp( aNode.DomNode()->StringPool() ); + TXnDirtyRegion* dirtyRegion = FindDirtyRegionL( *iCurrentView ); + RRegion region; + region.Copy( dirtyRegion->iRegion ); + CleanupClosePushL( region ); + + // Set initial position to (0, 0) to calculate popup metrics + CXnProperty* top = CXnProperty::NewL( + XnPropertyNames::style::common::KTop, 0, + CXnDomPropertyValue::EPx, sp ); + CleanupStack::PushL( top ); + aNode.SetPropertyL( top ); + CleanupStack::Pop( top ); + top = NULL; + CXnProperty* left = CXnProperty::NewL( + XnPropertyNames::style::common::KLeft, 0, + CXnDomPropertyValue::EPx, sp ); + CleanupStack::PushL( left ); + aNode.SetPropertyL( left ); + CleanupStack::Pop( left ); + left = NULL; + + // Make it visible + CXnProperty* display = CXnProperty::NewL( + XnPropertyNames::style::common::KDisplay, + XnPropertyNames::style::common::display::KBlock, + CXnDomPropertyValue::EString, sp ); + CleanupStack::PushL( display ); + aNode.SetPropertyL( display ); + CleanupStack::Pop( display ); + + if ( !aNode.IsLaidOut() || !aReference.IsLaidOut() ) + { + ForceRenderUIL( ETrue ); + } + + if ( !aNode.IsLaidOut() || !aReference.IsLaidOut() ) + { + // Something went wrong + CleanupStack::PopAndDestroy( ®ion ); + + return; + } + + TRect rectToFit( aReference.MarginRect() ); + TRect marginRect( aNode.MarginRect() ); + + if ( marginRect.Height() > rectToFit.Height() || + marginRect.Width() > rectToFit.Width() ) + { + // Won't fit even how much is moved + CleanupStack::PopAndDestroy( ®ion ); + + return; + } + + TPoint tl; + TPoint br; + + // Remove the initial 0,0 from redraw region and rects + dirtyRegion->iRegion.Clear(); + ClearRects( aNode, ETrue ); + CXnProperty* positionHint( aNode.GetPropertyL( + XnPropertyNames::styluspopup::KPositionHint ) ); + + // Default + const TDesC8* value( &XnPropertyNames::styluspopup::positionhint::KAbove ); + + if ( positionHint ) + { + value = &positionHint->StringValue(); + } + + if ( *value == XnPropertyNames::styluspopup::positionhint::KAbove ) + { + if ( AknLayoutUtils::LayoutMirrored() ) + { + tl = aPosition; + tl.iY -= marginRect.Height(); + tl.iX -= marginRect.Width(); + + // Will the popup float out? + if ( !rectToFit.Contains( tl ) ) + { + // top left floated out + TInt y( rectToFit.iTl.iY - tl.iY + 1 ); + + if ( y >= 0 ) + { + // y-coordinate floated out, move it position + // so that it will be inside reference rect + tl.iY = tl.iY + y; + } + + TInt x( rectToFit.iTl.iX - tl.iX + 1 ); + + if ( x >= 0 ) + { + // x-coordinate floated out, move it position + // so that it will be inside reference rect + tl.iX = tl.iX + x; + } + } + } + else + { + tl = aPosition; + tl.iY -= marginRect.Height(); + + // Will the popup float out? + if ( !rectToFit.Contains( tl ) ) + { + // top left floated out + TInt y( rectToFit.iTl.iY - tl.iY + 1 ); + + if ( y >= 0 ) + { + // y-coordinate floated out, move it position + // so that it will be inside reference rect + tl.iY = tl.iY + y; + } + } + + br = TPoint( tl.iX + marginRect.Width(), + tl.iY + marginRect.Height() ); + + if ( !rectToFit.Contains( br ) ) + { + // bottom right floated out + TInt x( br.iX - rectToFit.iBr.iX + 1 ); + + if ( x >= 0 ) + { + // x-coordinate floated out, move it position + // so that it will be inside reference rect + tl.iX = tl.iX - x; + } + } + } + } + else // value == XnPropertyNames::styluspopup::positionhint::KBelow + { + if ( AknLayoutUtils::LayoutMirrored() ) + { + tl = aPosition; + tl.iX = tl.iX - marginRect.Width(); + + if ( !rectToFit.Contains( tl ) ) + { + // Top left floated out + TInt x( rectToFit.iTl.iX - tl.iX + 1 ); + + if ( x >= 0 ) + { + // x-coordinate floated out, move it position + // so that it will be inside reference rect + tl.iX = tl.iX + x; + } + } + + br = TPoint( tl.iX + marginRect.Width(), + tl.iY + marginRect.Height() ); + + if ( !rectToFit.Contains( br ) ) + { + // bottom right floated out + TInt y( br.iY - rectToFit.iBr.iY + 1 ); + + if ( y >= 0 ) + { + // y-coordinate floated out, move it position + // so that it will be inside reference rect + tl.iY = tl.iY - y; + } + } + } + else + { + tl = aPosition; + br = TPoint( tl.iX + marginRect.Width(), + tl.iY + marginRect.Height() ); + + // Will the popup float out? + if ( !rectToFit.Contains( br ) ) + { + // Bottom right floated out + TInt x( br.iX - rectToFit.iBr.iX + 1 ); + + if ( x >= 0 ) + { + // x-coordinate floated out, move it position + // so that it will be inside reference rect + tl.iX = tl.iX - x; + } + + TInt y( br.iY - rectToFit.iBr.iY + 1 ); + + if ( y >= 0 ) + { + // y-coordinate floated out, move it position + // so that it will be inside reference rect + tl.iY = tl.iY - y; + } + } + } + } + + // Set positions + top = CXnProperty::NewL( + XnPropertyNames::style::common::KTop, tl.iY, + CXnDomPropertyValue::EPx, sp ); + CleanupStack::PushL( top ); + aNode.SetPropertyL( top ); + CleanupStack::Pop( top ); + left = CXnProperty::NewL( + XnPropertyNames::style::common::KLeft, tl.iX, + CXnDomPropertyValue::EPx, sp ); + CleanupStack::PushL( left ); + aNode.SetPropertyL( left ); + CleanupStack::Pop( left ); + + // Copy stored region back + dirtyRegion->iRegion.Copy( region ); + CleanupStack::PopAndDestroy( ®ion ); + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::GetThemeResource +// ----------------------------------------------------------------------------- +// +TInt CXnUiEngineImpl::GetThemeResource( const TDesC& aPath, RFile& aFile ) + { + TInt err = KErrNone; + + // parse file name and extension + TParsePtrC fileParser( aPath ); + TPtrC filepath = fileParser.DriveAndPath(); + + RFs session ( CCoeEnv::Static()->FsSession() ); + + // open resource file + session.SetSessionPath( filepath ); + session.ShareProtected(); + err = aFile.Open( session, aPath, EFileShareReadersOnly ); + if ( err != KErrNone ) + { + aFile.Close(); + } + + return err; + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::AnalyseAddedWidgetL +// ----------------------------------------------------------------------------- +// +TBool CXnUiEngineImpl::AnalyseAddedWidgetL( CXnNode& aNode ) + { + TBool retval( ETrue ); + + // Force layout to analyse added widget's dimensions + ForceRenderUIL( ETrue ); + + if ( aNode.IsAdaptive( ETrue ) ) + { + // If widget place holder (plugin in view.xml) is adaptive, then + // we need to verify that added widget will fit to available space + retval = EFalse; + + CXnNode* parent( aNode.Parent() ); + RPointerArray< CXnNode >& children( parent->Children() ); + CXnProperty* prop( parent->BlockProgressionL() ); + + const TDesC8* bp( + &XnPropertyNames::style::common::block_progression::KTB() ); + + if ( prop ) + { + bp = &prop->StringValue(); + } + + prop = parent->DirectionL(); + + const TDesC8* dir( + &XnPropertyNames::style::common::direction::KLTR() ); + + if ( prop ) + { + // use default + dir = &prop->StringValue(); + } + + TSize space( CalculateSpaceUsedByChildrenL( children, *parent, + *bp, *dir, *iCurrentGraphicsDevice, iHorizontalUnitInPixels, + iVerticalUnitInPixels ) ); + + TSize parentSize( parent->Rect().Size() ); + + if ( *bp == XnPropertyNames::style::common::block_progression::KTB || + *bp == XnPropertyNames::style::common::block_progression::KBT ) + { + if ( parentSize.iHeight >= space.iHeight ) + { + retval = ETrue; + } + } + else // LR / RL + { + if ( parentSize.iWidth >= space.iWidth ) + { + retval = ETrue; + } + } + } + + return retval; + } + + + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::NotifyWidgetRemovalL( ) +// Notify about widget removal +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::NotifyWidgetRemovalL( + const CXnPluginData& /*aPluginData*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::NotifyConfigureWidgetL( ) +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::NotifyConfigureWidgetL( + const CHsContentInfo& /*aContentInfo*/, CXnPluginData& /*aPluginData*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CXnUiEngineImpl::NotifyViewDeactivatedL +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::NotifyViewDeactivatedL( + const CXnViewData& /*aViewData*/ ) + { + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::DisableRenderUiLC() + { + CleanupStack::PushL( TCleanupItem( EnableRenderUi, this ) ); + + iDisableCount++; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +EXPORT_C /* static */ void CXnUiEngineImpl::EnableRenderUi( TAny* aAny ) + { + CXnUiEngineImpl* self = static_cast< CXnUiEngineImpl* >( aAny ); + + if ( self->iDisableCount > 0 ) + { + self->iDisableCount--; + + if ( self->iDisableCount == 0 ) + { + TRAP_IGNORE( + // Is menu refresh pending? + if ( ( self->iLayoutControl & XnLayoutControl::ERefreshMenu ) && + !self->IsMenuDisplaying() ) + { + // RefreshMenuL will reset the state flag + self->RefreshMenuL(); + } + + // Is layout pending? + if ( self->iLayoutControl & XnLayoutControl::ELayoutUI ) + { + self->LayoutUIL(); + } + + // Is render pending? + if ( self->iLayoutControl & XnLayoutControl::ERenderUI ) + { + self->RenderUIL(); + } + ); + } + } + } + + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CXnUiEngineImpl::ReportScreenDeviceChangeL() + { + CXnNode* trigger( BuildScreenDeviceChangeTriggerNodeLC( *iUiEngine ) ); + + // Notify current orientation to iCurrentView + iCurrentView->ReportXuikonEventL( *trigger ); + + // Notify also plugins + RPointerArray plugins = *Plugins(); + for( TInt i=0; i pluginChildren = pluginNode->Children(); + for( TInt ii=0; iiDomNode(); + if( widgetNode && widgetNode->Name() == KWidgetNodeName ) + { + pluginChildren[ii]->ReportXuikonEventL( *trigger ); + } + } + } + + CleanupStack::PopAndDestroy(); // trigger + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +CCoeControl* CXnUiEngineImpl::WindowOwningControl( CXnNode& aNode ) + { + CXnNode* parent = &aNode; + while( parent ) + { + CXnControlAdapter* adapter = parent->Control(); + if( adapter ) + { + if( parent->ViewNodeImpl() && + adapter == iCurrentViewControlAdapter ) + { + return adapter; + } + else if( adapter->OwnsWindow() ) + { + if( !IsNodeTooltip( *parent ) ) + { + return adapter; + } + else + { + return NULL; + } + } + } + parent = parent->Parent(); + } + return NULL; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +TXnDirtyRegion* CXnUiEngineImpl::FindDirtyRegionL( CXnNode& aNode ) + { + CCoeControl* control = WindowOwningControl( aNode ); + if( !control ) + { + return NULL; + } + for( TInt i=0; iiControl == control ) + { + return iRedrawRegions[i]; + } + } + TXnDirtyRegion* region = new (ELeave) TXnDirtyRegion; + CleanupStack::PushL( region ); + region->iControl = control; + iRedrawRegions.AppendL( region ); + CleanupStack::Pop(); + return region; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +void CXnUiEngineImpl::AddRedrawRectL( TRect aRect, CXnNode& aNode ) + { + TXnDirtyRegion* dirtyReg = FindDirtyRegionL( aNode ); + if( dirtyReg ) + { + dirtyReg->iRegion.AddRect( aRect ); + dirtyReg->iRegion.Tidy(); + } + } + +// ----------------------------------------------------------------------------- +// SetEventDispatcher +// ----------------------------------------------------------------------------- +void CXnUiEngineImpl::SetEventDispatcher( CXnKeyEventDispatcher* aDispatcher ) + { + iKeyEventDispatcher = aDispatcher; + } + +// ----------------------------------------------------------------------------- +// NotifyStatusPaneSizeChanged +// ----------------------------------------------------------------------------- +void CXnUiEngineImpl::NotifyStatusPaneSizeChanged() + { + TRAP_IGNORE( iUiEngine->SetClientRectL( iAppUiAdapter.ClientRect() ) ); + } + +// ----------------------------------------------------------------------------- +// NotifyResourceChanged +// ----------------------------------------------------------------------------- +void CXnUiEngineImpl::NotifyResourceChanged( TInt aType ) + { + TRAP_IGNORE( HandleResourceChangeL( aType ) ); + } + +// End of file