diff -r 0396474f30f5 -r 4ce476e64c59 meetingrequest/mrgui/src/cmrlistpane.cpp --- a/meetingrequest/mrgui/src/cmrlistpane.cpp Mon Mar 15 12:39:10 2010 +0200 +++ b/meetingrequest/mrgui/src/cmrlistpane.cpp Wed Mar 31 21:08:33 2010 +0300 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2009-2009 Nokia Corporation and/or its subsidiary(-ies). +* 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" @@ -15,61 +15,64 @@ * */ #include "cmrlistpane.h" +#include "mesmrfieldstorage.h" +#include "mmrscrollbarobserver.h" +#include "esmrdef.h" +#include "cesmrfield.h" +#include "cmrfieldcontainer.h" +#include "cmrlistpanephysics.h" #include -#include -#include +#include -#include "mesmrfieldstorage.h" -#include "cesmrfield.h" - +//DEBUG #include "emailtrace.h" -namespace // codescanner::namespace - { - /** - * Vertical scroll margin - */ - const TInt KVerticalScrollMargin = 3; +namespace { // codescanner::namespace + +const TInt KLongTapDelay( 700000 ); // 0,7 sec +const TInt KLongTapAnimationDelay( 300000 ); // 0,3 sec - // --------------------------------------------------------------------------- - // IndexByFieldId - // --------------------------------------------------------------------------- - // - TInt IndexByFieldId( const MESMRFieldStorage& aFactory, - TESMREntryFieldId aFieldId ) +// ---------------- +// IndexByFieldId +// ---------------- +// +TInt IndexByFieldId( const MESMRFieldStorage& aFactory, + TESMREntryFieldId aFieldId ) + { + TInt index( KErrNotFound ); + TInt count( aFactory.Count() ); + + for ( TInt i = 0; i < count; ++i ) { - TInt index( KErrNotFound ); - TInt count( aFactory.Count() ); - - for ( TInt i = 0; i < count; ++i ) + if ( aFactory.Field( i )->FieldId() == aFieldId ) { - if ( aFactory.Field( i )->FieldId() == aFieldId ) - { - index = i; - break; - } + index = i; + break; } - - return index; } + + return index; } +} + //----- MEMBER FUNCTIONS ---- // --------------------------------------------------------------------------- -// CMRListPane::NewL +// CMRListPane::CMRListPane // --------------------------------------------------------------------------- // -CMRListPane* CMRListPane::NewL( const CCoeControl& aParent, - MESMRFieldStorage& aFactory, - TAknDoubleSpanScrollBarModel& aScrollModel ) +CMRListPane::CMRListPane( MESMRFieldStorage& aFactory, + TAknDoubleSpanScrollBarModel& aScrollModel, + CAknDoubleSpanScrollBar& aScroll, + MMRScrollBarObserver& aScrollBarObserver ) + : iFactory( aFactory ), + iScrollModel( aScrollModel ), + iScroll( aScroll ), + iScrollBarObserver( aScrollBarObserver ) { - CMRListPane* self = new (ELeave) CMRListPane( aFactory, aScrollModel ); - CleanupStack::PushL( self ); - self->ConstructL( aParent ); - CleanupStack::Pop( self ); - return self; + FUNC_LOG; } // --------------------------------------------------------------------------- @@ -78,17 +81,32 @@ // CMRListPane::~CMRListPane() { + FUNC_LOG; + delete iLongtapDetector; + delete iPhysics; + delete iFieldContainer; } // --------------------------------------------------------------------------- -// CMRListPane::CMRListPane +// CMRListPane::NewL // --------------------------------------------------------------------------- // -CMRListPane::CMRListPane( MESMRFieldStorage& aFactory, - TAknDoubleSpanScrollBarModel& aScrollModel ) - : iFactory( aFactory ), - iScrollModel( aScrollModel ) +CMRListPane* CMRListPane::NewL( const CCoeControl& aParent, + MESMRFieldStorage& aFactory, + TAknDoubleSpanScrollBarModel& aScrollModel, + CAknDoubleSpanScrollBar& aScroll, + MMRScrollBarObserver& aScrollBarObserver ) { + FUNC_LOG; + CMRListPane* self = new( ELeave )CMRListPane( + aFactory, + aScrollModel, + aScroll, + aScrollBarObserver ); + CleanupStack::PushL( self ); + self->ConstructL( aParent ); + CleanupStack::Pop( self ); + return self; } // --------------------------------------------------------------------------- @@ -97,64 +115,173 @@ // void CMRListPane::ConstructL( const CCoeControl& aParent ) { + FUNC_LOG; + CCoeControl::SetComponentsToInheritVisibility( ETrue ); SetContainerWindowL( aParent ); - TBool focusSet = EFalse; + + iLongtapDetector = CAknLongTapDetector::NewL( this ); + iLongtapDetector->SetLongTapDelay( KLongTapDelay ); + iLongtapDetector->SetTimeDelayBeforeAnimation( KLongTapAnimationDelay ); + + iFieldContainer = CMRFieldContainer::NewL( iFactory, *this ); + iFieldContainer->SetFieldContainerObserver( this ); + + // Physics: Create physics + // Give pointer to control that should be able to flick/drag + iPhysics = CMRListPanePhysics::NewL( *this, *iFieldContainer, *this ); + } + +// --------------------------------------------------------------------------- +// CMRListPane::InitializeL() +// --------------------------------------------------------------------------- +// +void CMRListPane::InitializeL() + { + FUNC_LOG; const TInt count( iFactory.Count() ); for ( TInt i = 0; i < count; i++ ) { - iFactory.Field(i)->SetContainerWindowL( *this ); + iFactory.Field(i)->InitializeL(); } + iClickedField = NULL; + } + - for ( TInt i = 0; i < count; i++ ) - { - CESMRField* field = iFactory.Field( i ); - - // Initialize field - field->InitializeL(); - User::LeaveIfError( field->SetParent( this ) ); +// --------------------------------------------------------------------------- +// CMRListPane::InternalizeL() +// --------------------------------------------------------------------------- +// +void CMRListPane::InternalizeL( MESMRCalEntry& aEntry ) + { + FUNC_LOG; + iFactory.InternalizeL( aEntry ); + + // This is called to make sure everything is drawn correctly + DrawDeferred(); + } + +// --------------------------------------------------------------------------- +// CMRListPane::ExternalizeL() +// --------------------------------------------------------------------------- +// +void CMRListPane::ExternalizeL( + MESMRCalEntry& aEntry, + TBool aForceValidation ) + { + FUNC_LOG; + CESMRField* currentFocus = FocusedField(); + ASSERT( currentFocus ); + TESMREntryFieldId id = currentFocus->FieldId(); - if ( !focusSet - && field->IsVisible() - && !field->IsNonFocusing()) + if ( aForceValidation ) + { + // force validate the values: + TInt err = iFactory.Validate( id, aForceValidation ); + // fill the calendar entry with data in fields. + iFactory.ExternalizeL( aEntry ); + } + else + { + TInt err = iFactory.Validate( id ); + if ( err ) + { + //SetControlFocusedL( id ); Why would we set this focused here? + User::Leave( err ); + } + else { - field->SetOutlineFocusL( ETrue ); - focusSet = ETrue; - iFocus = i; + // fill the calendar entry with data in fields. + iFactory.ExternalizeL( aEntry ); } - } + } + } + +// --------------------------------------------------------------------------- +// CMRListPane::DisableSizeChange() +// --------------------------------------------------------------------------- +// +void CMRListPane::DisableSizeChange(TBool aDisable ) + { + FUNC_LOG; + iDisableSizeChanged = aDisable; } // --------------------------------------------------------------------------- +// CMRListPane::InitialScroll +// --------------------------------------------------------------------------- +// +void CMRListPane::InitialScrollL() + { + FUNC_LOG; + // TODO: Fix or remove! L-Function called in non-leaving function! + // Suggestion: Move functionality to viewerdialog and use existing + // functions in listpane to do the required actions. + + // Check if the ResponseArea exist + TESMREntryFieldId id = GetResponseFieldsFieldId(); + + if( id == EESMRFieldResponseArea ) + { + // Set the focus on the ResponseArea + iFieldContainer->SetControlFocusedL( id ); + //iFactory.FieldById(id)->SetFocus( ETrue ); + + // Scroll the list to put the ResponseArea on the top + CESMRField* focusField = FocusedField(); + TPoint pos( focusField->Position() ); + ScrollFieldsUp(pos.iY); + } + } + + +// --------------------------------------------------------------------------- // CMRListPane::FocusedItem // --------------------------------------------------------------------------- // -CESMRField* CMRListPane::FocusedItem() const +CESMRField* CMRListPane::FocusedField() const + { + FUNC_LOG; + return iFieldContainer->FocusedField(); + } + +// --------------------------------------------------------------------------- +// CMRListPane::SetControlFocusedL +// --------------------------------------------------------------------------- +// +void CMRListPane::SetControlFocusedL( TESMREntryFieldId aFieldId ) { FUNC_LOG; - CESMRField* field = NULL; - if ( iFactory.Count() > 0 ) - { - field = iFactory.Field( iFocus ); - } - return field; + iFieldContainer->SetControlFocusedL( aFieldId ); } - + +// --------------------------------------------------------------------------- +// CMRListPane::ClickedItem +// --------------------------------------------------------------------------- +// +CESMRField* CMRListPane::ClickedField() const + { + return iClickedField; + } + // --------------------------------------------------------------------------- // CMRListPane::CountComponentControls // --------------------------------------------------------------------------- // TInt CMRListPane::CountComponentControls() const { - return iFactory.Count(); + FUNC_LOG; + return 1; // iFieldContainer + } // --------------------------------------------------------------------------- // CMRListPane::ComponentControl // --------------------------------------------------------------------------- // -CCoeControl* CMRListPane::ComponentControl( TInt aIndex ) const +CCoeControl* CMRListPane::ComponentControl( TInt /*aIndex*/ ) const { - return iFactory.Field( aIndex ); + FUNC_LOG; + return iFieldContainer; } // --------------------------------------------------------------------------- @@ -163,35 +290,19 @@ // void CMRListPane::SizeChanged() { - TPoint tl( Position() ); - TInt scrollSpan = 0; - // Loop all the visible fields and set size and position in the list - TBool topVisibleFound( EFalse ); - - const TInt count( iFactory.Count() ); - for ( TInt i = 0; i < count; i++ ) + FUNC_LOG; + if ( iDisableSizeChanged || Rect() == TRect( 0, 0, 0, 0 ) ) { - CESMRField* field = iFactory.Field( i ); - - if ( field->IsVisible() ) - { - LayoutField( *field, tl ); - - if ( !topVisibleFound ) - { - iTopVisibleIndex = i; - topVisibleFound = ETrue; - } - - TInt height = field->Size().iHeight; - tl.iY += height; - scrollSpan += height; - } + return; } + + TSize containerSize( iFieldContainer->MinimumSize() ); + iFieldContainer->SetSize( containerSize ); - iScrollModel.SetScrollSpan( scrollSpan ); - iScrollModel.SetWindowSize( iSize.iHeight ); - UpdateFocusPosition(); + // Physics: + iPhysics->InitPhysics(); + + DoUpdateScrollBar(); } // --------------------------------------------------------------------------- @@ -201,737 +312,111 @@ TKeyResponse CMRListPane::OfferKeyEventL( const TKeyEvent &aKeyEvent, TEventCode aType ) { + FUNC_LOG; TKeyResponse response( EKeyWasNotConsumed ); + + // First check if the focused item needs the key event + response = FocusedField()->OfferKeyEventL( aKeyEvent, aType ); - // If we have at least one item in the list - if ( iFocus < iFactory.Count() ) + if ( aType == EEventKey + && response == EKeyWasNotConsumed ) { - CESMRField* field = iFactory.Field( iFocus ); - // First check if the focused item needs the key event - response = field->OfferKeyEventL( aKeyEvent, aType ); - - if ( aType == EEventKey - && response == EKeyWasNotConsumed ) + // Check if the focus should be changed + switch ( aKeyEvent.iScanCode ) { - // Check if the focus should be changed - switch ( aKeyEvent.iScanCode ) + case EStdKeyUpArrow: { - case EStdKeyUpArrow: - { - response = MoveFocusUpL(); - break; - } - case EStdKeyDownArrow: - { - response = MoveFocusDownL(); - break; - } - default: - { - break; - } + response = iFieldContainer->MoveFocusUpL( HiddenFocus() ); + + // Focus changed via keyboard, iClickedItem is no + // longer valid + iClickedField = NULL; + break; + } + case EStdKeyDownArrow: + { + response = iFieldContainer->MoveFocusDownL( HiddenFocus() ); + + // Focus changed via keyboard, iClickedItem is no + // longer valid + iClickedField = NULL; + break; + } + default: + { + break; } } } + return response; } // --------------------------------------------------------------------------- -// CMRListPane::ControlSizeChanged -// --------------------------------------------------------------------------- -// -void CMRListPane::ControlSizeChanged( CESMRField* aCtrl ) - { - if ( !aCtrl ) - { - SizeChanged(); - } - else - { - TPoint tl( aCtrl->Position() ); - TInt index = IndexByFieldId( iFactory, aCtrl->FieldId() ); - - // Relayout aCtrl - TSize old( aCtrl->Size() ); - TSize size( aCtrl->MinimumSize() ); - if ( aCtrl->IsExpandable() ) - { - size.iHeight = aCtrl->ExpandedHeight(); - } - aCtrl->SetSize( size ); - iScrollModel.SetScrollSpan( iScrollModel.ScrollSpan() - + size.iHeight - old.iHeight ); - - // Move other fields - ++index; - tl.iY += size.iHeight; - MoveFields( index, tl ); - UpdateFocusPosition(); - } - } - -// --------------------------------------------------------------------------- -// CMRListPane::InsertControl -// --------------------------------------------------------------------------- -// -void CMRListPane::InsertControl( TESMREntryFieldId aField ) - { - CESMRField* field = iFactory.FieldById( aField ); - - if ( field && !field->IsVisible() ) - { - // Make field visible - field->MakeVisible( ETrue ); - TInt index = IndexByFieldId( iFactory, aField ); - if ( index < iTopVisibleIndex ) - { - iTopVisibleIndex = index; - } - - TPoint tl( Rect().iTl ); - TInt prevIndex = index - 1; - - // Get previous visible field position - if ( prevIndex >= 0 ) - { - CESMRField* previous = NULL; - do - { - previous = iFactory.Field( prevIndex-- ); - } - while ( prevIndex >= 0 && !previous->IsVisible() ); - - tl.iY = previous->Rect().iBr.iY; - } - - // Layout field - LayoutField( *field, tl ); - iScrollModel.SetScrollSpan( iScrollModel.ScrollSpan() - + field->Size().iHeight ); - - // Move following fields - tl.iY += field->Size().iHeight; - MoveFields( ++index, tl ); - UpdateFocusPosition(); - } - } - -// --------------------------------------------------------------------------- -// CMRListPane::InsertControl -// --------------------------------------------------------------------------- -// -void CMRListPane::RemoveControl( TESMREntryFieldId aField ) - { - CESMRField* field = iFactory.FieldById( aField ); - - if ( field && field->IsVisible() ) - { - field->MakeVisible( EFalse ); - iScrollModel.SetScrollSpan( iScrollModel.ScrollSpan() - field->Size().iHeight ); - TInt index = IndexByFieldId( iFactory, aField ); - TBool focused = ( index == iFocus )? ETrue : EFalse; - - if ( index == iTopVisibleIndex ) - { - // Find next - TInt count( iFactory.Count() ); - while ( index < count ) - { - if ( iFactory.Field( ++index )->IsVisible() ) - { - iTopVisibleIndex = index; - break; - } - } - } - else - { - ++index; - } - TPoint pos( field->Position() ); - MoveFields( index, pos ); - if ( focused && !field->IsNonFocusing() ) - { - TRAP_IGNORE( DoSetFocusL( index ) ) - } - UpdateFocusPosition(); - } - } - -// --------------------------------------------------------------------------- -// CMRListPane::IsControlVisible -// --------------------------------------------------------------------------- -// -TBool CMRListPane::IsControlVisible( TESMREntryFieldId aField ) - { - TBool visible( EFalse ); - CESMRField* field = iFactory.FieldById( aField ); - - if ( field ) - { - visible = field->IsVisible(); - } - - return visible; - } - -// --------------------------------------------------------------------------- -// CMRListPane::SetControlFocusedL -// --------------------------------------------------------------------------- -// -void CMRListPane::SetControlFocusedL( TESMREntryFieldId aField ) - { - TInt count = iFactory.Count(); - for ( TInt i(0); i < count; i++ ) - { - CESMRField* field = iFactory.Field(i); - - if ( field->FieldId() == aField ) - { - if( field->IsVisible() && !field->IsNonFocusing() ) - { - // Remove current focus before setting new one - CESMRField* focusedField = FocusedItem(); - ASSERT( focusedField ); - focusedField->SetOutlineFocusL( EFalse ); - - // Set new focus - field->SetOutlineFocusL( ETrue ); - iFocus = i; - break; - } - else - { - // Not possible to set focus to non-visible control - User::Leave( KErrGeneral ); - } - } - } - } - -// SCROLLING_MOD: These two methods are for CESMRRichTextViewer to -// be able to control view area -// --------------------------------------------------------------------------- -// CMRListPane::MoveListAreaDownL -// --------------------------------------------------------------------------- -// -void CMRListPane::MoveListAreaDownL( TInt aAmount ) - { - FUNC_LOG; - // Method for CESMRRichTextViewer for moving view area down if the text in - // text field does not fit on the screen. - - // Fetch the position info about the first visible field in field set: - CESMRField* field; - if( iTopVisibleIndex != KErrNotFound ) - { - field = iFactory.Field( iTopVisibleIndex ); - } - else - { - field = iFactory.Field( iFactory.Count() - 1 ); - } - TRect rect( field->Rect() ); - - // check whether the first field is visible, if not, let's - // check should we scroll less than needed to get the first - // field shown. - if ( rect.iTl.iY + aAmount > Rect().iTl.iY ) - { - aAmount = Rect().iTl.iY - rect.iTl.iY + KVerticalScrollMargin; - } - else if ( rect.iTl.iY == Rect().iTl.iY ) - { - // field already visible, do not scroll. - aAmount = 0; - } - - // Do the view scrolling if needed: - if ( aAmount ) - { - ScrollItemsDown( aAmount ); - UpdateFocusPosition(); - //UpdateScrollBar(); - DrawDeferred(); - } - } - -// --------------------------------------------------------------------------- -// CMRListPane::MoveListAreaUpL +// CMRListPane::HandleLongTapEventL // --------------------------------------------------------------------------- // -void CMRListPane::MoveListAreaUpL( TInt aAmount ) - { - FUNC_LOG; - // Fetch the position information about currently focused field: - CESMRField* field = iFactory.Field( iFocus ); - TRect rect( field->Rect() ); - - // check whether the scroll pixels should be less than normal - // scroll sequence to let the field bottom to be placed at - // the bottom of view rect. - if ( rect.iBr.iY - aAmount < Rect().iBr.iY ) - { - aAmount = rect.iBr.iY - Rect().iBr.iY + KVerticalScrollMargin; - } - else if ( rect.iBr.iY + aAmount == Rect().iBr.iY ) - { - // field already visible, do not scroll. - aAmount = 0; - } - - // do the scrolling if needed: - if ( aAmount > 0 ) - { - // if the focus is on last - ScrollItemsUp( aAmount ); - UpdateFocusPosition(); - //UpdateScrollBar(); - DrawDeferred(); - } - } - -// --------------------------------------------------------------------------- -// CMRListPane::ListHeight -// --------------------------------------------------------------------------- -// -TInt CMRListPane::ListHeight() +void CMRListPane::HandleLongTapEventL( + const TPoint& aPenEventLocation, + const TPoint& /* aPenEventScreenLocation */ ) { FUNC_LOG; - return iSize.iHeight; - } - -// --------------------------------------------------------------------------- -// CMRListPane::IsFieldBottomVisible -// --------------------------------------------------------------------------- -// -TBool CMRListPane::IsFieldBottomVisible() - { - // Fetch the position information about currently focused field: - CESMRField* field = iFactory.Field( iFocus ); - TBool ret( EFalse ); - if ( field->Rect().iBr.iY <= Rect().iBr.iY ) - { - ret = ETrue; - } - - return ret; - } - -// --------------------------------------------------------------------------- -// CMRListPane::MoveFocusUpL -// --------------------------------------------------------------------------- -// -TKeyResponse CMRListPane::MoveFocusUpL() - { - TInt ind( iFocus ); - - // search next visible focus item - while ( ind > 0 ) - { - CESMRField* field = iFactory.Field( --ind ); - - if ( !field->IsNonFocusing() ) - { - field = iFactory.Field( ind ); - - CESMRField* focusedField = iFactory.Field( iFocus ); - if ( field->IsVisible() ) - { - TBool canLoseFocus( - focusedField->OkToLoseFocusL( field->FieldId() ) ); - - if ( canLoseFocus ) - { - iFocus = ind; - - // update focus index and scroll the item visible - focusedField->SetOutlineFocusL( EFalse ); - // This call changes the text color of previously - // focused field - focusedField->SetFocus( EFalse ); - field->SetOutlineFocusL( ETrue ); - // This call changes the text color of focused field - field->SetFocus( ETrue ); - - ScrollItemVisible( iFocus ); - } - return EKeyWasConsumed; - } - } - } - return EKeyWasNotConsumed; - } - -// --------------------------------------------------------------------------- -// CMRListPane::MoveFocusDownL -// --------------------------------------------------------------------------- -// -TKeyResponse CMRListPane::MoveFocusDownL() - { - TInt ind( iFocus ); - - // 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( iFocus ); - - TBool canLoseFocus( - focusedField->OkToLoseFocusL( field->FieldId() ) ); + iLongTapEventConsumed = EFalse; + // Long tap functionality may vary between fields + // ==> Command field to execute action related to long tap + TInt count( iFactory.Count() ); - // check it its ok for the old focus item to lose focus - if ( canLoseFocus ) - { - iFocus = ind; - - // update focus index and scroll the item visible - focusedField->SetOutlineFocusL( EFalse ); - // This call changes the text color of previously - // focused field - focusedField->SetFocus( EFalse ); - field->SetOutlineFocusL( ETrue ); - // This call changes the text color of focused field - field->SetFocus( ETrue ); - - ScrollItemVisible( iFocus ); - } - return EKeyWasConsumed; - } - } - return EKeyWasNotConsumed; - } - -// --------------------------------------------------------------------------- -// CMRListPane::MoveFocusL -// --------------------------------------------------------------------------- -// -TBool CMRListPane::MoveFocusL(TInt aNextFieldIndex) - { - // start searching next possible focus item - TInt maxItemIndex = iFactory.Count() - 1; - - CESMRField* focusedField = iFactory.Field( iFocus ); - - // only visible and focusable items can be focused - CESMRField* field = iFactory.Field( aNextFieldIndex ); - - if ( field->IsVisible() && !field->IsNonFocusing() ) - { - TBool canLoseFocus( - focusedField->OkToLoseFocusL( field->FieldId() ) ); - - // check it its ok for the old focus item to lose focus - if ( canLoseFocus ) - { - // tactile feedback if touch - if ( AknLayoutUtils::PenEnabled() ) - { - MTouchFeedback* feedback = MTouchFeedback::Instance(); - if ( feedback ) - { - feedback->InstantFeedback( this, ETouchFeedbackBasic ); - } - } - - iFocus = aNextFieldIndex; - - // update focus index and scroll the item visible - focusedField->SetOutlineFocusL( EFalse ); - // This call changes the text color of previously - // focused field - focusedField->SetFocus( EFalse ); - field->SetOutlineFocusL( ETrue ); - // This call changes the text color of focused field - field->SetFocus( ETrue ); - DrawDeferred(); - } - return ETrue; // operation succeed - } - return EFalse; - } - -// --------------------------------------------------------------------------- -// CMRListPane::LayoutField -// --------------------------------------------------------------------------- -// -void CMRListPane::LayoutField( CESMRField& aField, - const TPoint& aTl ) - { - TSize size( aField.MinimumSize() ); - if ( aField.IsExpandable() ) - { - size.iHeight = aField.ExpandedHeight(); - } - aField.SetPosition( aTl ); - aField.SetSize( size ); - } - -// --------------------------------------------------------------------------- -// CMRListPane::MoveFields -// --------------------------------------------------------------------------- -// -void CMRListPane::MoveFields( TInt aIndex, - TPoint& aTl ) - { - const TInt count( iFactory.Count() ); - - for ( TInt i = aIndex; i < count; ++i ) + for ( TInt i = 0; i < count; ++i ) { CESMRField* field = iFactory.Field( i ); - if ( field->IsVisible() ) + if ( field->IsVisible() + && field->Rect().Contains( aPenEventLocation ) ) { - field->SetPosition( aTl ); - - aTl.iY += field->Size().iHeight; + field->LongtapDetectedL( aPenEventLocation ); + iLongTapEventConsumed = ETrue; + break; } } } // --------------------------------------------------------------------------- -// CMRListPane::DoSetFocusL +// CMRListPane::DoUpdateScrollBar // --------------------------------------------------------------------------- // -void CMRListPane::DoSetFocusL( TInt aFocus ) - { - TInt count( iFactory.Count() ); - aFocus = Max( 0, Min( aFocus, count - 1 ) ); - - if ( aFocus != iFocus ) - { - // Get current focused field - CESMRField* old = iFactory.Field( iFocus ); - - // Get next focused field - CESMRField* field = iFactory.Field( aFocus ); - while ( aFocus < count && !field->IsVisible() ) - { - field = iFactory.Field( aFocus++ ); - } - - if ( !field->IsVisible() ) - { - aFocus = iFocus - 1; - while ( aFocus > 0 && !field->IsVisible() ) - { - field = iFactory.Field( aFocus-- ); - } - } - - ASSERT( field->IsVisible() ); - - // Remove focus from old - iFocus = aFocus; - // update focus index and scroll the item visible - old->SetOutlineFocusL( EFalse ); - // Change the text color of previously focused field - old->SetFocus( EFalse ); - field->SetOutlineFocusL( ETrue ); - // This call changes the text color of focused field - field->SetFocus( ETrue ); - } - } - -// --------------------------------------------------------------------------- -// CMRListPane::ScrollItemVisible -// --------------------------------------------------------------------------- -// -void CMRListPane::ScrollItemVisible( TInt aInd ) +void CMRListPane::DoUpdateScrollBar( TInt aFocusPosition ) { FUNC_LOG; - CESMRField* field = NULL; - if ( aInd == KErrNotFound ) + // Set this lispane's size as scroll bar's window size + iScrollModel.SetWindowSize( iSize.iHeight ); + // Set fieldcontainer's height as scrolbar's scroll span + iScrollModel.SetScrollSpan( iFieldContainer->MinimumSize().iHeight ); + + // Update scrollbar focus position. + if( aFocusPosition == KErrNotFound ) { - field = FocusedItem(); + iScrollModel.SetFocusPosition( iPhysics->VerticalScrollIndex() ); } else { - field = iFactory.Field( aInd ); + iScrollModel.SetFocusPosition( aFocusPosition ); } - ASSERT( field ); - - TRect rect( field->Rect() ); - - // move all items upwards - TInt bottomRightY = Rect().iBr.iY; - - - TInt fieldUpper(0); - TInt fieldLower(0); - field->GetMinimumVisibleVerticalArea( fieldUpper, fieldLower ); - - // desired position below view rect: - if ( rect.iTl.iY + fieldLower > Rect().iBr.iY ) - { - // field rect Y position related to view rect: - TInt fieldRelYPos = rect.iTl.iY - Size().iHeight; - TInt px = fieldRelYPos + fieldLower; + iScroll.SetModel( &iScrollModel ); - // if focus on first or last field: add margin height to - // scroll amount. - if ( iFocus == 0 || iFocus == iFactory.Count()-1 ) - { - px += 2 * KVerticalScrollMargin; - } - - ScrollItemsUp( px ); - } - - // move all items downwards. - TInt topLeftY = Rect().iTl.iY; - - if ( rect.iBr.iY - (rect.Height() - fieldUpper ) < topLeftY ) - { - TInt fieldRelYPos = topLeftY - rect.iBr.iY; - TInt px = fieldRelYPos + ( rect.Height() - fieldUpper); - - // if focus on first or last field: add margin height to - // scroll amount. - if ( iFocus == 0 || iFocus == iFactory.Count()-1 ) - { - px += KVerticalScrollMargin; - } - - ScrollItemsDown( px ); - } - - UpdateFocusPosition();//UpdateScrollBar(); - DrawDeferred(); + // finally update the new thumb position to view's + // iScrollBarThumbPosition member. + iScrollBarObserver.ScrollBarPositionChanged( + iScroll.ThumbPosition() ); } // --------------------------------------------------------------------------- -// CMRListPane::UpdateScrollBar +// CMRListPane::UpdatedFocusPosition // --------------------------------------------------------------------------- // -void CMRListPane::UpdateScrollBar() - { - FUNC_LOG; - // Scroll span is the size of the scrolled list, - // including the items that doesn't fit in the screen - TInt spanSize( 0 ); - TInt hidden( 0 ); - const TInt count(iFactory.Count()); - for ( TInt i(0); i < count; i++ ) - { - CESMRField* field = iFactory.Field( i ); - if ( field->IsVisible() ) - { - TRect rect( field->Rect() ); - spanSize += rect.Height(); - // Check if the field's top Y-position is hidden. - if ( rect.iTl.iY < 0 ) - { - // whole field is hidden - if ( rect.iBr.iY < 0 ) - { - hidden += rect.Height(); - } - // partly hidden: - else - { - hidden += Abs( rect.iTl.iY ); - } - } - } - } - - iScrollModel.SetScrollSpan( spanSize ); - iScrollModel.SetWindowSize( iSize.iHeight ); - iScrollModel.SetFocusPosition( hidden ); - - } - -// --------------------------------------------------------------------------- -// CMRListPane::ScrollItemsUp -// --------------------------------------------------------------------------- -// -void CMRListPane::ScrollItemsUp( TInt aPx ) +TInt CMRListPane::UpdatedFocusPosition() { FUNC_LOG; - TInt count( iFactory.Count() ); - for ( TInt i = 0; i < count; ++i ) - { - CESMRField* field = iFactory.Field(i); - if ( field->IsVisible() ) - { - TPoint pos( field->Position() ); - pos.iY -= aPx; - if ( i == iTopVisibleIndex && pos.iY < 0 ) - { - iTopVisibleIndex = KErrNotFound; - } - else if ( iTopVisibleIndex == KErrNotFound && pos.iY >= 0 ) - { - iTopVisibleIndex = i; - } - field->SetPosition( pos ); - } - } - } - -// --------------------------------------------------------------------------- -// CMRListPane::ScrollItemsDown -// --------------------------------------------------------------------------- -// -void CMRListPane::ScrollItemsDown( TInt aPx ) - { - FUNC_LOG; - TInt count( iFactory.Count() ); - for ( TInt i = 0; i < count; ++i ) - { - CESMRField* field = iFactory.Field( i ); - if ( field->IsVisible() ) - { - TPoint pos( field->Position() ); - pos.iY += aPx; - if ( pos.iY >= 0 && ( i < iTopVisibleIndex || iTopVisibleIndex == KErrNotFound ) ) - { - iTopVisibleIndex = i; - } - field->SetPosition( pos ); - } - } - } - -// --------------------------------------------------------------------------- -// CMRListPane::ScrollView -// --------------------------------------------------------------------------- -// -void CMRListPane::ScrollView( TInt aAmount ) - { - FUNC_LOG; - - if ( aAmount > 0 ) - { - // move list up - ScrollItemsUp( aAmount ); - UpdateFocusPosition(); - DrawDeferred(); - } - else if ( aAmount < 0 ) - { - // move list down - ScrollItemsDown( -aAmount ); - UpdateFocusPosition(); - DrawDeferred(); - } - } - - -// --------------------------------------------------------------------------- -// CMRListPane::UpdateFocusPosition -// --------------------------------------------------------------------------- -// -void CMRListPane::UpdateFocusPosition() - { TInt focusPos = 0; TInt count = iFactory.Count(); for ( TInt i = 0; i < count; ++i ) @@ -961,62 +446,300 @@ } } } + + return focusPos; + } + +// --------------------------------------------------------------------------- +// CMRListPane::ScrollFieldsUp +// --------------------------------------------------------------------------- +// +void CMRListPane::ScrollFieldsUp( TInt aPx ) + { + FUNC_LOG; + TPoint point = iFieldContainer->Position(); + point.iY -= aPx; - iScrollModel.SetFocusPosition( focusPos ); + // This initializes Draw also + iFieldContainer->SetPosition( point ); + + // Non-kinetic scrolling executed. Update + // new position to physics. + iPhysics->UpdateVerticalScrollIndex( UpdatedFocusPosition() ); + + DoUpdateScrollBar( UpdatedFocusPosition() ); + } + +// --------------------------------------------------------------------------- +// CMRListPane::ScrollFieldsDown +// --------------------------------------------------------------------------- +// +void CMRListPane::ScrollFieldsDown( TInt aPx ) + { + FUNC_LOG; + TPoint point = iFieldContainer->Position(); + point.iY += aPx; + + // This initializes Draw also + iFieldContainer->SetPosition( point ); + // Non-kinetic scrolling executed. Update + // new position to physics. + iPhysics->UpdateVerticalScrollIndex( UpdatedFocusPosition() ); + + DoUpdateScrollBar( UpdatedFocusPosition() ); } -// ----------------------------------------------------------------------------- -// CMRListPane::GetViewCenterPosition -// ----------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// CMRListPane::UpdateScrollBarAndPhysics +// --------------------------------------------------------------------------- +// +void CMRListPane::UpdateScrollBarAndPhysics() + { + // Update physics world size + iPhysics->InitPhysics(); + + // Update scrollbar + DoUpdateScrollBar(); + } + + +// --------------------------------------------------------------------------- +// CMRListPane::ShowControl +// --------------------------------------------------------------------------- +// +void CMRListPane::ShowControl( TESMREntryFieldId aFieldId ) + { + iFieldContainer->ShowControl( aFieldId ); + } + +// --------------------------------------------------------------------------- +// CMRListPane::ShowControl +// --------------------------------------------------------------------------- // -TPoint CMRListPane::GetViewCenterPosition() const +TBool CMRListPane::IsControlVisible( TESMREntryFieldId aFieldId ) + { + return iFieldContainer->IsControlVisible( aFieldId ); + } +// --------------------------------------------------------------------------- +// CMRListPane::GetResponseFieldsFieldId +// --------------------------------------------------------------------------- +// +TESMREntryFieldId CMRListPane::GetResponseFieldsFieldId() { - const TInt count( iFactory.Count() ); - TInt topFieldYPos( 0 ); - for ( TInt i = 0; i < count; i++ ) + // TODO: Should be removed. This shouldn't be even a public function! + CESMRField* rfield = iFactory.FieldById( EESMRFieldResponseArea ); + + if ( rfield && rfield->IsVisible() && !rfield->IsNonFocusing() ) + { + return EESMRFieldResponseArea; + } + else + { + return iFactory.Field(0)->FieldId(); + } + } + +// --------------------------------------------------------------------------- +// CMRListPane::ReActivateL +// --------------------------------------------------------------------------- +// +void CMRListPane::ReActivateL() + { + FUNC_LOG; + TInt count = iFactory.Count(); + + for ( TInt i = 0; i < count; ++i ) { CESMRField* field = iFactory.Field( i ); - if ( field->IsVisible() ) + if ( !field->IsFieldActivated() ) { - topFieldYPos = field->Position().iY; - break; + field->SetContainerWindowL( *iFieldContainer ); + field->SetListObserver( iFieldContainer ); + } + } + + // This "for" circle can not be mixed with the above one, since the + // field->ActivateL() will call some functions which will traverse + // all the fields, but that time, not all the fields have set the + // container window. + for ( TInt i = 0; i < count; ++i ) + { + CESMRField* field = iFactory.Field( i ); + if ( !field->IsFieldActivated() ) + { + field->ActivateL(); } } - TInt centerX = iSize.iWidth / 2; - TInt visibleHeight = iSize.iHeight; + } - TInt centerY = visibleHeight / 2 - topFieldYPos; +// --------------------------------------------------------------------------- +// CMRListPane::HandlePointerEventL +// --------------------------------------------------------------------------- +// +void CMRListPane::HandlePointerEventL( const TPointerEvent &aPointerEvent ) + { + // Check if touch is enabled or not + if( !AknLayoutUtils::PenEnabled() ) + { + return; + } + + // Forward all listpane related events to physics api first. + if ( iPhysics->HandlePointerEventL( aPointerEvent, iPhysicsActionOngoing ) ) + { + DoUpdateScrollBar(); + // Physics in action. If long tap detection is active, + // it should be cancelled. + if( iLongtapDetector->IsActive() ) + { + iLongtapDetector->Cancel(); + } + } - - return TPoint( centerX, centerY ); + if( !iPhysicsActionOngoing ) + { + // Offer pointer event to long tap detector + iLongtapDetector->PointerEventL( aPointerEvent ); + + SetFocusAfterPointerEventL( aPointerEvent ); + + // If longtap event has been handled, then do not handle signal event anymore. + if( !iLongTapEventConsumed ) + { + CCoeControl::HandlePointerEventL( aPointerEvent ); + } + else + { + iLongTapEventConsumed = EFalse; + } + + UpdateClickedField( aPointerEvent ); + } } +// --------------------------------------------------------------------------- +// CMRListPane::ActivateL +// --------------------------------------------------------------------------- +// +void CMRListPane::ActivateL() + { + FUNC_LOG; + // This ActiveteL is required only for setting the initial position + // of the field container. After setting the position, physics is + // initialized with new values also. + + CCoeControl::ActivateL(); + iFieldContainer->SetPosition( Position() ); + + // Physics: + iPhysics->InitPhysics(); + } -// ----------------------------------------------------------------------------- -// CMRListPane::HandlePointerEventL -// ----------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// CMRListPane::PhysicsEmulationEnded +// --------------------------------------------------------------------------- +// +void CMRListPane::PhysicsEmulationEnded() + { + FUNC_LOG; + DoUpdateScrollBar(); + iPhysicsActionOngoing = EFalse; + Parent()->DrawDeferred(); + } + +// --------------------------------------------------------------------------- +// CMRListPane::SetFocusAfterPointerEventL +// --------------------------------------------------------------------------- // -void CMRListPane::HandlePointerEventL( const TPointerEvent& aPointerEvent ) +void CMRListPane::SetFocusAfterPointerEventL( + const TPointerEvent &aPointerEvent ) { - if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + FUNC_LOG; + + if( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + TInt count( iFactory.Count() ); + for( TInt i = 0; i < count; ++i ) + { + CESMRField* field = iFactory.Field( i ); + if ( field->IsVisible() && + field->Rect().Contains( aPointerEvent.iPosition ) ) + { + CESMRField* focusedField = iFieldContainer->FocusedField(); + + if ( field != focusedField ) + { + TBool canLoseFocus( + focusedField->OkToLoseFocusL( field->FieldId() ) ); + + if ( canLoseFocus ) + { + iFieldContainer->SetControlFocusedL( field->FieldId() ); + } + } + + break; + } + } + } + } + +// --------------------------------------------------------------------------- +// CMRListPane::UpdateClickedField +// --------------------------------------------------------------------------- +// +void CMRListPane::UpdateClickedField( const TPointerEvent &aPointerEvent ) + { + FUNC_LOG; + TInt fieldCount( iFactory.Count() ); + + for( TInt i = 0; i < fieldCount; ++i ) { - TInt count = iFactory.Count(); - for ( TInt i = 0; i < count; ++i ) + if( iFactory.Field( i )->Rect().Contains( + aPointerEvent.iPosition ) ) { - CESMRField* field = static_cast(iFactory.Field( i ) ); - TRect r = field->Rect(); - TBool tapped = field->Rect().Contains( aPointerEvent.iPosition ); - if (tapped && field->IsVisible() && !field->IsFocused() ) + if( aPointerEvent.iType == TPointerEvent::EButton1Down ) { - MoveFocusL( i ); - break; + iClickedField = iFactory.Field( i ); } } } - // here some fields can further adjust their state (for example, CESMRResponseField has sub-fields) - CCoeControl::HandlePointerEventL(aPointerEvent); } + +// --------------------------------------------------------------------------- +// CMRListPane::HiddenFocus +// --------------------------------------------------------------------------- +// +TBool CMRListPane::HiddenFocus() + { + FUNC_LOG; + TBool hiddenFocus( EFalse ); + + CESMRField* focusedField( iFieldContainer->FocusedField() ); + TInt focusedFieldIndex( IndexByFieldId( + iFactory, focusedField->FieldId() ) ); + + if ( focusedFieldIndex < iFactory.Count() ) + { + TRect focusedFieldRect( focusedField->Rect() ); + TRect listPaneRect( Rect() ); + + TInt fieldTopY( focusedFieldRect.iTl.iY ); + TInt fieldBottomY( focusedFieldRect.iBr.iY ); + + TInt listTopY( listPaneRect.iTl.iY ); + TInt listBottomY( listPaneRect.iBr.iY ); + + if ( ( fieldBottomY > listBottomY || + fieldTopY < listTopY ) && + focusedFieldRect.Height() < listPaneRect.Height() ) + { + hiddenFocus = ETrue; + } + } + return hiddenFocus; + } + // End of file -