akntouchgesturefw/src/akntouchgesturefwrecognitionengine.cpp
author Dario Sestito <darios@symbian.org>
Fri, 30 Apr 2010 17:20:48 +0100
branchRCL_3
changeset 19 aa94898fb0b4
parent 0 2f259fa3e83a
permissions -rw-r--r--
Merge workaround for bug 2584

/*
* 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:  Gesture recognition engine.
*
*/

#include <akntouchgesturefwobserver.h>

#include "akntouchgesturefwdefs.h"
#include "akntouchgesturefwbaserecognizer.h"
#include "akntouchgesturefwdragrecognizer.h"
#include "akntouchgesturefwevent.h"
#include "akntouchgesturefwflickrecognizer.h"
#include "akntouchgesturefwpinchrecognizer.h"
#include "akntouchgesturefwpointerstate.h"
#include "akntouchgesturefwrecognitionengine.h"
#include "akntouchgesturefwsettings.h"
#include "akntouchgesturefwtaprecognizer.h"

using namespace AknTouchGestureFw;

// Array of gesture groups
const TAknTouchGestureFwGroup KGestureGroup[] =
    {
    EAknTouchGestureFwGroupTap,
    EAknTouchGestureFwGroupDrag,
    EAknTouchGestureFwGroupFlick,
    EAknTouchGestureFwGroupPinch
    };

// ======== MEMBER FUNCTIONS ========

// ---------------------------------------------------------------------------
// Two-phased constructor.
// ---------------------------------------------------------------------------
//
CAknTouchGestureFwRecognitionEngine* CAknTouchGestureFwRecognitionEngine::NewL(
        MAknTouchGestureFwObserver& aObserver, CCoeControl* aControl )
    {
    CAknTouchGestureFwRecognitionEngine* self =
        CAknTouchGestureFwRecognitionEngine::NewLC( aObserver, aControl );
    CleanupStack::Pop( self );
    return self;
    }


// ---------------------------------------------------------------------------
// Two-phased constructor.
// ---------------------------------------------------------------------------
//
CAknTouchGestureFwRecognitionEngine*
    CAknTouchGestureFwRecognitionEngine::NewLC(
            MAknTouchGestureFwObserver& aObserver, CCoeControl* aControl )
    {
    CAknTouchGestureFwRecognitionEngine* self
        = new ( ELeave ) CAknTouchGestureFwRecognitionEngine( aObserver,
            aControl );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }


// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CAknTouchGestureFwRecognitionEngine::~CAknTouchGestureFwRecognitionEngine()
    {
    delete iPointerState;
    delete iSettings;
    iRecognizers.ResetAndDestroy();
    iRecognizers.Close();
    }


// ---------------------------------------------------------------------------
// Notifies the observer about a gesture event.
// ---------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::NotifyObserverL(
        MAknTouchGestureFwEvent& aEvent )
    {
#ifdef GFW_DEBUG_TRACE_INPUTOUTPUT
    AknTouchGestureFwUtils::DumpGestureEvent( aEvent );
#endif  // GFW_DEBUG_TRACE_INPUTOUTPUT

    iObserver.HandleTouchGestureL( aEvent );
    }


// ---------------------------------------------------------------------------
// Sets the gesture interest.
// ---------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::SetGestureInterestL(
    TUint aGestureGroups )
    {
    TUint newGestureInterest( aGestureGroups );

    // Create recognizers on demand.
    if ( newGestureInterest & EAknTouchGestureFwGroupPinch )
        {
        CreateRecognizerL( EAknTouchGestureFwGroupPinch );
        }

    if ( newGestureInterest & EAknTouchGestureFwGroupDrag )
        {
        CreateRecognizerL( EAknTouchGestureFwGroupDrag );
        }

    if ( newGestureInterest & EAknTouchGestureFwGroupFlick )
        {
        CreateRecognizerL( EAknTouchGestureFwGroupFlick );
        }

    if ( newGestureInterest & EAknTouchGestureFwGroupTap )
        {
        CreateRecognizerL( EAknTouchGestureFwGroupTap );
        }

    iGestureInterest = newGestureInterest;

    // Enable/disable recognizers.
    UpdateRecognizersForInterest( newGestureInterest );
    }


