messagingappbase/msgeditor/viewsrc/MsgEditorView.cpp
changeset 79 2981cb3aa489
equal deleted inserted replaced
25:84d9eb65b26f 79:2981cb3aa489
       
     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:   MsgEditorView implementation*
       
    15 */
       
    16 
       
    17 
       
    18 
       
    19 // ========== INCLUDE FILES ================================
       
    20 
       
    21 #include <eikenv.h>                        // for CEikonEnv
       
    22 #include <eikappui.h>                      // for CEikAppUi
       
    23 #include <barsread.h>                      // for TResourceReader
       
    24 #include <eikrted.h>                       // for CEikRichTextEditor
       
    25 #include <eikscrlb.h>
       
    26 #include <AknUtils.h>                      // for AknUtils
       
    27 #include <txtrich.h>                       // for automatic highlight
       
    28 #include <aknappui.h>
       
    29 #include <applayout.cdl.h>                  // LAF
       
    30 #include <aknlayoutscalable_apps.cdl.h>
       
    31 
       
    32 #include <bautils.h>                        // NearestLanguageFile
       
    33 #include <data_caging_path_literals.hrh>
       
    34 
       
    35 #include <aknnavi.h>
       
    36 #include <aknnavide.h>
       
    37 #include <AknStatuspaneUtils.h>
       
    38 
       
    39 #include <AknsBasicBackgroundControlContext.h>  // for skins support    
       
    40 #include <AknsDrawUtils.h>
       
    41 
       
    42 #include <MsgEditorAppUi.rsg>
       
    43 #include <StringLoader.h>
       
    44 #include <AknPriv.hrh>
       
    45 #include "MsgEditorCommon.h"               //
       
    46 #include "MsgEditorView.h"                 // for CMsgEditorView
       
    47 #include "MsgEditorObserver.h"             // for MMsgEditorObserver
       
    48 #include "MsgHeader.h"                     // for CMsgHeader
       
    49 #include "MsgBody.h"                       // for CMsgBody
       
    50 #include "MsgExpandableControl.h"          // for MsgExpandableControl
       
    51 #include "MsgBodyControl.h"                // for MsgBodyControl
       
    52 #include "MsgAddressControl.h"             // for MsgAddressControl
       
    53 #include "MsgAttachmentControl.h"          // for MsgAttachmentControl
       
    54 #include "MsgAddressControlEditor.h"       // for MsgAddressControlEditor
       
    55 #include "MsgEditorPanic.h"                // for MsgEditor panics
       
    56 #include "MsgEditorLogging.h"
       
    57 
       
    58 // ========== EXTERNAL DATA STRUCTURES =====================
       
    59 
       
    60 // ========== EXTERNAL FUNCTION PROTOTYPES =================
       
    61 
       
    62 // ========== CONSTANTS ====================================
       
    63 
       
    64 // ========== MACROS =======================================
       
    65 
       
    66 // ========== LOCAL CONSTANTS AND MACROS ===================
       
    67 
       
    68 const TInt KMsgControlIndexHeader = 0;
       
    69 const TInt KMsgControlIndexBody = 1;
       
    70 const TInt KMsgNumberOfControls = 2;
       
    71 
       
    72 const TInt KMsgMaximumScrollPartLength = 64;
       
    73 const TInt KSelectionOffset = 50;
       
    74 _LIT( KMsgEditorAppUiResourceFileName, "msgeditorappui.rsc" );
       
    75 
       
    76 // ========== MODULE DATA STRUCTURES =======================
       
    77 
       
    78 // ========== LOCAL FUNCTION PROTOTYPES ====================
       
    79 
       
    80 // ========== LOCAL FUNCTIONS ==============================
       
    81 
       
    82 // ========== MEMBER FUNCTIONS =============================
       
    83 
       
    84 // ---------------------------------------------------------
       
    85 // CMsgEditorView::CMsgEditorView
       
    86 //
       
    87 // Constructor.
       
    88 // ---------------------------------------------------------
       
    89 //
       
    90 CMsgEditorView::CMsgEditorView( MMsgEditorObserver& aObserver,
       
    91                                 TUint32 aEditorModeFlags ): 
       
    92     iEditorObserver( aObserver ),
       
    93     iCurrentFocus( EMsgNoneFocused ),
       
    94     iEditorModeFlags( aEditorModeFlags ),
       
    95     iLineHeight( MsgEditorCommons::MsgBaseLineDelta() ),
       
    96     iBaseLineOffset( MsgEditorCommons::MsgBaseLineOffset() ),
       
    97     iResourceLoader( *iCoeEnv ),
       
    98     iPrevFocus( EMsgNoneFocused ), 
       
    99     iMoveUpDownEvent( EFalse) 
       
   100     {
       
   101     }
       
   102 
       
   103 // ---------------------------------------------------------
       
   104 // CMsgEditorView::ConstructL
       
   105 //
       
   106 // Constructs the editor view by creating the window, the header and the body.
       
   107 // ---------------------------------------------------------
       
   108 //
       
   109 void CMsgEditorView::ConstructL()
       
   110     { 
       
   111     CreateWindowL();
       
   112     
       
   113     if ( AknStatuspaneUtils::FlatLayoutActive() )
       
   114         {
       
   115         CEikStatusPane* statusPane = iEikonEnv->AppUiFactory()->StatusPane();
       
   116         if ( statusPane )
       
   117             {
       
   118             CAknNavigationControlContainer* naviPane = 
       
   119                 static_cast<CAknNavigationControlContainer*>( statusPane->ControlL( 
       
   120                                                               TUid::Uid( EEikStatusPaneUidNavi ) ) );
       
   121             
       
   122             if ( naviPane )
       
   123                 {
       
   124                 naviPane->SetPreferredNaviDecoratorLayoutStyle( 
       
   125                                 CAknNavigationDecorator::ENaviControlLayoutNormal );
       
   126                 }
       
   127             }
       
   128         }
       
   129     
       
   130     iBgContext = CAknsBasicBackgroundControlContext::NewL( KAknsIIDQsnBgAreaMainMessage, 
       
   131                                                            Rect(), 
       
   132                                                            EFalse );
       
   133 
       
   134     // T9: Add control to stack to make FEP work. View does not accept key
       
   135     //     events from CT9FepControl::HandleChangeInFocus(). Key events are
       
   136     //     handled first by editor app ui which routes them to view.
       
   137     iEikonEnv->EikAppUi()->AddToStackL( this, 
       
   138                                         ECoeStackPriorityDefault, 
       
   139                                         ECoeStackFlagRefusesAllKeys );
       
   140 
       
   141     Window().SetShadowDisabled( ETrue );
       
   142     
       
   143     // Disables automatic background color drawing
       
   144     // on window server.
       
   145     Window().SetBackgroundColor();    
       
   146     
       
   147     CreateScrollBarL();
       
   148     CreateHeaderL();
       
   149     CreateBodyL();
       
   150     }
       
   151 
       
   152 // ---------------------------------------------------------
       
   153 // CMsgEditorView::~CMsgEditorView
       
   154 //
       
   155 // Destructor.
       
   156 // ---------------------------------------------------------
       
   157 //
       
   158 EXPORT_C CMsgEditorView::~CMsgEditorView()
       
   159     {
       
   160     iEikonEnv->EikAppUi()->RemoveFromStack( this );
       
   161 
       
   162     delete iHeader;
       
   163     delete iBody;
       
   164     delete iScrollBar;
       
   165     delete iBgContext;
       
   166     
       
   167     iResourceLoader.Close();
       
   168            
       
   169     delete iScrollPopText;
       
   170     }
       
   171 
       
   172 // ---------------------------------------------------------
       
   173 // CMsgEditorView::NewL
       
   174 //
       
   175 // Factory method.
       
   176 // ---------------------------------------------------------
       
   177 //
       
   178 EXPORT_C CMsgEditorView* CMsgEditorView::NewL( MMsgEditorObserver& aObserver,
       
   179                                                TUint32 aEditorModeFlags )
       
   180     {
       
   181     CMsgEditorView* self = new( ELeave ) CMsgEditorView( aObserver, aEditorModeFlags );
       
   182     
       
   183     CleanupStack::PushL( self );
       
   184     self->ConstructL();
       
   185     CleanupStack::Pop( self );
       
   186     
       
   187     return self;
       
   188     }
       
   189 
       
   190 // ---------------------------------------------------------
       
   191 // CMsgEditorView::MopNext
       
   192 //
       
   193 // From MObjectProvider.
       
   194 // ---------------------------------------------------------
       
   195 //
       
   196 EXPORT_C MObjectProvider* CMsgEditorView::MopNext()
       
   197     {
       
   198     return iEikonEnv->EikAppUi();
       
   199     }
       
   200 
       
   201 // ---------------------------------------------------------
       
   202 // CMsgEditorView::ExecuteL
       
   203 //
       
   204 // Prepares the editor view for showing it on the screen.
       
   205 // ---------------------------------------------------------
       
   206 //
       
   207 EXPORT_C void CMsgEditorView::ExecuteL( const TRect& aRect,
       
   208                                         TInt aControlIdForFocus )
       
   209     {
       
   210     TRect rect( aRect );
       
   211     rect.iBr.iY = rect.iTl.iY + MsgEditorCommons::EditorViewHeigth();
       
   212 
       
   213     AdjustComponentDistances();
       
   214 
       
   215     SetViewRect( rect );
       
   216     iSize = rect.Size();
       
   217     
       
   218     // Set initial size for controls.
       
   219     TSize editorSize( rect.Size() );
       
   220     SetAndGetSizeL( editorSize, ETrue ); 
       
   221     
       
   222     // Enable here so that size affecting events are processed 
       
   223     // from header & body controls after this point.
       
   224     iStateFlags |= EMsgStateInitializing;
       
   225     
       
   226     SizeChanged();
       
   227     ActivateL();
       
   228     
       
   229     iScrollParts = 1;
       
   230 
       
   231     iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgScrollParts,
       
   232                                     &iScrollParts,
       
   233                                     NULL,
       
   234                                     NULL );
       
   235     
       
   236     if ( aControlIdForFocus != EMsgComponentIdNull )
       
   237         {
       
   238         SetFocusByControlIdL( aControlIdForFocus );
       
   239         }
       
   240 
       
   241     if ( aControlIdForFocus == EMsgComponentIdNull ||
       
   242          iCurrentFocus == EMsgNoneFocused )
       
   243         {
       
   244         iCurrentFocus = EMsgHeaderFocused;
       
   245         
       
   246         TInt newFocus = iHeader->FirstFocusableControl( 0, EMsgFocusDown );
       
   247         if ( newFocus == KErrNotFound )
       
   248             {
       
   249             iPrevFocus = EMsgHeaderFocused; 
       
   250             iCurrentFocus = EMsgBodyFocused;
       
   251             newFocus = iBody->FirstFocusableControl( 0, EMsgFocusDown );
       
   252             
       
   253             if ( newFocus == KErrNotFound )
       
   254                 {
       
   255 				iPrevFocus = EMsgNoneFocused;
       
   256                 iCurrentFocus = EMsgNoneFocused;
       
   257                 }
       
   258             else
       
   259                 {
       
   260                 iBody->ChangeFocusTo( newFocus, ENoDrawNow );
       
   261                 }
       
   262             }
       
   263         else
       
   264             {
       
   265             iHeader->ChangeFocusTo( newFocus, ENoDrawNow );
       
   266             }
       
   267         }
       
   268 
       
   269     UpdateScrollBarL();
       
   270 
       
   271     SetComponentsInitialized();
       
   272     
       
   273     iStateFlags &= ~EMsgStateInitializing;
       
   274     iStateFlags |= EMsgStateInitialized;
       
   275     
       
   276     // Has to be called after EMsgStateInitialized flag is set on since
       
   277     // otherwise control that have suppress text formatting are not 
       
   278     // resized correctly.
       
   279     NotifyControlsForEvent( EMsgViewEventPrepareForViewing, 0 );
       
   280     
       
   281     DrawNow();
       
   282     iCoeEnv->WsSession().Flush();
       
   283     }
       
   284 
       
   285 // ---------------------------------------------------------
       
   286 // CMsgEditorView::ControlById
       
   287 //
       
   288 // Finds a control from the header and the body by id and returns a pointer to it.
       
   289 // ---------------------------------------------------------
       
   290 //
       
   291 EXPORT_C CMsgBaseControl* CMsgEditorView::ControlById( TInt aControlId ) const
       
   292     {
       
   293     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
   294     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
   295 
       
   296     CMsgBaseControl* component = iHeader->Component( aControlId );
       
   297 
       
   298     if ( !component )
       
   299         {
       
   300         component = iBody->Component( aControlId );
       
   301         }
       
   302 
       
   303     return component;
       
   304     }
       
   305 
       
   306 // ---------------------------------------------------------
       
   307 // CMsgEditorView::FocusedControl
       
   308 //
       
   309 // Returns a pointer to a focused control. If no control is focused, returns NULL.
       
   310 // ---------------------------------------------------------
       
   311 //
       
   312 EXPORT_C CMsgBaseControl* CMsgEditorView::FocusedControl() const
       
   313     {
       
   314     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
   315     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
   316 
       
   317     if ( iCurrentFocus == EMsgHeaderFocused )
       
   318         {
       
   319         return iHeader->FocusedControl();
       
   320         }
       
   321     else if ( iCurrentFocus == EMsgBodyFocused )
       
   322         {
       
   323         return iBody->FocusedControl();
       
   324         }
       
   325     else
       
   326         {
       
   327         return NULL;
       
   328         }
       
   329     }
       
   330 
       
   331 // ---------------------------------------------------------
       
   332 // CMsgEditorView::SetFocus
       
   333 //
       
   334 // Sets focus to a control aControlId.
       
   335 // ---------------------------------------------------------
       
   336 //
       
   337 EXPORT_C void CMsgEditorView::SetFocus( TInt aControlId )
       
   338     {
       
   339     __ASSERT_DEBUG( iStateFlags & EMsgStateInitialized,
       
   340                     Panic( EMsgFunctionCalledBeforeInitialization ) );
       
   341 
       
   342     TRAP_IGNORE( 
       
   343         {
       
   344         SetFocusByControlIdL( aControlId );
       
   345         UpdateScrollBarL();
       
   346         } );
       
   347     }
       
   348 
       
   349 // ---------------------------------------------------------
       
   350 // CMsgEditorView::AddControlFromResourceL
       
   351 //
       
   352 // Constructs a control of type aControlType from resource and adds it to
       
   353 // a form component aFormComponent. The control is added to a position aIndex.
       
   354 //
       
   355 // Leaves with KErrNotFound if aControlType is incorrect.
       
   356 // ---------------------------------------------------------
       
   357 //
       
   358 EXPORT_C TInt CMsgEditorView::AddControlFromResourceL( TInt aResourceId,
       
   359                                                        TInt aControlType,
       
   360                                                        TInt aIndex,
       
   361                                                        TMsgFormComponent aFormComponent )
       
   362     {
       
   363     CMsgBaseControl* control = NULL;
       
   364 
       
   365     switch (aControlType)
       
   366         {
       
   367         case EMsgExpandableControl:
       
   368             {
       
   369             control = new ( ELeave ) CMsgExpandableControl( *this );
       
   370             break;
       
   371             }
       
   372         case EMsgAddressControl:
       
   373             {
       
   374             control = new ( ELeave ) CMsgAddressControl( *this );
       
   375             break;
       
   376             }
       
   377         case EMsgAttachmentControl:
       
   378             {
       
   379             control = new ( ELeave ) CMsgAttachmentControl( *this, *this );
       
   380             break;
       
   381             }
       
   382         default:
       
   383             {
       
   384             control = iEditorObserver.CreateCustomControlL( aControlType );
       
   385             if ( control == NULL )
       
   386                 {
       
   387                 User::Leave( KErrNotSupported );
       
   388                 }
       
   389             break;
       
   390             }
       
   391         }
       
   392 
       
   393     CleanupStack::PushL( control );
       
   394     control->SetControlType( aControlType );
       
   395     control->SetMopParent( this );
       
   396 
       
   397     control->ConstructFromResourceL( aResourceId );
       
   398 
       
   399     TInt controlId = control->ControlId();
       
   400     DoAddControlL( control, controlId, aIndex, aFormComponent );
       
   401     CleanupStack::Pop();  //control
       
   402 
       
   403     return controlId;
       
   404     }
       
   405 
       
   406 // ---------------------------------------------------------
       
   407 // CMsgEditorView::AddControlL
       
   408 //
       
   409 // Adds a control given by aControl to a form component aFormComponent.
       
   410 // The control is added to a position aIndex with control id aControlId.
       
   411 // ---------------------------------------------------------
       
   412 //
       
   413 EXPORT_C void CMsgEditorView::AddControlL( CMsgBaseControl* aControl,
       
   414                                            TInt aControlId,
       
   415                                            TInt aIndex,
       
   416                                            TMsgFormComponent aFormComponent )
       
   417     {
       
   418     DoAddControlL( aControl, aControlId, aIndex, aFormComponent );
       
   419     }
       
   420 
       
   421 // ---------------------------------------------------------
       
   422 // CMsgEditorView::RemoveControlL
       
   423 //
       
   424 // Removes the control aControlId from the header or the body and returns pointer
       
   425 // to it. If a control cannot be found, returns NULL.
       
   426 // ---------------------------------------------------------
       
   427 //
       
   428 EXPORT_C CMsgBaseControl* CMsgEditorView::RemoveControlL( TInt aControlId )
       
   429     {
       
   430     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
   431     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
   432 
       
   433     if ( iStateFlags & EMsgStateInitialized ) // Control is removed on run-time.
       
   434         {
       
   435         if ( FocusedControl() == ControlById( aControlId ) &&
       
   436              iHeader->CountMsgControls() + iBody->CountMsgControls() > 1 )
       
   437             {
       
   438             // Try to move focus to different control as focused control is removed and
       
   439             // there is more than one control loaded.
       
   440             MMsgEditorObserver::TMsgFocusEvent focusEvent = MMsgEditorObserver::EMsgFocusNone;
       
   441 
       
   442             if ( !RotateFocusL( EMsgFocusUp, focusEvent ) )
       
   443                 {
       
   444                 if ( !RotateFocusL( EMsgFocusDown, focusEvent ) )
       
   445                     {
       
   446                     //__ASSERT_DEBUG(EFalse, Panic(EMsgFocusLost));
       
   447                     // There are no focusing component left. Remove the focus from current control.
       
   448                     FocusedControl()->SetFocus( EFalse );
       
   449                     }
       
   450                 }
       
   451             
       
   452             iCoeEnv->SyncNotifyFocusObserversOfChangeInFocus();
       
   453             }
       
   454         }
       
   455 
       
   456     // Remove a component from the header.
       
   457     CMsgBaseControl* control = iHeader->RemoveControlL( aControlId );
       
   458 
       
   459     if ( control == NULL )
       
   460         {
       
   461         // If a component could not be found in the header, remove it from the body.
       
   462         control = iBody->RemoveControlL( aControlId );
       
   463         }
       
   464 
       
   465     if ( iStateFlags & EMsgStateInitialized ) // Control is removed on run-time.
       
   466         {
       
   467         if ( control != NULL )
       
   468             {
       
   469             CleanupStack::PushL( control );
       
   470             RefreshViewL();
       
   471             EnsureCorrectViewPosition();
       
   472             CleanupStack::Pop();  // control
       
   473             }
       
   474         }
       
   475     else if ( iHeader->CountMsgControls() == 0 )
       
   476         {
       
   477         iFormOffset = 0;
       
   478         }
       
   479     
       
   480     if ( control )
       
   481         {
       
   482         // This is needed atleast for japanese pictographs to not
       
   483         // draw into current control area.
       
   484         control->MakeVisible( EFalse );
       
   485         }
       
   486     
       
   487     return control;
       
   488     }
       
   489 
       
   490 // ---------------------------------------------------------
       
   491 // CMsgEditorView::DeleteControlL
       
   492 //
       
   493 // Removes the control aControlId from the header or the body and returns pointer
       
   494 // to it. If a control cannot be found, returns NULL.
       
   495 // ---------------------------------------------------------
       
   496 //
       
   497 EXPORT_C void CMsgEditorView::DeleteControlL( TInt aControlId )
       
   498     {
       
   499     CMsgBaseControl* baseControl = RemoveControlL( aControlId );
       
   500     delete baseControl;
       
   501     }
       
   502 
       
   503 // ---------------------------------------------------------
       
   504 // CMsgEditorView::FormComponent
       
   505 //
       
   506 // Returns a reference to a form component.
       
   507 // ---------------------------------------------------------
       
   508 //
       
   509 EXPORT_C CCoeControl& CMsgEditorView::FormComponent( TMsgFormComponent aFormComponent ) const
       
   510     {
       
   511     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
   512     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
   513 
       
   514     switch ( aFormComponent )
       
   515         {
       
   516         case EMsgHeader:
       
   517             {
       
   518             return *iHeader;
       
   519             }
       
   520         case EMsgBody:
       
   521             {
       
   522             return *iBody;
       
   523             }
       
   524         default:
       
   525             {
       
   526             __ASSERT_DEBUG( EFalse, Panic( EMsgIncorrectFormComponent ) );
       
   527             // Just to make compiler happy.
       
   528             return *iBody;
       
   529             }
       
   530         }
       
   531     }
       
   532 
       
   533 // ---------------------------------------------------------
       
   534 // CMsgEditorView::HandleScreenSizeChangeL
       
   535 //
       
   536 // Prepares the editor view for viewing it on the screen after screen size change.
       
   537 // ---------------------------------------------------------
       
   538 //
       
   539 EXPORT_C void CMsgEditorView::HandleScreenSizeChangeL( const TRect& aRect )
       
   540     {
       
   541     __ASSERT_DEBUG( iStateFlags & EMsgStateInitialized,
       
   542         Panic( EMsgFunctionCalledBeforeInitialization ) );
       
   543 
       
   544     SetViewRect( aRect );
       
   545     RefreshViewL();
       
   546     }
       
   547 
       
   548 
       
   549 // ---------------------------------------------------------
       
   550 // CMsgEditorView::ResetControls
       
   551 //
       
   552 // Reset all controls.
       
   553 // ---------------------------------------------------------
       
   554 //
       
   555 EXPORT_C void CMsgEditorView::ResetControls()
       
   556     {
       
   557     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
   558     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
   559 
       
   560     iHeader->ResetControls();
       
   561     iBody->ResetControls();
       
   562     }
       
   563 
       
   564 // ---------------------------------------------------------
       
   565 // CMsgEditorView::ResetControls
       
   566 //
       
   567 // Reset controls from header or body.
       
   568 // ---------------------------------------------------------
       
   569 //
       
   570 EXPORT_C void CMsgEditorView::ResetControls( TMsgFormComponent aFormComponent )
       
   571     {
       
   572     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
   573     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
   574 
       
   575     switch ( aFormComponent )
       
   576         {
       
   577         case EMsgHeader:
       
   578             {
       
   579             iHeader->ResetControls();
       
   580             break;
       
   581             }
       
   582         case EMsgBody:
       
   583             {
       
   584             iBody->ResetControls();
       
   585             break;
       
   586             }
       
   587         default:
       
   588             {
       
   589             __ASSERT_DEBUG( EFalse, Panic( EMsgIncorrectFormComponent ) );
       
   590             }
       
   591         }
       
   592     }
       
   593 
       
   594 // ---------------------------------------------------------
       
   595 // CMsgEditorView::IsAnyControlModified
       
   596 //
       
   597 // Checks if any control owned by view is modified.
       
   598 // ---------------------------------------------------------
       
   599 //
       
   600 EXPORT_C TBool CMsgEditorView::IsAnyControlModified() const
       
   601     {
       
   602     TInt i;
       
   603     CMsgBaseControl* ctrl;
       
   604     TInt countHeader = iHeader->CountMsgControls();
       
   605     TInt countBody = iBody->CountMsgControls();
       
   606 
       
   607     for ( i = 0; i < countHeader; i++ )
       
   608         {
       
   609         ctrl = iHeader->MsgControl( i );
       
   610         if ( ctrl && ctrl->IsModified() )
       
   611             {
       
   612             return ETrue;
       
   613             }
       
   614         }
       
   615 
       
   616     for ( i = 0; i < countBody; i++ )
       
   617         {
       
   618         ctrl = iBody->MsgControl( i );
       
   619         if ( ctrl && ctrl->IsModified() )
       
   620             {
       
   621             return ETrue;
       
   622             }
       
   623         }
       
   624 
       
   625     return EFalse;
       
   626     }
       
   627 
       
   628 // ---------------------------------------------------------
       
   629 // CMsgEditorView::SetControlsModified
       
   630 //
       
   631 // Updates modified flag of controls owned by view.
       
   632 // ---------------------------------------------------------
       
   633 //
       
   634 EXPORT_C void CMsgEditorView::SetControlsModified( TBool aFlag )
       
   635     {
       
   636     TInt i;
       
   637     CMsgBaseControl* ctrl;
       
   638     TInt countHeader = iHeader->CountMsgControls();
       
   639     TInt countBody = iBody->CountMsgControls();
       
   640 
       
   641     for ( i = 0; i < countHeader; i++ )
       
   642         {
       
   643         ctrl = iHeader->MsgControl( i );
       
   644         if ( ctrl )
       
   645             {
       
   646             ctrl->SetModified( aFlag );
       
   647             }
       
   648         }
       
   649 
       
   650     for ( i = 0; i < countBody; i++ )
       
   651         {
       
   652         ctrl = iBody->MsgControl( i );
       
   653         if ( ctrl )
       
   654             {
       
   655             ctrl->SetModified( aFlag );
       
   656             }
       
   657         }
       
   658     }
       
   659 
       
   660 // ---------------------------------------------------------
       
   661 // CMsgEditorView::OfferKeyEventL
       
   662 //
       
   663 // Handles key events.
       
   664 // ---------------------------------------------------------
       
   665 //
       
   666 EXPORT_C TKeyResponse CMsgEditorView::OfferKeyEventL( const TKeyEvent& aKeyEvent,
       
   667                                                       TEventCode aType )
       
   668     {
       
   669     CMsgBaseControl* ctrl = FocusedControl();
       
   670 
       
   671     // Is this needed?
       
   672     if ( ctrl && ctrl->ControlType() == EMsgAddressControl && aType == EEventKeyUp )
       
   673         {
       
   674         return ctrl->OfferKeyEventL( aKeyEvent, aType );
       
   675         }    
       
   676     
       
   677     if ( ( !( iStateFlags & EMsgStateInitialized ) ) || ( aType != EEventKey ) )
       
   678         {
       
   679         return EKeyWasNotConsumed;
       
   680         }
       
   681 
       
   682     TKeyResponse keyResp( EKeyWasNotConsumed );
       
   683     TBool focusRotated = EFalse;
       
   684     TBool forceScrollUp = EFalse;
       
   685     MMsgEditorObserver::TMsgFocusEvent focusEvent = MMsgEditorObserver::EMsgFocusNone;
       
   686 
       
   687     switch ( aKeyEvent.iCode )
       
   688         {
       
   689         case EKeyUpArrow:
       
   690             {
       
   691             if ( ctrl )
       
   692                 {
       
   693                 // No focus change allowed if selection is ongoing.
       
   694                 if ( !( aKeyEvent.iModifiers & EModifierShift ) &&
       
   695                      ctrl->IsFocusChangePossible( EMsgFocusUp ) )
       
   696                     {
       
   697                     if ( RotateFocusL( EMsgFocusUp, focusEvent ) )
       
   698                         {
       
   699                         focusRotated = ETrue;
       
   700                         keyResp = EKeyWasConsumed; // focus changed.
       
   701                         }
       
   702                     else
       
   703                         {
       
   704                         // the cursor is in the topmost control.
       
   705                         TInt delta = -iFormOffset;
       
   706                         ScrollForm( delta, ETrue );
       
   707                         
       
   708                         keyResp = EKeyWasNotConsumed;
       
   709                         }
       
   710                     }
       
   711                 }
       
   712             else
       
   713                 {
       
   714                 // no focused control: set focus event if many parts.
       
   715                 if ( iScrollParts > 1 )
       
   716                     {
       
   717                     focusEvent = MMsgEditorObserver::EMsgFocusAtTop;
       
   718                     }
       
   719                 }
       
   720             break;
       
   721             }
       
   722         case EKeyDownArrow:
       
   723             {
       
   724             if ( ctrl )
       
   725                 {
       
   726                 // No focus change allowed if selection is ongoing.
       
   727                 if ( !( aKeyEvent.iModifiers & EModifierShift ) &&
       
   728                      ctrl->IsFocusChangePossible( EMsgFocusDown ) )
       
   729                     {
       
   730                     if ( RotateFocusL( EMsgFocusDown, focusEvent ) )
       
   731                         {
       
   732                         focusRotated = ETrue;
       
   733                         keyResp = EKeyWasConsumed;
       
   734                         }
       
   735                     else
       
   736                         {
       
   737                         keyResp = EKeyWasNotConsumed;
       
   738                         }
       
   739                     }
       
   740                 }
       
   741             else
       
   742                 {
       
   743                 // no focused control: set focus event if many parts.
       
   744                 if ( iScrollParts > 1 )
       
   745                     {
       
   746                     focusEvent = MMsgEditorObserver::EMsgFocusAtBottom;
       
   747                     }
       
   748                 }
       
   749             break;
       
   750             }
       
   751         default:
       
   752             {
       
   753             break;
       
   754             }
       
   755         }
       
   756 
       
   757     if ( ctrl && keyResp == EKeyWasNotConsumed )
       
   758         {
       
   759         keyResp = ctrl->OfferKeyEventL( aKeyEvent, aType );
       
   760         }
       
   761 
       
   762     if ( focusEvent != MMsgEditorObserver::EMsgFocusNone )
       
   763         {
       
   764         MMsgEditorObserver::TMsgAfterFocusEventFunc after =
       
   765             MMsgEditorObserver::EMsgAfterFocusNone;
       
   766 
       
   767 #ifdef RD_SCALABLE_UI_V2
       
   768         if ( focusEvent == MMsgEditorObserver::EMsgFocusAtTop )
       
   769             {
       
   770             iVisiblePart--;
       
   771             }
       
   772         else if ( focusEvent == MMsgEditorObserver::EMsgFocusAtBottom )
       
   773             {
       
   774             iVisiblePart++;
       
   775             }
       
   776         
       
   777         iVisiblePart = Max( 0, Min( iScrollParts - 1, iVisiblePart ) );
       
   778 #endif
       
   779         iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgHandleFocusChange,
       
   780                                         &focusEvent,
       
   781                                         &after,
       
   782                                         &iVisiblePart );
       
   783         
       
   784         if ( after != MMsgEditorObserver::EMsgAfterFocusNone )
       
   785             {
       
   786             forceScrollUp = SetAfterFocusL( after );
       
   787             }
       
   788         }
       
   789     
       
   790     iMoveUpDownEvent = ETrue; 
       
   791     EnsureCorrectFormPosition( ( aKeyEvent.iCode == EKeyDownArrow ) && focusRotated, forceScrollUp );
       
   792     iMoveUpDownEvent = EFalse; 
       
   793 
       
   794     UpdateScrollBarL();
       
   795 
       
   796     return keyResp;
       
   797     }
       
   798 
       
   799 // ---------------------------------------------------------
       
   800 // CMsgEditorView::HandlePointerEventL
       
   801 //
       
   802 // Handles pointer event processing and propagation.
       
   803 // ---------------------------------------------------------
       
   804 //
       
   805 #ifdef RD_SCALABLE_UI_V2
       
   806 void CMsgEditorView::HandlePointerEventL( const TPointerEvent& aPointerEvent )
       
   807     {
       
   808     if ( AknLayoutUtils::PenEnabled() )
       
   809         {
       
   810         TBool handled( EFalse );
       
   811 
       
   812         if( IsReadOnly() )
       
   813             {
       
   814             handled = HandleScrollEventL(aPointerEvent);
       
   815             }
       
   816 
       
   817         if ( !handled && IsFocused() )
       
   818             {
       
   819             TPointerEvent pointerEvent( aPointerEvent );
       
   820                          
       
   821             iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgControlPointerEvent, 
       
   822             ControlFromPosition( aPointerEvent.iPosition, ETrue ),
       
   823             &pointerEvent, 
       
   824             &handled );
       
   825 	}
       
   826 
       
   827         if ( !handled )
       
   828             {
       
   829             CCoeControl::HandlePointerEventL( aPointerEvent );
       
   830             }
       
   831         }
       
   832     }
       
   833 #else
       
   834 void CMsgEditorView::HandlePointerEventL( const TPointerEvent& /*aPointerEvent*/ )
       
   835     {
       
   836     }
       
   837 #endif // RD_SCALABLE_UI_V2
       
   838 
       
   839 // ---------------------------------------------------------
       
   840 // CMsgEditorView::HandleScrollEventL
       
   841 //
       
   842 // Handle text scrolling from pointer event
       
   843 // ---------------------------------------------------------
       
   844 //
       
   845 
       
   846 TBool CMsgEditorView::HandleScrollEventL(const TPointerEvent& aPointerEvent)
       
   847     {
       
   848     TBool handled = EFalse;
       
   849 
       
   850     if ( IsFocused() )
       
   851         {
       
   852         switch(aPointerEvent.iType)
       
   853             {
       
   854             case TPointerEvent::EButton1Down:
       
   855                 {
       
   856                 if(!iScrollBar->VerticalScrollBar()->Rect().Contains(aPointerEvent.iPosition))
       
   857                     {
       
   858                     iIsScrolling = ETrue;
       
   859                     
       
   860                     iHaveScrolled = EFalse;
       
   861                     iFirstPointerDown = aPointerEvent;
       
   862                     iScrollPos = aPointerEvent.iPosition;
       
   863 
       
   864                     handled = ETrue;
       
   865                     }
       
   866                 else
       
   867                     {
       
   868                     iIsScrolling = EFalse;
       
   869                     }
       
   870                 }
       
   871                 break;
       
   872                 
       
   873             case TPointerEvent::EDrag:
       
   874                 {
       
   875 
       
   876                 if(iIsScrolling)
       
   877                     {
       
   878                     if(!iHaveScrolled)
       
   879                         {
       
   880                         TInt xOffset = aPointerEvent.iPosition.iX - iScrollPos.iX;
       
   881                         if(Abs(xOffset) > KSelectionOffset) // this is a selection
       
   882                             {
       
   883                             iIsScrolling = EFalse;
       
   884                             ThrowOutPointerEventL(iFirstPointerDown);
       
   885                             break;
       
   886                             }
       
   887                         }
       
   888 
       
   889                     TInt yOffset = aPointerEvent.iPosition.iY - iScrollPos.iY;
       
   890                     if(Abs(yOffset) > iLineHeight)
       
   891                         {
       
   892                         TInt scrolled = ScrollL(yOffset);
       
   893                         if(scrolled)
       
   894                             {
       
   895                             iScrollPos.iY += scrolled;
       
   896                             }
       
   897                         else
       
   898                             {
       
   899                             ScrollPageL(yOffset);
       
   900                             iScrollPos.iY = aPointerEvent.iPosition.iY;
       
   901                             }
       
   902                         
       
   903                         iHaveScrolled = ETrue;
       
   904                         }
       
   905                     
       
   906                     handled = ETrue;
       
   907                     }
       
   908                 }
       
   909                 break;
       
   910                 
       
   911             case TPointerEvent::EButton1Up:
       
   912                 {
       
   913                 if(iIsScrolling)
       
   914                     {
       
   915                     iIsScrolling = EFalse;
       
   916                     
       
   917                     if(!iHaveScrolled) // mainly perform a click
       
   918                         {
       
   919                         ThrowOutPointerEventL(iFirstPointerDown);
       
   920 
       
   921                         iFirstPointerDown.iType = TPointerEvent::EDrag;
       
   922                         ThrowOutPointerEventL(iFirstPointerDown);
       
   923                         
       
   924                         ThrowOutPointerEventL(aPointerEvent);
       
   925                         }
       
   926                     
       
   927                     handled = ETrue;
       
   928                     }
       
   929                 }
       
   930                 break;
       
   931                 
       
   932             default:
       
   933                 break;
       
   934             }
       
   935         }
       
   936 
       
   937     return handled;
       
   938     }
       
   939 	
       
   940 	// ---------------------------------------------------------
       
   941 // CMsgEditorView::ThrowOutPointerEventL
       
   942 //
       
   943 //
       
   944 // Throw the pointer event to the other handler
       
   945 // ---------------------------------------------------------
       
   946 //
       
   947 
       
   948 void CMsgEditorView::ThrowOutPointerEventL(const TPointerEvent& aPointerEvent)
       
   949     {
       
   950     TBool lastPosHandled = EFalse;
       
   951     
       
   952     TPointerEvent pointerEvent( aPointerEvent );
       
   953     iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgControlPointerEvent, 
       
   954                                     ControlFromPosition( aPointerEvent.iPosition, ETrue ), 
       
   955                                     &pointerEvent, &lastPosHandled );
       
   956 
       
   957     if ( !lastPosHandled )
       
   958         {
       
   959         CCoeControl::HandlePointerEventL( aPointerEvent );
       
   960         }
       
   961     }
       
   962 	
       
   963 	
       
   964 	// ---------------------------------------------------------
       
   965 // CMsgEditorView::ScrollPartL
       
   966 //
       
   967 // Move current view up or down with screen height. 
       
   968 //
       
   969 // ---------------------------------------------------------
       
   970 //
       
   971 
       
   972 void CMsgEditorView::ScrollPartL(TInt aOffset)
       
   973     {
       
   974     TKeyEvent keyEvent;
       
   975     keyEvent.iModifiers = 0;
       
   976     if(aOffset < 0)
       
   977         {
       
   978         keyEvent.iCode = EKeyDownArrow;
       
   979         keyEvent.iScanCode = EStdKeyDownArrow;
       
   980         }
       
   981     else
       
   982         {
       
   983         keyEvent.iCode = EKeyUpArrow;
       
   984         keyEvent.iScanCode = EStdKeyUpArrow;
       
   985         }
       
   986     
       
   987     OfferKeyEventL(keyEvent, EEventKeyDown);
       
   988     OfferKeyEventL(keyEvent, EEventKey);
       
   989     OfferKeyEventL(keyEvent, EEventKeyUp);
       
   990     
       
   991     
       
   992     CItemFinder* finder = ItemFinder();
       
   993     if(finder) 
       
   994 		{
       
   995 		finder->ResetCurrentItem();
       
   996 		}
       
   997     }
       
   998 	
       
   999 // ---------------------------------------------------------
       
  1000 // CMsgEditorView::ScrollPageL
       
  1001 //
       
  1002 // Change to the previous or the next part(slide) if possible. 
       
  1003 //
       
  1004 // ---------------------------------------------------------
       
  1005 //
       
  1006 
       
  1007 void CMsgEditorView::ScrollPageL(TInt aOffset)
       
  1008     {
       
  1009     CMsgBaseControl* headerFocus = iHeader ? iHeader->FocusedControl() : NULL;
       
  1010     CMsgBaseControl* bodyFocus = iBody ? iBody->FocusedControl() : NULL;
       
  1011 
       
  1012     if(aOffset < 0)
       
  1013         {
       
  1014         if ( iCurrentFocus == EMsgHeaderFocused )
       
  1015             {
       
  1016             iCurrentFocus = EMsgBodyFocused;
       
  1017             }
       
  1018         if(headerFocus) 
       
  1019 			{
       
  1020 			headerFocus->NotifyViewEvent( EMsgViewEventPrepareFocusTransitionDown, 0 );
       
  1021 			}
       
  1022         if(bodyFocus)
       
  1023             {
       
  1024             TBool isFocused = bodyFocus->IsFocused();
       
  1025             bodyFocus->SetFocus(ETrue);
       
  1026             bodyFocus->NotifyViewEvent( EMsgViewEventPrepareFocusTransitionDown, 0 );
       
  1027             bodyFocus->SetFocus(isFocused);
       
  1028             }
       
  1029         }
       
  1030     else
       
  1031         {
       
  1032         if(bodyFocus)
       
  1033             {
       
  1034             TBool isFocused = bodyFocus->IsFocused();
       
  1035             bodyFocus->SetFocus(ETrue);
       
  1036             bodyFocus->NotifyViewEvent( EMsgViewEventPrepareFocusTransitionUp, 0 );
       
  1037             bodyFocus->SetFocus(isFocused);
       
  1038             }
       
  1039         if(headerFocus) 
       
  1040 			{
       
  1041 			headerFocus->NotifyViewEvent( EMsgViewEventPrepareFocusTransitionUp, 0 );
       
  1042 			}
       
  1043         if ( iCurrentFocus==EMsgBodyFocused && 0==iVisiblePart)
       
  1044             {
       
  1045             iCurrentFocus = EMsgHeaderFocused;
       
  1046             }
       
  1047         }
       
  1048 
       
  1049     ScrollPartL(aOffset);
       
  1050     }
       
  1051 
       
  1052 
       
  1053 // ---------------------------------------------------------
       
  1054 // CMsgEditorView::ViewInitialized
       
  1055 //
       
  1056 // Returns whether view is initialized.
       
  1057 // ---------------------------------------------------------
       
  1058 //
       
  1059 TBool CMsgEditorView::ViewInitialized() const
       
  1060     {
       
  1061     return iStateFlags & EMsgStateInitialized;
       
  1062     }
       
  1063 
       
  1064 // ---------------------------------------------------------
       
  1065 // CMsgEditorView::ViewRect
       
  1066 //
       
  1067 // Returns the current view rectangle.
       
  1068 // ---------------------------------------------------------
       
  1069 //
       
  1070 TRect CMsgEditorView::ViewRect() const
       
  1071     {
       
  1072     return iViewRect;
       
  1073     }
       
  1074 
       
  1075 // ---------------------------------------------------------
       
  1076 // CMsgEditorView::HandleBaseControlEventRequestL
       
  1077 //
       
  1078 // Handles an event from a control.
       
  1079 // ---------------------------------------------------------
       
  1080 //
       
  1081 TBool CMsgEditorView::HandleBaseControlEventRequestL( CMsgBaseControl* aControl,
       
  1082                                                       TMsgControlEventRequest aRequest,
       
  1083                                                       TInt aDelta )
       
  1084     {
       
  1085     if ( !( iStateFlags & EMsgStateInitialized ) )
       
  1086         {
       
  1087         // Allow processing of possible height & position changing
       
  1088         // events when view is currently being initialized.
       
  1089         if ( !( iStateFlags & EMsgStateInitializing ) ||
       
  1090              !( aRequest == EMsgEnsureCorrectFormPosition ||
       
  1091                 aRequest == EMsgHeightChanged ) )
       
  1092             {
       
  1093             return ETrue;
       
  1094             }
       
  1095         }
       
  1096 
       
  1097     TBool done( EFalse );
       
  1098     MMsgEditorObserver::TMsgFocusEvent focusEvent = MMsgEditorObserver::EMsgFocusNone;
       
  1099 
       
  1100     switch ( aRequest )
       
  1101         {
       
  1102         case EMsgCheckIfFocusIsAboveThis:
       
  1103             {
       
  1104             TBool isAbove = EFalse;
       
  1105             TInt componentIndex = iHeader->ComponentIndexFromId( aControl->ControlId() );
       
  1106             if ( componentIndex != KErrNotFound )
       
  1107                 {
       
  1108                 // control found in header.
       
  1109                 isAbove = iCurrentFocus == EMsgHeaderFocused
       
  1110                     ? iHeader->CurrentFocus() < componentIndex
       
  1111                     : EFalse;
       
  1112                 }
       
  1113             else
       
  1114                 {
       
  1115                 // control found in body.
       
  1116                 componentIndex = iBody->ComponentIndexFromId( aControl->ControlId() );
       
  1117                 isAbove = iCurrentFocus == EMsgBodyFocused
       
  1118                     ? iBody->CurrentFocus() < componentIndex
       
  1119                     : ETrue;
       
  1120                 }
       
  1121             return isAbove;
       
  1122             }
       
  1123 
       
  1124         case EMsgEnsureCorrectFormPosition:
       
  1125             {
       
  1126             if ( iStateFlags & EMsgEnsureCorrectFormPositionRequestIssued )
       
  1127                 {
       
  1128                 // prevents recursion.
       
  1129                 return EFalse;
       
  1130                 }
       
  1131             break;
       
  1132             }
       
  1133         case EMsgRotateFocusUp:
       
  1134             {
       
  1135             done = RotateFocusL( EMsgFocusUp, focusEvent );
       
  1136             break;
       
  1137             }
       
  1138         case EMsgRotateFocusDown:
       
  1139             {
       
  1140             done = RotateFocusL( EMsgFocusDown, focusEvent );
       
  1141             break;
       
  1142             }
       
  1143         case EMsgHeightChanged:
       
  1144             {
       
  1145             if ( iStateFlags & EMsgStateRefreshing )
       
  1146                 {
       
  1147                 done = ETrue;
       
  1148                 }
       
  1149             else if ( aControl &&
       
  1150                       aControl->ControlModeFlags() & EMsgControlModeBodyMaxHeight )
       
  1151                 {
       
  1152                 // Special handling is needed when maximum height body control's height is changed.
       
  1153                 // Currently this is happening when control is reseted. Special handling is
       
  1154                 // needed as last line of body control's text should be shown on the
       
  1155                 // last visible editor line if editor total height permits it. If editor total
       
  1156                 // does not permit this then editor should show it's topmost line.
       
  1157                 TInt bottomYPos( aControl->Position().iY + aControl->VirtualHeight() );
       
  1158                 TInt distanceFromBottom( Rect().iBr.iY - bottomYPos );
       
  1159     
       
  1160                 if ( distanceFromBottom > 0 )
       
  1161                     {
       
  1162                     TInt delta = Abs( iFormOffset ) < distanceFromBottom ? -iFormOffset :
       
  1163                                                                            distanceFromBottom;
       
  1164                     
       
  1165                     if ( delta )
       
  1166                         {
       
  1167                         ScrollForm( delta, ETrue );
       
  1168                         }
       
  1169                     }
       
  1170                 
       
  1171                 if ( ViewInitialized() )
       
  1172                     {
       
  1173                     UpdateScrollBarL();
       
  1174                     }
       
  1175                 
       
  1176                 done = ETrue;
       
  1177                 }
       
  1178             else
       
  1179                 {
       
  1180                 done = HandleHeightChangedL( aControl, aDelta );
       
  1181                 
       
  1182                 if ( ViewInitialized() )
       
  1183                     {
       
  1184                     UpdateScrollBarL();
       
  1185                     }
       
  1186                 }
       
  1187             return done;
       
  1188             }
       
  1189         case EMsgScrollForm:
       
  1190             {
       
  1191             done = ScrollForm( aDelta, ETrue );
       
  1192             break;
       
  1193             }
       
  1194         case EMsgUpdateScrollbar:
       
  1195             {
       
  1196             UpdateScrollBarL();
       
  1197             return ETrue;
       
  1198             }
       
  1199         default:
       
  1200             {
       
  1201             break;
       
  1202             }
       
  1203         }
       
  1204 
       
  1205     done = EnsureCorrectFormPosition( EFalse );
       
  1206     
       
  1207     if ( iStateFlags & EMsgStateRefreshing ||
       
  1208          iStateFlags & EMsgStateInitializing )
       
  1209         {
       
  1210         return done;
       
  1211         }
       
  1212 
       
  1213     UpdateScrollBarL();
       
  1214 
       
  1215     return done;
       
  1216     }
       
  1217 
       
  1218 // ---------------------------------------------------------
       
  1219 // CMsgEditorView::HandleBaseControlEventRequestL
       
  1220 //
       
  1221 // Handles an event from a control.
       
  1222 // ---------------------------------------------------------
       
  1223 //
       
  1224 TBool CMsgEditorView::HandleBaseControlEventRequestL( CMsgBaseControl* aControl,
       
  1225                                                       TMsgControlEventRequest aRequest )
       
  1226     {
       
  1227     return HandleBaseControlEventRequestL( aControl, aRequest, 0 );
       
  1228     }
       
  1229 
       
  1230 // ---------------------------------------------------------
       
  1231 // CMsgEditorView::HandleEditObserverEventRequestL
       
  1232 //
       
  1233 // Handles an event from a control.
       
  1234 // ---------------------------------------------------------
       
  1235 //
       
  1236 TInt CMsgEditorView::HandleEditObserverEventRequestL( const CCoeControl* /*aControl*/,
       
  1237                                                       TMsgControlEventRequest aRequest,
       
  1238                                                       TAny* aArg1,
       
  1239                                                       TAny* aArg2,
       
  1240                                                       TAny* aArg3 )
       
  1241     {
       
  1242     switch ( aRequest )
       
  1243         {
       
  1244         case EMsgDenyCut:
       
  1245             {
       
  1246             CEikEdwin::TClipboardFunc cb = CEikEdwin::ECut;
       
  1247             TInt arg = 0;
       
  1248 
       
  1249             iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgDenyClipboardOperation,
       
  1250                                             &cb,
       
  1251                                             &arg,
       
  1252                                             NULL );
       
  1253             return arg;
       
  1254             }
       
  1255         case EMsgDenyCopy:
       
  1256             {
       
  1257             CEikEdwin::TClipboardFunc cb = CEikEdwin::ECopy;
       
  1258             TInt arg = 0;
       
  1259 
       
  1260             iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgDenyClipboardOperation,
       
  1261                                             &cb,
       
  1262                                             &arg,
       
  1263                                             NULL );
       
  1264             return arg;
       
  1265             }
       
  1266         case EMsgDenyPaste:
       
  1267             {
       
  1268             CEikEdwin::TClipboardFunc cb = CEikEdwin::EPaste;
       
  1269             TInt arg = 0;
       
  1270 
       
  1271             iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgDenyClipboardOperation,
       
  1272                                             &cb,
       
  1273                                             &arg,
       
  1274                                             NULL );
       
  1275             return arg;
       
  1276             }
       
  1277         case EMsgStateFlags:
       
  1278             {
       
  1279             return iStateFlags;
       
  1280             }
       
  1281         case EMsgGetNaviIndicators:
       
  1282             {
       
  1283             iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgGetNaviIndicators,
       
  1284                                             aArg1,
       
  1285                                             aArg2,
       
  1286                                             aArg3 );
       
  1287             return 0;
       
  1288             }
       
  1289         case EMsgButtonPressed:
       
  1290             {
       
  1291             iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgButtonEvent,
       
  1292                                             aArg1,
       
  1293                                             aArg2,
       
  1294                                             aArg3 );
       
  1295             return 0;
       
  1296             }
       
  1297         default:
       
  1298             {
       
  1299             break;
       
  1300             }
       
  1301         }
       
  1302     return 0;
       
  1303     }
       
  1304 
       
  1305 // ---------------------------------------------------------
       
  1306 // CMsgEditorView::CountComponentControls
       
  1307 //
       
  1308 // Returns a number of controls.
       
  1309 // ---------------------------------------------------------
       
  1310 //
       
  1311 TInt CMsgEditorView::CountComponentControls() const
       
  1312     {
       
  1313     TInt countScrollBarComponents( 0 );
       
  1314     
       
  1315     if ( iScrollBar )
       
  1316         {
       
  1317         countScrollBarComponents = iScrollBar->CountComponentControls();
       
  1318         }
       
  1319         
       
  1320     return KMsgNumberOfControls + countScrollBarComponents;
       
  1321     }
       
  1322 
       
  1323 // ---------------------------------------------------------
       
  1324 // CMsgEditorView::ComponentControl
       
  1325 //
       
  1326 // Returns a control of index aIndex.
       
  1327 // ---------------------------------------------------------
       
  1328 //
       
  1329 CCoeControl* CMsgEditorView::ComponentControl( TInt aIndex ) const
       
  1330     {
       
  1331     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
  1332     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
  1333 
       
  1334     TInt countScrollBarComponents( 0 );
       
  1335     
       
  1336     if ( iScrollBar )
       
  1337         {
       
  1338         countScrollBarComponents = iScrollBar->CountComponentControls();
       
  1339         }
       
  1340         
       
  1341     switch ( aIndex )
       
  1342         {
       
  1343         case KMsgControlIndexHeader:
       
  1344             {
       
  1345             return iHeader;
       
  1346             }
       
  1347         case KMsgControlIndexBody:
       
  1348             {
       
  1349             return iBody;
       
  1350             }
       
  1351         default:
       
  1352             {
       
  1353             if ( iScrollBar &&  
       
  1354                  aIndex >= KMsgNumberOfControls &&  
       
  1355                  aIndex < countScrollBarComponents + KMsgNumberOfControls )
       
  1356                 {
       
  1357                 return iScrollBar->ComponentControl( aIndex - KMsgNumberOfControls );
       
  1358                 }
       
  1359             else
       
  1360                 {
       
  1361                 __ASSERT_DEBUG( EFalse, Panic( EMsgIncorrectComponentIndex ) );
       
  1362                 }
       
  1363             return NULL;
       
  1364             }
       
  1365         }
       
  1366     }
       
  1367 
       
  1368 // ---------------------------------------------------------
       
  1369 // CMsgEditorView::SizeChanged
       
  1370 //
       
  1371 // Sets new position for all the controls.
       
  1372 // ---------------------------------------------------------
       
  1373 //
       
  1374 void CMsgEditorView::SizeChanged()
       
  1375     { 
       
  1376     MEBLOGGER_ENTERFN( "CMsgEditorView::SizeChanged" );
       
  1377 
       
  1378     if ( iBgContext )
       
  1379         {
       
  1380         iBgContext->SetRect( Rect() );
       
  1381         iBgContext->SetParentPos( PositionRelativeToScreen() );
       
  1382         }
       
  1383 
       
  1384     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
  1385     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
  1386 
       
  1387     TPoint bodyPosition( MsgEditorCommons::MsgBodyPane().iTl.iX, 0 );
       
  1388     TPoint headerPosition( MsgEditorCommons::MsgHeaderPane().iTl.iX, iFormOffset );
       
  1389 
       
  1390     //MEBLOGGER_WRITEF(_L("MEB: CMsgEditorView::SizeChanged: header height %d "), iHeader->Size().iHeight);
       
  1391     //MEBLOGGER_WRITEF(_L("MEB: CMsgEditorView::SizeChanged: body   height %d "), iBody->Size().iHeight);
       
  1392 
       
  1393     iHeader->SetExtent( headerPosition, iHeader->Size() );
       
  1394     bodyPosition.iY = iHeader->Rect().iBr.iY /* + 1 */;
       
  1395     iBody->SetExtent( bodyPosition, iBody->Size() );
       
  1396 
       
  1397     MEBLOGGER_LEAVEFN( "CMsgEditorView::SizeChanged" );
       
  1398     }
       
  1399 
       
  1400 // ---------------------------------------------------------
       
  1401 // CMsgEditorView::FocusChanged
       
  1402 //
       
  1403 // Sets focus off or on from focused control. This is called
       
  1404 // when e.g. options menu is shown. Removed e.g. cursor from
       
  1405 // text fields.
       
  1406 // ---------------------------------------------------------
       
  1407 //
       
  1408 void CMsgEditorView::FocusChanged( TDrawNow /*aDrawNow*/ )
       
  1409     {
       
  1410     if ( iHeader && iBody )
       
  1411         {
       
  1412         CMsgBaseControl* ctrl = FocusedControl();
       
  1413 
       
  1414         if ( ctrl )
       
  1415             {
       
  1416             if ( !( ctrl->IsNonFocusing() ) )
       
  1417                 {
       
  1418                 ctrl->SetFocus( IsFocused(), IsFocused() ? EDrawNow: ENoDrawNow );
       
  1419                 }
       
  1420             }
       
  1421         
       
  1422         if ( IsFocused() )
       
  1423             {
       
  1424             NotifyControlsForEvent( EMsgViewEventViewFocusGain, 0 );
       
  1425             }
       
  1426         else
       
  1427             {
       
  1428             NotifyControlsForEvent( EMsgViewEventViewFocusLost, 0 );
       
  1429             }
       
  1430         }
       
  1431     }
       
  1432 
       
  1433 // ---------------------------------------------------------
       
  1434 // CMsgEditorView::HandleResourceChange
       
  1435 //
       
  1436 //
       
  1437 // ---------------------------------------------------------
       
  1438 //
       
  1439 void CMsgEditorView::HandleResourceChange( TInt aType )
       
  1440     {
       
  1441     // Updates child control layouts. Must be called before
       
  1442     // layout switch is handled here as AdjustComponentDistances 
       
  1443     // expects controls to have correct height. Child control
       
  1444     // height may vary if layout is using different font.
       
  1445     CCoeControl::HandleResourceChange( aType ); 
       
  1446     
       
  1447     if ( (aType == KEikDynamicLayoutVariantSwitch) ||
       
  1448          (aType == KAknSplitInputEnabled ) || 
       
  1449          (aType == KAknSplitInputDisabled  ))
       
  1450         {
       
  1451         iScrollBar->SetScrollBarFrameObserver( this );
       
  1452         
       
  1453         TInt invisibleLines( iFormOffset / iLineHeight );
       
  1454         
       
  1455         iLineHeight = MsgEditorCommons::MsgBaseLineDelta();
       
  1456         iBaseLineOffset = MsgEditorCommons::MsgBaseLineOffset();
       
  1457         
       
  1458         // Correct the form offset to be multiple of current line height
       
  1459         iFormOffset = invisibleLines * iLineHeight;
       
  1460         
       
  1461         TRect mainPane = MsgEditorCommons::MsgMainPane();
       
  1462         SetViewRect( mainPane );
       
  1463         iSize = mainPane.Size();
       
  1464         
       
  1465         AknLayoutUtils::LayoutVerticalScrollBar(
       
  1466             iScrollBar,
       
  1467             TRect( TPoint( 0, 0 ), mainPane.Size() ),
       
  1468             AknLayoutScalable_Apps::scroll_pane_cp017().LayoutLine() );
       
  1469             
       
  1470         TRAP_IGNORE( RefreshViewL() );
       
  1471         
       
  1472         EnsureCorrectViewPosition();
       
  1473         }
       
  1474     }
       
  1475 
       
  1476 // ---------------------------------------------------------
       
  1477 // CMsgEditorView::HandleControlEventL
       
  1478 // ---------------------------------------------------------
       
  1479 //
       
  1480 #ifdef RD_SCALABLE_UI_V2
       
  1481 void CMsgEditorView::HandleControlEventL( CCoeControl* aControl, TCoeEvent aEventType )
       
  1482     {
       
  1483     if ( aControl != iHeader &&
       
  1484          aControl != iBody )
       
  1485         {
       
  1486         switch( aEventType )
       
  1487             {
       
  1488             case MCoeControlObserver::EEventPrepareFocusTransition:
       
  1489                 {
       
  1490                 // These things must be done before pointer event is handled.
       
  1491                 CMsgBaseControl* baseControl = static_cast<CMsgBaseControl*>( aControl );
       
  1492     
       
  1493                 if ( baseControl && 
       
  1494                      ( baseControl->ControlType() == EMsgBodyControl ||
       
  1495                        baseControl->ControlType() == EMsgXhtmlBodyControl ) &&
       
  1496                      baseControl->ItemFinder() && 
       
  1497                      static_cast<CMsgBodyControl*>( baseControl )->Editor().TextView() )
       
  1498                     {
       
  1499                     TInt componentIndex = iBody->ComponentIndexFromId( baseControl->ControlId() );
       
  1500                     baseControl->SetupAutomaticFindAfterFocusChangeL( iBody->CurrentFocus() <= componentIndex );
       
  1501                     }
       
  1502                     
       
  1503                 break;
       
  1504                 }
       
  1505             case MCoeControlObserver::EEventRequestFocus:
       
  1506                 {
       
  1507                 // These things are done when pointer event is handled and focus should be changed.
       
  1508                 // NOTE: CMsgAddressControlEditor is relying on focus not to set before
       
  1509                 //       pointer event is processed. Otherwise it is impossible to 
       
  1510                 //       determine whether control has been focused before or not.
       
  1511                 CMsgBaseControl* baseControl = static_cast<CMsgBaseControl*>( aControl );
       
  1512                 SetFocusByControlIdL( baseControl->ControlId(), ETrue, EFalse );                    
       
  1513                 
       
  1514                 UpdateScrollBarL();
       
  1515                 }
       
  1516             default:
       
  1517                 {
       
  1518                 break;
       
  1519                 }
       
  1520             }
       
  1521         }
       
  1522     //MEBLOGGER_WRITEF(_L("MEB: CMsgEditorView::HandleControlEventL"));
       
  1523     }
       
  1524 #else
       
  1525 void CMsgEditorView::HandleControlEventL( CCoeControl* /*aControl*/, TCoeEvent /*aEventType*/ )
       
  1526     {
       
  1527     //MEBLOGGER_WRITEF(_L("MEB: CMsgEditorView::HandleControlEventL"));
       
  1528     }
       
  1529 #endif // RD_SCALABLE_UI_V2
       
  1530 
       
  1531 // ---------------------------------------------------------
       
  1532 // CMsgEditorView::CreateHeaderL
       
  1533 //
       
  1534 // Creates the header.
       
  1535 // ---------------------------------------------------------
       
  1536 //
       
  1537 void CMsgEditorView::CreateHeaderL()
       
  1538     {
       
  1539     __ASSERT_DEBUG( iHeader == NULL, Panic( EMsgHeaderAlreadyExists ) );
       
  1540 
       
  1541     TMargins margins;
       
  1542 
       
  1543     margins.iLeft = 0;
       
  1544     margins.iRight = 0;
       
  1545     margins.iTop = 0;
       
  1546     margins.iBottom = 0;
       
  1547 
       
  1548     iHeader = CMsgHeader::NewL( *this, margins );
       
  1549     iHeader->SetObserver( this );
       
  1550     }
       
  1551 
       
  1552 // ---------------------------------------------------------
       
  1553 // CMsgEditorView::CreateBodyL
       
  1554 //
       
  1555 // Creates the body. Creates also the default body control if requested.
       
  1556 // ---------------------------------------------------------
       
  1557 //
       
  1558 void CMsgEditorView::CreateBodyL()
       
  1559     {
       
  1560     __ASSERT_DEBUG( iBody == NULL, Panic( EMsgBodyAlreadyExists ) );
       
  1561 
       
  1562     TMargins margins;
       
  1563 
       
  1564     margins.iLeft = 0;
       
  1565     margins.iRight = 0;
       
  1566     margins.iTop = 0;
       
  1567     margins.iBottom = 0;
       
  1568 
       
  1569     iBody = CMsgBody::NewL( *this, margins );
       
  1570     iBody->SetObserver( this );
       
  1571 
       
  1572     if ( !( iEditorModeFlags & EMsgDoNotUseDefaultBodyControl ) )
       
  1573         {
       
  1574         CMsgBaseControl* bodyControl = CMsgBodyControl::NewL( this );
       
  1575         bodyControl->SetControlType( EMsgBodyControl );
       
  1576         DoAddControlL( bodyControl, EMsgComponentIdBody, EMsgFirstControl, EMsgBody );
       
  1577         }
       
  1578     }
       
  1579 
       
  1580 // ---------------------------------------------------------
       
  1581 // CMsgEditorView::CreateScrollBarL
       
  1582 //
       
  1583 // Creates the scroll bar.
       
  1584 // ---------------------------------------------------------
       
  1585 //
       
  1586 void CMsgEditorView::CreateScrollBarL()
       
  1587     {
       
  1588     __ASSERT_DEBUG( iScrollBar == NULL, Panic( EMsgScrollBarAlreadyExists ) );
       
  1589 
       
  1590     iScrollBar = new ( ELeave ) CEikScrollBarFrame(
       
  1591         this,  // CCoeControl* aParentWindow
       
  1592         this  // MEikScrollBarObserver* aObserver
       
  1593         );
       
  1594 
       
  1595     // Check which type of scrollbar is to be shown    
       
  1596     if ( AknLayoutUtils::DefaultScrollBarType( iAvkonAppUi ) == CEikScrollBarFrame::EDoubleSpan )
       
  1597         {
       
  1598         // For EDoubleSpan type scrollbar
       
  1599         // non-window owning scrollbar
       
  1600         iScrollBar->CreateDoubleSpanScrollBarsL( EFalse, EFalse, ETrue, EFalse );
       
  1601         iScrollBar->SetTypeOfVScrollBar( CEikScrollBarFrame::EDoubleSpan );
       
  1602         
       
  1603         AknLayoutUtils::LayoutVerticalScrollBar(
       
  1604             iScrollBar,
       
  1605             TRect( TPoint( 0, 0 ), 
       
  1606                    MsgEditorCommons::MsgMainPane().Size() ),
       
  1607             AknLayoutScalable_Apps::scroll_pane_cp017().LayoutLine() );        
       
  1608         }
       
  1609     else
       
  1610         {
       
  1611         // For EArrowHead type scrollbar
       
  1612         iScrollBar->SetTypeOfVScrollBar( CEikScrollBarFrame::EArrowHead );
       
  1613         }
       
  1614 
       
  1615     iScrollBar->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, 
       
  1616                                          CEikScrollBarFrame::EAuto );
       
  1617     }
       
  1618 
       
  1619 // ---------------------------------------------------------
       
  1620 // CMsgEditorView::UpdateScrollBarL
       
  1621 //
       
  1622 // Updates the scroll bar.
       
  1623 // ---------------------------------------------------------
       
  1624 //
       
  1625 void CMsgEditorView::UpdateScrollBarL()
       
  1626     {   
       
  1627     TInt height( 0 );
       
  1628     TInt pos( 0 );
       
  1629     TInt windowSize( iViewRect.Height() - iBaseLineOffset );
       
  1630     
       
  1631     // Round height up to the next full line height.
       
  1632     MsgEditorCommons::RoundToNextLine( windowSize, iLineHeight );    
       
  1633     
       
  1634     GetVirtualFormHeightAndPos( height, pos );
       
  1635     
       
  1636     // Round height up to the next full line height.
       
  1637     MsgEditorCommons::RoundToNextLine( height, iLineHeight );    
       
  1638     
       
  1639     if ( pos < iLineHeight )
       
  1640         {
       
  1641         pos = 0;
       
  1642         }
       
  1643     
       
  1644     // Round position up to the next full line height.
       
  1645     MsgEditorCommons::RoundToNextLine( pos, iLineHeight );
       
  1646     
       
  1647 #ifdef _DEBUG
       
  1648     // CAknScrollIndicator::SetPosition has an __ASSERT_DEBUG
       
  1649     // for range check even if the control handles out-of-range
       
  1650     // values properly.
       
  1651     if ( pos > height ) pos = height;
       
  1652     if ( pos < -1 )     pos = -1;
       
  1653     
       
  1654 #endif
       
  1655 
       
  1656     if ( iScrollBar->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan )
       
  1657         {
       
  1658         TAknDoubleSpanScrollBarModel vDsSbarModel;
       
  1659         vDsSbarModel.SetScrollSpan( height );
       
  1660         vDsSbarModel.SetWindowSize( windowSize );       
       
  1661         
       
  1662         pos = Max( 0, Min( height - windowSize, pos ) );  
       
  1663         
       
  1664         vDsSbarModel.SetFocusPosition( pos );
       
  1665         
       
  1666         TEikScrollBarFrameLayout layout;
       
  1667         layout.iTilingMode = TEikScrollBarFrameLayout::EInclusiveRectConstant;
       
  1668         
       
  1669         // It seems to be important that we have separate
       
  1670         // variable for "inclusiveRect" and "clientRect"
       
  1671         TRect inclusiveRect( Rect() );
       
  1672         TRect clientRect( Rect() );
       
  1673         
       
  1674         iScrollBar->TileL( NULL, &vDsSbarModel, clientRect, inclusiveRect, layout );
       
  1675         iScrollBar->SetVFocusPosToThumbPos( vDsSbarModel.FocusPosition() );
       
  1676         
       
  1677         iViewFocusPosition = vDsSbarModel.FocusPosition();
       
  1678         }
       
  1679     else
       
  1680         {
       
  1681         TEikScrollBarModel vertModel;
       
  1682         vertModel.iScrollSpan = height;
       
  1683         vertModel.iThumbSpan  = windowSize;
       
  1684         vertModel.iThumbPosition = pos;
       
  1685         
       
  1686         TEikScrollBarFrameLayout layout;
       
  1687     
       
  1688         TRect rect( Rect() );
       
  1689         iScrollBar->TileL( NULL, &vertModel, rect, rect, layout );
       
  1690         iScrollBar->SetVFocusPosToThumbPos( vertModel.iThumbPosition );
       
  1691         
       
  1692         iViewFocusPosition = vertModel.iThumbPosition;
       
  1693         }
       
  1694     
       
  1695     MsgEditorCommons::RoundToNextLine( iViewFocusPosition, iLineHeight );    
       
  1696     }
       
  1697 
       
  1698 
       
  1699 // ---------------------------------------------------------
       
  1700 // CMsgEditorView::GetVirtualFormHeightAndPos
       
  1701 //
       
  1702 // Return virtual height and virtual Y position of the form.
       
  1703 // This function assumes that only body can contain controls which virtual
       
  1704 // height must be calculated. Also this funtion assumes that only the
       
  1705 // currently focused control in the body can contain text above visible
       
  1706 // text view.
       
  1707 // ---------------------------------------------------------
       
  1708 //
       
  1709 void CMsgEditorView::GetVirtualFormHeightAndPos( TInt& aHeight, TInt& aPos )
       
  1710     {
       
  1711     TInt screenHeight = MsgEditorCommons::EditorViewHeigth() - iBaseLineOffset;
       
  1712     
       
  1713     TInt scrollPartsHeight( 0 );
       
  1714     TInt abovePartHeight( 0 );
       
  1715     
       
  1716     TInt bodyHeight( iBody->VirtualHeight() );
       
  1717     
       
  1718     TInt headerHeight( 0 );
       
  1719     
       
  1720     TBool headerLoaded( iHeader->CountMsgControls() );
       
  1721     if ( headerLoaded )
       
  1722         {
       
  1723         // Header loaded so get header height and subtract base line offset
       
  1724         // from it as header first control contains it and it is not scrollable
       
  1725         // area.
       
  1726         headerHeight = iHeader->VirtualHeight() - iBaseLineOffset;
       
  1727         }
       
  1728     else
       
  1729         {
       
  1730         // No header so baseline offset is added to the first body control's distance.
       
  1731         // Baseline offset is not scrollable area so it must be subtracted from body height.
       
  1732         bodyHeight -= iBaseLineOffset;
       
  1733         }
       
  1734     
       
  1735     iVisiblePartHeight = bodyHeight + headerHeight;
       
  1736     
       
  1737     // Visible height is always at least one screen height.
       
  1738     iVisiblePartHeight = Max( screenHeight, iVisiblePartHeight );
       
  1739     
       
  1740     // Calculate total scroll parts high excluding visible part and 
       
  1741     // height of the scroll parts above visible part.
       
  1742     TInt singlePartHeight = Max( screenHeight, iVisiblePartHeight / 10 );
       
  1743     for ( TInt current = 0; current < iScrollParts; current++ )
       
  1744         {
       
  1745         if ( current != iVisiblePart )
       
  1746             {
       
  1747             scrollPartsHeight += singlePartHeight;
       
  1748             
       
  1749             if ( current < iVisiblePart )
       
  1750                 {
       
  1751                 abovePartHeight = scrollPartsHeight;
       
  1752                 }
       
  1753             }
       
  1754         }
       
  1755     
       
  1756     aHeight = iVisiblePartHeight + scrollPartsHeight;
       
  1757 
       
  1758     if ( iCurrentFocus == EMsgBodyFocused )
       
  1759         {
       
  1760         TInt bodyExt = abovePartHeight + iBody->VirtualExtension();
       
  1761         
       
  1762         if ( headerLoaded )
       
  1763             {
       
  1764             // Remove visible header pixels from header height.
       
  1765             TInt visiblePixels( iHeader->Position().iY + iHeader->Size().iHeight - iBaseLineOffset );
       
  1766             if (  visiblePixels > 0 )
       
  1767                 {
       
  1768                 headerHeight -= visiblePixels;
       
  1769                 }
       
  1770             }
       
  1771         else
       
  1772             {
       
  1773             // No header so baseline offset is added to the first body control's distance.
       
  1774             // Baseline offset is not scrollable area so it must be subtracted from body extension.
       
  1775             bodyExt -= iBaseLineOffset;
       
  1776             }
       
  1777         
       
  1778         aPos = headerHeight + bodyExt;
       
  1779 
       
  1780         if ( iVisiblePart == ( iScrollParts - 1 ) )
       
  1781             {
       
  1782             // This ensures that if we at the end of the scroll area then scroll position is also
       
  1783             // at the end.
       
  1784             CMsgBaseControl* ctrl = FocusedControl();
       
  1785             
       
  1786             if ( ctrl && 
       
  1787                  ctrl->IsCursorLocation( EMsgBottom ) &&
       
  1788                  NextFocusableFormControl( iBody, 
       
  1789                          iBody->CurrentFocus() + 1, 
       
  1790                          EMsgFocusDown ) == KErrNotFound )
       
  1791                 {
       
  1792                 // Further scrolling (down) not possible.
       
  1793                 aPos = aHeight;
       
  1794                 
       
  1795                 if ( iScrollBar->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan )
       
  1796                     {
       
  1797                     // Focus position is top of the view.
       
  1798                     aPos -= screenHeight;
       
  1799                     }
       
  1800                 }
       
  1801             }
       
  1802         }
       
  1803     else
       
  1804         {
       
  1805         aPos = abovePartHeight + iHeader->VirtualExtension() - iBaseLineOffset;
       
  1806         }
       
  1807     }
       
  1808 
       
  1809 // ---------------------------------------------------------
       
  1810 // CMsgEditorView::SetAndGetSizeL
       
  1811 //
       
  1812 // Sets sizes for the header and the body and returns their total size aSize
       
  1813 // as a reference. The function does not set new sizes for the controls if
       
  1814 // the aInit argument is EFalse. If aInit == ETrue, this function sets the size
       
  1815 // so that only a total height can change.
       
  1816 // ---------------------------------------------------------
       
  1817 //
       
  1818 void CMsgEditorView::SetAndGetSizeL( TSize& aSize, TBool aInit )
       
  1819     {
       
  1820     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
  1821     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
  1822 
       
  1823     if ( aInit && iStateFlags & EMsgStateInitialized )
       
  1824         {
       
  1825         // Size changing at run time. Set intializing flag on.
       
  1826         iStateFlags |= EMsgStateInitializing;
       
  1827         }
       
  1828 
       
  1829     TSize editorSize( aSize );
       
  1830     TSize headerSize( 0, 0 );
       
  1831     TSize bodySize( 0, 0 );
       
  1832 
       
  1833     headerSize = aSize;
       
  1834     iHeader->SetAndGetSizeL( headerSize, aInit );
       
  1835 
       
  1836     bodySize = aSize;
       
  1837     iBody->SetAndGetSizeL( bodySize, aInit );
       
  1838 
       
  1839     editorSize.iHeight = headerSize.iHeight + bodySize.iHeight;
       
  1840 
       
  1841     // View size must always be the size of client rect. Don't change "iSize"!
       
  1842     aSize = editorSize;
       
  1843     
       
  1844     if ( aInit && iStateFlags & EMsgStateInitialized )
       
  1845         {
       
  1846         iStateFlags &= ~EMsgStateInitializing;
       
  1847         }
       
  1848     }
       
  1849 
       
  1850 // ---------------------------------------------------------
       
  1851 // CMsgEditorView::RefreshViewL
       
  1852 //
       
  1853 // Sets the positions for the controls and re-draws the view.
       
  1854 // ---------------------------------------------------------
       
  1855 //
       
  1856 void CMsgEditorView::RefreshViewL()
       
  1857     {
       
  1858     iStateFlags |= EMsgStateRefreshing;
       
  1859     
       
  1860     // Component must know their correct height by now.
       
  1861     AdjustComponentDistances();
       
  1862 
       
  1863     TSize editorSize( iViewRect.Size() );
       
  1864     
       
  1865     // Called after AdjustComponentDistances because that
       
  1866     // information is used on some components to calculate
       
  1867     // their sizes
       
  1868     SetAndGetSizeL( editorSize, ETrue );
       
  1869     SizeChanged();
       
  1870     
       
  1871     UpdateScrollBarL();
       
  1872     
       
  1873     NotifyControlsForEvent( EMsgViewEventPrepareForViewing, 0 );
       
  1874     DrawDeferred();
       
  1875 
       
  1876     iStateFlags &= ~EMsgStateRefreshing;
       
  1877 
       
  1878     EnsureCorrectFormPosition( EFalse );
       
  1879     }
       
  1880 
       
  1881 // ---------------------------------------------------------
       
  1882 // CMsgEditorView::NotifyControlsForEvent
       
  1883 //
       
  1884 // Notifies controls for an event.
       
  1885 // ---------------------------------------------------------
       
  1886 //
       
  1887 void CMsgEditorView::NotifyControlsForEvent( TMsgViewEvent aEvent, TInt aParam )
       
  1888     {
       
  1889     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
  1890     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
  1891 
       
  1892     iHeader->NotifyControlsForEvent( aEvent, aParam );
       
  1893     iBody->NotifyControlsForEvent( aEvent, aParam );
       
  1894     }
       
  1895 
       
  1896 // ---------------------------------------------------------
       
  1897 // CMsgEditorView::SetFocusByControlIdL
       
  1898 //
       
  1899 // Sets focus to a control aControlId. aSetCursorPos specified
       
  1900 // whether cursor position should be set or not.
       
  1901 // ---------------------------------------------------------
       
  1902 //
       
  1903 void CMsgEditorView::SetFocusByControlIdL( TInt aControlId, 
       
  1904                                            TBool aCorrectFormPosition,
       
  1905                                            TBool aSetCursorPos )
       
  1906     {
       
  1907     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
  1908     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
  1909     __ASSERT_DEBUG( aControlId >= 0, Panic( EMsgIncorrectControlId ) );
       
  1910 
       
  1911     NotifyControlsForEvent( EMsgViewEventFocusMoveStarting, 0 ); 
       
  1912     
       
  1913     ReportFocusMovement( MMsgEditorObserver::EMsgFocusMovingFrom );
       
  1914     
       
  1915     TInt componentIndex = iHeader->ComponentIndexFromId( aControlId );
       
  1916 
       
  1917     if ( componentIndex != KErrNotFound )
       
  1918         {
       
  1919         // Control where focus is wanted to be moved was found from header.
       
  1920         if ( iCurrentFocus == EMsgBodyFocused )
       
  1921             {
       
  1922             if (IsReadOnly()) // viewer
       
  1923                 {
       
  1924                  iBody->NotifyControlsForEvent( EMsgViewEventPrepareFocusTransitionUp, 0 );
       
  1925                  iBody->SetFocus( EFalse, 
       
  1926                              iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  1927                                                                   ENoDrawNow );                            
       
  1928                 }
       
  1929             else
       
  1930                 {
       
  1931                 iBody->SetFocus( EFalse, 
       
  1932                              iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  1933                                                                   ENoDrawNow );                            
       
  1934                 iBody->NotifyControlsForEvent( EMsgViewEventPrepareFocusTransitionUp, 0 ); 
       
  1935                 }
       
  1936             }
       
  1937         
       
  1938         TMsgFocus previousMsgPart = iCurrentFocus;
       
  1939         iCurrentFocus = EMsgHeaderFocused;
       
  1940         
       
  1941         TInt delta = componentIndex - iHeader->CurrentFocus();
       
  1942         
       
  1943         if ( delta != 0 )
       
  1944             {
       
  1945             iHeader->SetFocus( EFalse, 
       
  1946                                iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  1947                                                                     ENoDrawNow );
       
  1948             iHeader->NotifyControlsForEvent( delta > 0 ? EMsgViewEventPrepareFocusTransitionDown : 
       
  1949                                                          EMsgViewEventPrepareFocusTransitionUp,
       
  1950                                              0 );
       
  1951             }
       
  1952         
       
  1953         // Do real focus movement when focus is moved between
       
  1954         // message parts or when focus is moved inside message part
       
  1955         // to different component. Do it also if currently focused 
       
  1956         // control does not have focus really.
       
  1957         if ( componentIndex != iHeader->CurrentFocus() ||
       
  1958              previousMsgPart != iCurrentFocus ||
       
  1959              !iHeader->FocusedControl()->IsFocused() )
       
  1960             {
       
  1961             if ( !iHeader->ChangeFocusTo( componentIndex, 
       
  1962                                           iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  1963                                                                                ENoDrawNow ) )
       
  1964                 {
       
  1965                 __ASSERT_DEBUG( EFalse, Panic( EMsgNonFocusingControl ) );
       
  1966                 }
       
  1967             }
       
  1968         }
       
  1969     else
       
  1970         {
       
  1971         componentIndex = iBody->ComponentIndexFromId( aControlId );
       
  1972         
       
  1973         if ( componentIndex != KErrNotFound )
       
  1974             {
       
  1975             // Control where focus is wanted to be moved was found from body.
       
  1976             if ( iCurrentFocus == EMsgHeaderFocused )
       
  1977                 {
       
  1978                  if (IsReadOnly())
       
  1979                     {
       
  1980                     iHeader->NotifyControlsForEvent( EMsgViewEventPrepareFocusTransitionDown, 0 ); 
       
  1981                     iHeader->SetFocus( EFalse, 
       
  1982                                    iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  1983                                                                         ENoDrawNow );
       
  1984                     }
       
  1985                 else
       
  1986                     {
       
  1987 
       
  1988                     iHeader->SetFocus( EFalse, 
       
  1989                                    iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  1990                                                                         ENoDrawNow );
       
  1991                     iHeader->NotifyControlsForEvent( EMsgViewEventPrepareFocusTransitionDown, 0 ); 
       
  1992                     }
       
  1993                 }
       
  1994             TMsgFocus previousMsgPart = iCurrentFocus;
       
  1995             iPrevFocus = iCurrentFocus; 
       
  1996             iCurrentFocus = EMsgBodyFocused;
       
  1997             
       
  1998             TInt delta = componentIndex - iBody->CurrentFocus();
       
  1999             
       
  2000             if ( delta != 0 )
       
  2001                 {
       
  2002                 iBody->SetFocus( EFalse, 
       
  2003                                  iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  2004                                                                       ENoDrawNow );            
       
  2005                 iBody->NotifyControlsForEvent( delta ? EMsgViewEventPrepareFocusTransitionDown : 
       
  2006                                                        EMsgViewEventPrepareFocusTransitionUp,
       
  2007                                                0 );
       
  2008                 }
       
  2009             
       
  2010             // Do real focus movement when focus is moved between
       
  2011             // message parts or when focus is moved inside message part
       
  2012             // to different component. Do it also if currently focused 
       
  2013             // control does not have focus really.
       
  2014             if ( componentIndex != iBody->CurrentFocus() ||
       
  2015                  previousMsgPart != iCurrentFocus ||
       
  2016                  !iBody->FocusedControl()->IsFocused() )
       
  2017                 {
       
  2018                 CMsgBaseControl* ctrl = iBody->MsgControl( componentIndex );
       
  2019     
       
  2020                 if ( aSetCursorPos &&
       
  2021                      ctrl && 
       
  2022                      ( ctrl->ControlType() == EMsgBodyControl ||
       
  2023                        ctrl->ControlType() == EMsgXhtmlBodyControl ) &&
       
  2024                      ctrl->ItemFinder() && 
       
  2025                      static_cast<CMsgBodyControl*>( ctrl )->Editor().TextView() )
       
  2026                     {
       
  2027                     ctrl->SetupAutomaticFindAfterFocusChangeL( iBody->CurrentFocus() <= componentIndex );
       
  2028                     }
       
  2029         
       
  2030                 if ( !iBody->ChangeFocusTo( componentIndex, 
       
  2031                                             iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  2032                                                                                  ENoDrawNow ) )
       
  2033                     {
       
  2034                     __ASSERT_DEBUG( EFalse, Panic( EMsgNonFocusingControl ) );
       
  2035                     }
       
  2036                 }
       
  2037             }
       
  2038         else
       
  2039             {
       
  2040             __ASSERT_DEBUG( EFalse, Panic( EMsgNoFocusingControlExist ) );
       
  2041             }
       
  2042         }
       
  2043         
       
  2044     NotifyControlsForEvent( EMsgViewEventFocusMoveFinished, 0 );
       
  2045     
       
  2046     ReportFocusMovement( MMsgEditorObserver::EMsgFocusMovedTo );
       
  2047 
       
  2048     if ( aCorrectFormPosition )
       
  2049         {
       
  2050         EnsureCorrectFormPosition( IsReadOnly() );
       
  2051         }
       
  2052 
       
  2053     if ( aSetCursorPos && 
       
  2054          IsReadOnly() && 
       
  2055          FocusedControl() )
       
  2056         {
       
  2057         FocusedControl()->NotifyViewEvent( EMsgViewEventSetCursorLastPos, 0 );
       
  2058         }
       
  2059     }
       
  2060 
       
  2061 // ---------------------------------------------------------
       
  2062 // CMsgEditorView::DoAddControlL
       
  2063 //
       
  2064 // Does an actual add operation for the control by setting all the necessary
       
  2065 // observers etc.
       
  2066 // ---------------------------------------------------------
       
  2067 //
       
  2068 void CMsgEditorView::DoAddControlL( CMsgBaseControl* aControl,
       
  2069                                     TInt aControlId,
       
  2070                                     TInt aIndex,
       
  2071                                     TMsgFormComponent aFormComponent )
       
  2072     {
       
  2073     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
  2074     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
  2075 
       
  2076     // set readonly for control here because readonly flag
       
  2077     // may be needed before ActivateL call.
       
  2078     TUint32 flags = aControl->ControlModeFlags();
       
  2079     if ( IsReadOnly() ||  
       
  2080          flags & EMsgControlModeReadOnly )
       
  2081         {
       
  2082         flags |= EMsgControlModeReadOnly;
       
  2083         }
       
  2084     else
       
  2085         {
       
  2086         flags &= ~EMsgControlModeReadOnly;
       
  2087         }
       
  2088     aControl->SetControlModeFlags( flags );
       
  2089     
       
  2090     if ( !aControl->OwnsWindow() )
       
  2091         {
       
  2092         aControl->SetContainerWindowL( *this );
       
  2093         }
       
  2094         
       
  2095     aControl->SetObserver( this );
       
  2096     aControl->SetBaseControlObserver( *this );
       
  2097     
       
  2098     if ( iEdwinObserver )
       
  2099         {
       
  2100         CEikRichTextEditor* editor = NULL;
       
  2101     
       
  2102         if ( aControl->ControlType() == EMsgExpandableControl ||
       
  2103              aControl->ControlType() == EMsgAddressControl )
       
  2104             {
       
  2105             editor = &static_cast<CMsgExpandableControl*>( aControl )->Editor();
       
  2106             }
       
  2107         else if ( aControl->ControlType() == EMsgBodyControl ||
       
  2108                   aControl->ControlType() == EMsgXhtmlBodyControl )
       
  2109             {
       
  2110             editor = &static_cast<CMsgBodyControl*>( aControl )->Editor();
       
  2111             }
       
  2112         
       
  2113         if ( editor )
       
  2114             {
       
  2115             editor->AddEdwinObserverL( iEdwinObserver );
       
  2116             }
       
  2117         }
       
  2118     
       
  2119     aControl->MakeVisible( ETrue );
       
  2120     aControl->ActivateL();
       
  2121     
       
  2122     // this calls PrepareForReadOnly and sets flags again
       
  2123     // but it doesn't matter.
       
  2124     aControl->SetReadOnly( flags & EMsgControlModeReadOnly );
       
  2125 
       
  2126     if ( aFormComponent == EMsgHeader )
       
  2127         {
       
  2128         iHeader->AddControlL( aControl, aControlId, aIndex );
       
  2129         }
       
  2130     else if ( aFormComponent == EMsgBody )
       
  2131         {
       
  2132         iBody->AddControlL( aControl, aControlId, aIndex );
       
  2133 
       
  2134         if ( iHeader->CountMsgControls() == 0 )
       
  2135             {
       
  2136             iCurrentFocus = EMsgBodyFocused;
       
  2137             }
       
  2138         }
       
  2139     else
       
  2140         {
       
  2141         __ASSERT_DEBUG( EFalse, Panic( EMsgIncorrectFormComponent ) );
       
  2142         }
       
  2143     
       
  2144     if ( aControl->UniqueHandle() == KErrNotFound )
       
  2145         {
       
  2146         // Control added first time. Set unique handle.
       
  2147         aControl->SetUniqueHandle( iUniqueHandlePool );
       
  2148         iUniqueHandlePool++;
       
  2149         }
       
  2150     
       
  2151     if ( iStateFlags & EMsgStateInitialized )  // Control is added on run-time.
       
  2152         {
       
  2153         TRAPD( err, RefreshViewL() );
       
  2154 
       
  2155         if ( err != KErrNone )
       
  2156             {
       
  2157             // if RefreshViewL fails, remove the added control from internal
       
  2158             // structures, i.e. transfer ownership back to caller.
       
  2159             if ( aFormComponent == EMsgHeader )
       
  2160                 {
       
  2161                 iHeader->RemoveControlL( aControlId ); // does not leave.
       
  2162                 }
       
  2163             else if ( aFormComponent == EMsgBody )
       
  2164                 {
       
  2165                 iBody->RemoveControlL( aControlId ); // does not leave.
       
  2166                 }
       
  2167 
       
  2168             User::Leave( err );
       
  2169             }
       
  2170         else
       
  2171             {
       
  2172             // Set control initialized as it has been successfully added & activated.
       
  2173             flags = aControl->ControlModeFlags();
       
  2174             flags |= EMsgControlModeInitialized;
       
  2175             aControl->SetControlModeFlags( flags );
       
  2176             }
       
  2177         }
       
  2178     }
       
  2179 
       
  2180 // ---------------------------------------------------------
       
  2181 // CMsgEditorView::RotateFocusL
       
  2182 //
       
  2183 // Rotates focus up or down depending aDirection argument. Returns ETrue if
       
  2184 // operation can be done.
       
  2185 // ---------------------------------------------------------
       
  2186 //
       
  2187 TBool CMsgEditorView::RotateFocusL( TMsgFocusDirection aDirection,
       
  2188                                     MMsgEditorObserver::TMsgFocusEvent& aFocusEvent )
       
  2189     {
       
  2190     __ASSERT_DEBUG( iHeader != NULL, Panic( EMsgHeaderNotExists ) );
       
  2191     __ASSERT_DEBUG( iBody != NULL, Panic( EMsgBodyNotExists ) );
       
  2192 
       
  2193     TBool startAutoFind = EFalse;
       
  2194     TBool setMaxHeight = EFalse;
       
  2195     
       
  2196     TInt newFocus = KErrNotFound;
       
  2197     TInt controlIndex = 0;
       
  2198     
       
  2199     CMsgFormComponent* currForm = NULL;
       
  2200     CMsgFormComponent* nextForm = NULL;
       
  2201     
       
  2202     if ( iCurrentFocus == EMsgHeaderFocused )
       
  2203         {
       
  2204         currForm = iHeader;
       
  2205         controlIndex = iHeader->CurrentFocus();
       
  2206 
       
  2207         if ( aDirection == EMsgFocusDown )
       
  2208             {
       
  2209             newFocus = NextFocusableFormControl( iHeader, controlIndex + 1, EMsgFocusDown );
       
  2210 
       
  2211             if ( newFocus != KErrNotFound )
       
  2212                 {
       
  2213                 nextForm = iHeader;
       
  2214                 }
       
  2215             else
       
  2216                 {
       
  2217                 newFocus = NextFocusableFormControl( iBody, 0, EMsgFocusDown );
       
  2218 
       
  2219                 if ( newFocus != KErrNotFound )
       
  2220                     {
       
  2221                     startAutoFind = ETrue;
       
  2222                     nextForm = iBody;
       
  2223                     aFocusEvent = MMsgEditorObserver::EMsgFocusToBody;
       
  2224                     }
       
  2225                 else
       
  2226                     {
       
  2227                     TInt currentlyFocused = iBody->CurrentFocus();
       
  2228                     
       
  2229                     if ( IsFocusable( iBody->MsgControl( currentlyFocused ), EMsgFocusDown ) )
       
  2230                         {
       
  2231                         // Refocus the currently focused control.
       
  2232                         nextForm = iBody;
       
  2233                         startAutoFind = ETrue;
       
  2234                         newFocus = currentlyFocused;
       
  2235                         }
       
  2236                         
       
  2237                     aFocusEvent = MMsgEditorObserver::EMsgFocusAtBottom;
       
  2238                     }
       
  2239                 }
       
  2240             }
       
  2241         else if ( aDirection == EMsgFocusUp )
       
  2242             {
       
  2243             newFocus = NextFocusableFormControl( iHeader, controlIndex - 1, EMsgFocusUp );
       
  2244 
       
  2245             if ( newFocus != KErrNotFound )
       
  2246                 {
       
  2247                 nextForm = iHeader;
       
  2248                 }
       
  2249             else
       
  2250                 {
       
  2251                 aFocusEvent = MMsgEditorObserver::EMsgFocusAtTop;
       
  2252                 }
       
  2253             }
       
  2254         }
       
  2255     else if ( iCurrentFocus == EMsgBodyFocused )
       
  2256         {
       
  2257         currForm = iBody;
       
  2258         controlIndex = iBody->CurrentFocus();
       
  2259 
       
  2260         if ( aDirection == EMsgFocusDown )
       
  2261             {
       
  2262             newFocus = NextFocusableFormControl( iBody, controlIndex + 1, EMsgFocusDown );
       
  2263 
       
  2264             if ( newFocus != KErrNotFound )
       
  2265                 {
       
  2266                 nextForm = iBody;
       
  2267                 }
       
  2268             else
       
  2269                 {
       
  2270                 aFocusEvent = MMsgEditorObserver::EMsgFocusAtBottom;
       
  2271                 }
       
  2272             }
       
  2273         else if ( aDirection == EMsgFocusUp )
       
  2274             {
       
  2275             newFocus = NextFocusableFormControl( iBody, controlIndex - 1, EMsgFocusUp );
       
  2276 
       
  2277             if ( newFocus != KErrNotFound )
       
  2278                 {
       
  2279                 nextForm = iBody;
       
  2280                 }
       
  2281             else
       
  2282                 {
       
  2283                 newFocus = NextFocusableFormControl( iHeader, iHeader->CountMsgControls() - 1, EMsgFocusUp );
       
  2284                 setMaxHeight = ETrue;
       
  2285                 
       
  2286                 if ( newFocus != KErrNotFound )
       
  2287                     {
       
  2288                     nextForm = iHeader;
       
  2289                     aFocusEvent = MMsgEditorObserver::EMsgFocusToHeader;
       
  2290                     }
       
  2291                 else
       
  2292                     {
       
  2293                     TInt currentlyFocused = iHeader->CurrentFocus();
       
  2294                     if ( IsFocusable( iHeader->MsgControl( currentlyFocused ), EMsgFocusUp ) )
       
  2295                         {
       
  2296                         // Refocus the currently focused control.
       
  2297                         nextForm = iHeader;
       
  2298                         newFocus = currentlyFocused;
       
  2299                         }
       
  2300                         
       
  2301                     aFocusEvent = MMsgEditorObserver::EMsgFocusAtTop;
       
  2302                     }
       
  2303                 }
       
  2304             }
       
  2305 
       
  2306         if ( ( aFocusEvent == MMsgEditorObserver::EMsgFocusNone || 
       
  2307                aFocusEvent == MMsgEditorObserver::EMsgFocusToBody ) && 
       
  2308              ( newFocus != controlIndex && 
       
  2309                newFocus > KErrNotFound ) ) // for automatic highlight
       
  2310             { 
       
  2311             // we assume that editor size is correct in this point
       
  2312             startAutoFind = ETrue;
       
  2313             }
       
  2314 
       
  2315         }
       
  2316     
       
  2317     if ( setMaxHeight )
       
  2318         {
       
  2319         CMsgBaseControl* ctrl = FocusedControl(); // for automatic highlight
       
  2320         
       
  2321         if ( ctrl && 
       
  2322              ( ctrl->ControlType() == EMsgBodyControl ||
       
  2323                ctrl->ControlType() == EMsgXhtmlBodyControl ) && 
       
  2324              ctrl->ItemFinder() ) 
       
  2325             {
       
  2326             static_cast<CMsgBodyControl*>( ctrl )->Editor().SetMaximumHeight( 
       
  2327                                                             MsgEditorCommons::MaxBodyHeight() );
       
  2328             } // for automatic highlight
       
  2329         }
       
  2330 
       
  2331     if ( nextForm != NULL )
       
  2332         {                                              
       
  2333         NotifyControlsForEvent( aDirection == EMsgFocusUp ? EMsgViewEventPrepareFocusTransitionUp : 
       
  2334                                                             EMsgViewEventPrepareFocusTransitionDown, 
       
  2335                                 0 );
       
  2336         
       
  2337         NotifyControlsForEvent( EMsgViewEventFocusMoveStarting, 0 );
       
  2338             
       
  2339         ReportFocusMovement( MMsgEditorObserver::EMsgFocusMovingFrom );
       
  2340         
       
  2341         if ( nextForm == currForm )
       
  2342             {
       
  2343             currForm->ChangeFocusTo( newFocus, 
       
  2344                                      iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  2345                                                                           ENoDrawNow );
       
  2346             }
       
  2347         else
       
  2348             {
       
  2349             currForm->SetFocus( EFalse, 
       
  2350                                 iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  2351                                                                      ENoDrawNow );
       
  2352             iCurrentFocus = ( nextForm == iBody ) ? EMsgBodyFocused : 
       
  2353                                                     EMsgHeaderFocused;
       
  2354             
       
  2355             nextForm->ChangeFocusTo( newFocus,
       
  2356                                      iStateFlags & EMsgStateInitialized ? EDrawNow :
       
  2357                                                                           ENoDrawNow );
       
  2358             }
       
  2359         
       
  2360         CMsgBaseControl* focusedControl = FocusedControl();
       
  2361         
       
  2362         if ( focusedControl )
       
  2363             {
       
  2364             if ( aDirection == EMsgFocusDown )
       
  2365                 {
       
  2366                 focusedControl->NotifyViewEvent( EMsgViewEventSetCursorFirstPos, 0 );
       
  2367                 }
       
  2368             else if ( aDirection == EMsgFocusUp )
       
  2369                 {
       
  2370                 focusedControl->NotifyViewEvent( EMsgViewEventSetCursorLastPos, 0 );
       
  2371                 }
       
  2372             }
       
  2373         
       
  2374         NotifyControlsForEvent( EMsgViewEventFocusMoveFinished, 0 );
       
  2375             
       
  2376         ReportFocusMovement( MMsgEditorObserver::EMsgFocusMovedTo );
       
  2377         }
       
  2378     else
       
  2379         {
       
  2380         CMsgBaseControl* focusedControl = FocusedControl();
       
  2381         
       
  2382         if ( !IsReadOnly() && focusedControl && !startAutoFind )
       
  2383             {
       
  2384             // Focus is tried to move to direction that does not cause any focus
       
  2385             // changes (either up when already at the topmost position or down when 
       
  2386             // already at the bottommost position) on editor. 
       
  2387             // => Set focused cursor position to either last or first position if we
       
  2388             // are at last or first scroll part. 
       
  2389             if ( aDirection == EMsgFocusDown && 
       
  2390                  iVisiblePart == iScrollParts - 1 )
       
  2391                 {
       
  2392                 if ( focusedControl->ControlType() == EMsgBodyControl ||
       
  2393                      focusedControl->ControlType() == EMsgXhtmlBodyControl )
       
  2394                     {
       
  2395                     CEikRichTextEditor& editor = static_cast<CMsgBodyControl*>( focusedControl )->Editor();
       
  2396                     editor.SetCursorPosL( editor.TextLength(), EFalse );
       
  2397                     }
       
  2398                 else if ( focusedControl->ControlType() == EMsgExpandableControl ||
       
  2399                           focusedControl->ControlType() == EMsgAddressControl )
       
  2400                     {
       
  2401                     CEikRichTextEditor& editor = 
       
  2402                                 static_cast<CMsgExpandableControl*>( focusedControl )->Editor();
       
  2403                     editor.SetCursorPosL( editor.TextLength(), EFalse );
       
  2404                     
       
  2405                     if ( focusedControl->ControlType() == EMsgAddressControl )
       
  2406                         {
       
  2407                         // Update the address field highlighting
       
  2408                         static_cast<CMsgAddressControlEditor&>( editor ).CheckHighlightingL();
       
  2409                         }
       
  2410                     }
       
  2411                 }
       
  2412             else if ( aDirection == EMsgFocusUp &&
       
  2413                       iVisiblePart == 0)
       
  2414                 {
       
  2415                 if ( focusedControl->ControlType() == EMsgBodyControl ||
       
  2416                      focusedControl->ControlType() == EMsgXhtmlBodyControl )
       
  2417                     {
       
  2418                     CEikRichTextEditor& editor = static_cast<CMsgBodyControl*>( focusedControl )->Editor();
       
  2419                     editor.SetCursorPosL( 0, EFalse );
       
  2420                     }
       
  2421                 else if ( focusedControl->ControlType() == EMsgExpandableControl ||
       
  2422                           focusedControl->ControlType() == EMsgAddressControl )
       
  2423                     {
       
  2424                     CEikRichTextEditor& editor = 
       
  2425                             static_cast<CMsgExpandableControl*>( focusedControl )->Editor();
       
  2426                     editor.SetCursorPosL( 0, EFalse );
       
  2427                     
       
  2428                     if ( focusedControl->ControlType() == EMsgAddressControl )
       
  2429                         {
       
  2430                         // Update the address field highlighting
       
  2431                         static_cast<CMsgAddressControlEditor&>( editor ).CheckHighlightingL();
       
  2432                         }
       
  2433                     }
       
  2434                 }
       
  2435             }
       
  2436         }
       
  2437     
       
  2438     if ( startAutoFind ) 
       
  2439         { 
       
  2440         CMsgBaseControl* ctrl = (CMsgBaseControl*)iBody->MsgControl( newFocus );
       
  2441     
       
  2442         if ( ctrl && 
       
  2443              ( ctrl->ControlType() == EMsgBodyControl ||
       
  2444                ctrl->ControlType() == EMsgXhtmlBodyControl ) &&
       
  2445              ctrl->ItemFinder() && 
       
  2446              static_cast<CMsgBodyControl*>( ctrl )->Editor().TextView() )
       
  2447             {
       
  2448             ctrl->SetupAutomaticFindAfterFocusChangeL( aDirection == EMsgFocusDown );
       
  2449             }
       
  2450         }
       
  2451         
       
  2452     return newFocus != KErrNotFound;
       
  2453     }
       
  2454 
       
  2455 // ---------------------------------------------------------
       
  2456 // CMsgEditorView::EnsureCorrectFormPosition
       
  2457 //
       
  2458 // Ensures that the cursor is visible on the view and that the form position
       
  2459 // is correct.
       
  2460 // ---------------------------------------------------------
       
  2461 //
       
  2462 TBool CMsgEditorView::EnsureCorrectFormPosition( TBool /*aScrollDown*/, TBool /*aScrollUp*/ )
       
  2463     {
       
  2464     CMsgBaseControl* ctrl = FocusedControl();
       
  2465     if ( !ctrl )
       
  2466         {
       
  2467         return EFalse;
       
  2468         }
       
  2469     else 
       
  2470         {
       
  2471         if ( ctrl->ControlType() == EMsgBodyControl 
       
  2472              && ctrl->ItemFinder()
       
  2473              && ctrl->IsReadOnly()
       
  2474              && !iMoveUpDownEvent ) 
       
  2475             {
       
  2476             TInt countHeader = iHeader->CountMsgControls();
       
  2477             for ( TInt i = 0; i < countHeader; i++ )
       
  2478                  {
       
  2479                  CMsgBaseControl* headerCtrl = iHeader->MsgControl( i );
       
  2480                  if ( headerCtrl )
       
  2481                      {
       
  2482                      TInt controlType;
       
  2483                      controlType = headerCtrl->ControlType();
       
  2484                      if ( controlType == EMsgAddressControl ||
       
  2485                           controlType == EMsgExpandableControl ||
       
  2486                           controlType == EMsgAttachmentControl )
       
  2487                          {
       
  2488                          if ( ControlFullyVisible(headerCtrl) || iPrevFocus == EMsgHeaderFocused )
       
  2489                              {
       
  2490                              return EFalse; // Ignoring Scroll Event
       
  2491                              }
       
  2492                          }
       
  2493                       }
       
  2494                  }
       
  2495             }        
       
  2496         }
       
  2497 
       
  2498     iStateFlags |= EMsgEnsureCorrectFormPositionRequestIssued;
       
  2499 
       
  2500     TInt delta = 0;
       
  2501     TBool viewScrolled = ETrue;
       
  2502     TRect lineRect = ctrl->IsReadOnly() ? ctrl->Rect() : 
       
  2503                                           ctrl->CurrentLineRect();
       
  2504 
       
  2505     if ( lineRect.Height() )
       
  2506         {
       
  2507         if ( lineRect.iBr.iY > iViewRect.Height() ) 
       
  2508            {
       
  2509             // the view must be scrolled up.
       
  2510             delta = iViewRect.Height() - lineRect.iBr.iY;
       
  2511             }
       
  2512         else if ( lineRect.iTl.iY < 0 && 
       
  2513                   lineRect.Height() <= iViewRect.Height() )
       
  2514             {
       
  2515             // the view must be scrolled down.
       
  2516             delta = -lineRect.iTl.iY;
       
  2517             }
       
  2518         
       
  2519         // Adjust to next(/previous) baseline
       
  2520         if ( delta > 0 )
       
  2521             {
       
  2522             MsgEditorCommons::RoundToNextLine( delta, iLineHeight );            
       
  2523             }
       
  2524         else
       
  2525             {
       
  2526             MsgEditorCommons::RoundToPreviousLine( delta, iLineHeight );                        
       
  2527             }
       
  2528         }
       
  2529 
       
  2530     if ( delta )
       
  2531         {
       
  2532         EnsureCorrectCursorPosition();
       
  2533         
       
  2534         viewScrolled = EFalse;
       
  2535         ScrollForm( delta, ETrue );
       
  2536         }
       
  2537 
       
  2538     iStateFlags &= ~EMsgEnsureCorrectFormPositionRequestIssued;
       
  2539 
       
  2540     return viewScrolled;
       
  2541     }
       
  2542 
       
  2543 // ---------------------------------------------------------
       
  2544 // CMsgEditorView::HandleHeightChangedL
       
  2545 //
       
  2546 // Handles the form's height change. Gets pointer aControl to a control which
       
  2547 // height is changing. If aDeltaHeight > 0 the height is increasing.
       
  2548 // Assumes that control's size has already been changed.
       
  2549 // ---------------------------------------------------------
       
  2550 //
       
  2551 TBool CMsgEditorView::HandleHeightChangedL( CMsgBaseControl* /*aControl*/, 
       
  2552                                             TInt /*aDeltaHeight*/ )
       
  2553     {
       
  2554     MEBLOGGER_ENTERFN( "CMsgEditorView::HandleHeightChangedL" );
       
  2555 
       
  2556     TSize headerSize = iHeader->Size();
       
  2557     
       
  2558     TSize size( headerSize + iBody->Size() );
       
  2559     TSize thisSize( iViewRect.Size() );
       
  2560 
       
  2561     SetAndGetSizeL( thisSize, EFalse );
       
  2562     
       
  2563     if ( size.iHeight != thisSize.iHeight )
       
  2564         {
       
  2565         SizeChanged();
       
  2566         }
       
  2567     
       
  2568     if ( ViewInitialized() )
       
  2569         {
       
  2570         if ( headerSize != iHeader->Size() )
       
  2571             {
       
  2572             DrawNow();
       
  2573             }
       
  2574         else
       
  2575             {
       
  2576             DrawDeferred();
       
  2577             }
       
  2578         }
       
  2579 
       
  2580     MEBLOGGER_ENTERFN( "CMsgEditorView::HandleHeightChangedL" );
       
  2581 
       
  2582     return ETrue;
       
  2583     }
       
  2584 
       
  2585 // ---------------------------------------------------------
       
  2586 // CMsgEditorView::ScrollForm
       
  2587 //
       
  2588 // Scrolls the form up or down depending on aDelta. If aDelta > 0, the form
       
  2589 // scrolls down. Form offset should also be less or equal to 0. 
       
  2590 // ---------------------------------------------------------
       
  2591 //
       
  2592 TBool CMsgEditorView::ScrollForm( TInt aDelta, TBool aUpdateScrollBarPos )
       
  2593     {
       
  2594     TBool result( ETrue );
       
  2595     
       
  2596     if ( iFormOffset + aDelta > 0 )
       
  2597         {
       
  2598         // Scrolling form given amount of pixels would result form to go above
       
  2599         // it's uppermost position.
       
  2600         aDelta = -iFormOffset;
       
  2601         
       
  2602         result = EFalse;
       
  2603         }
       
  2604         
       
  2605     if ( aDelta != 0 )
       
  2606         {    
       
  2607         iFormOffset += aDelta;
       
  2608         
       
  2609         // Real scrolling is performed here.
       
  2610         SizeChanged();
       
  2611         
       
  2612         // Do not redraw the screen if we are in the middle of state refreshing. 
       
  2613         if ( !( iStateFlags & EMsgStateRefreshing ) )
       
  2614             {
       
  2615             DrawNow();
       
  2616             }
       
  2617             
       
  2618         NotifyControlsForEvent( EMsgViewEventFormScrolled, aDelta );
       
  2619         
       
  2620         if ( aUpdateScrollBarPos )
       
  2621             {
       
  2622             iViewFocusPosition -= aDelta;
       
  2623             
       
  2624             const TAknDoubleSpanScrollBarModel* model = AknScrollBarModel();
       
  2625            
       
  2626             if ( model )
       
  2627                 {
       
  2628                 iScrollBar->MoveThumbsBy( 0, -aDelta );
       
  2629                 }
       
  2630             }
       
  2631         }
       
  2632     
       
  2633     return result;
       
  2634     }
       
  2635 
       
  2636 // ---------------------------------------------------------
       
  2637 // CMsgEditorView::SetViewRect
       
  2638 //
       
  2639 // Sets view rect.
       
  2640 // ---------------------------------------------------------
       
  2641 //
       
  2642 void CMsgEditorView::SetViewRect( const TRect& /*aRect*/ )
       
  2643     {
       
  2644     iViewRect = MsgEditorCommons::MsgMainPane();
       
  2645     
       
  2646     Window().SetExtent( iViewRect.iTl, iViewRect.Size() );
       
  2647     }
       
  2648 
       
  2649 // ---------------------------------------------------------
       
  2650 // CMsgEditorView::AdjustComponentDistances
       
  2651 //
       
  2652 // Set proper distances between controls to obey LAF coordinates.
       
  2653 //
       
  2654 // Note: Components must know their correct height when this function
       
  2655 //       is called.
       
  2656 // ---------------------------------------------------------
       
  2657 //
       
  2658 void CMsgEditorView::AdjustComponentDistances()
       
  2659     {
       
  2660     TInt i;
       
  2661     CMsgBaseControl* ctrl;
       
  2662     TInt controlType;
       
  2663     TInt countHeader = iHeader->CountMsgControls();
       
  2664     TInt countBody = iBody->CountMsgControls();    
       
  2665 
       
  2666     TInt baseLine = iLineHeight;
       
  2667     TInt firstComponentOffset = iBaseLineOffset;
       
  2668 
       
  2669     // beforeOffset + control height + afterOffset
       
  2670     // must be multiple of baseLine!
       
  2671     TInt beforeOffset = 0;
       
  2672     TInt afterOffset = 0;
       
  2673     TInt distance = 0;
       
  2674 
       
  2675     for ( i = 0; i < countHeader; i++ )
       
  2676         {
       
  2677         ctrl = iHeader->MsgControl( i );
       
  2678         if ( ctrl )
       
  2679             {
       
  2680             controlType = ctrl->ControlType();
       
  2681 
       
  2682             if ( controlType == EMsgAddressControl ||
       
  2683                  controlType == EMsgExpandableControl ||
       
  2684                  controlType == EMsgAttachmentControl )
       
  2685                 {
       
  2686                 distance = ( i == 0 ) ? firstComponentOffset : 
       
  2687                                         0;
       
  2688                 distance += afterOffset;
       
  2689 
       
  2690                 // At least in APAC there's offset in the header
       
  2691                 // fields. A header field is 21 pixels high whereas
       
  2692                 // the baseline is 19 pixels.
       
  2693                 TInt offset = -( ctrl->Size().iHeight % baseLine );
       
  2694                 // TODO: Minor MAGIC
       
  2695                 // header frames take 3 pixels so it's ok to
       
  2696                 // have offset of "-3".
       
  2697                 if ( offset < -3 )
       
  2698                     {
       
  2699                     offset += baseLine;
       
  2700                     }
       
  2701                 // divide offset evenly between before and after offset
       
  2702                 //beforeOffset = offset / 2;
       
  2703                 //afterOffset = offset - beforeOffset;
       
  2704                 //distance += beforeOffset;
       
  2705                 distance += offset;
       
  2706 
       
  2707                 ctrl->SetDistanceFromComponentAbove( distance );
       
  2708                 }
       
  2709             }
       
  2710         }
       
  2711 
       
  2712     for ( i = 0; i < countBody; i++ )
       
  2713         {
       
  2714         ctrl = iBody->MsgControl( i );
       
  2715         
       
  2716         if ( ctrl )
       
  2717             {
       
  2718             if ( i == 0 )
       
  2719                 {
       
  2720                 distance = ( countHeader == 0 ) ? firstComponentOffset : 
       
  2721                                                   0;
       
  2722                 }
       
  2723             else
       
  2724                 {
       
  2725                 distance = baseLine;
       
  2726                 }
       
  2727                 
       
  2728             distance += afterOffset;
       
  2729 
       
  2730             controlType = ctrl->ControlType();
       
  2731             
       
  2732             switch ( controlType )
       
  2733                 {
       
  2734                 case EMsgImageControl:
       
  2735                 case EMsgAudioControl:
       
  2736                     {
       
  2737                     // Image control height is always
       
  2738                     // multiple of baseLine
       
  2739                     beforeOffset = 0;
       
  2740                     afterOffset = 0;
       
  2741                     break;
       
  2742                     }
       
  2743                 case EMsgVideoControl:
       
  2744                     {
       
  2745                     // Video must be precisely at the top of the screen.
       
  2746                     beforeOffset = -firstComponentOffset;
       
  2747                     // Video control height is not multiple of baseLine
       
  2748                     // -> calculate offset
       
  2749                     afterOffset = firstComponentOffset -
       
  2750                         ( ctrl->Size().iHeight % baseLine );
       
  2751                     break;
       
  2752                     }
       
  2753                 default:
       
  2754                     {
       
  2755                     beforeOffset = 0;
       
  2756                     afterOffset = 0;
       
  2757                     break;
       
  2758                     }
       
  2759                 }
       
  2760             distance += beforeOffset;
       
  2761            
       
  2762             ctrl->SetDistanceFromComponentAbove( distance );
       
  2763 
       
  2764             // TODO: Is this the correct place to check this?!
       
  2765             if ( !IsReadOnly() && 
       
  2766                  ( controlType == EMsgBodyControl ||
       
  2767                    controlType == EMsgXhtmlBodyControl ) )
       
  2768                 {
       
  2769                 TUint32 flags = ctrl->ControlModeFlags();
       
  2770                 if ( iBody->ComponentIndexFromId( EMsgComponentIdBody ) == 
       
  2771                      countBody - 1 )
       
  2772                     {
       
  2773                     // In editor mode bodycontrol must have max height 
       
  2774                     // if it's the last control in msg body even if it
       
  2775                     // has no text so that all editor lines are drawn.
       
  2776                     flags |= EMsgControlModeBodyMaxHeight;
       
  2777                     }
       
  2778                 else
       
  2779                     {
       
  2780                     flags &= ~EMsgControlModeBodyMaxHeight;
       
  2781                     }
       
  2782                     
       
  2783                 ctrl->SetControlModeFlags( flags );
       
  2784                 }
       
  2785             }
       
  2786         }
       
  2787     }
       
  2788 
       
  2789 // ---------------------------------------------------------
       
  2790 // CMsgEditorView::SetComponentsInitialized
       
  2791 //
       
  2792 // Set all controls initialized.
       
  2793 // ---------------------------------------------------------
       
  2794 //
       
  2795 void CMsgEditorView::SetComponentsInitialized()
       
  2796     {
       
  2797     TInt i;
       
  2798     CMsgBaseControl* ctrl;
       
  2799     TInt countHeader = iHeader->CountMsgControls();
       
  2800     TInt countBody = iBody->CountMsgControls();
       
  2801 
       
  2802     TUint32 flags;
       
  2803 
       
  2804     for ( i = 0; i < countHeader; i++ )
       
  2805         {
       
  2806         ctrl = iHeader->MsgControl( i );
       
  2807         
       
  2808         if ( ctrl )
       
  2809             {
       
  2810             flags = ctrl->ControlModeFlags();
       
  2811             flags |= EMsgControlModeInitialized;
       
  2812             ctrl->SetControlModeFlags( flags );
       
  2813             }
       
  2814         }
       
  2815 
       
  2816     for ( i = 0; i < countBody; i++ )
       
  2817         {
       
  2818         ctrl = iBody->MsgControl( i );
       
  2819         
       
  2820         if ( ctrl )
       
  2821             {
       
  2822             flags = ctrl->ControlModeFlags();
       
  2823             flags |= EMsgControlModeInitialized;
       
  2824             ctrl->SetControlModeFlags( flags );
       
  2825             }
       
  2826         }
       
  2827     }
       
  2828 
       
  2829 
       
  2830 // ---------------------------------------------------------
       
  2831 // CMsgEditorView::SetAfterFocusL
       
  2832 //
       
  2833 //
       
  2834 //
       
  2835 // ---------------------------------------------------------
       
  2836 //
       
  2837 TBool CMsgEditorView::SetAfterFocusL( MMsgEditorObserver::TMsgAfterFocusEventFunc aAfterFocus )
       
  2838     {
       
  2839     TBool forceScrollUp = EFalse;
       
  2840     CMsgBaseControl* ctrl;
       
  2841     TInt newFocus;
       
  2842     CMsgBodyControl* body = static_cast<CMsgBodyControl*>( ControlById( EMsgComponentIdBody ) );
       
  2843     CEikRichTextEditor* bodyEditor = NULL;
       
  2844     
       
  2845     TBool toBodyBeginning = (aAfterFocus == MMsgEditorObserver::EMsgCursorToBodyBeginning);
       
  2846 
       
  2847     if ( body )
       
  2848         {
       
  2849         bodyEditor = &body->Editor();
       
  2850         body->SetupAutomaticFindAfterFocusChangeL( toBodyBeginning );
       
  2851         }
       
  2852 
       
  2853     if ( toBodyBeginning )
       
  2854         {
       
  2855         newFocus = iBody->FirstFocusableControl( 0, EMsgFocusDown );
       
  2856         
       
  2857         if ( newFocus != KErrNotFound )
       
  2858             {
       
  2859             ctrl = iBody->MsgControl( newFocus );
       
  2860             SetFocusByControlIdL( ctrl->ControlId() );
       
  2861 
       
  2862             if ( bodyEditor )
       
  2863                 {
       
  2864                 bodyEditor->SetCursorPosL( 0, EFalse );
       
  2865                 }
       
  2866             }
       
  2867         
       
  2868         // go to the first line
       
  2869         CMsgBaseControl* bodyFocus = iBody->FocusedControl();
       
  2870         if(bodyFocus) bodyFocus->NotifyViewEvent( EMsgViewEventPrepareFocusTransitionUp, 0 );
       
  2871         EnsureCorrectFormPosition(EFalse);
       
  2872         }
       
  2873     else if ( aAfterFocus == MMsgEditorObserver::EMsgCursorToBodyEnd )
       
  2874         {
       
  2875         newFocus = iBody->FirstFocusableControl( iBody->CountMsgControls() - 1, EMsgFocusUp );
       
  2876 
       
  2877         if ( newFocus == KErrNotFound )
       
  2878             {
       
  2879             // empty body perhaps...
       
  2880             newFocus = iHeader->FirstFocusableControl( iHeader->CountMsgControls() - 1, EMsgFocusUp );
       
  2881 
       
  2882             if ( newFocus != KErrNotFound )
       
  2883                 {
       
  2884                 ctrl = iHeader->MsgControl( newFocus );
       
  2885                 SetFocusByControlIdL( ctrl->ControlId(), EFalse );
       
  2886                 }
       
  2887             }
       
  2888         else
       
  2889             {
       
  2890             ctrl = iBody->MsgControl( newFocus );
       
  2891             SetFocusByControlIdL( ctrl->ControlId(), EFalse );
       
  2892 
       
  2893             if ( bodyEditor )
       
  2894                 {               
       
  2895                 bodyEditor->SetCursorPosL( bodyEditor->TextLength(), EFalse );
       
  2896                 }
       
  2897                 
       
  2898             forceScrollUp = ETrue;
       
  2899             }
       
  2900 
       
  2901         // go to the last line
       
  2902         CMsgBaseControl* bodyFocus = iBody->FocusedControl();
       
  2903         if(bodyFocus) bodyFocus->NotifyViewEvent( EMsgViewEventPrepareFocusTransitionDown, 0 );
       
  2904         EnsureCorrectFormPosition(ETrue);
       
  2905         }
       
  2906     return forceScrollUp;
       
  2907     }
       
  2908 
       
  2909 // ---------------------------------------------------------
       
  2910 // CMsgEditorView::ItemFinder
       
  2911 //
       
  2912 // ---------------------------------------------------------
       
  2913 //
       
  2914 EXPORT_C CItemFinder* CMsgEditorView::ItemFinder()
       
  2915     {   
       
  2916     if ( iBody )
       
  2917         {
       
  2918         CMsgBaseControl* ctrl;
       
  2919         TInt countBody = iBody->CountMsgControls();
       
  2920 
       
  2921         for ( TInt i = 0; i < countBody; i++ )
       
  2922             {
       
  2923             ctrl = iBody->MsgControl( i );
       
  2924             if ( ctrl &&
       
  2925                  ( ctrl->ControlType() == EMsgBodyControl ||
       
  2926                    ctrl->ControlType() == EMsgXhtmlBodyControl ) )
       
  2927                 {
       
  2928                 return ctrl->ItemFinder();
       
  2929                 }
       
  2930             }
       
  2931         }
       
  2932     return 0;
       
  2933     }
       
  2934 
       
  2935 // ---------------------------------------------------------
       
  2936 // CMsgEditorView::SetEdwinObserverL
       
  2937 //
       
  2938 // ---------------------------------------------------------
       
  2939 //
       
  2940 EXPORT_C void CMsgEditorView::SetEdwinObserverL( MEikEdwinObserver* aObserver )
       
  2941     {
       
  2942     iEdwinObserver = aObserver;
       
  2943     
       
  2944     TInt headerControlCount = iHeader->CountMsgControls();
       
  2945     TInt controlCount = headerControlCount + iBody->CountMsgControls();
       
  2946     
       
  2947     for ( TInt controlIndex = 0; controlIndex < controlCount; controlIndex++ )
       
  2948         {
       
  2949         CMsgBaseControl* control = NULL;
       
  2950         if ( controlIndex < headerControlCount )
       
  2951             {
       
  2952             control = iHeader->MsgControl( controlIndex );
       
  2953             }
       
  2954         else
       
  2955             {
       
  2956             control = iBody->MsgControl( controlIndex - headerControlCount );
       
  2957             }
       
  2958         
       
  2959         CEikRichTextEditor* editor = NULL;
       
  2960         if ( control->ControlType() == EMsgExpandableControl ||
       
  2961              control->ControlType() == EMsgAddressControl )
       
  2962             {
       
  2963             editor = &static_cast<CMsgExpandableControl*>( control )->Editor();
       
  2964             }
       
  2965         else if ( control->ControlType() == EMsgBodyControl ||
       
  2966                   control->ControlType() == EMsgXhtmlBodyControl )
       
  2967             {
       
  2968             editor = &static_cast<CMsgBodyControl*>( control )->Editor();
       
  2969             }
       
  2970         
       
  2971         if ( editor )
       
  2972             {
       
  2973             editor->RemoveEdwinObserver( iEdwinObserver );
       
  2974             
       
  2975             if ( iEdwinObserver )
       
  2976                 {
       
  2977                 editor->AddEdwinObserverL( iEdwinObserver );
       
  2978                 }
       
  2979             }
       
  2980         }
       
  2981     }
       
  2982 
       
  2983 // ---------------------------------------------------------
       
  2984 // CMsgEditorView::ControlFullyVisible
       
  2985 //
       
  2986 // If control's:
       
  2987 // - top Y-coordinate is below or equal messaging main pane top Y-coordinate and 
       
  2988 // - bottom Y-coordinate is above or equal messaging main pane bottom Y-coordinate 
       
  2989 // then control is fully visible. Currently all controls are expected
       
  2990 // to have equal width as messaging data pane.
       
  2991 // ---------------------------------------------------------
       
  2992 //
       
  2993 TBool CMsgEditorView::ControlFullyVisible( CMsgBaseControl* aControl ) const
       
  2994     {
       
  2995     TBool retVal = EFalse;
       
  2996     
       
  2997     if ( aControl )
       
  2998         {
       
  2999         TRect rect = aControl->Rect();
       
  3000         if ( rect.iTl.iY >= 0 && 
       
  3001              rect.iBr.iY <= MsgEditorCommons::EditorViewHeigth() )
       
  3002             {
       
  3003             retVal = ETrue;
       
  3004             }
       
  3005         }
       
  3006         
       
  3007     return retVal;
       
  3008     }
       
  3009 
       
  3010 // ---------------------------------------------------------
       
  3011 // CMsgEditorView::NextFocusableFormControl
       
  3012 // 
       
  3013 // Searches then next focusable form control from given form component
       
  3014 // starting from certain control and proceeding into given direction.
       
  3015 // 
       
  3016 // Stops when either focusable control is found or there is no more
       
  3017 // controls left. See CMsgEditorView::IsFocusable function for
       
  3018 // description when control is focusable.
       
  3019 // ---------------------------------------------------------
       
  3020 //
       
  3021 TInt CMsgEditorView::NextFocusableFormControl( CMsgFormComponent* aFormComponent, 
       
  3022                                                TInt aStart, 
       
  3023                                                TMsgFocusDirection aDirection )
       
  3024     {
       
  3025     TInt newFocus = aFormComponent->FirstFocusableControl( aStart, aDirection );
       
  3026     TBool found = EFalse;
       
  3027 
       
  3028     while ( newFocus != KErrNotFound && 
       
  3029             !found )
       
  3030         {
       
  3031         found = IsFocusable( aFormComponent->MsgControl( newFocus ), aDirection );
       
  3032             
       
  3033         if ( !found )
       
  3034             {
       
  3035             newFocus = aFormComponent->FirstFocusableControl( 
       
  3036                                 aDirection == EMsgFocusDown ? newFocus + 1 : 
       
  3037                                                               newFocus - 1, 
       
  3038                                 aDirection );
       
  3039             }        
       
  3040         }
       
  3041         
       
  3042     return newFocus;
       
  3043     }
       
  3044 
       
  3045 // ---------------------------------------------------------
       
  3046 // CMsgEditorView::MopSupplyObject
       
  3047 //
       
  3048 // ---------------------------------------------------------
       
  3049 //
       
  3050 EXPORT_C TTypeUid::Ptr CMsgEditorView::MopSupplyObject( TTypeUid aId )
       
  3051     {   
       
  3052     if ( aId.iUid == MAknsControlContext::ETypeId )
       
  3053         {
       
  3054         return MAknsControlContext::SupplyMopObject( aId, iBgContext );
       
  3055         }
       
  3056 
       
  3057     return CCoeControl::MopSupplyObject( aId );
       
  3058     }
       
  3059 
       
  3060 // ---------------------------------------------------------
       
  3061 // CMsgEditorView::HandleScrollEventL
       
  3062 //
       
  3063 // ---------------------------------------------------------
       
  3064 //
       
  3065 #ifdef RD_SCALABLE_UI_V2
       
  3066 void CMsgEditorView::HandleScrollEventL( CEikScrollBar* aScrollBar, 
       
  3067                                          TEikScrollEvent aEventType )
       
  3068     {
       
  3069     switch ( aEventType )
       
  3070         {
       
  3071         case EEikScrollUp:
       
  3072             {
       
  3073             ScrollViewL( iLineHeight, EMsgScrollUp, ETrue );
       
  3074             EnsureCorrectScrollPartL( AknScrollBarModel()->FocusPosition() );
       
  3075             break;
       
  3076             }
       
  3077         case EEikScrollDown:
       
  3078             {
       
  3079             ScrollViewL( iLineHeight, EMsgScrollDown, ETrue );
       
  3080             EnsureCorrectScrollPartL( AknScrollBarModel()->FocusPosition() );
       
  3081             break;
       
  3082             }
       
  3083         case EEikScrollTop:
       
  3084             {
       
  3085             // Not supported yet.
       
  3086             break;
       
  3087             }
       
  3088         case EEikScrollBottom:
       
  3089             {
       
  3090             // Not supported yet.
       
  3091             break;
       
  3092             }
       
  3093         case EEikScrollThumbReleaseVert:
       
  3094             {
       
  3095             iScrollBar->DrawBackground( ETrue, ETrue );
       
  3096             
       
  3097             EnsureCorrectScrollPartL( AknScrollBarModel()->FocusPosition() );
       
  3098             iPopUpPart = -1;
       
  3099             break;
       
  3100             }
       
  3101         case EEikScrollPageUp:
       
  3102         case EEikScrollPageDown:
       
  3103             {
       
  3104             TInt scrolledPixels = iViewFocusPosition - AknScrollBarModel()->FocusPosition();
       
  3105             
       
  3106             if( IsReadOnly() )
       
  3107                 {
       
  3108                 TInt screenHeight = MsgEditorCommons::EditorViewHeigth() - iBaseLineOffset;
       
  3109 
       
  3110                 if(scrolledPixels > screenHeight)
       
  3111                     {
       
  3112                     scrolledPixels = screenHeight;
       
  3113                     }
       
  3114                 else if(scrolledPixels < -screenHeight)
       
  3115                     {
       
  3116                     scrolledPixels = -screenHeight;
       
  3117                     }
       
  3118                 }
       
  3119 
       
  3120             // Round to the previous full line.
       
  3121             MsgEditorCommons::RoundToPreviousLine( scrolledPixels, iLineHeight );
       
  3122         
       
  3123             if ( scrolledPixels != 0 )
       
  3124                 {
       
  3125                 ScrollViewL( Abs( scrolledPixels ), 
       
  3126                              scrolledPixels > 0 ? EMsgScrollUp :
       
  3127                                                   EMsgScrollDown,
       
  3128                              EFalse );
       
  3129                 
       
  3130                 EnsureCorrectScrollPartL( AknScrollBarModel()->FocusPosition() );
       
  3131                 
       
  3132                 iScrollBar->DrawScrollBarsNow();
       
  3133                 }
       
  3134             break;
       
  3135             }
       
  3136         case EEikScrollThumbDragVert:
       
  3137             {
       
  3138             TInt currentPart( CurrentScrollPart( AknScrollBarModel()->FocusPosition() ) );
       
  3139             
       
  3140             if ( currentPart == iVisiblePart )
       
  3141                 {
       
  3142                 if ( iPopUpPart != -1 )
       
  3143                     {
       
  3144                     // Hide the popup if visible
       
  3145                     static_cast<CAknDoubleSpanScrollBar*>( aScrollBar )->SetScrollPopupInfoTextL( KNullDesC );
       
  3146                     iPopUpPart = -1;
       
  3147                     }    
       
  3148                 }
       
  3149             
       
  3150             if ( iPopUpPart == -1 )
       
  3151                 {
       
  3152                 TInt scrolledPixels = iViewFocusPosition - AknScrollBarModel()->FocusPosition();
       
  3153             
       
  3154                 // Round to the previous full line.
       
  3155                 MsgEditorCommons::RoundToPreviousLine( scrolledPixels, iLineHeight );
       
  3156             
       
  3157                 if ( scrolledPixels != 0 )
       
  3158                     {
       
  3159                     ScrollViewL( Abs( scrolledPixels ), 
       
  3160                                  scrolledPixels > 0 ? EMsgScrollUp :
       
  3161                                                       EMsgScrollDown,
       
  3162                                  EFalse );
       
  3163                     }
       
  3164                 }
       
  3165             
       
  3166             TInt pixelsScrolled = iViewFocusPosition - AknScrollBarModel()->FocusPosition();
       
  3167             TMsgScrollDirection scrollDirection = pixelsScrolled > 0 ? EMsgScrollUp : EMsgScrollDown;
       
  3168 
       
  3169             // If scrolled position is outside of visible part, then there is no need to 
       
  3170             // reset thumb position and no page number pop-up need be shown.
       
  3171             if ( ( currentPart != iVisiblePart ) &&
       
  3172                  EnsureVisiblePartScrollComplete ( AknScrollBarModel()->FocusPosition(), scrollDirection ) )
       
  3173                 {
       
  3174                 // Thumb position is forced to the top most position of currently scrolled slide.
       
  3175                 TInt currentHeight( 0 );
       
  3176                 TInt screenHeight = MsgEditorCommons::EditorViewHeigth() - iBaseLineOffset;
       
  3177                 TInt singlePartHeight = Max( screenHeight, iVisiblePartHeight / 10 );
       
  3178 
       
  3179                 for ( TInt current = 0; current < currentPart; current++ )
       
  3180                     {
       
  3181                     if ( current == iVisiblePart )
       
  3182                         {
       
  3183                         currentHeight += iVisiblePartHeight;
       
  3184                         }
       
  3185                     else
       
  3186                         {
       
  3187                         currentHeight += singlePartHeight;
       
  3188                         }
       
  3189                     }
       
  3190                 
       
  3191                 iScrollBar->DrawBackground( ETrue, EFalse );
       
  3192                 iScrollBar->SetVFocusPosToThumbPos( currentHeight + screenHeight/20 );
       
  3193                 
       
  3194                 if ( currentPart != iPopUpPart )
       
  3195                     {
       
  3196                     ShowScrollPopupInfoTextL( static_cast<CAknDoubleSpanScrollBar*>( aScrollBar ), 
       
  3197                                               currentPart + 1 );
       
  3198                     iPopUpPart = currentPart;
       
  3199                     }
       
  3200                 }
       
  3201             else
       
  3202                 {
       
  3203                 iScrollBar->DrawScrollBarsNow();
       
  3204                 }
       
  3205             break;
       
  3206             }
       
  3207         default:
       
  3208             {
       
  3209             break;
       
  3210             }
       
  3211         }
       
  3212     }
       
  3213 #else
       
  3214 void CMsgEditorView::HandleScrollEventL( CEikScrollBar* /*aScrollBar*/, 
       
  3215                                          TEikScrollEvent /*aEventType*/ )
       
  3216     {
       
  3217     }
       
  3218 #endif // RD_SCALABLE_UI_V2
       
  3219 
       
  3220 // ---------------------------------------------------------
       
  3221 // CMsgEditorView::ScrollL
       
  3222 //
       
  3223 // Scroll text in current part (slide)
       
  3224 // ---------------------------------------------------------
       
  3225 //
       
  3226 TInt CMsgEditorView::ScrollL(TInt aScrolledPixels)
       
  3227     {
       
  3228     TInt scrolledPixels = aScrolledPixels;
       
  3229     TInt focusPos = iViewFocusPosition;
       
  3230     TInt currentPart( CurrentScrollPart( AknScrollBarModel()->FocusPosition() ) );
       
  3231 
       
  3232     if ( currentPart == iVisiblePart )
       
  3233         {
       
  3234         if ( iPopUpPart != -1 )
       
  3235             {
       
  3236             // Hide the popup if visible
       
  3237             static_cast<CAknDoubleSpanScrollBar*>( iScrollBar->VerticalScrollBar() )->SetScrollPopupInfoTextL( KNullDesC );
       
  3238             iPopUpPart = -1;
       
  3239             }    
       
  3240         }
       
  3241 
       
  3242     if ( iPopUpPart == -1 )
       
  3243         {
       
  3244         // Round to the previous full line.
       
  3245         MsgEditorCommons::RoundToPreviousLine( scrolledPixels, iLineHeight );
       
  3246     
       
  3247         if ( scrolledPixels != 0 )
       
  3248             {
       
  3249             ScrollViewL( Abs( scrolledPixels ), scrolledPixels>0?EMsgScrollUp:EMsgScrollDown, EFalse );
       
  3250             EnsureCorrectScrollPartL( AknScrollBarModel()->FocusPosition() );
       
  3251             }
       
  3252         }
       
  3253     
       
  3254     TInt pixelsScrolled = iViewFocusPosition - AknScrollBarModel()->FocusPosition();
       
  3255     TMsgScrollDirection scrollDirection = pixelsScrolled > 0 ? EMsgScrollUp : EMsgScrollDown;
       
  3256 
       
  3257     // If scrolled position is outside of visible part, then there is no need to 
       
  3258     // reset thumb position and no page number pop-up need be shown.
       
  3259     if ( (currentPart!=iVisiblePart) && EnsureVisiblePartScrollComplete ( AknScrollBarModel()->FocusPosition(), scrollDirection ) )
       
  3260         {
       
  3261         // Thumb position is forced to the top most position of currently scrolled slide.
       
  3262         TInt currentHeight( 0 );
       
  3263         //TInt screenHeight = iViewRect.Height() - iBaseLineOffset;
       
  3264         TInt screenHeight = MsgEditorCommons::EditorViewHeigth() - iBaseLineOffset;
       
  3265         TInt singlePartHeight = Max( screenHeight, iVisiblePartHeight / 10 );
       
  3266 
       
  3267         for ( TInt current = 0; current < currentPart; current++ )
       
  3268             {
       
  3269             if ( current == iVisiblePart )
       
  3270                 {
       
  3271                 currentHeight += iVisiblePartHeight;
       
  3272                 }
       
  3273             else
       
  3274                 {
       
  3275                 currentHeight += singlePartHeight;
       
  3276                 }
       
  3277             }
       
  3278         
       
  3279         iScrollBar->DrawBackground( ETrue, EFalse );
       
  3280         iScrollBar->SetVFocusPosToThumbPos( currentHeight );
       
  3281         
       
  3282         if ( currentPart != iPopUpPart )
       
  3283             {
       
  3284             ShowScrollPopupInfoTextL( static_cast<CAknDoubleSpanScrollBar*>( iScrollBar->VerticalScrollBar() ), 
       
  3285                                       currentPart + 1 );
       
  3286             iPopUpPart = currentPart;
       
  3287             }
       
  3288         }
       
  3289     else
       
  3290         {
       
  3291         iScrollBar->SetVFocusPosToThumbPos( iViewFocusPosition );
       
  3292         iScrollBar->DrawScrollBarsNow();
       
  3293         }
       
  3294 
       
  3295     return (focusPos - iViewFocusPosition);
       
  3296     }
       
  3297 
       
  3298 // ---------------------------------------------------------
       
  3299 // CMsgEditorView::Draw
       
  3300 // Draws skin background for the view area. With video control
       
  3301 // this should not be done since we might accidentally draw over
       
  3302 // the video frame. In this case we only draw around the video control
       
  3303 // and let the video control draw its own background when approriate.
       
  3304 // ---------------------------------------------------------
       
  3305 //
       
  3306 void CMsgEditorView::Draw( const TRect& aRect ) const
       
  3307     {
       
  3308     CWindowGc& gc = SystemGc();
       
  3309     
       
  3310     CMsgBaseControl* videoControl = iBody->Component( EMsgComponentIdVideo );
       
  3311     
       
  3312     TBool backgroundDrawn( EFalse );
       
  3313     if ( !videoControl )
       
  3314         {
       
  3315         backgroundDrawn = AknsDrawUtils::Background( 
       
  3316                                      AknsUtils::SkinInstance(), 
       
  3317                                      AknsDrawUtils::ControlContext( this ), 
       
  3318                                      this, 
       
  3319                                      gc, 
       
  3320                                      aRect );
       
  3321         }
       
  3322     else
       
  3323         {
       
  3324         backgroundDrawn = AknsDrawUtils::BackgroundBetweenRects( 
       
  3325                                                      AknsUtils::SkinInstance(), 
       
  3326                                                      AknsDrawUtils::ControlContext( this ), 
       
  3327                                                      this, 
       
  3328                                                      gc, 
       
  3329                                                      aRect,
       
  3330                                                      videoControl->Rect() );
       
  3331         }
       
  3332 
       
  3333         
       
  3334     if ( !backgroundDrawn )
       
  3335         {
       
  3336         gc.SetBrushColor( AKN_LAF_COLOR( 0 ) );
       
  3337         gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
       
  3338         gc.SetPenStyle( CGraphicsContext::ENullPen );
       
  3339         gc.DrawRect( aRect );
       
  3340         }
       
  3341     }
       
  3342     
       
  3343 // ---------------------------------------------------------
       
  3344 // CMsgEditorView::ReportFocusMovement
       
  3345 //
       
  3346 // ---------------------------------------------------------
       
  3347 //
       
  3348 void CMsgEditorView::ReportFocusMovement( TInt aFocusEvent )
       
  3349     {
       
  3350     CMsgBaseControl* ctrl = FocusedControl();
       
  3351     
       
  3352     TInt controlId = ctrl ? ctrl->ControlId() : 
       
  3353                      EMsgComponentIdNull;
       
  3354                      
       
  3355     iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgHandleFocusChange,
       
  3356                                     &aFocusEvent,
       
  3357                                     &controlId,
       
  3358                                     NULL );
       
  3359     }
       
  3360 
       
  3361 // ---------------------------------------------------------
       
  3362 // CMsgEditorView::ControlFromPosition
       
  3363 //
       
  3364 // ---------------------------------------------------------
       
  3365 //
       
  3366 CMsgBaseControl* CMsgEditorView::ControlFromPosition( TPoint aPosition, 
       
  3367                                                       TBool aEvaluateHitTest ) const
       
  3368     {
       
  3369     CMsgBaseControl* control = NULL;
       
  3370     
       
  3371     if ( iHeader->Rect().Contains( aPosition ) )
       
  3372         {
       
  3373         control = iHeader->ControlFromPosition( aPosition, aEvaluateHitTest );
       
  3374         }
       
  3375     else
       
  3376         {
       
  3377         control = iBody->ControlFromPosition( aPosition, aEvaluateHitTest );
       
  3378         }
       
  3379         
       
  3380     return control;
       
  3381     }
       
  3382 
       
  3383 // ---------------------------------------------------------
       
  3384 // CMsgEditorView::EnsureVisiblePartScrollComplete
       
  3385 //
       
  3386 // Description
       
  3387 // ---------------------------------------------------------
       
  3388 
       
  3389 TBool CMsgEditorView::EnsureVisiblePartScrollComplete( TInt aFocusPosition,
       
  3390                                                        TMsgScrollDirection aDirection )
       
  3391     {
       
  3392     MEBLOGGER_ENTERFN( "CMsgEditorView::EnsureVisiblePartScrollComplete" );
       
  3393     TInt scrollTillPosition( 0 );
       
  3394     TBool result = ETrue;
       
  3395     
       
  3396     TInt screenHeight = MsgEditorCommons::EditorViewHeigth() - iBaseLineOffset;
       
  3397     TInt singlePartHeight = Max( screenHeight, iVisiblePartHeight / 10 );
       
  3398 
       
  3399     for ( TInt current = 0; current < iVisiblePart ; current++ )
       
  3400         scrollTillPosition += singlePartHeight;
       
  3401     
       
  3402     if ( aDirection == EMsgScrollDown )
       
  3403         {
       
  3404         scrollTillPosition += iVisiblePartHeight;
       
  3405 
       
  3406         if ( aFocusPosition < scrollTillPosition )
       
  3407             result = EFalse;
       
  3408         }
       
  3409     else
       
  3410         {
       
  3411         if ( aFocusPosition > scrollTillPosition )
       
  3412             result = EFalse;
       
  3413         }
       
  3414     
       
  3415     MEBLOGGER_LEAVEFN( "CMsgEditorView::EnsureVisiblePartScrollComplete" );
       
  3416     return result;
       
  3417     }
       
  3418 
       
  3419 // ---------------------------------------------------------
       
  3420 // CMsgEditorView::ScrollViewL
       
  3421 //
       
  3422 // First bound check is made so that no scrolling below minimum &
       
  3423 // above maximum is performed. This might happen with out check
       
  3424 // when using scrollbar arrows. DoScrollViewL function is called
       
  3425 // to perform the real scrolling. After all scrolling is done we 
       
  3426 // move the thumb position if this is requested by the caller.
       
  3427 // ---------------------------------------------------------
       
  3428 //
       
  3429 void CMsgEditorView::ScrollViewL( TInt aPixelsToScroll, 
       
  3430                                   TMsgScrollDirection aDirection, 
       
  3431                                   TBool aMoveThumb )
       
  3432     {
       
  3433     MEBLOGGER_ENTERFN( "CMsgEditorView::ScrollViewL" );
       
  3434     
       
  3435     const TAknDoubleSpanScrollBarModel* model = AknScrollBarModel();
       
  3436     
       
  3437     // Maximum value for thumb [0..scrollSpan]
       
  3438     TInt scrollSpan = model->ScrollSpan();
       
  3439     
       
  3440     // Position of the topmost part of the thumb
       
  3441     TInt thumbTopPos = iViewFocusPosition;
       
  3442     
       
  3443     // Position of the downmost part of the thumb
       
  3444     TInt thumbDownPos = thumbTopPos + model->WindowSize();
       
  3445     
       
  3446     // Bound check
       
  3447     if ( ( aDirection == EMsgScrollUp && thumbTopPos <= 0 ) ||
       
  3448          ( aDirection == EMsgScrollDown && thumbDownPos >= scrollSpan ) )
       
  3449         {
       
  3450         return;
       
  3451         }
       
  3452     
       
  3453     if ( CurrentScrollPart( iViewFocusPosition ) != iVisiblePart )
       
  3454         {
       
  3455         // No need to perform scrolling, if the visible part is completely
       
  3456         // scrolled and the new scroll position is outside the visible part
       
  3457         if ( EnsureVisiblePartScrollComplete ( iViewFocusPosition, aDirection ) )
       
  3458             return;
       
  3459         }
       
  3460     
       
  3461     DoScrollViewL( aPixelsToScroll, aDirection );
       
  3462             
       
  3463     if ( aMoveThumb )
       
  3464         {
       
  3465         // Scroll bar thumb is moved only if caller requests it. Scroll bar seems to
       
  3466         // add/subtract 1 pixel depending of direction.
       
  3467         TInt directionMultiplier( -1 );
       
  3468         if ( aDirection == EMsgScrollDown )
       
  3469             {
       
  3470             directionMultiplier = 1;
       
  3471             }
       
  3472         
       
  3473         iScrollBar->SetVFocusPosToThumbPos( model->FocusPosition() - 
       
  3474                                                 directionMultiplier * 1 + 
       
  3475                                                 directionMultiplier * aPixelsToScroll );
       
  3476         }
       
  3477     
       
  3478     MEBLOGGER_LEAVEFN( "CMsgEditorView::ScrollViewL" );
       
  3479     }
       
  3480 
       
  3481 // ---------------------------------------------------------
       
  3482 // CMsgEditorView::EnsureCorrectCursorPosition
       
  3483 //
       
  3484 // Ensures that cursor position relative to focus position
       
  3485 // on all controls is on correct position.
       
  3486 // ---------------------------------------------------------
       
  3487 //
       
  3488 void CMsgEditorView::EnsureCorrectCursorPosition()
       
  3489     {
       
  3490     CMsgFormComponent* currentForm = NULL;
       
  3491     if ( iCurrentFocus == EMsgHeaderFocused )
       
  3492         {
       
  3493         iBody->NotifyControlsForEvent( EMsgViewEventSetCursorFirstPos, 0 );
       
  3494         currentForm = iHeader;
       
  3495         }
       
  3496     else
       
  3497         {
       
  3498         iHeader->NotifyControlsForEvent( EMsgViewEventSetCursorLastPos, 0 );
       
  3499         currentForm = iBody;
       
  3500         }
       
  3501     
       
  3502     TInt componentIndex = currentForm->ComponentIndexFromId( currentForm->FocusedControl()->ControlId() );
       
  3503     
       
  3504     for ( TInt current = 0; current < currentForm->CountMsgControls(); current++ )
       
  3505         { 
       
  3506         CMsgBaseControl* control = currentForm->MsgControl( current );
       
  3507         TInt currentIndex = currentForm->ComponentIndexFromId( control->ControlId() );
       
  3508         if (  currentIndex < componentIndex )
       
  3509             {
       
  3510             control->NotifyViewEvent( EMsgViewEventSetCursorLastPos, 0 );
       
  3511             }
       
  3512         else if ( currentIndex > componentIndex )
       
  3513             {
       
  3514             control->NotifyViewEvent( EMsgViewEventSetCursorFirstPos, 0 );
       
  3515             }
       
  3516         }
       
  3517     }
       
  3518 
       
  3519 // ---------------------------------------------------------
       
  3520 // CMsgEditorView::EnsureCorrectScrollPartL
       
  3521 //
       
  3522 // Ensures that correct scroll part is visible. Performs scroll
       
  3523 // part change if focus position is outside of currently visible scroll
       
  3524 // part.
       
  3525 // ---------------------------------------------------------
       
  3526 //
       
  3527 void CMsgEditorView::EnsureCorrectScrollPartL( TInt aFocusPosition )
       
  3528     {
       
  3529     TInt currentPart( CurrentScrollPart( aFocusPosition ) );
       
  3530     if ( currentPart != iVisiblePart )
       
  3531         {
       
  3532         MMsgEditorObserver::TMsgFocusEvent focusEvent = MMsgEditorObserver::EMsgFocusNone;
       
  3533         
       
  3534         if ( currentPart > iVisiblePart )
       
  3535             {
       
  3536             focusEvent = MMsgEditorObserver::EMsgFocusAtBottom;
       
  3537             }
       
  3538         else
       
  3539             {
       
  3540             focusEvent = MMsgEditorObserver::EMsgFocusAtTop;
       
  3541             }
       
  3542         
       
  3543         MMsgEditorObserver::TMsgAfterFocusEventFunc after = 
       
  3544                                         MMsgEditorObserver::EMsgAfterFocusNone;
       
  3545         
       
  3546         iVisiblePart = currentPart;
       
  3547         iEditorObserver.EditorObserver( MMsgEditorObserver::EMsgHandleFocusChange,
       
  3548                                         &focusEvent,
       
  3549                                         &after,
       
  3550                                         &iVisiblePart );
       
  3551         
       
  3552         if ( after != MMsgEditorObserver::EMsgAfterFocusNone )
       
  3553             {
       
  3554             SetAfterFocusL( after );
       
  3555             }
       
  3556     
       
  3557         EnsureCorrectFormPosition( EFalse, EFalse );
       
  3558 
       
  3559         UpdateScrollBarL();
       
  3560         }
       
  3561     }
       
  3562 
       
  3563 // ---------------------------------------------------------
       
  3564 // CMsgEditorView::CurrentScrollPart
       
  3565 // 
       
  3566 // Calculates the correct scroll part of the given focus position.
       
  3567 // Current scroll part is evaluated based on position of top & bottom
       
  3568 // of the view rectangle. If either one of the borders are on the
       
  3569 // different scroll part than visible part then that part is returned
       
  3570 // as current part.
       
  3571 // ---------------------------------------------------------
       
  3572 //
       
  3573 TInt CMsgEditorView::CurrentScrollPart( TInt aFocusPosition )
       
  3574     {
       
  3575     TInt result( 0 );
       
  3576     
       
  3577     TInt currentHeight( 0 );
       
  3578     TInt topPart( -1 );
       
  3579     TInt bottomPart( -1 );
       
  3580     
       
  3581     TInt topPosition( aFocusPosition );
       
  3582     
       
  3583     TInt screenHeight = MsgEditorCommons::EditorViewHeigth() - iBaseLineOffset;
       
  3584     TInt singlePartHeight = Max( screenHeight, iVisiblePartHeight / 10 );
       
  3585 
       
  3586     for ( TInt current = 0; current < iScrollParts; current++ )
       
  3587         {
       
  3588         if ( current == iVisiblePart )
       
  3589             {
       
  3590             currentHeight += iVisiblePartHeight;
       
  3591             bottomPart = current;
       
  3592             }
       
  3593         else
       
  3594             {
       
  3595             currentHeight += singlePartHeight;
       
  3596             }
       
  3597         
       
  3598         if ( topPart == -1 &&
       
  3599              topPosition < currentHeight )
       
  3600             {
       
  3601             topPart = current;
       
  3602             }
       
  3603         
       
  3604         }
       
  3605     
       
  3606     if ( topPart == -1 )
       
  3607         {
       
  3608         topPart = iScrollParts - 1;
       
  3609         }
       
  3610     
       
  3611     if ( bottomPart == -1 )
       
  3612         {
       
  3613         bottomPart = iScrollParts - 1;
       
  3614         }
       
  3615     
       
  3616     if ( topPart == bottomPart )
       
  3617         {
       
  3618         result = topPart;
       
  3619         }
       
  3620     else
       
  3621         {
       
  3622         if ( topPart != iVisiblePart )
       
  3623             {
       
  3624             result = topPart;
       
  3625             }
       
  3626         else
       
  3627             {
       
  3628             result = bottomPart;
       
  3629             }
       
  3630         }
       
  3631     return result;
       
  3632     }  
       
  3633 
       
  3634 // ---------------------------------------------------------
       
  3635 // CMsgEditorView::IsFocusable
       
  3636 // 
       
  3637 // Determines if given control should receive focus when navigating
       
  3638 // into given direction.
       
  3639 //
       
  3640 // On editor mode (i.e. non read-only) every control is focusable.
       
  3641 //
       
  3642 // On viewer mode (i.e. read-only) control is focusable if:
       
  3643 // - force focus stop flag is set to control, 
       
  3644 // - control is not fully visible on the screen,
       
  3645 // - focus change to given direction is not allowed or
       
  3646 // - there is currently focused (i.e. currently shown and
       
  3647 //   highlighted) automatic finder item.
       
  3648 // ---------------------------------------------------------
       
  3649 //
       
  3650 TBool CMsgEditorView::IsFocusable( CMsgBaseControl* aControl,
       
  3651                                    TMsgFocusDirection aDirection ) const
       
  3652     {
       
  3653     if ( !aControl )
       
  3654         {
       
  3655         return EFalse;
       
  3656         }
       
  3657         
       
  3658     if ( aControl->IsReadOnly() )
       
  3659         {
       
  3660         if ( aControl->ControlModeFlags() & EMsgControlModeForceFocusStop ||
       
  3661              !ControlFullyVisible( aControl ) ||
       
  3662              !( aControl->IsFocusChangePossible( aDirection ) ) )
       
  3663             {
       
  3664             return ETrue;
       
  3665             }
       
  3666         else if ( aControl->ItemFinder() ) 
       
  3667             {
       
  3668             const CItemFinder::CFindItemExt& item = aControl->ItemFinder()->CurrentItemExt();
       
  3669             
       
  3670             if ( item.iItemType != CItemFinder::ENoneSelected )
       
  3671                 {
       
  3672                 return ETrue;
       
  3673                 }
       
  3674             }
       
  3675             
       
  3676         return EFalse;
       
  3677         }
       
  3678         
       
  3679     return ETrue;
       
  3680     }
       
  3681 
       
  3682 // ---------------------------------------------------------
       
  3683 // CMsgEditorView::ShowScrollPopupInfoTextL
       
  3684 //
       
  3685 // Loads the info text resouce if not yet loaded. Creates correct
       
  3686 // text string based on this resource and given part number.
       
  3687 // After this sets the created info text for the scroll bar.
       
  3688 // ---------------------------------------------------------
       
  3689 //
       
  3690 void CMsgEditorView::ShowScrollPopupInfoTextL( CAknDoubleSpanScrollBar* aScrollBar, TInt aPartNumber )
       
  3691     {
       
  3692     if ( !iScrollPopText )
       
  3693         {
       
  3694         if ( !iCoeEnv->IsResourceAvailableL( R_QTN_MSG_PAGE_NUMBER_POPUP ) )
       
  3695             {
       
  3696 	        // Load the resource file containing page number popup if it has not yet
       
  3697 	        // been loaded. This should not happen but better to be prepared for that also.
       
  3698 	        TParse parse;
       
  3699             User::LeaveIfError( parse.Set( KMsgEditorAppUiResourceFileName, 
       
  3700                                            &KDC_RESOURCE_FILES_DIR, 
       
  3701                                            NULL ) );
       
  3702         
       
  3703             TFileName* fileName = new( ELeave ) TFileName( parse.FullName() );
       
  3704             CleanupStack::PushL( fileName );
       
  3705         
       
  3706             iResourceLoader.OpenL( *fileName );
       
  3707         
       
  3708             CleanupStack::PopAndDestroy( fileName );
       
  3709 	        }
       
  3710     
       
  3711         iScrollPopText = StringLoader::LoadL( R_QTN_MSG_PAGE_NUMBER_POPUP, iCoeEnv );
       
  3712         }
       
  3713     
       
  3714     TBuf<KMsgMaximumScrollPartLength> buffer;
       
  3715     StringLoader::Format( buffer, *iScrollPopText, KErrNotFound, aPartNumber );
       
  3716 
       
  3717     aScrollBar->SetScrollPopupInfoTextL( buffer );
       
  3718     }
       
  3719 
       
  3720 // ---------------------------------------------------------
       
  3721 // CMsgEditorView::EnsureCorrectViewPosition
       
  3722 // ---------------------------------------------------------
       
  3723 //
       
  3724 void CMsgEditorView::EnsureCorrectViewPosition()
       
  3725     {
       
  3726     CMsgBaseControl* firstHeaderControl = iHeader->CountMsgControls() > 0 ? iHeader->MsgControl( 0 ) : NULL;
       
  3727 
       
  3728     CMsgBaseControl* lastControlBody = iBody->CountMsgControls() > 0 ? 
       
  3729                                                     iBody->MsgControl( iBody->CountMsgControls() - 1 ) : NULL;
       
  3730     
       
  3731     if ( firstHeaderControl &&
       
  3732          firstHeaderControl->Position().iY > iBaseLineOffset )
       
  3733         {
       
  3734         TInt pixelsToScroll( firstHeaderControl->Position().iY - iBaseLineOffset );
       
  3735         TRAP_IGNORE( DoScrollViewL( pixelsToScroll, 
       
  3736                                     EMsgScrollDown ) );
       
  3737         }
       
  3738     else if ( lastControlBody && 
       
  3739               lastControlBody->Rect().iBr.iY <= iViewRect.Height() - iLineHeight )
       
  3740         {
       
  3741         TInt pixelsToScroll( iViewRect.Height() - lastControlBody->Rect().iBr.iY );
       
  3742         TRAP_IGNORE( DoScrollViewL( pixelsToScroll, 
       
  3743                                     EMsgScrollUp ) );
       
  3744         }
       
  3745     else
       
  3746         {         
       
  3747         
       
  3748       	CMsgBaseControl* ctrl = FocusedControl();
       
  3749         if (( ctrl && ctrl->ControlModeFlags() & EMsgControlModeBodyMaxHeight) &&  ctrl->VirtualHeight() < MsgEditorCommons::MaxBodyHeight() )
       
  3750             {
       
  3751              // Special handling is required when we rotate the phone from 
       
  3752              // landscape to portrait or vice versa when the Editor is placed last 
       
  3753              TInt bottomYPos( ctrl->Position().iY + ctrl->VirtualHeight() );          
       
  3754              TInt distanceFromBottom( Rect().iBr.iY - bottomYPos );
       
  3755     
       
  3756              if ( distanceFromBottom > 0 )
       
  3757                 {
       
  3758                 TInt delta = Abs( iFormOffset ) < distanceFromBottom ? -iFormOffset :
       
  3759                                                                            distanceFromBottom;                    
       
  3760                 if ( delta )
       
  3761                     {
       
  3762                      ScrollForm( delta, ETrue );
       
  3763                     }
       
  3764                  }               
       
  3765                  if ( ViewInitialized() )
       
  3766                     {
       
  3767                		TRAP_IGNORE(UpdateScrollBarL());
       
  3768                     }
       
  3769                     
       
  3770             }
       
  3771         else if( ctrl )
       
  3772         	{
       
  3773         	TInt height( 0 );
       
  3774         	TInt pos( 0 );   
       
  3775     
       
  3776         	GetVirtualFormHeightAndPos( height, pos );
       
  3777         	if(!ControlFullyVisible( ctrl ) &&  height > iViewRect.Height() )
       
  3778             	{
       
  3779                	TInt controlPixels(  Abs(ctrl->Position().iY  ));                                                  
       
  3780                	MsgEditorCommons::RoundToPreviousLine( controlPixels, iLineHeight );
       
  3781                	TRAP_IGNORE(DoScrollViewL(controlPixels,EMsgScrollDown));  
       
  3782            		}	
       
  3783         	}                      
       
  3784        	}     
       
  3785     }
       
  3786 
       
  3787 // ---------------------------------------------------------
       
  3788 // CMsgEditorView::DoScrollViewL
       
  3789 //
       
  3790 // First & last loaded control is
       
  3791 // needed in order to do bound checking so that empty space above
       
  3792 // or below loaded controls isn't shown. Actual scrolling is performed
       
  3793 // so that control from first or last visible (depends about the
       
  3794 // scrolling direction) line is retrieved. If this control isn't fully
       
  3795 // visible on the scroll we try to move it as much visible as allowed
       
  3796 // by the scrollable pixels. When the control is fully visible it can
       
  3797 // perform internal scrolling if needed. When it has finished internal
       
  3798 // scrolling then we move the view one line up or down. This is continued
       
  3799 // as long as there is pixels left. After all scrolling is done we 
       
  3800 // update our internal view focus position
       
  3801 // that keeps count where the focus position on the view is really
       
  3802 // located. Finally we draw the screen if needed.
       
  3803 // ---------------------------------------------------------
       
  3804 //
       
  3805 void CMsgEditorView::DoScrollViewL( TInt& aPixelsToScroll, 
       
  3806                                     TMsgScrollDirection aDirection )
       
  3807     {
       
  3808     MEBLOGGER_ENTERFN( "CMsgEditorView::DoScrollViewL" );
       
  3809     
       
  3810     TInt pixelsLeftToScroll( aPixelsToScroll );
       
  3811     
       
  3812     TInt directionMultiplier( -1 );
       
  3813     if ( aDirection == EMsgScrollDown )
       
  3814         {
       
  3815         directionMultiplier = 1;
       
  3816         }
       
  3817     
       
  3818     CMsgBaseControl* firstControl = iHeader->CountMsgControls() > 0 ? iHeader->MsgControl( 0 ) :
       
  3819                                                                       iBody->MsgControl( 0 );
       
  3820     
       
  3821     CMsgBaseControl* lastControl = iBody->CountMsgControls() > 0 ? 
       
  3822                                         iBody->MsgControl( iBody->CountMsgControls() - 1 ) :
       
  3823                                         iHeader->MsgControl( iHeader->CountMsgControls() - 1 );
       
  3824     
       
  3825     while ( pixelsLeftToScroll > 0 )
       
  3826         {
       
  3827         MEBLOGGER_WRITEF(_L("MEB: CMsgEditorView::DoScrollViewL: pixelsLeftToScroll %d "), pixelsLeftToScroll );
       
  3828         
       
  3829         CMsgBaseControl* scrolledControl = NULL;
       
  3830        
       
  3831         if ( aDirection == EMsgScrollUp )
       
  3832             {
       
  3833             // Control located at first visible line
       
  3834             scrolledControl = ControlFromPosition( TPoint( iViewRect.Width() / 2, iLineHeight / 2 + iBaseLineOffset ), EFalse );
       
  3835             }
       
  3836         else
       
  3837             {
       
  3838             // Control located at last visible line
       
  3839             scrolledControl = ControlFromPosition( TPoint( iViewRect.Width() / 2, iViewRect.Height() - iLineHeight / 2 ), EFalse );
       
  3840             }
       
  3841     
       
  3842         if ( scrolledControl )
       
  3843             {
       
  3844             // Assumption: Control will make internal scrolling only if
       
  3845             // it's height is greater or equal to view height.
       
  3846             if ( !ControlFullyVisible( scrolledControl ) )
       
  3847                 {   
       
  3848                 // Calculate how many pixels needs to be scrolled in order
       
  3849                 // to control be fully visible.
       
  3850                 TInt controlPixels( Abs( scrolledControl->Position().iY ) );
       
  3851                 
       
  3852                 if ( aDirection == EMsgScrollDown )
       
  3853                     {
       
  3854                     // Round to the previous full line.
       
  3855                     MsgEditorCommons::RoundToPreviousLine( controlPixels, iLineHeight );
       
  3856                     }
       
  3857                 else 
       
  3858                     {
       
  3859                     // Round to the next full line.
       
  3860                     MsgEditorCommons::RoundToNextLine( controlPixels, iLineHeight );
       
  3861                     }
       
  3862                 
       
  3863                 // Scroll form so that control is fully visible or
       
  3864                 // at minimum one line height and at maximum pixels left to scroll.
       
  3865                 TInt scrollFormByPixels = Max( iLineHeight, Min( pixelsLeftToScroll, 
       
  3866                                                                  controlPixels ) );                    
       
  3867                 
       
  3868                 TInt oldYPos( scrolledControl->Position().iY );
       
  3869                 
       
  3870                 // To disable drawing in the middle of scrolling.
       
  3871                 iStateFlags |= EMsgStateRefreshing;
       
  3872                 
       
  3873                 if ( CurrentScrollPart( iViewFocusPosition - aPixelsToScroll + pixelsLeftToScroll + directionMultiplier * scrollFormByPixels ) != iVisiblePart )
       
  3874                     {
       
  3875                     // Do not scroll form if scrolling would make scroll part change.
       
  3876                     break;
       
  3877                     }
       
  3878                 
       
  3879                 ScrollForm( -directionMultiplier * scrollFormByPixels, EFalse );
       
  3880                 
       
  3881                 // Substract the pixels really moved.
       
  3882                 pixelsLeftToScroll -= Abs( oldYPos - scrolledControl->Position().iY );
       
  3883                 
       
  3884                 MEBLOGGER_WRITEF(_L("MEB: CMsgEditorView::DoScrollViewL: pixelsLeftToScroll after fully visible %d "), pixelsLeftToScroll );
       
  3885                 }
       
  3886             
       
  3887             if ( pixelsLeftToScroll > 0 )
       
  3888                 {
       
  3889                 // Perform internal scrolling for the control if there is still pixels left to scroll.
       
  3890                 pixelsLeftToScroll -= scrolledControl->ScrollL( pixelsLeftToScroll, aDirection );
       
  3891                 
       
  3892                 MEBLOGGER_WRITEF(_L("MEB: CMsgEditorView::DoScrollViewL: pixelsLeftToScroll after internal scrolling %d "), pixelsLeftToScroll );
       
  3893                 }
       
  3894             }
       
  3895         
       
  3896         // After component's internal scrolling there is still some pixels left to scroll
       
  3897         // move the view to correction direction one line.
       
  3898         if ( pixelsLeftToScroll > 0 )
       
  3899             {
       
  3900             // Boundary check for form scrolling. Do not scroll up (down) if first (last) control is
       
  3901             // fully visible. Also do not scroll form if scrolling would make scroll part change.
       
  3902             
       
  3903             TBool needScroll = EFalse;
       
  3904             TInt height = iViewRect.Height(); 
       
  3905 
       
  3906             if(aDirection == EMsgScrollDown)
       
  3907                 {
       
  3908                 TInt length = lastControl->Rect().iBr.iY;
       
  3909                 needScroll = (length > height);
       
  3910                 }
       
  3911             else
       
  3912                 {
       
  3913                 TInt length = firstControl->Rect().iTl.iY;
       
  3914                 needScroll = (length < height);
       
  3915                 }
       
  3916             
       
  3917             TBool isCurrent = (CurrentScrollPart( iViewFocusPosition - aPixelsToScroll + pixelsLeftToScroll + directionMultiplier * iLineHeight ) == iVisiblePart);
       
  3918 
       
  3919             if ( needScroll && isCurrent )
       
  3920                 {
       
  3921                 
       
  3922                 if ( pixelsLeftToScroll > 0 )
       
  3923                     {
       
  3924                     // To disable drawing in the middle of scrolling.
       
  3925                     iStateFlags |= EMsgStateRefreshing;
       
  3926                     
       
  3927                     ScrollForm( -directionMultiplier * iLineHeight, EFalse );
       
  3928                     pixelsLeftToScroll -= iLineHeight;
       
  3929                     
       
  3930                     MEBLOGGER_WRITEF(_L("MEB: CMsgEditorView::DoScrollViewL: pixelsLeftToScroll after single scrolling %d "), pixelsLeftToScroll );
       
  3931                     
       
  3932                     }
       
  3933                 }
       
  3934             else                
       
  3935                 {
       
  3936                 break;                    
       
  3937                 }
       
  3938             }
       
  3939         }
       
  3940         
       
  3941     iViewFocusPosition += directionMultiplier * ( aPixelsToScroll - pixelsLeftToScroll );
       
  3942     
       
  3943     if ( iStateFlags & EMsgStateRefreshing )
       
  3944         {
       
  3945         iStateFlags &= ~EMsgStateRefreshing;
       
  3946         DrawNow();
       
  3947         }
       
  3948     
       
  3949     MEBLOGGER_LEAVEFN( "CMsgEditorView::ScrollViewL" );
       
  3950     }
       
  3951 
       
  3952 
       
  3953 // End of File