diff -r 000000000000 -r f72a12da539e idlehomescreen/xmluirendering/renderingplugins/xntextfactory/src/xntextadapter.cpp --- /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 +#include +#include +#include +#include + +#include +#include // for japanese variants. +#include +#include +#include + +#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(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( 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( *bc ) ); + CopyBitmapData( *iBackgroundBitmap, *tmpBitmap, iNode.Rect().iTl ); + CleanupStack::PopAndDestroy( 3 ); + } + +// ----------------------------------------------------------------------------- +// CXnTextAdapter::DrawBackground +// ----------------------------------------------------------------------------- +// +void CXnTextAdapter::DrawBackground(const TRect& aRect, CWindowGc& aGc) const + { + RPointerArray 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 +