// ---------------------------------------------------------------------------
// Returns the current gesture interest.
// ---------------------------------------------------------------------------
//
TUint CAknTouchGestureFwRecognitionEngine::GestureInterest() const
    {
    return iGestureInterest;
    }


// ---------------------------------------------------------------------------
// Cancels the gesture recognition.
// ---------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::CancelRecognizing()
    {
    if ( iSingleRecognizing || iMultiRecognizing )
        {
        iSingleRecognizing = EFalse;
        iMultiRecognizing = EFalse;

        iPointerState->Reset();

        for ( TInt i = 0; i < iRecognizers.Count(); i++ )
            {
            iRecognizers[ i ]->CancelRecognizing();
            }
        }
    }


// ---------------------------------------------------------------------------
// Handles pointer events.
// ---------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::HandlePointerEventL(
    const TPointerEventData& aPointerData )
    {
    // Note: term pointer means physical pointer, e.g. finger
    // in the following comments. So first pointer down
    // means that single finger has been pressed down and
    // second pointer down means that also another finger has
    // been pressed down

    // Update pointer state
    if ( !iPointerState->Update( aPointerData ) )
        {
        // Send unknown event if successive down events were received
        // to same pointer
        if ( iTestingEnabled && iPointerState->SuccessiveDownEventsReceived() )
            {
            TAknTouchGestureFwUnknownEvent unknown;
            NotifyObserverL( unknown );
            }
        return;
        }

    TBool multiTouchEvent( iMultiRecognizing );

    if ( aPointerData.iPointerEvent.iType == TPointerEvent::EButton1Down )
        {
        // Single recognizing with first button down
        if ( !iSingleRecognizing )
            {
            iMultiRecognizing = EFalse;
            iSingleRecognizing = ETrue;
            multiTouchEvent = EFalse;
            }
        else
            {
            // Second pointer down starts multi recognizing
            iSingleRecognizing = EFalse;
            iMultiRecognizing = ETrue;
            multiTouchEvent = ETrue;
            }
        }
    else if ( aPointerData.iPointerEvent.iType == TPointerEvent::EButton1Up )
        {
        if ( iMultiRecognizing && iPointerState->IsSingleTouch() )
            {
            iSingleRecognizing = ETrue;
            iMultiRecognizing = EFalse;
            multiTouchEvent = ETrue;
            }
        else if ( iSingleRecognizing && iPointerState->IsNoTouch() )
            {
            // Single recognizing ongoing, pointer goes up.
            iSingleRecognizing = EFalse;
            iMultiRecognizing = EFalse;
            multiTouchEvent = EFalse;
            }
        }

    SendPointerEventToRecognizersL( multiTouchEvent, aPointerData );
    }


// ---------------------------------------------------------------------------
// Returns the framework settings provider.
// ---------------------------------------------------------------------------
//
CAknTouchGestureFwSettings& CAknTouchGestureFwRecognitionEngine::Settings() const
    {
    return *iSettings;
    }


// ---------------------------------------------------------------------------
// EnableTestingFeatures
// ---------------------------------------------------------------------------
//    
void CAknTouchGestureFwRecognitionEngine::EnableTestingFeatures()
    {
    iTestingEnabled = ETrue;
    }


// ---------------------------------------------------------------------------
// C++ constructor.
// ---------------------------------------------------------------------------
//
CAknTouchGestureFwRecognitionEngine::CAknTouchGestureFwRecognitionEngine(
        MAknTouchGestureFwObserver& aObserver, CCoeControl* aControl )
    :
    iObserver( aObserver ),
    iPointerState( NULL ),
    iSettings( NULL ),
    iGestureInterest( EAknTouchGestureFwNoGroup ),
    iSingleRecognizing( EFalse ),
    iMultiRecognizing( EFalse ),
    iControl( aControl ),
    iFeedBack( MTouchFeedback::Instance() )
    {
    }


