src/hbcore/gestures/hbswipegesturerecognizer.cpp
changeset 1 f7ac710697a9
parent 0 16d8024aca5e
child 2 06ff229162e9
equal deleted inserted replaced
0:16d8024aca5e 1:f7ac710697a9
     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 /*!
       
    27 //
       
    28 //  W A R N I N G
       
    29 //  -------------
       
    30 //
       
    31 // This implementation of Gesture filter is most probably removed in later releases.
       
    32 // It exists purely as an implementation detail.
       
    33 // This implementation may change from version to
       
    34 // version without notice, or even be removed.
       
    35 //
       
    36 // We mean it.
       
    37 //
       
    38 */
       
    39 
       
    40 #include "hbswipegesturerecognizer_p.h"
       
    41 #include "hbswipegesture.h"
       
    42 #include "hbswipegesture_p.h"
       
    43 
       
    44 #include <QEvent>
       
    45 #include <QTouchEvent>
       
    46 #include <QGraphicsSceneMouseEvent>
       
    47 #include <QPoint>
       
    48 #include <QLine>
       
    49 #include <QVariant>
       
    50 
       
    51 #include <QDebug>
       
    52 
       
    53 const int KMilliSecsToSecs = 1000;
       
    54 
       
    55 /*!
       
    56 	@proto
       
    57     @hbcore
       
    58 	\class HbSwipeGestureRecognizer
       
    59     \brief HbSwipeGestureRecognizer Gesture recognizer for swipes (flicks).
       
    60 	
       
    61 */
       
    62 
       
    63 
       
    64 /*!
       
    65 	Constructs new HbSwipeGestureRecognizer.
       
    66  */
       
    67 HbSwipeGestureRecognizer::HbSwipeGestureRecognizer()
       
    68 {
       
    69 }
       
    70 
       
    71 HbSwipeGestureRecognizer::~HbSwipeGestureRecognizer()
       
    72 {
       
    73 }
       
    74 
       
    75 QGesture* HbSwipeGestureRecognizer::create(QObject *)
       
    76 {
       
    77     return new HbSwipeGesture();
       
    78 }
       
    79 
       
    80 /*!
       
    81 	The event filter function.
       
    82 	\a obj Parameter not currently used.
       
    83 
       
    84 	\internal
       
    85  */
       
    86 QGestureRecognizer::Result HbSwipeGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event)
       
    87 {
       
    88     HbSwipeGesture *q = qobject_cast<HbSwipeGesture *>(state);
       
    89     if (!q) {
       
    90         return QGestureRecognizer::Ignore;
       
    91     }
       
    92     if (QTouchEvent *touchEvent = dynamic_cast<QTouchEvent *>(event)) {
       
    93         return recognizeTouchEvent(q, touchEvent);
       
    94     }
       
    95     else if (QGraphicsSceneMouseEvent *mouseEvent = dynamic_cast<QGraphicsSceneMouseEvent *>(event)){
       
    96         return recognizeMouseEvent(q, mouseEvent);
       
    97     }
       
    98 
       
    99     return QGestureRecognizer::Ignore;
       
   100 }
       
   101 
       
   102 /*!
       
   103 
       
   104 */
       
   105 QGestureRecognizer::Result HbSwipeGestureRecognizer::recognizeTouchEvent(HbSwipeGesture *q, QTouchEvent *touchEvent)
       
   106 {
       
   107     QGestureRecognizer::Result result;
       
   108 
       
   109     switch (touchEvent->type()) {
       
   110     case QEvent::TouchBegin: {
       
   111         q->d_func()->mSpeed = 1;
       
   112         q->d_func()->mTouchPointCount = 1;
       
   113         q->d_func()->mTime = QTime::currentTime();
       
   114         result = QGestureRecognizer::MayBeGesture | QGestureRecognizer::ConsumeEventHint;
       
   115         break;
       
   116     }
       
   117     case QEvent::TouchEnd: {
       
   118         if (q->state() != Qt::NoGesture) {
       
   119             result = QGestureRecognizer::FinishGesture;
       
   120             q->setProperty("speed", (int)(q->d_func()->mSpeed*KMilliSecsToSecs));
       
   121         } else {
       
   122             result = QGestureRecognizer::CancelGesture;
       
   123         }
       
   124         break;
       
   125     }
       
   126     case QEvent::TouchUpdate: {
       
   127         if(q->d_func()->mInitialPoint == QPointF()) {
       
   128             q->d_func()->mInitialPoint = touchEvent->touchPoints().first().lastScreenPos();
       
   129         }
       
   130         
       
   131         q->setHotSpot(touchEvent->touchPoints().first().screenPos());
       
   132 
       
   133         int touchPointCount = touchEvent->touchPoints().size();
       
   134 
       
   135         qreal xDistance = 0;
       
   136         for (int i = 0; i < touchPointCount; i++) {
       
   137             qreal distance = touchEvent->touchPoints().at(i).screenPos().x() - touchEvent->touchPoints().at(i).lastScreenPos().x();
       
   138             if(qAbs(distance) > qAbs(xDistance)) {
       
   139                 xDistance = distance;
       
   140             }
       
   141         }
       
   142 
       
   143         qreal yDistance = 0;
       
   144         for (int i = 0; i < touchPointCount; i++) {
       
   145             qreal distance = touchEvent->touchPoints().at(i).screenPos().y() - touchEvent->touchPoints().at(i).lastScreenPos().y();
       
   146             if(qAbs(distance) > qAbs(yDistance)) {
       
   147                 yDistance = distance;
       
   148             }
       
   149         }
       
   150 
       
   151         xDistance = qAbs(xDistance);
       
   152         yDistance = qAbs(yDistance);
       
   153 
       
   154         const qreal distance = xDistance >= yDistance ? xDistance : yDistance;
       
   155         int elapsedTime = q->d_func()->mTime.msecsTo(QTime::currentTime());
       
   156         if (!elapsedTime)
       
   157             elapsedTime = 1;
       
   158         q->d_func()->mSpeed = 0.9 * q->d_func()->mSpeed + distance / elapsedTime;
       
   159         q->d_func()->mTime = QTime::currentTime();
       
   160         q->setSwipeAngle(QLineF(q->d_func()->mInitialPoint, touchEvent->touchPoints().first().screenPos()).angle());
       
   161 
       
   162         static const int MoveThreshold = 5;
       
   163         if (!touchMoveEvent(touchEvent)) {
       
   164             if (q->state() != Qt::NoGesture) {
       
   165                 result = QGestureRecognizer::TriggerGesture/* | QGestureRecognizer::ConsumeEventHint*/;
       
   166             } else {
       
   167                 result = QGestureRecognizer::MayBeGesture/* | QGestureRecognizer::ConsumeEventHint*/;
       
   168             }
       
   169         }
       
   170         else if (xDistance > MoveThreshold || yDistance > MoveThreshold) {
       
   171             // measure the distance to check if the direction changed
       
   172             QSwipeGesture::SwipeDirection horizontal = QSwipeGesture::NoDirection;
       
   173             if(xDistance >= MoveThreshold)
       
   174                 horizontal = touchEvent->touchPoints().first().screenPos().x() - touchEvent->touchPoints().first().lastScreenPos().x() > 0 ? QSwipeGesture::Right : QSwipeGesture::Left;
       
   175             QSwipeGesture::SwipeDirection vertical = QSwipeGesture::NoDirection;
       
   176             if(yDistance >= MoveThreshold)
       
   177                 vertical = touchEvent->touchPoints().first().screenPos().y() - touchEvent->touchPoints().first().lastScreenPos().y() > 0 ? QSwipeGesture::Down : QSwipeGesture::Up;
       
   178             if ((yDistance > MoveThreshold && q->d_func()->mVerticalDirection != QSwipeGesture::NoDirection &&  q->d_func()->mVerticalDirection != vertical) ||
       
   179                 (xDistance > MoveThreshold && q->d_func()->mHorizontalDirection != QSwipeGesture::NoDirection && q->d_func()->mHorizontalDirection != horizontal)) {
       
   180                 // the user has changed the direction!
       
   181                 result = QGestureRecognizer::CancelGesture;
       
   182             }
       
   183             else {
       
   184                 result = QGestureRecognizer::TriggerGesture/* | QGestureRecognizer::ConsumeEventHint*/;
       
   185             }
       
   186             q->d_func()->mVerticalDirection = vertical;
       
   187             q->d_func()->mHorizontalDirection = horizontal;
       
   188 
       
   189         } else {
       
   190             if (q->state() != Qt::NoGesture)
       
   191                 result = QGestureRecognizer::CancelGesture;
       
   192             else
       
   193                 result = QGestureRecognizer::MayBeGesture/* | QGestureRecognizer::ConsumeEventHint*/;
       
   194         }
       
   195         q->d_func()->mTouchPointCount = touchPointCount;
       
   196         break;
       
   197     }
       
   198     default:
       
   199         result = QGestureRecognizer::Ignore;
       
   200         break;    
       
   201     }
       
   202     return result;
       
   203 }
       
   204 
       
   205 /*!
       
   206 
       
   207 */
       
   208 QGestureRecognizer::Result HbSwipeGestureRecognizer::recognizeMouseEvent(HbSwipeGesture *q, QGraphicsSceneMouseEvent *mouseEvent)
       
   209 {
       
   210     QGestureRecognizer::Result result;
       
   211 
       
   212     switch (mouseEvent->type()) {
       
   213     case QEvent::GraphicsSceneMousePress: {
       
   214         q->d_func()->mSpeed = 1;
       
   215         q->d_func()->mTime = QTime::currentTime();
       
   216         result = QGestureRecognizer::MayBeGesture;
       
   217         break;
       
   218     }
       
   219     case QEvent::GraphicsSceneMouseRelease: {
       
   220         if (q->state() != Qt::NoGesture) {
       
   221             result = QGestureRecognizer::FinishGesture;
       
   222             q->setProperty("speed", (int)(q->d_func()->mSpeed*KMilliSecsToSecs));
       
   223         } else {
       
   224             result = QGestureRecognizer::CancelGesture;
       
   225         }
       
   226         break;
       
   227     }
       
   228     case QEvent::GraphicsSceneMouseMove: {
       
   229         if(q->d_func()->mInitialMousePoint == QPoint()) {
       
   230             q->d_func()->mInitialMousePoint = mouseEvent->lastScreenPos();
       
   231         }
       
   232         
       
   233         q->setHotSpot(mouseEvent->screenPos());
       
   234 
       
   235         int xDistance = qAbs(mouseEvent->lastScreenPos().x() - mouseEvent->screenPos().x());
       
   236         int yDistance = qAbs(mouseEvent->lastScreenPos().y() - mouseEvent->screenPos().y());
       
   237 
       
   238         const int distance = xDistance >= yDistance ? xDistance : yDistance;
       
   239         int elapsedTime = q->d_func()->mTime.msecsTo(QTime::currentTime());
       
   240         if (!elapsedTime)
       
   241             elapsedTime = 1;
       
   242         q->d_func()->mSpeed = 0.9 * q->d_func()->mSpeed + distance / elapsedTime;
       
   243         q->d_func()->mTime = QTime::currentTime();
       
   244         q->setSwipeAngle(QLineF(QLine(q->d_func()->mInitialMousePoint, mouseEvent->screenPos())).angle());
       
   245 
       
   246         static const int MoveThreshold = 5;
       
   247         if (xDistance > MoveThreshold || yDistance > MoveThreshold) {
       
   248             // measure the distance to check if the direction changed
       
   249             QSwipeGesture::SwipeDirection horizontal = QSwipeGesture::NoDirection;
       
   250             if(xDistance >= MoveThreshold)
       
   251                 horizontal = mouseEvent->screenPos().x() - mouseEvent->lastScreenPos().x() > 0 ? QSwipeGesture::Right : QSwipeGesture::Left;
       
   252             QSwipeGesture::SwipeDirection vertical = QSwipeGesture::NoDirection;
       
   253             if(yDistance >= MoveThreshold)
       
   254                 vertical = mouseEvent->screenPos().y() - mouseEvent->lastScreenPos().y() > 0 ? QSwipeGesture::Down : QSwipeGesture::Up;
       
   255             if ((yDistance > MoveThreshold && q->d_func()->mVerticalDirection != QSwipeGesture::NoDirection &&  q->d_func()->mVerticalDirection != vertical) ||
       
   256                 (xDistance > MoveThreshold && q->d_func()->mHorizontalDirection != QSwipeGesture::NoDirection && q->d_func()->mHorizontalDirection != horizontal)) {
       
   257                 // the user has changed the direction!
       
   258                 result = QGestureRecognizer::CancelGesture;
       
   259             }
       
   260             else {
       
   261                 result = QGestureRecognizer::TriggerGesture;
       
   262             }
       
   263             q->d_func()->mVerticalDirection = vertical;
       
   264             q->d_func()->mHorizontalDirection = horizontal;
       
   265 
       
   266         } else {
       
   267             if (q->state() != Qt::NoGesture)
       
   268                 result = QGestureRecognizer::CancelGesture;
       
   269             else
       
   270                 result = QGestureRecognizer::MayBeGesture;
       
   271         }
       
   272         break;
       
   273     }
       
   274     default:
       
   275         result = QGestureRecognizer::Ignore;
       
   276         break;    
       
   277     }
       
   278     return result;
       
   279 }
       
   280 
       
   281 /*!
       
   282 
       
   283 */
       
   284 void HbSwipeGestureRecognizer::reset(QGesture* state)
       
   285 {
       
   286     HbSwipeGesture *q = qobject_cast<HbSwipeGesture *>(state);
       
   287     if(q) {
       
   288         q->d_func()->mVerticalDirection = QSwipeGesture::NoDirection;
       
   289         q->d_func()->mHorizontalDirection = QSwipeGesture::NoDirection;
       
   290         q->setSwipeAngle(0);
       
   291 
       
   292         q->d_func()->mInitialPoint = QPointF();
       
   293         q->d_func()->mInitialMousePoint = QPoint();
       
   294         q->d_func()->mSpeed = 0;
       
   295         q->d_func()->mTime = QTime();
       
   296         q->setProperty("speed", QVariant());
       
   297         q->d_func()->mTouchPointCount= 0;
       
   298     }
       
   299     QGestureRecognizer::reset(state);
       
   300 }
       
   301 
       
   302 /*!
       
   303 
       
   304 */
       
   305 bool HbSwipeGestureRecognizer::touchMoveEvent(QTouchEvent *touchEvent)
       
   306 {
       
   307     QTouchEvent::TouchPoint touchPoint;
       
   308     foreach (touchPoint, touchEvent->touchPoints()) {
       
   309         if (QLineF(touchPoint.screenPos(), touchPoint.lastScreenPos()).length() > 2) {
       
   310             return true;
       
   311         }
       
   312     }
       
   313     return false;
       
   314 }
       
   315 
       
   316 /*!
       
   317 
       
   318 */
       
   319 QPointF HbSwipeGestureRecognizer::touchPointsCenterPoint(QTouchEvent *touchEvent)
       
   320 {
       
   321     qreal x = 0;
       
   322     for(int i = 0; i < touchEvent->touchPoints().size(); i++) {
       
   323         x += touchEvent->touchPoints().at(i).screenPos().x();
       
   324     }
       
   325     x /= touchEvent->touchPoints().size();
       
   326 
       
   327     qreal y = 0;
       
   328     for(int i = 0; i < touchEvent->touchPoints().size(); i++) {
       
   329         y += touchEvent->touchPoints().at(i).screenPos().y();
       
   330     }
       
   331     y /= touchEvent->touchPoints().size();
       
   332 
       
   333     return QPointF(x, y);
       
   334 }
       
   335 
       
   336 // End of File