diff -r 000000000000 -r 8466d47a6819 emailuis/uicomponents/src/fstextviewercontrol.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emailuis/uicomponents/src/fstextviewercontrol.cpp Thu Dec 17 08:39:21 2009 +0200 @@ -0,0 +1,660 @@ +/* +* Copyright (c) 2007 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: Implementation of class CFsTextViewerControl +* +*/ + + +// removed __FS_ALFRED_SUPPORT flag +//#include +// removed __FS_ALFRED_SUPPORT flag +// SF +#include "emailtrace.h" +#include +#include +#include +// + +// Needed for pointer events. "Base class modifications for using touch" +#include +#include +#include +// + +#include "fstextviewercontrol.h" +#include "fstextviewervisualizer.h" +#include "fstextviewervisualizerdata.h" +#include "fstextviewerobserver.h" +#include "fstextviewerkeys.h" + +// Dragging treshold in pixels, so the amount of pixels that the pointer +// poisition can move without indicating it as dragging +const TInt KDraggingTresholdInPixels = 20; + +// To be removed after aknphysics is working +#define FS_VIEWER_DISABLE_AKN_PHYSICS + +// --------------------------------------------------------------------------- +// NewL +// --------------------------------------------------------------------------- +CFsTextViewerControl* CFsTextViewerControl::NewL( CAlfEnv& aEnv ) + { + FUNC_LOG; + CFsTextViewerControl* self = new ( ELeave ) CFsTextViewerControl(); + CleanupStack::PushL( self ); + self->ConstructL(aEnv); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CFsTextViewerControl +// --------------------------------------------------------------------------- +CFsTextViewerControl::CFsTextViewerControl( ) + : CAlfControl(), + iCursorUDScroll( EFalse ), + iScrollEventHandlingOngoing( EFalse ), + iIsVisible( EFalse ), + iStartHotspotAction( EFalse ) + { + FUNC_LOG; + } + +// --------------------------------------------------------------------------- +// ConstructL +// --------------------------------------------------------------------------- +void CFsTextViewerControl::ConstructL(CAlfEnv& aEnv) + { + FUNC_LOG; + CAlfControl::ConstructL(aEnv); + +#ifndef FS_VIEWER_DISABLE_AKN_PHYSICS + if ( CAknPhysics::FeatureEnabled() ) + { + CCoeControl* ctrl = NULL; + //ctrl = CCoeEnv::Static()->AppUi()->TopFocusedControl(); + + iPhysics = CAknPhysics::NewL( *this, ctrl ); + } +#endif //FS_VIEWER_DISABLE_AKN_PHYSICS + } + +// --------------------------------------------------------------------------- +// ~CFsTextViewerControl +// --------------------------------------------------------------------------- +CFsTextViewerControl::~CFsTextViewerControl() + { + FUNC_LOG; + + delete iPhysics; + iPhysics = NULL; + } + +// --------------------------------------------------------------------------- +// SetVisualizer +// --------------------------------------------------------------------------- +void CFsTextViewerControl::SetVisualizer( CFsTextViewerVisualizer* aVis ) + { + FUNC_LOG; + iVisualizer = aVis; + } + +// --------------------------------------------------------------------------- +// SetObserver +// --------------------------------------------------------------------------- +void CFsTextViewerControl::SetObserver( MFsTextViewerObserver* aObserver ) + { + FUNC_LOG; + iObserver = aObserver; + } + +// --------------------------------------------------------------------------- +// EnableCursorScroll +// --------------------------------------------------------------------------- +void CFsTextViewerControl::EnableCursorScroll( TBool aStatus ) + { + FUNC_LOG; + iCursorUDScroll = aStatus; + } + +// --------------------------------------------------------------------------- +// CursorScroll +// --------------------------------------------------------------------------- +TBool CFsTextViewerControl::CursorScroll() + { + FUNC_LOG; + return iCursorUDScroll; + } + +// --------------------------------------------------------------------------- +// SetKeys +// --------------------------------------------------------------------------- +void CFsTextViewerControl::SetKeys( CFsTextViewerKeys* aKeys ) + { + FUNC_LOG; + iKeys = aKeys; + } + +// --------------------------------------------------------------------------- +// Keys +// --------------------------------------------------------------------------- +CFsTextViewerKeys* CFsTextViewerControl::Keys() + { + FUNC_LOG; + return iKeys; + } + +TBool CFsTextViewerControl::IsScrollEventHandlingOngoing() + { + return iScrollEventHandlingOngoing; + } + +void CFsTextViewerControl::NotifyControlVisibility( TBool aIsVisible, CAlfDisplay& aDisplay ) + { + iVisualizer->NotifyControlVisibilityChange(aIsVisible); + + //Add & remove extra touch events. + if(aIsVisible && !iIsVisible) + { + TInt dragTreshold_X = KDraggingTresholdInPixels; + // If AknPhysics used, get drag treshold from there + if( iPhysics ) + { + dragTreshold_X = iPhysics->DragThreshold(); + } + + // Currently only panning (vertical dragging) is implemented, + // so horizontal drag treshold should be a bit bigger + TInt dragTreshold_Y = dragTreshold_X * 2; + + // Add observer for long tap and drag events, set treshold for drag + // events and disable long tap events while dragging + aDisplay.Roster().AddPointerEventObserver( EAlfPointerEventReportLongTap, *this ); + aDisplay.Roster().AddPointerEventObserver( EAlfPointerEventReportDrag, *this ); + aDisplay.Roster().SetPointerDragThreshold( + *this, TAlfXYMetric( TAlfMetric(dragTreshold_X), TAlfMetric(dragTreshold_Y) ) ); + aDisplay.Roster().DisableLongTapEventsWhenDragging( *this ); + iIsVisible = ETrue; + } + else if(!aIsVisible && iIsVisible ) + { + if( iPhysics ) + { + iPhysics->StopPhysics(); + iPhysics->ResetFriction(); + } + + aDisplay.Roster().RemovePointerEventObserver(EAlfPointerEventReportLongTap, *this); + aDisplay.Roster().RemovePointerEventObserver(EAlfPointerEventReportDrag, *this); + + iIsVisible = EFalse; + } + + } + +// --------------------------------------------------------------------------- +// OfferEventL +// --------------------------------------------------------------------------- +TBool CFsTextViewerControl::OfferEventL(const TAlfEvent& aEvent) + { + FUNC_LOG; + TBool retVal = EFalse; + + if ( aEvent.IsPointerEvent() ) + { + retVal = HandlePointerEventL( aEvent ); + } + else if( aEvent.IsKeyEvent() && aEvent.Code() == EEventKey ) + { + retVal = HandleKeyEventL( aEvent ); + } + + return retVal; + } + +// --------------------------------------------------------------------------- +// CFsTextViewerControl::HandleKeyEventL +// Handle keyboard events +// --------------------------------------------------------------------------- +// +TBool CFsTextViewerControl::HandleKeyEventL(const TAlfEvent& aEvent) + { + TBool eventHandled( EFalse ); + + if( iPhysics ) + { + iPhysics->StopPhysics(); + iPhysics->ResetFriction(); + } + + if ( aEvent.KeyEvent().iCode == iKeys->GetKeyUp() ) + { + TBool hotspotChanged = EFalse; + if ( iCursorUDScroll ) + { + iVisualizer->MoveUpL(); + } + else + { + if ( iVisualizer->PrevVisibleHotspotL( hotspotChanged ) ) + { + if ( iObserver && hotspotChanged ) + { + iObserver->HandleTextViewerEventL( + MFsTextViewerObserver::EFsTextViewerHotspotChanged ); + } + } + else + { + ScrollL( MFsTextViewerObserver::EFsTextViewerScrollUp ); + } + } + eventHandled = ETrue; + } + else if ( aEvent.KeyEvent().iCode == iKeys->GetKeyDown() ) + { + TBool hotspotChanged = EFalse; + if ( iCursorUDScroll ) + { + iVisualizer->MoveDownL(); + } + else + { + if ( iVisualizer->NextVisibleHotspotL( hotspotChanged ) ) + { + if ( iObserver && hotspotChanged ) + { + iObserver->HandleTextViewerEventL( + MFsTextViewerObserver::EFsTextViewerHotspotChanged ); + } + } + else + { + ScrollL( MFsTextViewerObserver::EFsTextViewerScrollDown ); + } + } + eventHandled = ETrue; + } + else if ( aEvent.KeyEvent().iCode == iKeys->GetKeyPgUp() ) + { + iVisualizer->PageUpL(); + } + else if ( aEvent.KeyEvent().iCode == iKeys->GetKeyPgDown() ) + { + iVisualizer->PageDownL(); + } + else if ( aEvent.KeyEvent().iCode == iKeys->GetKeyRight() ) + { + iVisualizer->MoveRightL(); + if ( iVisualizer->MarkEnabled() && iObserver ) + { + iObserver->HandleTextViewerEventL( + MFsTextViewerObserver::EFsTextViewerMarkChange ); + } + eventHandled = ETrue; + } + else if ( aEvent.KeyEvent().iCode == iKeys->GetKeyLeft() ) + { + iVisualizer->MoveLeftL(); + if ( iVisualizer->MarkEnabled() && iObserver ) + { + iObserver->HandleTextViewerEventL( + MFsTextViewerObserver::EFsTextViewerMarkChange ); + } + eventHandled = ETrue; + } + else if ( aEvent.KeyEvent().iCode == iKeys->GetKeyMark() ) + { + iVisualizer->SwitchMarkL(); + if ( iVisualizer->MarkEnabled() && iObserver ) + { + iObserver->HandleTextViewerEventL( + MFsTextViewerObserver::EFsTextViewerMarkStart ); + } + else if ( iObserver ) + { + iObserver->HandleTextViewerEventL( + MFsTextViewerObserver::EFsTextViewerMarkEnd ); + } + eventHandled = ETrue; + } + else if ( aEvent.KeyEvent().iCode == iKeys->GetKeyClick() ) + { + iVisualizer->ClickedL(); + if ( iVisualizer->IsHotspotHighlighted() && iObserver ) + { + iObserver->HandleTextViewerEventL( + MFsTextViewerObserver::EFsTextViewerHotspotClicked ); + } + eventHandled = ETrue; + } + else if ( aEvent.KeyEvent().iCode == iKeys->GetKeyScrollUp() ) + { + ScrollL( MFsTextViewerObserver::EFsTextViewerScrollUp ); + eventHandled = ETrue; + } + else if ( aEvent.KeyEvent().iCode == iKeys->GetKeyScrollDown() ) + { + ScrollL( MFsTextViewerObserver::EFsTextViewerScrollDown ); + eventHandled = ETrue; + } + + return eventHandled; + } + +// --------------------------------------------------------------------------- +// CFsTextViewerControl::HandlePointerEventL +// Handle pointer (touch) events +// --------------------------------------------------------------------------- +// +TBool CFsTextViewerControl::HandlePointerEventL(const TAlfEvent& aEvent) + { + TBool eventHandled( EFalse ); + + // Check if this event is bound to some of our visuals + CAlfVisual* selectedVis = aEvent.Visual(); + TFsRangedVisual* rangedVis = NULL; + if( selectedVis ) + { + rangedVis = iVisualizer->Navigator()->GetRangedVisual( selectedVis ); + } + + switch ( aEvent.PointerEvent().iType ) + { + case TPointerEvent::EButton1Down: + { + // Save current and original position so that those can be used in + // drag/scrolling calculations + iPreviousPosition = iOriginalPosition = aEvent.PointerEvent().iParentPosition; + iIsDragging = EFalse; + iIsFlicking = EFalse; + + if( iPhysics ) + { + iPhysics->StopPhysics(); + iPhysics->ResetFriction(); + iStartTime.HomeTime(); + UpdatePhysicsL(); + } + + // On button down event, move focus to highlighted hotspot + if( rangedVis && rangedVis->iHotspot ) + { + // Allow future hotspot actions + iStartHotspotAction = ETrue; + + // Move focus to currently pointed hotspot and report event + // to observers + iVisualizer->SetCurrentHotspotByCharL( rangedVis->iStart ); + if ( iObserver ) + { + iObserver->HandleTextViewerEventL( MFsTextViewerObserver::EFsTextViewerHotspotChanged ); + } + + eventHandled = ETrue; + } + } + break; + + case TPointerEvent::EButton1Up: + { + if( iIsDragging && iPhysics ) + { + TPoint drag(iOriginalPosition - aEvent.PointerEvent().iParentPosition); + iPhysics->StartPhysics(drag, iStartTime); + iIsFlicking = ETrue; + } + + // On button up event start action for focused hotspot, if hotspot + // action allowed + else if( iStartHotspotAction && rangedVis && rangedVis->iHotspot ) + { + // Hotspot action started, so disable all future actions + iStartHotspotAction = EFalse; + + // Move focus to currently pointed hotspot and report event + // to observers + iVisualizer->SetCurrentHotspotByCharL( rangedVis->iStart ); + if ( iObserver ) + { + iObserver->HandleTextViewerEventL( MFsTextViewerObserver::EFsTextViewerHotspotClicked ); + } + + eventHandled = ETrue; + } + } + break; + + case TPointerEvent::EButtonRepeat: + { + // On repeat event report long tap event to observers, if hotspot + // actions are allowed + if( iStartHotspotAction ) + { + // Hotspot action started, so disable all future actions + iStartHotspotAction = EFalse; + + // Report long tap event to observers + if ( iObserver ) + { + iObserver->HandleTextViewerEventL( MFsTextViewerObserver::EFsTextViewerHotspotLongTap ); + } + + eventHandled = ETrue; + } + break; + } + + case TPointerEvent::EDrag: + { + // Get current pointer position + TPoint position = aEvent.PointerEvent().iParentPosition; + + // If user started dragging, cancel hotspot actions + iStartHotspotAction = EFalse; + iIsDragging = ETrue; + + if( iPhysics ) + { + TPoint delta( 0, iPreviousPosition.iY - position.iY ); + iPhysics->RegisterPanningPosition( delta ); + } + else + { + // Calculate new scroll offset based on current and previous Y-positions + TInt scrollOffset = iVisualizer->GetViewTopPosition() + ( iPreviousPosition.iY - position.iY ); + // Ensure that thumb position is in correct range + scrollOffset = Max( scrollOffset, 0 ); + scrollOffset = Min( scrollOffset, iVisualizer->GetTotalHeight() - iVisualizer->iContentSize.iHeight ); + + ScrollL( scrollOffset ); + } + + // Save current position as previous pos for future calculations + iPreviousPosition = position; + + eventHandled = ETrue; + } + break; + + default: + { + // Unknown event, ignore. + } + break; + } + + return eventHandled; + } + +// Change scrollbar to avkon (to support skinning & touch) +// --------------------------------------------------------------------------- +// Handle scrollbar events +// --------------------------------------------------------------------------- +// +void CFsTextViewerControl::HandleScrollEventL(CEikScrollBar* aScrollBar, TEikScrollEvent aEventType) + { + iScrollEventHandlingOngoing = ETrue; + + if( iPhysics ) + { + iPhysics->StopPhysics(); + iPhysics->ResetFriction(); + } + + if ( aScrollBar == iVisualizer->GetScrollBar() ) + { + TInt thumbPos = -1; + switch( aEventType ) + { + case EEikScrollHome : + { + //Jump to beginning + thumbPos = 0; + } + break; + case EEikScrollEnd : + { + //Jump to end + thumbPos = iVisualizer->GetTotalHeight() - iVisualizer->iContentSize.iHeight; + } + break; + default: + { + thumbPos = aScrollBar->ThumbPosition(); + } + break; + } + + if( thumbPos >= 0 ) + { + // Ensure that thumb position is in correct range + thumbPos = Min( thumbPos, iVisualizer->GetTotalHeight() - iVisualizer->iContentSize.iHeight ); + + // Scroll text viewer to thumb position with default scroll time + ScrollL( thumbPos ); + } + } + + iScrollEventHandlingOngoing = EFalse; + } + +void CFsTextViewerControl::ScrollL( + const TInt aOffset, + const TInt aTime /*= CFsTextViewerVisualizer::EUseDefaultScrollTime*/ ) + { + // Scroll text viewer to the calculated position. + // If position is above current line offset, scroll up. + // If position is below current line offset, scroll down. + // If position is same as current line offset, do nothing. + if ( aOffset < iVisualizer->GetViewTopPosition() ) + { + ScrollL( MFsTextViewerObserver::EFsTextViewerScrollUp, aOffset, aTime ); + } + else if ( aOffset > iVisualizer->GetViewTopPosition() ) + { + ScrollL( MFsTextViewerObserver::EFsTextViewerScrollDown, aOffset, aTime ); + } + } + +void CFsTextViewerControl::ScrollL( + const MFsTextViewerObserver::TFsTextViewerEvent aEventDirection, + const TInt aOffset /*= CFsTextViewerVisualizer::EUseDefaultScrollOffset*/, + const TInt aTime /*= CFsTextViewerVisualizer::EUseDefaultScrollTime*/ ) + { + switch( aEventDirection ) + { + case MFsTextViewerObserver::EFsTextViewerScrollUp: + { + iVisualizer->ScrollUpL( aOffset, aTime ); + } + break; + + case MFsTextViewerObserver::EFsTextViewerScrollDown: + { + iVisualizer->ScrollDownL( aOffset, aTime ); + } + break; + + // No need to handle any other events here + default: + return; + } + + if ( iObserver ) + { + iObserver->HandleTextViewerEventL( aEventDirection ); + } + } + +// --------------------------------------------------------------------------- +// Update physics +// --------------------------------------------------------------------------- +// +void CFsTextViewerControl::UpdatePhysicsL() + { + FUNC_LOG; + if ( iPhysics ) + { + const TSize viewSize( iVisualizer->iContentSize ); + const TSize worldSize( viewSize.iWidth, iVisualizer->GetTotalHeight() ); + iPhysics->InitPhysicsL( worldSize, viewSize, EFalse ); + } + } + +/** + * @see MAknPhysicsObserver::ViewPositionChanged + */ +void CFsTextViewerControl::ViewPositionChanged( + const TPoint& aNewPosition, + TBool /*aDrawNow*/, + TUint /*aFlags*/ ) + { + // Sometimes ViewPositionChanged events come after view is already changed, + // so adding a safety check here + if( iIsVisible ) + { + TInt scrollOffset = aNewPosition.iY - iVisualizer->iContentSize.iHeight / 2; + + //CAlfStatic::Env().SetRefreshMode( EAlfRefreshModeManual ); + if( iIsFlicking ) + { + TRAP_IGNORE( ScrollL( scrollOffset, 1 ) ); + } + else + { + TRAP_IGNORE( ScrollL( scrollOffset, 250 ) ); + } + //iListLayout->Env().RefreshCallBack( &iListLayout->Env() ); + //iVisualizer->RootLayout()->UpdateChildrenLayout(); + //CAlfStatic::Env().RefreshCallBack( &CAlfStatic::Env() ); + //CAlfStatic::Env().SetRefreshMode( EAlfRefreshModeAutomatic ); + } + } + +/** + * @see MAknPhysicsObserver::PhysicEmulationEnded + */ +void CFsTextViewerControl::PhysicEmulationEnded() + { + iIsFlicking = EFalse; + } + +/** + * @see MAknPhysicsObserver::ViewPosition + */ +TPoint CFsTextViewerControl::ViewPosition() const + { + return iVisualizer->GetViewCenterPosition(); + }