// ---------------------------------------------------------------------------
// Second-phase constructor.
// ---------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::ConstructL()
    {
    iPointerState = CAknTouchGestureFwPointerState::NewL();
    iSettings = CAknTouchGestureFwSettings::NewL();
    }


// ---------------------------------------------------------------------------
// Enables/disables the necessary recognizers based on the gesture interest.
// ---------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::UpdateRecognizersForInterest(
    TUint aGestureInterest )
    {
    for ( TInt i = 0; i < iRecognizers.Count(); i++ )
        {
        if ( iRecognizers[i]->GestureGroup() & aGestureInterest )
            {
            iRecognizers[i]->SetEnabled( ETrue );
            }
        else
            {
            iRecognizers[i]->SetEnabled( EFalse );
            }
        }
    }


// ---------------------------------------------------------------------------
// Creates the recognizer for the specified gesture group.
// ---------------------------------------------------------------------------
//
CAknTouchGestureFwBaseRecognizer*
    CAknTouchGestureFwRecognitionEngine::CreateRecognizerL(
        TAknTouchGestureFwGroup aGroup )
    {
    // Check first that the recognizer doesn't already exist.
    CAknTouchGestureFwBaseRecognizer* newRecognizer( Recognizer( aGroup ) );
    if ( newRecognizer )
        {
        return newRecognizer;
        }
    
    switch ( aGroup )
        {
        case ( EAknTouchGestureFwGroupTap ):
            {
            newRecognizer = CAknTouchGestureFwTapRecognizer::NewLC( *this );
            break;
            }
        case ( EAknTouchGestureFwGroupFlick ):
            {
            newRecognizer = CAknTouchGestureFwFlickRecognizer::NewLC( *this );
            break;
            }
        case ( EAknTouchGestureFwGroupDrag ):
            {
            newRecognizer = CAknTouchGestureFwDragRecognizer::NewLC( *this );
            break;
            }
        case ( EAknTouchGestureFwGroupPinch ):
            {
            newRecognizer = CAknTouchGestureFwPinchRecognizer::NewLC( *this );
            break;
            }
            
        default:
            {
            break;
            }
        }

    if ( newRecognizer )
        {
        iRecognizers.AppendL( newRecognizer );
        CleanupStack::Pop( newRecognizer );
        }

    return newRecognizer;
    }


// ---------------------------------------------------------------------------
// Gets recognizer for the specified gesture group.
// ---------------------------------------------------------------------------
//
CAknTouchGestureFwBaseRecognizer*
    CAknTouchGestureFwRecognitionEngine::Recognizer(
        TAknTouchGestureFwGroup aGroup )
    {
    for ( TInt i = 0; i < iRecognizers.Count(); i++ )
        {
        if ( iRecognizers[i]->GestureGroup() == aGroup )
            {
            return iRecognizers[i];
            }
        }
    return NULL;
    }


// ---------------------------------------------------------------------------
// Sends a pointer event to all enabled recognizers.
// ---------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::SendPointerEventToRecognizersL(
    TBool aMultiPointer,
    const TPointerEventData& aPointerData )
    {    
    // Inform recognizers of pointer event
    for ( TInt i = 0; i < iRecognizers.Count(); i++ )
        {
        if ( iRecognizers[ i ]->Enabled() )
            {
            // Multi pointer event
            if ( aMultiPointer )
                {
                // Both pointers in use
                if ( iPointerState->IsDoubleTouch() )
                    {
                    iRecognizers[ i ]->HandleMultiPointerEventL(
                            aPointerData,
                            *iPointerState->FirstPointerPosition(),
                            *iPointerState->SecondPointerPosition() );
                    }
                // One pointer up
                else
                    {
                    iRecognizers[ i ]->HandleMultiPointerEventL(
                            aPointerData,
                            *iPointerState->FirstPointerPosition(),
                            TPoint() );
                    }
                }
            // Single pointer event
            else
                {
                iRecognizers[ i ]->HandleSinglePointerEventL( 
                        aPointerData );
                }
            }
        }
    }


