diff -r 000000000000 -r f72a12da539e idlehomescreen/xmluirendering/uiengine/src/xncontroladapterimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/idlehomescreen/xmluirendering/uiengine/src/xncontroladapterimpl.cpp Thu Dec 17 08:40:49 2009 +0200 @@ -0,0 +1,5960 @@ +/* +* Copyright (c) 2002-2004 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: Xuikon control adapter source file +* +*/ + + +// System includes +#include +#include +#include +#include +//skinning support +#include +#include +#include +#include +#include +#include +#ifdef RD_TACTILE_FEEDBACK +#include +#endif // RD_TACTILE_FEEDBACK + +// User includes +#include "xnappuiadapter.h" +#include "xnviewadapter.h" +#include "xnviewmanager.h" +#include "xncontroladapterimpl.h" +#include "xncontroladapter.h" +#include "xnmenuadapter.h" +#include "xncomponentnodeimpl.h" +#include "xntype.h" +#include "xnnodepluginif.h" +#include "xnuiengine.h" +#include "xnviewnodeimpl.h" +#include "c_xnutils.h" +#include "xndomdocument.h" +#include "xndomattribute.h" +#include "xndomnode.h" +#include "xnproperty.h" +#include "xndomlist.h" +#include "xnodt.h" +#include "xnresource.h" +#include "xnhittest.h" +#include "xnplugindata.h" +#include "xnnode.h" +#include "xnpanic.h" +#include "xnviewdata.h" +#include "xnscrollablecontroladapter.h" +#include "xnfocuscontrol.h" +#include "xneditmode.h" + +_LIT8(KScrollableBoxNodeName, "scrollablebox"); + +using namespace XnGestureHelper; +#include "xngesture.h" + +// Constants +const TInt KSkinGfxInnerRectShrink = 5; +const TInt KFocusGrowValue = 3; + + +// LOCAL FUNCTION PROTOTYPES +static TRgb ConvertHslToRgb( TInt aHue, TInt aSaturation, TInt aLightness ); +static void ConvertRgbToHsl( TRgb aRGB, TUint& aHue, TUint& aSaturation, + TUint& aLightness ); +static void LoadFbsBitmapL( + CXnResource& aResource, CFbsBitmap*& aTarget, RFs& aFsSession ); +static void LoadMbmBitmapL( CXnResource& aResource, + TInt aBitmapIndex, CFbsBitmap*& aTarget, RFs& aFsSession ); +static void LoadSVGBitmapL( CXnResource& aResource, + CFbsBitmap*& aBitmap, CFbsBitmap*& aBitmapMask, + TRect aRect, RFs& aFsSession ); +static TBool GetBitmapL( CXnUiEngine& aEngine, CXnNode& aNode, + const TDesC& aResourceFileName, TInt& aBitmapIndex, + CFbsBitmap*& aTarget, CFbsBitmap*& aBitmapMask, + CXnControlAdapterImpl::TIconProvider*& aIconProvider, + TRect aRect, RFs& aFsSession ); + +static void LimitRectToPaddingRect( CXnNode& aNode, TRect& aRect ); +static void DrawSpaceBackgroundY( CWindowGc& aGc, TInt aYRepeatCount, + CXnNode& aNode, TRect& aRect, CFbsBitmap* aBitmap, TRect aBitmapRect, + TRect aImageRect, TInt& aYOffset ); +static void DrawRepeatBackgroundY( CWindowGc& aGc, TInt aYRepeatCount, + CXnNode& aNode, TRect& aRect, CFbsBitmap* aBitmap, TRect aBitmapRect, + TRect aImageRect, TInt& aYOffset ); +static void StripQuotes( HBufC*& aString ); +static void DrawBackgroundColorL( + const TRect& /*aRect*/, CXnNode& aNode, CWindowGc& aGc ); +static void GetBackroundRepeatValuesL( CXnNode& aNode, TBool& aRepeatX, + TBool& aRepeatY, TBool& aSpaceX, TBool& aSpaceY ); +static void DrawRepeatedBackgroundImage( CWindowGc& aGc, CXnNode& aNode, + TRect& aRect, TRect aImageRect, TRect aBitmapRect, + CFbsBitmap* aBitmap, TBool aRepeatX, TBool aRepeatY, TBool aSpaceX, + TBool aSpaceY, TInt aXRepeatCount, TInt aYRepeatCount ); +static TBool GetBackgroundPositionFromPropertyL( + CXnNode& aNode, TBool aScaleImage, TRect& aRect, + TRect aImageRect, CFbsBitmap* aBitmap, TBool& aHeightSet ); +static TBool GetBackgroundSizeFromPropertyL( TRect& aRect, CXnNode& aNode, + CFbsBitmap* aBitmap, TBool& aScaleImage ); +static TRgb LighterColor( const TRgb& aRgb ); +static TRgb DarkerColor( const TRgb& aRgb ); +static void DrawSolidTopBorder( CArrayFix< TPoint >* aArray, CWindowGc& aGc ); +static void SplitTopBorderPolygonL( CArrayFix< TPoint >* aArray, + CArrayFix< TPoint >*& aUpperPart, CArrayFix< TPoint >*& aLowerPart ); +static void DrawRidgeTopBorderL( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawGrooveTopBorderL( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawInsetTopBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawOutsetTopBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static TBool GetBorderColorL( + const TDesC8& aPropertyName, CXnNode& aNode, CWindowGc& aGc, TRgb& aRgb ); +static void DrawTopBorderL( + const TRect& /*aRect*/, CXnNode& aNode, CWindowGc& aGc ); +static void DrawBottomBorderL( + const TRect& /*aRect*/, CXnNode& aNode, CWindowGc& aGc ); +static void DrawSolidBottomBorder( CArrayFix< TPoint >* aArray, CWindowGc& aGc ); +static void SplitBottomBorderPolygonL( CArrayFix< TPoint >* aArray, + CArrayFix< TPoint >*& aUpperPart, CArrayFix< TPoint >*& aLowerPart ); +static void DrawRidgeBottomBorderL( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawGrooveBottomBorderL( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawInsetBottomBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawOutsetBottomBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawSolidLeftBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc ); +static void SplitLeftBorderPolygonL( CArrayFix< TPoint >* aArray, + CArrayFix< TPoint >*& aLeftPart, CArrayFix< TPoint >*& aRightPart ); +static void DrawRidgeLeftBorderL( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawGrooveLeftBorderL( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawInsetLeftBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawOutsetLeftBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawLeftBorderL( + const TRect& /*aRect*/, CXnNode& aNode, CWindowGc& aGc ); +static void DrawRightBorderL( + const TRect& /*aRect*/, CXnNode& aNode, CWindowGc& aGc ); +static void DrawSolidRightBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc ); +static void SplitRightBorderPolygonL( CArrayFix< TPoint >* aArray, + CArrayFix< TPoint >*& aLeftPart, CArrayFix< TPoint >*& aRightPart ); +static void DrawRidgeRightBorderL( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawGrooveRightBorderL( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawInsetRightBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawOutsetRightBorder( + CArrayFix< TPoint >* aArray, CWindowGc& aGc, TRgb& aRgb ); +static void DrawBorderImagesL( + const TRect& /*aRect*/, CXnNode& aNode, CWindowGc& aGc, + CFbsBitmap* aBitmap, TInt aBorderBitmapDividerTop, + TInt aBorderBitmapDividerRight, + TInt aBorderBitmapDividerBottom, TInt aBorderBitmapDividerLeft ); +static TBool IsPropertyNone( CXnProperty& aProperty ); +static void DrawBordersL( const TRect& aRect, CXnNode& aNode, CWindowGc& aGc ); +static void SwapChildArrays( RPointerArray< CXnControlAdapter >& originalArray, + RPointerArray< CXnControlAdapter >& sortedArray ); +static CXnProperty* GetZIndexL( CXnControlAdapter* aAdapter ); +static void InsertChildToSortedArrayL( + RPointerArray< CXnControlAdapter >& aTargetArray, + CXnControlAdapter* aChild ); +static void InitializeBackgroundBitmapL( CXnUiEngine& aEngine, CXnNode& aNode, + TInt& aBitmapIndex, CFbsBitmap*& aBitmap, CFbsBitmap*& aMask, + CXnControlAdapterImpl::TIconProvider*& aIconProvider, RFs& aFsSession ); +static HBufC* GetBackgroundImagePathLC( CXnNode& aNode ); +static CFbsBitmap* InitializeBorderBitmapL( + CXnUiEngine& aEngine, CXnNode& aNode, + TInt& aBitmapIndex, TInt& aBorderBitmapDividerTop, + TInt& aBorderBitmapDividerRight, TInt& aBorderBitmapDividerBottom, + TInt& aBorderBitmapDividerLeft, + CXnControlAdapterImpl::TIconProvider*& aIconProvider, RFs& aFsSession ); +static void DrawDottedBorder( + TRect aBorderRect, CWindowGc& aGc, TRgb& aRgb, TBool aHorizontal ); +static HBufC* GetBackgroundImageMaskPathLC( CXnNode& aNode ); +static CFbsBitmap* CreateBitmapFromColorL( TSize aSize, TRgb aColor ); +static TBool CreateGestureHelperL( CXnNode& aNode ); +static TInt AccessResourceFileL( + CXnResource& aResource, RFile& aFile, RFs& aFsSession ); +static void DrawFocusAppearance( CXnNode& aNode, CWindowGc& aGc ); +static CXnDomNode* HasHoldTrigger( CXnDomNode* aNode ); +static void CancelFocusRefusalL( CXnUiEngine& aUiEngine ); + +// ============================= LOCAL FUNCTIONS =============================== +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +static CXnScrollableControlAdapter* IsChildOfScrollableControl( CXnNode& aNode ) + { + CXnNode* parent = aNode.Parent(); + while( parent ) + { + if( parent->Type()->Type() == KScrollableBoxNodeName ) + { + CXnScrollableControlAdapter* ret = static_cast(parent->Control()); + return ret; + } + parent = parent->Parent(); + } + return NULL; + } + +// ----------------------------------------------------------------------------- +// SetControlContext +// +// ----------------------------------------------------------------------------- +// +static void SetControlContext(CXnControlAdapter& aChild, CXnNode& aNode) + { + CXnScrollableControlAdapter* scrollableControl = IsChildOfScrollableControl( aNode ); + if(scrollableControl) + { + aNode.SetScrollableControl(scrollableControl); + aChild.CopyControlContextFrom(scrollableControl); + } + } + +// ----------------------------------------------------------------------------- +// AccessResourceFileL +// Opens a resource file for accessing. The caller must close the file. +// ----------------------------------------------------------------------------- +// +static TInt AccessResourceFileL( + CXnResource& aResource, + RFile& aFile, + RFs& aFsSession ) + { + TInt err = KErrNone; + + // parse file name and extension + const TDesC& fileName = aResource.FileName(); + TParsePtrC fileParser( fileName ); + TPtrC filepath = fileParser.DriveAndPath(); + + // open resource file + aFsSession.SetSessionPath( filepath ); + aFsSession.ShareProtected(); + err = aFile.Open( aFsSession, fileName, EFileShareReadersOnly ); + if ( err != KErrNone ) + { + aFile.Close(); + } + + return err; + } + +// ----------------------------------------------------------------------------- +// LoadFbsBitmapL +// Loads a bitmap file from the theme server and creates a CFbsBitmap +// ----------------------------------------------------------------------------- +// +static void LoadFbsBitmapL( + CXnResource& aResource, + CFbsBitmap*& aTarget, + RFs& aFsSession ) + { + RFile file; + + TInt ret = AccessResourceFileL( aResource, file, aFsSession ); + if ( ret == KErrNone ) + { + CleanupClosePushL( file ); + aTarget = new ( ELeave ) CFbsBitmap; + if ( !aTarget ) + { + CleanupStack::PopAndDestroy(); + return; + } + RFileReadStream readStream( file ); + CleanupClosePushL( readStream ); + aTarget->InternalizeL( readStream ); + CleanupStack::PopAndDestroy( &readStream ); + CleanupStack::PopAndDestroy( &file ); + } + } + +// ----------------------------------------------------------------------------- +// LoadMifBitmapL +// Loads a bitmap file from the theme server and creates a CFbsBitmap +// ----------------------------------------------------------------------------- +// +static void LoadMifBitmapL( + CXnResource& aResource, + TInt aBitmapIndex, + CFbsBitmap*& aBitmap, + CFbsBitmap*& aMask, + CXnControlAdapterImpl::TIconProvider*& aIconProvider, + RFs& aFsSession, + const TRect& aRect ) + { + RFile file; + + TInt ret = AccessResourceFileL( aResource, file, aFsSession ); + if ( ret == KErrNone ) + { + aIconProvider = new ( ELeave ) CXnControlAdapterImpl::TIconProvider( file ); + } + + if ( ret == KErrNone ) + { + // Mask is next after bitmap + AknIconUtils::CreateIconL( aBitmap, aMask, *aIconProvider, + aBitmapIndex + KMifIdFirst, aBitmapIndex + KMifIdFirst + 1 ); + AknIconUtils::SetSize( aBitmap, aRect.Size(), EAspectRatioNotPreserved ); + } + } + +// ----------------------------------------------------------------------------- +// LoadMbmBitmapL +// Loads a bitmap file from the theme server and creates a CFbsBitmap +// ----------------------------------------------------------------------------- +// +static void LoadMbmBitmapL( + CXnResource& aResource, + TInt aBitmapIndex, + CFbsBitmap*& aTarget, + RFs& aFsSession ) + { + RFile file; + + TInt ret = AccessResourceFileL( aResource, file, aFsSession ); + if ( ret == KErrNone ) + { + CleanupClosePushL( file ); + aTarget = new ( ELeave ) CFbsBitmap; + aTarget->Load( file, aBitmapIndex ); + CleanupStack::PopAndDestroy(); + } + } + +// ----------------------------------------------------------------------------- +// LoadSVGBitmapL +// Loads an SVG file from the theme server and creates a CFbsBitmap. +// ----------------------------------------------------------------------------- +// +static void LoadSVGBitmapL( + CXnResource& aResource, + CFbsBitmap*& aBitmap, + CFbsBitmap*& aBitmapMask, + TRect /*aRect*/, + RFs& aFsSession ) + { + RFile file; + + TInt ret = AccessResourceFileL( aResource, file, aFsSession ); + if ( ret == KErrNone ) + { + CleanupClosePushL( file ); + + CFbsBitmap* frameBuffer = new ( ELeave ) CFbsBitmap; + CleanupStack::PushL( frameBuffer ); + + frameBuffer->Create( TSize( 0, 0 ), EColor16M ); + + TFontSpec fontSpec; + CSvgEngineInterfaceImpl* svgEngine = + CSvgEngineInterfaceImpl::NewL( frameBuffer, NULL, fontSpec ); + + CleanupStack::PushL( svgEngine ); + + svgEngine->Load( file ); + + TSize contentSize = svgEngine->ContentDimensions(); + + TInt domHandle; + svgEngine->PrepareDom( file, domHandle ); + + svgEngine->SetSvgDimensionToFrameBuffer( + contentSize.iWidth, contentSize.iHeight ); + + CFbsBitmap* target = new ( ELeave ) CFbsBitmap; + target->Create( contentSize, EColor16M ); + svgEngine->RenderDom( domHandle, target ); + + aBitmap = target; + + CFbsBitmap* mask = new ( ELeave ) CFbsBitmap; + mask->Create( contentSize, EGray256 ); + svgEngine->GenerateMask( mask ); + + aBitmapMask = mask; + + CleanupStack::PopAndDestroy( 3, &file ); // frameBuffer, svgEngine, file + } + } + + +// ----------------------------------------------------------------------------- +// ResolveMifIDL +// Resolves a mif id from a given string. +// ----------------------------------------------------------------------------- +// +static TBool ResolveMifIDL( + const TDesC& aMifId, + TInt& aMifID ) + { + HBufC* str = aMifId.AllocL(); + TPtr ptrMif = str->Des(); + ptrMif.TrimAll(); + TInt pos( ptrMif.FindF( KMif ) ); + if ( KErrNotFound != pos ) + { + pos += KMif().Length(); + TPtr ptr = ptrMif.MidTPtr( pos, ( ptrMif.Length() - pos ) ); + ptr.TrimAll(); + TInt offset( ptr.Locate( KRightParenthesis ) ); + if ( KErrNotFound != offset ) + { + TLex lex( ptr.Left( offset ) ); + lex.SkipSpace(); + lex.Val( aMifID ); + delete str; + return ETrue; + } + } + delete str; + return EFalse; + } + +// ----------------------------------------------------------------------------- +// LoadSkinBitmapL +// Loads a skin bitmap and creates a CFbsBitmap from it. +// ----------------------------------------------------------------------------- +// +static TBool LoadSkinBitmapL( + const TDesC& aSkinId, + CFbsBitmap*& aBitmap, + CFbsBitmap*& aBitmapMask, + TRect aRect ) + { + TAknsItemID itemID; + + MAknsSkinInstance* skin( AknsUtils::SkinInstance() ); + + TInt mifId( 0 ); + + TInt mifFound( ResolveMifIDL( aSkinId, mifId ) ); + + TInt colorIndex( KErrNotFound ); + + if ( skin && CXnUtils::ResolveSkinItemIDL( aSkinId, itemID, colorIndex ) ) + { + if ( itemID.iMajor == EAknsMajorAppIcon ) // Check if appl. icon request + { + TUid applUid; + applUid = TUid::Uid( itemID.iMinor ); + + AknsUtils::CreateAppIconLC( + skin, applUid, EAknsAppIconTypeList, aBitmap, aBitmapMask ); + AknIconUtils::SetSize( + aBitmap, aRect.Size(), EAspectRatioNotPreserved ); + CleanupStack::Pop( 2 ); //aBitmap, aBitmapMask + + return ETrue; + } + else + { + TInt error( KErrNone ); + + // if we have a color index, then we create a colored icon + if ( colorIndex != KErrNotFound ) + { + TRgb defaultColor( 0, 0, 0 ); + + TRAP( error, AknsUtils::CreateColorIconL( + skin, itemID, KAknsIIDQsnTextColors, + colorIndex, aBitmap, aBitmapMask, + KNullDesC, mifId, mifId + 1, defaultColor ) ); + } + else + { + TRAP( error, AknsUtils::CreateIconL( + skin, itemID, aBitmap, aBitmapMask, KNullDesC, + mifId, mifId + 1 ) ); + } + + if ( error != KErrNone ) + { + error = KErrNone; + TRAP( error, AknsUtils::CreateIconL( + skin, itemID, aBitmap, KNullDesC, mifId ) ); + } + + if ( error == KErrNone ) + { + AknIconUtils::SetSize( + aBitmap, aRect.Size(), EAspectRatioNotPreserved ); + + return ETrue; + } + } + } + + if ( mifFound ) + { + AknIconUtils::CreateIconL( + aBitmap, aBitmapMask, KAvkonBitmapFile, mifId, mifId + 1 ); + AknIconUtils::SetSize( + aBitmap, aRect.Size(), EAspectRatioNotPreserved ); + + return ETrue; + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// GetBitmap +// Fetches a bitmap +// ----------------------------------------------------------------------------- +// +static TBool GetBitmapL( + CXnUiEngine& aEngine, + CXnNode& /*aNode*/, + const TDesC& aResourceFileName, + TInt& aBitmapIndex, + CFbsBitmap*& aBitmap, + CFbsBitmap*& aBitmapMask, + CXnControlAdapterImpl::TIconProvider*& aIconProvider, + TRect aRect, + RFs& aFsSession ) + { + if ( LoadSkinBitmapL( aResourceFileName, aBitmap, aBitmapMask, aRect ) ) + { + return ETrue; + } + + CXnResource* resource( CXnUtils::FindResource( + aEngine.Resources(), aResourceFileName, aBitmapIndex ) ); + + if ( resource ) + { + if ( resource->ResourceType() == EResourceSVG ) + { + LoadSVGBitmapL( *resource, aBitmap, aBitmapMask, aRect, aFsSession ); + + return ETrue; + } + else if ( resource->ResourceType() == EResourceMIF ) + { + LoadMifBitmapL( *resource, aBitmapIndex, aBitmap, + aBitmapMask, aIconProvider, aFsSession, aRect ); + + return ETrue; + } + else if ( resource->ResourceType() == EResourceMBM ) + { + LoadMbmBitmapL( *resource, aBitmapIndex, aBitmap, aFsSession ); + + return ETrue; + } + else if ( resource->ResourceType() == EResourceFBS ) + { + LoadFbsBitmapL( *resource, aBitmap, aFsSession ); + + return ETrue; + } + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// DrawBackgroundColorL +// Draws background color to the padding rect +// ----------------------------------------------------------------------------- +// +static void DrawBackgroundColorL( + const TRect& /*aRect*/, + CXnNode& aNode, + CWindowGc& aGc ) + { + CXnProperty* colorProperty( aNode.BackgroundColorL() ); + + if ( colorProperty ) + { + TRect paddingRect = aNode.PaddingRect(); + + CXnDomPropertyValue* value = + static_cast< CXnDomPropertyValue* >( + colorProperty->Property()->PropertyValueList().Item( 0 ) ); + + if ( value->PrimitiveValueType() == CXnDomPropertyValue::ERgbColor ) + { + TRgb rgb( value->RgbColorValueL() ); + + aGc.SetPenColor( rgb ); + + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + + aGc.DrawRect( paddingRect ); + } + } + } + +// ----------------------------------------------------------------------------- +// StripQuotes +// Strips enclosing quotes from a string +// ----------------------------------------------------------------------------- +// +static void StripQuotes( HBufC*& aString ) + { + TInt pos1 = aString->Locate( '\"' ); + TInt pos2 = aString->Locate( '\'' ); + // check, if the first character is " or ' + if ( pos1 == 0 || pos2 == 0 ) + { + TInt len = aString->Length() - 2; + TPtr ptr = aString->Des(); + TPtrC16 newString( aString->Mid( 1, len ).Ptr(), len ); + ptr = newString; + } + } + +// ----------------------------------------------------------------------------- +// DrawRepeatBackgroundY +// Draws repeated background in the vertical direction +// ----------------------------------------------------------------------------- +// +static void DrawRepeatBackgroundY( + CWindowGc& aGc, TInt aYRepeatCount, CXnNode& aNode, TRect& aRect, + CFbsBitmap* aBitmap, TRect aBitmapRect, + TRect aImageRect, TInt& aYOffset ) + { + for (TInt i = 0; i <= aYRepeatCount && aRect.iTl.iY < aNode.PaddingRect().iBr.iY;) + { + TRect newRect; + newRect = TRect( + aRect.iTl, + TPoint( + aRect.iTl.iX + aImageRect.Width(), + aRect.iTl.iY + aImageRect.Height() ) ); + aGc.DrawBitmap( newRect, aBitmap, aBitmapRect ); + aRect.Move( 0, newRect.Height() ); + aYOffset += newRect.Height(); + if ( ++i == aYRepeatCount || aYRepeatCount == 0 ) + { + break; + } + } + } + +// ----------------------------------------------------------------------------- +// DrawSpaceBackgroundY +// Draws spaced background in the vertical direction +// ----------------------------------------------------------------------------- +// +static void DrawSpaceBackgroundY( + CWindowGc& aGc, TInt aYRepeatCount, CXnNode& aNode, TRect& aRect, + CFbsBitmap* aBitmap, TRect aBitmapRect, + TRect aImageRect, TInt& aYOffset ) + { + for (TInt j = 0; j <= aYRepeatCount && aRect.iTl.iY < aNode.PaddingRect().iBr.iY;) + { + TRect newRect = aRect; + newRect = TRect( + aRect.iTl, + TPoint( + aRect.iTl.iX + aImageRect.Width(), + aRect.iTl.iY + aImageRect.Height() ) ); + aGc.DrawBitmap( newRect, aBitmap, aBitmapRect ); + aRect.Move( 0, newRect.Height() ); + aYOffset += newRect.Height(); + if ( ++j == aYRepeatCount || aYRepeatCount == 0 ) + { + break; + } + } + } + +// ----------------------------------------------------------------------------- +// LimitRectToPaddingRect +// Limits a rect so that it does not exceed padding rect +// ----------------------------------------------------------------------------- +// +static void LimitRectToPaddingRect( CXnNode& aNode, TRect& aRect ) + { + TRect tmpRect = aNode.PaddingRect(); + if ( aRect.iTl.iX < tmpRect.iTl.iX ) + { + aRect.SetRect( tmpRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY ); + } + if ( aRect.iTl.iY < tmpRect.iTl.iY ) + { + aRect.SetRect( aRect.iTl.iX, tmpRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY ); + } + if ( aRect.iBr.iX > tmpRect.iBr.iX ) + { + aRect.SetRect( aRect.iTl.iX, aRect.iTl.iY, tmpRect.iBr.iX, aRect.iBr.iY ); + } + if ( aRect.iBr.iY > tmpRect.iBr.iY ) + { + aRect.SetRect( aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, tmpRect.iBr.iY ); + } + } + +// ----------------------------------------------------------------------------- +// GetBackroundRepeatValuesL +// Gets background repeat information from node properties +// ----------------------------------------------------------------------------- +// +static void GetBackroundRepeatValuesL( + CXnNode& aNode, + TBool& aRepeatX, + TBool& aRepeatY, + TBool& aSpaceX, + TBool& aSpaceY ) + { + CXnProperty* backgroundRepeatProperty = aNode.GetPropertyL( + XnPropertyNames::appearance::common::KBackGroundRepeat ); + if ( backgroundRepeatProperty ) + { + CXnDomList& propertyValueList = + backgroundRepeatProperty->Property()->PropertyValueList(); + TInt valueCount = propertyValueList.Length(); + for ( TInt i = 0; i < valueCount; ++i ) + { + CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( + propertyValueList.Item( i ) ); + if ( value->PrimitiveValueType() == CXnDomPropertyValue::EString || + value->PrimitiveValueType() == CXnDomPropertyValue::EIdent ) + { + switch ( i ) + { + case 0: + { + if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundrepeat::KRepeat ) + { + aRepeatX = ETrue; + aRepeatY = ETrue; + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundrepeat::KSpace ) + { + aSpaceX = ETrue; + aSpaceY = ETrue; + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundrepeat::KRepeatX ) + { + aRepeatX = ETrue; + aRepeatY = EFalse; + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundrepeat::KRepeatY ) + { + aRepeatX = EFalse; + aRepeatY = ETrue; + } + break; + } + case 1: + { + if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundrepeat::KRepeat ) + { + aRepeatY = ETrue; + aSpaceY = EFalse; + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundrepeat::KSpace ) + { + aRepeatY = EFalse; + aSpaceY = ETrue; + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundrepeat::KNoRepeat ) + { + aRepeatY = EFalse; + aSpaceY = EFalse; + } + break; + } + } + } + } + } + } + +// ----------------------------------------------------------------------------- +// DrawRepeatedBackgroundImage +// Draws a repeated background image +// ----------------------------------------------------------------------------- +// +static void DrawRepeatedBackgroundImage( + CWindowGc& aGc, + CXnNode& aNode, + TRect& aRect, + TRect aImageRect, + TRect aBitmapRect, + CFbsBitmap* aBitmap, + TBool aRepeatX, + TBool aRepeatY, + TBool aSpaceX, + TBool aSpaceY, + TInt aXRepeatCount, + TInt aYRepeatCount ) + { + TRect paddingRect = aNode.PaddingRect(); + if ( aRepeatX && !aRepeatY && !aSpaceX && !aSpaceY ) + { + aRect.SetRect( TPoint( paddingRect.iTl.iX, aRect.iTl.iY ), aRect.Size() ); + for ( TInt i = 0; i <= aXRepeatCount && aRect.iTl.iX < paddingRect.iBr.iX; ) + { + TRect newRect = TRect( + aRect.iTl, + TPoint( + aRect.iTl.iX + aImageRect.Width(), + aRect.iTl.iY + aImageRect.Height() ) ); + aGc.DrawBitmap( newRect, aBitmap, aBitmapRect ); + aRect.Move( newRect.Width(), 0 ); + if ( ++i == aXRepeatCount || aXRepeatCount == 0 ) + { + break; + } + } + } + else if ( !aRepeatX && !aRepeatY && aSpaceX && !aSpaceY ) + { + aRect.SetRect( TPoint( paddingRect.iTl.iX, aRect.iTl.iY ), aRect.Size() ); + if ( aImageRect.Width() < paddingRect.Width() && aXRepeatCount > 0 ) + { + aRect.Move( + ( paddingRect.Width() - aImageRect.Width() * aXRepeatCount ) / 2, + 0 ); + } + for ( TInt i = 0; i <= aXRepeatCount && aRect.iTl.iX < paddingRect.iBr.iX; ) + { + TRect newRect = TRect( + aRect.iTl, + TPoint( + aRect.iTl.iX + aImageRect.Width(), + aRect.iTl.iY + aImageRect.Height() ) ); + aGc.DrawBitmap( newRect, aBitmap, aBitmapRect ); + aRect.Move( newRect.Width(), 0 ); + if ( ++i == aXRepeatCount || aXRepeatCount == 0 ) + { + break; + } + } + } + else if ( !aRepeatX && aRepeatY && !aSpaceX && !aSpaceY ) + { + aRect.SetRect( TPoint( aRect.iTl.iX, paddingRect.iTl.iY ), aRect.Size() ); + TInt yOffset = 0; + DrawRepeatBackgroundY( + aGc, aYRepeatCount, aNode, aRect, + aBitmap, aBitmapRect, + aImageRect, yOffset ); + } + else if ( !aRepeatX && !aRepeatY && !aSpaceX && aSpaceY ) + { + aRect.SetRect( TPoint( aRect.iTl.iX, paddingRect.iTl.iY ), aRect.Size() ); + if ( aImageRect.Height() < paddingRect.Height() && aYRepeatCount > 0 ) + { + aRect.Move( + 0, + ( paddingRect.Height() - aImageRect.Height() * aYRepeatCount ) / 2 ); + } + TInt yOffset = 0; + DrawSpaceBackgroundY( + aGc, aYRepeatCount, aNode, aRect, + aBitmap, aBitmapRect, + aImageRect, yOffset ); + } + else if ( aRepeatX && aRepeatY && !aSpaceX && !aSpaceY ) + { + aRect.SetRect( paddingRect.iTl, aRect.Size() ); + TInt yOffset = 0; + for ( TInt i = 0; i <= aXRepeatCount && aRect.iTl.iX < paddingRect.iBr.iX; ) + { + aRect.Move( 0, -yOffset ); + yOffset = 0; + TRect newRect = TRect( + aRect.iTl, + TPoint( + aRect.iTl.iX + aImageRect.Width(), + aRect.iTl.iY + aImageRect.Height() ) ); + aRect = newRect; + DrawRepeatBackgroundY( + aGc, aYRepeatCount, aNode, aRect, + aBitmap, aBitmapRect, + aImageRect, yOffset ); + aRect.Move( newRect.Width(), 0 ); + if ( ++i == aXRepeatCount || aXRepeatCount == 0 ) + { + break; + } + } + } + else if ( !aRepeatX && !aRepeatY && aSpaceX && aSpaceY ) + { + aRect.SetRect( paddingRect.iTl, aRect.Size() ); + if ( aImageRect.Width() < paddingRect.Width() && aXRepeatCount > 0 ) + { + aRect.Move( + ( paddingRect.Width() - aImageRect.Width() * aXRepeatCount ) / 2, + 0 ); + } + if ( aImageRect.Height() < paddingRect.Height() && aYRepeatCount > 0 ) + { + aRect.Move( + 0, + ( paddingRect.Height() - aImageRect.Height() * aYRepeatCount ) / 2 ); + } + TInt yOffset = 0; + for ( TInt i = 0; i <= aXRepeatCount && aRect.iTl.iX < paddingRect.iBr.iX; ) + { + aRect.Move( 0, -yOffset ); + yOffset = 0; + TRect newRect = TRect( + aRect.iTl, + TPoint( + aRect.iTl.iX + aImageRect.Width(), + aRect.iTl.iY + aImageRect.Height() ) ); + aRect = newRect; + DrawSpaceBackgroundY( + aGc, aYRepeatCount, aNode, aRect, + aBitmap, aBitmapRect, + aImageRect, yOffset ); + aRect.Move( newRect.Width(), 0 ); + if ( ++i == aXRepeatCount || aXRepeatCount == 0 ) + { + break; + } + } + } + else if ( aRepeatX && !aRepeatY && !aSpaceX && aSpaceY ) + { + aRect.SetRect( paddingRect.iTl, aRect.Size() ); + if ( aImageRect.Height() < paddingRect.Height() && aYRepeatCount > 0 ) + { + aRect.Move( + 0, + ( paddingRect.Height() - aImageRect.Height() * aYRepeatCount ) / 2 ); + } + TInt yOffset = 0; + for ( TInt i = 0; i <= aXRepeatCount && aRect.iTl.iX < paddingRect.iBr.iX; ) + { + aRect.Move( 0, -yOffset ); + yOffset = 0; + TRect newRect = TRect( + aRect.iTl, + TPoint( + aRect.iTl.iX + aImageRect.Width(), + aRect.iTl.iY + aImageRect.Height() ) ); + aRect = newRect; + DrawSpaceBackgroundY( + aGc, aYRepeatCount, aNode, aRect, + aBitmap, aBitmapRect, + aImageRect, yOffset ); + aRect.Move( newRect.Width(), 0 ); + if ( ++i == aXRepeatCount || aXRepeatCount == 0 ) + { + break; + } + } + } + else if ( !aRepeatX && aRepeatY && aSpaceX && !aSpaceY ) + { + aRect.SetRect( paddingRect.iTl, aRect.Size() ); + TInt yOffset = 0; + if ( aImageRect.Width() < paddingRect.Width() && aXRepeatCount > 0 ) + { + aRect.Move( + ( paddingRect.Width() - aImageRect.Width() * aXRepeatCount ) / 2, + -yOffset ); + } + for ( TInt i = 0; i <= aXRepeatCount && aRect.iTl.iX < paddingRect.iBr.iX; ) + { + aRect.Move( 0, -yOffset ); + yOffset = 0; + TRect newRect = TRect( + aRect.iTl, + TPoint( + aRect.iTl.iX + aImageRect.Width(), + aRect.iTl.iY + aImageRect.Height() ) ); + aRect = newRect; + DrawRepeatBackgroundY( + aGc, aYRepeatCount, aNode, aRect, + aBitmap, aBitmapRect, + aImageRect, yOffset ); + aRect.Move( newRect.Width(), 0 ); + if ( ++i == aXRepeatCount || aXRepeatCount == 0 ) + { + break; + } + } + } + } + +// ----------------------------------------------------------------------------- +// GetBackgroundPositionFromPropertyL +// Gets background position information from node properties +// ----------------------------------------------------------------------------- +// +static TBool GetBackgroundPositionFromPropertyL( + CXnNode& aNode, + TBool aScaleImage, + TRect& aRect, + TRect aImageRect, + CFbsBitmap* aBitmap, + TBool& aHeightSet ) + { + CXnProperty* backgroundPositionProperty = aNode.GetPropertyL( + XnPropertyNames::appearance::common::KBackGroundPosition ); + TBool centerHorizontal = ETrue; + if ( backgroundPositionProperty ) + { + CXnDomList& propertyValueList = + backgroundPositionProperty->Property()->PropertyValueList(); + TSize size; + 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 ) + { + if ( aScaleImage ) + { + size = aImageRect.Size(); + } + else + { + size = aBitmap->SizeInPixels(); + } + switch ( i ) + { + case 0: + { + // StringValueL will not leave, we check the type first + if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundposition::KRight ) + { + centerHorizontal = EFalse; + aRect.Move( aRect.Width(), 0 ); + aRect.Move( -size.iWidth, 0 ); + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundposition::KLeft ) + { + centerHorizontal = EFalse; + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundposition::KBottom ) + { + aHeightSet = ETrue; + aRect.Move( 0, aRect.Height() ); + aRect.Move( 0, -size.iHeight ); + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundposition::KTop ) + { + aHeightSet = ETrue; + } + break; + } + case 1: + { + // StringValueL will not leave, we check the type first + if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundposition::KRight ) + { + aRect.Move( aRect.Width(), 0 ); + aRect.Move( -size.iWidth, 0 ); + centerHorizontal = EFalse; + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundposition::KLeft ) + { + centerHorizontal = EFalse; + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundposition::KBottom ) + { + aHeightSet = ETrue; + aRect.Move( 0, aRect.Height() ); + aRect.Move( 0, -size.iHeight ); + } + else if ( value->StringValueL() == + XnPropertyNames::appearance::common::backgroundposition::KTop ) + { + aHeightSet = ETrue; + } + break; + } + } + } + else if ( value->PrimitiveValueType() == CXnDomPropertyValue::EPercentage ) + { + // FloatValueL will not leave, we check the type first + TReal percentage = value->FloatValueL(); + if ( percentage > 100 ) + { + percentage = 100; + } + TSize size = aImageRect.Size(); + switch ( i ) + { + case 0: + { + TInt rectOffset = ( percentage / 100.0 ) * aRect.Width(); + TInt bitmapOffset = ( percentage / 100.0 ) * size.iWidth; + aRect.Move( rectOffset, 0 ); + aRect.Move( -bitmapOffset, 0 ); + centerHorizontal = EFalse; + break; + } + case 1: + { + aHeightSet = ETrue; + TInt rectOffset = ( percentage / 100.0 ) * aRect.Height(); + TInt bitmapOffset = ( percentage / 100.0 ) * size.iHeight; + aRect.Move( 0, rectOffset ); + aRect.Move( 0, -bitmapOffset ); + break; + } + } + } + else + { + CXnDomPropertyValue* tmpValue = NULL; + TRAPD( error, tmpValue = value->CloneL(); ); + if ( error != KErrNone ) + { + return EFalse; + } + CXnProperty* tmpProperty = NULL; + TRAP( error, tmpProperty = CXnProperty::NewL( + KNullDesC8, + tmpValue, + aNode.UiEngine()->ODT()->DomDocument().StringPool() ); ); + if ( error != KErrNone ) + { + delete tmpValue; + return EFalse; + } + switch ( i ) + { + case 0: + { + TInt intValue = 0; + TRAP( error, + intValue = aNode.UiEngine()->HorizontalPixelValueL( + tmpProperty, 0 ); ); + if ( error != KErrNone ) + { + delete tmpProperty; + return EFalse; + } + aRect.Move( intValue, 0 ); + centerHorizontal = EFalse; + break; + } + case 1: + { + aHeightSet = ETrue; + TInt intValue = 0; + TRAP( error, + intValue = aNode.UiEngine()->VerticalPixelValueL( + tmpProperty, 0 ); ); + if ( error != KErrNone ) + { + delete tmpProperty; + return EFalse; + } + aRect.Move( 0, intValue ); + break; + } + } + delete tmpProperty; + } + } + if ( centerHorizontal ) + { + aRect.Move( aRect.Width() / 2, 0 ); + aRect.Move( -size.iWidth / 2, 0 ); + } + } + else + { + aHeightSet = ETrue; + } + return ETrue; + } + +// ----------------------------------------------------------------------------- +// GetBackgroundSizeFromPropertyL +// Gets background size information from node properties +// ----------------------------------------------------------------------------- +// +static TBool GetBackgroundSizeFromPropertyL( + TRect& aRect, + CXnNode& aNode, + CFbsBitmap* aBitmap, + TBool& aScaleImage ) + { + CXnProperty* backgroundSizeProperty = aNode.GetPropertyL( + XnPropertyNames::appearance::common::KBackGroundSize ); + TBool widthAuto = ETrue; + TBool heightAuto = ETrue; + TBool heightSet = EFalse; + TSize size = aBitmap->SizeInPixels(); + if ( backgroundSizeProperty ) + { + widthAuto = EFalse; + heightAuto = EFalse; + CXnDomList& propertyValueList = + backgroundSizeProperty->Property()->PropertyValueList(); + for ( TInt i = propertyValueList.Length() - 1; i >= 0; --i ) + { + CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( + propertyValueList.Item( i ) ); + if ( value->IsAutoIdent() ) + { + switch ( i ) + { + case 0: + { + widthAuto = ETrue; + break; + } + case 1: + { + heightAuto = ETrue; + break; + } + } + } + } + for ( TInt i = propertyValueList.Length() - 1; i >= 0; --i ) + { + CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( + propertyValueList.Item( i ) ); + if ( value->IsAutoIdent() ) + { + continue; + } + else if ( value->PrimitiveValueType() == CXnDomPropertyValue::EPercentage ) + { + // FloatValueL will not leave, we check the type first + TReal percentage = 100; + TRAP_IGNORE( percentage = value->FloatValueL() ); + if ( percentage > 100 ) + { + percentage = 100; + } + switch ( i ) + { + case 0: + { + TInt widthOffset = ( 1 - ( percentage / 100.0 ) ) * aRect.Width(); + if ( heightAuto ) + { + TReal aspectRatio = + static_cast< TReal >( size.iHeight ) / + static_cast< TReal >( size.iWidth ); + aRect.Resize( -widthOffset, 0 ); + aRect.SetHeight( + static_cast< TInt >( + static_cast< TReal >( + aRect.Width() ) * aspectRatio + 0.5 ) ); + aScaleImage = ETrue; + heightSet = ETrue; + } + else + { + aRect.Resize( -widthOffset, 0 ); + aScaleImage = ETrue; + } + if ( !heightSet ) + { + TInt heightOffset = ( 1 - ( percentage / 100.0 ) ) * aRect.Height(); + aRect.Resize( 0, -heightOffset ); + } + break; + } + case 1: + { + TInt heightOffset = ( 1 - ( percentage / 100.0 ) ) * aRect.Height(); + if ( widthAuto ) + { + TReal aspectRatio = + static_cast< TReal >( size.iHeight ) / + static_cast< TReal >( size.iWidth ); + aRect.Resize( 0, -heightOffset ); + aRect.SetWidth( + static_cast< TInt >( + static_cast< TReal >( + aRect.Height() ) / aspectRatio + 0.5 ) ); + aScaleImage = ETrue; + heightSet = ETrue; + } + else + { + aRect.Resize( 0, -heightOffset ); + aScaleImage = ETrue; + heightSet = ETrue; + } + break; + } + } + } + else + { + CXnDomPropertyValue* tmpValue = NULL; + TRAPD( error, tmpValue = value->CloneL(); ); + if ( error != KErrNone ) + { + return EFalse; + } + CXnProperty* tmpProperty = NULL; + TRAP( error, tmpProperty = CXnProperty::NewL( + KNullDesC8, tmpValue, + aNode.UiEngine()->ODT()->DomDocument().StringPool() ); ); + if ( error != KErrNone ) + { + delete tmpValue; + return EFalse; + } + switch ( i ) + { + case 0: + { + TInt intValue = 0; + TRAP( error, + intValue = aNode.UiEngine()->HorizontalPixelValueL( + tmpProperty, 0 ); ); + TInt widthOffset = aRect.Width() - intValue; + if ( heightAuto ) + { + TReal aspectRatio = + static_cast< TReal >( size.iHeight ) / + static_cast< TReal >( size.iWidth ); + aRect.Resize( -widthOffset, 0 ); + aRect.SetHeight( + static_cast< TInt >( + static_cast< TReal >( + aRect.Width() ) * aspectRatio + 0.5 ) ); + aScaleImage = ETrue; + heightSet = ETrue; + } + else + { + aRect.Resize( -widthOffset, 0 ); + aScaleImage = ETrue; + } + if ( !heightSet ) + { + TInt heightOffset = aRect.Height() - intValue; + aRect.Resize( 0, -heightOffset ); + } + break; + } + case 1: + { + TInt intValue = 0; + TRAP( error, + intValue = aNode.UiEngine()->VerticalPixelValueL( + tmpProperty, 0 ); ); + TInt heightOffset = aRect.Height() - intValue; + if ( widthAuto ) + { + TReal aspectRatio = + static_cast< TReal >( size.iHeight ) / + static_cast< TReal >( size.iWidth ); + aRect.Resize( 0, -heightOffset ); + aRect.SetWidth( + static_cast< TInt >( + static_cast< TReal >( + aRect.Height() ) / aspectRatio + 0.5 ) ); + aScaleImage = ETrue; + heightSet = ETrue; + } + else + { + aRect.Resize( 0, -heightOffset ); + aScaleImage = ETrue; + heightSet = ETrue; + } + break; + } + } + delete tmpProperty; + } + } + } + if ( widthAuto && heightAuto ) + { + if ( size.iHeight < aRect.Height() ) + { + aRect.SetHeight( size.iHeight ); + } + if ( size.iWidth < aRect.Width() ) + { + aRect.SetWidth( size.iWidth ); + } + aScaleImage = EFalse; + } + return ETrue; + } + +// ----------------------------------------------------------------------------- +// LighterColor +// Gets a color that has more HSL lightness (used for border effects) +// ----------------------------------------------------------------------------- +// +static TRgb LighterColor( const TRgb& aRgb ) + { + TUint hue; + TUint saturation; + TUint lightness; + ConvertRgbToHsl( aRgb, hue, saturation, lightness ); + if ( ( static_cast< TInt >( lightness ) + 10 ) <= 100 ) + { + lightness += 10; + } + else + { + lightness = 100; + } + return ConvertHslToRgb( hue, saturation, lightness ); + } + +// ----------------------------------------------------------------------------- +// DarkerColor +// Gets a color that has less HSL lightness (used for border effects) +// ----------------------------------------------------------------------------- +// +static TRgb DarkerColor( const TRgb& aRgb ) + { + TUint hue; + TUint saturation; + TUint lightness; + ConvertRgbToHsl( aRgb, hue, saturation, lightness ); + if ( ( static_cast< TInt >( lightness ) - 10 ) >= 0 ) + { + lightness -= 10; + } + else + { + lightness = 0; + } + return ConvertHslToRgb( hue, saturation, lightness ); + } + +// ----------------------------------------------------------------------------- +// DrawSolidTopBorder +// Draw a top border with solid style +// ----------------------------------------------------------------------------- +// +static void DrawSolidTopBorder( CArrayFix< TPoint >* aArray, CWindowGc& aGc ) + { + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// SplitTopBorderPolygonL +// Split top border to two parts for border effect drawing +// ----------------------------------------------------------------------------- +// +static void SplitTopBorderPolygonL( + CArrayFix< TPoint >* aArray, + CArrayFix< TPoint >*& aUpperPart, + CArrayFix< TPoint >*& aLowerPart ) + { + TPoint leftHalf = + TPoint( + ( *aArray )[0].iX + ( ( *aArray )[3].iX - ( *aArray )[0].iX ) / 2, + ( *aArray )[0].iY + ( ( *aArray )[3].iY - ( *aArray )[0].iY ) / 2); + TPoint rightHalf = + TPoint( + ( *aArray )[2].iX + ( ( *aArray )[1].iX - ( *aArray )[2].iX ) / 2, + ( *aArray )[1].iY + ( ( *aArray )[2].iY - ( *aArray )[1].iY ) / 2); + aUpperPart->AppendL( ( *aArray )[0] ); + aUpperPart->AppendL( ( *aArray )[1] ); + aUpperPart->AppendL( rightHalf ); + aUpperPart->AppendL( leftHalf ); + aLowerPart->AppendL( leftHalf ); + aLowerPart->AppendL( rightHalf ); + aLowerPart->AppendL( ( *aArray )[2] ); + aLowerPart->AppendL( ( *aArray )[3] ); + } + +// ----------------------------------------------------------------------------- +// DrawRidgeTopBorderL +// Draw top border with ridge style +// ----------------------------------------------------------------------------- +// +static void DrawRidgeTopBorderL( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, TRgb& aRgb ) + { + CArrayFix< TPoint >* upperPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( upperPart ); + CArrayFix< TPoint >* lowerPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( lowerPart ); + SplitTopBorderPolygonL( aArray, upperPart, lowerPart ); + TRgb rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( upperPart ); + rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( lowerPart ); + CleanupStack::PopAndDestroy( lowerPart ); + CleanupStack::PopAndDestroy( upperPart ); + } + +// ----------------------------------------------------------------------------- +// DrawGrooveTopBorderL +// Draw top border with groove style +// ----------------------------------------------------------------------------- +// +static void DrawGrooveTopBorderL( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, TRgb& aRgb ) + { + CArrayFix< TPoint >* upperPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( upperPart ); + CArrayFix< TPoint >* lowerPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( lowerPart ); + SplitTopBorderPolygonL( aArray, upperPart, lowerPart ); + TRgb rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( upperPart ); + rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( lowerPart ); + CleanupStack::PopAndDestroy( lowerPart ); + CleanupStack::PopAndDestroy( upperPart ); + } + +// ----------------------------------------------------------------------------- +// DrawInsetTopBorder +// Draw top border with inset style +// ----------------------------------------------------------------------------- +// +static void DrawInsetTopBorder( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, TRgb& aRgb ) + { + TRgb rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// DrawOutsetTopBorder +// Draw top border with outset style +// ----------------------------------------------------------------------------- +// +static void DrawOutsetTopBorder( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, TRgb& aRgb ) + { + TRgb rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// GetBorderColorL +// Get border color from properties +// ----------------------------------------------------------------------------- +// +static TBool GetBorderColorL( + const TDesC8& aPropertyName, + CXnNode& aNode, + CWindowGc& aGc, + TRgb& aRgb ) + { + CXnProperty* colorProperty = aNode.GetPropertyL( aPropertyName ); + CXnProperty* currentColorProperty = aNode.GetPropertyL( + XnPropertyNames::appearance::common::KColor ); + CXnProperty* borderColorProperty = aNode.GetPropertyL( + XnPropertyNames::appearance::common::KBorderColor ); + if ( colorProperty ) + { + CXnDomProperty* domProperty = colorProperty->Property(); + CXnDomPropertyValue* propertyValue = NULL; + propertyValue = static_cast< CXnDomPropertyValue* >( + domProperty->PropertyValueList().Item( 0 ) ); + if ( propertyValue->IsAutoIdent() ) + { + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + TInt error = AknsUtils::GetCachedColor( + skinInstance, + aRgb, + KAknsIIDQsnLineColors, + EAknsCIQsnLineColorsCG4 ); + if ( error != KErrNone ) + { + return EFalse; + } + } + else + { + TRAPD( error, aRgb = propertyValue->RgbColorValueL(); ); + if ( error != KErrNone ) + { + return EFalse; + } + } + aGc.SetPenColor( aRgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( aRgb ); + } + else if ( borderColorProperty ) + { + CXnDomProperty* domProperty = borderColorProperty->Property(); + CXnDomPropertyValue* propertyValue = NULL; + propertyValue = static_cast< CXnDomPropertyValue* >( + domProperty->PropertyValueList().Item( 0 ) ); + if ( propertyValue->IsAutoIdent() ) + { + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + TInt error = AknsUtils::GetCachedColor( + skinInstance, + aRgb, + KAknsIIDQsnLineColors, + EAknsCIQsnLineColorsCG4 ); + if ( error != KErrNone ) + { + return EFalse; + } + } + else + { + TRAPD( error, aRgb = propertyValue->RgbColorValueL(); ); + if ( error != KErrNone ) + { + return EFalse; + } + } + aGc.SetPenColor( aRgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( aRgb ); + } + else if ( currentColorProperty ) + { + CXnDomProperty* domProperty = currentColorProperty->Property(); + CXnDomPropertyValue* propertyValue = NULL; + propertyValue = static_cast< CXnDomPropertyValue* >( + domProperty->PropertyValueList().Item( 0 ) ); + if ( propertyValue->IsAutoIdent() ) + { + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + TInt error = AknsUtils::GetCachedColor( + skinInstance, + aRgb, + KAknsIIDQsnLineColors, + EAknsCIQsnLineColorsCG4 ); + if ( error != KErrNone ) + { + return EFalse; + } + } + else + { + TRAPD( error, aRgb = propertyValue->RgbColorValueL(); ); + if ( error != KErrNone ) + { + return EFalse; + } + } + aGc.SetPenColor( aRgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( aRgb ); + } + else + { + return EFalse; + } + return ETrue; + } + +// ----------------------------------------------------------------------------- +// DrawTopBorderL +// Draw top border +// ----------------------------------------------------------------------------- +// +static void DrawTopBorderL( + const TRect& /*aRect*/, + CXnNode& aNode, + CWindowGc& aGc ) + { + TRect borderRect = aNode.BorderRect(); + TRect paddingRect = aNode.PaddingRect(); + TRgb rgb; + if ( !GetBorderColorL( XnPropertyNames::appearance::common::KBorderTopColor, aNode, aGc, rgb ) ) + { + return; + } + TPoint tl = borderRect.iTl; + TPoint bl = paddingRect.iTl; + bl.iY -= 1; + bl.iX -= 1; + TPoint tr = borderRect.iTl; + tr.iX += borderRect.Width()-1; + TPoint br = paddingRect.iTl; + br.iX += paddingRect.Width(); + br.iY -= 1; + CArrayFix< TPoint >* array = NULL; + array = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + TRAPD( error, + array->AppendL( tl ); + array->AppendL( tr ); + array->AppendL( br ); + array->AppendL( bl ) ); + if ( error != KErrNone ) + { + delete array; + return; + } + CXnProperty* borderTopStyle = aNode.BorderTopStyleL(); + CXnProperty* borderStyle = aNode.BorderStyleL(); + const TDesC8& borderStyleString = ( borderTopStyle ) ? + borderTopStyle->StringValue() : + ( borderStyle ) ? borderStyle->StringValue() : KNullDesC8; + if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KSolid ) + { + DrawSolidTopBorder( array, aGc ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KInset ) + { + DrawInsetTopBorder( array, aGc, rgb ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KOutset ) + { + DrawOutsetTopBorder( array, aGc, rgb ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KRidge ) + { + TRAP_IGNORE( DrawRidgeTopBorderL( array, aGc, rgb ) ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KGroove ) + { + TRAP_IGNORE( DrawGrooveTopBorderL( array, aGc, rgb ) ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KDotted ) + { + TPoint end( borderRect.iBr.iX, paddingRect.iTl.iY ); + TRect rect( borderRect.iTl, end ); + DrawDottedBorder( rect, aGc, rgb, ETrue ); + } + delete array; + } + +// ----------------------------------------------------------------------------- +// DrawSolidBottomBorder +// Draw bottom border with solid style +// ----------------------------------------------------------------------------- +// +static void DrawSolidBottomBorder( CArrayFix< TPoint >* aArray, CWindowGc& aGc ) + { + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// SplitBottomBorderPolygonL +// Split bottom border to two parts for border effect drawing +// ----------------------------------------------------------------------------- +// +static void SplitBottomBorderPolygonL( + CArrayFix< TPoint >* aArray, + CArrayFix< TPoint >*& aUpperPart, + CArrayFix< TPoint >*& aLowerPart ) + { + TPoint leftHalf = + TPoint( + ( *aArray )[3].iX + ( ( *aArray )[0].iX - ( *aArray )[3].iX ) / 2, + ( *aArray )[3].iY + ( ( *aArray )[0].iY - ( *aArray )[3].iY ) / 2); + TPoint rightHalf = + TPoint( + ( *aArray )[1].iX + ( ( *aArray )[2].iX - ( *aArray )[1].iX ) / 2, + ( *aArray )[2].iY + ( ( *aArray )[1].iY - ( *aArray )[2].iY ) / 2); + aUpperPart->AppendL( ( *aArray )[0] ); + aUpperPart->AppendL( ( *aArray )[1] ); + aUpperPart->AppendL( rightHalf ); + aUpperPart->AppendL( leftHalf ); + aLowerPart->AppendL( leftHalf ); + aLowerPart->AppendL( rightHalf ); + aLowerPart->AppendL( ( *aArray )[2] ); + aLowerPart->AppendL( ( *aArray )[3] ); + } + +// ----------------------------------------------------------------------------- +// DrawRidgeBottomBorderL +// Draw bottom border with ridge style +// ----------------------------------------------------------------------------- +// +static void DrawRidgeBottomBorderL( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + CArrayFix< TPoint >* upperPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( upperPart ); + CArrayFix< TPoint >* lowerPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( lowerPart ); + SplitBottomBorderPolygonL( aArray, upperPart, lowerPart ); + TRgb rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( upperPart ); + rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( lowerPart ); + CleanupStack::PopAndDestroy( lowerPart ); + CleanupStack::PopAndDestroy( upperPart ); + } + +// ----------------------------------------------------------------------------- +// DrawGrooveBottomBorderL +// Draw bottom border with groove style +// ----------------------------------------------------------------------------- +// +static void DrawGrooveBottomBorderL( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + CArrayFix< TPoint >* upperPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( upperPart ); + CArrayFix< TPoint >* lowerPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( lowerPart ); + SplitBottomBorderPolygonL( aArray, upperPart, lowerPart ); + TRgb rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( upperPart ); + rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( lowerPart ); + CleanupStack::PopAndDestroy( lowerPart ); + CleanupStack::PopAndDestroy( upperPart ); + } + +// ----------------------------------------------------------------------------- +// DrawInsetBottomBorder +// Draw bottom border with inset style +// ----------------------------------------------------------------------------- +// +static void DrawInsetBottomBorder( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + TRgb rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// DrawOutsetBottomBorder +// Draw bottom border with outset style +// ----------------------------------------------------------------------------- +// +static void DrawOutsetBottomBorder( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + TRgb rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// DrawDottedBorder +// Draw dotted border +// ----------------------------------------------------------------------------- +// +static void DrawDottedBorder( + TRect aBorderRect, + CWindowGc& aGc, + TRgb& aRgb, + TBool aHorizontal ) + { + TInt height( aBorderRect.Height() ); + TInt width( aBorderRect.Width() ); + + TInt squareSide( Min( height, width ) ); + + if ( !squareSide ) + { + return; + } + + // Square size 1, 2 and 3 can be drawn with pen patterns + if ( squareSide < 4 ) + { + aGc.SetBrushStyle( CGraphicsContext::ENullBrush ); + + aGc.SetPenColor( aRgb ); + + for ( TInt i = 0; i < squareSide; i++ ) + { + TPoint start; + TPoint end; + + if ( aHorizontal ) + { + start = TPoint( aBorderRect.iTl.iX, aBorderRect.iTl.iY + i ); + end = TPoint( + aBorderRect.iTl.iX + aBorderRect.Width(), + aBorderRect.iTl.iY + i ); + } + else + { + start = TPoint( aBorderRect.iTl.iX + i, aBorderRect.iTl.iY ); + end = TPoint( + aBorderRect.iTl.iX + i, + aBorderRect.iTl.iY + aBorderRect.Height() ); + } + + if ( squareSide == 3 ) + { + // dashed pen pattern 111000... + aGc.SetPenStyle( CGraphicsContext::EDashedPen ); + aGc.DrawLine( start, end ); + } + else + { + // dotted pen pattern 1000... + aGc.SetPenStyle( CGraphicsContext::EDottedPen ); + aGc.DrawLine( start, end ); + + if ( aHorizontal ) + { + start.iX += ( squareSide == 1 ) ? 2 : 1; + } + else + { + start.iY += ( squareSide == 1 ) ? 2 : 1; + } + + aGc.SetPenStyle( CGraphicsContext::EDottedPen ); + aGc.DrawLine( start, end ); + } + } + } + else + { + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetPenStyle( CGraphicsContext::ENullPen ); + + aGc.SetBrushColor( aRgb ); + + TInt divideCount( 0 ); + + if ( aHorizontal ) + { + divideCount = width / squareSide; + } + else + { + divideCount = height / squareSide; + } + + TRect drawingRect( aBorderRect.iTl, TSize( squareSide, squareSide ) ); + + // every other is drawn + TInt count( divideCount / 2 ); + + for ( TInt i = 0; i <= count; i++ ) + { + aGc.DrawRect( drawingRect ); + + if ( aHorizontal ) + { + drawingRect.Move( squareSide * 2, 0 ); + } + else + { + drawingRect.Move( 0, squareSide * 2 ); + } + } + } + } + +// ----------------------------------------------------------------------------- +// DrawBottomBorder +// Draw bottom border +// ----------------------------------------------------------------------------- +// +static void DrawBottomBorderL( + const TRect& /*aRect*/, + CXnNode& aNode, + CWindowGc& aGc ) + { + TRect borderRect = aNode.BorderRect(); + TRect paddingRect = aNode.PaddingRect(); + TRgb rgb; + if ( !GetBorderColorL( XnPropertyNames::appearance::common::KBorderBottomColor, aNode, aGc, rgb ) ) + { + return; + } + TPoint tl = paddingRect.iBr; + tl.iX -= paddingRect.Width() + 1; + TPoint bl = borderRect.iBr; + bl.iX -= borderRect.Width(); + bl.iY-= 1; + TPoint tr = paddingRect.iBr; + TPoint br = borderRect.iBr; + br.iY -= 1; + br.iX -= 1; + CArrayFix< TPoint >* array = NULL; + array = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + TRAPD( error, + array->AppendL( tl ); + array->AppendL( tr ); + array->AppendL( br ); + array->AppendL( bl ); ); + if ( error != KErrNone ) + { + delete array; + return; + } + CXnProperty* borderBottomStyle = aNode.BorderBottomStyleL(); + CXnProperty* borderStyle = aNode.BorderStyleL(); + const TDesC8& borderStyleString = ( borderBottomStyle ) ? + borderBottomStyle->StringValue() : + ( borderStyle ) ? borderStyle->StringValue() : KNullDesC8; + if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KSolid ) + { + DrawSolidBottomBorder( array, aGc ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KInset ) + { + DrawInsetBottomBorder( array, aGc, rgb ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KOutset ) + { + DrawOutsetBottomBorder( array, aGc, rgb ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KRidge ) + { + TRAP_IGNORE( DrawRidgeBottomBorderL( array, aGc, rgb ) ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KGroove ) + { + TRAP_IGNORE( DrawGrooveBottomBorderL( array, aGc, rgb ) ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KDotted ) + { + TPoint origo( borderRect.iTl.iX, paddingRect.iBr.iY ); + TRect rect( origo, borderRect.iBr ); + DrawDottedBorder( rect, aGc, rgb, ETrue ); + } + delete array; + } + +// ----------------------------------------------------------------------------- +// DrawSolidLeftBorder +// ----------------------------------------------------------------------------- +// +static void DrawSolidLeftBorder( CArrayFix< TPoint >* aArray, CWindowGc& aGc ) + { + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// SplitLeftBorderPolygonL +// ----------------------------------------------------------------------------- +// +static void SplitLeftBorderPolygonL( + CArrayFix< TPoint >* aArray, + CArrayFix< TPoint >*& aLeftPart, + CArrayFix< TPoint >*& aRightPart ) + { + TPoint upHalf = + TPoint( + ( *aArray )[0].iX + ( ( *aArray )[1].iX - ( *aArray )[0].iX ) / 2, + ( *aArray )[0].iY + ( ( *aArray )[1].iY - ( *aArray )[0].iY ) / 2); + TPoint downHalf = + TPoint( + ( *aArray )[3].iX + ( ( *aArray )[2].iX - ( *aArray )[3].iX ) / 2, + ( *aArray )[2].iY + ( ( *aArray )[3].iY - ( *aArray )[2].iY ) / 2); + aLeftPart->AppendL( ( *aArray )[0] ); + aLeftPart->AppendL( upHalf ); + aLeftPart->AppendL( downHalf ); + aLeftPart->AppendL( ( *aArray )[3] ); + + aRightPart->AppendL( upHalf ); + aRightPart->AppendL( ( *aArray )[1] ); + aRightPart->AppendL( ( *aArray )[2]) ; + aRightPart->AppendL( downHalf ); + } + +// ----------------------------------------------------------------------------- +// DrawRidgeLeftBorderL +// ----------------------------------------------------------------------------- +// +static void DrawRidgeLeftBorderL( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + CArrayFix< TPoint >* leftPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( leftPart ); + CArrayFix< TPoint >* rightPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( rightPart ); + SplitLeftBorderPolygonL( aArray, leftPart, rightPart ); + TRgb rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( leftPart ); + rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( rightPart ); + CleanupStack::PopAndDestroy( rightPart ); + CleanupStack::PopAndDestroy( leftPart ); + } + +// ----------------------------------------------------------------------------- +// DrawGrooveLeftBorderL +// ----------------------------------------------------------------------------- +// +static void DrawGrooveLeftBorderL( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + CArrayFix< TPoint >* leftPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( leftPart ); + CArrayFix< TPoint >* rightPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( rightPart ); + SplitLeftBorderPolygonL( aArray, leftPart, rightPart ); + TRgb rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( leftPart ); + rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( rightPart ); + CleanupStack::PopAndDestroy( rightPart ); + CleanupStack::PopAndDestroy( leftPart ); + } + +// ----------------------------------------------------------------------------- +// DrawInsetLeftBorder +// ----------------------------------------------------------------------------- +// +static void DrawInsetLeftBorder( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + TRgb rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// DrawOutsetLeftBorder +// ----------------------------------------------------------------------------- +// +static void DrawOutsetLeftBorder( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + TRgb rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// DrawLeftBorderL +// ----------------------------------------------------------------------------- +// +static void DrawLeftBorderL( + const TRect& /*aRect*/, + CXnNode& aNode, + CWindowGc& aGc ) + { + TRect borderRect = aNode.BorderRect(); + TRect paddingRect = aNode.PaddingRect(); + TRgb rgb; + if ( !GetBorderColorL( XnPropertyNames::appearance::common::KBorderLeftColor, aNode, aGc, rgb ) ) + { + return; + } + TPoint tl = borderRect.iTl; + TPoint bl = borderRect.iBr; + bl.iX -= borderRect.Width(); + TPoint tr = paddingRect.iTl; + tr.iX -= 1; + tr.iY -= 1; + TPoint br = paddingRect.iBr; + br.iX -= paddingRect.Width() + 1; + CArrayFix< TPoint >* array = NULL; + array = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + TRAPD( error, + array->AppendL( tl ); + array->AppendL( tr ); + array->AppendL( br ); + array->AppendL( bl ); ); + if ( error != KErrNone ) + { + delete array; + return; + } + CXnProperty* borderLeftStyle = aNode.BorderLeftStyleL(); + CXnProperty* borderStyle = aNode.BorderStyleL(); + const TDesC8& borderStyleString = ( borderLeftStyle ) ? + borderLeftStyle->StringValue() : + ( borderStyle ) ? borderStyle->StringValue() : KNullDesC8; + if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KSolid ) + { + DrawSolidLeftBorder( array, aGc ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KInset ) + { + DrawInsetLeftBorder( array, aGc, rgb ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KOutset ) + { + DrawOutsetLeftBorder( array, aGc, rgb ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KRidge ) + { + TRAP_IGNORE( DrawRidgeLeftBorderL( array, aGc, rgb ) ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KGroove ) + { + TRAP_IGNORE( DrawGrooveLeftBorderL( array, aGc, rgb ) ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KDotted ) + { + TPoint origo( borderRect.iTl.iX, paddingRect.iTl.iY ); + TPoint end( paddingRect.iTl.iX, paddingRect.iBr.iY ); + TRect rect( origo, end ); + DrawDottedBorder( rect, aGc, rgb, EFalse ); + } + delete array; + } + +// ----------------------------------------------------------------------------- +// DrawSolidRightBorder +// ----------------------------------------------------------------------------- +// +static void DrawSolidRightBorder( CArrayFix< TPoint >* aArray, CWindowGc& aGc ) + { + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// SplitRightBorderPolygonL +// ----------------------------------------------------------------------------- +// +static void SplitRightBorderPolygonL( + CArrayFix< TPoint >* aArray, + CArrayFix< TPoint >*& aLeftPart, + CArrayFix< TPoint >*& aRightPart ) + { + TPoint upHalf = + TPoint( + ( *aArray )[0].iX + ( ( *aArray )[1].iX - ( *aArray )[0].iX ) / 2, + ( *aArray )[1].iY + ( ( *aArray )[0].iY - ( *aArray )[1].iY ) / 2); + TPoint downHalf = + TPoint( + ( *aArray )[3].iX + ( ( *aArray )[2].iX - ( *aArray )[3].iX ) / 2, + ( *aArray )[3].iY + ( ( *aArray )[2].iY - ( *aArray )[3].iY ) / 2); + aLeftPart->AppendL( ( *aArray )[0] ); + aLeftPart->AppendL( upHalf ); + aLeftPart->AppendL( downHalf ); + aLeftPart->AppendL( ( *aArray )[3] ); + + aRightPart->AppendL( upHalf ); + aRightPart->AppendL( ( *aArray )[1] ); + aRightPart->AppendL( ( *aArray )[2]) ; + aRightPart->AppendL( downHalf ); + } + +// ----------------------------------------------------------------------------- +// DrawRidgeRightBorderL +// ----------------------------------------------------------------------------- +// +static void DrawRidgeRightBorderL( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + CArrayFix< TPoint >* leftPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( leftPart ); + CArrayFix< TPoint >* rightPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( rightPart ); + SplitRightBorderPolygonL( aArray, leftPart, rightPart ); + TRgb rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( leftPart ); + rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( rightPart ); + CleanupStack::PopAndDestroy( rightPart ); + CleanupStack::PopAndDestroy( leftPart ); + } + +// ----------------------------------------------------------------------------- +// DrawGrooveRightBorderL +// ----------------------------------------------------------------------------- +// +static void DrawGrooveRightBorderL( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + CArrayFix< TPoint >* leftPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( leftPart ); + CArrayFix< TPoint >* rightPart = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + CleanupStack::PushL( rightPart ); + SplitRightBorderPolygonL( aArray, leftPart, rightPart ); + TRgb rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( leftPart ); + rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( rightPart ); + CleanupStack::PopAndDestroy( rightPart ); + CleanupStack::PopAndDestroy( leftPart ); + } + +// ----------------------------------------------------------------------------- +// DrawInsetRightBorder +// ----------------------------------------------------------------------------- +// +static void DrawInsetRightBorder( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + TRgb rgb = LighterColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// DrawOutsetRightBorder +// ----------------------------------------------------------------------------- +// +static void DrawOutsetRightBorder( + CArrayFix< TPoint >* aArray, + CWindowGc& aGc, + TRgb& aRgb ) + { + TRgb rgb = DarkerColor( aRgb ); + aGc.SetPenColor( rgb ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( rgb ); + aGc.DrawPolygon( aArray ); + } + +// ----------------------------------------------------------------------------- +// DrawRightBorderL +// ----------------------------------------------------------------------------- +// +static void DrawRightBorderL( + const TRect& /*aRect*/, + CXnNode& aNode, + CWindowGc& aGc ) + { + TRect borderRect = aNode.BorderRect(); + TRect paddingRect = aNode.PaddingRect(); + TRgb rgb; + if ( !GetBorderColorL( XnPropertyNames::appearance::common::KBorderRightColor, aNode, aGc, rgb ) ) + { + return; + } + TPoint tl = paddingRect.iTl; + tl.iX += paddingRect.Width(); + TPoint bl = paddingRect.iBr; + TPoint tr = borderRect.iTl; + tr.iX += borderRect.Width()-1; + TPoint br = borderRect.iBr; + br.iX -= 1; + br.iY -= 1; + CArrayFix< TPoint >* array = NULL; + array = new ( ELeave ) CArrayFixFlat< TPoint >( 3 ); + TRAPD( error, + array->AppendL( tl ); + array->AppendL( tr ); + array->AppendL( br ); + array->AppendL( bl ); ); + if ( error != KErrNone ) + { + delete array; + return; + } + CXnProperty* borderRightStyle = aNode.BorderRightStyleL(); + CXnProperty* borderStyle = aNode.BorderStyleL(); + const TDesC8& borderStyleString = ( borderRightStyle ) ? + borderRightStyle->StringValue() : + ( borderStyle ) ? borderStyle->StringValue() : KNullDesC8; + if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KSolid ) + { + DrawSolidRightBorder( array, aGc ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KInset ) + { + DrawInsetRightBorder( array, aGc, rgb ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KOutset ) + { + DrawOutsetRightBorder( array, aGc, rgb ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KRidge ) + { + TRAP_IGNORE( DrawRidgeRightBorderL( array, aGc, rgb ) ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KGroove ) + { + TRAP_IGNORE( DrawGrooveRightBorderL( array, aGc, rgb ) ); + } + else if ( borderStyleString == XnPropertyNames::appearance::common::borderstyle::KDotted ) + { + TPoint origo( paddingRect.iBr.iX, paddingRect.iTl.iY ); + TPoint end( borderRect.iBr.iX, paddingRect.iBr.iY ); + TRect rect( origo, end ); + DrawDottedBorder( rect, aGc, rgb, EFalse ); + } + delete array; + } + +// ----------------------------------------------------------------------------- +// DrawBorderImagesL +// ----------------------------------------------------------------------------- +// +static void DrawBorderImagesL( + const TRect& /*aRect*/, + CXnNode& aNode, + CWindowGc& aGc, + CFbsBitmap* aBitmap, + TInt aBorderBitmapDividerTop, + TInt aBorderBitmapDividerRight, + TInt aBorderBitmapDividerBottom, + TInt aBorderBitmapDividerLeft ) + { + CXnProperty* pathProperty = aNode.BorderImageL(); + if ( !pathProperty ) + { + return; + } + TRect borderRect = aNode.BorderRect(); + TRect paddingRect = aNode.PaddingRect(); + TRect topLeft = TRect( borderRect.iTl, paddingRect.iTl ); + TRect topLeftSource = TRect( + TPoint( 0, 0 ), + TPoint( aBorderBitmapDividerLeft, aBorderBitmapDividerTop ) ); + aGc.DrawBitmap( topLeft, aBitmap, topLeftSource ); + TRect bottomLeft = TRect( + TPoint( borderRect.iTl.iX, paddingRect.iTl.iY + paddingRect.Height() ), + TPoint( paddingRect.iTl.iX, borderRect.iTl.iY + borderRect.Height() ) ); + TSize imageSize = aBitmap->SizeInPixels(); + TRect bottomLeftSource = TRect( + TPoint( 0, imageSize.iHeight - aBorderBitmapDividerBottom ), + TPoint( aBorderBitmapDividerLeft, imageSize.iHeight ) ); + aGc.DrawBitmap( bottomLeft, aBitmap, bottomLeftSource ); + TRect topRight = TRect( + TPoint( paddingRect.iBr.iX, borderRect.iTl.iY ), + TPoint( borderRect.iBr.iX, paddingRect.iTl.iY ) ); + TRect topRightSource = TRect( + TPoint( imageSize.iWidth - aBorderBitmapDividerRight, 0 ), + TPoint( imageSize.iWidth, aBorderBitmapDividerTop ) ); + aGc.DrawBitmap( topRight, aBitmap, topRightSource ); + TRect bottomRight = TRect( paddingRect.iBr, borderRect.iBr ); + TRect bottomRightSource = TRect( + TPoint( + imageSize.iWidth - aBorderBitmapDividerRight, + imageSize.iHeight - aBorderBitmapDividerBottom ), + TPoint( + imageSize.iWidth, + imageSize.iHeight ) ); + aGc.DrawBitmap( bottomRight, aBitmap, bottomRightSource ); + TBool xStretch = ETrue; + TBool xRepeat = EFalse; + TBool xRound = EFalse; + TBool yStretch = ETrue; + TBool yRepeat = EFalse; + TBool yRound = EFalse; + if ( pathProperty ) + { + CXnDomList& propertyValueList = pathProperty->Property()->PropertyValueList(); + TBool xHandled = EFalse; + TInt count = propertyValueList.Length(); + for ( TInt i = 0; i < count; ++i ) + { + CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( + propertyValueList.Item( i ) ); + if ( value->PrimitiveValueType() == CXnDomPropertyValue::EString || + value->PrimitiveValueType() == CXnDomPropertyValue::EIdent ) + { + const TDesC8& stringValue = value->StringValueL(); + if ( !xHandled ) + { + xHandled = ETrue; + if ( stringValue == XnPropertyNames::appearance::common::borderimage::KStretch ) + { + xStretch = ETrue; + yStretch = ETrue; + } + else if ( stringValue == XnPropertyNames::appearance::common::borderimage::KRepeat ) + { + xStretch = EFalse; + yStretch = EFalse; + xRepeat = ETrue; + yRepeat = ETrue; + } + else if ( stringValue == XnPropertyNames::appearance::common::borderimage::KRound ) + { + xStretch = EFalse; + yStretch = EFalse; + xRound = ETrue; + yRound = ETrue; + } + } + else + { + if ( stringValue == XnPropertyNames::appearance::common::borderimage::KStretch ) + { + yStretch = ETrue; + yRepeat = EFalse; + yRound = EFalse; + } + else if ( stringValue == XnPropertyNames::appearance::common::borderimage::KRepeat ) + { + yStretch = EFalse; + yRepeat = ETrue; + yRound = EFalse; + } + else if ( stringValue == XnPropertyNames::appearance::common::borderimage::KRound ) + { + yStretch = EFalse; + yRepeat = EFalse; + yRound = ETrue; + } + } + } + } + } + TRect top = TRect( + TPoint( paddingRect.iTl.iX, borderRect.iTl.iY ), + TPoint( paddingRect.iBr.iX, paddingRect.iTl.iY ) ); + TRect topSource = TRect( + TPoint( aBorderBitmapDividerLeft, 0 ), + TPoint( imageSize.iWidth - aBorderBitmapDividerRight, aBorderBitmapDividerTop ) ); + if ( xStretch ) + { + aGc.DrawBitmap( top, aBitmap, topSource ); + } + else if ( xRepeat && topSource.Width() ) + { + TInt count = top.Width() / topSource.Width(); + TInt topWidth = top.Width(); + top.SetWidth( topSource.Width() ); + for ( TInt i = 0; i < count; ++i ) + { + aGc.DrawBitmap( top, aBitmap, topSource ); + top.Move( topSource.Width(), 0 ); + } + top.SetWidth( topWidth - count * topSource.Width() ); + aGc.DrawBitmap( top, aBitmap, topSource ); + } + else if ( xRound && topSource.Width() ) + { + TInt count = top.Width() / topSource.Width(); + TInt topWidth = top.Width(); + //top.Move((topWidth - count * topSource.Width()) / 2, 0); + if ( ( count * topSource.Width() ) < topWidth ) + { + ++count; + top.SetWidth( topWidth / count ); + } + else + { + top.SetWidth( topSource.Width() ); + } + for ( TInt i = 0; i < count; ++i ) + { + aGc.DrawBitmap( top, aBitmap, topSource ); + top.Move( top.Width(), 0 ); + } + } + TRect right = TRect( + TPoint( paddingRect.iBr.iX, paddingRect.iTl.iY ), + TPoint( borderRect.iBr.iX, paddingRect.iBr.iY ) ); + TRect rightSource = TRect( + TPoint( imageSize.iWidth - aBorderBitmapDividerRight, aBorderBitmapDividerTop ), + TPoint( imageSize.iWidth, imageSize.iHeight - aBorderBitmapDividerBottom ) ); + if ( yStretch ) + { + aGc.DrawBitmap( right, aBitmap, rightSource ); + } + else if ( yRepeat && rightSource.Height() ) + { + TInt count = right.Height() / rightSource.Height(); + TInt rightHeight = right.Height(); + right.SetHeight( rightSource.Height() ); + for ( TInt i = 0; i < count; ++i ) + { + aGc.DrawBitmap( right, aBitmap, rightSource ); + right.Move( 0, rightSource.Height() ); + } + right.SetHeight( rightHeight - count * rightSource.Height() ); + aGc.DrawBitmap( right, aBitmap, rightSource ); + } + else if ( yRound && rightSource.Height() ) + { + TInt count = right.Height() / rightSource.Height(); + TInt rightHeight = right.Height(); + if ( ( count * rightSource.Height() ) < rightHeight ) + { + ++count; + right.SetHeight( rightHeight / count ); + } + else + { + right.SetHeight( rightSource.Width() ); + } + for ( TInt i = 0; i < count; ++i ) + { + aGc.DrawBitmap( right, aBitmap, rightSource ); + right.Move( 0, right.Height() ); + } + } + TRect bottom = TRect( + TPoint( paddingRect.iTl.iX, paddingRect.iBr.iY ), + TPoint( paddingRect.iBr.iX, borderRect.iBr.iY ) ); + TRect bottomSource = TRect( + TPoint( aBorderBitmapDividerLeft, imageSize.iHeight - aBorderBitmapDividerBottom ), + TPoint( imageSize.iWidth - aBorderBitmapDividerRight, imageSize.iHeight ) ); + if ( xStretch ) + { + aGc.DrawBitmap( bottom, aBitmap, bottomSource ); + } + else if ( xRepeat && bottomSource.Width() ) + { + TInt count = bottom.Width() / bottomSource.Width(); + TInt bottomWidth = bottom.Width(); + bottom.SetWidth( bottomSource.Width() ); + for ( TInt i = 0; i < count; ++i ) + { + aGc.DrawBitmap( bottom, aBitmap, bottomSource ); + bottom.Move( bottomSource.Width(), 0 ); + } + bottom.SetWidth( bottomWidth - count * bottomSource.Width() ); + aGc.DrawBitmap( bottom, aBitmap, bottomSource ); + } + else if ( xRound && bottomSource.Width() ) + { + TInt count = bottom.Width() / bottomSource.Width(); + TInt bottomWidth = bottom.Width(); + if ( ( count * bottomSource.Width() ) < bottomWidth ) + { + ++count; + bottom.SetWidth( bottomWidth / count ); + } + else + { + bottom.SetWidth( bottomSource.Width() ); + } + for ( TInt i = 0; i < count; ++i ) + { + aGc.DrawBitmap( bottom, aBitmap, bottomSource ); + bottom.Move( bottom.Width(), 0 ); + } + } + TRect left = TRect( + TPoint( borderRect.iTl.iX, paddingRect.iTl.iY ), + TPoint( paddingRect.iTl.iX, paddingRect.iBr.iY ) ); + TRect leftSource = TRect( + TPoint( 0, aBorderBitmapDividerTop ), + TPoint( aBorderBitmapDividerLeft, imageSize.iHeight - aBorderBitmapDividerBottom ) ); + if ( yStretch ) + { + aGc.DrawBitmap( left, aBitmap, leftSource ); + } + else if ( yRepeat && leftSource.Height() ) + { + TInt count = left.Height() / leftSource.Height(); + TInt leftHeight = left.Height(); + left.SetHeight( leftSource.Height() ); + for ( TInt i = 0; i < count; ++i ) + { + aGc.DrawBitmap( left, aBitmap, leftSource ); + left.Move( 0, leftSource.Height() ); + } + left.SetHeight( leftHeight - count * leftSource.Height() ); + aGc.DrawBitmap( left, aBitmap, leftSource ); + } + else if ( yRound && leftSource.Height() ) + { + TInt count = left.Height() / leftSource.Height(); + TInt leftHeight = left.Height(); + if ( ( count * leftSource.Height() ) < leftHeight ) + { + ++count; + left.SetHeight( leftHeight / count ); + } + else + { + left.SetHeight( leftSource.Width() ); + } + for ( TInt i = 0; i < count; ++i ) + { + aGc.DrawBitmap( left, aBitmap, leftSource ); + left.Move( 0, left.Height() ); + } + } + } + +// ----------------------------------------------------------------------------- +// IsPropertyNone +// ----------------------------------------------------------------------------- +// +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; + } + +// ----------------------------------------------------------------------------- +// DrawBordersL +// ----------------------------------------------------------------------------- +// +static void DrawBordersL( const TRect& aRect, CXnNode& aNode, CWindowGc& aGc ) + { + TRect borderRect( aNode.BorderRect() ); + + if( aNode.PaddingRect() == borderRect ) + { + return; + } + + CXnProperty* commonBorderStyle( aNode.BorderStyleL() ); + CXnProperty* borderStyle( aNode.BorderTopStyleL() ); + + if ( ( borderStyle && !IsPropertyNone( *borderStyle ) ) || + ( commonBorderStyle && !IsPropertyNone( *commonBorderStyle ) ) ) + { + DrawTopBorderL( aRect, aNode, aGc ); + } + + borderStyle = aNode.BorderLeftStyleL(); + + if ( ( borderStyle && !IsPropertyNone( *borderStyle ) ) || + ( commonBorderStyle && !IsPropertyNone( *commonBorderStyle ) ) ) + { + DrawLeftBorderL( aRect, aNode, aGc ); + } + + borderStyle = aNode.BorderRightStyleL(); + + if ( ( borderStyle && !IsPropertyNone( *borderStyle ) ) || + ( commonBorderStyle && !IsPropertyNone( *commonBorderStyle ) ) ) + { + DrawRightBorderL( aRect, aNode, aGc ); + } + + borderStyle = aNode.BorderBottomStyleL(); + + if ( ( borderStyle && !IsPropertyNone( *borderStyle ) ) || + ( commonBorderStyle && !IsPropertyNone( *commonBorderStyle ) ) ) + { + DrawBottomBorderL( aRect, aNode, aGc ); + } + } + +// ----------------------------------------------------------------------------- +// SwapChildArrays +// ----------------------------------------------------------------------------- +// +static void SwapChildArrays( + RPointerArray< CXnControlAdapter >& originalArray, + RPointerArray< CXnControlAdapter >& sortedArray ) + { + originalArray.Reset(); + TInt count = sortedArray.Count(); + for ( TInt i = 0; i < count; ++i ) + { + originalArray.Append( sortedArray[i] ); + } + sortedArray.Reset(); + } + +// ----------------------------------------------------------------------------- +// IsChildZIndexLowerThanCandidateZIndexL +// ----------------------------------------------------------------------------- +// +static TBool IsChildZIndexLowerThanCandidateZIndexL( + CXnProperty* aChildZIndex, + CXnDomPropertyValue* aChildZIndexValue, + CXnProperty* aCandidateZIndex ) + { + if ( !aChildZIndex && !aCandidateZIndex ) + { + return ETrue; + } + if ( !aChildZIndex ) + { + CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( + aCandidateZIndex->Property()->PropertyValueList().Item( 0 ) ); + if ( value->IsAutoIdent() ) + { + return ETrue; + } + TReal num = value->FloatValueL(); + if ( num > 0 ) + { + return ETrue; + } + } + else if ( !aCandidateZIndex ) + { + if ( aChildZIndexValue->IsAutoIdent() ) + { + return ETrue; + } + TReal num = aChildZIndexValue->FloatValueL(); + if ( num < 0 ) + { + return ETrue; + } + } + else + { + CXnDomPropertyValue* candidateValue = + static_cast< CXnDomPropertyValue* >( + aCandidateZIndex->Property()->PropertyValueList().Item( 0 ) ); + if ( aChildZIndexValue->IsAutoIdent() && candidateValue->IsAutoIdent() ) + { + return ETrue; + } + else if ( aChildZIndexValue->IsAutoIdent() && !candidateValue->IsAutoIdent() ) + { + return ETrue; + } + else if ( !aChildZIndexValue->IsAutoIdent() && candidateValue->IsAutoIdent() ) + { + return EFalse; + } + TReal childNum = aChildZIndexValue->FloatValueL(); + TReal candidateNum = candidateValue->FloatValueL(); + if ( childNum <= candidateNum ) + { + return ETrue; + } + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// GetZIndex +// ----------------------------------------------------------------------------- +// +static CXnProperty* GetZIndexL( CXnControlAdapter* aAdapter ) + { + CXnComponent* component = aAdapter->Component(); + if ( !component ) + { + return NULL; + } + CXnNode& node = component->Node()->Node(); + return node.ZIndexL(); + } + +// ----------------------------------------------------------------------------- +// InsertChildToSortedArrayL +// ----------------------------------------------------------------------------- +// +static void InsertChildToSortedArrayL( + RPointerArray< CXnControlAdapter >& aTargetArray, + CXnControlAdapter* aChild ) + { + CXnProperty* childZIndex = GetZIndexL( aChild ); + CXnDomPropertyValue* childValue = NULL; + if ( childZIndex ) + { + childValue = static_cast< CXnDomPropertyValue* >( + childZIndex->Property()->PropertyValueList().Item( 0 ) ); + } + TInt count = aTargetArray.Count(); + for ( TInt i = 0; i < count; ++i ) + { + CXnControlAdapter* candidate = aTargetArray[i]; + if ( IsChildZIndexLowerThanCandidateZIndexL( + childZIndex, childValue, GetZIndexL( candidate ) ) ) + { + aTargetArray.Insert( aChild, i ); + return; + } + } + aTargetArray.Append( aChild ); + } + +// ----------------------------------------------------------------------------- +// InitializeBackgroundBitmapL +// ----------------------------------------------------------------------------- +// +static void InitializeBackgroundBitmapL( CXnUiEngine& aEngine, CXnNode& aNode, + TInt& aBitmapIndex, CFbsBitmap*& aBitmap, CFbsBitmap*& aMask, + CXnControlAdapterImpl::TIconProvider*& aIconProvider, RFs& aFsSession ) + { + HBufC* bgPath( GetBackgroundImagePathLC( aNode ) ); + TPtr ptr( bgPath->Des() ); + + GetBitmapL( aEngine, aNode, ptr, aBitmapIndex, + aBitmap, aMask, aIconProvider, aNode.PaddingRect(), aFsSession ); + + CleanupStack::PopAndDestroy( bgPath ); + + if ( !aMask ) + { + HBufC* bgMaskPath( GetBackgroundImageMaskPathLC( aNode ) ); + TPtr ptr( bgMaskPath->Des() ); + + if ( ptr != KNullDesC ) + { + CFbsBitmap* tmpMask( NULL ); + + TRAP_IGNORE( GetBitmapL( aEngine, aNode, ptr, aBitmapIndex, aMask, + tmpMask, aIconProvider, aNode.PaddingRect(), aFsSession ) ); + + delete tmpMask; + } + + CleanupStack::PopAndDestroy( bgMaskPath ); + } + } + +// ----------------------------------------------------------------------------- +// GetBackgroundImagePathLC +// ----------------------------------------------------------------------------- +// +static HBufC* GetBackgroundImagePathLC( CXnNode& aNode ) + { + CXnProperty* pathProperty( aNode.BackgroundImageL() ); + + if ( pathProperty && pathProperty->StringValue() != KNullDesC8 ) + { + HBufC* path( pathProperty->StringValueL() ); + CleanupStack::PushL( path ); + + CXnUtils::StripQuotes( path ); + + return path; + } + + return KNullDesC().AllocLC(); + } + +// ----------------------------------------------------------------------------- +// GetBackgroundImageMaskPathLC +// ----------------------------------------------------------------------------- +// +static HBufC* GetBackgroundImageMaskPathLC( CXnNode& aNode ) + { + CXnProperty* pathProperty( aNode.GetPropertyL( + XnPropertyNames::common::KBackgroundMask ) ); + + if ( pathProperty && pathProperty->StringValue() != KNullDesC8 ) + { + HBufC* path( pathProperty->StringValueL() ); + CleanupStack::PushL( path ); + + CXnUtils::StripQuotes( path ); + + return path; + } + + return KNullDesC().AllocLC(); + } + +// ----------------------------------------------------------------------------- +// InitializeBorderBitmapL +// ----------------------------------------------------------------------------- +// +static CFbsBitmap* InitializeBorderBitmapL( + CXnUiEngine& aEngine, + CXnNode& aNode, + TInt& aBitmapIndex, + TInt& aBorderBitmapDividerTop, + TInt& aBorderBitmapDividerRight, + TInt& aBorderBitmapDividerBottom, + TInt& aBorderBitmapDividerLeft, + CXnControlAdapterImpl::TIconProvider*& aIconProvider, + RFs& aFsSession ) + { + CXnProperty* pathProperty = aNode.BorderImageL(); + CFbsBitmap* returnValue = NULL; + CFbsBitmap* bitmapMask = NULL; + + CXnDomList& propertyValueList = pathProperty->Property()->PropertyValueList(); + TInt count = propertyValueList.Length(); + + for ( TInt i = 0; i < propertyValueList.Length(); ++i ) + { + CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( + propertyValueList.Item( i ) ); + + if ( value->PrimitiveValueType() == CXnDomPropertyValue::EUri ) + { + const TDesC8& path = value->StringValueL(); + + HBufC* utfPath = HBufC::NewL( path.Length() ); + TPtr16 ptr = utfPath->Des(); + + CnvUtfConverter::ConvertToUnicodeFromUtf8( ptr, path ); + CleanupStack::PushL( utfPath ); + + StripQuotes( utfPath ); + + GetBitmapL( aEngine, aNode, *utfPath, aBitmapIndex, returnValue, + bitmapMask, aIconProvider, aNode.BorderRect(), aFsSession ); + + delete bitmapMask; + + CleanupStack::PopAndDestroy( utfPath ); + } + else if ( value->PrimitiveValueType() == CXnDomPropertyValue::EPercentage ) + { + CXnDomPropertyValue* tmpValue = NULL; + tmpValue = value->CloneL(); + CXnProperty* tmpProperty = NULL; + CleanupStack::PushL( tmpValue ); + tmpProperty = CXnProperty::NewL( + KNullDesC8, + tmpValue, + aNode.UiEngine()->ODT()->DomDocument().StringPool() ); + CleanupStack::Pop( tmpValue ); + TSize imageSize = returnValue->SizeInPixels(); + CleanupStack::PushL( tmpProperty ); + TInt intValue = static_cast< TInt >( value->FloatValueL() ); + TInt dividerValue = 0; + + switch ( i ) + { + case 1: + { + dividerValue = aNode.UiEngine()->VerticalPixelValueL( + tmpProperty, imageSize.iHeight ); + aBorderBitmapDividerTop = dividerValue; + break; + } + case 2: + { + dividerValue = aNode.UiEngine()->HorizontalPixelValueL( + tmpProperty, imageSize.iWidth ); + aBorderBitmapDividerRight = dividerValue; + break; + } + case 3: + { + dividerValue = aNode.UiEngine()->VerticalPixelValueL( + tmpProperty, imageSize.iHeight ); + aBorderBitmapDividerBottom = dividerValue; + break; + } + case 4: + { + dividerValue = aNode.UiEngine()->HorizontalPixelValueL( + tmpProperty, imageSize.iWidth ); + aBorderBitmapDividerLeft = dividerValue; + break; + } + } + + CleanupStack::PopAndDestroy( tmpProperty ); + } + else if ( value->PrimitiveValueType() == CXnDomPropertyValue::EString || + value->PrimitiveValueType() == CXnDomPropertyValue::EIdent ) + { + } + else + { + TInt intValue = static_cast< TInt >( value->FloatValueL() ); + + switch ( i ) + { + case 1: + { + aBorderBitmapDividerTop = intValue; + break; + } + case 2: + { + aBorderBitmapDividerRight = intValue; + break; + } + case 3: + { + aBorderBitmapDividerBottom = intValue; + break; + } + case 4: + { + aBorderBitmapDividerLeft = intValue; + break; + } + } + } + } + + return returnValue; + } + +// ----------------------------------------------------------------------------- +// BuildTriggerTypeNodeL +// ----------------------------------------------------------------------------- +// +static CXnNode* BuildTriggerTypeNodeL( const TDesC8& aName, + const TDesC8& aValue, CXnUiEngine& aUiEngine ) + { + CXnNode* node = CXnNode::NewL(); + CleanupStack::PushL( node ); + CXnType* type = CXnType::NewL( XnPropertyNames::action::KProperty ); + 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, aName ); + CXnProperty* name = CXnProperty::NewL( XnPropertyNames::action::KName, + nameValue, aUiEngine.ODT()->DomDocument().StringPool() ); + CleanupStack::Pop( nameValue ); + CleanupStack::PushL( name ); + node->SetPropertyL( name ); + CleanupStack::Pop( name ); + CXnDomPropertyValue* valueValue = CXnDomPropertyValue::NewL( + aUiEngine.ODT()->DomDocument().StringPool() ); + CleanupStack::PushL( valueValue ); + valueValue->SetStringValueL( CXnDomPropertyValue::EString, aValue ); + CXnProperty* value = CXnProperty::NewL( XnPropertyNames::action::KValue, + valueValue, aUiEngine.ODT()->DomDocument().StringPool() ); + CleanupStack::Pop( valueValue ); + CleanupStack::PushL( value ); + node->SetPropertyL( value ); + CleanupStack::Pop( value ); + CleanupStack::Pop( node ); + return node; + } + +// ----------------------------------------------------------------------------- +// BuildTriggerNodeL +// Builds a trigger node +// ----------------------------------------------------------------------------- +// +static CXnNode* BuildTriggerNodeL( + CXnUiEngine& aUiEngine, + const TDesC8& aTriggerName, + const TDesC8& aTriggerValueName, + const TDesC8& aTriggerValue ) + { + 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 ); + CXnNode* triggerType = BuildTriggerTypeNodeL( aTriggerValueName, + aTriggerValue, aUiEngine ); + CleanupStack::PushL( triggerType ); + node->AddChildL( triggerType ); + CleanupStack::Pop( triggerType ); + CleanupStack::Pop( node ); + return node; + } + +// ----------------------------------------------------------------------------- +// BuildTriggerNodeL +// Builds a trigger node +// ----------------------------------------------------------------------------- +// +static CXnNode* BuildTriggerNodeL( + 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; + } + +// ----------------------------------------------------------------------------- +// Create scaled bitmap from source bitmap. +// ----------------------------------------------------------------------------- +// +void CreateScaledBitmapL( + const TRect& aRect, + CFbsBitmap*& aTrgBitmap, + CFbsBitmap* aSrcBitmap, + TBool aPreserveAspectRatio, + TBool aForceFallBack ) + { + TRect destRect = aRect; + + if ( aPreserveAspectRatio ) + { + // Calculate the bitmap image dimensions so that it uses maximum space + // of the given rectangle and maintains aspect ratio. + TInt srcHeight = aSrcBitmap->SizeInPixels().iHeight; + TInt srcWidth = aSrcBitmap->SizeInPixels().iWidth; + TReal scaleRatio( 1 ); //no scale as defaul + + //If any dimension is 0, then we do not bother to scale + if ( aRect.Width() > 0 && aRect.Height() > 0 ) + { + TReal xRatio = ( ( TReal )srcWidth / ( TReal )aRect.Width() ); + TReal yRatio = ( ( TReal )srcHeight / ( TReal )aRect.Height() ); + //Find out appropriate scaling factor + xRatio > yRatio ? ( scaleRatio = xRatio ) : ( scaleRatio = yRatio ); + } + + //Scale the size for target bitmap + destRect.SetHeight( srcHeight / scaleRatio ); + destRect.SetWidth( srcWidth / scaleRatio ); + } + + // see if there's a need to scale. If source and destination size are the same, + // then we don't need to duplicate the bitmap. aTrgBitmap will be null. + TSize srcSize = aSrcBitmap->SizeInPixels(); + TSize destSize = destRect.Size(); + if ( srcSize == destSize ) + { + return; + } + + aTrgBitmap = new ( ELeave ) CFbsBitmap; + CleanupStack::PushL( aTrgBitmap ); + //It is allowed to create zero height or width bitmap. + TInt err( aTrgBitmap->Create( destRect.Size(), aSrcBitmap->DisplayMode() ) ); + + if ( err == KErrNone ) + { + CXnUtils::ScaleBitmapExtL( destRect, aTrgBitmap, aSrcBitmap, aForceFallBack ); + } + + //we do not own the bitmap so just Pop. + CleanupStack::Pop( aTrgBitmap ); + } + +// ----------------------------------------------------------------------------- +// SoftkeyNode +// Gets the node of softkey according to index +// ----------------------------------------------------------------------------- +// +static CXnNode* SoftkeyNodeL( CXnNode* aMenuBarNode, const TDesC8& aSoftkey ) + { + if ( aMenuBarNode ) + { + XnMenuInterface::MXnMenuInterface* menuIf( NULL ); + XnComponentInterface::MakeInterfaceL( menuIf, aMenuBarNode->AppIfL() ); + CXnNodePluginIf* skNode( NULL ); + if ( menuIf ) + { + if ( aSoftkey == XnPropertyNames::softkey::type::KLeft ) + { + skNode = menuIf->SoftKeyL( + XnMenuInterface::MXnMenuInterface::ELeft ); + } + else if ( aSoftkey == XnPropertyNames::softkey::type::KMiddle ) + { + skNode = menuIf->SoftKeyL( + XnMenuInterface::MXnMenuInterface::ECenter ); + } + else if ( aSoftkey == XnPropertyNames::softkey::type::KRight ) + { + skNode = menuIf->SoftKeyL( + XnMenuInterface::MXnMenuInterface::ERight ); + } + } + if ( skNode ) + { + return &skNode->Node(); + } + } + return NULL; + } + +// ----------------------------------------------------------------------------- +// SoftkeyNode +// Gets the node of softkey according to pointer location +// ----------------------------------------------------------------------------- +// +static CXnNode* SoftkeyNode( CXnNode* aMenuBarNode, const TPoint aPosition ) + { + if ( aMenuBarNode ) + { + CXnMenuAdapter* adapter = static_cast< CXnMenuAdapter* >( + aMenuBarNode->ComponentNodeImpl()->Component()->ControlAdapter() ); + + CXnNodePluginIf* node( NULL ); + + if ( adapter->FindSoftKeyNodeByPosition( aPosition, node ) ) + { + return &node->Node(); + } + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// DrawFocusAppearance +// Draws focus appearance +// ----------------------------------------------------------------------------- +// +static void DrawFocusAppearance( CXnNode& aNode, CWindowGc& aGc ) + { + TBool grow( EFalse ); + + const TDesC8& name( aNode.DomNode()->Name() ); + + if( name == XnPropertyNames::KPlugin ) + { + grow = ETrue; + } + else + { + TRect marginRect( aNode.MarginRect() ); + + CXnNode* parent( aNode.Parent() ); + + for( ; parent; parent = parent->Parent() ) + { + if( parent->DomNode()->Name() == XnPropertyNames::KPlugin ) + { + if( parent->Rect() == marginRect ) + { + grow = ETrue; + } + + break; + } + } + } + + TRect rect( aNode.PaddingRect() ); + + if( grow ) + { + rect.Grow( KFocusGrowValue, KFocusGrowValue ); + } + + CXnAppUiAdapter* appui( + static_cast< CXnAppUiAdapter* >( iAvkonAppUi ) ); + + appui->ViewAdapter().FocusControl().Draw( rect, aGc ); + } + +// ----------------------------------------------------------------------------- +// HasHoldTrigger +// Queries whether this node has a hold trigger defined +// ----------------------------------------------------------------------------- +// +static CXnDomNode* HasHoldTrigger( CXnDomNode* aNode ) + { + if ( !aNode ) + { + return NULL; + } + + if ( aNode->Name() == XnPropertyNames::action::KTrigger ) + { + CXnDomList& list( aNode->AttributeList() ); + + CXnDomAttribute* name( NULL ); + + name = static_cast< CXnDomAttribute* >( + list.FindByName( XnPropertyNames::action::KName ) ); + + if ( name && name->Value() == XnPropertyNames::action::trigger::name::KHold ) + { + return aNode; + } + } + + CXnDomList& list( aNode->ChildNodes() ); + + for ( TInt i = 0; i < list.Length(); i++ ) + { + CXnDomNode* retval( HasHoldTrigger( + static_cast< CXnDomNode* >( list.Item( i ) ) ) ); + + if ( retval ) + { + return retval; + } + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CancelFocusRefusalL +// Cancels focus refusal +// ----------------------------------------------------------------------------- +// +static void CancelFocusRefusalL( CXnUiEngine& aUiEngine ) + { + CXnNode* focused( aUiEngine.FocusedNode() ); + + if ( focused ) + { + CXnControlAdapter* control( focused->Control() ); + + if ( control && control->RefusesFocusLoss() ) + { + // It is now time to give up holding focus + focused->UnsetStateL( + XnPropertyNames::style::common::KFocus ); + } + } + } + +// ----------------------------------------------------------------------------- +// BuildSwipeTriggerNodeLC +// Build trigger node for swipe event +// ----------------------------------------------------------------------------- +// +CXnNode* CXnControlAdapterImpl::BuildSwipeTriggerNodeLC( + CXnUiEngine& aUiEngine, + const TDesC8& aDirection ) + { + 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::KSwipe ); + + 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 ); + + reasonValue->SetStringValueL( CXnDomPropertyValue::EString, aDirection ); + + CXnProperty* reason = CXnProperty::NewL( + XnPropertyNames::action::trigger::name::swipe::KDirection, + reasonValue, sp ); + + CleanupStack::Pop( reasonValue ); + + CleanupStack::PushL( reason ); + node->SetPropertyL( reason ); + CleanupStack::Pop( reason ); + + return node; + } + +// ----------------------------------------------------------------------------- +// CreateGestureHelperL +// Checks whether gesture is needed to be detected for this node +// ----------------------------------------------------------------------------- +// +static TBool CreateGestureHelperL( CXnNode& aNode ) + { + if ( AknLayoutUtils::PenEnabled() ) + { + CXnProperty* prop( aNode.GetPropertyL( XnPropertyNames::common::KSwipe ) ); + + if ( prop && prop->StringValue() == XnPropertyNames::KTrue ) + { + return ETrue; + } + } + + return EFalse; + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::NewL +// Two-phased constructor. Can leave. +// ----------------------------------------------------------------------------- +// +CXnControlAdapterImpl* CXnControlAdapterImpl::NewL( + CXnNodePluginIf& aNode, + CXnControlAdapter& aAdapter, + CWindowGc& aGc ) + { + CXnControlAdapterImpl* self = new ( ELeave ) CXnControlAdapterImpl( aNode ); + CleanupStack::PushL( self ); + self->ConstructL( aNode, aAdapter, aGc ); + CleanupStack::Pop(); + return self; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::~CXnControlAdapterImpl +// Destructor. +// ----------------------------------------------------------------------------- +// +CXnControlAdapterImpl::~CXnControlAdapterImpl() + { + delete iBackgroundBitmap; + delete iBackgroundMask; + delete iBorderBitmap; + delete iContentBitmap; + delete iContentMask; + + delete iScaledContentBitmap; + delete iScaledContentMask; + + delete iScaledTransparentColor; + delete iScaledBackgroundSkin; + delete iScaledBackgroundImage; + + iChildren.Reset(); + + if ( iAnimation ) + { + iAnimation->Stop(); + delete iAnimation; + } + + if ( iGestureHelper ) + { + delete iGestureHelper; + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::CXnControlAdapterImpl +// C++ default constructor. Must not leave. +// ----------------------------------------------------------------------------- +// +CXnControlAdapterImpl::CXnControlAdapterImpl( CXnNodePluginIf& aNode ) + : iNode( aNode ) + { + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::SetComponent +// Sets component object to adapter. +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::SetComponent( CXnComponent* aComponent ) + { + iComponent = aComponent; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::Component +// Gets component object from adapter. +// ----------------------------------------------------------------------------- +// +CXnComponent* CXnControlAdapterImpl::Component() + { + return iComponent; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::Component +// Gets component object from adapter. +// ----------------------------------------------------------------------------- +// +CXnComponent* CXnControlAdapterImpl::Component() const + { + return iComponent; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::OfferKeyEventL +// Handles key events. +// ----------------------------------------------------------------------------- +// +TKeyResponse CXnControlAdapterImpl::OfferKeyEventL( + const TKeyEvent& aKeyEvent, + TEventCode aType ) + { + CXnNode* node( &iNode.Node() ); + + // Need to get softkey nodes + CXnUiEngine* engine( node->UiEngine() ); + + CXnNode* menuBar( engine->MenuBarNode() ); + + CXnNode* temp( node ); + + for ( ; temp; temp = temp->Parent() ) + { + if ( temp == menuBar ) + { + // This is softkey node + const TDesC8* pos( NULL ); + node = NULL; + + if ( aKeyEvent.iScanCode == EStdKeyDevice0 ) + { + pos = &XnPropertyNames::softkey::type::KLeft; + } + else if ( aKeyEvent.iScanCode == EStdKeyDevice1 ) + { + pos = &XnPropertyNames::softkey::type::KRight; + } + else if ( aKeyEvent.iScanCode == EStdKeyDevice3 ) + { + pos = &XnPropertyNames::softkey::type::KMiddle; + } + + if ( pos ) + { + node = SoftkeyNodeL( menuBar, *pos ); + } + + break; + } + } + + if ( !node ) + { + return EKeyWasNotConsumed; + } + + if ( aKeyEvent.iScanCode == EStdKeyDevice0 || // RSK + aKeyEvent.iScanCode == EStdKeyDevice1 || // LSK + aKeyEvent.iScanCode == EStdKeyDevice3 ) // MSK + { + if ( aType == EEventKeyDown ) + { + iLongtap = EFalse; + + if ( aKeyEvent.iScanCode == EStdKeyDevice3 || + aKeyEvent.iScanCode == EStdKeyEnter ) + { + if ( node->IsStateSet( XnPropertyNames::style::common::KFocus ) ) + { + // Set "pressed down" + node->SetStateL( + XnPropertyNames::style::common::KPressedDown ); + + node->UiEngine()->RenderUIL(); + } + } + + _LIT8( KDown, "3" ); // EEventKeyDown == 3 + + CXnNode* keydown( BuildTriggerNodeL( *engine, + XnPropertyNames::action::trigger::name::KActivate, + XnPropertyNames::action::trigger::name::keyevent::KEventType, KDown ) ); + CleanupStack::PushL( keydown ); + + node->ReportXuikonEventL( *keydown ); + + CleanupStack::PopAndDestroy( keydown ); + } + else if( aType == EEventKey ) + { + if ( aKeyEvent.iRepeats == 0 ) + { + if ( !HasHoldTrigger( node->DomNode() ) ) + { + // If node doesn't define hold trigger, then report activate + // immediately. Otherwise activate is triggered with keyup event + node->SetStateL( + XnPropertyNames::style::common::KActive ); + } + } + else + { + CXnNode* hold( BuildTriggerNodeL( *engine, + XnPropertyNames::action::trigger::name::KHold ) ); + CleanupStack::PushL( hold ); + + node->ReportXuikonEventL( *hold ); + + CleanupStack::PopAndDestroy( hold ); + + iLongtap = ETrue; + } + } + + else if ( aType == EEventKeyUp ) + { + if ( !iLongtap ) + { + if ( HasHoldTrigger( node->DomNode() ) ) + { + // Hold trigger defined, report activate event here + node->SetStateL( + XnPropertyNames::style::common::KActive ); + } + else + { + _LIT8( KUp, "2" ); // EEventKeyUp == 2 + + CXnNode* keyup( BuildTriggerNodeL( *engine, + XnPropertyNames::action::trigger::name::KActivate, + XnPropertyNames::action::trigger::name::keyevent::KEventType, KUp ) ); + CleanupStack::PushL( keyup ); + + node->ReportXuikonEventL( *keyup ); + + CleanupStack::PopAndDestroy( keyup ); + } + } + + if ( aKeyEvent.iScanCode == EStdKeyDevice3 || + aKeyEvent.iScanCode == EStdKeyEnter ) + { + // Reset "pressed down" + node->UnsetStateL( + XnPropertyNames::style::common::KPressedDown ); + + node->UiEngine()->RenderUIL(); + } + + iLongtap = EFalse; + } + } + else + { + // Other than softkey node + node->OfferKeyEventL( aKeyEvent, aType ); + } + + CXnNode* viewNode( engine->ActiveView() ); + + if ( viewNode && node != viewNode ) + { + viewNode->OfferKeyEventL( aKeyEvent, aType ); + } + + return EKeyWasConsumed; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::HandleLongTapEventL +// Handles the long tap events. +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::HandleLongTapEventL( + const TPoint& /*aPenEventLocation*/, const TPoint& aPenEventScreenLocation ) + { + CXnNode* node( &iNode.Node() ); + + CXnUiEngine* engine( node->UiEngine() ); + + TBool menuBar( node == engine->MenuBarNode() ); + + if ( menuBar ) + { + // Need to update node to match to the real softkey node + node = SoftkeyNode( engine->MenuBarNode(), aPenEventScreenLocation ); + } + + if ( node ) + { + CXnProperty* prop( node->GetPropertyL( + XnPropertyNames::common::KLongTap ) ); + + if ( prop && prop->StringValue() == XnPropertyNames::KTrue ) + { + CXnUiEngine* engine( node->UiEngine() ); + CXnAppUiAdapter& appui( engine->AppUiAdapter() ); + + CancelFocusRefusalL( *engine ); + + appui.HideFocus(); + + CCoeControl& bg( appui.ViewAdapter().BgControl() ); + + // Ignore events + bg.IgnoreEventsUntilNextPointerUp(); + + // Indicate long tap has taken plave + iLongtap = ETrue; + + CXnNode* hold = BuildTriggerNodeL( *engine, + XnPropertyNames::action::trigger::name::KHold ); + + CleanupStack::PushL( hold ); + + node->ReportXuikonEventL( *hold ); + + CleanupStack::PopAndDestroy( hold ); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::HandlePointerEventL +// Handle pointer events +// ----------------------------------------------------------------------------- +// +TBool CXnControlAdapterImpl::HandlePointerEventL( + const TPointerEvent& aPointerEvent ) + { + const TPointerEvent& event( aPointerEvent ); + + // Forward event to gesture helper + if( PassEventToGestureHelperL( aPointerEvent ) ) + { + // Swipe took place, consume this event + return ETrue; + } + + CXnNode* node( &iNode.Node() ); + + CXnUiEngine* engine( node->UiEngine() ); + + TBool menuBar( node == engine->MenuBarNode() ); + + if ( menuBar ) + { + // Need to update node to match to the real softkey node + node = SoftkeyNode( engine->MenuBarNode(), event.iParentPosition ); + + if ( !node ) + { + // No softkey node found, consume event + return ETrue; + } + } + + CAknLongTapDetector* detector( iAdapter->LongTapDetector() ); + + if ( detector ) + { + if ( menuBar ) + { + // CXnMenuAdapter owns the longtap detector, but only + // softkey nodes can have longtap functionality, so + // need to check whether this softkey node has a longtap + // property defined + CXnProperty* prop( + node->GetPropertyL( XnPropertyNames::common::KLongTap ) ); + + if ( prop && prop->StringValue() == XnPropertyNames::KTrue ) + { + detector->PointerEventL( event ); + } + } + else + { + detector->PointerEventL( event ); + } + } + + CXnProperty* focusable( + node->GetPropertyL( XnPropertyNames::common::KFocusable ) ); + + if ( !menuBar && ( !focusable || + focusable->StringValue() == XnPropertyNames::KFalse ) ) + { + iLongtap = EFalse; + + return EFalse; + } + + if ( event.iType == TPointerEvent::EButton1Down ) + { + iLongtap = EFalse; + + if ( !menuBar ) + { + CancelFocusRefusalL( *engine ); + } + + if ( !menuBar && !engine->FocusedNode() ) + { + // Require focus to be shown + engine->AppUiAdapter().ShowFocus(); + +#ifdef RD_TACTILE_FEEDBACK + MTouchFeedback* feedback( MTouchFeedback::Instance() ); + + if ( feedback ) + { + feedback->InstantFeedback( ETouchFeedbackBasic ); + } +#endif + node->SetStateL( + XnPropertyNames::style::common::KFocus, + XnEventSource::EStylus ); + node->SetStateL( + XnPropertyNames::style::common::KPressedDown ); + } + } + else if ( event.iType == TPointerEvent::EDrag ) + { + if ( node->IsStateSet( XnPropertyNames::style::common::KFocus ) ) + { + if ( !node->MarginRect().Contains( event.iPosition ) ) + { + // Remove pressed down + node->UnsetStateL( XnPropertyNames::style::common::KPressedDown ); + node->HideTooltipsL(); + } + } + } + else if ( event.iType == TPointerEvent::EButton1Up ) + { + if ( !iLongtap ) + { + if ( menuBar ) + { + node->SetStateL( XnPropertyNames::style::common::KActive ); + } + else if ( ( node->MarginRect().Contains( event.iPosition ) && + node->IsStateSet( XnPropertyNames::style::common::KFocus ) && + node->IsStateSet( XnPropertyNames::style::common::KPressedDown ) ) ) + { + node->SetStateL( XnPropertyNames::style::common::KActive ); + } + } + + // Remove focus + engine->AppUiAdapter().HideFocus(); + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::DoDrawL +// Leaving draw function. +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DoDrawL( const TRect& aRect, CWindowGc& aGc ) const + { + CXnNode& node = iComponent->Node()->Node(); + + DrawBordersL( aRect, node, aGc ); + + const_cast< CXnControlAdapterImpl* >( this )->DrawBackgroundDataL( aRect, node, aGc ); + + if ( iAdapter->IsFocused() ) + { + DrawFocusAppearance( node, aGc ); + } + + if ( iAnimation ) + { + TRect rect = iComponent->Node()->Rect(); + iAnimation->Render( aGc, rect ); + } + + if ( iBorderBitmap ) + { + DrawBorderImagesL( + aRect, node, aGc, iBorderBitmap, + iBorderBitmapDividerTop, iBorderBitmapDividerRight, + iBorderBitmapDividerBottom, iBorderBitmapDividerLeft ); + } + + DrawContentImageL( aGc ); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::DrawBackgroundDataL +// Draws the background (color and image) +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DrawBackgroundDataL( + const TRect& aRect, + CXnNode& aNode, + CWindowGc& aGc ) + { + // For widgets and plugins, drawing is handled differently in edit mode + const TDesC8& widgetType = aNode.DomNode()->Name(); + if( ( widgetType == XnPropertyNames::KWidget || + widgetType == XnPropertyNames::KPlugin ) && + aNode.UiEngine()->EditMode()->EditState() ) + { + DrawEditModeBgData( aNode, aGc ); + return; + } + + if ( !iBackgroundBitmap && iBackgroundMask ) + // mask, but no bitmap: draw masked color (if available) + { + DrawTransparentColorL( aNode, aGc, iBackgroundMask ); + } + else if ( !iBackgroundBitmap || !iBackgroundMask ) + // no mask or no bitmap: draw color (if available) + { + DrawBackgroundColorL( aRect, aNode, aGc ); + } + + CXnProperty* colorProperty( aNode.BackgroundColorL() ); + DrawBackgroundSkinL( aNode, iBackgroundMask, aGc, colorProperty ); + + if ( !iBackgroundBitmap ) + { + return; + } + + CXnProperty* pathProperty( aNode.BackgroundImageL() ); + + if ( pathProperty && pathProperty->StringValue() != KNullDesC8 ) + { + if ( iBackgroundMask ) + { + // draw transparent background image + DrawBackgroundImageL( aRect, aNode, aGc, iBackgroundBitmap, iBackgroundMask ); + } + else + { + // draw background image without mask + DrawBackgroundImageL( aRect, aNode, aGc, iBackgroundBitmap, NULL ); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::DrawEditModeBgDataL +// +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DrawEditModeBgData( + CXnNode& aNode, + CWindowGc& aGc ) + { + // Draw rastered background for plugins + const TDesC8& widgetType = aNode.DomNode()->Name(); + if( widgetType == XnPropertyNames::KPlugin ) + { + TRect rect = aNode.PaddingRect(); + DrawBackgroundSkin( KAknsIIDQgnHomeEditBgWidget, aGc, rect ); + + CXnPluginData& data( aNode.UiEngine()->ViewManager()->ActiveViewData().Plugin( &aNode ) ); + if( !data.Occupied() ) // Empty widget + { + // Draw + -icon + // Make rect as 50% of the widget's height. + // It needs to be square in order to keep aspect ratio. + TInt w = rect.Width(); + TInt h = rect.Height(); + rect.Shrink( ( w - h * 0.5 ) * 0.5, h * 0.25 ); + DrawBackgroundSkin( KAknsIIDQgnHomeAdd, aGc, rect ); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::DrawTransparentColorL +// Draws masked background by RGB color. +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DrawTransparentColorL( + CXnNode& aNode, + CWindowGc& aGc, + CFbsBitmap* aMask ) + { + CXnProperty* colorProperty( aNode.BackgroundColorL() ); + + if ( colorProperty ) + { + // check value type + CXnDomPropertyValue* value = + static_cast< CXnDomPropertyValue* >( + colorProperty->Property()->PropertyValueList().Item( 0 ) ); + + if ( value->PrimitiveValueType() == CXnDomPropertyValue::ERgbColor ) + { + TRect paddingRect = aNode.PaddingRect(); + aMask->SetDisplayMode( EGray256 ); + + aGc.SetBrushColor( NULL ); + aGc.SetBrushStyle( CGraphicsContext::ENullBrush ); + + if ( !iScaledTransparentColor ) + { + CFbsBitmap* bitmap( NULL ); + CFbsBitmap* mask( NULL ); + + mask = new ( ELeave ) CFbsBitmap; + CleanupStack::PushL( mask ); + + mask->Create( paddingRect.Size(), EGray256 ); + + CXnUtils::ScaleBitmapL( + TRect( 0, 0, paddingRect.Width(), paddingRect.Height() ), + mask, aMask ); + + CXnDomPropertyValue* value = + static_cast< CXnDomPropertyValue* >( + colorProperty->Property()->PropertyValueList().Item( 0 ) ); + + TRgb rgb( value->RgbColorValueL() ); + + bitmap = CreateBitmapFromColorL( paddingRect.Size(), rgb ); + CleanupStack::PushL( bitmap ); + + iScaledTransparentColor = CGulIcon::NewL( bitmap, mask ); + + CleanupStack::Pop( 2 ); + } + + aGc.DrawBitmapMasked( paddingRect, + iScaledTransparentColor->Bitmap(), + TRect( TPoint( 0, 0 ), paddingRect.Size() ), + iScaledTransparentColor->Mask(), + EFalse ); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::DrawBackgroundSkinL +// Draws a skin item to the given rect +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DrawBackgroundSkin(const TAknsItemID& aSkinId, + CWindowGc& aGc, TRect aRect) + { + TRect shrunkRect = aRect; + + shrunkRect.Shrink( + KSkinGfxInnerRectShrink, + KSkinGfxInnerRectShrink ); + + AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(), aGc, + aRect, shrunkRect, aSkinId, KAknsIIDDefault ); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::DrawBackgroundSkinL +// Draws a skin item to the padding rect +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DrawBackgroundSkinL(CXnNode& aNode, + CFbsBitmap* aMask, CWindowGc& aGc, CXnProperty* aBgColor, + TRect aRect) + { + if( aRect == TRect::EUninitialized ) + { + aRect = aNode.PaddingRect(); + } + + //CXnProperty* colorProperty( aNode.BackgroundColorL() ); + CXnProperty* colorProperty( aBgColor ); + if ( colorProperty ) + { + HBufC* skinID = colorProperty->StringValueL(); + CleanupStack::PushL( skinID ); + + if ( skinID->Length() != 0 ) + { + TAknsItemID itemID; + StripQuotes( skinID ); + + if ( CXnUtils::ResolveSkinItemIDL( *skinID, itemID ) ) + { + if ( aMask ) // If there is a mask, draw masked. + { + TRect paddingRect = aRect; + TRect outerRect = TRect( paddingRect.Size() ); + TRect innerRect = outerRect; + innerRect.Shrink( + KSkinGfxInnerRectShrink, + KSkinGfxInnerRectShrink ); + + if ( !iScaledBackgroundSkin ) + { + CFbsBitmap* bitmap = new ( ELeave ) CFbsBitmap; + CleanupStack::PushL( bitmap ); + + CFbsBitmap* mask = new ( ELeave ) CFbsBitmap; + CleanupStack::PushL( mask ); + + bitmap->Create( outerRect.Size(), aGc.Device()->DisplayMode() ); + + CFbsBitmapDevice* device = CFbsBitmapDevice::NewL( bitmap ); + CleanupStack::PushL( device ); + + CBitmapContext* bc( NULL ); + + User::LeaveIfError( device->CreateBitmapContext( bc ) ); + CleanupStack::PushL( bc ); + + CAknsFrameBackgroundControlContext* frameContext = + CAknsFrameBackgroundControlContext::NewL( + itemID, outerRect, innerRect, EFalse ); + CleanupStack::PushL( frameContext ); + + AknsDrawUtils::Background( AknsUtils::SkinInstance(), + frameContext, NULL, + static_cast< CWindowGc& >( *bc ), + outerRect, KAknsDrawParamNoClearUnderImage ); + + aMask->SetDisplayMode( EGray256 ); + + aGc.SetBrushColor( NULL ); + aGc.SetBrushStyle( CGraphicsContext::ENullBrush ); + + mask->Create( paddingRect.Size(), EGray256 ); + + CXnUtils::ScaleBitmapL( outerRect, mask, aMask ); + + CleanupStack::PopAndDestroy( 3 ); + + iScaledBackgroundSkin = CGulIcon::NewL( bitmap, mask ); + + CleanupStack::Pop( 2 ); + } + + CFbsBitmap* bitmap( iScaledBackgroundSkin->Bitmap() ); + CFbsBitmap* mask( iScaledBackgroundSkin->Mask() ); + + aGc.BitBltMasked( paddingRect.iTl, bitmap, outerRect, mask, ETrue ); + } + else // draw background skin graphics without mask + { + TRect paddingRect = aRect; + TRect shrunkRect = paddingRect; + + shrunkRect.Shrink( + KSkinGfxInnerRectShrink, + KSkinGfxInnerRectShrink ); + + CAknsFrameBackgroundControlContext* frameContext = + CAknsFrameBackgroundControlContext::NewL( + itemID, paddingRect, shrunkRect, EFalse ); + + CleanupStack::PushL( frameContext ); + + AknsDrawUtils::Background( AknsUtils::SkinInstance(), + frameContext, + NULL, + aGc, + paddingRect, + KAknsDrawParamNoClearUnderImage ); + + CleanupStack::PopAndDestroy( frameContext ); + } + } + } + + CleanupStack::PopAndDestroy( skinID ); + } + } + +// ----------------------------------------------------------------------------- +// DrawBackgroundImageL +// Draws the background image +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DrawBackgroundImageL( + const TRect& aRect, + CXnNode& aNode, + CWindowGc& aGc, + CFbsBitmap* aBitmap, + CFbsBitmap* aMask ) + { + if ( !aBitmap ) + { + return; + } + + TRect rect = aNode.PaddingRect(); + TBool scaleImage = EFalse; + + if (!GetBackgroundSizeFromPropertyL( rect, aNode, aBitmap, scaleImage ) ) + { + return; + } + if ( AknIconUtils::IsMifIcon( aBitmap ) ) + { + if ( scaleImage ) + { + AknIconUtils::SetSize( aBitmap, rect.Size(), EAspectRatioNotPreserved ); + } + else + { + AknIconUtils::SetSize( aBitmap, rect.Size(), EAspectRatioPreserved ); + } + } + TRect imageRect = rect; + rect = aNode.PaddingRect(); + TBool heightSet = EFalse; + TBool backgroundPosFound = EFalse; + TRAP_IGNORE( backgroundPosFound = GetBackgroundPositionFromPropertyL( + aNode, scaleImage, rect, imageRect, aBitmap, heightSet ); ); + if ( !backgroundPosFound ) + { + return; + } + if ( !heightSet ) + { + rect.Move( 0, rect.Height() / 2 ); + if ( scaleImage ) + { + rect.Move( 0, -imageRect.Height() / 2 ); + } + else + { + rect.Move( 0, -aBitmap->SizeInPixels().iHeight / 2 ); + } + } + TRect tmpRect = aNode.PaddingRect(); + LimitRectToPaddingRect( aNode, rect ); + TBool repeatX = EFalse; + TBool repeatY = EFalse; + TBool spaceX = EFalse; + TBool spaceY = EFalse; + TRAP_IGNORE( GetBackroundRepeatValuesL( aNode, repeatX, repeatY, spaceX, spaceY ) ); + TRect bitmapRect = TRect( + TPoint( 0, 0 ), + TPoint( aBitmap->SizeInPixels().iWidth, aBitmap->SizeInPixels().iHeight ) ); + TInt xRepeatCount = 0; + TInt yRepeatCount = 0; + TRect paddingRect = aNode.PaddingRect(); + if ( scaleImage ) + { + if ( imageRect.Width() && imageRect.Height() ) + { + xRepeatCount = paddingRect.Width() / imageRect.Width(); + yRepeatCount = paddingRect.Height() / imageRect.Height(); + } + } + else + { + TSize size = aBitmap->SizeInPixels(); + if ( size.iWidth == 0 || size.iHeight == 0 ) + { + return; + } + xRepeatCount = paddingRect.Width() / size.iWidth; + yRepeatCount = paddingRect.Height() / size.iHeight; + } + + if ( xRepeatCount == 0 && yRepeatCount == 0 || + !repeatX && !repeatY && !spaceX && !spaceY ) + { + TRect newRect = TRect( + rect.iTl, + TPoint( + rect.iTl.iX + imageRect.Width(), + rect.iTl.iY + imageRect.Height() ) ); + aGc.SetClippingRect( aRect ); + + if ( aMask ) + { + aMask->SetDisplayMode( EGray256 ); + + aGc.SetBrushColor( NULL ); + aGc.SetBrushStyle( CGraphicsContext::ENullBrush ); + + if ( !iScaledBackgroundImage ) + { + CFbsBitmap* mask( NULL ); + + mask = new ( ELeave ) CFbsBitmap; + CleanupStack::PushL( mask ); + + mask->Create( bitmapRect.Size(), EGray256 ); + + CXnUtils::ScaleBitmapL( + TRect( + 0, + 0, + bitmapRect.Width(), + bitmapRect.Height() ), + mask, + aMask ); + + iScaledBackgroundImage = mask; + + CleanupStack::Pop( mask ); + } + + aGc.DrawBitmapMasked( newRect, aBitmap, bitmapRect, + iScaledBackgroundImage, EFalse ); + } + else + { + TRect newRect = TRect( + rect.iTl, + TPoint( + rect.iTl.iX + imageRect.Width(), + rect.iTl.iY + imageRect.Height() ) ); + aGc.SetClippingRect( aRect ); + + aGc.DrawBitmap( newRect, aBitmap, bitmapRect ); + } + + aGc.CancelClippingRect(); + + return; + } + + DrawRepeatedBackgroundImage( + aGc, + aNode, + rect, + imageRect, + bitmapRect, + aBitmap, + repeatX, + repeatY, + spaceX, + spaceY, + xRepeatCount, + yRepeatCount ); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::Draw +// Draws the control +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::Draw( const TRect& aRect ) const + { + if ( iBlank ) + { + return; + } + + CWindowGc& gc = iAdapter->SystemGc(); + //gc.SetClippingRect(aRect); +#ifdef _XN_DEBUG_ + CXnComponent* comp = Component(); + CXnNode& node = comp->Node()->Node(); + TRect contentRect = node.Rect(); + TRect marginRect = node.MarginRect(); + TRect paddingRect = node.PaddingRect(); + + gc.SetBrushStyle( CGraphicsContext::ENullBrush ); + gc.SetPenColor( KRgbBlue ); + gc.DrawRect( marginRect ); + gc.SetPenColor( KRgbGray ); + gc.DrawRect( paddingRect ); + gc.SetPenColor( KRgbRed ); + gc.DrawRect( contentRect ); +#endif + TRAP_IGNORE( DoDrawL( aRect, gc )); + //gc.CancelClippingRect(); + RPointerArray< CXnControlAdapter > sortedArray; + TBool needsSorting = EFalse; + for ( TInt count = iChildren.Count() - 1; count >= 0; --count ) + { + needsSorting = ETrue; + CXnControlAdapter* child = iChildren[count]; + TRAP_IGNORE( InsertChildToSortedArrayL( sortedArray, child ) ); + } + if ( !needsSorting ) + { + return; + } + SwapChildArrays( iChildren, sortedArray ); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::Draw +// Draws the control +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::Draw( const TRect& aRect, CWindowGc& aGc ) const + { + if ( iBlank ) + { + return; + } + + aGc.SetClippingRect( aRect ); +#ifdef _XN_DEBUG_ + CXnComponent* comp = Component(); + CXnNode& node = comp->Node()->Node(); + TRect contentRect = node.Rect(); + TRect marginRect = node.MarginRect(); + TRect paddingRect = node.PaddingRect(); + aGc.SetBrushStyle( CGraphicsContext::ENullBrush ); + aGc.SetPenColor( KRgbBlue ); + aGc.DrawRect( marginRect ); + aGc.SetPenColor( KRgbGray ); + aGc.DrawRect( paddingRect ); + aGc.SetPenColor( KRgbRed ); + aGc.DrawRect( contentRect ); +#endif + TRAP_IGNORE( DoDrawL( aRect, aGc ) ); + aGc.CancelClippingRect(); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::ComponentControl +// Return a child control by index +// ----------------------------------------------------------------------------- +// +CCoeControl* CXnControlAdapterImpl::ComponentControl( TInt aIndex ) const + { + return iChildren[aIndex]; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::CountComponentControls +// Return count of children +// ----------------------------------------------------------------------------- +// +TInt CXnControlAdapterImpl::CountComponentControls() const + { + return iChildren.Count(); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::AppendChildL +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::AppendChildL(CXnControlAdapter& aChild, CXnNode& aNode) + { + if( !aChild.OwnsWindow() ) + { + SetControlContext( aChild, aNode ); + if( iChildren.Append( &aChild ) != KErrNone ) + { + User::Leave( KXnErrAppendingChildToControlAdapterFailed ); + } + aChild.SetContainerWindowL( *iAdapter ); + } + } + + +// ----------------------------------------------------------------------------- +// ConvertHslToRgb +// Converts a HSL color to RGB color +// ----------------------------------------------------------------------------- +// +static TRgb ConvertHslToRgb( + TInt aHue, TInt aSaturation, TInt aLightness ) + { + TRgb rgb( 0, 0, 0 ); + TReal h( aHue ); + h /= 360; + TReal s( aSaturation ); + s /= 100; + TReal l( aLightness ); + l /= 100; + + if ( 0 == aSaturation ) + { + rgb.SetRed( TInt( l * 255 ) ); + rgb.SetGreen( TInt( l * 255 ) ); + rgb.SetBlue( TInt( l * 255 ) ); + } + else + { + TReal m1( 0 ); + TReal m2( 0 ); + + // l<=0.5: PUT l*(s+1) IN m2 + if ( aLightness < 0.5 ) + { + m2 = l * ( s + 1.0 ); + } + // PUT l+s-l*s IN m2 + else + { + m2 = l + s - ( l * s ); + } + + // PUT l*2-m2 IN m1 + m1 = l * 2.0 - m2; + + TReal helperH( h ); + TReal helperM1( m1 ); + TReal helperM2( m2 ); + + // calculate Red + helperH = h + ( 1.0 / 3.0 ); + + // IF h<0: PUT h+1 IN h + if ( helperH < 0 ) + { + helperH += 1.0; + } + + // IF h>1: PUT h-1 IN h + else if ( helperH > 1 ) + { + helperH -= 1.0; + } + else + { + } + + TReal val( 0 ); + + // IF h*6<1: RETURN m1+(m2-m1)*h*6 + if ( ( helperH * 6 ) < 1 ) + { + val = ( 255 * ( helperM1 + ( helperM2 - helperM1 ) * helperH * 6.0 ) ); + } + + // IF h*2<1: RETURN m2 ) + else if ( ( helperH * 2.0 ) < 1.0 ) + { + val = ( 255.0 * helperM2 ); + } + + // IF h*3<2: RETURN m1+(m2-m1)*(2/3-h)*6 + else if ( ( helperH * 3.0 ) < 2.0 ) + { + val = ( 255.0 * ( helperM1 + ( helperM2 - helperM1 ) * + ( 2.0 / 3.0 - helperH ) * 6.0 ) ); + } + else + { + val = 255.0 * helperM1; + } + TInt tmpVal = TInt( val + 0.5 ); + rgb.SetRed( ( tmpVal >= 0) ? tmpVal : -tmpVal ); + + // calculate Green + // PUT hue.to.rgb(m1, m2, h ) IN g + helperH = h; + helperM1 = m1; + helperM2 = m2; + + // IF h<0: PUT h+1 IN h + if ( helperH < 0 ) + { + helperH += 1.0; + } + // IF h>1: PUT h-1 IN h + else if ( helperH > 1 ) + { + helperH -= 1.0; + } + else + { + } + + // IF h*6<1: RETURN m1+(m2-m1)*h*6 + if ( ( helperH * 6 ) < 1 ) + { + val = ( 255.0 * ( helperM1 + ( helperM2 - helperM1 ) * helperH * 6.0 ) ); + } + // IF h*2<1: RETURN m2 + else if ( ( helperH * 2 ) < 1 ) + { + val = ( 255.0 * helperM2 ); + } + // IF h*3<2: RETURN m1+(m2-m1)*(2/3-h)*6 + else if ( ( helperH * 3 ) < 2 ) + { + val = ( 255.0 * ( helperM1 + ( helperM2 - helperM1 ) * + ( 2.0 / 3.0 - helperH ) * 6.0 ) ); + } + else + { + val = 255.0 * helperM1; + } + + tmpVal = TInt( val + 0.5 ); + rgb.SetGreen( ( tmpVal >= 0) ? tmpVal : tmpVal ); + + // calculate Blue + // PUT hue.to.rgb(m1, m2, h-1/3) IN b + helperH = h - ( 1.0 / 3.0 ); + helperM1 = m1; + helperM2 = m2; + + // IF h<0: PUT h+1 IN h + if ( helperH < 0 ) + { + helperH += 1.0; + } + // IF h>1: PUT h-1 IN h + else if ( helperH > 1 ) + { + helperH -= 1.0; + } + else + { + } + + // IF h*6<1: RETURN m1+(m2-m1)*h*6 + if ( ( helperH * 6 ) < 1 ) + { + val = ( 255.0 * ( helperM1 + ( helperM2 - helperM1 ) * helperH * 6.0 ) ); + } + // IF h*2<1: RETURN m2 + else if ( ( helperH * 2 ) < 1 ) + { + val = ( 255.0 * helperM2 ); + } + // IF h*3<2: RETURN m1+(m2-m1)*(2/3-h)*6 + else if ( ( helperH * 3 ) < 2 ) + { + val = ( 255.0 * ( helperM1 + ( helperM2 - helperM1 ) * + ( 2.0 / 3.0 - helperH ) * 6.0 ) ); + } + else + { + val = 255.0 * helperM1; + } + + tmpVal = TInt( val + 0.5 ); + rgb.SetBlue( ( tmpVal >= 0) ? tmpVal : -tmpVal ); + + } + return rgb; + } + +// ----------------------------------------------------------------------------- +// ConvertRgbToHsl +// Converts a RGB color to HSL color +// ----------------------------------------------------------------------------- +// +static void ConvertRgbToHsl( + TRgb aRGB, + TUint& aHue, + TUint& aSaturation, + TUint& aLightness ) + { + TReal red = static_cast< TReal >( aRGB.Red() ) / 255.0; + TReal green = static_cast< TReal >( aRGB.Green() ) / 255.0; + TReal blue = static_cast< TReal >( aRGB.Blue() ) / 255.0; + TReal maxColor = ( red > green && red > blue ) ? + red : ( green > red && green > blue ) ? green : blue; + TReal minColor = ( red <= green && red <= blue ) ? + red : ( green <= red && green <= blue ) ? green : blue; + TReal lightness = ( maxColor + minColor ) / 2.0; + if ( maxColor == minColor ) + { + aSaturation = 0; + aHue = 0; + aLightness = static_cast< TInt >( 100.0 * lightness + 0.5 ); + return; + } + + if ( lightness < 0.5 ) + { + TReal saturation = ( maxColor - minColor ) / ( maxColor + minColor ); + aSaturation = static_cast< TInt >( 100.0 * saturation + 0.5 ); + } + else + { + TReal saturation = ( maxColor - minColor ) / ( 2.0 - maxColor - minColor ); + aSaturation = static_cast< TInt >( 100.0 * saturation + 0.5 ); + } + + if ( red == maxColor ) + { + TReal hue = ( green - blue ) / ( maxColor - minColor ); + TInt tmp = static_cast< TInt >( 60.0 * hue + 0.5 ); + aHue = ( tmp >= 0 ) ? tmp : tmp + 360; + } + else if ( green == maxColor ) + { + TReal hue = 2.0 + ( ( blue - red ) / ( maxColor - minColor ) ); + TInt tmp = static_cast< TInt >( 60.0 * hue + 0.5 ); + aHue = ( tmp >= 0 ) ? tmp : tmp + 360; + } + else + { + TReal hue = 4.0 + ( ( red - green ) / ( maxColor - minColor ) ); + TInt tmp = static_cast< TInt >( 60.0 * hue + 0.5 ); + aHue = ( tmp >= 0 ) ? tmp : tmp + 360; + } + + aLightness = static_cast< TInt >( 100.0 * lightness + 0.5 ); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::IsDrawingAllowed +// Checks whether drawing is allowed +// ----------------------------------------------------------------------------- +// +TBool CXnControlAdapterImpl::IsDrawingAllowed() const + { + TBool retVal = EFalse; + CXnNode& node = Component()->Node()->Node(); + CXnProperty* propVisibility = NULL; + TRAP_IGNORE( propVisibility = node.VisibilityL() ); + if ( propVisibility ) + { + const TDesC8& visibility = propVisibility->StringValue(); + if ( visibility != KNullDesC8 ) + { + if ( visibility == XnPropertyNames::style::common::visibility::KHidden ) + { + return EFalse; + } + else + { + retVal = ETrue; + } + } + } + else + { + // default value for visibility + retVal = ETrue; + } + CXnProperty* propDisplay = NULL; + TRAP_IGNORE( propDisplay = node.DisplayL() ); + if ( propDisplay ) + { + const TDesC8& display = propDisplay->StringValue(); + if ( display != KNullDesC8 ) + { + if ( display == XnPropertyNames::style::common::display::KNone ) + { + return EFalse; + } + else + { + retVal = ETrue; + } + } + } + if ( node.IsDropped() ) + { + return EFalse; + } + else + { + retVal = ETrue; + } + return retVal; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::ContentBitmaps +// Gets content bitmaps +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::ContentBitmaps( + CFbsBitmap*& aBitmap, + CFbsBitmap*& aMask ) + { + aBitmap = iContentBitmap; + aMask = iContentMask; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::SetContentBitmaps +// Sets content bitmaps +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::SetContentBitmaps( + CFbsBitmap* aBitmap, + CFbsBitmap* aMask ) + { + delete iContentBitmap; + iContentBitmap = NULL; + + delete iContentMask; + iContentMask = NULL; + + delete iScaledContentBitmap; + iScaledContentBitmap = NULL; + + delete iScaledContentMask; + iScaledContentMask = NULL; + + iContentBitmap = aBitmap; + iContentMask = aMask; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::SetContentBitmapsL +// Sets content bitmaps +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::SetContentBitmapsL( const TDesC& aBitmapUrl, + const TDesC& aMaskUrl ) + { + delete iContentBitmap; + iContentBitmap = NULL; + + delete iContentMask; + iContentMask = NULL; + + delete iScaledContentBitmap; + iScaledContentBitmap = NULL; + + delete iScaledContentMask; + iScaledContentMask = NULL; + + CXnNode& node( iNode.Node() ); + CXnUiEngine* engine( node.UiEngine() ); + + TRect rect( node.Rect() ); + + GetBitmapL( *engine, node, aBitmapUrl, iContentBitmapIndex, + iContentBitmap, iContentMask, iIconProvider, rect, FsSession() ); + if ( !iContentBitmap ) + { + CXnProperty* prop( node.GetPropertyL( + XnPropertyNames::appearance::common::KFallBackImage ) ); + + if ( prop ) + { + HBufC* fallBackImage( prop->StringValueL( ) ); + + CleanupStack::PushL( fallBackImage ); + + if ( *fallBackImage != KNullDesC ) + { + StripQuotes( fallBackImage ); + + GetBitmapL( *engine, node, *fallBackImage, iContentBitmapIndex, + iContentBitmap, iContentMask, iIconProvider, rect, FsSession() ); + } + + CleanupStack::PopAndDestroy( fallBackImage ); + } + } + + if ( !iContentMask ) + { + if ( aMaskUrl != KNullDesC ) + { + CFbsBitmap* bitmapMask( NULL ); + + GetBitmapL( *engine, node, aMaskUrl, iContentMaskIndex, + iContentMask, bitmapMask, iIconProvider, rect, FsSession() ); + + delete bitmapMask; + } + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::DrawContentImage +// Draws content image +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DrawContentImage() const + { + TRAP_IGNORE( DrawContentImageL( *iGc ) ); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::DrawContentImage +// Draws content image +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DrawContentImageL( CWindowGc& aGc ) const + { + if ( !iContentBitmap ) + { + return; + } + + TRect rect = iComponent->Node()->Node().Rect(); + + // Check if the node has a property "preserve image aspect ratio". + TBool preserveAspectRatio = EFalse; + CXnNode& currentNode = iComponent->Node()->Node(); + + CXnProperty* aspectProperty = currentNode.GetPropertyL( + XnPropertyNames::image::KS60AspectRatio ); + if ( aspectProperty ) + { + const TDesC8& value = aspectProperty->StringValue(); + + if ( value.CompareF( XnPropertyNames::image::KPreserve ) == 0 ) + { + preserveAspectRatio = ETrue; + } + } + + TRect bitmapRect = rect; + bitmapRect.Move( -rect.iTl.iX, -rect.iTl.iY ); + + if ( AknIconUtils::IsMifIcon( iContentBitmap ) ) + { + if ( preserveAspectRatio ) + { + AknIconUtils::SetSize( + iContentBitmap, bitmapRect.Size(), EAspectRatioPreserved ); + } + else + { + AknIconUtils::SetSize( + iContentBitmap, bitmapRect.Size(), EAspectRatioNotPreserved ); + } + //Calculate new point to start draw in order to center bitmap to drawing area + rect.iTl.iY += + ( rect.Height() - iContentBitmap->SizeInPixels().iHeight ) / 2; + rect.iTl.iX += + ( rect.Width() - iContentBitmap->SizeInPixels().iWidth ) / 2; + + if ( iContentMask ) + { + // Based on the avkon's assumtion that mask is always inverted, the + // value of aInvertMask parameter is set to 'ETrue' + aGc.BitBltMasked( rect.iTl, iContentBitmap, bitmapRect, iContentMask, + ETrue ); + } + else + { + aGc.BitBlt( rect.iTl, iContentBitmap, bitmapRect ); + } + } + else + { + if ( !iScaledContentBitmap ) + { + TBool forceFallBack = CXnUtils::DoesScaleBitmapUseFallBack( + iContentBitmap ); + + TRAPD( err, CreateScaledBitmapL( bitmapRect, + iScaledContentBitmap, + iContentBitmap, + preserveAspectRatio, + forceFallBack ) ); + if ( err ) + { + // return if CreateScaledBitmapL() leaves. This prevents the + // drawing of the original content bitmap which is wrong size. + return; + } + } + if ( iContentMask && !iScaledContentMask ) + { + TBool forceFallBack = CXnUtils::DoesScaleBitmapUseFallBack( + iContentMask ); + + TRAPD( err, CreateScaledBitmapL( bitmapRect, + iScaledContentMask, + iContentMask, + preserveAspectRatio, + forceFallBack ) ); + if ( err ) + { + // return if CreateScaledBitmapL() leaves. This prevents the + // drawing of the original content mask which is wrong size + // (and may distort the image). + return; + } + } + + CFbsBitmap* bitmap( 0 ); + CFbsBitmap* mask( 0 ); + + if ( iScaledContentBitmap ) + { + bitmap = iScaledContentBitmap; + } + else + { + bitmap = iContentBitmap; + } + + if ( iScaledContentMask ) + { + mask = iScaledContentMask; + } + else + { + mask = iContentMask; + } + + if ( bitmap && mask ) + { + //Calculate new point to start draw in order to center bitmap to + // drawing area + rect.iTl.iY += + ( rect.Height() - bitmap->SizeInPixels().iHeight ) / 2; + rect.iTl.iX += + ( rect.Width() - bitmap->SizeInPixels().iWidth ) / 2; + + // Based on the avkon's assumtion that mask is always inverted, the + // value of aInvertMask parameter is set to 'ETrue' + aGc.BitBltMasked( rect.iTl, bitmap, bitmapRect, mask, ETrue ); + } + else if ( bitmap ) + { + //Calculate new point to start draw in order to center bitmap to + // drawing area + rect.iTl.iY += + ( rect.Height() - bitmap->SizeInPixels().iHeight ) / 2; + rect.iTl.iX += + ( rect.Width() - bitmap->SizeInPixels().iWidth ) / 2; + + aGc.BitBlt( rect.iTl, bitmap ); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::SizeChanged +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::SizeChanged() + { + delete iScaledContentBitmap; + iScaledContentBitmap = NULL; + + delete iScaledContentMask; + iScaledContentMask = NULL; + + delete iScaledTransparentColor; + iScaledTransparentColor = NULL; + + delete iScaledBackgroundSkin; + iScaledBackgroundSkin = NULL; + + delete iScaledBackgroundImage; + iScaledBackgroundImage = NULL; + + TRAP_IGNORE( InitializeBackgroundAndBorderBitmapsL() ); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::SkinChanged +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::SkinChanged() + { + delete iScaledContentBitmap; + iScaledContentBitmap = NULL; + + delete iScaledContentMask; + iScaledContentMask = NULL; + + delete iScaledTransparentColor; + iScaledTransparentColor = NULL; + + delete iScaledBackgroundSkin; + iScaledBackgroundSkin = NULL; + + delete iScaledBackgroundImage; + iScaledBackgroundImage = NULL; + + TRAP_IGNORE( InitializeBackgroundAndBorderBitmapsL() ); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::FocusChangedL +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::FocusChangedL( TBool aFocused ) + { + CXnNode& node( iNode.Node() ); + + CXnUiEngine* engine( node.UiEngine() ); + + CXnNode* menubar( engine->MenuBarNode() ); + + if ( engine->IsEditMode() || !node.IsLayoutCapable() || !menubar ) + { + return; + } + + XnMenuInterface::MXnMenuInterface* menuIf( NULL ); + + XnComponentInterface::MakeInterfaceL( menuIf, menubar->AppIfL() ); + + if ( !menuIf ) + { + return; + } + + CXnViewManager* manager( engine->ViewManager() ); + + const TDesC8& ns( node.Namespace() ); + + CXnPluginData* data( manager->ActiveViewData().Plugin( ns ) ); + + if ( !data ) + { + return; + } + + CXnNode* plugin( data->Node()->LayoutNode() ); + + CXnNode* extension( NULL ); + + if ( plugin == engine->ActiveView() ) + { + // Pretend that this node is extension + extension = &node; + } + else + { + RPointerArray< CXnNode >& children( plugin->Children() ); + + for ( TInt i = 0; i < children.Count(); i++ ) + { + CXnNode* child( children[i] ); + + const TDesC8& type( child->Type()->Type() ); + + if ( type == XnPropertyNames::menu::KMenuExtension ) + { + extension = child; + break; + } + } + } + + if ( !extension ) + { + // No extension available + return; + } + + // Find proper softkey from extension + RPointerArray< CXnNode >& children( extension->Children() ); + + for ( TInt i = 0; i < children.Count(); i++ ) + { + CXnNode* child( children[i] ); + + const TDesC8& type( child->Type()->Type() ); + + if ( type == XnPropertyNames::softkey::KNodeName ) + { + + CXnProperty* prop( child->GetPropertyL( + XnPropertyNames::softkey::KTypeAttribute ) ); + + if ( prop ) + { + const TDesC8& type( prop->StringValue() ); + + XnMenuInterface::MXnMenuInterface::TSoftKeyPosition pos; + + if ( type == XnPropertyNames::softkey::type::KLeft ) + { + pos = XnMenuInterface::MXnMenuInterface::ELeft; + } + else if ( type == XnPropertyNames::softkey::type::KMiddle ) + { + pos = XnMenuInterface::MXnMenuInterface::ECenter; + } + else if ( type == XnPropertyNames::softkey::type::KRight ) + { + pos = XnMenuInterface::MXnMenuInterface::ERight; + } + else + { + // Declaration error + __ASSERT_DEBUG( EFalse, Panic( EXnInvalidState ) ); + break; + } + + if ( aFocused ) + { + // Set softkey + menuIf->SetSoftKeyL( &child->PluginIfL(), pos ); + } + else + { + // Remove softkey + menuIf->SetSoftKeyL( NULL, pos ); + } + + // This is not a correct way to do dirty setting, + // but here in case of menubar it is acceptable + engine->AddDirtyNodeL( menubar, XnDirtyLevel::ERender ); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::InitializeBackgroundandBorderBitmapsL +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::InitializeBackgroundAndBorderBitmapsL() + { + CXnNode& node( iNode.Node() ); + CXnUiEngine* engine( node.UiEngine() ); + + CXnProperty* backgroundImageProperty( node.BackgroundImageL() ); + + if ( backgroundImageProperty ) + { + delete iBackgroundBitmap; + iBackgroundBitmap = NULL; + + delete iBackgroundMask; + iBackgroundMask = NULL; + + delete iScaledTransparentColor; + iScaledTransparentColor = NULL; + + delete iScaledBackgroundSkin; + iScaledBackgroundSkin = NULL; + + delete iScaledBackgroundImage; + iScaledBackgroundImage = NULL; + + InitializeBackgroundBitmapL( *engine, node, iBackgroundBitmapIndex, + iBackgroundBitmap, iBackgroundMask, iIconProvider, FsSession() ); + + HBufC* bgPath( GetBackgroundImagePathLC( node ) ); + + if ( *bgPath != KNullDesC ) + { + iAnimIDResolved = CXnUtils::ResolveSkinItemIDL( *bgPath, iAnimIID ); + } + + CleanupStack::PopAndDestroy( bgPath ); + } + + CXnProperty* borderImageProperty( node.BorderImageL() ); + + if ( borderImageProperty ) + { + delete iBorderBitmap; + iBorderBitmap = NULL; + + iBorderBitmap = InitializeBorderBitmapL( + *engine, node, + iBorderBitmapIndex, iBorderBitmapDividerTop, + iBorderBitmapDividerRight, + iBorderBitmapDividerBottom, iBorderBitmapDividerLeft, + iIconProvider, FsSession() ); + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::ConstructL +// 2nd phase constructor. Can leave. +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::ConstructL( + CXnNodePluginIf& aNode, + CXnControlAdapter& aAdapter, + CWindowGc& aGc ) + { + iGc = &aGc; + + iAdapter = &aAdapter; + + if ( CreateGestureHelperL( aNode.Node() ) ) + { + iGestureHelper = CXnGestureHelper::NewL( aNode.Node() ); + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::LoadBitmap +// Load a bitmap from the server. Ownership is transferred. +// ----------------------------------------------------------------------------- +// +CFbsBitmap* CXnControlAdapterImpl::LoadBitmap( const TDesC& aBitmapUrl ) + { + CXnNode& node( iNode.Node() ); + CXnUiEngine* engine( node.UiEngine() ); + + CFbsBitmap* bitmap( NULL ); + CFbsBitmap* mask( NULL ); + + TRect rect( node.Rect() ); + + TInt index( 0 ); + + TRAP_IGNORE( GetBitmapL( + *engine, node, + aBitmapUrl, index, + bitmap, mask, + iIconProvider, rect, FsSession() ) ); + + delete mask; + + return bitmap; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::GetBitmapAndMask +// Load a bitmap and mask from the server. Ownership is transferred. +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::GetBitmapAndMask( + const TDesC& aBitmapUrl, + const TDesC& aMaskUrl, + CFbsBitmap*& aBitmap, + CFbsBitmap*& aMask ) + { + CXnNode& node( iNode.Node() ); + CXnUiEngine* engine( node.UiEngine() ); + + TRect rect( node.Rect() ); + + TInt index( 0 ); + + TRAP_IGNORE( GetBitmapL( + *engine, node, + aBitmapUrl, index, + aBitmap, aMask, + iIconProvider, rect, FsSession() ) ); + + if ( !aMask ) + { + if ( aMaskUrl != KNullDesC ) + { + CFbsBitmap* bitmapMask( NULL ); + + TRAP_IGNORE( GetBitmapL( + *engine, node, + aMaskUrl, index, + aMask, bitmapMask, + iIconProvider, rect, FsSession() ) ); + + delete bitmapMask; + } + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::AnimFrameReady +// Callback of the animated skin background. +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::AnimFrameReady( TInt aError, TInt /* aAnimId */ ) + { + if ( !aError ) + { + iAdapter->DrawNow(); + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::CreateAnimationL +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::CreateAnimationL( /* TDesC& aPath */ ) + { + if ( iAnimation ) + { + delete iAnimation; + iAnimation = NULL; + } + + iAnimation = CAknsEffectAnim::NewL( this ); + TBool ok = iAnimation->ConstructFromSkinL( iAnimIID ); + if ( !ok ) + { + delete iAnimation; + iAnimation = NULL; + User::Leave( KErrNotSupported ); + } + + CXnNode& node = iComponent->Node()->Node(); + if ( !node.IsLaidOut() ) + { + // Animation is created before layout of nodes has been calculated + node.UiEngine()->LayoutUIL( &node ); + } + TRect rect( node.Rect() ); + + iAnimation->BeginConfigInputLayersL( rect.Size(), ETrue ); + + if ( iAnimation->InputRgbGc() ) + { + TRect mainPane; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPane ); + TRect mainPaneRect( mainPane.Size() ); + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = NULL; + const TAknsItemID* id = &KAknsIIDNone; + if ( AknsUtils::AvkonSkinEnabled() ) + { + cc = CAknsListBoxBackgroundControlContext::NewL( + KAknsIIDQsnBgAreaMainListGene, + mainPaneRect, + EFalse, + *id, + mainPaneRect ); + + AknsDrawUtils::DrawBackground( AknsUtils::SkinInstance(), + cc, + NULL, + *iAnimation->InputRgbGc(), + TPoint(), + rect, + KAknsDrawParamBottomLevelRGBOnly ); + } + } + + iAnimation->EndConfigInputLayersL(); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::StartHighlightAnimation() +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::StartHighlightAnimation( TBool aAnimRestart ) + { + TBool focused = EFalse; + + // No need to start animation again if already running + if ( iAnimation ) + { + if ( iAnimation->State() == EAknsAnimStateRunning && !aAnimRestart ) + { + return; + } + } + // Check control's focus + if ( iComponent ) + { + CXnNodePluginIf* pluginIf = iComponent->Node(); + if ( pluginIf ) + { + focused = pluginIf->IsFocusedState(); + } + else + { + return; + } + } + + // If the node is not focused or no Anim ID, return. + if ( !focused || !iAnimIDResolved ) + { + return; + } + + // Restart animation + if ( aAnimRestart ) + { + if ( iAnimation ) + { + iAnimation->Stop(); + delete iAnimation; + iAnimation = NULL; + + TRAPD( error, CreateAnimationL() ); + + if ( !error ) + { + iAnimation->Start(); + return; + } + } + } + + // Node is focused. Try to start animation. + if ( iAnimation ) + { + iAnimation->Start(); + } + else + { + TRAPD( error, CreateAnimationL() ); + + if ( !error ) + { + iAnimation->Start(); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::StopHighlightAnimation() +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::StopHighlightAnimation() + { + if ( iAnimation ) + { + // Stop animation and delete. + iAnimation->Stop(); + delete iAnimation; + iAnimation = NULL; + + iAdapter->DrawNow(); + } + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::MeasureAdaptiveContentL +// ----------------------------------------------------------------------------- +// +TSize CXnControlAdapterImpl::MeasureAdaptiveContentL( + const TSize& /* aAvailableSize */ ) + { + // By default the size is 0 + return TSize( 0, 0 ); + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::SetBlank +// +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::SetBlank( TBool aBlank ) + { + iBlank = aBlank; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::DoHandlePropertyChangeL +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::DoHandlePropertyChangeL( CXnProperty* /*aProperty*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::UpdateBackgroundImageL +// ----------------------------------------------------------------------------- +// +CXnControlAdapterImpl::TPropertyChangeResponse CXnControlAdapterImpl::UpdateBackgroundImageL( + CXnProperty* aProperty ) + { + if ( aProperty ) + { + const TDesC8& name( aProperty->Property()->Name() ); + + if ( name == XnPropertyNames::appearance::common::KBackGroundImage ) + { + delete iBackgroundBitmap; + iBackgroundBitmap = NULL; + + delete iBackgroundMask; + iBackgroundMask = NULL; + + delete iScaledTransparentColor; + iScaledTransparentColor = NULL; + + delete iScaledBackgroundSkin; + iScaledBackgroundSkin = NULL; + + delete iScaledBackgroundImage; + iScaledBackgroundImage = NULL; + + InitializeBackgroundBitmapL( *( iNode.Node().UiEngine() ), iNode.Node(), + iBackgroundBitmapIndex, iBackgroundBitmap, iBackgroundMask, + iIconProvider, FsSession()); + + return EPropertyChangeConsumed; + } + } + + return EPropertyChangeNotConsumed; + } + +// ----------------------------------------------------------------------------- +// CXnControlAdapterImpl::HandleScreenDeviceChangedL +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::HandleScreenDeviceChangedL() + { + } + +// ----------------------------------------------------------------------------- +// CreateBitmapFromColorL +// Creates a bitmap object with the given size and fill color +// ----------------------------------------------------------------------------- +// +static CFbsBitmap* CreateBitmapFromColorL( TSize aSize, TRgb aColor ) + { + CFbsBitmap* newBitmap = new ( ELeave ) CFbsBitmap; + newBitmap->Create( aSize, EColor16M ); + CleanupStack::PushL( newBitmap ); + + CFbsBitmapDevice* bitmapDev = CFbsBitmapDevice::NewL( newBitmap ); + CleanupStack::PushL( bitmapDev ); + + CFbsBitGc* bc = NULL; + User::LeaveIfError( bitmapDev->CreateContext( bc ) ); + CleanupStack::PushL( bc ); + + bc->SetBrushColor( aColor ); + bc->Clear(); // area is filled with the brush color + + CleanupStack::PopAndDestroy( bc ); + CleanupStack::PopAndDestroy( bitmapDev ); + CleanupStack::Pop( newBitmap ); + return newBitmap; + } + +// ----------------------------------------------------------------------------- +// PassEventToGestureHelperL +// Forwards event to gesturehelper +// ----------------------------------------------------------------------------- +// +TBool CXnControlAdapterImpl::PassEventToGestureHelperL( + const TPointerEvent& aPointerEvent ) + { + TBool ret( EFalse ); + + CXnNode* node( &iNode.Node() ); + CXnUiEngine* engine( node->UiEngine() ); + + if ( iGestureHelper && iGestureHelper->Owner() == node ) + { + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + // Set default destination + iGestureHelper->SetDestination( iGestureHelper->Owner() ); + + RPointerArray< CXnPluginData >& plugins( + engine->ViewManager()->ActiveViewData().PluginData() ); + + for ( TInt i = 0; i < plugins.Count(); i++ ) + { + CXnPluginData* plugin( plugins[i] ); + + if ( plugin->Occupied() ) + { + CXnNode* widget( plugin->Node()->LayoutNode() ); + + if ( widget->MarginRect().Contains( aPointerEvent.iPosition ) ) + { + // Resolve swipe destination + CXnProperty* prop( widget->GetPropertyL( + XnPropertyNames::common::KSwipeDestination ) ); + + if ( prop ) + { + const TDesC8& value( prop->StringValue() ); + + if( value == XnPropertyNames::KWidget ) + { + // Set widget as destination + iGestureHelper->SetDestination( widget ); + } + else if( value == XnPropertyNames::KNone ) + { + // Set no destination + iGestureHelper->SetDestination( NULL ); + } + } + + break; + } + } + } + } + + TSwipeResult result( iGestureHelper->HandlePointerEventL( aPointerEvent ) ); + + const TDesC8* swipe( NULL ); + + if ( result == ESwipeLeft ) + { + swipe = &XnPropertyNames::action::trigger::name::swipe::direction::KLeft; + } + else if ( result == ESwipeRight ) + { + swipe = &XnPropertyNames::action::trigger::name::swipe::direction::KRight; + } + + if ( swipe ) + { + CXnNode* destination( iGestureHelper->Destination() ); + + if ( destination ) + { + if ( destination == iGestureHelper->Owner() ) + { + CancelFocusRefusalL( *engine ); + } + + // Remove focus + engine->AppUiAdapter().HideFocus(); + + CXnNode* trigger( BuildSwipeTriggerNodeLC( *engine, *swipe ) ); + destination->ReportXuikonEventL( *trigger ); + CleanupStack::PopAndDestroy( trigger ); + + // If needed we can call here for example HandleSwipeL() + + // Consume this event + ret = ETrue; + } + } + } + + return ret; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::RemoveChildAdapters() + { + iChildren.Reset(); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +RPointerArray< CXnControlAdapter >& CXnControlAdapterImpl::ChildAdapters() + { + return iChildren; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +RFs& CXnControlAdapterImpl::FsSession() + { + return iAdapter->ControlEnv()->FsSession(); + } + + +// ============================= TIconProvider =============================== + +// ----------------------------------------------------------------------------- +// Constructor +// ----------------------------------------------------------------------------- +// +CXnControlAdapterImpl::TIconProvider::TIconProvider( RFile& aFile ) : + iFile( aFile ) + { + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CXnControlAdapterImpl::TIconProvider::~TIconProvider() + { + iFile.Close(); + } + +// ----------------------------------------------------------------------------- +// Retreive Icon handle +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::TIconProvider::RetrieveIconFileHandleL( + RFile& aFile, const TIconFileType /*aType*/) + { + aFile.Duplicate( iFile ); + } + +// ----------------------------------------------------------------------------- +// Finish +// ----------------------------------------------------------------------------- +// +void CXnControlAdapterImpl::TIconProvider::Finished() + { + iFile.Close(); + delete this; + } +