meetingrequest/mrgui/src/cmrfieldcontainer.cpp
branchRCL_3
changeset 64 3533d4323edc
child 80 726fba06891a
equal deleted inserted replaced
63:d189ee25cf9d 64:3533d4323edc
       
     1 /*
       
     2 * Copyright (c) 2009 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:  Field container for UI fields
       
    15 *
       
    16 */
       
    17 #include "cmrfieldcontainer.h"
       
    18 #include "mesmrfieldstorage.h"
       
    19 #include "mmrfieldcontainerobserver.h"
       
    20 #include "cesmrfield.h"
       
    21 
       
    22 //DEBUG
       
    23 #include "emailtrace.h"
       
    24 
       
    25 namespace { // codescanner::namespace
       
    26 
       
    27 // Off screen field x coordinate
       
    28 const TInt KOffScreenPositionX =  1000;
       
    29 
       
    30 /**
       
    31  * Vertical scroll margin
       
    32  */
       
    33 const TInt KVerticalScrollMargin = 3;
       
    34 
       
    35 
       
    36 // ----------------
       
    37 // IndexByFieldId
       
    38 // ----------------
       
    39 //
       
    40 TInt IndexByFieldId( const MESMRFieldStorage& aFactory,
       
    41                      TESMREntryFieldId aFieldId )
       
    42     {
       
    43     TInt index( KErrNotFound );
       
    44     TInt count( aFactory.Count() );
       
    45 
       
    46     for ( TInt i = 0; i < count; ++i )
       
    47         {
       
    48         if ( aFactory.Field( i )->FieldId() == aFieldId )
       
    49             {
       
    50             index = i;
       
    51             break;
       
    52             }
       
    53         }
       
    54 
       
    55     return index;
       
    56     }
       
    57 }
       
    58 
       
    59 //----- MEMBER FUNCTIONS ----
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 // CMRFieldContainer::CMRFieldContainer
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 CMRFieldContainer::CMRFieldContainer( MESMRFieldStorage& aFactory )
       
    66     : iFactory( aFactory )
       
    67     {
       
    68     FUNC_LOG;
       
    69     }
       
    70 
       
    71 // ---------------------------------------------------------------------------
       
    72 // CMRFieldContainer::~CMRFieldContainer
       
    73 // ---------------------------------------------------------------------------
       
    74 //
       
    75 CMRFieldContainer::~CMRFieldContainer()
       
    76     {
       
    77     FUNC_LOG;
       
    78     // No implementation
       
    79     }
       
    80 
       
    81 // ---------------------------------------------------------------------------
       
    82 // CMRFieldContainer::NewL
       
    83 // ---------------------------------------------------------------------------
       
    84 //
       
    85 CMRFieldContainer* CMRFieldContainer::NewL(
       
    86         MESMRFieldStorage& aFactory,
       
    87         const CCoeControl& aParent )
       
    88     {
       
    89     FUNC_LOG;
       
    90     CMRFieldContainer* self = new( ELeave )CMRFieldContainer( aFactory );
       
    91     CleanupStack::PushL( self );
       
    92     self->ConstructL( aParent );
       
    93     CleanupStack::Pop( self );
       
    94     return self;
       
    95     }
       
    96 
       
    97 // ---------------------------------------------------------------------------
       
    98 // CMRFieldContainer::ConstructL
       
    99 // ---------------------------------------------------------------------------
       
   100 //
       
   101 void CMRFieldContainer::ConstructL( const CCoeControl& aParent )
       
   102     {
       
   103     FUNC_LOG;
       
   104     CCoeControl::SetComponentsToInheritVisibility( ETrue );
       
   105     SetContainerWindowL( aParent );
       
   106 
       
   107     TBool focusSet( EFalse );
       
   108     const TInt count( iFactory.Count() );
       
   109     for ( TInt i = 0; i < count; i++ )
       
   110         {
       
   111         iFactory.Field(i)->SetContainerWindowL( *this );
       
   112         }
       
   113 
       
   114     for ( TInt i = 0; i < count; i++ )
       
   115         {
       
   116         CESMRField* field = iFactory.Field( i );
       
   117 
       
   118         // Initialize field
       
   119         field->InitializeL();
       
   120 
       
   121         if ( !focusSet
       
   122              && field->IsVisible()
       
   123              && !field->IsNonFocusing())
       
   124             {
       
   125             field->SetOutlineFocusL( ETrue );
       
   126             focusSet = ETrue;
       
   127             iFocusedFieldIndex = i;
       
   128             }
       
   129         }
       
   130 
       
   131     for ( TInt i = 0; i < count; i++ )
       
   132         {
       
   133         CESMRField* field = iFactory.Field( i );
       
   134 
       
   135         field->SetListObserver( this );
       
   136         }
       
   137     }
       
   138 
       
   139 // ---------------------------------------------------------------------------
       
   140 // CMRFieldContainer::FocusedItem
       
   141 // ---------------------------------------------------------------------------
       
   142 //
       
   143 CESMRField* CMRFieldContainer::FocusedField() const
       
   144     {
       
   145     FUNC_LOG;
       
   146     /*
       
   147      * Returns currently focused field
       
   148      */
       
   149     CESMRField* field = NULL;
       
   150     if ( iFactory.Count() > 0 )
       
   151         {
       
   152         field = iFactory.Field( iFocusedFieldIndex );
       
   153         }
       
   154     return field;
       
   155     }
       
   156 
       
   157 
       
   158 // ---------------------------------------------------------------------------
       
   159 // CMRFieldContainer::MoveFocusUpL
       
   160 // ---------------------------------------------------------------------------
       
   161 //
       
   162 TKeyResponse CMRFieldContainer::MoveFocusUpL( TBool aHiddenFocus )
       
   163     {
       
   164     FUNC_LOG;
       
   165     /*
       
   166      * Moves focus up after key event. If aHiddenFocus, moves focus
       
   167      * to the first visible field in the bottom of the viewable area.
       
   168      */
       
   169 
       
   170     if( aHiddenFocus )
       
   171         {
       
   172         return MoveFocusVisibleL();
       
   173         }
       
   174     else
       
   175         {
       
   176         TInt ind( iFocusedFieldIndex );
       
   177 
       
   178         // search next visible focus item
       
   179         while ( ind > 0 )
       
   180             {
       
   181             CESMRField* field = iFactory.Field( --ind );
       
   182 
       
   183             if ( !field->IsNonFocusing() )
       
   184                 {
       
   185                 field = iFactory.Field( ind );
       
   186 
       
   187                 CESMRField* focusedField = iFactory.Field( iFocusedFieldIndex );
       
   188                 if ( field->IsVisible() )
       
   189                     {
       
   190                     TBool canLoseFocus(
       
   191                             focusedField->OkToLoseFocusL( field->FieldId() ) );
       
   192 
       
   193                     if ( canLoseFocus )
       
   194                         {
       
   195                         field->SetPreItemIndex( iFocusedFieldIndex );
       
   196                         iFocusedFieldIndex = ind;
       
   197                         field->SetCurrentItemIndex( iFocusedFieldIndex );
       
   198 
       
   199                         // Remove focus from previous position
       
   200                         focusedField->SetOutlineFocusL( EFalse );
       
   201                         focusedField->SetFocus( EFalse );
       
   202                         focusedField->MoveToScreen( EFalse );
       
   203 
       
   204                         // Set focus to new position
       
   205                         field->SetOutlineFocusL( ETrue );
       
   206                         field->SetFocus( ETrue );
       
   207                         field->MoveToScreen( ETrue );
       
   208 
       
   209                         // Scrollbar and physics update is done here
       
   210                         ScrollControlVisible( iFocusedFieldIndex );
       
   211 
       
   212                         DrawDeferred();
       
   213                         }
       
   214 
       
   215                     return EKeyWasConsumed;
       
   216                     }
       
   217                 }
       
   218             }
       
   219         return EKeyWasNotConsumed;
       
   220         }
       
   221     }
       
   222 
       
   223 // ---------------------------------------------------------------------------
       
   224 // CMRFieldContainer::MoveFocusDownL
       
   225 // ---------------------------------------------------------------------------
       
   226 //
       
   227 TKeyResponse CMRFieldContainer::MoveFocusDownL( TBool aHiddenFocus )
       
   228     {
       
   229     FUNC_LOG;
       
   230     /*
       
   231      * Moves focus down after key event. If aHiddenFocus, moves focus
       
   232      * to the first visible field in the top of the viewable area.
       
   233      */
       
   234 
       
   235     if( aHiddenFocus )
       
   236         {
       
   237         return MoveFocusVisibleL();
       
   238         }
       
   239     else
       
   240         {
       
   241         TInt ind( iFocusedFieldIndex );
       
   242 
       
   243         // start searching next possible focus item
       
   244         TInt maxItemIndex = iFactory.Count() - 1;
       
   245 
       
   246         while ( ind < maxItemIndex )
       
   247             {
       
   248             // only visible and focusable items can be focused
       
   249             CESMRField* field = iFactory.Field( ++ind );
       
   250 
       
   251             if ( field->IsVisible() && !field->IsNonFocusing() )
       
   252                 {
       
   253                 CESMRField* focusedField = iFactory.Field( iFocusedFieldIndex );
       
   254 
       
   255                 TBool canLoseFocus(
       
   256                         focusedField->OkToLoseFocusL( field->FieldId() ) );
       
   257 
       
   258                 // check it its ok for the old focus item to lose focus
       
   259                 if ( canLoseFocus )
       
   260                     {
       
   261                     field->SetPreItemIndex( iFocusedFieldIndex );
       
   262                     iFocusedFieldIndex = ind;
       
   263                     field->SetCurrentItemIndex( iFocusedFieldIndex );
       
   264 
       
   265                     // Remove focus from previous position
       
   266                     focusedField->SetOutlineFocusL( EFalse );
       
   267                     focusedField->SetFocus( EFalse );
       
   268                     focusedField->MoveToScreen( EFalse );
       
   269 
       
   270                     // Set focus to new position
       
   271                     field->SetOutlineFocusL( ETrue );
       
   272                     field->SetFocus( ETrue );
       
   273                     field->MoveToScreen( ETrue );
       
   274 
       
   275                     // Scrollbar and physics update is done here
       
   276                     ScrollControlVisible( iFocusedFieldIndex );
       
   277 
       
   278                     DrawDeferred();
       
   279                     }
       
   280 
       
   281                 return EKeyWasConsumed;
       
   282                 }
       
   283             }
       
   284         return EKeyWasNotConsumed;
       
   285         }
       
   286     }
       
   287 
       
   288 // ---------------------------------------------------------------------------
       
   289 // CMRFieldContainer::MoveFocusVisibleL
       
   290 // ---------------------------------------------------------------------------
       
   291 //
       
   292 TKeyResponse CMRFieldContainer::MoveFocusVisibleL()
       
   293     {
       
   294     FUNC_LOG;
       
   295     /*
       
   296      * Move focus to first completely visible field in the view,
       
   297      * if focus was in a field that was not visible in the view.
       
   298      * Use case: After pointer scroll focus is hidden. User presses
       
   299      * arrow keys -> Focus appears to the first visible field on the upper
       
   300      * or bottom part of the viewable area.
       
   301      */
       
   302 
       
   303     TKeyResponse response( EKeyWasNotConsumed );
       
   304 
       
   305     CESMRField* focusedField = FocusedField();
       
   306     CESMRField* visibleField = NULL;
       
   307     TRect view( Parent()->Rect() );
       
   308 
       
   309     // Focus is above the visible view area
       
   310     if ( focusedField->Rect().iBr.iY <= view.iTl.iY )
       
   311         {
       
   312         // Move focus to next visible field
       
   313         TInt lastIndex = iFactory.Count() - 1;
       
   314         TInt ind( iFocusedFieldIndex );
       
   315         while ( ind < lastIndex && !visibleField )
       
   316             {
       
   317             visibleField = iFactory.Field( ++ind );
       
   318             TRect fieldRect = visibleField->Rect();
       
   319             if ( visibleField->IsVisible()
       
   320                  && !visibleField->IsNonFocusing()
       
   321                  && fieldRect.iTl.iY >= view.iTl.iY )
       
   322                 {
       
   323                 // Update previous and current field indexes
       
   324                 visibleField->SetPreItemIndex( iFocusedFieldIndex );
       
   325                 iFocusedFieldIndex = ind;
       
   326                 visibleField->SetCurrentItemIndex( iFocusedFieldIndex );
       
   327                 }
       
   328             else
       
   329                 {
       
   330                 visibleField = NULL;
       
   331                 }
       
   332             }
       
   333         }
       
   334     // Focus is below the visible view area
       
   335     else
       
   336         {
       
   337         // Move focus to previous visible field
       
   338         TInt ind( iFocusedFieldIndex );
       
   339         while ( ind > 0 && !visibleField )
       
   340             {
       
   341             visibleField = iFactory.Field( --ind );
       
   342             TRect fieldRect = visibleField->Rect();
       
   343             if ( visibleField->IsVisible()
       
   344                  && !visibleField->IsNonFocusing()
       
   345                  && fieldRect.iBr.iY <= view.iBr.iY )
       
   346                 {
       
   347                 // Update previous and current field indexes
       
   348                 visibleField->SetPreItemIndex( iFocusedFieldIndex );
       
   349                 iFocusedFieldIndex = ind;
       
   350                 visibleField->SetCurrentItemIndex( iFocusedFieldIndex );
       
   351                 }
       
   352             else
       
   353                 {
       
   354                 visibleField = NULL;
       
   355                 }
       
   356             }
       
   357         }
       
   358 
       
   359     if ( visibleField )
       
   360         {
       
   361         // Remove existing focus
       
   362         focusedField->SetOutlineFocusL( EFalse );
       
   363         focusedField->SetFocus( EFalse );
       
   364 
       
   365         // Set focus to new field
       
   366         visibleField->SetOutlineFocusL( ETrue );
       
   367         visibleField->SetFocus( ETrue );
       
   368 
       
   369         response = EKeyWasConsumed;
       
   370 
       
   371         DrawDeferred();
       
   372         }
       
   373 
       
   374     return response;
       
   375     }
       
   376 
       
   377 // ---------------------------------------------------------------------------
       
   378 // CMRFieldContainer::SetFieldContainerObserver
       
   379 // ---------------------------------------------------------------------------
       
   380 //
       
   381 void CMRFieldContainer::SetFieldContainerObserver(
       
   382         MMRFieldContainerObserver* aObserver )
       
   383     {
       
   384     FUNC_LOG;
       
   385     iObserver = aObserver;
       
   386     }
       
   387 
       
   388 // ---------------------------------------------------------------------------
       
   389 // CMRFieldContainer::CountComponentControls
       
   390 // ---------------------------------------------------------------------------
       
   391 //
       
   392 TInt CMRFieldContainer::CountComponentControls() const
       
   393     {
       
   394     FUNC_LOG;
       
   395 
       
   396     // If field container is scrolling, container will draw also children
       
   397     TInt count( 0 );
       
   398 
       
   399     if ( !iScrolling )
       
   400         {
       
   401         count = iFactory.Count();
       
   402         }
       
   403 
       
   404     return count;
       
   405     }
       
   406 
       
   407 // ---------------------------------------------------------------------------
       
   408 // CMRFieldContainer::ComponentControl
       
   409 // ---------------------------------------------------------------------------
       
   410 //
       
   411 CCoeControl* CMRFieldContainer::ComponentControl( TInt aIndex ) const
       
   412     {
       
   413     FUNC_LOG;
       
   414     return iFactory.Field( aIndex );
       
   415     }
       
   416 
       
   417 // ---------------------------------------------------------------------------
       
   418 // CMRFieldContainer::MinimumSize
       
   419 // ---------------------------------------------------------------------------
       
   420 //
       
   421 TSize CMRFieldContainer::MinimumSize()
       
   422     {
       
   423     FUNC_LOG;
       
   424     /*
       
   425      * Returns the minimum size required by the field container
       
   426      */
       
   427 
       
   428     TSize containerSize;
       
   429 
       
   430     // Calculate height as the sum of the heights of the visible fields
       
   431     const TInt count( iFactory.Count() );
       
   432 
       
   433     for ( TInt i(0); i < count; ++i )
       
   434         {
       
   435         CESMRField* field = iFactory.Field( i );
       
   436         if ( field->IsVisible() )
       
   437             {
       
   438             TRect rect( field->Rect() );
       
   439             containerSize.iHeight += rect.Height();
       
   440             }
       
   441         }
       
   442 
       
   443     containerSize.iWidth = Parent()->Rect().Width();
       
   444 
       
   445     return containerSize;
       
   446     }
       
   447 
       
   448 // ---------------------------------------------------------------------------
       
   449 // CMRFieldContainer::SizeChanged
       
   450 // ---------------------------------------------------------------------------
       
   451 //
       
   452 void CMRFieldContainer::SizeChanged()
       
   453     {
       
   454     FUNC_LOG;
       
   455 
       
   456     // For example when orientation changes, we might need to scroll
       
   457     // the currently focused control visible again. This handles also
       
   458     // scrollbar and physics updates.
       
   459     ScrollControlVisible( KErrNotFound );
       
   460 
       
   461     TPoint tl( Position() );
       
   462 
       
   463     const TInt count( iFactory.Count() );
       
   464 
       
   465     // Loop all the visible fields and set size and position in the list
       
   466     for ( TInt i = 0; i < count; i++ )
       
   467         {
       
   468         CESMRField* field = iFactory.Field( i );
       
   469 
       
   470         if ( field->IsVisible() )
       
   471             {
       
   472             TPoint pos( tl );
       
   473 
       
   474             // If field is not focused, layout it outside screen
       
   475             if ( i != iFocusedFieldIndex )
       
   476                 {
       
   477                 pos.iX = KOffScreenPositionX;
       
   478                 }
       
   479 
       
   480             LayoutField( *field, pos );
       
   481 
       
   482             TInt height = field->Size().iHeight;
       
   483             tl.iY += height;
       
   484             }
       
   485         }
       
   486     }
       
   487 
       
   488 
       
   489 // ---------------------------------------------------------------------------
       
   490 // CMRFieldContainer::HandlePointerEventL
       
   491 // ---------------------------------------------------------------------------
       
   492 //
       
   493 void CMRFieldContainer::HandlePointerEventL( const TPointerEvent &aPointerEvent )
       
   494     {
       
   495     FUNC_LOG;
       
   496 
       
   497     // Find out to which field this pointer event is intended to
       
   498     TInt fieldCount( iFactory.Count() );
       
   499 
       
   500     for( TInt i = 0; i < fieldCount; ++i )
       
   501         {
       
   502         CCoeControl* field = iFactory.Field( i );
       
   503         if( field->Rect().Contains( aPointerEvent.iPosition ) &&
       
   504                 field->IsVisible() )
       
   505             {
       
   506             field->HandlePointerEventL( aPointerEvent );
       
   507             }
       
   508         }
       
   509     }
       
   510 
       
   511 // ---------------------------------------------------------------------------
       
   512 // CMRFieldContainer::ControlSizeChanged
       
   513 // ---------------------------------------------------------------------------
       
   514 //
       
   515 void CMRFieldContainer::ControlSizeChanged( CESMRField* aField )
       
   516     {
       
   517     FUNC_LOG;
       
   518     /*
       
   519      * Called whenever a fields size has changed. Requires always
       
   520      * relayouting.
       
   521      */
       
   522 
       
   523     if ( !aField )
       
   524         {
       
   525         SizeChanged();
       
   526         }
       
   527     else
       
   528         {
       
   529         // Relayout field if size has changed
       
   530         TSize old( aField->Size() );
       
   531         TSize size( aField->MinimumSize() );
       
   532         if( size != old )
       
   533             {
       
   534             aField->SetSize( size );
       
   535 
       
   536             TPoint tl( aField->Position() );
       
   537             TInt index = IndexByFieldId( iFactory, aField->FieldId() );
       
   538 
       
   539             // Move fields below this particular field
       
   540             tl.iY += size.iHeight;
       
   541             MoveFields( index + 1, tl );
       
   542 
       
   543             // Fields have been re-layouted / moved. This requires resetting
       
   544             // the size of this field container.
       
   545             SetSizeWithoutNotification( MinimumSize() );
       
   546 
       
   547             // Update also scrollbar and physics
       
   548             iObserver->UpdateScrollBarAndPhysics();
       
   549 
       
   550             if( index <= iFocusedFieldIndex )
       
   551                 {
       
   552                 // Scroll this field completely visible, if required.
       
   553                 // This updates also scrollbar and physics if scrolling
       
   554                 // is done.
       
   555                 ScrollControlVisible( iFocusedFieldIndex );
       
   556                 }
       
   557 
       
   558             DrawDeferred();
       
   559             }
       
   560         }
       
   561     }
       
   562 
       
   563 // ---------------------------------------------------------------------------
       
   564 // CMRFieldContainer::ShowControl
       
   565 // ---------------------------------------------------------------------------
       
   566 //
       
   567 void CMRFieldContainer::ShowControl( TESMREntryFieldId aFieldId )
       
   568     {
       
   569     FUNC_LOG;
       
   570     /*
       
   571      * Inserts field visible and layouts it.
       
   572      */
       
   573 
       
   574     CESMRField* field = iFactory.FieldById( aFieldId );
       
   575 
       
   576     if ( field && !field->IsVisible() )
       
   577         {
       
   578         // Make field visible
       
   579         field->MakeVisible( ETrue );
       
   580         TInt index = IndexByFieldId( iFactory, aFieldId );
       
   581 
       
   582         TPoint tl( Rect().iTl );
       
   583         TInt prevIndex = index - 1;
       
   584 
       
   585         // Get previous visible field position
       
   586         // Index 0 must be included in attendee field case,
       
   587         // to avoid field collision. But in response field,
       
   588         // causes misplacing of area.
       
   589         if ( ( prevIndex >= 0 ) && ( aFieldId != EESMRFieldResponseArea ) )
       
   590             {
       
   591             CESMRField* previous = NULL;
       
   592             do
       
   593                 {
       
   594                 previous = iFactory.Field( prevIndex-- );
       
   595                 }
       
   596             while ( prevIndex >= 0 && !previous->IsVisible() );
       
   597 
       
   598             tl.iY = previous->Rect().iBr.iY;
       
   599             }
       
   600 
       
   601         // Layout field
       
   602         LayoutField( *field, tl);
       
   603         // Move field off screen if it is not focused
       
   604         field->MoveToScreen( index == iFocusedFieldIndex );
       
   605 
       
   606         // Move following fields
       
   607         tl.iY += field->Size().iHeight;
       
   608         MoveFields( ++index, tl );
       
   609 
       
   610         // Set fieldcontainer size again, because
       
   611         // the amount of fields has changed.
       
   612         SetSizeWithoutNotification( MinimumSize() );
       
   613 
       
   614         // Scrollbar and physics require updating.
       
   615         iObserver->UpdateScrollBarAndPhysics();
       
   616         }
       
   617 
       
   618     DrawDeferred();
       
   619     }
       
   620 
       
   621 // ---------------------------------------------------------------------------
       
   622 // CMRFieldContainer::HideControl()
       
   623 // ---------------------------------------------------------------------------
       
   624 //
       
   625 void CMRFieldContainer::HideControl( TESMREntryFieldId aFieldId )
       
   626     {
       
   627     FUNC_LOG;
       
   628     /*
       
   629      * Sets field non-visible and moves other fields accordingly.
       
   630      * Does not delete the field.
       
   631      */
       
   632     CESMRField* field = iFactory.FieldById( aFieldId );
       
   633 
       
   634     if ( field && field->IsVisible() )
       
   635         {
       
   636         field->MakeVisible( EFalse );
       
   637         TInt index = IndexByFieldId( iFactory, aFieldId );
       
   638         TBool focused = ( index == iFocusedFieldIndex )? ETrue : EFalse;
       
   639 
       
   640         TPoint pos( field->Position() );
       
   641         MoveFields( index, pos );
       
   642 
       
   643         // Set fieldcontainer size again, because
       
   644         // the amount of fields has changed.
       
   645         SetSizeWithoutNotification( MinimumSize() );
       
   646 
       
   647         // Scrollbar and physics require updating.
       
   648         iObserver->UpdateScrollBarAndPhysics();
       
   649 
       
   650         if ( focused && !field->IsNonFocusing() )
       
   651             {
       
   652             // Set focus to next field, or if removed field was the last
       
   653             // field, then move focus to last visible field
       
   654             TInt lastVisibleFieldIndex( LastVisibleField( aFieldId ) );
       
   655 
       
   656             // If field was the last one...
       
   657             if( lastVisibleFieldIndex == index )
       
   658                 {
       
   659                 // ... Set focus to last visible field.
       
   660                 TRAP_IGNORE( DoSetFocusL( lastVisibleFieldIndex ) )
       
   661                 }
       
   662             else
       
   663                 {
       
   664                 // Othwerwise set focus to next field
       
   665                 TRAP_IGNORE( DoSetFocusL( index + 1 ) )
       
   666                 }
       
   667             }
       
   668         }
       
   669     DrawDeferred();
       
   670     }
       
   671 
       
   672 // ---------------------------------------------------------------------------
       
   673 // CMRFieldContainer::IsControlVisible
       
   674 // ---------------------------------------------------------------------------
       
   675 //
       
   676 TBool CMRFieldContainer::IsControlVisible( TESMREntryFieldId aField )
       
   677     {
       
   678     FUNC_LOG;
       
   679     /*
       
   680      * Returns ETrue/EFalse if the field with given field id is
       
   681      * visible or not.
       
   682      */
       
   683 
       
   684     TBool ret( EFalse );
       
   685 
       
   686     CESMRField* field = iFactory.FieldById( aField );
       
   687     if ( field && field->IsVisible() )
       
   688         {
       
   689         ret = ETrue;
       
   690         }
       
   691 
       
   692     return ret;
       
   693     }
       
   694 
       
   695 // ---------------------------------------------------------------------------
       
   696 // CMRFieldContainer::SetControlFocused
       
   697 // ---------------------------------------------------------------------------
       
   698 //
       
   699 void CMRFieldContainer::SetControlFocusedL( TESMREntryFieldId aField )
       
   700     {
       
   701     FUNC_LOG;
       
   702     /*
       
   703      * Set the field with given field id focused.
       
   704      */
       
   705 
       
   706     // This handles scrollbar and physics updates also.
       
   707     DoSetFocusL( IndexByFieldId( iFactory, aField ) );
       
   708     }
       
   709 
       
   710 // ---------------------------------------------------------------------------
       
   711 // CMRFieldContainer::ListHeight
       
   712 // ---------------------------------------------------------------------------
       
   713 //
       
   714 TInt CMRFieldContainer::ListHeight()
       
   715     {
       
   716     FUNC_LOG;
       
   717     /*
       
   718      * Returns the height of all fields, in other words the height
       
   719      * of the field container.
       
   720      */
       
   721     return MinimumSize().iHeight;
       
   722     }
       
   723 
       
   724 // ---------------------------------------------------------------------------
       
   725 // CMRFieldContainer::IsFocusedControlsBottomVisible
       
   726 // ---------------------------------------------------------------------------
       
   727 //
       
   728 TBool CMRFieldContainer::IsFocusedControlsBottomVisible()
       
   729     {
       
   730     FUNC_LOG;
       
   731     /*
       
   732      * Checks if focused field is completely visible in the viewable area.
       
   733      */
       
   734 
       
   735     // Fetch the position information about currently focused field:
       
   736     CESMRField* field = iFactory.Field( iFocusedFieldIndex );
       
   737     TBool ret( EFalse );
       
   738     if ( field->Rect().iBr.iY <= Parent()->Rect().iBr.iY )
       
   739        {
       
   740        ret = ETrue;
       
   741        }
       
   742 
       
   743     return ret;
       
   744     }
       
   745 
       
   746 
       
   747 // ---------------------------------------------------------------------------
       
   748 // CMRFieldContainer::ScrollControlVisible
       
   749 // ---------------------------------------------------------------------------
       
   750 //
       
   751 void CMRFieldContainer::ScrollControlVisible( TInt aInd )
       
   752     {
       
   753     FUNC_LOG;
       
   754     /*
       
   755      * Scrolls the field with the given index visible
       
   756      */
       
   757 
       
   758     CESMRField* field = NULL;
       
   759     if ( aInd == KErrNotFound )
       
   760         {
       
   761         field = FocusedField();
       
   762         }
       
   763     else
       
   764         {
       
   765         field = iFactory.Field( aInd );
       
   766         }
       
   767 
       
   768     ASSERT( field );
       
   769 
       
   770     TRect fieldRect( field->Position(), field->Size() );
       
   771     TRect parentRect( Parent()->Rect() );
       
   772 
       
   773     /*
       
   774      * Case 1: Field's height is less than the viewable area height,
       
   775      * let's scroll the whole field visible.
       
   776      */
       
   777     if( fieldRect.Height() < parentRect.Height() )
       
   778         {
       
   779         // Scrolling down, let's move fields up
       
   780         if( fieldRect.iBr.iY > parentRect.iBr.iY )
       
   781             {
       
   782             iObserver->ScrollFieldsUp(
       
   783                     fieldRect.iBr.iY - parentRect.iBr.iY );
       
   784             }
       
   785         // scrolling up, let's move field down
       
   786         if( fieldRect.iTl.iY < parentRect.iTl.iY )
       
   787             {
       
   788             iObserver->ScrollFieldsDown(
       
   789                     parentRect.iTl.iY - fieldRect.iTl.iY );
       
   790             }
       
   791         }
       
   792 
       
   793     /*
       
   794      * Case 2: Field's height is more than the viewable area's height.
       
   795      */
       
   796     else
       
   797         {
       
   798         // Field is in view mode
       
   799         if( field->FieldMode() == EESMRFieldModeView )
       
   800             {
       
   801             // Focus to this field is coming from above
       
   802             if( field->PreItemIndex() < field->CurrentItemIndex() )
       
   803                 {
       
   804                 // Let's scroll the top of the field to the
       
   805                 // top of the viewable area
       
   806                 iObserver->ScrollFieldsUp(
       
   807                                    fieldRect.iTl.iY - parentRect.iTl.iY );
       
   808 
       
   809                 }
       
   810             // Focus to this field is coming from below
       
   811             if( field->PreItemIndex() > field->CurrentItemIndex() )
       
   812                 {
       
   813                 // Let's scroll the bottom of the field to the
       
   814                 // bottom of the viewable area
       
   815                 iObserver->ScrollFieldsDown(
       
   816                                    parentRect.iBr.iY - fieldRect.iBr.iY );
       
   817                 }
       
   818             }
       
   819 
       
   820         // Field is in edit mode
       
   821         if( field->FieldMode() == EESMRFieldModeEdit )
       
   822             {
       
   823             TInt viewBottom( parentRect.iBr.iY );
       
   824 
       
   825             TInt fieldUpper( 0 );
       
   826             TInt fieldLower( 0 );
       
   827             field->GetCursorLineVerticalPos( fieldUpper, fieldLower );
       
   828 
       
   829             TInt focusFieldVisibleUp( fieldRect.iTl.iY + fieldUpper );
       
   830             TInt focusFieldVisibleBottom( fieldRect.iTl.iY + fieldLower );
       
   831 
       
   832             // desired position below view rect:
       
   833             TInt viewHeight( parentRect.Height() );
       
   834             if ( focusFieldVisibleBottom > viewBottom )
       
   835                 {
       
   836                 // move field focus line bottom to view bottom
       
   837                 TInt px = focusFieldVisibleBottom - viewHeight;
       
   838 
       
   839 
       
   840                 // if focus on last field: add margin height to
       
   841                 // scroll amount.
       
   842                 if ( iFocusedFieldIndex == iFactory.Count()-1 )
       
   843                     {
       
   844                     px += KVerticalScrollMargin;
       
   845                     }
       
   846 
       
   847                 // Scrollbar and physics update is done here
       
   848                 iObserver->ScrollFieldsUp( px );
       
   849                 }
       
   850             else
       
   851                 {
       
   852                 // If field top is invisible, move downwards to make top visible.
       
   853                 TInt viewTop( parentRect.iTl.iY );
       
   854 
       
   855                 // recalculate field rect
       
   856                 focusFieldVisibleUp = fieldRect.iTl.iY + fieldUpper;
       
   857                 focusFieldVisibleBottom = fieldRect.iTl.iY + fieldLower;
       
   858 
       
   859                 if ( focusFieldVisibleUp < viewTop )
       
   860                     {
       
   861                     TInt px( viewTop - focusFieldVisibleUp );
       
   862 
       
   863                     // Scrollbar and physics update is done here
       
   864                     iObserver->ScrollFieldsDown( px );
       
   865                     }
       
   866                 }
       
   867             }
       
   868         }
       
   869     }
       
   870 
       
   871 // ---------------------------------------------------------------------------
       
   872 // CMRFieldContainer::RePositionFields
       
   873 // ---------------------------------------------------------------------------
       
   874 //
       
   875 void CMRFieldContainer::RePositionFields( TInt aAmount )
       
   876     {
       
   877     FUNC_LOG;
       
   878 
       
   879     // Movement downwards
       
   880     if( aAmount >= 0 )
       
   881         {
       
   882         // Also scrollbar and physics update is done here
       
   883         iObserver->ScrollFieldsDown( aAmount );
       
   884         }
       
   885     // Movement upwards
       
   886     else
       
   887         {
       
   888         // Also scrollbar and physics update is done here
       
   889         iObserver->ScrollFieldsUp( -aAmount );
       
   890         }
       
   891     }
       
   892 
       
   893 // ---------------------------------------------------------------------------
       
   894 // CMRFieldContainer::ViewableAreaRect
       
   895 // ---------------------------------------------------------------------------
       
   896 //
       
   897 TRect CMRFieldContainer::ViewableAreaRect()
       
   898     {
       
   899     FUNC_LOG;
       
   900     return Parent()->Rect();
       
   901     }
       
   902 
       
   903 // ---------------------------------------------------------------------------
       
   904 // CMRFieldContainer::MoveFields
       
   905 // ---------------------------------------------------------------------------
       
   906 //
       
   907 void CMRFieldContainer::MoveFields( TInt aIndex, TPoint& aTl )
       
   908     {
       
   909     FUNC_LOG;
       
   910     /*
       
   911      * Moves fields from the given index towards the last item.
       
   912      * This function does not update scrollbar or physics.
       
   913      */
       
   914 
       
   915     const TInt count( iFactory.Count() );
       
   916 
       
   917     for ( TInt i = aIndex; i < count; ++i )
       
   918         {
       
   919         CESMRField* field = iFactory.Field( i );
       
   920 
       
   921         if ( field->IsVisible() )
       
   922             {
       
   923             field->SetPosition( aTl );
       
   924 
       
   925             aTl.iY += field->Size().iHeight;
       
   926             }
       
   927         }
       
   928     }
       
   929 
       
   930 // ---------------------------------------------------------------------------
       
   931 // CMRFieldContainer::LayoutField
       
   932 // ---------------------------------------------------------------------------
       
   933 //
       
   934 void CMRFieldContainer::LayoutField( CESMRField& aField, const TPoint& aTl )
       
   935     {
       
   936     FUNC_LOG;
       
   937     /*
       
   938      * Layouts given field according to the size required by the field and
       
   939      * given TPoint. This function does not update scrollbar or physics.
       
   940      */
       
   941 
       
   942     TSize size( aField.MinimumSize() );
       
   943     aField.SetExtent( aTl, size );
       
   944     }
       
   945 
       
   946 // ---------------------------------------------------------------------------
       
   947 // CMRFieldContainer::IsLastVisibleField
       
   948 // ---------------------------------------------------------------------------
       
   949 //
       
   950 TInt CMRFieldContainer::LastVisibleField(
       
   951         TESMREntryFieldId aFieldId )
       
   952     {
       
   953     /*
       
   954      * Helper function to find out the last visible field in the list.
       
   955      */
       
   956 
       
   957     TInt lastVisibleFieldIndex( 0 );
       
   958     TInt count( iFactory.Count() );
       
   959 
       
   960     // Go through fields from last field towards the first field
       
   961     for( TInt i( 1 ); i > count; ++i )
       
   962         {
       
   963         // Once last visible field is found...
       
   964         if( iFactory.Field( count - i )->IsVisible() )
       
   965             {
       
   966             // ... Compare it to the given field index ...
       
   967             if( iFactory.Field( count - i )->FieldId() == aFieldId )
       
   968                 {
       
   969                 // ... And if match is found, given fieldId is the
       
   970                 // the last visible field.
       
   971                 lastVisibleFieldIndex =
       
   972                     IndexByFieldId( iFactory, aFieldId );
       
   973                 }
       
   974             else
       
   975                 {
       
   976                 // Otherwise return the found last visible field.
       
   977                 lastVisibleFieldIndex =
       
   978                     IndexByFieldId( iFactory,
       
   979                                     iFactory.Field( count - i )->FieldId() );
       
   980                 }
       
   981             break;
       
   982             }
       
   983         }
       
   984 
       
   985     return lastVisibleFieldIndex;
       
   986     }
       
   987 
       
   988 // ---------------------------------------------------------------------------
       
   989 // CMRFieldContainer::DoSetFocusL
       
   990 // ---------------------------------------------------------------------------
       
   991 //
       
   992 void CMRFieldContainer::DoSetFocusL( TInt aNewFocusIndex )
       
   993     {
       
   994     FUNC_LOG;
       
   995     /*
       
   996      * Sets the focus according to the given index.
       
   997      */
       
   998 
       
   999     TInt count( iFactory.Count() );
       
  1000     aNewFocusIndex = Max( 0, Min( aNewFocusIndex, count - 1 ) );
       
  1001 
       
  1002     if ( aNewFocusIndex != iFocusedFieldIndex )
       
  1003         {
       
  1004         // Get current focused field
       
  1005         CESMRField* old = iFactory.Field( iFocusedFieldIndex );
       
  1006 
       
  1007         // Get next focused field
       
  1008         CESMRField* field = iFactory.Field( aNewFocusIndex );
       
  1009 
       
  1010         // Do sanity checks
       
  1011         while ( aNewFocusIndex < count && !field->IsVisible() )
       
  1012             {
       
  1013             field = iFactory.Field( aNewFocusIndex++ );
       
  1014             }
       
  1015 
       
  1016         if ( !field->IsVisible() )
       
  1017             {
       
  1018             aNewFocusIndex = iFocusedFieldIndex - 1;
       
  1019             while ( aNewFocusIndex > 0 && !field->IsVisible() )
       
  1020                 {
       
  1021                 field = iFactory.Field( aNewFocusIndex-- );
       
  1022                 }
       
  1023             }
       
  1024 
       
  1025         ASSERT( field->IsVisible() );
       
  1026 
       
  1027         // Update current and previous item indexes
       
  1028         field->SetPreItemIndex( iFocusedFieldIndex );
       
  1029         iFocusedFieldIndex = aNewFocusIndex;
       
  1030         field->SetCurrentItemIndex( iFocusedFieldIndex );
       
  1031 
       
  1032         // Remove focus from old
       
  1033         old->SetOutlineFocusL( EFalse );
       
  1034         old->SetFocus( EFalse );
       
  1035         old->MoveToScreen( EFalse );
       
  1036 
       
  1037         // update focus index to new index
       
  1038         field->SetOutlineFocusL( ETrue );
       
  1039         field->SetFocus( ETrue );
       
  1040         field->MoveToScreen( ETrue );
       
  1041 
       
  1042         // This handles also scrollbar and physics updating,
       
  1043         // if view scrolling is done.
       
  1044         ScrollControlVisible( iFocusedFieldIndex );
       
  1045 
       
  1046         DrawDeferred();
       
  1047         }
       
  1048     }
       
  1049 
       
  1050 
       
  1051 // ---------------------------------------------------------------------------
       
  1052 // CMRFieldContainer::SetScrolling
       
  1053 // ---------------------------------------------------------------------------
       
  1054 //
       
  1055 void CMRFieldContainer::SetScrolling( TBool aScrolling )
       
  1056     {
       
  1057     FUNC_LOG;
       
  1058 
       
  1059     iScrolling = aScrolling;
       
  1060 
       
  1061     // Move focused field away from screen if container is scrolling.
       
  1062     // Otherwise move it to screen.
       
  1063     CESMRField* field = iFactory.Field( iFocusedFieldIndex );
       
  1064     field->MoveToScreen( !iScrolling );
       
  1065     }
       
  1066 
       
  1067 
       
  1068 // ---------------------------------------------------------------------------
       
  1069 // CMRFieldContainer::Draw
       
  1070 // ---------------------------------------------------------------------------
       
  1071 //
       
  1072 void CMRFieldContainer::Draw( const TRect& aRect ) const
       
  1073     {
       
  1074     FUNC_LOG;
       
  1075 
       
  1076     // Get visible screen area from parent (list pane)
       
  1077     TRect parent( Parent()->Rect() );
       
  1078 
       
  1079     // Current container position used to calculate actual field positions
       
  1080     TPoint tl( iPosition );
       
  1081 
       
  1082     // Field index to skip
       
  1083     TInt fieldToSkip = KErrNotFound;
       
  1084 
       
  1085     if ( !iScrolling )
       
  1086         {
       
  1087         // Container is not scrolling. Don't draw focused field from buffer
       
  1088         fieldToSkip = iFocusedFieldIndex;
       
  1089         }
       
  1090 
       
  1091     // Draw all visible fields which are not on screen
       
  1092     TInt count( iFactory.Count() );
       
  1093 
       
  1094     for ( TInt i = 0; i < count; ++i )
       
  1095         {
       
  1096         CESMRField* field = iFactory.Field( i );
       
  1097         if ( field->IsVisible() )
       
  1098             {
       
  1099             // Calculate actual field rect on screen
       
  1100             TRect screenRect( tl, field->Size() );
       
  1101 
       
  1102             // Draw field if it intersects with screen visible area
       
  1103             if ( i != fieldToSkip
       
  1104                  && screenRect.Intersects( parent ) )
       
  1105                 {
       
  1106                 field->Draw( screenRect );
       
  1107                 }
       
  1108             // Move next field top left corner
       
  1109             tl.iY += screenRect.Height();
       
  1110             }
       
  1111         }
       
  1112     }
       
  1113 
       
  1114 // ---------------------------------------------------------------------------
       
  1115 // CMRFieldContainer::ScrollContainer
       
  1116 // ---------------------------------------------------------------------------
       
  1117 //
       
  1118 void CMRFieldContainer::ScrollContainer( const TPoint& aTl )
       
  1119     {
       
  1120     FUNC_LOG;
       
  1121 
       
  1122     // Set scrolling flag and move focused field off screen
       
  1123     SetScrolling( ETrue );
       
  1124     // Update control position,
       
  1125     // but dont propagate the change to component controls
       
  1126     iPosition = aTl;
       
  1127     }
       
  1128 
       
  1129 // ---------------------------------------------------------------------------
       
  1130 // CMRFieldContainer::Synchronize
       
  1131 // ---------------------------------------------------------------------------
       
  1132 //
       
  1133 void CMRFieldContainer::Synchronize()
       
  1134     {
       
  1135     FUNC_LOG;
       
  1136 
       
  1137     // Set actual control positions (y-coordinate) to visible fields
       
  1138     TPoint tl( iPosition );
       
  1139 
       
  1140     TInt count( iFactory.Count() );
       
  1141 
       
  1142     for ( TInt i = 0; i < count; ++i )
       
  1143         {
       
  1144         CESMRField* field = iFactory.Field( i );
       
  1145         if ( field->IsVisible() )
       
  1146             {
       
  1147             TPoint pos( field->Position().iX, tl.iY );
       
  1148             tl.iY += field->Size().iHeight;
       
  1149             field->SetPosition( pos );
       
  1150             }
       
  1151         }
       
  1152     SetScrolling( EFalse );
       
  1153     }
       
  1154 
       
  1155 // End of file