phoneuis/easydialing/tsrc/edta/src/edta_screentextbuffer.cpp
branchRCL_3
changeset 3 8871b09be73b
equal deleted inserted replaced
2:c84cf270c54f 3:8871b09be73b
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Easy dialing test application.
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include "edta_screentextbuffer.h"
       
    20 #include "edta_debugprint.h"
       
    21 #include "edta.pan"
       
    22 
       
    23 #include <coemain.h>
       
    24 #include <aknsbasicbackgroundcontrolcontext.h>
       
    25 #include <eiksbfrm.h>
       
    26 #include <eikenv.h>
       
    27 #include <eikdef.h>
       
    28 #include <aknappui.h>
       
    29 #include <aknutils.h>
       
    30 
       
    31 
       
    32 const TInt KLineWidthCent = 90; // Percent of total screen width
       
    33 const TInt KHeightMarginCent = 7; // Percent of total height
       
    34 const TInt KBottomMarginCent = 3; // Percent of total height
       
    35 const TInt KLineHeightCent = 135; // How many percent is the line height of font height
       
    36 const TInt KCent = 100;
       
    37 const TInt KInitialScreenBufferSize = 20; // This many lines is initially allocated to the screen buffer.
       
    38 const TInt KInitialScreenStartAmount = 5; // This many screen starts are initially allocated to screen buffer.
       
    39 
       
    40 
       
    41 CEdtaScreenTextBuffer* CEdtaScreenTextBuffer::NewL( const TRect& aRect )
       
    42     {
       
    43     CEdtaScreenTextBuffer* self = CEdtaScreenTextBuffer::NewLC( aRect );
       
    44     CleanupStack::Pop( self );
       
    45     return self;
       
    46     }
       
    47 
       
    48 CEdtaScreenTextBuffer* CEdtaScreenTextBuffer::NewLC( const TRect& aRect )
       
    49     {
       
    50     CEdtaScreenTextBuffer* self = new ( ELeave ) CEdtaScreenTextBuffer;
       
    51     CleanupStack::PushL( self );
       
    52     self->ConstructL( aRect );
       
    53     return self;
       
    54     }
       
    55 
       
    56 // constructors
       
    57 CEdtaScreenTextBuffer::CEdtaScreenTextBuffer()
       
    58     {
       
    59     }
       
    60 
       
    61 void CEdtaScreenTextBuffer::ConstructL( const TRect& aRect )
       
    62     {
       
    63     CreateWindowL();
       
    64     CalculateL(aRect);
       
    65     ActivateL();
       
    66     }
       
    67 
       
    68 // destructor
       
    69 CEdtaScreenTextBuffer::~CEdtaScreenTextBuffer()
       
    70     {
       
    71     delete iSBFrame;
       
    72     delete iScreenStarts;
       
    73 
       
    74     if ( iText )
       
    75         {
       
    76         iText->ResetAndDestroy();
       
    77         delete iText;
       
    78         }
       
    79     }
       
    80 
       
    81 void CEdtaScreenTextBuffer::SizeChanged()
       
    82     {
       
    83     // TRAP_IGNORE( CalculateL( Rect() ) );
       
    84     // DrawDeferred();
       
    85     }
       
    86 
       
    87 
       
    88 // -----------------------------------------------------------------------------
       
    89 // CEdtaScreenTextBuffer::Draw()
       
    90 // -----------------------------------------------------------------------------
       
    91 void CEdtaScreenTextBuffer::Draw( const TRect& aRect ) const
       
    92     {
       
    93 	// DebugPrintF(_L("CEdtaScreenTextBuffer::Draw, rect: %d, %d - %d, %d"), aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY );
       
    94 
       
    95     __ASSERT_DEBUG( iText, Panic(EEdtaFieldNotInitialized,_L("CEdtaScreenTextBuffer::Draw: iText == NULL") ));
       
    96     __ASSERT_DEBUG( iScreenStarts, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::Draw: iScreenStarts == NULL") ));
       
    97     __ASSERT_DEBUG( iScreenStarts->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::Draw: iScreenStarts has zero elements") ));
       
    98 
       
    99     CWindowGc& gc = SystemGc();
       
   100 
       
   101     gc.SetBrushColor( KRgbWhite );
       
   102     gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   103     gc.Clear( aRect );
       
   104     
       
   105     if ( IsFocused() )
       
   106         {
       
   107         TRect frame( aRect );
       
   108         frame.Shrink(3,3);
       
   109         frame.iBr.iX -= 10;
       
   110         gc.SetPenColor(KRgbBlack);
       
   111         gc.SetPenSize( TSize(2,2) );
       
   112         TSize cornerRounding(8,8);
       
   113         gc.DrawRoundRect( frame, cornerRounding );
       
   114         }
       
   115     
       
   116     gc.UseFont( iFont );
       
   117 
       
   118     // index of the first line on the screen in the text array
       
   119     TInt firstLine = 0 ;
       
   120     if((iScreenStarts ) && (iScreenStarts->Count() > iCurrentScreen))
       
   121         {
       
   122         firstLine = ( (*iScreenStarts)[ iCurrentScreen ] );
       
   123         }
       
   124     else
       
   125         {
       
   126         firstLine = (*iScreenStarts)[ iScreenStarts->Count() - 1 ];
       
   127         }
       
   128 
       
   129     // index of the last line on the screen in the text array
       
   130     TInt lastLine( firstLine + iLinesPerScreen - 1 );
       
   131 
       
   132     gc.SetBrushStyle( CGraphicsContext::ENullBrush );
       
   133 
       
   134     TPoint position( iTopBaseLineX, iTopBaseLineY );
       
   135     TPoint topLeft;
       
   136     TSize rectSize( iLineWidth, iBaseLineDelta +iFont->DescentInPixels() );
       
   137 
       
   138     for ( TInt index = firstLine; index < iText->Count() && index <= lastLine; index++, position.iY += iBaseLineDelta )
       
   139         {
       
   140         HBufC* text = (*iText)[ index ];
       
   141 
       
   142         if ( text )
       
   143             {
       
   144             topLeft = TPoint( position.iX, position.iY-iBaseLineDelta );
       
   145             gc.SetPenColor(KRgbBlack);
       
   146             gc.DrawText( *text, TRect( topLeft, rectSize ), iBaseLineDelta, iTextAlign );
       
   147             }
       
   148         }
       
   149 
       
   150     gc.DiscardFont();
       
   151 
       
   152     // DebugPrintF(_L("CEdtaScreenTextBuffer::Draw exit"));
       
   153     }
       
   154 
       
   155 
       
   156 // -----------------------------------------------------------------------------
       
   157 // CEdtaScreenTextBuffer::ActivateL()
       
   158 // -----------------------------------------------------------------------------
       
   159 void CEdtaScreenTextBuffer::ActivateL()
       
   160     {
       
   161     CCoeControl::ActivateL();
       
   162     UpdateScrollIndicatorL();
       
   163     }
       
   164 
       
   165 
       
   166 // -----------------------------------------------------------------------------
       
   167 // CEdtaScreenTextBuffer::SetTextL()
       
   168 // -----------------------------------------------------------------------------
       
   169 void CEdtaScreenTextBuffer::WriteLineL(TRefByValue<const TDesC> aText,... )
       
   170     {
       
   171     TBuf<KEdtaMaxLineWidth> bufLine;
       
   172     VA_LIST list;
       
   173     VA_START(list,aText);
       
   174     bufLine.FormatList(aText,list);
       
   175 
       
   176     if(!bufLine.Length())
       
   177         {
       
   178         iText->AppendL( NULL );
       
   179         }
       
   180     else
       
   181         {
       
   182         HBufC* line = HBufC::NewLC(bufLine.Length());
       
   183         *line = bufLine;
       
   184         iText->AppendL( line );
       
   185         CleanupStack::Pop(line);
       
   186         }
       
   187 
       
   188     // Updating scrollbars and screen starts etc are moved to UpdateScrollIndicatorL()
       
   189 
       
   190     // if text, last line is shown again in next screen
       
   191     iDoNotShowLastLineAgain = EFalse;
       
   192 
       
   193     DrawDeferred(); //New
       
   194     UpdateScrollIndicatorL();
       
   195     }
       
   196 
       
   197 
       
   198 // -----------------------------------------------------------------------------
       
   199 // CEdtaScreenTextBuffer::DeleteLastLine()
       
   200 // -----------------------------------------------------------------------------
       
   201 void CEdtaScreenTextBuffer::DeleteLastLine(TInt aCount)
       
   202     {
       
   203     __ASSERT_DEBUG( iText, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::DeleteLastLine: iText == NULL") ));
       
   204     __ASSERT_DEBUG( iText->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::DeleteLastLine: iText has zero elements") ));
       
   205 
       
   206     while (aCount > 0)
       
   207         {
       
   208         // Avoiding memory leaks
       
   209         TInt lastIndex = iText->Count() - 1;
       
   210 
       
   211         // The first item in iText cannot be deleted, since UpdateScrollIndicatorL
       
   212         // relies on there being at least one item.
       
   213         if (lastIndex > 0)
       
   214             {
       
   215             HBufC* text = (*iText)[ lastIndex ];
       
   216             delete text;
       
   217             iText->Delete(lastIndex);
       
   218             }
       
   219         --aCount;
       
   220         }
       
   221     }
       
   222 
       
   223 
       
   224 
       
   225 // -----------------------------------------------------------------------------
       
   226 // CEdtaScreenTextBuffer::OfferKeyEventL()
       
   227 // -----------------------------------------------------------------------------
       
   228 TKeyResponse CEdtaScreenTextBuffer::OfferKeyEventL( const TKeyEvent& aKeyEvent,
       
   229                                               TEventCode aType )
       
   230     {
       
   231     __ASSERT_DEBUG(iScreenStarts, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::OfferKeyEventL: iScreenStarts == NULL") ));
       
   232     __ASSERT_DEBUG(iScreenStarts->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::OfferKeyEventL: iScreenStarts has zero elements") ));
       
   233 
       
   234     if ( aType == EEventKey && iScreenStarts->Count() > 1 )
       
   235         {
       
   236         switch ( aKeyEvent.iCode )
       
   237             {
       
   238             case EKeyUpArrow:
       
   239                 if ( iCurrentScreen > 0 )
       
   240                     {
       
   241                     iCurrentScreen--;
       
   242                     DrawNow();
       
   243                     UpdateScrollIndicatorL();
       
   244                     }
       
   245                 break;
       
   246 
       
   247             case EKeyDownArrow:
       
   248                 if ( iCurrentScreen < iScreenStarts->Count() - 1 )
       
   249                     {
       
   250                     iCurrentScreen++;
       
   251                     DrawNow();
       
   252                     UpdateScrollIndicatorL();
       
   253                     }
       
   254                 break;
       
   255 
       
   256             default:
       
   257                 return EKeyWasNotConsumed;
       
   258             }
       
   259         }
       
   260 
       
   261     return EKeyWasConsumed;
       
   262     }
       
   263 
       
   264 
       
   265 
       
   266 // -----------------------------------------------------------------------------
       
   267 // CEdtaScreenTextBuffer::FocusChanged()
       
   268 // -----------------------------------------------------------------------------
       
   269 void CEdtaScreenTextBuffer::FocusChanged(TDrawNow aDrawNow)
       
   270     {
       
   271     if ( aDrawNow == EDrawNow )
       
   272         {
       
   273         DrawNow();
       
   274         }
       
   275     }
       
   276 
       
   277 
       
   278 // -----------------------------------------------------------------------------
       
   279 // CEdtaScreenTextBuffer::HandleScrollEventL()
       
   280 // -----------------------------------------------------------------------------
       
   281 void CEdtaScreenTextBuffer::HandleScrollEventL ( CEikScrollBar* aScrollBar, TEikScrollEvent aEventType)
       
   282     {
       
   283     //Only on page up/down,scroll up/down and drag events
       
   284     switch (aEventType)
       
   285         {
       
   286         case EEikScrollPageDown:
       
   287         case EEikScrollPageUp:
       
   288         case EEikScrollThumbDragVert:
       
   289         case EEikScrollUp:
       
   290         case EEikScrollDown:
       
   291 
       
   292             iCurrentScreen = aScrollBar->ThumbPosition();
       
   293 
       
   294             //Refresh now
       
   295             DrawNow();
       
   296             UpdateScrollIndicatorL();
       
   297             break;
       
   298         }
       
   299     }
       
   300 
       
   301 // -----------------------------------------------------------------------------
       
   302 // CEdtaScreenTextBuffer::UpdateScrollIndicatorL()
       
   303 //
       
   304 // This function assumes that
       
   305 // - iText exists and has at least one element.
       
   306 // - iScreenStarts exist and has at least one element.
       
   307 // These conditions are met if CalculateL / ConstructL has been called.
       
   308 // -----------------------------------------------------------------------------
       
   309 void CEdtaScreenTextBuffer::UpdateScrollIndicatorL()
       
   310     {
       
   311     __ASSERT_DEBUG( iText, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::UpdateScrollIndicatorL: iText == NULL") ));
       
   312     __ASSERT_DEBUG( iText->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::UpdateScrollIndicatorL: iText has zero elements") ));
       
   313     __ASSERT_DEBUG( iScreenStarts, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::UpdateScrollIndicatorL: iScreenStarts == NULL") ));
       
   314     __ASSERT_DEBUG( iScreenStarts->Count() > 0, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::UpdateScrollIndicatorL: iScreenStarts has zero elements") ));
       
   315 
       
   316     TInt lastLine( iText->Count() - 1 );
       
   317     TInt screenStart( (*iScreenStarts)[ iScreenStarts->Count() - 1 ] );
       
   318 
       
   319     TBool firstNewScreenHandled( EFalse );
       
   320 
       
   321     while ( lastLine >= screenStart + iLinesPerScreen )
       
   322         {
       
   323         if ( !firstNewScreenHandled && iDoNotShowLastLineAgain )
       
   324             {
       
   325             screenStart++;
       
   326             firstNewScreenHandled = ETrue;
       
   327             }
       
   328 
       
   329         // If the shows screen is the last on, scroll the view along with new lines.
       
   330         if (iCurrentScreen == iScreenStarts->Count() - 1)
       
   331             {
       
   332             iCurrentScreen++;
       
   333             }
       
   334 
       
   335         screenStart += iLinesPerScreen - 1;
       
   336         iScreenStarts->AppendL( screenStart );
       
   337         }
       
   338 
       
   339     if ( !iSBFrame )
       
   340         {
       
   341         iSBFrame = new( ELeave ) CEikScrollBarFrame( this, NULL, ETrue );
       
   342 
       
   343         iSBFrame->CreateDoubleSpanScrollBarsL(ETrue, EFalse); // non-window owning scrollbar
       
   344         iSBFrame->SetTypeOfVScrollBar(CEikScrollBarFrame::EDoubleSpan);
       
   345 
       
   346         iSBFrame->SetScrollBarFrameObserver(this);
       
   347         iSBFrame->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff,CEikScrollBarFrame::EAuto);
       
   348         }
       
   349 
       
   350     TEikScrollBarModel vSbarModel;
       
   351     vSbarModel.iThumbPosition = iCurrentScreen;
       
   352     vSbarModel.iScrollSpan = iScreenStarts->Count();
       
   353     vSbarModel.iThumbSpan = 1;
       
   354 
       
   355     TRect rect(Rect());
       
   356     TEikScrollBarFrameLayout layout;
       
   357     layout.iTilingMode = TEikScrollBarFrameLayout::EInclusiveRectConstant;
       
   358 
       
   359     // For EDoubleSpan type scrollbar
       
   360     if (vSbarModel.iThumbPosition + vSbarModel.iThumbSpan > vSbarModel.iScrollSpan)
       
   361         {
       
   362         // Not let scrollbar values overflow
       
   363         vSbarModel.iThumbPosition = vSbarModel.iScrollSpan - vSbarModel.iThumbSpan;
       
   364         }
       
   365 
       
   366     TAknDoubleSpanScrollBarModel vDsSbarModel(vSbarModel);
       
   367     iSBFrame->TileL(NULL, &vDsSbarModel, rect, rect, layout);
       
   368     iSBFrame->SetVFocusPosToThumbPos(vDsSbarModel.FocusPosition());
       
   369     }
       
   370 
       
   371 
       
   372 // -----------------------------------------------------------------------------
       
   373 // CEdtaScreenTextBuffer::CalculateL()
       
   374 // Needs to be called in construction, and whenever layout changes.
       
   375 // Screen orientation change, etc.
       
   376 // -----------------------------------------------------------------------------
       
   377 void CEdtaScreenTextBuffer::CalculateL(const TRect& aRect)
       
   378     {
       
   379     // DebugPrintF(_L("CEdtaScreenTextBuffer::CalculateL, rect: %d, %d - %d, %d"), aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY  );
       
   380 
       
   381     TRect rect(0,0,0,0);
       
   382 
       
   383     iCurrentScreen = 0;
       
   384 
       
   385     iFont = AknLayoutUtils::FontFromId(EAknLogicalFontSecondaryFont);
       
   386 
       
   387     // Calculate various text positioning parameters
       
   388     iBaseLineDelta = iFont->HeightInPixels() * KLineHeightCent / KCent;
       
   389 
       
   390     TInt mainPaneWidth( aRect.iBr.iX - aRect.iTl.iX );
       
   391     TInt mainPaneHeight( aRect.iBr.iY - aRect.iTl.iY );
       
   392     // Line width is 90% (by default) of client rect, and horizontal margins 10%
       
   393     iLineWidth = mainPaneWidth * KLineWidthCent / KCent;
       
   394 
       
   395     iTopBaseLineX = ( mainPaneWidth - iLineWidth ) / 2;
       
   396 
       
   397     // top margin is 7% (by default) of the client rect
       
   398     TInt topMargin = mainPaneHeight * KHeightMarginCent / KCent;
       
   399     iTopBaseLineY = topMargin + iFont->AscentInPixels();
       
   400 
       
   401     // minimum bottom margin is 3% (by default) of the client rect
       
   402     TInt bottomMargin = mainPaneHeight * KBottomMarginCent / KCent;
       
   403     iLinesPerScreen =
       
   404         ( mainPaneHeight - topMargin - bottomMargin ) / iBaseLineDelta;
       
   405 
       
   406     iTextAlign = CGraphicsContext::ELeft;
       
   407 
       
   408     // Text must not be deleted, otherwise all accumulated data will be lost.
       
   409     if ( !iText )
       
   410         {
       
   411         // Every text line on screen is one entry in this array
       
   412         iText = new( ELeave ) CArrayPtrFlat<HBufC>( KInitialScreenBufferSize );
       
   413         iText->AppendL(NULL); // Extra newline for visual reasons
       
   414         }
       
   415 
       
   416      if ( iScreenStarts )
       
   417         {
       
   418         delete iScreenStarts;
       
   419         iScreenStarts = NULL;
       
   420         }
       
   421 
       
   422 
       
   423     // This array contains indices for lines that start the subsequent
       
   424     // screens, for custom scrolling
       
   425     iScreenStarts = new( ELeave ) CArrayFixFlat<TInt>( KInitialScreenStartAmount );
       
   426     // Initialisation: first screen starts at line 0.
       
   427     iScreenStarts->AppendL( 0 );
       
   428 
       
   429     if ( iSBFrame )
       
   430         {
       
   431         delete iSBFrame;
       
   432         iSBFrame = NULL;
       
   433         }
       
   434 
       
   435     UpdateScrollIndicatorL();
       
   436     }
       
   437 
       
   438 
       
   439 // -----------------------------------------------------------------------------
       
   440 // CEdtaScreenTextBuffer::HandleResourceChange()
       
   441 // -----------------------------------------------------------------------------
       
   442 void CEdtaScreenTextBuffer::HandleResourceChange(TInt aType)
       
   443     {
       
   444     switch ( aType )
       
   445         {
       
   446         case KEikDynamicLayoutVariantSwitch :
       
   447             {
       
   448             TRAPD( error, CalculateL( iAvkonAppUi->ClientRect() ));
       
   449 
       
   450             if( error != KErrNone )
       
   451                 {
       
   452                 DebugPrintF(_L("CEdtaScreenTextBuffer::HandleResourceChange: CalculateL -method failed: %d"), error );
       
   453                 }
       
   454             else
       
   455                 {
       
   456                 DrawNow();
       
   457                 }
       
   458             }
       
   459             break;
       
   460 
       
   461         case KAknsMessageSkinChange :
       
   462             {
       
   463             __ASSERT_DEBUG(iSBFrame, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::HandleResourceChange: iSBFrame == NULL") ));
       
   464 
       
   465             TRAPD( error,
       
   466                 {
       
   467                 iSBFrame->CreateDoubleSpanScrollBarsL(ETrue, EFalse); // window owning scrollbar
       
   468                 iSBFrame->SetTypeOfVScrollBar(CEikScrollBarFrame::EDoubleSpan);
       
   469                 iSBFrame->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff,CEikScrollBarFrame::EOn);
       
   470                 UpdateScrollIndicatorL();
       
   471                 }
       
   472             );
       
   473 
       
   474             if( error != KErrNone )
       
   475                 {
       
   476                 DebugPrintF(_L("CEdtaScreenTextBuffer::HandleResourceChange: Create ScrollBars failed: %d"), error );
       
   477                 __ASSERT_DEBUG( error == KErrNone, Panic(EEdtaFieldNotInitialized, _L("CEdtaScreenTextBuffer::HandleResourceChange => Skin change caused panic") ));
       
   478                 }
       
   479             }
       
   480 
       
   481         default:
       
   482             {
       
   483             CCoeControl::HandleResourceChange(aType);
       
   484             }
       
   485             break;
       
   486         }
       
   487     }
       
   488 
       
   489 
       
   490 // ---------------------------------------------------------
       
   491 // CEdtaScreenTextBuffer::MopSupplyObject()
       
   492 // Pass skin information if need.
       
   493 // ---------------------------------------------------------
       
   494 TTypeUid::Ptr CEdtaScreenTextBuffer::MopSupplyObject(TTypeUid aId)
       
   495     {
       
   496     return CCoeControl::MopSupplyObject(aId);
       
   497     }
       
   498 
       
   499 
       
   500 // End of file