diff -r 000000000000 -r 2f259fa3e83a uifw/ganes/src/HgDrawUtils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/ganes/src/HgDrawUtils.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,504 @@ +/* +* Copyright (c) 2009 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: +* +*/ + + +#include "HgDrawUtils.h" + +#include "HgMarquee.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const TInt KHgDrawUtilsGranularity(10); +const TInt KHgDrawUtilsMaxNumberOfLines(4); + +CHgDrawUtils* CHgDrawUtils::NewL( TCallBack& aMarqueeCallback ) + { + CHgDrawUtils* self = new (ELeave) CHgDrawUtils(); + CleanupStack::PushL( self ); + self->ConstructL( aMarqueeCallback ); + CleanupStack::Pop(self); + return self; + } + +CHgDrawUtils::~CHgDrawUtils() + { + delete iMarquee; + } + + +void DrawEmptyListImpl_real_DrawUpToTwoLines( CGraphicsContext &aGc, + TPtrC aText, + TAknLayoutText &aLine1, + TAknLayoutText &aLine2, + TInt aLine1length, + TInt aLine2length, + const CFont* aFont, + TRgb aColor, + TDes& aBuffer ) + { + TRAPD( error, + { + CArrayFix* wrapWidthArray = new( ELeave ) CArrayFixFlat(KHgDrawUtilsGranularity); + CleanupStack::PushL( wrapWidthArray ); + + wrapWidthArray->AppendL( aLine1length ); + wrapWidthArray->AppendL( aLine2length ); + + AknBidiTextUtils::ConvertToVisualAndWrapToStringL( + aText, *wrapWidthArray, *aFont, aBuffer, ETrue ); + + CleanupStack::PopAndDestroy( wrapWidthArray ); // wrapWidthArray + } ); // TRAP end + + if ( error != KErrNone ) + { + aBuffer = aText; + } + + // Drawing text + aGc.Reset(); + TBool oneline( EFalse ); + TPtrC ptr = aBuffer; + TPtrC top = ptr; + TInt off = ptr.Locate('\n'); + if ( off >= 0 ) + { + top.Set(ptr.Left(off)); + ptr.Set(ptr.Mid(off+1)); + + TInt off1 = ptr.Locate('\n'); + if ( off1 >= 0 ) + { + ptr.Set(ptr.Left(off1)); + } + else + { + oneline = ETrue; + } + } + + aGc.SetBrushStyle(CGraphicsContext::ENullBrush); + + // no layout exist for popup list - mainpane layout is ok for X + // coords, center vertically. Also need to calculate vertical + // position for mainpane lists, since laf is broken as designed. + // If you don't believe this, try using laf values in phonebook. + aGc.UseFont( aFont ); + aGc.SetPenColor( aColor ); + + aLine1.DrawText(aGc, top, EFalse, aColor ); + if ( !oneline ) + { + aLine2.DrawText( aGc, ptr, EFalse, aColor ); + } + aGc.DiscardFont(); + } + +void DrawEmptyListImpl_real_DrawMoreThanTwoLines( const TRect &aParentRect, + CGraphicsContext &aGc, + TPtrC aText, + TRgb aColor, + TDes& buffer ) + + { + // fetch layouts + TAknLayoutText line[KHgDrawUtilsMaxNumberOfLines]; + + line[0].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t1(2) ); + line[1].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t3(0) ); + line[2].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t4(0) ); + line[3].LayoutText( aParentRect, AknLayoutScalable_Avkon::main_pane_empty_t5(0) ); + + TInt lineLength[KHgDrawUtilsMaxNumberOfLines]; + TInt i; + for ( i = 0; i < KHgDrawUtilsMaxNumberOfLines; i++ ) + { + lineLength[i] = line[i].TextRect().Width(); + } + + const CFont *bigFont = line[0].Font(); + const CFont *smallFont = line[1].Font(); + + // wrap text + TInt off = aText.Locate('\n'); + TPtrC rest( aText ); + rest.Set( aText.Right(aText.Length() - off - 1 )); + + HBufC* firstLine = NULL; + + TRAPD( error1, + { + firstLine = HBufC::NewL( + aText.Left(off).Length() + KAknBidiExtraSpacePerLine ); + }); + + if (error1 == KErrNone) + { + TPtr firstLinePtr = firstLine->Des(); + AknBidiTextUtils::ConvertToVisualAndClip( + aText.Left(off), + firstLinePtr, + *bigFont, + lineLength[0], + lineLength[0] ); + } + + TRAPD( error2, + { + CArrayFix* wrapWidthArray = new( ELeave ) CArrayFixFlat(KHgDrawUtilsGranularity); + CleanupStack::PushL( wrapWidthArray ); + + // wrap small font lines + wrapWidthArray->Reset(); + for ( i = 1; i < KHgDrawUtilsMaxNumberOfLines; i++ ) + { + wrapWidthArray->AppendL( lineLength[i] ); + } + + AknBidiTextUtils::ConvertToVisualAndWrapToStringL( + rest, *wrapWidthArray, *smallFont, buffer, ETrue ); + + CleanupStack::PopAndDestroy( wrapWidthArray ); // wrapWidthArray + } ); // TRAP end + + + TPtrC ptr[KHgDrawUtilsMaxNumberOfLines]; + TInt n = 0; + + if (error1 == KErrNone) + { + ptr[0].Set( firstLine->Des() ); + } + if ( error1 != KErrNone || error2 != KErrNone ) + { + ptr[0].Set(aText.Left(off)); + } + else + { + TInt newlines[3]; + n = 0; + for ( i = 0; i < buffer.Length(); i++ ) + { + if ( buffer[i] != '\n' ) + { + continue; + } + newlines[n] = i; + + n++; + if ( n >= 3 ) + { + break; + } + } + + if ( n >= 1 ) + { + ptr[1].Set( buffer.Left( newlines[0] ) ); + } + if ( n >= 2 ) + { + ptr[2].Set( buffer.Mid( newlines[0] + 1, newlines[1] - newlines[0] - 1 ) ); + } + if ( n >= 3 ) + { + ptr[3].Set( buffer.Mid( newlines[1] + 1, newlines[2] - newlines[1] - 1 ) ); + } + } + + // draw texts + aGc.SetBrushStyle(CGraphicsContext::ENullBrush); + + for ( i = 0; i < KHgDrawUtilsMaxNumberOfLines; i++ ) + { + line[i].DrawText( aGc, ptr[i], EFalse, aColor ); + } + + delete firstLine; + } + +void DrawEmptyListImpl_real( const TRect &aClientRect, + CGraphicsContext &aGc, + TPtrC aText, + const TRgb& aColor ) + { + if ( !aText.Length() ) + { + return; + } + + HBufC* hbuf = HBufC::New( aText.Size() + 3 * ( KAknBidiExtraSpacePerLine +1 ) + + 10 ); // reserve space for newlines + if ( !hbuf ) + { // can't really do anything + return; + } + + TPtr buffer(hbuf->Des()); + + /* + * input text can be either + * - "line1" + * - "line1 which will be wrapped to 2 lines and truncated with..." + * - "line1\nline2" + * - "line1\nMany other lines which will be wrapped to several lines" + * + * there are 3 layouts + * - 1 line with big font, + * - 2 lines with big font + * - 1 line with big font + 1..3 lines with small font (not for popup lists) + * + * so first we need to check if given text has a newline, + * if so, then we need to check if given text fits to 2 lines or + * should it be split to several small font lines + */ + + TInt i, n; + n = 0; + for (i = 0; i < aText.Length(); i ++) + { + if ( aText[i] == '\n' ) + { + n++; + } + } + + + TAknTextComponentLayout layout1( AknLayoutScalable_Avkon::main_pane_empty_t1( 0 ) ); + TAknTextComponentLayout layout2( AknLayoutScalable_Avkon::main_pane_empty_t2( 0 ) ); + TAknLayoutText line1; + TAknLayoutText line2; + + line1.LayoutText( aClientRect, layout1 ); + TInt line1length = line1.TextRect().Size().iWidth; + + line2.LayoutText( aClientRect, layout2 ); + TInt line2length = line2.TextRect().Size().iWidth; + + const CFont *font = line1.Font(); + + if ( n == 0 ) + { // one line, or one line which will be wrapped to two + DrawEmptyListImpl_real_DrawUpToTwoLines( aGc, aText, line1, line2, + line1length, line2length, + font, aColor, buffer ); + delete hbuf; + return; + } + + TRAPD( error, + { + CArrayFix* wrapWidthArray = new( ELeave ) CArrayFixFlat(KHgDrawUtilsGranularity); + CleanupStack::PushL( wrapWidthArray ); + + wrapWidthArray->AppendL( line1length ); + wrapWidthArray->AppendL( line2length ); + wrapWidthArray->AppendL( line2length ); // allow wrap to 3 lines + + AknBidiTextUtils::ConvertToVisualAndWrapToStringL( + aText, *wrapWidthArray, *font, buffer, ETrue ); + + CleanupStack::PopAndDestroy( wrapWidthArray ); // wrapWidthArray + } ); // TRAP end + + + n = 0; + for ( i = 0; i < buffer.Length(); i ++) + { + if (buffer[i] == '\n') + { + n++; + } + } + + // wrapping adds a \n to end of each line --> n < 3 + // there is no layout for empty popuplist + if ( error != KErrNone || n < 3 ) + { // 2 lines which fit to 2 line space + DrawEmptyListImpl_real_DrawUpToTwoLines( aGc, aText, line1, line2, + line1length, line2length, + font, aColor, buffer ); + } + else + { // 1 line with big font + 1..3 lines with small font + DrawEmptyListImpl_real_DrawMoreThanTwoLines( aClientRect, aGc, aText, aColor, buffer ); + } + + delete hbuf; + } + +void CHgDrawUtils::DrawEmptyText( + CWindowGc& aGc, + const TRect& aRect, + const TDesC& aText, + const TRgb& aColor + ) const + { + DrawEmptyListImpl_real(aRect, aGc, aText, aColor); + } + +// ----------------------------------------------------------------------------- +// CHgScroller::DrawImage() +// ----------------------------------------------------------------------------- +// +void CHgDrawUtils::DrawImage( + CWindowGc& aGc, + const TRect& aRect, + const TAknWindowComponentLayout& aLayout, + const CGulIcon& aIcon + ) const + { + TAknLayoutRect image; + image.LayoutRect(aRect, aLayout); +// image.DrawImage(aGc, aIcon.Bitmap(), aIcon.Mask()); + TSize slotSize(image.Rect().Size()); + TPoint cropPoint(0,0); + TPoint toTl(image.Rect().iTl); + if( aIcon.Bitmap() && aIcon.Bitmap()->SizeInPixels() != slotSize ) + { + TSize bitmapSize( aIcon.Bitmap()->SizeInPixels() ); + if( bitmapSize.iWidth != slotSize.iWidth ) + { + if( bitmapSize.iWidth < slotSize.iWidth ) + { + // Bitmap smaller than slot -> move draw position + toTl.iX += ( slotSize.iWidth - bitmapSize.iWidth )/2; + } + else + { + // Slot smaller than bitmap -> move crop rect position + cropPoint.iX += ( bitmapSize.iWidth - slotSize.iWidth )/2; + } + } + + if( bitmapSize.iHeight != slotSize.iHeight ) + { + if( bitmapSize.iHeight < slotSize.iHeight ) + { + // Bitmap smaller than slot -> move draw position + toTl.iY += ( slotSize.iHeight - bitmapSize.iHeight )/2; + } + else + { + // Slot smaller than bitmap -> move crop rect position + cropPoint.iY += ( bitmapSize.iHeight - slotSize.iHeight )/2; + } + } + } + + TRect cropRect(cropPoint, slotSize); + + if (aIcon.Mask()) + { + aGc.BitBltMasked(toTl, aIcon.Bitmap(), cropRect, aIcon.Mask(), ETrue); + } + else + { + aGc.BitBlt(toTl, aIcon.Bitmap(), cropRect); + } + } + +// ----------------------------------------------------------------------------- +// CHgScroller::DrawText() +// ----------------------------------------------------------------------------- +// +void CHgDrawUtils::DrawText( + CWindowGc& aGc, + const TRect& aRect, + const TAknTextComponentLayout& aLayout, + const TDesC& aText, + const TRgb& aColor + ) const + { + TAknLayoutText textLayout; + textLayout.LayoutText(aRect, aLayout.LayoutLine()); + textLayout.DrawText(aGc, aText, ETrue, aColor ); + } + +// ----------------------------------------------------------------------------- +// CHgScroller::DrawTextMarquee() +// ----------------------------------------------------------------------------- +// +void CHgDrawUtils::DrawTextMarquee( + CWindowGc& aGc, + const TRect& aRect, + const TAknTextComponentLayout& aLayout, + const TDesC& aText, + const TRgb& aColor, + const TInt& aMarqueeLine + ) + { + TBool drawn = EFalse; + + if( iMarqueeLine == aMarqueeLine) + + { + if( iMarquee->DrawText( + aGc, + aRect, + aLayout.LayoutLine(), + aText, + aColor)) + { + iMarquee->Reset(); + iMarqueeLine++; + } + else + { + drawn = ETrue; + } + } + + if(!drawn) + { + DrawText(aGc, aRect, aLayout, aText, aColor); + } + } + + +CHgDrawUtils::CHgDrawUtils() + { + + } + +void CHgDrawUtils::ConstructL( TCallBack& aMarqueeCallback ) + { + iMarquee = CHgMarquee::NewL(); + iMarquee->SetRedrawCallBack( aMarqueeCallback ); + } + +void CHgDrawUtils::ResetMarquee() + { + if(iMarquee) + { + iMarquee->Reset(); + iMarqueeLine = 0; + } + } + +void CHgDrawUtils::EnableMarquee( TBool aEnable ) + { + iMarquee->EnableMarquee(aEnable); + }