akntouchgesturefw/src/akntouchgesturefwtaprecognizer.cpp
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/akntouchgesturefw/src/akntouchgesturefwtaprecognizer.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,432 @@
+/*
+* 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:  Tap touch gesture recognizer.
+*
+*/
+
+#include "akntouchgesturefwdefs.h"
+#include "akntouchgesturefwevent.h"
+#include "akntouchgesturefwsettings.h"
+#include "akntouchgesturefwtaprecognizer.h"
+
+using namespace AknTouchGestureFw;
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CAknTouchGestureFwTapRecognizer* CAknTouchGestureFwTapRecognizer::NewL(
+        CAknTouchGestureFwRecognitionEngine& aEngine )
+    {
+    CAknTouchGestureFwTapRecognizer* self =
+        CAknTouchGestureFwTapRecognizer::NewLC( aEngine );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CAknTouchGestureFwTapRecognizer* CAknTouchGestureFwTapRecognizer::NewLC(
+        CAknTouchGestureFwRecognitionEngine& aEngine )
+    {
+    CAknTouchGestureFwTapRecognizer* self
+        = new ( ELeave ) CAknTouchGestureFwTapRecognizer( aEngine );
+    CleanupStack::PushL( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CAknTouchGestureFwTapRecognizer::~CAknTouchGestureFwTapRecognizer()
+    {
+    if ( iLongTapTimer )
+        {
+        iLongTapTimer->Cancel();
+        }
+    delete iLongTapTimer;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the tap gesture group.
+// ---------------------------------------------------------------------------
+//
+TAknTouchGestureFwGroup CAknTouchGestureFwTapRecognizer::GestureGroup() const
+    {
+    return EAknTouchGestureFwGroupTap;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Cancels the tap recognition.
+// ---------------------------------------------------------------------------
+//
+void CAknTouchGestureFwTapRecognizer::CancelRecognizing()
+    {
+    DoCancelTapRecognition( ETrue );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles single-touch pointer events.
+// ---------------------------------------------------------------------------
+//
+void CAknTouchGestureFwTapRecognizer::HandleSinglePointerEventL(
+        const TPointerEventData& aPointerData )
+    {
+    switch ( aPointerData.iPointerEvent.iType )
+        {
+        case TPointerEvent::EButton1Down:
+            {
+            // Start recognition on down event
+            StartTapRecognition( 
+                    aPointerData.iPointerEvent.iPosition,
+                    aPointerData.iTimeStamp );
+            break;
+            }
+        case TPointerEvent::EDrag:
+            {
+            // Continue tap recognizing.
+            TapRecognize( aPointerData.iPointerEvent.iPosition );
+            break;
+            }
+        case TPointerEvent::EButton1Up:
+            {
+            // Pointer up - complete recognition
+            CompleteTapRecognitionL( aPointerData.iTimeStamp );
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles multi-touch pointer events.
+// ---------------------------------------------------------------------------
+//
+void CAknTouchGestureFwTapRecognizer::HandleMultiPointerEventL(
+    const TPointerEventData& aPointerData,
+    const TPoint& /*aFirstPointerPosition*/,
+    const TPoint& /*aSecondPointerPosition*/ )
+    {
+    if ( aPointerData.iPointerEvent.iType == TPointerEvent::EButton1Down )
+        {
+        // First pointer is already down, second pointer down cancels tap
+        // recognizing because taps are allowed only for the first pointer.
+        CancelRecognizing();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// C++ constructor.
+// ---------------------------------------------------------------------------
+//
+CAknTouchGestureFwTapRecognizer::CAknTouchGestureFwTapRecognizer(
+        CAknTouchGestureFwRecognitionEngine& aEngine )
+    : CAknTouchGestureFwBaseRecognizer( aEngine ),
+    iThresholdArea(),
+    iLongTapTimer( NULL ),
+    iFirstTapDetected( EFalse ),
+    iFirstTapTime(),
+    iFirstTapPos(),
+    iLongTapIntensity( 0 ),
+    iFeedBackStarted( EFalse ) 
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// Starts the tap gesture recognition.
+// ---------------------------------------------------------------------------
+//
+void CAknTouchGestureFwTapRecognizer::StartTapRecognition(
+    const TPoint& aStartPoint, 
+    const TTime& aTimeStamp )
+    {
+    iThresholdArea.Start( aStartPoint );
+
+    // Start timer to recognize long tap
+    if ( !iLongTapTimer )
+        {
+        iLongTapTimer = CPeriodic::New( CActive::EPriorityStandard );
+        }
+
+    if ( iLongTapTimer )
+        {
+        iLongTapTimer->Cancel();
+        // Set timer for initial long tap delay.
+        iLongTapTimer->Start( KDefaultLongTapInitialDelay, 
+                              KDefaultLongTapInitialDelay,
+                              TCallBack( LongTapCallback, this ) );
+        }
+
+    if ( iFirstTapDetected )
+        {
+        // First tap already detected, check if this tap is double tap
+
+        // Check if position of this tap is too far from
+        // position of first tap.
+        TInt xDistance = Abs( aStartPoint.iX - iFirstTapPos.iX );
+        TInt yDistance = Abs( aStartPoint.iY - iFirstTapPos.iY );
+
+        if ( xDistance > DragThreshold() || yDistance > DragThreshold() )
+            {
+            // Too far, this tap can't be double tap.
+            iFirstTapDetected = EFalse;
+            return;
+            }
+
+        // Check if delay between already detected tap and this tap is too long.
+        TInt delay( aTimeStamp.MicroSecondsFrom( iFirstTapTime ).Int64() );
+
+        if ( delay > DoubleTapMaximumDuration() )
+            {
+            // Delay is too long, this tap can't be double tap.
+            iFirstTapDetected = EFalse;
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Continues the tap gesture recognition, called on drag pointer events.
+// ---------------------------------------------------------------------------
+//
+void CAknTouchGestureFwTapRecognizer::TapRecognize( const TPoint& aPoint )
+    {
+    if ( iThresholdArea.Check( aPoint, TapThreshold() ) )
+        {
+        CancelRecognizing();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Ends the tap gesture recognition.
+// ---------------------------------------------------------------------------
+//
+void CAknTouchGestureFwTapRecognizer::CompleteTapRecognitionL( 
+    const TTime& aTimeStamp )
+    {
+    if ( iThresholdArea.IsActive() )
+        {
+        // Single pointer has been down and goes up now
+        // and tap recognition hasn't been cancelled
+        const TPoint startPos( iThresholdArea.InitialPosition() );
+
+        // Cancel tap recognition of this tap, but don't
+        // remove the possible info that first tap has already been detected
+        DoCancelTapRecognition( EFalse );
+
+        if ( iFirstTapDetected )
+            {
+            iFirstTapDetected = EFalse;
+            // First tap already detected: Send Double Tap gesture event
+            SendTapEventL( EAknTouchGestureFwDoubleTap, iFirstTapPos );
+            }
+        else
+            {
+            iFirstTapTime = aTimeStamp;
+            iFirstTapDetected = ETrue;
+            iFirstTapPos = startPos;
+
+            // First tap not detected: Send normal Tap gesture event
+            SendTapEventL( EAknTouchGestureFwTap, startPos );
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sends a tap gesture event to the observer.
+// ---------------------------------------------------------------------------
+//
+void CAknTouchGestureFwTapRecognizer::SendTapEventL(
+    TAknTouchGestureFwType aGestureType,
+    const TPoint& aPointerPos )
+    {
+    TTouchFeedbackType feedbackType( FeedbackType( aGestureType ) );
+    if ( feedbackType )
+        {
+        switch ( aGestureType )
+            {
+            case EAknTouchGestureFwTap:
+                {
+                ImmediateFeedback( ETouchFeedbackSensitive, feedbackType );
+                break;
+                }
+            case EAknTouchGestureFwDoubleTap:
+                {
+                ImmediateFeedback( ETouchFeedbackBasic, feedbackType );
+                break;
+                }
+            case EAknTouchGestureFwLongTap:
+                {
+                ImmediateFeedback( ETouchFeedbackBasic, feedbackType );                                                       
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }    
+        }
+
+    TAknTouchGestureFwTapEvent tap;
+    tap.SetType( aGestureType );
+    tap.SetPosition( aPointerPos );
+    SendGestureEventL( tap );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Called when long tap has been detected.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTouchGestureFwTapRecognizer::LongTapCallback( TAny* aThis )
+    {
+    CAknTouchGestureFwTapRecognizer* recognizer =
+        static_cast<CAknTouchGestureFwTapRecognizer*>( aThis );
+    if ( recognizer )
+        {
+        TRAP_IGNORE( recognizer->HandleLongTapCallbackL() );
+        }
+    return 0;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles long tap callback related actions.
+// ---------------------------------------------------------------------------
+//
+void CAknTouchGestureFwTapRecognizer::HandleLongTapCallbackL()
+    {   
+    if ( iLongTapIntensity == 0 && iLongTapTimer )
+        {   
+        iLongTapTimer->Cancel();
+
+        TInt interval = ( LongTapThreshold() - KDefaultLongTapInitialDelay )
+            / KDefaultMaxLongTapIntensitySteps;
+        
+        TInt timeOut = 
+            interval * ( KDefaultMaxLongTapIntensitySteps + 1 );
+        
+        // Start timer again to increase long tap intensity on
+        // regular interval until max intensity is reached.
+        iLongTapTimer->Start( 0, interval,
+            TCallBack( LongTapCallback, this ) );
+        
+        TTouchFeedbackType feedbackType(
+            FeedbackType( EAknTouchGestureFwTap ) );       
+           
+        if ( feedbackType & ETouchFeedbackVibra )
+            {      
+            // Start feedback for long tap gesture.
+            StartContinuousFeedback( ETouchContinuousSmooth, 0, timeOut ); 
+            iFeedBackStarted = ETrue;
+            }
+        }
+ 
+    // Calculate new long tap intensity value.
+    iLongTapIntensity = iLongTapIntensity + 
+        KDefaultMaxLongTapIntensity / KDefaultMaxLongTapIntensitySteps;
+    
+    if ( iFeedBackStarted )
+        {
+        // Modify existing continuous feedback. Intensity will grow 
+        // from 0 to 100 and after that long tap is detected. 
+        ModifyContinuousFeedback( iLongTapIntensity );
+        }
+    
+    if ( iLongTapIntensity >= KDefaultMaxLongTapIntensity )
+        {
+        const TPoint startPos( iThresholdArea.InitialPosition() );
+        CancelRecognizing();
+        // Send Long Tap gesture event.
+        SendTapEventL( EAknTouchGestureFwLongTap, startPos );
+        }            
+    }
+
+
+// ---------------------------------------------------------------------------
+// Cancels the tap gesture recognition.
+// ---------------------------------------------------------------------------
+//
+void CAknTouchGestureFwTapRecognizer::DoCancelTapRecognition(
+        TBool aResetFirstTapDetection )
+    {
+    iThresholdArea.Reset();
+
+    if ( aResetFirstTapDetection )
+        {
+        iFirstTapDetected = EFalse;
+        }
+
+    if ( iLongTapTimer )
+        {
+        iLongTapTimer->Cancel();
+        
+        if ( iLongTapIntensity > 0 )
+            {
+            StopContinuousFeedback();
+            iFeedBackStarted = EFalse;
+            iLongTapIntensity = 0;
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the value for the long tap threshold setting.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTouchGestureFwTapRecognizer::LongTapThreshold() const
+    {
+    return Settings().LongTapThreshold() * KMicroSecondsInMilliSecond;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the value for the single tap threshold setting.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTouchGestureFwTapRecognizer::TapThreshold() const
+    {
+    return Settings().TapThreshold();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the value for the double tap maximum duration setting.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTouchGestureFwTapRecognizer::DoubleTapMaximumDuration() const
+    {
+    return Settings().DoubleTapMaximumDuration() * KMicroSecondsInMilliSecond;
+    }
+
+// End of File