messagingappbase/msgeditor/viewsrc/MsgFormComponent.cpp
changeset 0 72b543305e3a
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     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:  MsgFormComponent implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // ========== INCLUDE FILES ================================
       
    21 #include <AknUtils.h>                      // for AknUtils
       
    22 #include <AknDef.h>
       
    23 
       
    24 #include "MsgFormComponent.h"              // for CMsgFormComponent
       
    25 #include "MsgControlArray.h"               // for CMsgControlArray
       
    26 #include "MsgBaseControl.h"                // for CMsgBaseControl
       
    27 #include "MsgEditorPanic.h"                // for CMsgEditor panics
       
    28 #include "MsgEditorCommon.h"
       
    29 
       
    30 // ========== EXTERNAL DATA STRUCTURES =====================
       
    31 
       
    32 // ========== EXTERNAL FUNCTION PROTOTYPES =================
       
    33 
       
    34 // ========== CONSTANTS ====================================
       
    35 
       
    36 // ========== MACROS =======================================
       
    37 
       
    38 // ========== LOCAL CONSTANTS AND MACROS ===================
       
    39 
       
    40 const TInt KComponentArrayGranularity = 5;
       
    41 const TInt ENoFocus = -1;
       
    42 
       
    43 // ========== MODULE DATA STRUCTURES =======================
       
    44 
       
    45 // ========== LOCAL FUNCTION PROTOTYPES ====================
       
    46 
       
    47 // ========== LOCAL FUNCTIONS ==============================
       
    48 
       
    49 // ========== MEMBER FUNCTIONS =============================
       
    50 
       
    51 // ---------------------------------------------------------
       
    52 // CMsgFormComponent::CMsgFormComponent
       
    53 //
       
    54 // Constructor.
       
    55 // ---------------------------------------------------------
       
    56 //
       
    57 CMsgFormComponent::CMsgFormComponent( const TMargins& aMargins ) : 
       
    58     iCurrentFocus( ENoFocus ),
       
    59     iMargins( aMargins )
       
    60     {
       
    61     SetComponentsToInheritVisibility( ETrue );
       
    62     }
       
    63 
       
    64 // ---------------------------------------------------------
       
    65 // CMsgFormComponent::~CMsgFormComponent
       
    66 //
       
    67 // Destructor.
       
    68 // ---------------------------------------------------------
       
    69 //
       
    70 CMsgFormComponent::~CMsgFormComponent()
       
    71     {
       
    72     delete iControls;
       
    73     }
       
    74 
       
    75 // ---------------------------------------------------------
       
    76 // CMsgFormComponent::BaseConstructL
       
    77 //
       
    78 //
       
    79 // ---------------------------------------------------------
       
    80 //
       
    81 void CMsgFormComponent::BaseConstructL( const CCoeControl& aParent )
       
    82     {
       
    83     SetContainerWindowL( aParent );
       
    84     iControls = new ( ELeave ) CMsgControlArray( KComponentArrayGranularity );
       
    85     }
       
    86 
       
    87 // ---------------------------------------------------------
       
    88 // CMsgFormComponent::Component
       
    89 //
       
    90 // Return a pointer to a control by given control id aControlId. If the
       
    91 // control cannot be found returns NULL.
       
    92 // ---------------------------------------------------------
       
    93 //
       
    94 CMsgBaseControl* CMsgFormComponent::Component( TInt aControlId ) const
       
    95     {
       
    96     TInt index = ComponentIndexFromId( aControlId );
       
    97 
       
    98     if ( index == KErrNotFound )
       
    99         {
       
   100         return NULL;
       
   101         }
       
   102 
       
   103     return (*iControls)[index];
       
   104     }
       
   105 
       
   106 // ---------------------------------------------------------
       
   107 // CMsgFormComponent::ComponentIndexFromId
       
   108 //
       
   109 // Returns control's array index by given control id aControlId.
       
   110 // ---------------------------------------------------------
       
   111 //
       
   112 TInt CMsgFormComponent::ComponentIndexFromId( TInt aControlId ) const
       
   113     {
       
   114     return iControls->ComponentIndexFromId( aControlId );
       
   115     }
       
   116 
       
   117 // ---------------------------------------------------------
       
   118 // CMsgFormComponent::ControlFromPosition
       
   119 // ---------------------------------------------------------
       
   120 //
       
   121 #ifdef RD_SCALABLE_UI_V2
       
   122 CMsgBaseControl* CMsgFormComponent::ControlFromPosition( TPoint aPosition, TBool aEvaluateHitTest ) const
       
   123     {
       
   124     TInt componentCount = iControls->Count();
       
   125 
       
   126     for ( TInt index = 0; index < componentCount; index++ )
       
   127         {
       
   128         CMsgBaseControl* current = (*iControls)[index];
       
   129         if ( current->Rect().Contains( aPosition ) &&
       
   130              ( !aEvaluateHitTest ||
       
   131                ( !current->HitTest() ||
       
   132                  current->HitTest()->HitRegionContains( aPosition, *current ) ) ) )
       
   133             {
       
   134             return current;
       
   135             }
       
   136         }
       
   137     return NULL;
       
   138     }
       
   139 #else
       
   140 CMsgBaseControl* CMsgFormComponent::ControlFromPosition( TPoint /*aPosition*/, TBool /*aEvaluateHitTest*/ ) const
       
   141     {
       
   142     return NULL;
       
   143     }
       
   144 #endif // RD_SCALABLE_UI_V2
       
   145 
       
   146 
       
   147 // ---------------------------------------------------------
       
   148 // CMsgFormComponent::AddControlL
       
   149 //
       
   150 // Adds a control aControl to the control array to position aIndex and sets
       
   151 // control id for the control.
       
   152 // ---------------------------------------------------------
       
   153 //
       
   154 void CMsgFormComponent::AddControlL(
       
   155     CMsgBaseControl* aControl,
       
   156     TInt aControlId,
       
   157     TInt aIndex /* = 0*/ )
       
   158     {
       
   159     aControl->SetControlId( aControlId );
       
   160     DoAddControlL( aControl, aIndex );
       
   161     }
       
   162 
       
   163 // ---------------------------------------------------------
       
   164 // CMsgFormComponent::RemoveControlL
       
   165 //
       
   166 // Removes a control from array by given control id aControlId and returns
       
   167 // pointer to it. If the control cannot be found retuns NULL.
       
   168 // ---------------------------------------------------------
       
   169 //
       
   170 CMsgBaseControl* CMsgFormComponent::RemoveControlL( TInt aControlId )
       
   171     {
       
   172     CMsgBaseControl* control = NULL;
       
   173     TInt index = ComponentIndexFromId( aControlId );
       
   174 
       
   175     if ( index != KErrNotFound )
       
   176         {
       
   177         control = (*iControls)[index];
       
   178         control->SetFocus( EFalse );
       
   179         iControls->Delete( index );
       
   180 
       
   181         if ( index <= iCurrentFocus )
       
   182             {
       
   183             iCurrentFocus--;
       
   184             }
       
   185         
       
   186         if ( iControls->Count() == 0 )
       
   187             {
       
   188             iCurrentFocus = ENoFocus;
       
   189             }
       
   190         else if ( iCurrentFocus < 0 )
       
   191             {
       
   192             iCurrentFocus = 0;
       
   193             }
       
   194         }
       
   195 
       
   196     return control;
       
   197     }
       
   198 
       
   199 // ---------------------------------------------------------
       
   200 // CMsgFormComponent::Margins
       
   201 //
       
   202 // Returns margins.
       
   203 // ---------------------------------------------------------
       
   204 //
       
   205 TMargins CMsgFormComponent::Margins() const
       
   206     {
       
   207     return iMargins;
       
   208     }
       
   209 
       
   210 // ---------------------------------------------------------
       
   211 // CMsgFormComponent::CurrentLineRect
       
   212 //
       
   213 // Returns the current control rect.
       
   214 // ---------------------------------------------------------
       
   215 //
       
   216 TRect CMsgFormComponent::CurrentLineRect()
       
   217     {
       
   218     __ASSERT_DEBUG( ( iCurrentFocus < iControls->Count() ) &&
       
   219         ( iCurrentFocus != ENoFocus ), Panic( EMsgFocusLost ) );
       
   220 
       
   221     return (*iControls)[iCurrentFocus]->CurrentLineRect();
       
   222     }
       
   223 
       
   224 // ---------------------------------------------------------
       
   225 // CMsgFormComponent::ChangeFocusTo
       
   226 //
       
   227 // Changes focus to a control whose index is aNewFocus. Returns EFalse if focus
       
   228 // cannot be changed.
       
   229 // ---------------------------------------------------------
       
   230 //
       
   231 TBool CMsgFormComponent::ChangeFocusTo( TInt aNewFocus, TDrawNow aDrawNow /*= EDrawNow*/ )
       
   232     {
       
   233     __ASSERT_DEBUG( ( aNewFocus < iControls->Count() ) &&
       
   234         ( aNewFocus >= 0 ), Panic( EMsgFocusLost ) );
       
   235 
       
   236     if ( (*iControls)[aNewFocus]->IsNonFocusing() )
       
   237         {
       
   238         return EFalse;
       
   239         }
       
   240         
       
   241     if ( aNewFocus != iCurrentFocus )
       
   242         {
       
   243         // Take focus off from the currently focused component
       
   244         SetFocus( EFalse, aDrawNow );
       
   245         iCurrentFocus = aNewFocus;
       
   246         }
       
   247 
       
   248     SetFocus( ETrue, aDrawNow );
       
   249 
       
   250     return ETrue;
       
   251     }
       
   252 
       
   253 // ---------------------------------------------------------
       
   254 // CMsgFormComponent::FocusedControl
       
   255 //
       
   256 // Returns a pointer to the focused control. If focus not set returns NULL.
       
   257 // ---------------------------------------------------------
       
   258 //
       
   259 CMsgBaseControl* CMsgFormComponent::FocusedControl() const
       
   260     {
       
   261     TInt numberOfControls = iControls->Count();
       
   262 
       
   263     if ( ( iCurrentFocus != ENoFocus ) && ( iCurrentFocus < numberOfControls ) )
       
   264         {
       
   265         return (*iControls)[iCurrentFocus];
       
   266         }
       
   267     return NULL;
       
   268     }
       
   269 
       
   270 // ---------------------------------------------------------
       
   271 // CMsgFormComponent::FirstFocusableControl
       
   272 //
       
   273 // Finds the first focusable control and returns index of the found control
       
   274 // or KErrNotFound if the focusable control cannot be found.
       
   275 // ---------------------------------------------------------
       
   276 //
       
   277 TInt CMsgFormComponent::FirstFocusableControl( TInt aStart, TMsgFocusDirection aDirection )
       
   278     {
       
   279     TInt components = iControls->Count();
       
   280     TInt newFocus = aStart;
       
   281 
       
   282     while ( ( newFocus < components ) && ( newFocus >= 0 ) )
       
   283         {
       
   284         if ( (*iControls)[newFocus]->IsNonFocusing() )
       
   285             {
       
   286             newFocus += aDirection;
       
   287             }
       
   288         else
       
   289             {
       
   290             return newFocus;
       
   291             }
       
   292         }
       
   293 
       
   294     return KErrNotFound;
       
   295     }
       
   296 
       
   297 // ---------------------------------------------------------
       
   298 // CMsgFormComponent::NotifyControlsForEvent
       
   299 //
       
   300 // Notifies all the controls about a view event.
       
   301 // ---------------------------------------------------------
       
   302 //
       
   303 void CMsgFormComponent::NotifyControlsForEvent( TMsgViewEvent aEvent, TInt aParam )
       
   304     {
       
   305     TInt componentCount = iControls->Count();
       
   306 
       
   307     for ( TInt i = 0; i < componentCount; i++ )
       
   308         {
       
   309         (*iControls)[i]->NotifyViewEvent( aEvent, aParam );
       
   310         }
       
   311     }
       
   312 
       
   313 // ---------------------------------------------------------
       
   314 // CMsgFormComponent::CurrentFocus
       
   315 //
       
   316 // Returns index of currently focused control.
       
   317 // ---------------------------------------------------------
       
   318 //
       
   319 TInt CMsgFormComponent::CurrentFocus() const
       
   320     {
       
   321     return iCurrentFocus;
       
   322     }
       
   323 
       
   324 // ---------------------------------------------------------
       
   325 // CMsgFormComponent::ResetControls
       
   326 //
       
   327 // Reset all controls in this component.
       
   328 // ---------------------------------------------------------
       
   329 //
       
   330 void CMsgFormComponent::ResetControls()
       
   331     {
       
   332     TInt componentCount = iControls->Count();
       
   333 
       
   334     for (TInt i = 0; i < componentCount; i++)
       
   335         {
       
   336         (*iControls)[i]->Reset();
       
   337         }
       
   338     }
       
   339 
       
   340 // ---------------------------------------------------------
       
   341 // CMsgFormComponent::VirtualHeight
       
   342 //
       
   343 // Return virtual height of controls.
       
   344 // ---------------------------------------------------------
       
   345 //
       
   346 TInt CMsgFormComponent::VirtualHeight()
       
   347     {
       
   348     TInt numberOfControls = iControls->Count();
       
   349     TInt totalHeight = 0;
       
   350     CMsgBaseControl* ctrl;
       
   351 
       
   352     for ( TInt i = 0; i < numberOfControls; i++ )
       
   353         {
       
   354         ctrl = (*iControls)[i];
       
   355         totalHeight += ctrl->VirtualHeight();
       
   356         totalHeight += ctrl->DistanceFromComponentAbove();
       
   357         }
       
   358 
       
   359     return totalHeight + iMargins.iTop + iMargins.iBottom;
       
   360     }
       
   361 
       
   362 // ---------------------------------------------------------
       
   363 // CMsgFormComponent::VirtualExtension
       
   364 //
       
   365 // Returns total of pixels above each control' band. This function is
       
   366 // needed for the scroll bar for estimating message form's position
       
   367 // relative to screen.
       
   368 // ---------------------------------------------------------
       
   369 //
       
   370 TInt CMsgFormComponent::VirtualExtension()
       
   371     {
       
   372     TInt numberOfControls = iControls->Count();
       
   373     TInt pos = 0;
       
   374 
       
   375     if ( iCurrentFocus < numberOfControls && 
       
   376          iCurrentFocus != ENoFocus )
       
   377         {
       
   378         TInt offset = MsgEditorCommons::MsgBaseLineOffset();
       
   379         
       
   380         CMsgBaseControl* ctrl;
       
   381         for ( TInt i = 0; i <= iCurrentFocus; i++ )
       
   382             {
       
   383             ctrl = (*iControls)[i];
       
   384             
       
   385             if ( ctrl->Position().iY > offset )
       
   386                 {
       
   387                 break;
       
   388                 }
       
   389 
       
   390             pos += ctrl->DistanceFromComponentAbove();
       
   391             
       
   392             if ( ctrl->IsFocused() )
       
   393                 {
       
   394                 pos += ctrl->VirtualVisibleTop();
       
   395                 
       
   396                 TInt visiblePixels( ctrl->Position().iY + ctrl->Size().iHeight );
       
   397                 visiblePixels -= offset;
       
   398                 
       
   399                 if ( ctrl->Position().iY < 0 &&
       
   400                      visiblePixels > 0 )
       
   401                     {
       
   402                     pos += ( ctrl->Size().iHeight - visiblePixels );
       
   403                     }
       
   404                 }
       
   405             else
       
   406                 {
       
   407                 pos += ctrl->VirtualHeight();
       
   408                 
       
   409                 TInt visiblePixels( 0 );
       
   410                 
       
   411                 if ( ctrl->Position().iY < 0 )
       
   412                     {
       
   413                     visiblePixels = ctrl->Position().iY + ctrl->Size().iHeight - offset;
       
   414                     }
       
   415                 else
       
   416                     {
       
   417                     visiblePixels = ctrl->Size().iHeight;
       
   418                     }
       
   419                 
       
   420                 // If control is partially visible on the screen remove
       
   421                 // these pixels.
       
   422                 if ( visiblePixels > 0 )
       
   423                     {
       
   424                     pos -= visiblePixels;
       
   425                     }
       
   426                 }
       
   427             }
       
   428         }
       
   429     return pos;
       
   430     }
       
   431 
       
   432 // ---------------------------------------------------------
       
   433 // CMsgFormComponent::OfferKeyEventL
       
   434 //
       
   435 // Handles key event by passing the event to a focused control.
       
   436 // ---------------------------------------------------------
       
   437 //
       
   438 TKeyResponse CMsgFormComponent::OfferKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType )
       
   439     {
       
   440     __ASSERT_DEBUG( (iCurrentFocus < iControls->Count() ) &&
       
   441         ( iCurrentFocus != ENoFocus ), Panic( EMsgFocusLost ) );
       
   442 
       
   443     return static_cast<CCoeControl*>( (*iControls)[iCurrentFocus] )
       
   444         ->OfferKeyEventL( aKeyEvent, aType );
       
   445     }
       
   446 
       
   447 // ---------------------------------------------------------
       
   448 // CMsgFormComponent::CountComponentControls
       
   449 //
       
   450 // Returns a number of controls.
       
   451 // ---------------------------------------------------------
       
   452 //
       
   453 TInt CMsgFormComponent::CountComponentControls() const
       
   454     {
       
   455     return iControls->Count();
       
   456     }
       
   457 
       
   458 // ---------------------------------------------------------
       
   459 // CMsgFormComponent::ComponentControl
       
   460 //
       
   461 // Returns a control of index aIndex.
       
   462 // ---------------------------------------------------------
       
   463 //
       
   464 CCoeControl* CMsgFormComponent::ComponentControl( TInt aIndex ) const
       
   465     {
       
   466     if ( aIndex < iControls->Count() )
       
   467         {
       
   468         return ( (*iControls)[aIndex] );
       
   469         }
       
   470 
       
   471     __ASSERT_DEBUG(EFalse, Panic(EMsgIncorrectComponentIndex));
       
   472 
       
   473     return NULL;
       
   474     }
       
   475 
       
   476 // ---------------------------------------------------------
       
   477 // CMsgFormComponent::SizeChanged
       
   478 //
       
   479 // Sets new position for all the controls.
       
   480 //
       
   481 // SetExtent function must be used for setting positions because when this
       
   482 // is called the first time, positions are not set yet. Hence, SetPosition
       
   483 // cannot be used because it assumes that positions are already set.
       
   484 // ---------------------------------------------------------
       
   485 //
       
   486 void CMsgFormComponent::SizeChanged()
       
   487     {
       
   488     TPoint componentPosition(
       
   489         Position().iX + iMargins.iLeft,
       
   490         Position().iY + iMargins.iTop );
       
   491     CMsgBaseControl* component;
       
   492     TInt components( iControls->Count() );
       
   493     TSize componentSize;
       
   494 
       
   495     for ( TInt cc = 0; cc < components; cc++ )
       
   496         {
       
   497         component = (*iControls)[cc];
       
   498         componentPosition.iY += component->DistanceFromComponentAbove();
       
   499         componentSize = component->Size();
       
   500         // SetPosition cannot be used here
       
   501         component->SetExtent( componentPosition, componentSize );
       
   502         componentSize = component->Size();
       
   503         componentPosition.iY += componentSize.iHeight;
       
   504         }
       
   505     }
       
   506 
       
   507 // ---------------------------------------------------------
       
   508 // CMsgFormComponent::HandleResourceChange
       
   509 // Handles a resource relative event
       
   510 // (other items were commented in a header).
       
   511 // ---------------------------------------------------------
       
   512 //
       
   513 void CMsgFormComponent::HandleResourceChange( TInt aType )
       
   514 	{
       
   515     CEikBorderedControl::HandleResourceChange( aType );
       
   516 	if( aType == KEikDynamicLayoutVariantSwitch )
       
   517 		{
       
   518         SizeChanged();
       
   519         }
       
   520 	}
       
   521 
       
   522 // ---------------------------------------------------------
       
   523 // CMsgFormComponent::FocusChanged
       
   524 //
       
   525 // Sets focus off or on if this form component lost focus or gets focused.
       
   526 // ---------------------------------------------------------
       
   527 //
       
   528 void CMsgFormComponent::FocusChanged( TDrawNow aDrawNow )
       
   529     {
       
   530     if ( iControls->Count() > 0 )
       
   531         {
       
   532         CMsgBaseControl* control = (*iControls)[iCurrentFocus];
       
   533 
       
   534         if ( !( control->IsNonFocusing() ) )
       
   535             {
       
   536             control->SetFocus( IsFocused(), aDrawNow );
       
   537             }
       
   538         }
       
   539     }
       
   540 
       
   541 // ---------------------------------------------------------
       
   542 // CMsgFormComponent::DoAddControlL
       
   543 //
       
   544 // Adds control aControl to the component array to position aIndex. If aIndex =
       
   545 // the number components in the array or EMsgAppendControl, appends the control
       
   546 // to end of the array. Panics is aIndex is incorrect.
       
   547 // ---------------------------------------------------------
       
   548 //
       
   549 TInt CMsgFormComponent::DoAddControlL( CMsgBaseControl* aControl, TInt aIndex )
       
   550     {
       
   551     TInt controlId = aControl->ControlId();
       
   552     TInt componentCount = iControls->Count();
       
   553 
       
   554     __ASSERT_DEBUG( controlId != 0,
       
   555         Panic( EMsgControlIdNotSet ) );
       
   556     __ASSERT_DEBUG( iControls->ComponentIndexFromId( controlId ) == KErrNotFound,
       
   557         Panic( EMsgControlIdNotUnique ) );
       
   558     __ASSERT_DEBUG( ( aIndex >= EMsgAppendControl ) && ( aIndex <= componentCount ),
       
   559         Panic( EMsgIncorrectComponentIndex ) );
       
   560 
       
   561     TInt index = ( aIndex == EMsgAppendControl )
       
   562         ? componentCount
       
   563         : aIndex;
       
   564 
       
   565     if ( componentCount == 0 )
       
   566         {
       
   567         iCurrentFocus = 0;
       
   568         }
       
   569     else if ( index <= iCurrentFocus )
       
   570         {
       
   571         iCurrentFocus++;
       
   572         }
       
   573 
       
   574     if ( index == componentCount )
       
   575         {
       
   576         iControls->AppendL( aControl );
       
   577         }
       
   578     else if ( ( index >= EMsgFirstControl ) && ( index < componentCount ) )
       
   579         {
       
   580         iControls->InsertL( index, aControl );
       
   581         }
       
   582     else
       
   583         {
       
   584         __ASSERT_DEBUG( EFalse, Panic( EMsgIncorrectComponentIndex ) );
       
   585         }
       
   586 
       
   587     return controlId;
       
   588     }
       
   589 
       
   590 // ---------------------------------------------------------
       
   591 // CMsgFormComponent::CountMsgControls
       
   592 //
       
   593 // Returns the number of components.
       
   594 // ---------------------------------------------------------
       
   595 //
       
   596 TInt CMsgFormComponent::CountMsgControls( ) const
       
   597     {
       
   598     return iControls->Count();    
       
   599     }
       
   600     
       
   601 // ---------------------------------------------------------
       
   602 // CMsgFormComponent::MsgControl
       
   603 //
       
   604 // Return a pointer to a control by given control id aControlId. If the
       
   605 // control cannot be found returns NULL.
       
   606 // ---------------------------------------------------------
       
   607 //
       
   608 CMsgBaseControl* CMsgFormComponent::MsgControl( TInt aIndex ) const
       
   609     {
       
   610     
       
   611     if( aIndex >= iControls->Count( ) || aIndex < 0 )
       
   612         {
       
   613         return NULL;
       
   614         }
       
   615     
       
   616     return (*iControls)[aIndex];
       
   617     }
       
   618 
       
   619 
       
   620 //  End of File