meetingrequest/mrgui/src/cmrfieldcontainer.cpp
branchRCL_3
changeset 12 4ce476e64c59
child 16 b5fbb9b25d57
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meetingrequest/mrgui/src/cmrfieldcontainer.cpp	Wed Mar 31 21:08:33 2010 +0300
@@ -0,0 +1,1007 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Field container for UI fields
+*
+*/
+#include "cmrfieldcontainer.h"
+#include "mesmrfieldstorage.h"
+#include "mmrfieldcontainerobserver.h"
+#include "cesmrfield.h"
+
+//DEBUG
+#include "emailtrace.h"
+
+namespace { // codescanner::namespace
+
+/**
+ * Vertical scroll margin
+ */
+const TInt KVerticalScrollMargin = 3;
+
+
+// ----------------
+// IndexByFieldId
+// ----------------
+//
+TInt IndexByFieldId( const MESMRFieldStorage& aFactory,
+                     TESMREntryFieldId aFieldId )
+    {
+    TInt index( KErrNotFound );
+    TInt count( aFactory.Count() );
+
+    for ( TInt i = 0; i < count; ++i )
+        {
+        if ( aFactory.Field( i )->FieldId() == aFieldId )
+            {
+            index = i;
+            break;
+            }
+        }
+
+    return index;
+    }
+}
+
+//----- MEMBER FUNCTIONS ----
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::CMRFieldContainer
+// ---------------------------------------------------------------------------
+//
+CMRFieldContainer::CMRFieldContainer( MESMRFieldStorage& aFactory )
+    : iFactory( aFactory )
+    {
+    FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::~CMRFieldContainer
+// ---------------------------------------------------------------------------
+//
+CMRFieldContainer::~CMRFieldContainer()
+    {
+    FUNC_LOG;
+    // No implementation
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::NewL
+// ---------------------------------------------------------------------------
+//
+CMRFieldContainer* CMRFieldContainer::NewL( 
+        MESMRFieldStorage& aFactory, 
+        const CCoeControl& aParent )
+    {
+    FUNC_LOG;
+    CMRFieldContainer* self = new( ELeave )CMRFieldContainer( aFactory );
+    CleanupStack::PushL( self );
+    self->ConstructL( aParent );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::ConstructL( const CCoeControl& aParent )
+    {
+    FUNC_LOG;
+    CCoeControl::SetComponentsToInheritVisibility( ETrue );
+    SetContainerWindowL( aParent );
+    
+    TBool focusSet( EFalse );
+    const TInt count( iFactory.Count() );
+    for ( TInt i = 0; i < count; i++ )
+        {
+        iFactory.Field(i)->SetContainerWindowL( *this );
+        }
+
+    for ( TInt i = 0; i < count; i++ )
+        {
+        CESMRField* field = iFactory.Field( i );
+
+        // Initialize field
+        field->InitializeL();
+        User::LeaveIfError( field->SetParent( this ) );
+
+        if ( !focusSet
+             && field->IsVisible()
+             && !field->IsNonFocusing())
+            {
+            field->SetOutlineFocusL( ETrue );
+            focusSet = ETrue;
+            iFocusedFieldIndex = i;
+            }
+        }
+
+    for ( TInt i = 0; i < count; i++ )
+        {
+        CESMRField* field = iFactory.Field( i );
+
+        field->SetListObserver( this );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::FocusedItem
+// ---------------------------------------------------------------------------
+//
+CESMRField* CMRFieldContainer::FocusedField() const
+    {
+    FUNC_LOG;
+    /*
+     * Returns currently focused field
+     */
+    CESMRField* field = NULL;
+    if ( iFactory.Count() > 0 )
+        {
+        field = iFactory.Field( iFocusedFieldIndex );
+        }
+    return field;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::MoveFocusUpL
+// ---------------------------------------------------------------------------
+//
+TKeyResponse CMRFieldContainer::MoveFocusUpL( TBool aHiddenFocus )
+    {
+    FUNC_LOG;
+    /*
+     * Moves focus up after key event. If aHiddenFocus, moves focus 
+     * to the first visible field in the bottom of the viewable area.
+     */
+     
+    if( aHiddenFocus )
+        {
+        return MoveFocusVisibleL();
+        }
+    else
+        {
+        TInt ind( iFocusedFieldIndex );
+
+        // search next visible focus item
+        while ( ind > 0 )
+            {
+            CESMRField* field = iFactory.Field( --ind );
+
+            if ( !field->IsNonFocusing() )
+                {
+                field = iFactory.Field( ind );
+
+                CESMRField* focusedField = iFactory.Field( iFocusedFieldIndex );
+                if ( field->IsVisible() )
+                    {
+                    TBool canLoseFocus(
+                            focusedField->OkToLoseFocusL( field->FieldId() ) );
+
+                    if ( canLoseFocus )
+                        {
+                        field->SetPreItemIndex( iFocusedFieldIndex );
+                        iFocusedFieldIndex = ind;
+                        field->SetCurrentItemIndex( iFocusedFieldIndex );
+
+                        // Remove focus from previous position 
+                        focusedField->SetOutlineFocusL( EFalse );
+                        focusedField->SetFocus( EFalse );
+                        
+                        // Set focus to new position
+                        field->SetOutlineFocusL( ETrue );
+                        field->SetFocus( ETrue );
+
+                        // Scrollbar and physics update is done here
+                        ScrollControlVisible( iFocusedFieldIndex );
+                        
+                        DrawDeferred();
+                        }
+
+                    return EKeyWasConsumed;
+                    }
+                }
+            }
+        return EKeyWasNotConsumed;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::MoveFocusDownL
+// ---------------------------------------------------------------------------
+//
+TKeyResponse CMRFieldContainer::MoveFocusDownL( TBool aHiddenFocus )
+    {
+    FUNC_LOG;
+    /*
+     * Moves focus down after key event. If aHiddenFocus, moves focus 
+     * to the first visible field in the top of the viewable area.
+     */
+    
+    if( aHiddenFocus )
+        {
+        return MoveFocusVisibleL();
+        }
+    else
+        {
+        TInt ind( iFocusedFieldIndex );
+
+        // start searching next possible focus item
+        TInt maxItemIndex = iFactory.Count() - 1;
+
+        while ( ind < maxItemIndex )
+            {
+            // only visible and focusable items can be focused
+            CESMRField* field = iFactory.Field( ++ind );
+
+            if ( field->IsVisible() && !field->IsNonFocusing() )
+                {
+                CESMRField* focusedField = iFactory.Field( iFocusedFieldIndex );
+
+                TBool canLoseFocus(
+                        focusedField->OkToLoseFocusL( field->FieldId() ) );
+
+                // check it its ok for the old focus item to lose focus
+                if ( canLoseFocus )
+                    {
+                    field->SetPreItemIndex( iFocusedFieldIndex );
+                    iFocusedFieldIndex = ind;
+                    field->SetCurrentItemIndex( iFocusedFieldIndex );
+
+                    // Remove focus from previous position 
+                    focusedField->SetOutlineFocusL( EFalse );
+                    focusedField->SetFocus( EFalse );
+                    
+                    // Set focus to new position
+                    field->SetOutlineFocusL( ETrue );
+                    field->SetFocus( ETrue );
+
+                    // Scrollbar and physics update is done here
+                    ScrollControlVisible( iFocusedFieldIndex );
+                    
+                    DrawDeferred();
+                    }
+
+                return EKeyWasConsumed;
+                }
+            }
+        return EKeyWasNotConsumed;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::MoveFocusVisibleL
+// ---------------------------------------------------------------------------
+//
+TKeyResponse CMRFieldContainer::MoveFocusVisibleL()
+    {
+    FUNC_LOG;
+    /*
+     * Move focus to first completely visible field in the view, 
+     * if focus was in a field that was not visible in the view.
+     * Use case: After pointer scroll focus is hidden. User presses
+     * arrow keys -> Focus appears to the first visible field on the upper
+     * or bottom part of the viewable area.
+     */
+    
+    TKeyResponse response( EKeyWasNotConsumed );
+
+    CESMRField* focusedField = FocusedField();
+    CESMRField* visibleField = NULL;
+    TRect view( Parent()->Rect() );
+
+    // Focus is above the visible view area
+    if ( focusedField->Rect().iBr.iY <= view.iTl.iY )
+        {
+        // Move focus to next visible field
+        TInt lastIndex = iFactory.Count() - 1;
+        TInt ind( iFocusedFieldIndex );
+        while ( ind < lastIndex && !visibleField )
+            {
+            visibleField = iFactory.Field( ++ind );
+            TRect fieldRect = visibleField->Rect();
+            if ( visibleField->IsVisible()
+                 && !visibleField->IsNonFocusing()
+                 && fieldRect.iTl.iY >= view.iTl.iY )
+                {
+                // Update previous and current field indexes
+                visibleField->SetPreItemIndex( iFocusedFieldIndex );
+                iFocusedFieldIndex = ind;
+                visibleField->SetCurrentItemIndex( iFocusedFieldIndex );
+                }
+            else
+                {
+                visibleField = NULL;
+                }
+            }
+        }
+    // Focus is below the visible view area
+    else
+        {
+        // Move focus to previous visible field
+        TInt ind( iFocusedFieldIndex );
+        while ( ind > 0 && !visibleField )
+            {
+            visibleField = iFactory.Field( --ind );
+            TRect fieldRect = visibleField->Rect();
+            if ( visibleField->IsVisible()
+                 && !visibleField->IsNonFocusing()
+                 && fieldRect.iBr.iY <= view.iBr.iY )
+                {
+                // Update previous and current field indexes
+                visibleField->SetPreItemIndex( iFocusedFieldIndex );
+                iFocusedFieldIndex = ind;
+                visibleField->SetCurrentItemIndex( iFocusedFieldIndex );
+                }
+            else
+                {
+                visibleField = NULL;
+                }
+            }
+        }
+
+    if ( visibleField )
+        {
+        // Remove existing focus
+        focusedField->SetOutlineFocusL( EFalse );
+        focusedField->SetFocus( EFalse );
+        
+        // Set focus to new field
+        visibleField->SetOutlineFocusL( ETrue );
+        visibleField->SetFocus( ETrue );
+
+        response = EKeyWasConsumed;
+        
+        DrawDeferred();
+        }
+    
+    return response;
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::SetFieldContainerObserver
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::SetFieldContainerObserver( 
+        MMRFieldContainerObserver* aObserver )
+    {
+    FUNC_LOG;
+    iObserver = aObserver;
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::CountComponentControls
+// ---------------------------------------------------------------------------
+//
+TInt CMRFieldContainer::CountComponentControls() const
+    {
+    FUNC_LOG;
+    return iFactory.Count();
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::ComponentControl
+// ---------------------------------------------------------------------------
+//
+CCoeControl* CMRFieldContainer::ComponentControl( TInt aIndex ) const
+    {
+    FUNC_LOG;
+    return iFactory.Field( aIndex );
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::MinimumSize
+// ---------------------------------------------------------------------------
+//
+TSize CMRFieldContainer::MinimumSize()
+    {
+    FUNC_LOG;
+    /*
+     * Returns the minimum size required by the field container
+     */
+    
+    TSize containerSize;
+    
+    const TInt count( iFactory.Count() );
+    
+    for ( TInt i(0); i < count; ++i )
+        {
+        CESMRField* field = iFactory.Field( i );
+        if ( field->IsVisible() )
+            {
+            TRect rect( field->Rect() );
+            containerSize.iHeight += rect.Height();
+            }
+        }
+    
+    containerSize.iWidth = Parent()->Rect().Width();
+    
+    return containerSize;
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::SizeChanged
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::SizeChanged()
+    {
+    FUNC_LOG;
+    
+    // TEST CODE:
+    TRect fieldcontainerRect = Rect();
+    TRect parentRect = Parent()->Rect();
+    
+
+    // For example when orientation changes, we might need to scroll 
+    // the currently focused control visible again. This handles also
+    // scrollbar and physics updates.
+    ScrollControlVisible( KErrNotFound ); 
+    
+    TPoint tl( Position() );
+
+    const TInt count( iFactory.Count() );
+
+    // Loop all the visible fields and set size and position in the list
+    for ( TInt i = 0; i < count; i++ )
+        {
+        CESMRField* field = iFactory.Field( i );
+
+        if ( field->IsVisible() )
+            {
+            LayoutField( *field, tl );
+
+            TInt height = field->Size().iHeight;
+            tl.iY += height;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::ControlSizeChanged
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::ControlSizeChanged( CESMRField* aField )
+    {
+    FUNC_LOG;
+    /*
+     * Called whenever a fields size has changed. Requires always 
+     * relayouting. 
+     */
+
+    if ( !aField )
+        {
+        SizeChanged();
+        }
+    else
+        {
+        // Relayout field if size has changed
+        TSize old( aField->Size() );
+        TSize size( aField->MinimumSize() );
+        if( size != old )
+            {
+            aField->SetSize( size );
+            
+            TPoint tl( aField->Position() );
+            TInt index = IndexByFieldId( iFactory, aField->FieldId() );
+
+            // Move fields below this particular field
+            tl.iY += size.iHeight;
+            MoveFields( index + 1, tl );
+
+            // Fields have been re-layouted / moved. This requires resetting
+            // the size of this field container.
+            SetSize( MinimumSize() );
+            
+            // Update also scrollbar and physics
+            iObserver->UpdateScrollBarAndPhysics();
+            
+            if( index == iFocusedFieldIndex )
+                {
+                // Scroll this field completely visible, if required.
+                // This updates also scrollbar and physics if scrolling 
+                // is done.
+                ScrollControlVisible( iFocusedFieldIndex );
+                }
+            
+            DrawDeferred();
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::ShowControl
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::ShowControl( TESMREntryFieldId aFieldId )
+    {
+    FUNC_LOG;
+    /*
+     * Inserts field visible and layouts it.
+     */
+    
+    CESMRField* field = iFactory.FieldById( aFieldId );
+
+    if ( field && !field->IsVisible() )
+        {
+        // Make field visible
+        field->MakeVisible( ETrue );
+        TInt index = IndexByFieldId( iFactory, aFieldId );
+
+        TPoint tl( Rect().iTl );
+        TInt prevIndex = index - 1;
+
+        // Get previous visible field position
+        // Index 0 must be included in attendee field case, 
+        // to avoid field collision. But in response field, 
+        // causes misplacing of area.
+        if ( ( prevIndex >= 0 ) && ( aFieldId != EESMRFieldResponseArea ) )
+            {
+            CESMRField* previous = NULL;
+            do
+                {
+                previous = iFactory.Field( prevIndex-- );
+                }
+            while ( prevIndex >= 0 && !previous->IsVisible() );
+
+            tl.iY = previous->Rect().iBr.iY;
+            }
+
+        // Layout field
+        LayoutField( *field, tl);
+
+        // Move following fields
+        tl.iY += field->Size().iHeight;
+        MoveFields( ++index, tl );
+
+        // Set fieldcontainer size again, because 
+        // the amount of fields has changed.
+        SetSize( MinimumSize() );
+        
+        // Scrollbar and physics require updating.
+        iObserver->UpdateScrollBarAndPhysics();
+        }
+    
+    DrawDeferred();
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::HideControl()
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::HideControl( TESMREntryFieldId aFieldId )
+    {
+    FUNC_LOG;
+    /*
+     * Sets field non-visible and moves other fields accordingly.
+     * Does not delete the field. 
+     */
+    CESMRField* field = iFactory.FieldById( aFieldId );
+
+    if ( field && field->IsVisible() )
+        {
+        field->MakeVisible( EFalse );
+        TInt index = IndexByFieldId( iFactory, aFieldId );
+        TBool focused = ( index == iFocusedFieldIndex )? ETrue : EFalse;
+
+        TPoint pos( field->Position() );
+        MoveFields( index, pos );
+
+        // Set fieldcontainer size again, because 
+        // the amount of fields has changed.
+        SetSize( MinimumSize() );
+        
+        // Scrollbar and physics require updating.
+        iObserver->UpdateScrollBarAndPhysics();
+        
+        if ( focused && !field->IsNonFocusing() )            
+            {
+            // Set focus to next field, or if removed field was the last 
+            // field, then move focus to last visible field
+            TInt lastVisibleFieldIndex( LastVisibleField( aFieldId ) ); 
+            
+            // If field was the last one...
+            if( lastVisibleFieldIndex == index )
+                {
+                // ... Set focus to last visible field.
+                TRAP_IGNORE( DoSetFocusL( lastVisibleFieldIndex ) )
+                }
+            else
+                {
+                // Othwerwise set focus to next field
+                TRAP_IGNORE( DoSetFocusL( index + 1 ) )
+                }
+            }
+        }
+    DrawDeferred();
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::IsControlVisible
+// ---------------------------------------------------------------------------
+//
+TBool CMRFieldContainer::IsControlVisible( TESMREntryFieldId aField )
+    {
+    FUNC_LOG;
+    /*
+     * Returns ETrue/EFalse if the field with given field id is 
+     * visible or not.
+     */
+    
+    TBool ret( EFalse );
+
+    CESMRField* field = iFactory.FieldById( aField );
+    if ( field && field->IsVisible() )
+        {
+        ret = ETrue;
+        }
+
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::SetControlFocused
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::SetControlFocusedL( TESMREntryFieldId aField )
+    {
+    FUNC_LOG;
+    /*
+     * Set the field with given field id focused.
+     */
+
+    // This handles scrollbar and physics updates also.
+    DoSetFocusL( IndexByFieldId( iFactory, aField ) );
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::ListHeight
+// ---------------------------------------------------------------------------
+//
+TInt CMRFieldContainer::ListHeight()
+    {
+    FUNC_LOG;
+    /*
+     * Returns the height of all fields, in other words the height
+     * of the field container.
+     */
+    return MinimumSize().iHeight;
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::IsFocusedControlsBottomVisible
+// ---------------------------------------------------------------------------
+//
+TBool CMRFieldContainer::IsFocusedControlsBottomVisible()
+    {
+    FUNC_LOG;
+    /*
+     * Checks if focused field is completely visible in the viewable area. 
+     */
+    
+    // Fetch the position information about currently focused field:
+    CESMRField* field = iFactory.Field( iFocusedFieldIndex );
+    TBool ret( EFalse );
+    if ( field->Rect().iBr.iY <= Parent()->Rect().iBr.iY )
+       {
+       ret = ETrue;
+       }
+
+    return ret;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::ScrollControlVisible
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::ScrollControlVisible( TInt aInd )
+    {
+    FUNC_LOG;
+    /*
+     * Scrolls the field with the given index visible
+     */
+    
+    CESMRField* field = NULL;
+    if ( aInd == KErrNotFound )
+        {
+        field = FocusedField();
+        }
+    else
+        {
+        field = iFactory.Field( aInd );
+        }
+
+    ASSERT( field );
+    
+    TRect fieldRect( field->Position(), field->Size() );
+    TRect parentRect( Parent()->Rect() );
+    
+    /*
+     * Case 1: Field's height is less than the viewable area height,
+     * let's scroll the whole field visible.
+     */
+    if( fieldRect.Height() < parentRect.Height() )
+        {
+        // Scrolling down, let's move fields up
+        if( fieldRect.iBr.iY > parentRect.iBr.iY )
+            {
+            iObserver->ScrollFieldsUp( 
+                    fieldRect.iBr.iY - parentRect.iBr.iY );
+            }
+        // scrolling up, let's move field down
+        if( fieldRect.iTl.iY < parentRect.iTl.iY )
+            {
+            iObserver->ScrollFieldsDown( 
+                    parentRect.iTl.iY - fieldRect.iTl.iY );
+            }
+        }
+    
+    /*
+     * Case 2: Field's height is more than the viewable area's height.
+     */
+    else
+        {
+        // Field is in view mode
+        if( field->FieldMode() == EESMRFieldModeView )
+            {
+            // Focus to this field is coming from above
+            if( field->PreItemIndex() < field->CurrentItemIndex() )
+                {
+                // Let's scroll the top of the field to the 
+                // top of the viewable area
+                iObserver->ScrollFieldsUp( 
+                                   fieldRect.iTl.iY - parentRect.iTl.iY );
+                
+                }
+            // Focus to this field is coming from below
+            if( field->PreItemIndex() > field->CurrentItemIndex() )
+                {
+                // Let's scroll the bottom of the field to the
+                // bottom of the viewable area
+                iObserver->ScrollFieldsDown( 
+                                   parentRect.iBr.iY - fieldRect.iBr.iY );
+                }
+            }
+        
+        // Field is in edit mode
+        if( field->FieldMode() == EESMRFieldModeEdit )
+            {
+            // TODO: CORRECT if broken
+            TInt viewBottom( parentRect.iBr.iY );
+
+            TInt fieldUpper( 0 );
+            TInt fieldLower( 0 );
+            field->GetCursorLineVerticalPos( fieldUpper, fieldLower );
+
+            TInt focusFieldVisibleUp( fieldRect.iTl.iY + fieldUpper );
+            TInt focusFieldVisibleBottom( fieldRect.iTl.iY + fieldLower );
+
+            // desired position below view rect:
+            TInt viewHeight( parentRect.Height() );
+            if ( focusFieldVisibleBottom > viewBottom )
+                {
+                // move field focus line bottom to view bottom
+                TInt px = focusFieldVisibleBottom - viewHeight;
+
+                
+                // if focus on last field: add margin height to
+                // scroll amount.
+                if ( iFocusedFieldIndex == iFactory.Count()-1 )
+                    {
+                    px += KVerticalScrollMargin; // TODO: Fix me! K-value must be removed.
+                    }
+                
+                // Scrollbar and physics update is done here
+                iObserver->ScrollFieldsUp( px );
+                }
+            else
+                {
+                // If field top is invisible, move downwards to make top visible.
+                TInt viewTop( parentRect.iTl.iY );
+
+                // recalculate field rect
+                focusFieldVisibleUp = fieldRect.iTl.iY + fieldUpper;
+                focusFieldVisibleBottom = fieldRect.iTl.iY + fieldLower;
+
+                if ( focusFieldVisibleUp < viewTop )
+                    {
+                    TInt px( viewTop - focusFieldVisibleUp );
+
+                    // Scrollbar and physics update is done here
+                    iObserver->ScrollFieldsDown( px );
+                    }
+                }
+            }        
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::RePositionFields
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::RePositionFields( TInt aAmount )
+    {
+    FUNC_LOG;
+    
+    // Movement downwards
+    if( aAmount >= 0 )
+        {
+        // Also scrollbar and physics update is done here
+        iObserver->ScrollFieldsDown( aAmount );
+        }
+    // Movement upwards
+    else
+        {
+        // Also scrollbar and physics update is done here
+        iObserver->ScrollFieldsUp( -aAmount );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::ViewableAreaRect
+// ---------------------------------------------------------------------------
+//
+TRect CMRFieldContainer::ViewableAreaRect()
+    {
+    FUNC_LOG;
+    return Parent()->Rect();
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::MoveFields
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::MoveFields( TInt aIndex, TPoint& aTl )
+    {
+    FUNC_LOG;
+    /*
+     * Moves fields from the given index towards the last item. 
+     * This function does not update scrollbar or physics.
+     */
+    
+    const TInt count( iFactory.Count() );
+    
+    for ( TInt i = aIndex; i < count; ++i )
+        {
+        CESMRField* field = iFactory.Field( i );
+        
+        if ( field->IsVisible() )
+            {
+            field->SetPosition( aTl );
+            
+            aTl.iY += field->Size().iHeight;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::LayoutField
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::LayoutField( CESMRField& aField, const TPoint& aTl )
+    {
+    FUNC_LOG;
+    /*
+     * Layouts given field according to the size required by the field and
+     * given TPoint. This function does not update scrollbar or physics.
+     */
+    
+    TSize size( aField.MinimumSize() );
+    aField.SetPosition( aTl );
+    aField.SetSize( size );
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::IsLastVisibleField
+// ---------------------------------------------------------------------------
+//
+TInt CMRFieldContainer::LastVisibleField( 
+        TESMREntryFieldId aFieldId )
+    {
+    /*
+     * Helper function to find out the last visible field in the list.
+     */
+    
+    TInt lastVisibleFieldIndex( 0 );
+    TInt count( iFactory.Count() );
+    
+    // Go through fields from last field towards the first field
+    for( TInt i( 1 ); i > count; ++i )
+        {
+        // Once last visible field is found...
+        if( iFactory.Field( count - i )->IsVisible() )
+            {
+            // ... Compare it to the given field index ...
+            if( iFactory.Field( count - i )->FieldId() == aFieldId )
+                {
+                // ... And if match is found, given fieldId is the 
+                // the last visible field.
+                lastVisibleFieldIndex = 
+                    IndexByFieldId( iFactory, aFieldId );
+                }
+            else
+                {
+                // Otherwise return the found last visible field.
+                lastVisibleFieldIndex = 
+                    IndexByFieldId( iFactory, 
+                                    iFactory.Field( count - i )->FieldId() );
+                }
+            break;
+            }
+        }
+    
+    return lastVisibleFieldIndex;
+    }
+
+// ---------------------------------------------------------------------------
+// CMRFieldContainer::DoSetFocusL
+// ---------------------------------------------------------------------------
+//
+void CMRFieldContainer::DoSetFocusL( TInt aNewFocusIndex )
+    {
+    FUNC_LOG;
+    /*
+     * Sets the focus according to the given index.
+     */
+    
+    TInt count( iFactory.Count() );
+    aNewFocusIndex = Max( 0, Min( aNewFocusIndex, count - 1 ) );
+
+    if ( aNewFocusIndex != iFocusedFieldIndex )
+        {
+        // Get current focused field
+        CESMRField* old = iFactory.Field( iFocusedFieldIndex );
+
+        // Get next focused field
+        CESMRField* field = iFactory.Field( aNewFocusIndex );
+        
+        // Do sanity checks
+        while ( aNewFocusIndex < count && !field->IsVisible() )
+            {
+            field = iFactory.Field( aNewFocusIndex++ );
+            }
+
+        if ( !field->IsVisible() )
+            {
+            aNewFocusIndex = iFocusedFieldIndex - 1;
+            while ( aNewFocusIndex > 0 && !field->IsVisible() )
+                {
+                field = iFactory.Field( aNewFocusIndex-- );
+                }
+            }
+
+        ASSERT( field->IsVisible() );
+        
+        // Update current and previous item indexes
+        field->SetPreItemIndex( iFocusedFieldIndex );
+        iFocusedFieldIndex = aNewFocusIndex;
+        field->SetCurrentItemIndex( iFocusedFieldIndex );
+        
+        // Remove focus from old
+        old->SetOutlineFocusL( EFalse );
+        old->SetFocus( EFalse );
+        
+        // update focus index to new index
+        field->SetOutlineFocusL( ETrue );
+        field->SetFocus( ETrue );
+        
+        // This handles also scrollbar and physics updating,
+        // if view scrolling is done.
+        ScrollControlVisible( iFocusedFieldIndex ); 
+        
+        DrawDeferred();
+        }
+    }
+
+
+// End of file