src/hbcore/gestures/hbtapandholdgesturerecognizer.cpp
changeset 0 16d8024aca5e
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbCore module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include "hbtapandholdgesture.h"
       
    27 #include "hbtapandholdgesture_p.h"
       
    28 #include "hbtapandholdgesturerecognizer_p.h"
       
    29 
       
    30 #include <QWidget>
       
    31 #include <QGesture>
       
    32 #include <QEvent>
       
    33 #include <QVariant>
       
    34 #include <QGraphicsSceneEvent>
       
    35 #include <QDebug>
       
    36 
       
    37 /*!
       
    38     \internal
       
    39     \class HbTapAndHoldGestureRecognizer
       
    40 
       
    41     \brief HbTapAndHoldGestureRecognizer implements a gesture for tap and hold.
       
    42 */
       
    43 
       
    44 /*!
       
    45     \internal
       
    46     \brief Default constructor.
       
    47 */
       
    48 HbTapAndHoldGestureRecognizer::HbTapAndHoldGestureRecognizer()
       
    49     :
       
    50     QGestureRecognizer()
       
    51 {
       
    52 }
       
    53 
       
    54 /*!
       
    55     \internal
       
    56     \brief Create new gesture object.
       
    57     \param target Associated target.
       
    58 */
       
    59 QGesture* HbTapAndHoldGestureRecognizer::create(QObject* /*target*/)
       
    60 {
       
    61     return new HbTapAndHoldGesture;
       
    62 }
       
    63 
       
    64 /*!
       
    65     \internal
       
    66     \brief Handle mouse press event.
       
    67     \return State change information.
       
    68 
       
    69     Mouse press event only needs to record the location and start short timer
       
    70     before triggering.
       
    71 */
       
    72 QGestureRecognizer::Result HbTapAndHoldGestureRecognizer::HandleGraphicsSceneMousePress(
       
    73 	HbTapAndHoldGesture& gesture )
       
    74 {
       
    75     // Last position is automatically recorded before this event call.
       
    76     // Press event only means, that gesture is starting, thus last position is
       
    77     // also the starting position.
       
    78     gesture.setProperty("startPos", gesture.property("position"));
       
    79     gesture.priv->mTimerID = startTimer(gesture, HOLDTAP_ACTIVATION_USECS);
       
    80     gesture.setHotSpot(gesture.property("startPos").toPointF());
       
    81 
       
    82     return QGestureRecognizer::MayBeGesture;
       
    83 }
       
    84 
       
    85 /*!
       
    86     \internal
       
    87     \brief Handle mouse move event.
       
    88     \return State change information.
       
    89 
       
    90     Mousemove -event should cancel the gesture, when finger has moved outside
       
    91     the threshold.
       
    92 */
       
    93 QGestureRecognizer::Result HbTapAndHoldGestureRecognizer::HandleGraphicsSceneMouseMove(
       
    94 	HbTapAndHoldGesture& gesture )
       
    95 {
       
    96     // In case timer is not running, just cancel gesture.priv-> This is an unknown state.
       
    97     if ( !gesture.priv->mRunningTime ) return QGestureRecognizer::CancelGesture;
       
    98 
       
    99     // Makes sure that finger remains inside the movement threshold.
       
   100     if ( gesture.outsideThreshold() )
       
   101     {
       
   102         // Finger has moved outside, so reset and cancel this gesture.priv->
       
   103         reset(&gesture);
       
   104         return QGestureRecognizer::CancelGesture;
       
   105     }
       
   106 
       
   107     // Move events should be just ignored.
       
   108     return QGestureRecognizer::Ignore;
       
   109 }
       
   110 
       
   111 /*!
       
   112     \internal
       
   113     \brief Handles mouse release event.
       
   114     \return State change information.
       
   115 
       
   116     When release happens, any timer running dictates, whether the gesture
       
   117     should be considered as cancelled or finished. Both events needs to be
       
   118     sent, so that UI may react correctly.
       
   119 */
       
   120 QGestureRecognizer::Result HbTapAndHoldGestureRecognizer::HandleGraphicsSceneMouseRelease(
       
   121 	HbTapAndHoldGesture& gesture )
       
   122 {
       
   123     // Check if the gesture is already been cancelled. This is an unknown state.
       
   124     if ( !gesture.priv->mRunningTime ) return QGestureRecognizer::CancelGesture;
       
   125 
       
   126     // If release happens, before timer has expired, cancel the gesture.priv->
       
   127     if ( gesture.priv->mTimerID )
       
   128     {
       
   129         reset(&gesture);
       
   130         return QGestureRecognizer::CancelGesture;
       
   131     }
       
   132     else
       
   133     {
       
   134         // Gesture has succesfully executed. Reward the UI with finished event.
       
   135         gesture.priv->mTimerID = 0;
       
   136         gesture.priv->mRunningTime = 0;
       
   137         return QGestureRecognizer::FinishGesture;
       
   138     }
       
   139 }
       
   140 
       
   141 /*!
       
   142     \internal
       
   143     \brief Handle timer event.
       
   144     \return State change information.
       
   145 
       
   146     Timer is a heart of the tap and hold gesture and dictates its
       
   147     behavior. There are three phases: not started - started - finished.
       
   148     When the timer event is invoked, the state of the gesture is changed
       
   149     and the timer event is consumed.
       
   150 
       
   151     \see HbTapAndHoldGestureRecognizer::HandleGesture()
       
   152 */
       
   153 QGestureRecognizer::Result HbTapAndHoldGestureRecognizer::HandleTimer(
       
   154 	HbTapAndHoldGesture& gesture,
       
   155 	QEvent& event)
       
   156 {
       
   157     // React only to own timer event, please.
       
   158     if ( gesture.priv->mTimerID == GetTimerID(event) )
       
   159     {
       
   160         // Handle the event and consume the timer event as it doesn't belong
       
   161         // to anybody else.
       
   162         return HandleGesture(gesture) | QGestureRecognizer::ConsumeEventHint;
       
   163     }
       
   164     else
       
   165     {
       
   166         // Not our business.
       
   167         return QGestureRecognizer::Ignore;
       
   168     }
       
   169 }
       
   170 
       
   171 /*!
       
   172     \internal
       
   173     \brief Handle event invoked by the timer.
       
   174     \return State change information.
       
   175 
       
   176     Changes the hold and tap -gestures state, dictated by the expired timer.
       
   177     Changes the state from Not started to started and from started to finished.
       
   178 
       
   179     \see HbTapAndHoldGestureRecognizer::HandleTimer()
       
   180 */
       
   181 QGestureRecognizer::Result HbTapAndHoldGestureRecognizer::HandleGesture(
       
   182 	HbTapAndHoldGesture& gesture)
       
   183 {
       
   184     switch ( gesture.priv->mRunningTime )
       
   185     {
       
   186         // Time to invoke the started event.
       
   187         case HOLDTAP_ACTIVATION_USECS:
       
   188             gesture.priv->mTimerID = startTimer(gesture, HOLDTAP_DURATION_USECS);
       
   189             return QGestureRecognizer::TriggerGesture;
       
   190 
       
   191         // Time to invoke finish event.
       
   192         case HOLDTAP_DURATION_USECS:
       
   193             gesture.priv->mTimerID = 0;
       
   194             return QGestureRecognizer::FinishGesture;
       
   195 
       
   196         default: break;
       
   197     }
       
   198 
       
   199     return QGestureRecognizer::Ignore;
       
   200 }
       
   201 
       
   202 /*!
       
   203     \internal
       
   204     \brief Checks whether the events needs to be reacted or not
       
   205     \param event Event to be analyzed.
       
   206     \return True, if the event is mouse event or timer event, otherwise False.
       
   207 */
       
   208 bool HbTapAndHoldGestureRecognizer::IsInterestingEvent(QEvent& event)
       
   209 {
       
   210     return ( event.type() >= QEvent::GraphicsSceneMouseMove &&
       
   211 			 event.type() <= QEvent::GraphicsSceneMouseRelease ) ||
       
   212            event.type() == QEvent::Timer;
       
   213 }
       
   214 
       
   215 /*!
       
   216     \internal
       
   217     \brief Retrieves the timer event from the event from the event.
       
   218     \param event Event for investigation.
       
   219     \return Valid timer ID
       
   220 */
       
   221 int HbTapAndHoldGestureRecognizer::GetTimerID(QEvent& event)
       
   222 {
       
   223 	// It is already safe to presume the event is timer event, because
       
   224 	// the test is already made.
       
   225     QTimerEvent* te = static_cast<QTimerEvent*>(&event);
       
   226     return te->timerId();
       
   227 }
       
   228 
       
   229 /*!
       
   230     \internal
       
   231     \brief Recognizes and handles events and converts them to gesture events.
       
   232     \param state Associated gesture.priv->
       
   233     \param watched Object that needs attention.
       
   234     \param event Event invoked the this function call.
       
   235     \return State change information.
       
   236     \relates QGestureRecognizer
       
   237 */
       
   238 QGestureRecognizer::Result HbTapAndHoldGestureRecognizer::recognize(
       
   239         QGesture *state, QObject * /*watched*/, QEvent *event)
       
   240 {
       
   241     // Don't even try to handle cases, when any of the pointers is NULL.
       
   242     if (!state || !event) return QGestureRecognizer::Ignore;
       
   243     // Ignore events which are not gesture events.
       
   244     if ( !IsInterestingEvent(*event) ) return QGestureRecognizer::Ignore;
       
   245 
       
   246     HbTapAndHoldGesture& gesture = *static_cast<HbTapAndHoldGesture*>(state);
       
   247     gesture.update(*event);
       
   248 
       
   249     QGestureRecognizer::Result result(QGestureRecognizer::Ignore);
       
   250 
       
   251     switch (event->type()) {
       
   252     case QEvent::GraphicsSceneMousePress:   return HandleGraphicsSceneMousePress(gesture);
       
   253     case QEvent::GraphicsSceneMouseRelease: return HandleGraphicsSceneMouseRelease(gesture);
       
   254     case QEvent::GraphicsSceneMouseMove:    return HandleGraphicsSceneMouseMove(gesture);
       
   255     case QEvent::Timer:                     return HandleTimer(gesture, *event);
       
   256 
       
   257     case QEvent::TouchBegin:
       
   258     case QEvent::TouchUpdate:
       
   259     case QEvent::TouchEnd: return QGestureRecognizer::Ignore;
       
   260     default: break;
       
   261     }
       
   262     return QGestureRecognizer::Ignore;
       
   263 }
       
   264 
       
   265 /*!
       
   266     \internal
       
   267     \brief Clears all values for recognizer and gesture.priv->
       
   268     \param state Associated gesture.priv->
       
   269     \relates QGestureRecognizer
       
   270 */
       
   271 void HbTapAndHoldGestureRecognizer::reset(QGesture *state)
       
   272 {
       
   273     QGestureRecognizer::reset(state);
       
   274 
       
   275 	HbTapAndHoldGesture& gesture = *static_cast<HbTapAndHoldGesture*>(state);
       
   276     if ( gesture.priv->mTimerID )
       
   277     {
       
   278         gesture.killTimer(gesture.priv->mTimerID);
       
   279     }
       
   280 
       
   281 	gesture.setProperty("startPos", QVariant());
       
   282     gesture.setProperty("tapRadius", QVariant());
       
   283 
       
   284     gesture.priv->mTimerID = 0;
       
   285     gesture.priv->mRunningTime = 0;
       
   286 }
       
   287 
       
   288 /*!
       
   289     \internal
       
   290     \brief Starts brand new timer.
       
   291     \param msecs Timer runtime in microseconds
       
   292     \return ID of the timer
       
   293 */
       
   294 int HbTapAndHoldGestureRecognizer::startTimer(
       
   295 	HbTapAndHoldGesture& gesture,
       
   296 	int msecs)
       
   297 {
       
   298     gesture.priv->mRunningTime = msecs;
       
   299     return gesture.startTimer(msecs);
       
   300 }
       
   301