// -----------------------------------------------------------------------------
// CAknTouchGestureFwRecognitionEngine::ImmediateFeedback
// -----------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::ImmediateFeedback(
    TTouchLogicalFeedback aLogicalFeedback,
    TTouchFeedbackType aFeedbackType )
    {
    if ( iFeedBack )
        {
        // dummy pointer event is needed
        TPointerEvent pointerEvent;
        iFeedBack->InstantFeedback( iControl, aLogicalFeedback, aFeedbackType,
            pointerEvent );
        }
    }


// -----------------------------------------------------------------------------
// CAknTouchGestureFwRecognitionEngine::StartContinuousFeedback
// -----------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::StartContinuousFeedback(
    TTouchContinuousFeedback aType,
    TInt aIntensity,
    TTimeIntervalMicroSeconds32 aTimeout )
    {
    if ( iFeedBack )
        {
        iFeedBack->StartFeedback( iControl, aType, NULL,
            aIntensity, aTimeout );
        }
    }


// -----------------------------------------------------------------------------
// CAknTouchGestureFwRecognitionEngine::ModifyContinuousFeedback
// -----------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::ModifyContinuousFeedback(
    TInt aIntensity )
    {
    iFeedBack->ModifyFeedback( iControl, aIntensity );
    }


// -----------------------------------------------------------------------------
// CAknTouchGestureFwRecognitionEngine::StopContinuousFeedback
// -----------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::StopContinuousFeedback()
    {
    if ( iFeedBack )
        {
        iFeedBack->StopFeedback( iControl );
        }
    }


// ---------------------------------------------------------------------------
// Defines gesture groups, which trigger tactile feedback automatically.
// ---------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::SetFeedbackForGroupsL( TUint aGestureGroups )
    {
    CAknTouchGestureFwBaseRecognizer* recognizer;
    
    TInt count = sizeof( KGestureGroup )/sizeof( TAknTouchGestureFwGroup );
    for ( TInt i = 0; i < count; i++ )
        {
        if ( aGestureGroups & KGestureGroup[ i ] )
            {
            recognizer = Recognizer( KGestureGroup[ i ] );
            if ( recognizer )
                {
                recognizer->SetFeedbackForTypesL(
                    KAknTouchGestureFwAllGestureTypes,
                    KAknTouchGestureFwAllGestureTypes );
                }
            }
        }
    }


// ---------------------------------------------------------------------------
// Defines gesture types, which trigger tactile feedback automatically.
// ---------------------------------------------------------------------------
//
void CAknTouchGestureFwRecognitionEngine::SetFeedbackForTypesL(
    TAknTouchGestureFwGroup aGestureGroup,
    TUint aGestureTypesForTactile,
    TUint aGestureTypesForAudio )
    {
    if ( aGestureGroup == EAknTouchGestureFwNoGroup )
        {
        return;
        }
    if ( aGestureGroup == EAknTouchGestureFwAll )
        {
        for ( TInt i = 0; i < iRecognizers.Count(); i++ )
            {
            iRecognizers[ i ]->SetFeedbackForTypesL( aGestureTypesForTactile,
                aGestureTypesForAudio );        
            }
        return;
        }
    
    CAknTouchGestureFwBaseRecognizer* recognizer =
        Recognizer( aGestureGroup );
           
    if ( recognizer )
        {
        recognizer->SetFeedbackForTypesL( aGestureTypesForTactile,
            aGestureTypesForAudio );
        }
    }

// End of File