/*
* 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 <utf.h>
#include <eikapp.h>
#include <AknUtils.h>
#include <layoutmetadata.cdl.h>
#include <AknPriv.hrh>
#include <debug.h>
// 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 "xnviewcontroladapter.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 <aknlayoutscalable_avkon.cdl.h>
#include "xuikon_builds_cfg.hrh"
#include "xndomdocument.h"
#include "xndomnode.h"
#include "xneditmode.h"
#include "xnnode.h"
#include "xnpanic.h"
#include "xneffectmanager.h"
#include "xneditor.h"
#include "xnbackgroundmanager.h"
#include "xntexteditor.h"
#include "xnrootdata.h"
#ifdef _XN_PERFORMANCE_TEST_
#include "xntimemon.h"
#endif
#ifdef _XN3_DEBUG_
#include "xndepthfirsttreeiterator.h" // for TraceTreeL
#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( KEditorNodeName, "texteditor" );
_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 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 ===============================
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CXnNode* FindPlugin( CXnNode& aNode )
{
CXnNode* pluginNode( NULL );
for( CXnNode* node = &aNode; node; node = node->Parent() )
{
if( node->DomNode()->Name() == KPlugin )
{
pluginNode = node;
break;
}
}
return pluginNode;
}
// -----------------------------------------------------------------------------
// 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::
orientation::reason::KLandscape;
}
else
{
reasonString = &XnPropertyNames::action::trigger::name::
orientation::reason::KPortrait;
}
reasonValue->SetStringValueL( CXnDomPropertyValue::EString, *reasonString );
CXnProperty* reason = CXnProperty::NewL( XnPropertyNames::action::trigger::
name::orientation::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 );
}
}
// -----------------------------------------------------------------------------
// 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 );
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;
iFocusCandidateList.Reset();
if ( iRedrawRegions.Count() )
{
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 );
// popup calculates its position based on _s60-position-hint property
if( node->Type()->Type() == KPopUpNodeName )
{
adapter->DoHandlePropertyChangeL();
}
else
{
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
__PRINTS("*** CXnUiEngineImpl::RenderUIL ***");
for( TInt i=0; i<iRedrawRegions.Count(); i++)
{
CCoeControl* control = iRedrawRegions[i]->iControl;
RRegion& redrawRegion = iRedrawRegions[i]->iRegion;
if( redrawRegion.CheckError() )
{
// Mark tree rendered
iCurrentView->SetRenderedL();
// Error occured during dirty set, redraw whole window
control->DrawNow();
__PRINTS("* CXnUiEngineImpl::RenderUIL - redraw region error -> full redraw ***");
}
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() );
__PRINT( __DBG_FORMAT( "* CXnUiEngineImpl::RenderUIL - redrawing bounding rect iTl.iX: %d, iTl.iY: %d, iBr.iX: %d, iBr.iY: %d" ),
boundingRect.iTl.iX, boundingRect.iTl.iY, boundingRect.iBr.iX, boundingRect.iBr.iY );
control->DrawNow( boundingRect );
}
else
{
for( TInt i = 0; i < count; i++ )
{
// Draw every dirty area separately
TRect redrawRect( redrawRegion[i] );
__PRINT( __DBG_FORMAT( "* CXnUiEngineImpl::RenderUIL - redrawing rect iTl.iX: %d, iTl.iY: %d, iBr.iX: %d, iBr.iY: %d" ),
redrawRect.iTl.iX, redrawRect.iTl.iY, redrawRect.iBr.iX, redrawRect.iBr.iY );
control->DrawNow( redrawRect );
}
}
}
else
{
__PRINTS("* CXnUiEngineImpl::RenderUIL - nothing to redraw ***");
}
}
redrawRegion.Clear();
}
RefreshMenuL();
iLayoutControl &= ~XnLayoutControl::ERenderUI;
iAppUiAdapter.EffectManager()->UiRendered();
__PRINTS("*** CXnUiEngineImpl::RenderUIL - done ***");
}
// -----------------------------------------------------------------------------
// 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
CXnViewData& active( iViewManager.ActiveViewData() );
CXnPluginData* pluginData( active.Plugin( aNamespace ) );
if ( aNamespace != KNullDesC8 && !pluginData )
{
RPointerArray< CXnPluginData >& views(
iViewManager.ActiveAppData().PluginData() );
for ( TInt i = 0; i < views.Count(); i++ )
{
CXnViewData* view = static_cast< CXnViewData* >( views[i] );
if ( view != &active )
{
pluginData = view->Plugin( aNamespace );
if ( pluginData )
{
break;
}
}
}
}
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
CXnViewData& active( iViewManager.ActiveViewData() );
CXnPluginData* pluginData( active.Plugin( aNamespace ) );
if ( aNamespace != KNullDesC8 && !pluginData )
{
RPointerArray< CXnPluginData >& views(
iViewManager.ActiveAppData().PluginData() );
for ( TInt i = 0; i < views.Count(); i++ )
{
CXnViewData* view = static_cast< CXnViewData* >( views[i] );
if ( view != &active )
{
pluginData = view->Plugin( aNamespace );
if ( pluginData )
{
break;
}
}
}
}
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::FindContentSourceNodesL()
// -----------------------------------------------------------------------------
//
CXnPointerArray* CXnUiEngineImpl::FindContentSourceNodesL(
const TDesC8& aNamespace )
{
CXnViewData& active( iViewManager.ActiveViewData() );
CXnPluginData* pluginData( active.Plugin( aNamespace ) );
if ( aNamespace != KNullDesC8 && !pluginData )
{
RPointerArray< CXnPluginData >& views(
iViewManager.ActiveAppData().PluginData() );
for ( TInt i = 0; i < views.Count(); i++ )
{
CXnViewData* view = static_cast< CXnViewData* >( views[i] );
if ( view != &active )
{
pluginData = view->Plugin( aNamespace );
if ( pluginData )
{
break;
}
}
}
}
CXnPointerArray* array = CXnPointerArray::NewL();
CleanupStack::PushL( array );
if ( pluginData )
{
RPointerArray< CXnNode > list;
CleanupClosePushL( list );
pluginData->ContentSourceNodesL( list );
const TInt count( list.Count() );
array->Container().ReserveL( count );
for ( TInt i = 0; i < count; i++ )
{
array->Container().Append( list[i] );
}
CleanupStack::PopAndDestroy( &list );
}
CleanupStack::Pop( array );
return array;
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::Resources()
// -----------------------------------------------------------------------------
//
CArrayPtrSeg< CXnResource >& CXnUiEngineImpl::Resources()
{
return iViewManager.Resources();
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::SetFocusedNodeL()
// -----------------------------------------------------------------------------
//
void CXnUiEngineImpl::SetFocusedNodeL( CXnNode* aFocusedNode, TInt aSource )
{
if ( iKeyEventDispatcher )
{
iKeyEventDispatcher->SetNodeL( aFocusedNode, aSource );
}
}
// -----------------------------------------------------------------------------
// CXnUiEngine::FocusedNode
// Forwards the call to the ui engine implementation
// -----------------------------------------------------------------------------
//
CXnNode* CXnUiEngineImpl::FocusedNode()
{
if ( iKeyEventDispatcher )
{
return iKeyEventDispatcher->FocusedNode();
}
return NULL;
}
// -----------------------------------------------------------------------------
// 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();
iDirtyList.Reset();
iRedrawRegions.ResetAndDestroy();
// Remove previous menubar and stylus popup node
iMenuNode = NULL;
iStylusPopupNode = NULL;
if ( iKeyEventDispatcher )
{
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
if ( iKeyEventDispatcher )
{
iKeyEventDispatcher->SetMenuNodeL( iMenuNode );
}
ReportScreenDeviceChangeL();
SetClientRectL( iAppUiAdapter.ClientRect(), EFalse );
RootNode()->SetDirtyL();
ForceRenderUIL();
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::NotifyWidgetAdditionL()
// -----------------------------------------------------------------------------
//
void CXnUiEngineImpl::NotifyWidgetAdditionL(
const CXnPluginData& /*aPluginData*/ )
{
}
// -----------------------------------------------------------------------------
// 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 && &aPlugin->Node() )
{
CXnPluginData* data( viewData.Plugin( &aPlugin->Node() ) );
if ( data && !data->Occupied() )
{
retval = ETrue;
}
}
}
else if ( *itemType == KRemoveWidget )
{
CXnNode* node( ( aPlugin ) ? &aPlugin->Node() : FocusedNode() );
if ( node )
{
CXnPluginData* data( viewData.Plugin( node ) );
if ( data && 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 )
{
if ( iKeyEventDispatcher )
{
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 )
{
HandleDynamicLayoutVariantSwitchL();
}
else if ( aType == KAknsMessageSkinChange )
{
HandleSkinChangeL();
}
else if( iCurrentViewControlAdapter )
{
iCurrentViewControlAdapter->HandleResourceChange( aType );
}
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::HandleSkinChangeL
// Handles a skin change to the controls
// -----------------------------------------------------------------------------
//
void CXnUiEngineImpl::HandleSkinChangeL()
{
// Force relayout
DisableRenderUiLC();
RootNode()->SetDirtyL();
for ( TInt i = 0; i < iControlAdapterList->Count(); i++ )
{
CXnControlAdapter* adapter( ( *iControlAdapterList )[i] );
adapter->SkinChanged();
}
ForceRenderUIL();
CleanupStack::PopAndDestroy();
// Handle inactive views
RPointerArray< CXnPluginData >& views(
iAppUiAdapter.ViewManager().ActiveAppData().PluginData() );
for ( TInt i = 0; i < views.Count(); i++ )
{
CXnViewData* view = static_cast< CXnViewData* >( views[i] );
if ( view && !view->Active() )
{
RPointerArray< CXnControlAdapter > controls;
CleanupClosePushL( controls );
view->ControlsL( controls );
for ( TInt j = 0; j < controls.Count(); j++ )
{
controls[j]->SkinChanged();
}
CleanupStack::PopAndDestroy( &controls );
}
}
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::HandleDynamicLayoutVariantSwitchL
// Handles a KEikDynamicLayoutVariantSwitch resource change
// -----------------------------------------------------------------------------
//
void CXnUiEngineImpl::HandleDynamicLayoutVariantSwitchL()
{
// 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;
}
// remove focus
iAppUiAdapter.HideFocus();
// Update client rect
SetClientRectL( iAppUiAdapter.ClientRect(), EFalse );
// Update background rect
// Bg rect is always screen size.
TRect bgRect;
AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, bgRect );
iAppUiAdapter.ViewAdapter().BgManager().SetRect( bgRect );
iEditMode->HandleScreenDeviceChangedL();
// Force relayout
DisableRenderUiLC();
RootNode()->SetDirtyL();
ReportScreenDeviceChangeL();
iViewManager.OrientationChanged();
if ( !iControlAdapterList )
{
iControlAdapterList = &iViewManager.Controls();
}
for ( TInt i = 0; i < iControlAdapterList->Count(); i++ )
{
CXnControlAdapter* adapter( ( *iControlAdapterList )[i] );
adapter->HandleScreenDeviceChangedL();
}
ForceRenderUIL();
CleanupStack::PopAndDestroy();
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::IsMenuDisplaying
// Checks whether the menu is displaying or not.
// -----------------------------------------------------------------------------
//
TBool CXnUiEngineImpl::IsMenuDisplaying()
{
if ( iKeyEventDispatcher )
{
return iKeyEventDispatcher->IsMenuFocused();
}
return EFalse;
}
// -----------------------------------------------------------------------------
// 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 )
{
if ( iKeyEventDispatcher )
{
iKeyEventDispatcher->AddPassiveFocusedNodeL( aNode );
}
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::RemovePassiveFocusedNode
// -----------------------------------------------------------------------------
//
void CXnUiEngineImpl::RemovePassiveFocusedNodeL( CXnNode* aNode )
{
if ( iKeyEventDispatcher )
{
iKeyEventDispatcher->RemovePassiveFocusedNodeL( aNode );
}
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::AddPassiveFocusedNode
// -----------------------------------------------------------------------------
//
void CXnUiEngineImpl::ClearPassiveFocusedNodesL()
{
if ( iKeyEventDispatcher )
{
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 ( !( iLayoutControl & XnLayoutControl::EIgnoreState ) )
{
if ( iDisableCount > 0 )
{
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 )
{
if ( aNode )
{
CXnNode* nodeToRedrawList( aNode );
CXnNode* nodeToDirtyList( aNode );
if ( aNode == RootNode() )
{
// Force relayout and redraw from current view
iDirtyList.Reset();
if ( !iCurrentView )
{
iCurrentView = iViewManager.ViewNode();
}
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 );
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::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<CXnNode> plugins = *Plugins();
for( TInt i=0; i<plugins.Count(); i++ )
{
CXnNode* pluginNode = plugins[i];
RPointerArray<CXnNode> pluginChildren = pluginNode->Children();
for( TInt ii=0; ii<pluginChildren.Count(); ii++ )
{
CXnDomNode* widgetNode = pluginChildren[ii]->DomNode();
if( widgetNode && widgetNode->Name() == KWidgetNodeName )
{
pluginChildren[ii]->ReportXuikonEventL( *trigger );
}
}
}
CleanupStack::PopAndDestroy(); // trigger
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::HandlePartialTouchInputL()
// -----------------------------------------------------------------------------
void CXnUiEngineImpl::HandlePartialTouchInputL( CXnNode& aNode, TBool aEnable )
{
CXnNode* editorplugin = FindPlugin( aNode );
if ( !editorplugin )
{
User::Leave( KErrNotFound );
}
DisableRenderUiLC();
if ( aEnable )
{
iSplitScreenState.iPartialScreenOpen = ETrue;
iSplitScreenState.iPartialScreenEditorNode = &aNode;
// make sure that we always get up event
CXnViewControlAdapter* control = static_cast< CXnViewControlAdapter* >(
iViewManager.ActiveViewData().ViewNode()->Control() );
control->ResetGrabbing();
// Block progression must be bottom-to-top when partial screen is open
// Previous value needs to be stored first
CXnProperty* prop(
editorplugin->Parent()->GetPropertyL(
XnPropertyNames::style::common::KBlockProgression ) );
if ( prop )
{
iSplitScreenState.iPartialScreenBlock = &prop->StringValue();
}
else
{
iSplitScreenState.iPartialScreenBlock =
&XnPropertyNames::style::common::block_progression::KTB();
}
SetPartialScreenBlockProgressionL(
editorplugin->Parent(),
XnPropertyNames::style::common::block_progression::KBT );
// Hide all plugins except the one that contains given editor node
RPointerArray< CXnNode >& plugins( *Plugins() );
for( TInt i=0; i<plugins.Count(); i++ )
{
CXnNode* pluginNode = plugins[i];
if ( pluginNode != editorplugin )
{
SetNodeVisibleL(pluginNode, EFalse);
}
}
// Hide statuspane
iAppUiAdapter.StatusPane()->MakeVisible( EFalse );
}
else
{
// Show plugin nodes again
RPointerArray< CXnNode >& plugins( *Plugins() );
for( TInt i=0; i<plugins.Count(); i++ )
{
CXnNode* pluginNode = plugins[i];
if ( pluginNode != editorplugin )
{
SetNodeVisibleL(pluginNode, ETrue);
}
}
SetPartialScreenBlockProgressionL(
editorplugin->Parent(),
*iSplitScreenState.iPartialScreenBlock );
iSplitScreenState.iPartialScreenBlock = NULL;
iSplitScreenState.iPartialScreenEditorNode = NULL;
iSplitScreenState.iPartialScreenOpen = EFalse;
// Show statuspane again
iAppUiAdapter.StatusPane()->MakeVisible(ETrue);
}
RootNode()->SetDirtyL();
ForceRenderUIL();
CleanupStack::PopAndDestroy();
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
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; i<iRedrawRegions.Count(); i++ )
{
if( iRedrawRegions[i]->iControl == 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(), EFalse ) );
}
// -----------------------------------------------------------------------------
// NotifyResourceChanged
// -----------------------------------------------------------------------------
void CXnUiEngineImpl::NotifyResourceChanged( TInt aType )
{
TRAP_IGNORE( HandleResourceChangeL( aType ) );
}
// -----------------------------------------------------------------------------
// EnablePartialTouchInput
// -----------------------------------------------------------------------------
void CXnUiEngineImpl::EnablePartialTouchInput( CXnNode& aNode, TBool aEnable )
{
if( aEnable && !iSplitScreenState.iPartialScreenOpen ||
!aEnable && iSplitScreenState.iPartialScreenOpen )
{
TRAP_IGNORE( HandlePartialTouchInputL( aNode, aEnable ) );
}
}
// -----------------------------------------------------------------------------
// SetNodeVisibleL
// -----------------------------------------------------------------------------
void CXnUiEngineImpl::SetNodeVisibleL( CXnNode* aNode , TBool aVisible )
{
CXnDomStringPool* sp( iUiEngine->ODT()->DomDocument().StringPool());
if(!aVisible)
{
CXnProperty* display = CXnProperty::NewL(
XnPropertyNames::style::common::KDisplay,
XnPropertyNames::style::common::display::KNone,
CXnDomPropertyValue::EString, *sp );
CleanupStack::PushL( display );
aNode->SetPropertyL(display);
CleanupStack::Pop( display );
}
else
{
CXnProperty* visible = CXnProperty::NewL(
XnPropertyNames::style::common::KDisplay,
XnPropertyNames::style::common::display::KBlock,
CXnDomPropertyValue::EString, *sp );
CleanupStack::PushL( visible );
aNode->SetPropertyL(visible);
CleanupStack::Pop( visible );
}
}
// -----------------------------------------------------------------------------
// SetPartialScreenBlockProgressionL
// -----------------------------------------------------------------------------
void CXnUiEngineImpl::SetPartialScreenBlockProgressionL(
CXnNode* aParent, const TDesC8& aBlockProgression )
{
CXnDomStringPool* sp( iUiEngine->ODT()->DomDocument().StringPool());
if( aParent && sp )
{
CXnProperty* block_progression = CXnProperty::NewL(
XnPropertyNames::style::common::KBlockProgression,
aBlockProgression,
CXnDomPropertyValue::EString, *sp );
if ( block_progression )
{
CleanupStack::PushL( block_progression );
aParent->SetPropertyL(block_progression);
CleanupStack::Pop( block_progression );
}
}
}
// -----------------------------------------------------------------------------
// isPartialInputActive
// -----------------------------------------------------------------------------
TBool CXnUiEngineImpl::IsPartialInputActive()
{
return iSplitScreenState.iPartialScreenOpen;
}
// -----------------------------------------------------------------------------
// CXnUiEngineImpl::IsTextEditorActive()
// -----------------------------------------------------------------------------
//
TBool CXnUiEngineImpl::IsTextEditorActive()
{
if( iSplitScreenState.iPartialScreenOpen )
{
return ETrue;
}
CXnNode* focusedNode = FocusedNode();
if( focusedNode )
{
if( focusedNode->Type()->Type() == KEditorNodeName )
{
return ETrue;
}
}
return EFalse;
}
// End of file