uifw/ganes/src/HgDrawUtils.cpp
changeset 0 2f259fa3e83a
--- /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 <gdi.h>
+#include <gulicon.h>
+#include <AknUtils.h>
+#include <AknsUtils.h>
+#include <AknsControlContext.h>
+#include <AknsDrawUtils.h>
+#include <AknsListBoxBackgroundControlContext.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <AknBidiTextUtils.h>
+
+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<TInt>* wrapWidthArray = new( ELeave ) CArrayFixFlat<TInt>(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<TInt>* wrapWidthArray = new( ELeave ) CArrayFixFlat<TInt>(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<TInt>* wrapWidthArray = new( ELeave ) CArrayFixFlat<TInt>(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);
+    }