idlehomescreen/xmluirendering/renderingplugins/xntextfactory/src/xntextadapter.cpp
changeset 0 f72a12da539e
child 15 ff572dfe6d86
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idlehomescreen/xmluirendering/renderingplugins/xntextfactory/src/xntextadapter.cpp	Thu Dec 17 08:40:49 2009 +0200
@@ -0,0 +1,1155 @@
+/*
+* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Implementation for wrapper for a label
+*
+*/
+
+
+#include <e32base.h>
+#include <coecntrl.h>
+#include <barsread.h>
+#include <gulcolor.h>
+#include <utf.h>
+
+#include <AknsUtils.h>
+#include <AknPictographInterface.h> // for japanese variants.
+#include <AknBidiTextUtils.h>
+#include <AknUtils.h>
+#include <AknLayoutFont.h>
+
+#include "xnnodepluginif.h"
+#include "xndompropertyvalue.h"
+#include "xndomproperty.h"
+#include "xndomlist.h"
+#include "xnproperty.h"
+#include "xncomponent.h"
+#include "xnuienginepluginif.h"
+#include "xncomponent.h"
+#include "xncontroladapter.h"
+#include "c_xnutils.h"
+#include "xntype.h"
+#include "xntextadapter.h"
+#include "xncomponentnodeimpl.h"
+#include "xnviewnodeimpl.h"
+#include "xneditmode.h"
+
+namespace XnText
+    {
+    const TUint8 KClip = 0x01;   
+    const TUint8 KEllipse = 0x02; 
+    const TUint8 KWrap = 0x04;    
+    const TUint8 KOverflowVisible = 0x08; 
+    const TUint8 KLtr = 0x10;     
+    const TUint8 KConstructText = 0x20;
+
+    _LIT8( tooltip, "tooltip" );
+    _LIT8( clock, "clock" );
+    }
+    
+// -----------------------------------------------------------------------------
+// IsBitSet
+// Test whether bit is set in a flag
+// -----------------------------------------------------------------------------
+static TBool IsBitSet(TUint8 aBit,TUint8 aFlag)
+    {
+    return ( aFlag & aBit );    
+    }
+    
+// -----------------------------------------------------------------------------
+// SetLabelTextL
+// Prepares text to label, wraps or clips if needed
+// -----------------------------------------------------------------------------
+static void SetLabelTextL( CEikLabel& aLabel, const TDesC& aSource, TInt aMaxLineWidth, 
+                           TInt aMaxLines, TUint8 aFlags, TBool aMeasureOnly = EFalse )    
+    {   
+    // By default, let the label do the logical to visual conversion                
+    TBool conversion( ETrue );
+    
+    if( IsBitSet( XnText::KOverflowVisible, aFlags ) || aSource == KNullDesC )
+        {        
+        // no clipping or wrapping needed if,
+        // overflow is visible
+        // no text or no space,
+        // or text fits to given space
+        aLabel.SetTextL( aSource );                        
+        }
+    else
+        {
+        AknBidiTextUtils::TParagraphDirectionality dir( AknBidiTextUtils::EImplicit );
+        
+        const CFont* font( aLabel.Font() );
+        
+        HBufC* buffer( NULL );
+        
+        if( IsBitSet( XnText::KEllipse, aFlags ) )
+    	    {	    
+            buffer = aSource.AllocLC();
+    	    
+    	    TPtr ptr( buffer->Des() );
+    	    	    	    
+            AknBidiTextUtils::ConvertToVisualAndClipL(
+    	                ptr, *font, aMaxLineWidth, aMaxLineWidth, dir );
+
+            
+            // The text is already in visual form, no need for conversion
+            conversion = EFalse;            
+            
+            aLabel.SetTextL( *buffer );            
+            
+            CleanupStack::PopAndDestroy( buffer );	        	                                    
+    	    }
+    	else if( IsBitSet( XnText::KWrap, aFlags ) )
+    	    {        	    
+    	    if( aMaxLines > 0 )
+    	        {
+        	    CArrayFixFlat< TInt >* array = new ( ELeave ) CArrayFixFlat< TInt >( 8 );
+        	    CleanupStack::PushL( array );
+    	        
+        	    for( TInt i = 0; i < aMaxLines; i++ )
+        	        {
+        	        array->AppendL( aMaxLineWidth );
+        	        }
+        	        
+                buffer = HBufC::NewLC( aSource.Length() + aMaxLines * 
+                                        ( KAknBidiExtraSpacePerLine + 1 ) );
+                
+                TPtr ptr( buffer->Des() );
+                
+        	    AknBidiTextUtils::ConvertToVisualAndWrapToStringL(
+        	                aSource, *array, *font, ptr, ETrue, dir );    	        
+    	        }
+            else
+                {
+        	    CArrayFixFlat< TPtrC >* array = new ( ELeave ) CArrayFixFlat< TPtrC >( 8 );
+        	    CleanupStack::PushL( array );
+                
+                HBufC* temp = AknBidiTextUtils::ConvertToVisualAndWrapToArrayL(
+                            aSource, aMaxLineWidth, *font, *array, dir );
+                            
+                CleanupStack::PushL( temp );
+                
+                TInt lineCount( array->Count() );
+                
+                buffer = HBufC::NewLC( temp->Length() + ( lineCount - 1 ) );
+                
+                TPtr ptr( buffer->Des() );
+                                                
+                for( TInt i = 0; i < lineCount; i++ )
+                    {
+                    TPtrC line( array->At( i ) );
+                    
+                    ptr.Append( line );
+                    
+                    if( i + 1 < lineCount )
+                        {
+                        ptr.Append( '\n' );
+                        }                    
+                    }
+                    
+                CleanupStack::Pop();
+                CleanupStack::PopAndDestroy( temp );
+                CleanupStack::PushL( buffer );                                                    
+                }    	        
+
+            // The text is already in visual form, no need for conversion
+            conversion = EFalse;
+
+            aLabel.SetTextL( *buffer );            
+                        
+            CleanupStack::PopAndDestroy( 2 ); // buffer, array                                       
+    	    }
+        else
+            {
+            aLabel.SetTextL( aSource );            
+            }    	                   
+        } 
+    
+    if( !aMeasureOnly )
+        {     
+        // Text is truly set, set conversion and defer draw
+        aLabel.UseLogicalToVisualConversion( conversion );                    
+        }
+    }
+      
+// -----------------------------------------------------------------------------
+// CopyBitmapData
+// Copies a data from source bitmap to target bitmap.
+// -----------------------------------------------------------------------------
+//
+static TInt CopyBitmapData(
+    CFbsBitmap& aTarget,
+    const CFbsBitmap& aSource,
+    TPoint aSourcePoint)
+	{
+    TSize targetSize(aTarget.SizeInPixels());
+    TSize sourceSize(aSource.SizeInPixels());
+    TInt lineLength(targetSize.iWidth);
+    TInt maxSourceLineLength(sourceSize.iWidth - aSourcePoint.iX);
+    if(lineLength > maxSourceLineLength)
+        {
+        lineLength = maxSourceLineLength;
+        }
+    TInt rowCount(targetSize.iHeight);
+    TInt maxSourceRowCount(sourceSize.iHeight - aSourcePoint.iY);
+    if(rowCount > maxSourceRowCount)
+        {
+        rowCount = maxSourceRowCount;
+        }
+
+    // Get bitmap display mode
+	TDisplayMode displayMode(aSource.DisplayMode());
+
+    // Create buffer for a scan line
+	HBufC8* scanLine = HBufC8::New(
+        aSource.ScanLineLength(lineLength, displayMode));
+    if(!scanLine)
+    	{
+    	return KErrNoMemory;
+    	}
+     
+	TPtr8 scanPtr(scanLine->Des());
+
+    // Copy all rows to destination bitmap
+	for(TInt row(0); row < rowCount; row++)
+		{
+		aSource.GetScanLine(scanPtr,
+            TPoint(aSourcePoint.iX, aSourcePoint.iY + row),
+            lineLength, displayMode);
+		aTarget.SetScanLine(scanPtr, row);
+		}
+    delete scanLine;
+	return KErrNone;
+	}        
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::NewL
+// Symbian static 1st phase constructor
+// -----------------------------------------------------------------------------
+//
+CXnTextAdapter* CXnTextAdapter::NewL(CXnControlAdapter* aParent, CXnNodePluginIf& aNode)
+    {
+	CXnTextAdapter* self = new( ELeave ) CXnTextAdapter( aParent, aNode );
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    return self;	
+    }
+    
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::CXnTextAdapter
+// C++ default constructor
+// -----------------------------------------------------------------------------
+//
+CXnTextAdapter::CXnTextAdapter(CXnControlAdapter* aParent, CXnNodePluginIf& aNode)
+    : iParent( aParent ), iNode( aNode )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::~CXnTextAdapter
+// C++ destructor
+// -----------------------------------------------------------------------------
+//
+CXnTextAdapter::~CXnTextAdapter()
+    {    
+    delete iLabel;
+    
+    delete iText;
+    
+    if( iFont && iReleaseFont )
+        {
+        CWsScreenDevice* dev = iCoeEnv->ScreenDevice();
+        dev->ReleaseFont( iFont ); 
+        }
+        
+    if( iPictographInterface )
+    	{
+    	delete iPictographInterface;
+    	}
+
+    delete iBackgroundBitmap;
+    }
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CXnTextAdapter::ConstructL()
+    {
+    iGc = &SystemGc();
+       
+    iLabel = new ( ELeave ) CEikLabel;
+    iLabel->SetContainerWindowL( *iParent );
+    iLabel->SetTextL( KNullDesC );
+    
+    CXnControlAdapter::ConstructL( iNode );
+            
+    iPictographInterface = CAknPictographInterface::NewL( *iLabel, *this );
+    iLabel->EnablePictographsL( *iPictographInterface );
+                            
+    SetTextPropertiesL( iNode );
+    UpdateTextL( iNode.GetPCData() );    
+	}
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::ConstructTextL
+// Construct the text component according to properties.
+// -----------------------------------------------------------------------------
+//    
+void CXnTextAdapter::ConstructTextL()
+    {   
+    if( !iText )        
+        {
+        // CEikLabel will panic in ::Draw if text is not set
+        SetLabelTextL( *iLabel, KNullDesC, 0, 0, 0 );
+        return;
+        }
+    
+    if( !( iFlags & XnText::KConstructText ) )
+        {
+        return;
+        }
+                                   
+    TRect rect( iNode.Rect() );
+
+	SetLineSpacingL( rect.Height() );
+	
+	TInt flags( iFlags );
+	               
+    // Now we must restrict side into parent        
+    flags = RestrictSizeL();
+                                                                                                                  
+    SetLabelTextL( *iLabel, *iText, iLabel->Rect().Width(), iMaxLines, flags );                       
+    }
+    
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::SetTextPropertiesL
+// Sets text properties, such as color, font, etc.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CXnTextAdapter::SetTextPropertiesL( CXnNodePluginIf& aNode )
+    {
+    // Store current state
+    const CFont* font( iFont );
+    TInt flags( iFlags );
+    TInt maxLines( iMaxLines );
+    
+    if( iFont && iReleaseFont )
+        {
+        CWsScreenDevice* dev = iCoeEnv->ScreenDevice();
+        dev->ReleaseFont( iFont ); 
+        iFont = NULL;
+        }
+    
+    // Find out the font and set it
+    CXnUtils::CreateFontL( aNode, iFont, iReleaseFont );
+    iLabel->SetFont( iFont );
+    
+    // Turn off all graphic context effects
+    iLabel->SetUnderlining( EFalse );
+    iLabel->SetStrikethrough( EFalse );
+    
+    //following data types are used due to we are handling text via CEikLabel instead of direct
+    //font color and effects manipulation via graphics context.
+    //We manipulate pen and brush colors indirectly via
+    //Label's OverrideColorL method applying EColorControlBackground and EColorLabelText parameters
+    //with corresponding RGB value.
+    TRgb textColor;
+    TRgb effectsColor;
+    TBool textColorSet( EFalse );
+    TBool effectsColorSet( EFalse );
+    TBool effectsDevColorSet( EFalse );
+    
+    CXnProperty* colorProperty = aNode.GetPropertyL( XnPropertyNames::appearance::common::KColor );
+    
+    if( colorProperty != NULL )
+        {
+        CXnDomProperty* domProperty = colorProperty->Property();
+        
+        if( domProperty )
+            {
+            TInt error( KErrNotSupported );
+
+            CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >
+                                            ( domProperty->PropertyValueList().Item( 0 ) );
+            
+            if( value->IsAutoIdent() )
+                {
+                MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+                error = AknsUtils::GetCachedColor(skinInstance, textColor, KAknsIIDQsnTextColors,
+                EAknsCIQsnTextColorsCG6);
+                }
+            else if( value->PrimitiveValueType() == CXnDomPropertyValue::ERgbColor )
+                {
+                textColor = value->RgbColorValueL();
+                error = KErrNone;
+                }
+            else
+            	{
+                HBufC* colorString = colorProperty->StringValueL();
+                CleanupStack::PushL( colorString );
+                
+                CXnUtils::StripQuotes( colorString );
+                
+                TInt index = 0;
+                TAknsItemID skinID;
+                
+                TBool idResolved = CXnUtils::ResolveSkinItemIDL( colorString->Des(), skinID, index );
+                
+                if( idResolved )
+                	{
+                	MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+                	error = AknsUtils::GetCachedColor( skinInstance, textColor, skinID, index );
+                	}
+                else // use auto value if skin id is invalid.
+                	{
+	                MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+	                error = AknsUtils::GetCachedColor(skinInstance, textColor, KAknsIIDQsnTextColors,
+	                EAknsCIQsnTextColorsCG6);
+	                }
+            	CleanupStack::PopAndDestroy( colorString );                	
+            	}
+            if (error == KErrNone)
+                {
+                textColorSet = ETrue;
+                }
+            }
+        }
+    
+    CXnProperty* effectsProperty = aNode.GetPropertyL(XnPropertyNames::appearance::common::KTextEffects);
+    if ( effectsProperty )
+        {
+        TInt error(KErrNotSupported);
+        effectsDevColorSet = ETrue; //some color needed, device color by default
+        CXnProperty* effectsColorProperty = aNode.GetPropertyL(XnPropertyNames::appearance::common::KEffectsColor);
+        if (effectsColorProperty)
+            {
+            CXnDomProperty* domProperty = effectsColorProperty->Property();
+            if( domProperty )
+                {
+                CXnDomPropertyValue* value = static_cast<CXnDomPropertyValue*>(domProperty->PropertyValueList().Item(0));
+                    if (value->IsAutoIdent())
+                        {
+                        MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+                        error = AknsUtils::GetCachedColor(skinInstance, effectsColor, KAknsIIDQsnTextColors,
+                        EAknsCIQsnTextColorsCG6);
+                        }
+                    else if (value->PrimitiveValueType() == CXnDomPropertyValue::ERgbColor)
+                        {
+                        effectsColor = value->RgbColorValueL();
+                        error = KErrNone;
+                        }
+                        else
+                        	{
+                            HBufC* colorString = effectsColorProperty->StringValueL();
+                            CleanupStack::PushL( colorString );
+                            CXnUtils::StripQuotes( colorString );
+                            
+                            TInt index = 0;
+                            TAknsItemID skinID;
+                            
+                            TBool idResolved = CXnUtils::ResolveSkinItemIDL( colorString->Des(), skinID, index );
+                            if( idResolved )
+                            	{
+                            	MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+                            	error = AknsUtils::GetCachedColor( skinInstance, effectsColor, skinID, index );
+                            	}
+                            else // use auto value if skin id is invalid.
+                            	{
+            	                MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+            	                error = AknsUtils::GetCachedColor(skinInstance, effectsColor, KAknsIIDQsnTextColors,
+            	                EAknsCIQsnTextColorsCG6);
+            	                }
+                        	CleanupStack::PopAndDestroy( colorString );                	
+                        	}
+                if ( error == KErrNone )
+                	{
+                    effectsColorSet = ETrue; //theme color found
+                    effectsDevColorSet = EFalse;//device color not needed
+                    }
+                }
+            }
+        }
+
+    if ( textColorSet )
+        {
+        if ( effectsColorSet )
+            {//theme font color and theme effects color
+            iLabel->OverrideColorL(EColorControlBackground, textColor);
+            iLabel->OverrideColorL(EColorLabelText, effectsColor);
+            }
+        else if ( effectsDevColorSet )
+            {//theme font color and device effects color
+            iLabel->OverrideColorL(EColorControlBackground, textColor);
+            }
+        else
+            {//theme font color, but no effects defined
+            iLabel->OverrideColorL(EColorLabelText, textColor);
+            }
+        }
+    else if ( effectsColorSet )
+            {//device font color and theme effects color
+            iLabel->OverrideColorL(EColorLabelText, effectsColor);
+            }//else device font color and device effects color (default)
+
+    CXnProperty* textDecorationProp = aNode.GetPropertyL( XnPropertyNames::appearance::common::KTextDecoration );
+    
+    if( textDecorationProp )
+        {
+        CXnDomList& propertyValueList = textDecorationProp->Property()->PropertyValueList();
+        
+        TInt valueCount = propertyValueList.Length();
+        
+        for( TInt i = 0; i < valueCount; ++i )
+            {
+            CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( propertyValueList.Item( i ) );
+            
+            if( value->StringValueL() == XnPropertyNames::appearance::common::textdecoration::KUnderline )
+                {
+                iLabel->SetUnderlining( ETrue );
+                }
+
+            if( value->StringValueL() == XnPropertyNames::appearance::common::textdecoration::KLinethrough )
+                {
+                iLabel->SetStrikethrough( ETrue );
+                }
+            }
+        }
+       
+    iFlags = 0;
+    iFlags |= XnText::KEllipse; //default
+    iFlags |= XnText::KLtr; 
+    iMaxLines = 0;
+    
+    TGulAlignmentValue alignment = CXnUtils::TextAlignment( aNode );
+    
+    TInt labelAlignment( ELayoutAlignLeft ); // all are vertically top aligned by default (avkon)
+    
+    switch( alignment )
+        {
+        case EHCenterVCenter:            
+            labelAlignment = ELayoutAlignCenter;                 
+            break;
+        case EHRightVCenter:            
+            labelAlignment = ELayoutAlignRight;                
+            break;
+        default: 
+            break;    
+        }
+    
+    iLabel->SetLabelAlignment( labelAlignment ); // avkon extension needs this, it modifys horizontal alignment
+    iLabel->SetAlignment( alignment ); // call to have vertical alignment
+  
+    CXnProperty* direction = iNode.GetPropertyL( XnPropertyNames::style::common::KDirection );
+    const TDesC8* directionValue = &XnPropertyNames::style::common::direction::KLTR;
+    
+    if( direction )
+        {
+        directionValue = &direction->StringValue();    
+        }
+    
+    if( *directionValue == XnPropertyNames::style::common::direction::KRTL )
+        {
+        iLabel->SetLabelAlignment( ELayoutAlignBidi );     
+        iFlags &= ~XnText::KLtr;
+        }
+        	            
+    CXnProperty* overflowProp = aNode.GetPropertyL( XnPropertyNames::appearance::common::KTextOverflowMode );
+    
+    if( overflowProp )
+        {
+        CXnDomList& propertyValueList = overflowProp->Property()->PropertyValueList();
+        
+        TInt valueCount = propertyValueList.Length();
+        
+        for( TInt i = 0; i < valueCount; ++i )
+            {
+            CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( propertyValueList.Item( i ) );
+            
+            if( value->StringValueL() == XnPropertyNames::appearance::common::textoverflow::KClipMode )
+                {
+                iFlags |= XnText::KClip;
+                iFlags &= ~XnText::KWrap;
+                iFlags &= ~XnText::KEllipse;                
+                }
+            else if( value->StringValueL() == XnPropertyNames::appearance::common::textoverflow::KWrapMode )
+                {
+                iFlags |= XnText::KWrap;
+                iFlags &= ~XnText::KClip;
+                iFlags &= ~XnText::KEllipse;
+                }                
+            }
+            
+        //Get max lines amount for wrap
+        if( iFlags & XnText::KWrap )
+            {
+            CXnProperty* maxlinesProp = aNode.GetPropertyL( XnPropertyNames::appearance::common::textoverflow::KMaxLineAmount );
+            
+            if( maxlinesProp )
+                {
+                iMaxLines = static_cast< TInt >( maxlinesProp->FloatValueL() );
+                }
+            }
+        }
+        
+    CXnProperty* overflowProperty = iNode.GetPropertyL( XnPropertyNames::style::common::KOverflow );
+    
+    if( overflowProperty )
+        {
+        const TDesC8& overflowValue = overflowProperty->StringValue();
+        
+        if( overflowValue == XnPropertyNames::style::common::visibility::KVisible )
+            {
+            iFlags |= XnText::KOverflowVisible;
+            }
+        }
+        
+    if( flags & XnText::KConstructText )
+        {
+        iFlags |= XnText::KConstructText;
+        }
+        
+    if( font != iFont || flags != iFlags || maxLines != iMaxLines )
+        {
+        return ETrue;
+        }
+        
+    return EFalse;        
+    }
+        
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::SetTextL
+// Sets the new content to the underlying CEikLabel
+// -----------------------------------------------------------------------------
+//
+void CXnTextAdapter::SetTextL( const TDesC& aText )
+    {      
+    UpdateTextL( &aText );          
+    }
+	
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::Text
+// Returns the text contained in the underlying CEikLabel
+// -----------------------------------------------------------------------------
+//
+const TDesC* CXnTextAdapter::Text() const
+    {
+    if( iFlags & XnText::KConstructText )
+        {
+        return iText;
+        }
+    else
+        {
+        return iLabel->Text();
+        }            
+    }
+    
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::CountComponentControls
+// Returns the number of component controls.
+// -----------------------------------------------------------------------------
+//
+TInt CXnTextAdapter::CountComponentControls() const
+    {
+    return 1;
+    }
+    
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::ComponentControl
+// Returns the component control of the given index
+// -----------------------------------------------------------------------------
+//
+CCoeControl* CXnTextAdapter::ComponentControl(TInt aIndex) const
+    {
+    if( aIndex == 0 )
+        {
+        return iLabel;
+        }
+
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::DoHandlePropertyChangeL
+// -----------------------------------------------------------------------------
+//
+void CXnTextAdapter::DoHandlePropertyChangeL(CXnProperty* aProperty)
+    {        
+    if( aProperty )
+        {
+        const TDesC8& name( aProperty->Property()->Name() );
+        
+        if( name == XnPropertyNames::style::common::KDisplay || 
+            name == XnPropertyNames::style::common::KVisibility ||
+            name == XnPropertyNames::style::common::KWidth ||
+            name == XnPropertyNames::style::common::KHeight )
+            {
+            return;
+            }
+        
+        if( name == XnPropertyNames::common::KPCData )
+            {
+            UpdateTextL( iNode.GetPCData() );
+            }
+        }
+               
+    if( SetTextPropertiesL( iNode ) )
+        {
+        iFlags |= XnText::KConstructText;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::HandleResourceChange
+// -----------------------------------------------------------------------------
+//
+void CXnTextAdapter::HandleScreenDeviceChangedL()
+    {
+    if( SetTextPropertiesL( iNode ) )
+        {
+        iFlags |= XnText::KConstructText;
+        }
+
+    CXnControlAdapter::HandleScreenDeviceChangedL();        
+    }
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::HandlePointerEventL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+// 
+void CXnTextAdapter::HandlePointerEventL( const TPointerEvent& aPointerEvent )
+    {
+	if( AknLayoutUtils::PenEnabled() )
+	    {
+	    CXnControlAdapter::HandlePointerEventL( aPointerEvent );
+	    }
+    }
+
+// ---------------------------------------------------------
+// CXnTextAdapter::SizeChanged()
+// Called by framework when the view size is changed
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CXnTextAdapter::SizeChanged()
+    {
+    TRAP_IGNORE( SizeChangedL() );
+    }
+    
+ // ---------------------------------------------------------
+// CXnTextAdapter::SizeChangedL()
+// ---------------------------------------------------------
+//
+void CXnTextAdapter::SizeChangedL()
+    {
+    if( SetTextPropertiesL( iNode ) )
+        {
+        iFlags |= XnText::KConstructText;
+        }
+    
+    TRect rect( iNode.Rect() );
+
+    TRect labelRect( iLabel->Rect() );
+    iLabel->SetRect( rect );
+    
+    if( iText )
+        {
+    	TInt textWidth( iLabel->Font()->TextWidthInPixels( *iText ) );
+           
+        TInt rectWidth( rect.Width() );
+                
+        if( iFlags & XnText::KOverflowVisible ) 
+            {            
+            TBool isTooltip( iNode.ParentL()->Type()->Type() == XnText::tooltip );
+
+            // Tooltip can grow and shrink, others just grow                        
+            if( isTooltip || textWidth > rectWidth ) 
+                {    
+                rect = Rect();
+                                        
+                TInt dx( textWidth - rectWidth );
+                                                                                                                        
+                if( dx != 0 )
+                    {                
+                    rect.Resize( dx, 0 );
+                    SetSizeWithoutNotification( rect.Size() );                                                                
+
+                    // Update                 
+                    iLabel->SetRect( rect );                               
+                    }                       
+                }
+            }            
+        }
+    if( labelRect != iLabel->Rect() )
+    	{
+        iFlags |= XnText::KConstructText;
+    	}
+    }
+
+// ---------------------------------------------------------
+// CXnTextAdapter::SkinChanged()
+// Called by framework when the skin is changed
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CXnTextAdapter::SkinChanged()
+    {    
+    TRAP_IGNORE
+        ( 
+        if( SetTextPropertiesL( iNode ) )
+            {
+            iFlags |= XnText::KConstructText;
+            }
+        );    
+    }
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::Draw
+// Draws the text component
+// -----------------------------------------------------------------------------
+//
+void CXnTextAdapter::Draw(const TRect& aRect) const
+    {   
+    CXnTextAdapter* adapter = const_cast< CXnTextAdapter* >( this );
+
+    if( iFlags & XnText::KConstructText )
+        {
+        TRAPD( err, adapter->ConstructTextL() );                        
+        
+        adapter->iFlags &= ~XnText::KConstructText;
+        
+        if( err )
+            {
+            return;
+            }
+        }
+                               
+    CXnControlAdapter::Draw( aRect );
+    
+    if( iPictographInterface )
+    	{
+	    TRAP_IGNORE( UpdateBackgroundL() );
+	    iGc->BitBlt( iNode.Rect().iTl, iBackgroundBitmap );
+    	}
+    }
+    
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::DrawPictographArea
+// Draws the text component
+// -----------------------------------------------------------------------------
+//    
+void CXnTextAdapter::DrawPictographArea()
+    {
+    DrawNow();	
+    }
+	
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::UpdateBackgroundL
+// -----------------------------------------------------------------------------
+//   	
+void CXnTextAdapter::UpdateBackgroundL() const
+	{
+	CGraphicsDevice* gdevice = iGc->Device();
+	TDisplayMode displayMode = gdevice->DisplayMode();
+	
+	// create "screenshot" from the background appearance
+	if( iBackgroundBitmap )
+		{
+		delete iBackgroundBitmap;
+		iBackgroundBitmap = NULL;
+		}
+
+	iBackgroundBitmap = new (ELeave) CFbsBitmap();
+	iBackgroundBitmap->Create( iNode.Rect().Size(), displayMode );
+	CFbsBitmap* tmpBitmap = new (ELeave) CFbsBitmap;
+	CleanupStack::PushL( tmpBitmap );
+	
+	CWsScreenDevice* scrDevice = static_cast<CWsScreenDevice*>( iGc->Device() );
+	TSize tmpSize = scrDevice->SizeInPixels();
+	tmpBitmap->Create( tmpSize, displayMode );
+	
+	CFbsBitmapDevice* tmpDevice = CFbsBitmapDevice::NewL( tmpBitmap );
+	CleanupStack::PushL( tmpDevice );
+	CBitmapContext* bc( NULL );
+	tmpDevice->CreateBitmapContext( bc );
+	CleanupStack::PushL( bc );
+	DrawBackground( iNode.Rect(), reinterpret_cast<CWindowGc&>( *bc ) );
+	CopyBitmapData( *iBackgroundBitmap, *tmpBitmap, iNode.Rect().iTl );
+	CleanupStack::PopAndDestroy( 3 );
+	}
+	
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::DrawBackground
+// -----------------------------------------------------------------------------
+//   	
+void CXnTextAdapter::DrawBackground(const TRect& aRect, CWindowGc& aGc) const
+	{
+	RPointerArray<CXnControlAdapter> adapters;
+
+	for( CXnNodePluginIf* node = &iNode; node; )
+		{
+        TRAP_IGNORE( 
+		    CXnControlAdapter* adapter( node->Control() );
+
+		    if ( adapter )
+    		    {
+	    	    adapters.AppendL( adapter );  
+		        }
+
+		    node = node->ParentL()
+		    );
+        }
+
+    for( TInt i = adapters.Count() - 1; i >= 0; --i )
+        {
+        adapters[i]->Draw( aRect, aGc );
+        }
+
+    adapters.Reset();
+	}    
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::MeasureAdaptiveContentL
+// -----------------------------------------------------------------------------
+// 
+TSize CXnTextAdapter::MeasureAdaptiveContentL( const TSize& aAvailableSize )
+    {         
+    TSize size;
+    
+    if( ( aAvailableSize.iWidth > 0 ) && ( aAvailableSize.iHeight > 0 ) )
+        {  
+        size = MeasureTextL( aAvailableSize );           
+        }
+        
+    return size;
+    }
+
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::RestrictSizeL
+// -----------------------------------------------------------------------------
+//     
+TInt CXnTextAdapter::RestrictSizeL()
+    {        
+    CXnNodePluginIf* parent( iNode.ParentL() );
+    
+    if( !parent )
+        {
+        // No parent where to restrict own size
+        return iFlags;
+        }
+       
+    TRect parentRect( parent->Rect() );
+    
+    if( parentRect.IsEmpty() )
+        {
+        return iFlags;
+        }
+    
+    TRect rect( Rect() );
+    
+    TInt dx( 0 );
+    TInt dy( 0 );
+            
+    // Restrict own size inside parent rect to prevent flowing outside parent's rect
+    if( rect.iBr.iX > parentRect.iBr.iX )
+        {
+        dx = rect.iBr.iX - parentRect.iBr.iX;       
+        }
+        
+    if( rect.iBr.iY > parentRect.iBr.iY )
+        {
+        dy = rect.iBr.iY - parentRect.iBr.iY;
+        }
+
+    if( dx == 0 && dy == 0 )
+        {
+        // No need to change sizes
+        return iFlags;
+        }
+                
+    TInt flags( iFlags );
+    
+    if( parent->Type()->Type() == XnText::tooltip )
+        {
+        // Remove temporarily to allow tooltip truncation
+        flags &= ~XnText::KOverflowVisible;
+        }
+    
+    // Clip text again, parent size restriction may result in re-clipping    
+    if( !IsBitSet( XnText::KOverflowVisible, flags ) )
+        {
+        TSize size( rect.Size() );
+        
+        size.iWidth -= dx;
+        size.iHeight -= dy;
+        
+        // Update own size ...    
+        SetSizeWithoutNotification( size );
+
+        // ... and label        
+        rect = iLabel->Rect();
+        
+        rect.Resize( -dx, -dy );
+            
+        iLabel->SetRect( rect );               
+        }
+        
+    return flags;                                
+    }
+        
+// -----------------------------------------------------------------------------
+// CXnTextAdapter::SetLineSpacingL
+// -----------------------------------------------------------------------------
+//     
+void CXnTextAdapter::SetLineSpacingL( TInt aReference )
+    {
+    // Set linespacing, one pixel is the default
+    TInt lineSpace( 1 );
+    
+    CXnProperty* lineSpaceProp( 
+        iNode.GetPropertyL( XnPropertyNames::appearance::common::KFontLineSpace ) );
+
+    if( lineSpaceProp )
+        {        
+        lineSpace = iNode.UiEngineL()->VerticalPixelValueL( lineSpaceProp, aReference );
+        }
+        
+    if( lineSpace < 1 )
+        {
+        // Must be at least 1
+        lineSpace = 1;
+        }
+
+    const CAknLayoutFont* layoutFont( CAknLayoutFont::AsCAknLayoutFontOrNull( iFont ) );         
+        
+    if( layoutFont )
+        {
+        TInt textPaneHeight = layoutFont->TextPaneHeight();
+        
+        lineSpace += ( textPaneHeight - iFont->HeightInPixels() );        
+        }
+    /* end of CEikLabel fix */        
+    
+    iLabel->SetPixelGapBetweenLines( lineSpace );   
+    }
+
+// -----------------------------------------------------------------------------
+// MeasureTextL
+// Measures the text dimensions fitted to available size
+// -----------------------------------------------------------------------------
+//    
+TSize CXnTextAdapter::MeasureTextL( const TSize& aAvailableSize )    
+    {
+    TSize size;
+    
+    if( !iText || *iText == KNullDesC )
+        {
+        return size;
+        }
+                                              
+    // Save the current text before measure
+    HBufC* original( iLabel->Text()->AllocLC() );
+
+    SetLineSpacingL( 0 );
+                                                                                                                                                      
+    SetLabelTextL( *iLabel, *iText, aAvailableSize.iWidth, iMaxLines, iFlags, ETrue );
+    
+    TPtrC text( *iLabel->Text() );
+                    
+    // help CEikLabel to calculate its content size more precisely
+    iLabel->iMargin.iBottom = iLabel->Font()->DescentInPixels();
+
+    // Get the size needed for the text                        
+    size = iLabel->CalcMinimumSize( text );            
+    
+    // Restore original text
+    iLabel->SetTextL( *original );
+    CleanupStack::PopAndDestroy( original );        
+           
+    return size;                            	                  
+    }
+
+// -----------------------------------------------------------------------------
+// UpdateTextL
+// -----------------------------------------------------------------------------
+//    
+void CXnTextAdapter::UpdateTextL( const TDesC8& aText )
+    {
+    HBufC* text( CnvUtfConverter::ConvertToUnicodeFromUtf8L( aText ) );
+    
+    CleanupStack::PushL( text );
+    
+    UpdateTextL( text );
+    
+    CleanupStack::PopAndDestroy( text );
+    }
+
+// -----------------------------------------------------------------------------
+// UpdateTextL
+// -----------------------------------------------------------------------------
+//    
+void CXnTextAdapter::UpdateTextL( const TDesC* aText )
+    {
+    if( aText )
+        {
+        if( iText && *iText == *aText )
+            {
+            // New text is same as current
+            return;
+            }
+            
+        if( iText && iText->Des().MaxLength() >= aText->Length() )
+            {
+            // New text fits to earlier allocated space
+            *iText = *aText;
+            }
+        else
+            {
+            // Need to reserve space for new text
+            delete iText;
+            iText = NULL;
+            iText = aText->AllocL();
+            }            
+           
+    	TPtr ptr( iText->Des() );
+    	
+    	CXnUtils::CollapseWhiteSpace( iNode, ptr );	             
+            
+        iFlags |= XnText::KConstructText;
+        
+        iNode.SetDirtyL();
+        
+        const TDesC8& parentType( iNode.ParentL()->Type()->Type() );
+        
+        if( parentType == XnText::tooltip )
+        	{
+        	// Force tooltip text size to be recalculted by layout algorithm
+        	SetSizeWithoutNotification( TSize() );
+        	}
+        else if( parentType == XnText::clock )
+            {
+            iNode.ParentL()->SetDirtyL();
+            }
+        }
+    }
+
+// End of file
+