uifw/AvKon/src/aknmessagequerycontrol.cpp
changeset 0 2f259fa3e83a
child 9 0aa5fbdfbc30
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2002 - 2006 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:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <barsread.h>
       
    21 #include <eikenv.h>
       
    22 #include <AknPanic.h>
       
    23 #include <avkon.hrh>
       
    24 #include <avkon.rsg>
       
    25 #include <aknmessagequerycontrol.h>
       
    26 #include <aknmessagequerydialog.h>
       
    27 
       
    28 #include <eiksbfrm.h>
       
    29 #include <eikscrlb.h>
       
    30 
       
    31 #include <eikappui.h>
       
    32 
       
    33 #include <frmlaydt.h>
       
    34 #include "aknconsts.h"
       
    35 
       
    36 #include <AknsDrawUtils.h>
       
    37 
       
    38 #include <applayout.cdl.h>
       
    39 #include "aknappui.h"
       
    40 
       
    41 #include <eikrted.h>
       
    42 #include <txtrich.h> 
       
    43 #include <txtfrmat.h>
       
    44 
       
    45 #include <layoutmetadata.cdl.h>
       
    46 #include <aknlayoutscalable_avkon.cdl.h>
       
    47 
       
    48 #include <eikdialg.h>
       
    49 #include <eikdialogext.h>
       
    50 
       
    51 #include <eikedwob.h>
       
    52 
       
    53 #include <AknTasHook.h> // for testability hooks
       
    54 class CAknMessageQueryControlExtension: public CBase, public MEikEdwinObserver
       
    55     {
       
    56 public:
       
    57     CAknMessageQueryControlExtension( CAknMessageQueryControl* aParent ): iParent( aParent ) {}
       
    58         
       
    59     /**
       
    60     * From MEikEdwinObserver. Handles edwin events.
       
    61     * On the scroll event, any selected link is dehighlighted.
       
    62     */
       
    63     void HandleEdwinEventL( CEikEdwin* /*aEdwin*/, TEdwinEvent aEventType )
       
    64         {
       
    65     	if( aEventType == MEikEdwinObserver::EEventScroll )
       
    66     	    {
       
    67     		iParent->DehighlightLink();
       
    68     		}
       
    69         }
       
    70         
       
    71     ~CAknMessageQueryControlExtension()
       
    72         {    
       
    73         if( iDestroyedPtr )
       
    74             {
       
    75             // Mark the object as destroyed.
       
    76             *iDestroyedPtr = ETrue;
       
    77             iDestroyedPtr = NULL;
       
    78             }
       
    79         }
       
    80         
       
    81     public:
       
    82     
       
    83     CAknMessageQueryControl* iParent;
       
    84     /**
       
    85     * @c iDestroyedPtr is used for the object destruction check.
       
    86     * If it has non-null value, the destruction check is turned on, and
       
    87     * the value points to a local boolean variable that keeps the destroyed state.
       
    88     */
       
    89     TBool* iDestroyedPtr;
       
    90     };
       
    91 
       
    92 CAknMessageQueryControl::CAknMessageQueryControl() :
       
    93     iTopLine( 0 ), iLinksCount( 0 ), iVisibleLinksCount( 0 ),
       
    94     iFirstVisibleLink( -1 ), iCurPos( 0 ), iFullMessage( NULL )
       
    95     {
       
    96     iLinesPerPage = AknLayoutScalable_Avkon::popup_info_list_pane_t1_ParamLimits().LastRow() + 1;
       
    97     AKNTASHOOK_ADD( this, "CAknMessageQueryControl" );
       
    98     }
       
    99 
       
   100 CAknMessageQueryControl::~CAknMessageQueryControl()
       
   101     {
       
   102     AKNTASHOOK_REMOVE();
       
   103     AknsUtils::DeregisterControlPosition( iEdwin );
       
   104     delete iEdwin;
       
   105     iLinkTextLocationArray.Close();
       
   106     iLinkTextArray.Close();
       
   107     delete iFullMessage;
       
   108     delete iExtension;
       
   109     }
       
   110 
       
   111 EXPORT_C void CAknMessageQueryControl::ConstructFromResourceL( TResourceReader& aReader )
       
   112     {
       
   113     CEikDialog* dlg;
       
   114     MopGetObject( dlg );
       
   115 
       
   116     if ( dlg )
       
   117         {
       
   118         dlg->Extension()->iPublicFlags.Set( CEikDialogExtension::EClipChildControlRect );
       
   119         }
       
   120     
       
   121     TPtrC messageLabel = aReader.ReadTPtrC();
       
   122     SetMessageTextL( &messageLabel );
       
   123     }
       
   124 
       
   125 EXPORT_C void CAknMessageQueryControl::SetMessageTextL( TDesC* aMessage )
       
   126     {
       
   127     CreateEditorL();
       
   128     iEdwin->TextLayout()->SetAmountToFormat( CTextLayout::EFFormatAllText );
       
   129     if ( aMessage->Length() > iEdwin->UpperFullFormattingLength() )
       
   130         iEdwin->SetUpperFullFormattingLength( aMessage->Length() ); 
       
   131     iEdwin->SetTextL( aMessage );
       
   132     LayoutEditorL(); 
       
   133     
       
   134     HBufC* msgBuf = aMessage->AllocLC();
       
   135     TPtr message( msgBuf->Des() );
       
   136     if( iListQLayout )
       
   137         {
       
   138         TruncateTextForListQLayout( message );
       
   139         iEdwin->SetTextL( &message );
       
   140         LayoutEditorL(); 
       
   141         }
       
   142 
       
   143     if ( message.Locate('\n') != KErrNotFound )
       
   144         {
       
   145         iEdwin->SetCursorPosL( 1, EFalse );
       
   146         SEdwinFindModel findModel;
       
   147         _LIT( KNChar,"\n" ); 
       
   148         _LIT( KFChar,"\f" );
       
   149         TBuf<1> text( KNChar );
       
   150         TBuf<1> replaceText( KFChar );
       
   151         findModel.iFlags = 0;
       
   152         findModel.iText = text;
       
   153         findModel.iReplaceText = replaceText;
       
   154         findModel.iReplaceOption = EReplaceAll;
       
   155         iEdwin->ReplaceAllL( &findModel );
       
   156         }
       
   157     CleanupStack::PopAndDestroy( msgBuf );  // After all usages of message        
       
   158              
       
   159     iNumberOfLines = iEdwin->TextLayout()->NumFormattedLines();
       
   160     iTopLine = 0;
       
   161     UpdateScrollIndicatorL();    
       
   162     }           
       
   163     
       
   164 void CAknMessageQueryControl::CreateEditorL()
       
   165     {
       
   166     delete iEdwin;
       
   167     iEdwin = NULL;
       
   168     iSBFrame = NULL;
       
   169     
       
   170     iEdwin = new ( ELeave ) CEikRichTextEditor( TGulBorder::ENone );
       
   171     iEdwin->SetContainerWindowL( *this );
       
   172     AknEditUtils::ConstructEditingL( iEdwin, R_AVKON_MESSAGE_QUERY_EDITOR );
       
   173     
       
   174     if ( !iExtension )
       
   175         {
       
   176         iExtension = new (ELeave) CAknMessageQueryControlExtension( this );
       
   177         }
       
   178     iEdwin->SetEdwinObserver( iExtension );
       
   179     iEdwin->SetAvkonWrap( ETrue );                                  
       
   180     iEdwin->SetFocus( EFalse );
       
   181     iEdwin->SetNonFocusing();
       
   182     iEdwin->EnableKineticScrollingL(ETrue);
       
   183     }    
       
   184     
       
   185 void CAknMessageQueryControl::LayoutEditorL()
       
   186     {
       
   187     TInt lines = 1;
       
   188 
       
   189     RArray<TAknTextComponentLayout> textComponentLayoutArray;
       
   190     for ( TInt rowIndex = 0; rowIndex < lines; rowIndex++)
       
   191         {
       
   192         TRAPD(error, textComponentLayoutArray.AppendL(AknLayoutScalable_Avkon::popup_info_list_pane_t1(rowIndex)));
       
   193         if (error != KErrNone)
       
   194             {
       
   195             textComponentLayoutArray.Close();
       
   196             User::Leave(error);
       
   197             }
       
   198         }
       
   199 
       
   200     TRect parentRect = LayoutRect();
       
   201     TAknLayoutRect listScrollPopupInfoPane;
       
   202     listScrollPopupInfoPane.LayoutRect(parentRect, AknLayoutScalable_Avkon::listscroll_popup_info_pane());
       
   203     TAknLayoutRect listPopupInfoPane;
       
   204     listPopupInfoPane.LayoutRect(listScrollPopupInfoPane.Rect(), AknLayoutScalable_Avkon::list_popup_info_pane( 0 ));  // Variety with scroll bar
       
   205     
       
   206     /** The edwin rect is set totally from layout list_popup_info_pane. But
       
   207       * AknLayoutUtils::LayoutEdwin() is still used for setting its text color and font. 
       
   208      **/ 
       
   209     AknLayoutUtils::LayoutEdwin( iEdwin, listPopupInfoPane.Rect(),
       
   210         TAknTextComponentLayout::Multiline(textComponentLayoutArray), EAknsCIQsnTextColorsCG19 );
       
   211     iEdwin->SetSuppressFormatting(ETrue);
       
   212     iEdwin->SetRect( listPopupInfoPane.Rect() );
       
   213     iEdwin->SetSuppressFormatting(EFalse);
       
   214     textComponentLayoutArray.Close();
       
   215     }    
       
   216 
       
   217 TKeyResponse CAknMessageQueryControl::OfferKeyEventL( const TKeyEvent& aKeyEvent, TEventCode /*aModifiers*/ )
       
   218     {
       
   219     TInt key( aKeyEvent.iCode );
       
   220     if( !(key == EKeyDownArrow || key == EKeyUpArrow) )
       
   221         return EKeyWasConsumed;
       
   222     TBool moveDown = key == EKeyDownArrow; // Moving down?
       
   223         
       
   224     /* 4 transitions are possible:
       
   225     
       
   226     Text   -> *Link*
       
   227     *Link* -> *Link*
       
   228     *Link* -> Text
       
   229     Text   -> >>Scroll page>>
       
   230     
       
   231     */
       
   232     
       
   233     // If the editor was scrolled with pen, synchronize the query's and editor's states
       
   234     TInt editorTopLine = iEdwin->TextLayout()->FirstLineInBand();
       
   235     if( editorTopLine != iTopLine )
       
   236         {
       
   237         if( LinkHighLighted() ) // Standing on a link?
       
   238             {
       
   239             // Synchronize to the query's position
       
   240             iEdwin->TextView()->SetViewLineAtTopL( iTopLine + 1 );    // Uses 1-based line numbers
       
   241             }
       
   242         else
       
   243             {
       
   244             // Synchronize to the editor's position
       
   245             iTopLine = editorTopLine;
       
   246             UpdatePageInfo();
       
   247             }
       
   248         }
       
   249         
       
   250     SetHighlightOnL( EFalse );  // Dehighlight the old link    
       
   251         
       
   252     // Move to the following position    
       
   253     iCurPos += moveDown? 1 : -1;
       
   254     if( iCurPos < 1 || iPositionsCount -1  <= iCurPos ) // Beyond the allowed range
       
   255         {
       
   256         if( CanScrollPage( moveDown ) )
       
   257             {
       
   258             iTopLine += moveDown? iLinesPerPage - 1 : 1 - iLinesPerPage;
       
   259             if( iTopLine >= iNumberOfLines - iLinesPerPage)
       
   260                 {
       
   261                 iTopLine = iNumberOfLines - iLinesPerPage;
       
   262                 }
       
   263             if( iTopLine < 0)
       
   264                 {
       
   265                 iTopLine = 0;
       
   266                 }
       
   267             iEdwin->MoveDisplayL( moveDown? TCursorPosition::EFPageDown : TCursorPosition::EFPageUp );
       
   268             int lastPageLink = -1;
       
   269             if( iFirstVisibleLink > -1 )
       
   270             	lastPageLink = moveDown?
       
   271             	    (iFirstVisibleLink + iVisibleLinksCount - 1): iFirstVisibleLink;
       
   272             UpdatePageInfo();
       
   273             if( lastPageLink > -1 && iFirstVisibleLink > -1 )
       
   274                 {
       
   275                 if( moveDown )
       
   276                     {
       
   277                 	iCurPos = 1;
       
   278                 	while( lastPageLink-- >= iFirstVisibleLink )
       
   279                 	    {
       
   280                 		iCurPos++;
       
   281                 	    }
       
   282                     }
       
   283                 
       
   284                 else
       
   285                     {
       
   286                     iCurPos = iPositionsCount - 2;
       
   287                     while( lastPageLink++ <= iFirstVisibleLink + iVisibleLinksCount - 1 )
       
   288                         {
       
   289                     	iCurPos--;
       
   290                         }	
       
   291                     }
       
   292             	
       
   293                 }
       
   294             else
       
   295                 {
       
   296             	iCurPos = moveDown? 1 : iPositionsCount - 2;   // Proceed to top or bottom of the following page
       
   297                 }
       
   298             }
       
   299         else
       
   300             {
       
   301             iCurPos = moveDown? iPositionsCount - 1 : 0;    // Return to bottom or top of the current page
       
   302             }
       
   303         }
       
   304     
       
   305     SetHighlightOnL( ETrue );   // Highlight the new link
       
   306     
       
   307         
       
   308     UpdateScrollIndicatorL();
       
   309     return( EKeyWasConsumed );
       
   310     }
       
   311 
       
   312 void CAknMessageQueryControl::SizeChanged()
       
   313     {
       
   314     TRAP_IGNORE( DoSizeChangedL() );
       
   315     }
       
   316 
       
   317 
       
   318 TSize CAknMessageQueryControl::MinimumSize()
       
   319     {
       
   320     const TRect rect( LayoutRect() );
       
   321     TAknLayoutRect listScrollPopupInfoPane;
       
   322     listScrollPopupInfoPane.LayoutRect(rect, AknLayoutScalable_Avkon::listscroll_popup_info_pane());
       
   323 
       
   324     if ( AknLayoutUtils::PenEnabled() )
       
   325         {
       
   326         return TSize( rect.Width(), listScrollPopupInfoPane.Rect().Height() );
       
   327         }
       
   328     else
       
   329         {
       
   330         return listScrollPopupInfoPane.Rect().Size();
       
   331         }
       
   332     } 
       
   333 
       
   334 
       
   335 TRect CAknMessageQueryControl::LayoutRect() const
       
   336     {
       
   337     TInt lines = iNumberOfLines > iLinesPerPage ? iLinesPerPage : iNumberOfLines;
       
   338     
       
   339     lines--;
       
   340     if ( lines < 0 ) 
       
   341         {
       
   342         lines = 0;    
       
   343         }
       
   344 
       
   345     TInt variety = 0;
       
   346     AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation();
       
   347     if (cbaLocation == AknLayoutUtils::EAknCbaLocationRight)
       
   348         { // Variety numbers for right CBA are 6-11
       
   349         variety = lines + 6;
       
   350         }
       
   351     else if (cbaLocation == AknLayoutUtils::EAknCbaLocationLeft)
       
   352         { // Variety numbers for left CBA are 12-17
       
   353         variety = lines + 12;
       
   354         }
       
   355     else // bottom
       
   356         {
       
   357         variety = lines;
       
   358         }
       
   359 
       
   360     TRect appRect = iAvkonAppUi->ApplicationRect();
       
   361     TAknLayoutRect applicationWindow;
       
   362     applicationWindow.LayoutRect(appRect, AknLayoutScalable_Avkon::application_window(0));    
       
   363     TRect mainPane;
       
   364     AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EPopupParent, mainPane );
       
   365     
       
   366     TAknLayoutRect layout;
       
   367     layout.LayoutRect( mainPane, AknLayoutScalable_Avkon::popup_query_sat_info_window( variety ) );
       
   368     TRect rect( layout.Rect() );
       
   369 
       
   370     return TRect( TPoint(0, 0), rect.Size() );
       
   371     }
       
   372 
       
   373 // Get component controls into a table
       
   374 const TInt KMaxMessageQueryControls = 2;
       
   375 static TInt ComponentControls(CCoeControl* aEditor,
       
   376     CEikScrollBarFrame* aScrollBarFrame,
       
   377     CCoeControl* aControls[KMaxMessageQueryControls])
       
   378     {
       
   379     TInt i = 0;
       
   380     if (aEditor)
       
   381         {
       
   382         aControls[i++] = aEditor;
       
   383         }
       
   384     // Non-window owning acroll bar
       
   385     if (aScrollBarFrame && aScrollBarFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan)
       
   386         {
       
   387         aControls[i++] = aScrollBarFrame->GetScrollBarHandle(
       
   388             CEikScrollBar::EVertical);
       
   389         }
       
   390     return i;
       
   391     }
       
   392 
       
   393 TInt CAknMessageQueryControl::CountComponentControls() const
       
   394     {
       
   395      CCoeControl* unused[KMaxMessageQueryControls];
       
   396      return ComponentControls(iEdwin, iSBFrame, unused);
       
   397     }
       
   398 
       
   399 
       
   400 CCoeControl* CAknMessageQueryControl::ComponentControl( TInt aIndex ) const
       
   401     {
       
   402      CCoeControl* controls[KMaxMessageQueryControls];
       
   403      TInt cnt = ComponentControls(iEdwin, iSBFrame, controls);
       
   404      if (aIndex < cnt)
       
   405         {
       
   406         return controls[aIndex];
       
   407         }
       
   408     else
       
   409         {
       
   410         return NULL;
       
   411         }
       
   412     }         
       
   413 
       
   414 // This method is needed to set correct initial value to scroll indicator.
       
   415 void CAknMessageQueryControl::ActivateL()
       
   416     {
       
   417     CCoeControl::ActivateL();
       
   418     UpdateScrollIndicatorL();
       
   419     }
       
   420 
       
   421 void CAknMessageQueryControl::UpdateScrollIndicatorL()
       
   422     {
       
   423     if ( iNumberOfLines <= iLinesPerPage )
       
   424         {
       
   425         return;
       
   426         }
       
   427     
       
   428     if ( !iSBFrame )
       
   429         {
       
   430         // edwin will make scrollbar and also observe it
       
   431         iSBFrame = iEdwin->CreateScrollBarFrameL();
       
   432 
       
   433         // Check which type of scrollbar is to be shown
       
   434         iSBFrame->CreateDoubleSpanScrollBarsL(EFalse, EFalse, ETrue, EFalse );
       
   435         iSBFrame->SetTypeOfVScrollBar( CEikScrollBarFrame::EDoubleSpan );
       
   436         iSBFrame->DrawBackground( EFalse, EFalse );
       
   437         iSBFrame->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff,
       
   438                 CEikScrollBarFrame::EAuto );
       
   439         }
       
   440     
       
   441     iEdwin->UpdateScrollBarsL();    
       
   442     }
       
   443 
       
   444 EXPORT_C void CAknMessageQueryControl::Draw( const TRect& /*aRect*/ ) const
       
   445     {
       
   446     if ( iListQLayout )
       
   447     	{
       
   448         return;
       
   449         }
       
   450 
       
   451     CWindowGc& gc=SystemGc(); 
       
   452     TRect messageQueryControlRect( Rect() );
       
   453     TRect popupRect(LayoutRect());
       
   454 
       
   455     TRect backgroundRect(messageQueryControlRect.iTl, popupRect.iBr);    
       
   456     MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
   457     MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
       
   458 
       
   459     TRegionFix<4> clipReg;
       
   460     clipReg.AddRect( backgroundRect );
       
   461     
       
   462     if ( iEdwin )
       
   463         {
       
   464         clipReg.SubRect( iEdwin->Rect() );
       
   465         }
       
   466     
       
   467     gc.SetClippingRegion( clipReg );
       
   468     AknsDrawUtils::Background( skin, cc, this, gc, backgroundRect, 
       
   469             KAknsDrawParamNoClearUnderImage );
       
   470     gc.CancelClippingRegion();
       
   471     }
       
   472 
       
   473 TInt CAknMessageQueryControl::CurrentLink() const
       
   474     {
       
   475     if( 0 < iCurPos && iCurPos < iPositionsCount - 1 ) // The current position is on a link
       
   476         {
       
   477         return iCurPos - 1 + iFirstVisibleLink;
       
   478         }
       
   479     else    // No link is active
       
   480         {
       
   481         return -1;
       
   482         }
       
   483     }
       
   484 
       
   485 EXPORT_C TBool CAknMessageQueryControl::LinkHighLighted() const
       
   486     {
       
   487     return CurrentLink() > -1;
       
   488     }
       
   489 
       
   490 void CAknMessageQueryControl::SetHighlightOnL( TBool aOn )
       
   491     {
       
   492     if( !LinkHighLighted() )
       
   493         return;
       
   494     iCharFormatMask.ClearAll();
       
   495     if ( iEdwin && iEdwin->TextLength() > 0 &&
       
   496         iLinkTextArray.Count() > 0 && iLinkTextArray[CurrentLink()]->Length() > 0 )
       
   497         {
       
   498         iCharFormatMask.SetAttrib( EAttFontHighlightStyle );
       
   499         iCharFormatMask.SetAttrib( EAttFontHighlightColor );
       
   500         if ( aOn )
       
   501             {
       
   502             iCharFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightNormal;
       
   503             
       
   504             TRgb color = AKN_LAF_COLOR( 244 );
       
   505             AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), color, KAknsIIDQsnHighlightColors, EAknsCIQsnHighlightColorsCG1 ); 
       
   506             iCharFormat.iFontPresentation.iHighlightColor = color;
       
   507             
       
   508             color = AKN_LAF_COLOR( 210 );
       
   509             AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), color, KAknsIIDQsnHighlightColors, EAknsCIQsnHighlightColorsCG3 );                    
       
   510 	        iCharFormat.iFontPresentation.iTextColor = color;           
       
   511             }
       
   512         else
       
   513             {
       
   514             iCharFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightNone;
       
   515             }
       
   516 
       
   517         if ( iLinksCount > 0 )
       
   518             {
       
   519             iEdwin->RichText()->ApplyCharFormatL( iCharFormat, iCharFormatMask, ( iLinkTextLocationArray )[CurrentLink()], ( iLinkTextArray )[CurrentLink()]->Length() );
       
   520             }
       
   521 
       
   522         iEdwin->DrawNow();
       
   523         }
       
   524     }
       
   525     
       
   526 TBool CAknMessageQueryControl::CanScrollPage( TBool aMoveDown )
       
   527     {
       
   528     if( iNumberOfLines <= iLinesPerPage )    // Only one page
       
   529         return EFalse;
       
   530     if( aMoveDown )
       
   531         return iTopLine < iNumberOfLines - iLinesPerPage;
       
   532     else
       
   533         return iTopLine > 0;
       
   534     }    
       
   535 
       
   536 TBool CAknMessageQueryControl::IsLinkVisible( TInt aIndex ) const
       
   537     {
       
   538     if ( aIndex >= iLinksCount )
       
   539         {
       
   540         return EFalse;
       
   541         }
       
   542     TInt linkLine( iEdwin->TextLayout()->GetLineNumber( iLinkTextLocationArray[aIndex] ) );
       
   543     if ( iTopLine <= linkLine && linkLine < iTopLine + iLinesPerPage )
       
   544         {
       
   545         return ETrue;
       
   546         }
       
   547     else
       
   548         {
       
   549         return EFalse;
       
   550         }
       
   551     }
       
   552 
       
   553 void CAknMessageQueryControl::UpdatePageInfo()
       
   554     {
       
   555     TBool firstFound( EFalse );
       
   556     iVisibleLinksCount = 0;
       
   557     iFirstVisibleLink = -1;
       
   558     
       
   559     // Update visible links
       
   560     for( TInt count = 0; count < iLinksCount; count++ )
       
   561         {
       
   562         if( IsLinkVisible( count ) )
       
   563             {
       
   564             iVisibleLinksCount++;
       
   565             if( !firstFound )
       
   566                 {
       
   567                 iFirstVisibleLink = count;
       
   568                 firstFound = ETrue;
       
   569                 }
       
   570             }
       
   571         else if( firstFound )   // All visible links have been already found
       
   572             {
       
   573             break;
       
   574             }
       
   575         }
       
   576     
       
   577     // Update number of cursor positions
       
   578     if( iVisibleLinksCount > 0 )
       
   579         {
       
   580         iPositionsCount = iVisibleLinksCount + 2;
       
   581         }
       
   582     else
       
   583         {
       
   584         iPositionsCount = 1;
       
   585         }
       
   586     }
       
   587     
       
   588 void CAknMessageQueryControl::SetListQLayout(TBool aListQLayout)
       
   589     {
       
   590     iListQLayout = aListQLayout;
       
   591     }
       
   592 
       
   593     
       
   594 void CAknMessageQueryControl::SetMessageTextWithFormattingL( TDesC* aMessage, RArray<TDesC*>* aFormatTextArray, RArray<TInt>* aFormatTextLocationArray, RArray<TMsgQueryTag>* aFormatTypeArray )
       
   595     {
       
   596     if( iListQLayout )
       
   597         User::Leave( KErrNotSupported );  // Links in the list query layout are not supported
       
   598     CreateEditorL();
       
   599     iEdwin->TextLayout()->SetAmountToFormat( CTextLayout::EFFormatAllText );
       
   600     if ( aMessage->Length() > iEdwin->UpperFullFormattingLength() )
       
   601         iEdwin->SetUpperFullFormattingLength( aMessage->Length() ); 
       
   602     iEdwin->RichText()->DeleteL( 0, iEdwin->RichText()->DocumentLength() );
       
   603     iEdwin->RichText()->InsertL ( 0, *aMessage );
       
   604                 
       
   605     // Initialize link data
       
   606     for ( TInt count = 0; count < aFormatTypeArray->Count(); count++ )
       
   607         {
       
   608         if ( (*aFormatTypeArray)[count] == EMsgQueryLink )
       
   609             {
       
   610             // Add the link location and text keeping the arrays sorted on the location
       
   611             TInt location = (*aFormatTextLocationArray)[count];
       
   612             iLinkTextLocationArray.InsertInOrder( location );
       
   613             TInt index = iLinkTextLocationArray.FindInOrder( location );
       
   614             iLinkTextArray.Insert( (*aFormatTextArray)[count], index );
       
   615             }
       
   616         }
       
   617     iLinksCount = iLinkTextLocationArray.Count();
       
   618 
       
   619     iCharFormatMask.ClearAll();    
       
   620     
       
   621     // Set link font
       
   622     if (aMessage->Length() > 0)
       
   623         {
       
   624         // Set font color and underlining
       
   625        	for (TInt count = 0; count < iLinksCount; count++)
       
   626 	        {    
       
   627 	        if ((iLinkTextLocationArray )[count] != KErrNotFound)
       
   628 	            {
       
   629 	            iCharFormatMask.SetAttrib( EAttFontUnderline );
       
   630 	            iCharFormatMask.SetAttrib( EAttColor );
       
   631 	            iCharFormat.iFontPresentation.iUnderline = EUnderlineOn;
       
   632 	            
       
   633 	            TRgb color = AKN_LAF_COLOR( 210 );
       
   634                 AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), color, KAknsIIDQsnHighlightColors, EAknsCIQsnHighlightColorsCG3 );
       
   635                     
       
   636 	            iCharFormat.iFontPresentation.iTextColor = color;
       
   637 	            
       
   638 	            iEdwin->RichText()->ApplyCharFormatL(iCharFormat, iCharFormatMask, (iLinkTextLocationArray)[count], ((iLinkTextArray )[count])->Length());
       
   639 	            }            
       
   640 	        }     
       
   641         
       
   642         iCharFormatMask.ClearAll();
       
   643         
       
   644         // Set font boldness
       
   645         for ( TInt count = 0; count < aFormatTextLocationArray->Count(); count++ )
       
   646 	        {    
       
   647 	        if ((*aFormatTextLocationArray)[count] != KErrNotFound && (*aFormatTypeArray)[count] == EMsgQueryBold)
       
   648 	            {
       
   649 	            iCharFormatMask.SetAttrib( EAttFontStrokeWeight );
       
   650 	            iCharFormat.iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
       
   651 	            iEdwin->RichText()->ApplyCharFormatL( iCharFormat, iCharFormatMask, (*aFormatTextLocationArray)[count], (*aFormatTextArray )[count]->Length() );
       
   652 	            }
       
   653 	        }
       
   654 	    }
       
   655         
       
   656     LayoutEditorL();
       
   657     
       
   658     if ( aMessage->Locate( '\n' ) != KErrNotFound )
       
   659         {
       
   660         iEdwin->SetCursorPosL( 1, EFalse );
       
   661         SEdwinFindModel findModel;
       
   662         _LIT( KNChar,"\n" ); 
       
   663         _LIT( KFChar,"\f" );
       
   664         TBuf<1> text( KNChar );
       
   665         TBuf<1> replaceText( KFChar );
       
   666         findModel.iFlags = 0;
       
   667         findModel.iText = text;
       
   668         findModel.iReplaceText = replaceText;
       
   669         findModel.iReplaceOption = EReplaceAll;
       
   670         iEdwin->ReplaceAllL( &findModel );
       
   671         }
       
   672         
       
   673     iNumberOfLines = iEdwin->TextLayout()->NumFormattedLines();
       
   674     iTopLine = 0;
       
   675     iCurPos = 0;   // Page top, no link selected
       
   676     
       
   677     UpdatePageInfo();
       
   678     UpdateScrollIndicatorL();
       
   679     }
       
   680 
       
   681 
       
   682 /**
       
   683  * CAknMessageQueryControl::HandlePointerEventL()
       
   684  *
       
   685  * Transfers pointerevent to editor control.
       
   686  * Checks for the object destruction after the pointer event handling.
       
   687  */
       
   688 void CAknMessageQueryControl::HandlePointerEventL( const TPointerEvent& aPointerEvent )
       
   689     {
       
   690     TBool highlightBefore = LinkHighLighted();
       
   691     /**
       
   692     * The local @c destroyed variable keeps track of the object destroyed state.
       
   693     */
       
   694     TBool destroyed = EFalse;
       
   695     
       
   696     iExtension->iDestroyedPtr = &destroyed;
       
   697 
       
   698     // Call default implementation of HandlePointerEventL to transfer event to correct control.
       
   699     CAknControl::HandlePointerEventL( aPointerEvent );
       
   700 
       
   701     if ( !destroyed )
       
   702         {
       
   703         iExtension->iDestroyedPtr = NULL;
       
   704         }
       
   705     else
       
   706         {
       
   707         return;
       
   708         }
       
   709     
       
   710     TBool highlightAfter = LinkHighLighted();
       
   711     if( aPointerEvent.iType == TPointerEvent::EButton1Down && 
       
   712         highlightBefore == highlightAfter && highlightAfter )
       
   713         {
       
   714         DehighlightLink();
       
   715         }
       
   716     }
       
   717 
       
   718 //----------------------------------------------------------------------------------
       
   719 // CAknMessageQueryControl::LinkTapped()
       
   720 // Checks if a link is tapped and hightlights it. 
       
   721 //----------------------------------------------------------------------------------
       
   722 //
       
   723 
       
   724 TBool CAknMessageQueryControl::LinkTappedL( TInt aPos )
       
   725     {
       
   726     if ( iLinksCount <= 0 )
       
   727         {
       
   728         return EFalse; 
       
   729         }
       
   730     /** There can be 3 possible results.
       
   731     1. The link is found and it's a new link.
       
   732     2. The link is found, but it's the current link.
       
   733     3. The link was not found at the tapped position. 
       
   734     */
       
   735     TInt oldLink = CurrentLink();
       
   736     TInt linkPos = 0; 
       
   737     for ( TInt count = 0; count < iLinksCount; count++ )
       
   738         {
       
   739         linkPos = iLinkTextLocationArray[count];
       
   740         if ( linkPos <= aPos && aPos < linkPos + iLinkTextArray[count]->Length() ) // The tapped link found
       
   741             {
       
   742             if ( oldLink != count ) // A new link
       
   743                 {
       
   744                 TInt editorTopLine = iEdwin->TextLayout()->FirstLineInBand();
       
   745                 if( iTopLine != editorTopLine ) // User scrolled with the pen
       
   746                     {
       
   747                     // Synchronize query's top line with editor's one
       
   748                     iTopLine = editorTopLine;
       
   749                     UpdatePageInfo();
       
   750                     }
       
   751                 SetCurPosL( count - iFirstVisibleLink + 1 ); 
       
   752                 }
       
   753             return ETrue; 
       
   754             }
       
   755         }
       
   756     DehighlightLink();
       
   757     return EFalse; 
       
   758     }
       
   759 
       
   760 
       
   761 TBool CAknMessageQueryControl::SetCurPosL( TInt aCurPos )
       
   762     {
       
   763     if( aCurPos < 0 || aCurPos >= iPositionsCount )
       
   764         return EFalse;
       
   765     SetHighlightOnL( EFalse );  // Dehighlight the old link
       
   766     iCurPos = aCurPos;
       
   767     SetHighlightOnL( ETrue );     // Highlight the new link
       
   768     return ETrue;
       
   769     }
       
   770     
       
   771 void CAknMessageQueryControl::DehighlightLink()
       
   772     {
       
   773     if ( !LinkHighLighted() )
       
   774         {
       
   775         return; 
       
   776         }
       
   777     TRAP_IGNORE( SetHighlightOnL( EFalse ) );  // Dehighlight the old link
       
   778     iCurPos = 0;    // Move the cursor to the top of the page
       
   779     // Update the softkey labels (set them to "Ok - Cancel")
       
   780     CAknMessageQueryDialog* dlg;
       
   781     MopGetObject( dlg );
       
   782     if ( dlg )
       
   783         {
       
   784         dlg->UpdateSoftkeyLabels();
       
   785         }
       
   786     }
       
   787 
       
   788 TBool CAknMessageQueryControl::ScrollBarGrabbing()
       
   789     {
       
   790     CCoeControl* grabbingComponent = GrabbingComponent();
       
   791 
       
   792     TBool grabbing = EFalse;
       
   793     if (grabbingComponent)
       
   794         {
       
   795         grabbing = iSBFrame && iSBFrame->GetScrollBarHandle(
       
   796             CEikScrollBar::EVertical) == grabbingComponent;
       
   797         }
       
   798     return grabbing;
       
   799     }
       
   800 
       
   801 void CAknMessageQueryControl::TruncateTextForListQLayout( TDes& aMessage )
       
   802     {
       
   803     if( !iListQLayout )
       
   804         return;
       
   805 
       
   806     delete iFullMessage;
       
   807     iFullMessage = NULL;
       
   808     iFullMessage = aMessage.AllocL();
       
   809     TInt maxLines = 3;  // Should be AknLayoutScalable_Apps::loc_type_pane_t1_ParamLimits().LastRow();
       
   810     TInt lastLineBegin = iEdwin->TextLayout()->FirstCharOnLine( maxLines );       
       
   811     TInt lastLineEnd = iEdwin->TextLayout()->FirstCharOnLine( maxLines + 1 );       
       
   812     if( lastLineEnd < aMessage.Length() )
       
   813         {
       
   814         const CFont* font = AknLayoutUtils::FontFromId(
       
   815             AknLayoutScalable_Avkon::popup_info_list_pane_t1( 0 ).Font() );
       
   816         TInt ellipsisPosInLastLine = font->TextCount( aMessage.Mid( lastLineBegin, lastLineEnd - lastLineBegin ),
       
   817             iEdwin->LayoutWidth() - font->CharWidthInPixels( KEllipsis ) ) - 1;
       
   818         aMessage = aMessage.LeftTPtr( lastLineBegin + ellipsisPosInLastLine );
       
   819         aMessage.Append( KEllipsis );
       
   820         }
       
   821     }
       
   822 
       
   823 void CAknMessageQueryControl::DoSizeChangedL()
       
   824     {
       
   825     if ( iListQLayout )
       
   826         {
       
   827         iLinesPerPage = 3;  // Should be AknLayoutScalable_Apps::loc_type_pane_t1_ParamLimits().LastRow();
       
   828         HBufC* msgBuf = iFullMessage->AllocLC() ;
       
   829         TPtr message( msgBuf->Des() );
       
   830         iEdwin->SetTextL( &message );
       
   831         LayoutEditorL(); 
       
   832         TruncateTextForListQLayout( message );
       
   833         iEdwin->SetTextL( &message );
       
   834         CleanupStack::PopAndDestroy( msgBuf );  // After all usages of message        
       
   835         iNumberOfLines = iEdwin->TextLayout()->NumFormattedLines();
       
   836         }
       
   837     else
       
   838         {
       
   839         iLinesPerPage = AknLayoutScalable_Avkon::popup_info_list_pane_t1_ParamLimits().LastRow() + 1;    
       
   840         }    
       
   841     
       
   842     TInt lines = iNumberOfLines > iLinesPerPage ? iLinesPerPage : iNumberOfLines;
       
   843     if (lines <= 0)
       
   844         {
       
   845         return;
       
   846         }
       
   847 
       
   848     RArray<TAknTextComponentLayout> textComponentLayoutArray;
       
   849     for ( TInt rowIndex = 0; rowIndex < lines; rowIndex++)
       
   850         {
       
   851         TRAPD(error, textComponentLayoutArray.AppendL(AknLayoutScalable_Avkon::popup_info_list_pane_t1(rowIndex)));
       
   852         if (error != KErrNone)
       
   853             {
       
   854             if (rowIndex == 0)
       
   855                 {
       
   856                 // Give up! textComponentLayoutArray does not contain any items.
       
   857                 textComponentLayoutArray.Close();
       
   858                 return; // Layout will fail...
       
   859                 }
       
   860             }
       
   861         }
       
   862 
       
   863     TAknLayoutRect listScrollPopupInfoPane;
       
   864     listScrollPopupInfoPane.LayoutRect( LayoutRect(), AknLayoutScalable_Avkon::listscroll_popup_info_pane() );
       
   865     TRect listScrollPopupInfoPaneRect( listScrollPopupInfoPane.Rect() );
       
   866     CAknPopupHeadingPane* heading = NULL;
       
   867     if( iListQLayout )
       
   868     	{
       
   869     	CAknListQueryDialog* dlg;
       
   870     	MopGetObject( dlg );
       
   871     	if( dlg )
       
   872     		{
       
   873     		heading = dlg->QueryHeading();
       
   874     		}    	
       
   875     	}
       
   876     else
       
   877     	{
       
   878     	CEikDialog* dlg;
       
   879         MopGetObject( dlg );
       
   880         if( dlg )
       
   881         	{
       
   882         	heading = (CAknPopupHeadingPane*)dlg->ControlOrNull(EAknMessageQueryHeaderId); 
       
   883         	}        
       
   884     	}
       
   885     if( heading && heading->PromptText() == KNullDesC )
       
   886         {
       
   887         TAknLayoutRect headingPaneLayout;
       
   888         headingPaneLayout.LayoutRect( LayoutRect(), AknLayoutScalable_Avkon::heading_pane_cp5() );
       
   889         listScrollPopupInfoPaneRect.Move( 0, -1 * headingPaneLayout.Rect().Height() );
       
   890         }
       
   891     TAknLayoutRect listPopupInfoPane;    
       
   892     listPopupInfoPane.LayoutRect( listScrollPopupInfoPaneRect, AknLayoutScalable_Avkon::list_popup_info_pane( 0 ) );  // Variety with scroll bar    
       
   893     
       
   894     
       
   895     /** The edwin rect is set totally from layout list_popup_info_pane. But
       
   896       * AknLayoutUtils::LayoutEdwin() is still used for setting its text color and font. 
       
   897      **/ 
       
   898     TAknMultiLineTextLayout multilineLayout = TAknTextComponentLayout::Multiline(textComponentLayoutArray);
       
   899     AknLayoutUtils::LayoutEdwin( iEdwin, listPopupInfoPane.Rect(),
       
   900         multilineLayout, EAknsCIQsnTextColorsCG19 );
       
   901     //iEdwin->SetRect( listPopupInfoPane.Rect() );
       
   902     textComponentLayoutArray.Close();
       
   903     
       
   904     iEdwin->SetBorder( TGulBorder::ENone );
       
   905     iEdwin->SetFocus( EFalse );
       
   906     AknsUtils::RegisterControlPosition( iEdwin );
       
   907     
       
   908     iNumberOfLines = iEdwin->TextLayout()->NumFormattedLines();
       
   909     
       
   910     UpdateScrollIndicatorL();
       
   911     }
       
   912 //  End of File