emailuis/uicomponents/src/fstextviewercontrol.cpp
changeset 0 8466d47a6819
--- /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
+*
+*/
+
+
+//<cmail> removed __FS_ALFRED_SUPPORT flag
+//#include <fsconfig.h>
+//</cmail> removed __FS_ALFRED_SUPPORT flag
+// <cmail> SF
+#include "emailtrace.h"
+#include <alf/alfevent.h>
+#include <alf/alfstatic.h>
+#include <alf/alfenv.h>
+// </cmail>
+
+// <cmail> Needed for pointer events. "Base class modifications for using touch"
+#include <alf/alfdisplay.h>
+#include <alf/alfroster.h>
+#include <aknphysics.h>
+// </cmail>
+
+#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;
+    }
+
+// <cmail> 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();
+    }