uifw/AvKon/src/aknmessagequerydialog.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
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 <eikimage.h>
       
    21 #include <eikcapc.h>
       
    22 
       
    23 #include <avkon.rsg>
       
    24 
       
    25 #include <avkon.hrh>
       
    26 #include <aknappui.h>
       
    27 #include <aknextendedinputcapabilities.h>
       
    28 
       
    29 #include "aknPopupHeadingPane.h"
       
    30 #include "aknconsts.h"
       
    31 #include "aknborders.h"
       
    32 #include "AknUtils.h"
       
    33 
       
    34 #include "aknmessagequerycontrol.h"
       
    35 #include "aknmessagequerydialog.h"
       
    36 
       
    37 #include <applayout.cdl.h>
       
    38 #include <layoutmetadata.cdl.h>
       
    39 #include <aknlayoutscalable_avkon.cdl.h>
       
    40 #include <touchfeedback.h>
       
    41 
       
    42 #include <AknTasHook.h> // for testability hooks
       
    43 #include "AknHeadingPaneTouchObserver.h"
       
    44 
       
    45 
       
    46 // CONSTANTS
       
    47 const TInt KMaxLinks = 64;
       
    48 
       
    49 const TInt KLinkStartTagLength = 22;
       
    50 const TInt KLinkEndTagLength = 23;
       
    51 const TInt KBoldStartTagLength = 22;
       
    52 const TInt KBoldEndTagLength = 23;
       
    53 
       
    54 
       
    55 class CAknMessageQueryDialogExtension : public CBase, public CAknExtendedInputCapabilities::MAknEventObserver,
       
    56                                         public MAknHeadingPaneTouchObserver
       
    57     {
       
    58 public:
       
    59     CAknMessageQueryDialogExtension( CAknMessageQueryDialog* aParent  ) : iParent(aParent),
       
    60                                                                           iControlRegisted( EFalse ) {}
       
    61     ~CAknMessageQueryDialogExtension()
       
    62         {       
       
    63         TInt count = iFormatTextArray.Count();
       
    64         for ( TInt i = 0; i < count; i++ )
       
    65             {
       
    66             delete iFormatTextArray[i];        
       
    67             }
       
    68         iCallBackArray.Close();
       
    69         iFormatTextLocationArray.Close();
       
    70         iFormatTextArray.Close();
       
    71         iFormatTypeArray.Close();
       
    72         
       
    73         if ( iDestroyedPtr )
       
    74             {
       
    75             // Mark the object as destroyed.
       
    76             *iDestroyedPtr = ETrue;
       
    77             iDestroyedPtr = NULL;
       
    78             }
       
    79         }
       
    80             
       
    81     /** From CAknExtendedInputCapabilities::MAknEventObserver
       
    82     */
       
    83     void HandleInputCapabilitiesEventL( TInt aEvent, TAny* aParams ) 
       
    84         {
       
    85         if ( aEvent == CAknExtendedInputCapabilities::MAknEventObserver::EPointerEventReceived )
       
    86             {
       
    87             iParent->CheckLinkTappedL(aParams); 
       
    88             }   
       
    89         }
       
    90         
       
    91     /**
       
    92     * From MAknHeadingPaneTouchObserver
       
    93     * Processes heading pane pointer events. On the pen down events, any link is dehighlighted.
       
    94     */
       
    95     void HandleHeadingPanePointerEventL( CAknPopupHeadingPane* /*aHeadingPane*/, const TPointerEvent& aPointerEvent )
       
    96         {
       
    97         if( aPointerEvent.iType == TPointerEvent::EButton1Down && iCtrl )
       
    98             {
       
    99             iCtrl->DehighlightLink();
       
   100             }
       
   101         }
       
   102 
       
   103 public:
       
   104     
       
   105     TInt iAnimationId;
       
   106         
       
   107     RArray<TCallBack> iCallBackArray;
       
   108     RArray<TInt> iFormatTextLocationArray;
       
   109     RArray<TDesC*> iFormatTextArray;
       
   110     RArray<TMsgQueryTag> iFormatTypeArray;
       
   111         
       
   112     TInt iLinkCount; // values between 0 and KMaxLinks-1
       
   113     TBool iMarkedLinks;
       
   114     TInt iButtonGroupPreviouslyChanged;
       
   115     CAknMessageQueryDialog* iParent;
       
   116     TBool iControlRegisted; 
       
   117     CAknMessageQueryControl* iCtrl;
       
   118     
       
   119     /**
       
   120     * @c iDestroyedPtr is used for the object destruction check.
       
   121     * If it has non-null value, the destruction check is turned on, and
       
   122     * the value points to a local boolean variable that keeps the destroyed state.
       
   123     */
       
   124     TBool* iDestroyedPtr;
       
   125     TBool iIsInEditor;
       
   126     };
       
   127     
       
   128 
       
   129 EXPORT_C CAknMessageQueryDialog* CAknMessageQueryDialog::NewL( TDesC& aMessage, const TTone& aTone )
       
   130     {
       
   131     CAknMessageQueryDialog* self = new ( ELeave ) CAknMessageQueryDialog( aTone );
       
   132     CleanupStack::PushL( self );
       
   133     self->SetMessageTextL( aMessage );
       
   134     CleanupStack::Pop(); //self
       
   135     AKNTASHOOK_ADDL( self, "CAknMessageQueryDialog" );
       
   136     return self;
       
   137     }
       
   138 
       
   139 //@deprecated
       
   140 EXPORT_C CAknMessageQueryDialog::CAknMessageQueryDialog() : CAknQueryDialog( ENoTone )
       
   141     {
       
   142 #ifndef RD_NO_DIALOG_BORDERS
       
   143     iBorder = AknBorderId::EAknBorderNotePopup;
       
   144 #else
       
   145     iBorder = TGulBorder::ENone;
       
   146 #endif
       
   147     }
       
   148 
       
   149 EXPORT_C CAknMessageQueryDialog::CAknMessageQueryDialog( const TTone aTone ) : CAknQueryDialog( aTone )
       
   150     {
       
   151 #ifndef RD_NO_DIALOG_BORDERS
       
   152     iBorder = AknBorderId::EAknBorderNotePopup;
       
   153 #else
       
   154     iBorder = TGulBorder::ENone;
       
   155 #endif
       
   156     }
       
   157 
       
   158 //@deprecated
       
   159 EXPORT_C CAknMessageQueryDialog::CAknMessageQueryDialog( TDesC* aMessage, TDesC* aHeader ) 
       
   160     : CAknQueryDialog( ENoTone ), iMessage( aMessage ), iHeader( aHeader )
       
   161     {
       
   162 #ifndef RD_NO_DIALOG_BORDERS
       
   163     iBorder = AknBorderId::EAknBorderNotePopup;
       
   164 #else
       
   165     iBorder = TGulBorder::ENone;
       
   166 #endif
       
   167     }
       
   168 
       
   169 //@deprecated
       
   170 EXPORT_C CAknMessageQueryDialog::CAknMessageQueryDialog( TDesC* aMessage, TDesC* aHeader, CEikImage *aHeaderImage )
       
   171     : CAknQueryDialog( ENoTone ), iMessage( aMessage ), iHeader( aHeader ), iHeaderImage( aHeaderImage )
       
   172     {
       
   173 #ifndef RD_NO_DIALOG_BORDERS
       
   174     iBorder = AknBorderId::EAknBorderNotePopup;
       
   175 #else
       
   176     iBorder = TGulBorder::ENone;
       
   177 #endif
       
   178     }
       
   179 
       
   180 //@deprecated
       
   181 EXPORT_C CAknMessageQueryDialog::CAknMessageQueryDialog( TDesC* aMessage, TDesC* aHeader, const TTone aTone )
       
   182     : CAknQueryDialog( aTone ), iMessage( aMessage ), iHeader( aHeader )
       
   183     {
       
   184 #ifndef RD_NO_DIALOG_BORDERS
       
   185     iBorder = AknBorderId::EAknBorderNotePopup;
       
   186 #else
       
   187     iBorder = TGulBorder::ENone;
       
   188 #endif
       
   189     }
       
   190 
       
   191 //@deprecated
       
   192 EXPORT_C CAknMessageQueryDialog::CAknMessageQueryDialog( TDesC* aMessage, TDesC* aHeader, CEikImage *aHeaderImage, const TTone aTone )
       
   193     : CAknQueryDialog( aTone ), iMessage( aMessage ), iHeader( aHeader ), iHeaderImage( aHeaderImage )
       
   194     {
       
   195 #ifndef RD_NO_DIALOG_BORDERS
       
   196     iBorder = AknBorderId::EAknBorderNotePopup;
       
   197 #else
       
   198     iBorder = TGulBorder::ENone;
       
   199 #endif
       
   200     }
       
   201 
       
   202 EXPORT_C CAknMessageQueryDialog::~CAknMessageQueryDialog()
       
   203     {
       
   204     AKNTASHOOK_REMOVE();
       
   205     delete iMessage;
       
   206     delete iHeader;
       
   207     delete iHeaderImage;
       
   208     RegisterPointerEventObserver( EFalse ); 
       
   209     delete iMsgQueryExtension;
       
   210     }
       
   211 
       
   212 EXPORT_C void CAknMessageQueryDialog::SetMessageTextL( const TDesC& aMessage )
       
   213     {
       
   214     delete iMessage;
       
   215     iMessage = NULL;
       
   216     iMessage = aMessage.AllocL();
       
   217     }
       
   218 
       
   219 EXPORT_C void CAknMessageQueryDialog::SetLinkTextL( const TDesC& aLinkText )
       
   220     {
       
   221     if ( !iMsgQueryExtension )
       
   222         {
       
   223         CreateExtensionL();
       
   224         }
       
   225 
       
   226     if ( iMsgQueryExtension->iMarkedLinks ) 
       
   227         {
       
   228         return;            
       
   229         }
       
   230     else if ( iMsgQueryExtension->iLinkCount < KMaxLinks ) 
       
   231         {        
       
   232         if ( LinksInArray() > iMsgQueryExtension->iLinkCount )
       
   233             {
       
   234             // SetLinkText is already set and method resets it
       
   235             TInt lastIndex = LastLinkInArray();
       
   236             if (lastIndex == -1)
       
   237                 {
       
   238                 return; //something went wrong - go away
       
   239                 }
       
   240             iMsgQueryExtension->iFormatTextArray[lastIndex] = aLinkText.AllocL();
       
   241             }
       
   242         else
       
   243             {
       
   244             // SetLinkTextL creates new callback in the callback array for the new link
       
   245             iMsgQueryExtension->iFormatTextArray.Append( aLinkText.AllocL() );
       
   246             iMsgQueryExtension->iFormatTypeArray.Append( EMsgQueryLink );
       
   247                
       
   248             // If the other method SetLink has been already called 
       
   249             // the new link is finished by adding the link count
       
   250             if ( iMsgQueryExtension->iCallBackArray.Count() > iMsgQueryExtension->iLinkCount )
       
   251                 {
       
   252                 iMsgQueryExtension->iLinkCount++;                                            
       
   253                 }                
       
   254             }
       
   255         }
       
   256     }
       
   257 
       
   258 EXPORT_C void CAknMessageQueryDialog::SetLink( TCallBack& aCallBack )
       
   259     {
       
   260     if ( !iMsgQueryExtension )
       
   261         {
       
   262         TRAPD( Err, CreateExtensionL() );
       
   263         if ( Err != KErrNone )
       
   264             {
       
   265             return;
       
   266             }
       
   267         }
       
   268            
       
   269     if ( !iMsgQueryExtension->iMarkedLinks && iMessage )
       
   270         {
       
   271         TInt index = iMessage->Find( KOpeningLinkTag );
       
   272         
       
   273         if ( index != KErrNotFound ) 
       
   274             {
       
   275             iMsgQueryExtension->iMarkedLinks = ETrue;
       
   276             }
       
   277         else 
       
   278             {
       
   279             iMsgQueryExtension->iMarkedLinks = EFalse;
       
   280             }
       
   281         iMsgQueryExtension->iLinkCount = CountLinks();
       
   282         }
       
   283         
       
   284     if ( iMsgQueryExtension->iMarkedLinks )
       
   285         {
       
   286         if ( iMsgQueryExtension->iCallBackArray.Count() < iMsgQueryExtension->iLinkCount )
       
   287             {
       
   288             // SetLink creates new callback in the callback array for the new link
       
   289             iMsgQueryExtension->iCallBackArray.Append( aCallBack );                
       
   290             }
       
   291         }         
       
   292     else if ( iMsgQueryExtension->iLinkCount < KMaxLinks ) 
       
   293         {
       
   294         if ( iMsgQueryExtension->iCallBackArray.Count() > iMsgQueryExtension->iLinkCount ) 
       
   295             {
       
   296             // SetLink is already set and method resets it
       
   297             iMsgQueryExtension->iCallBackArray[iMsgQueryExtension->iCallBackArray.Count()-1] = aCallBack;            
       
   298             }
       
   299         else
       
   300             {
       
   301             // SetLink creates new callback in the callback array for the new link
       
   302             iMsgQueryExtension->iCallBackArray.Append( aCallBack );
       
   303                 
       
   304             // If the other method SetLinkText has been already called 
       
   305             // the new link is finished by adding the link count
       
   306             
       
   307             if ( LinksInArray() > iMsgQueryExtension->iLinkCount )                        
       
   308                 {
       
   309                 iMsgQueryExtension->iLinkCount++;                                            
       
   310                 }                
       
   311             }
       
   312         }
       
   313     }
       
   314 
       
   315 
       
   316 /**
       
   317  * @deprecated and will be removed - Use SetMessageTextL instead
       
   318  */
       
   319 EXPORT_C void CAknMessageQueryDialog::SetMessageText( const TDesC& aMessage )
       
   320     {
       
   321     TRAP_IGNORE( SetMessageTextL( aMessage ) );
       
   322     }
       
   323 
       
   324 /**
       
   325  * @deprecated - use Heading() + CAknPopupHeadingPane API
       
   326  */
       
   327 EXPORT_C void CAknMessageQueryDialog::SetHeaderTextL( const TDesC& aHeader )
       
   328     {
       
   329     delete iHeader;
       
   330     iHeader = NULL;
       
   331     iHeader = aHeader.AllocL();
       
   332     }
       
   333 
       
   334 /**
       
   335  * @deprecated and will be removed - Use SetHeaderTextL instead
       
   336  */
       
   337 EXPORT_C void CAknMessageQueryDialog::SetHeaderText( const TDesC& aHeader )
       
   338     {
       
   339     TRAP_IGNORE( SetHeaderTextL( aHeader ) );
       
   340     }
       
   341 
       
   342 //@deprecated
       
   343 EXPORT_C void CAknMessageQueryDialog::SetMessageText( TDesC* aMessage )
       
   344     {
       
   345     delete iMessage;
       
   346     iMessage = aMessage;
       
   347     }
       
   348 
       
   349 //@deprecated
       
   350 EXPORT_C void CAknMessageQueryDialog::SetHeaderText( TDesC* aHeader )
       
   351     {
       
   352     delete iHeader;
       
   353     iHeader = aHeader;
       
   354     }
       
   355 
       
   356 EXPORT_C void CAknMessageQueryDialog::PreLayoutDynInitL()
       
   357     {
       
   358     if ( !iMsgQueryExtension )
       
   359         {
       
   360         CreateExtensionL();
       
   361         }      
       
   362         
       
   363     //old style with no tags
       
   364     if ( iMessage && iMsgQueryExtension )
       
   365         {
       
   366         if ( !iMsgQueryExtension->iMarkedLinks && iMsgQueryExtension->iLinkCount >0  )
       
   367             {
       
   368             for ( TInt count = 0; count < iMsgQueryExtension->iLinkCount; count++ )
       
   369                 {
       
   370                 if ( !SetNextLinkTextLocationL( iMsgQueryExtension->iFormatTextArray[count] ) ) 
       
   371                     {
       
   372                     break;
       
   373                     }
       
   374                 }
       
   375             }
       
   376         else if ( TaggedMessageL() )
       
   377             {      
       
   378             iMsgQueryExtension->iMarkedLinks = ETrue;
       
   379             ParseMessageTxtL();
       
   380             }          
       
   381         }
       
   382     
       
   383     SetLineNonFocusing( EAknMessageQueryHeaderId );  
       
   384         
       
   385     CAknMessageQueryControl* msgCtrl = STATIC_CAST( CAknMessageQueryControl*, Control( EAknMessageQueryContentId ) );
       
   386 
       
   387     if ( iMsgQueryExtension )
       
   388         {
       
   389         iMsgQueryExtension->iCtrl = msgCtrl;
       
   390         }
       
   391     
       
   392     if ( iMessage && iMsgQueryExtension )
       
   393         {
       
   394         msgCtrl->SetMessageTextWithFormattingL( iMessage, &iMsgQueryExtension->iFormatTextArray, &iMsgQueryExtension->iFormatTextLocationArray, &iMsgQueryExtension->iFormatTypeArray );
       
   395         RegisterPointerEventObserver( ETrue ); 
       
   396         }    
       
   397     else if ( iMessage )
       
   398         {
       
   399         msgCtrl->SetMessageTextL( iMessage );
       
   400         }
       
   401     
       
   402     msgCtrl->SetMopParent( this );
       
   403     delete iMessage;
       
   404     iMessage = NULL;
       
   405 
       
   406     CAknPopupHeadingPane* headingPane = STATIC_CAST( CAknPopupHeadingPane*, Control( EAknMessageQueryHeaderId ) );
       
   407     if ( iHeader )
       
   408         {
       
   409         headingPane->SetTextL( *iHeader );
       
   410         delete iHeader;
       
   411         iHeader = NULL;
       
   412         }
       
   413         
       
   414     if ( iMsgQueryExtension && iMsgQueryExtension->iAnimationId > 0 )
       
   415         {
       
   416         headingPane->SetHeaderAnimationL( iMsgQueryExtension->iAnimationId );
       
   417         }
       
   418     else if ( iHeaderImage )
       
   419         {
       
   420         headingPane->SetHeaderImageL( iHeaderImage );
       
   421         }
       
   422         
       
   423     if (headingPane)
       
   424         {
       
   425         headingPane->SetLayout(CAknPopupHeadingPane::EMessageQueryHeadingPane); // Use message query heading layout.    
       
   426         headingPane->SetTouchObserver( iMsgQueryExtension );
       
   427         }
       
   428     }
       
   429 
       
   430    
       
   431 EXPORT_C void CAknMessageQueryDialog::SetSizeAndPosition( const TSize& aSize )
       
   432     {
       
   433     if ( AknLayoutUtils::PenEnabled() )
       
   434         {
       
   435         // Ideally line below would be replaced with base class call. However
       
   436         // CAknQueryDialog's functionality relies on method
       
   437         // CAknQueryDialog::QueryControl that doesn't return message query
       
   438         // control -> dialog's size won't be set in the base class.
       
   439         SetRect( TRect( AknPopupUtils::Position( aSize, this ), aSize ) ); 
       
   440         }
       
   441     else
       
   442         {
       
   443         TAknLayoutRect dialogLayout;
       
   444         
       
   445         CAknMessageQueryControl* messageQueryControl =
       
   446             STATIC_CAST( CAknMessageQueryControl*,
       
   447                 Control( EAknMessageQueryContentId ) );
       
   448         
       
   449         TInt numberOfLines = messageQueryControl->Lines();
       
   450         
       
   451         // Number of rows that fits to the dialog
       
   452         const TInt rowsPerPage =
       
   453             AknLayoutScalable_Avkon::popup_info_list_pane_t1_ParamLimits().
       
   454                 LastRow() + 1;
       
   455         
       
   456         numberOfLines =
       
   457             numberOfLines > rowsPerPage ? rowsPerPage : numberOfLines;
       
   458         numberOfLines--;
       
   459         if ( numberOfLines < 0 ) 
       
   460             {
       
   461             numberOfLines = 0;    
       
   462             }
       
   463 
       
   464         TRect mainPane;
       
   465         AknLayoutUtils::LayoutMetricsRect(
       
   466             AknLayoutUtils::EPopupParent, mainPane );
       
   467             
       
   468         TInt variety = 0;
       
   469         AknLayoutUtils::TAknCbaLocation cbaLocation =
       
   470             AknLayoutUtils::CbaLocation();
       
   471         
       
   472         if (cbaLocation == AknLayoutUtils::EAknCbaLocationRight)
       
   473             { // Variety numbers for right CBA are 6-11
       
   474             variety = numberOfLines + 6;
       
   475             }
       
   476         else if (cbaLocation == AknLayoutUtils::EAknCbaLocationLeft)
       
   477             { // Variety numbers for left CBA are 12-17
       
   478             variety = numberOfLines + 12;
       
   479             }
       
   480         else // bottom
       
   481             {
       
   482             variety = numberOfLines;
       
   483             }
       
   484 
       
   485         dialogLayout.LayoutRect(mainPane,
       
   486             AknLayoutScalable_Avkon::popup_query_sat_info_window( variety ) );
       
   487         TRect dialogRect( dialogLayout.Rect() );
       
   488         if( QueryHeading()->PromptText() == KNullDesC )
       
   489             {
       
   490             TAknLayoutRect headingPaneLayout;
       
   491             headingPaneLayout.LayoutRect(dialogRect,
       
   492                 AknLayoutScalable_Avkon::heading_pane_cp5() );
       
   493             dialogRect.iTl.iY += headingPaneLayout.Rect().Height();
       
   494             }
       
   495         // No Dialog borders in message queries
       
   496         SetBorder( TGulBorder::ENone ); 
       
   497         SetRect( dialogRect ); 
       
   498         }
       
   499     }
       
   500    
       
   501 
       
   502 EXPORT_C void CAknMessageQueryDialog::PostLayoutDynInitL()
       
   503     {
       
   504     }
       
   505 
       
   506 
       
   507 EXPORT_C TKeyResponse CAknMessageQueryDialog::OfferKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aModifiers )
       
   508     {
       
   509     
       
   510     TInt code=aKeyEvent.iCode;
       
   511 
       
   512     switch ( code )
       
   513         {
       
   514         case EKeyUpArrow:
       
   515         case EKeyDownArrow:
       
   516             {
       
   517             CAknMessageQueryControl* messageQueryControl = STATIC_CAST( CAknMessageQueryControl*, Control( EAknMessageQueryContentId ) );
       
   518             if ( messageQueryControl )
       
   519                 {
       
   520                 TKeyResponse answer = messageQueryControl->OfferKeyEventL( aKeyEvent, aModifiers );   
       
   521                 if ( answer == EKeyWasConsumed && iMsgQueryExtension )
       
   522                     {
       
   523                     UpdateSoftkeyLabels();
       
   524                     }
       
   525                 return answer;  
       
   526                 }
       
   527             }
       
   528             break;      
       
   529         case EKeyEnter:
       
   530         case EKeyOK:    
       
   531             {
       
   532             if ( iMsgQueryExtension && iMsgQueryExtension->iLinkCount > 0 )
       
   533                 {
       
   534                 if( ExecuteLinkL() )
       
   535                     return EKeyWasConsumed;
       
   536                 }
       
   537             TryExitL(EEikBidOk);
       
   538             return EKeyWasConsumed;
       
   539             }
       
   540 
       
   541         default:
       
   542             break;
       
   543         }
       
   544     return CAknQueryDialog::OfferKeyEventL( aKeyEvent, aModifiers );
       
   545     }
       
   546     
       
   547     
       
   548 /**
       
   549  *From MEikCommandObserver (act on the menu selection if menu is showing - pass on to client if not processed here)
       
   550  */
       
   551 EXPORT_C void CAknMessageQueryDialog::ProcessCommandL(TInt aCommandId)
       
   552     {
       
   553     CAknDialog::ProcessCommandL(aCommandId);    
       
   554     
       
   555     // Respond to softkey event
       
   556     switch (aCommandId)
       
   557         {
       
   558         case EAknSoftkeyView:
       
   559             {
       
   560             if ( iMsgQueryExtension && iMsgQueryExtension->iLinkCount > 0 )
       
   561                 {
       
   562                 if( ExecuteLinkL() )
       
   563                     return;
       
   564                 }
       
   565             }
       
   566             break;
       
   567         case EAknSoftkeyEmpty: // SoftkeyEmpty also comes to this observer, but is ingnored
       
   568         default:
       
   569             break;
       
   570         }   
       
   571     }
       
   572 
       
   573 
       
   574 TInt CAknMessageQueryDialog::CountLinks() const 
       
   575     {
       
   576     if ( iMsgQueryExtension->iLinkCount > 0 ) 
       
   577         {
       
   578         return iMsgQueryExtension->iLinkCount;    
       
   579         }
       
   580     // TInt previouslySearched = 0;
       
   581     TInt index = 0;
       
   582     TInt count = -1;
       
   583     TPtrC clippedTextOut = iMessage->Mid( 0 );
       
   584     TPtrC clippedTextIn = clippedTextOut.Mid( 0 );        
       
   585     while ( index != KErrNotFound )
       
   586         {
       
   587         count++;
       
   588         index = clippedTextOut.Find( KOpeningLinkTag );            
       
   589         clippedTextOut.Set( clippedTextIn.Mid( index+1 ) );
       
   590         clippedTextIn.Set( clippedTextOut.Mid( 0 ) );
       
   591         }    
       
   592     return count;
       
   593     }    
       
   594 
       
   595 TBool CAknMessageQueryDialog::SetNextLinkTextLocationL( const TDesC* aLinkText )
       
   596     {        
       
   597     TInt linkTextLocation = 0;
       
   598     TInt previouslySearched = 0;
       
   599     if ( iMessage && iMessage->Length() > 0 && aLinkText->Length() > 0 )
       
   600         {
       
   601         HBufC* messageBuf = iMessage->AllocL();
       
   602         if ( messageBuf )
       
   603             {
       
   604             TPtrC clippedMessageTextOld = iMessage->Mid( 0 ); // pointer to the descriptor data                
       
   605             TPtrC clippedMessageTextNew = clippedMessageTextOld; 
       
   606             linkTextLocation = clippedMessageTextNew.Find( *aLinkText );          
       
   607             if ( linkTextLocation != KErrNotFound ) 
       
   608                 {            
       
   609                 while ( iMsgQueryExtension->iFormatTextLocationArray.Find( linkTextLocation ) != KErrNotFound )
       
   610                     {
       
   611                     previouslySearched += linkTextLocation+1;
       
   612                     clippedMessageTextNew.Set( clippedMessageTextOld.Mid( linkTextLocation+1 ) );
       
   613                     clippedMessageTextOld.Set( clippedMessageTextNew.Mid( 0 ) );
       
   614                     linkTextLocation = clippedMessageTextNew.Find( *aLinkText );                    
       
   615                     if ( linkTextLocation == KErrNotFound ) 
       
   616                         {
       
   617                         return EFalse;    
       
   618                         }
       
   619                     }
       
   620                 linkTextLocation += previouslySearched;
       
   621                 }
       
   622             else 
       
   623                 {
       
   624                 return EFalse;                    
       
   625                 }
       
   626             }
       
   627         delete messageBuf;
       
   628         }      
       
   629      iMsgQueryExtension->iFormatTextLocationArray.Append( linkTextLocation );         
       
   630      return ETrue;
       
   631     }
       
   632     
       
   633 void CAknMessageQueryDialog::CreateExtensionL()
       
   634     {
       
   635     if ( !iMsgQueryExtension )
       
   636         {
       
   637         iMsgQueryExtension = new ( ELeave ) CAknMessageQueryDialogExtension(this);
       
   638         }
       
   639     }
       
   640     
       
   641 void CAknMessageQueryDialog::ParseMessageTxtL()
       
   642     {
       
   643     if ( iMessage && iMessage->Length() > 0 )
       
   644         {
       
   645         TMsgQueryTag tag;        
       
   646 
       
   647         while (GetNextTagL(tag))
       
   648             {
       
   649             SetMsgFormattingL(tag);
       
   650             }            
       
   651         }
       
   652     }
       
   653     
       
   654 void CAknMessageQueryDialog::SetMsgFormattingL(TMsgQueryTag aTag)
       
   655     {
       
   656     TInt openingTag = KErrNotFound;
       
   657     TInt closingTag = KErrNotFound;
       
   658     TInt startLength = 0;
       
   659     TInt endLength = 0;
       
   660     
       
   661     if (aTag == EMsgQueryLink)
       
   662         {
       
   663         openingTag = iMessage->Find( KOpeningLinkTag );
       
   664         closingTag = iMessage->Find( KClosingLinkTag );
       
   665         startLength = KLinkStartTagLength;
       
   666         endLength = KLinkEndTagLength;                
       
   667         }
       
   668     else if (aTag == EMsgQueryBold)
       
   669         {
       
   670         openingTag = iMessage->Find( KOpeningBoldTag );
       
   671         closingTag = iMessage->Find( KClosingBoldTag );
       
   672         startLength = KBoldStartTagLength;
       
   673         endLength = KBoldEndTagLength;                
       
   674         }
       
   675     else User::Leave(KErrCorrupt);
       
   676                    
       
   677     HBufC* messageBuf = iMessage->AllocL();    
       
   678     TPtr message = messageBuf->Des();
       
   679                 
       
   680     message.Delete( closingTag, endLength );
       
   681     message.Delete( openingTag, startLength );
       
   682 
       
   683     iMsgQueryExtension->iFormatTextArray.Append( message.MidTPtr( openingTag, closingTag - openingTag - startLength ).AllocL() );
       
   684     iMsgQueryExtension->iFormatTextLocationArray.Append( openingTag );
       
   685     iMsgQueryExtension->iFormatTypeArray.Append( aTag );
       
   686     delete iMessage;
       
   687     iMessage = messageBuf;        
       
   688     }    
       
   689                 
       
   690 TBool CAknMessageQueryDialog::GetNextTagL(TMsgQueryTag& aTag)
       
   691     {
       
   692     TInt indexLinkStart = iMessage->Find( KOpeningLinkTag );
       
   693     TInt indexLinkEnd = iMessage->Find( KClosingLinkTag );
       
   694     TInt indexBoldStart = iMessage->Find( KOpeningBoldTag );
       
   695     TInt indexBoldEnd = iMessage->Find( KClosingBoldTag );
       
   696     
       
   697     //no tags found
       
   698     if (indexLinkStart == KErrNotFound && indexLinkEnd == KErrNotFound && indexBoldStart == KErrNotFound && indexBoldEnd == KErrNotFound)
       
   699         {
       
   700         return EFalse;
       
   701         }
       
   702 
       
   703     //start tag found without end tag or vice versa
       
   704     if ((indexLinkStart != KErrNotFound && indexLinkEnd == KErrNotFound) || (indexLinkStart == KErrNotFound && indexLinkEnd!= KErrNotFound))
       
   705         {
       
   706         User::Leave(KErrCorrupt);
       
   707         }
       
   708     if ((indexBoldStart!= KErrNotFound && indexBoldEnd == KErrNotFound) || (indexBoldStart == KErrNotFound && indexBoldEnd!= KErrNotFound))
       
   709         {
       
   710         User::Leave(KErrCorrupt);
       
   711         } 
       
   712         
       
   713     //tags in incorrect order
       
   714     if ( indexLinkStart != KErrNotFound && indexLinkStart > indexLinkEnd)
       
   715         {
       
   716         User::Leave(KErrCorrupt);
       
   717         }
       
   718     if (indexBoldStart != KErrNotFound && indexBoldStart > indexBoldEnd)
       
   719         {
       
   720         User::Leave(KErrCorrupt);
       
   721         }
       
   722 
       
   723     //link tags & no bold tags
       
   724     if (indexBoldStart == KErrNotFound)
       
   725         {
       
   726         aTag = EMsgQueryLink;
       
   727         return ETrue;
       
   728         }
       
   729     //bold tags & no link tags
       
   730     else if (indexLinkStart == KErrNotFound)
       
   731         {
       
   732         aTag = EMsgQueryBold;
       
   733         return ETrue;
       
   734         }
       
   735         
       
   736     //next tag pair is link start & link end
       
   737     if (indexLinkStart < indexBoldStart && indexLinkStart < indexBoldEnd
       
   738             && indexLinkEnd < indexBoldStart && indexLinkEnd < indexBoldEnd)
       
   739         {
       
   740         aTag = EMsgQueryLink;
       
   741         return ETrue;
       
   742         }
       
   743     //next tag pair is bold start & bold end
       
   744     else if (indexBoldStart < indexLinkStart && indexBoldStart < indexLinkEnd
       
   745             && indexBoldEnd < indexLinkStart && indexBoldEnd < indexLinkEnd)
       
   746         {
       
   747         aTag = EMsgQueryBold;
       
   748         return ETrue;
       
   749         }
       
   750     //there are bold & link tags within each other - not permitted
       
   751     else
       
   752         {
       
   753         User::Leave(KErrCorrupt);
       
   754         }
       
   755 
       
   756     //should never get here   
       
   757     return EFalse;
       
   758     }      
       
   759     
       
   760 TBool CAknMessageQueryDialog::TaggedMessageL()       
       
   761     {       
       
   762     if (iMessage->Find(KOpeningLinkTag) != KErrNotFound) return ETrue;
       
   763     if (iMessage->Find(KOpeningBoldTag) != KErrNotFound) return ETrue;    
       
   764     if (iMessage->Find(KClosingLinkTag) != KErrNotFound) return ETrue;    
       
   765     if (iMessage->Find(KClosingBoldTag) != KErrNotFound) return ETrue;
       
   766     
       
   767     return EFalse;
       
   768     }
       
   769     
       
   770     
       
   771 TInt CAknMessageQueryDialog::LinksInArray()       
       
   772     {
       
   773     if (!iMsgQueryExtension) 
       
   774         {
       
   775         return 0;
       
   776         }
       
   777         
       
   778     TInt linkCount = 0;    
       
   779     for ( TInt count = 0; count < iMsgQueryExtension->iFormatTypeArray.Count(); count++ )
       
   780         {
       
   781         if (iMsgQueryExtension->iFormatTypeArray[count] == EMsgQueryLink)
       
   782             {
       
   783             linkCount++;
       
   784             }
       
   785         }
       
   786     return linkCount;
       
   787     }
       
   788     
       
   789     
       
   790 TInt CAknMessageQueryDialog::LastLinkInArray()       
       
   791     {
       
   792     if (!iMsgQueryExtension) 
       
   793         {
       
   794         return -1;
       
   795         }
       
   796         
       
   797     TInt lastLinkIndex = -1;
       
   798     for ( TInt count = iMsgQueryExtension->iFormatTypeArray.Count(); count >= 0; count-- )
       
   799         {
       
   800         if (iMsgQueryExtension->iFormatTypeArray[count] == EMsgQueryLink)
       
   801             {
       
   802             lastLinkIndex = count;
       
   803             break;
       
   804             }
       
   805         }
       
   806     return lastLinkIndex;
       
   807     }                                  
       
   808     
       
   809 EXPORT_C void CAknMessageQueryDialog::HandlePointerEventL( const TPointerEvent& aPointerEvent ) 
       
   810     { 
       
   811     CEikEdwin* edwin = NULL; 
       
   812     CAknMessageQueryControl* msgCtrl = static_cast<CAknMessageQueryControl*>( Control( EAknMessageQueryContentId ) );
       
   813     if( msgCtrl )
       
   814         {
       
   815         edwin = static_cast<CEikEdwin*>( msgCtrl->ComponentControl( 0 ) );
       
   816         }
       
   817     
       
   818     switch (aPointerEvent.iType)
       
   819         {
       
   820         case TPointerEvent::EButton1Down:
       
   821             {
       
   822             if ( edwin && ( edwin->Rect().Contains( aPointerEvent.iPosition ) ) )
       
   823                 iMsgQueryExtension->iIsInEditor = ETrue;
       
   824             }
       
   825             break;
       
   826         case TPointerEvent::EButton1Up:
       
   827             {
       
   828             iMsgQueryExtension->iIsInEditor = EFalse;
       
   829             if (!Rect().Contains( aPointerEvent.iPosition) && msgCtrl)
       
   830                 {
       
   831                 msgCtrl->HandlePointerEventL(aPointerEvent);    
       
   832                 }
       
   833             }
       
   834             break;
       
   835         case TPointerEvent::EDrag:
       
   836         case TPointerEvent::EButtonRepeat:
       
   837               {
       
   838               if ( !Rect().Contains( aPointerEvent.iPosition) && iMsgQueryExtension->iIsInEditor && edwin )
       
   839                   {
       
   840                   edwin->HandlePointerEventL(aPointerEvent);        
       
   841                   return;
       
   842                   }
       
   843               }
       
   844              break;
       
   845           default:
       
   846               break;
       
   847            
       
   848         }
       
   849     // This is a bit of a hack to support non window owning scroll bar.
       
   850     // CAknQueryDialog and CEikDialogPage will stop pointer event processing
       
   851     // if it occurs outside of the dialog area. If scroll bar has received
       
   852     // pointer down, hand pointer up to it regardless where it occurred.
       
   853     if (AknLayoutUtils::PenEnabled() &&
       
   854         aPointerEvent.iType != TPointerEvent::EButton1Down &&
       
   855         msgCtrl && msgCtrl->ScrollBarGrabbing())
       
   856         {
       
   857         msgCtrl->HandlePointerEventL(aPointerEvent);
       
   858         }
       
   859     else
       
   860         {
       
   861         CAknQueryDialog::HandlePointerEventL( aPointerEvent );
       
   862         }
       
   863     }
       
   864 
       
   865 EXPORT_C void* CAknMessageQueryDialog::ExtensionInterface( TUid /*aInterface*/ ) 
       
   866     { 
       
   867     return NULL;
       
   868     }
       
   869 
       
   870 EXPORT_C void CAknMessageQueryDialog::CEikDialog_Reserved_1()
       
   871     {
       
   872     }
       
   873 
       
   874 EXPORT_C void CAknMessageQueryDialog::CEikDialog_Reserved_2()
       
   875     {
       
   876     }
       
   877 
       
   878 EXPORT_C void CAknMessageQueryDialog::CAknDialog_Reserved()
       
   879     {
       
   880     }
       
   881 
       
   882 EXPORT_C void CAknMessageQueryDialog::CAknQueryDialog_Reserved()
       
   883     {
       
   884     }
       
   885 
       
   886 void CAknMessageQueryDialog::CheckLinkTappedL( TAny* aParams )
       
   887     {
       
   888     if ( iMsgQueryExtension->iLinkCount <= 0 )
       
   889         {
       
   890         return; 
       
   891         }
       
   892     CAknExtendedInputCapabilities::MAknEventObserver::TPointerEventReceivedParams aInfo = 
       
   893         *((CAknExtendedInputCapabilities::MAknEventObserver::TPointerEventReceivedParams*)aParams); 
       
   894     CAknMessageQueryControl* messageQueryControl = STATIC_CAST( CAknMessageQueryControl*, Control( EAknMessageQueryContentId ) );
       
   895 
       
   896     if ( messageQueryControl )
       
   897         {
       
   898         TBool linkTapped = messageQueryControl->LinkTappedL( aInfo.iDocPos );
       
   899         
       
   900         if ( linkTapped && 
       
   901             aInfo.iPointerEvent.iType == TPointerEvent::EButton1Down )
       
   902             {
       
   903             MTouchFeedback* feedback = MTouchFeedback::Instance();
       
   904             if ( feedback )
       
   905                 {
       
   906                 feedback->InstantFeedback( this, ETouchFeedbackSensitive );            
       
   907                 }
       
   908             }
       
   909         
       
   910         UpdateSoftkeyLabels();
       
   911         if( linkTapped && aInfo.iPointerEvent.iType == TPointerEvent::EButton1Up )
       
   912             {
       
   913             ExecuteLinkL();
       
   914             }
       
   915         }
       
   916     }
       
   917 
       
   918 void CAknMessageQueryDialog::RegisterPointerEventObserver( TBool aRegister )
       
   919     {
       
   920     if( !iMsgQueryExtension || ( !aRegister && !iMsgQueryExtension->iControlRegisted  ) )
       
   921         {
       
   922         return;
       
   923         }
       
   924         
       
   925     CAknMessageQueryControl* msgCtrl = STATIC_CAST( CAknMessageQueryControl*, Control( EAknMessageQueryContentId ) );
       
   926     CEikEdwin* edwin = (CEikEdwin*)msgCtrl->ComponentControl( 0 ); 
       
   927         
       
   928     MObjectProvider* mop = edwin->InputCapabilities().ObjectProvider();
       
   929     
       
   930     if ( mop )
       
   931         {
       
   932         CAknExtendedInputCapabilities* extendedInputCapabilities = 
       
   933         mop->MopGetObject( extendedInputCapabilities );
       
   934 
       
   935         if ( extendedInputCapabilities ) 
       
   936             {
       
   937             if ( aRegister )
       
   938                 {
       
   939                 iMsgQueryExtension->iControlRegisted = ETrue;
       
   940                 extendedInputCapabilities->RegisterObserver( iMsgQueryExtension );
       
   941                 }
       
   942             else 
       
   943                 {
       
   944                 extendedInputCapabilities->UnregisterObserver( iMsgQueryExtension );                
       
   945                 }
       
   946             }
       
   947         }
       
   948     }
       
   949     
       
   950 void CAknMessageQueryDialog::UpdateSoftkeyLabels()
       
   951     {
       
   952     CAknMessageQueryControl* control = STATIC_CAST( CAknMessageQueryControl*, Control( EAknMessageQueryContentId ) );
       
   953 
       
   954     if ( control && control->LinkHighLighted() )
       
   955         {
       
   956         if ( !iMsgQueryExtension->iButtonGroupPreviouslyChanged ) 
       
   957             {   
       
   958             TRAP_IGNORE( ButtonGroupContainer().AddCommandSetToStackL( R_AVKON_SOFTKEYS_VIEW_EMPTY ) );
       
   959             TRAP_IGNORE( ButtonGroupContainer().UpdateCommandObserverL( CEikButtonGroupContainer::ELeftSoftkeyPosition, *this ) );
       
   960             TRAP_IGNORE( ButtonGroupContainer().UpdateCommandObserverL( CEikButtonGroupContainer::ERightSoftkeyPosition, *this ) );
       
   961             TRAP_IGNORE( ButtonGroupContainer().UpdateCommandObserverL( CEikButtonGroupContainer::EMiddleSoftkeyPosition, *this ) );
       
   962             ButtonGroupContainer().DrawNow();
       
   963             iMsgQueryExtension->iButtonGroupPreviouslyChanged = ETrue;
       
   964             }
       
   965          }
       
   966     else
       
   967         {
       
   968         if ( iMsgQueryExtension->iButtonGroupPreviouslyChanged ) 
       
   969             {                            
       
   970             ButtonGroupContainer().RemoveCommandObserver( CEikButtonGroupContainer::ELeftSoftkeyPosition );
       
   971             ButtonGroupContainer().RemoveCommandObserver( CEikButtonGroupContainer::ERightSoftkeyPosition );
       
   972             ButtonGroupContainer().RemoveCommandObserver( CEikButtonGroupContainer::EMiddleSoftkeyPosition );
       
   973             ButtonGroupContainer().RemoveCommandFromStack( CEikButtonGroupContainer::ELeftSoftkeyPosition, EAknSoftkeyView );
       
   974             ButtonGroupContainer().RemoveCommandFromStack( CEikButtonGroupContainer::ERightSoftkeyPosition, EAknSoftkeyEmpty );
       
   975             ButtonGroupContainer().RemoveCommandFromStack( CEikButtonGroupContainer::EMiddleSoftkeyPosition, EAknSoftkeyView );
       
   976             ButtonGroupContainer().DrawNow();
       
   977             iMsgQueryExtension->iButtonGroupPreviouslyChanged = EFalse; 
       
   978             }
       
   979         }
       
   980     }
       
   981     
       
   982 /**
       
   983 * CAknMessageQueryDialog::ExecuteLinkL() checks for the object destruction after
       
   984 * the link execution.
       
   985 */    
       
   986     
       
   987 TBool CAknMessageQueryDialog::ExecuteLinkL()
       
   988     {
       
   989     CAknMessageQueryControl* control = STATIC_CAST( CAknMessageQueryControl*, Control( EAknMessageQueryContentId ) );
       
   990     if( !control )
       
   991         {
       
   992         return EFalse;
       
   993         }
       
   994     if( !control->LinkHighLighted() )
       
   995         {
       
   996         return EFalse;
       
   997         }
       
   998     TInt curLink = control->CurrentLink();
       
   999     /**
       
  1000     * The local @c destroyed variable keeps track of the object destroyed state.
       
  1001     */
       
  1002     TBool destroyed = EFalse;
       
  1003     iMsgQueryExtension->iDestroyedPtr = &destroyed;
       
  1004     TRAPD( err, iMsgQueryExtension->iCallBackArray[curLink].CallBack() );
       
  1005     if ( !destroyed )
       
  1006         {
       
  1007         iMsgQueryExtension->iDestroyedPtr = NULL;
       
  1008         }
       
  1009     User::LeaveIfError( err );
       
  1010     if ( !destroyed )
       
  1011         {
       
  1012         control->DehighlightLink();
       
  1013         }
       
  1014     return ETrue;
       
  1015     }
       
  1016 
       
  1017 //  End of File