src/imports/gestures/qdeclarativegesturearea.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qdeclarativegesturearea_p.h"
       
    43 
       
    44 #include <qdeclarativeexpression.h>
       
    45 #include <qdeclarativecontext.h>
       
    46 #include <qdeclarativeinfo.h>
       
    47 
       
    48 #include <private/qdeclarativeproperty_p.h>
       
    49 #include <private/qdeclarativeitem_p.h>
       
    50 
       
    51 #include <QtCore/qdebug.h>
       
    52 #include <QtCore/qstringlist.h>
       
    53 
       
    54 #include <QtGui/qevent.h>
       
    55 
       
    56 #include <private/qobject_p.h>
       
    57 
       
    58 QT_BEGIN_NAMESPACE
       
    59 
       
    60 class QDeclarativeGestureAreaPrivate : public QDeclarativeItemPrivate
       
    61 {
       
    62     Q_DECLARE_PUBLIC(QDeclarativeGestureArea)
       
    63 public:
       
    64     QDeclarativeGestureAreaPrivate() : componentcomplete(false), gesture(0) {}
       
    65 
       
    66     typedef QMap<Qt::GestureType,QDeclarativeExpression*> Bindings;
       
    67     Bindings bindings;
       
    68 
       
    69     bool componentcomplete;
       
    70 
       
    71     QByteArray data;
       
    72 
       
    73     QGesture *gesture;
       
    74 
       
    75     bool gestureEvent(QGestureEvent *event);
       
    76 };
       
    77 
       
    78 /*!
       
    79     \qmlclass GestureArea QDeclarativeGestureArea
       
    80     \brief The GestureArea item enables simple gesture handling.
       
    81     \inherits Item
       
    82 
       
    83     A GestureArea is like a MouseArea, but it has signals for gesture events.
       
    84 
       
    85     \e {Elements in the Qt.labs module are not guaranteed to remain compatible
       
    86     in future versions.}
       
    87 
       
    88     \e {This element is only functional on devices with touch input.}
       
    89 
       
    90     \qml
       
    91     import Qt.labs.gestures 0.1
       
    92 
       
    93     GestureArea {
       
    94         anchors.fill: parent
       
    95         onPan: ... gesture.acceleration ...
       
    96         onPinch: ... gesture.rotationAngle ...
       
    97         onSwipe: ...
       
    98         onTapAndHold: ...
       
    99         onTap: ...
       
   100         onGesture: ...
       
   101     }
       
   102     \endqml
       
   103 
       
   104     Each signal has a \e gesture parameter that has the
       
   105     properties of the gesture.
       
   106 
       
   107     \table
       
   108     \header \o Signal \o Type \o Property \o Description
       
   109     \row \o onTap \o point \o position \o the position of the tap
       
   110     \row \o onTapAndHold \o point \o position \o the position of the tap
       
   111     \row \o onPan \o real \o acceleration \o the acceleration of the pan
       
   112     \row \o onPan \o point \o delta \o the offset from the previous input position to the current input
       
   113     \row \o onPan \o point \o offset \o the total offset from the first input position to the current input position
       
   114     \row \o onPan \o point \o lastOffset \o the previous value of offset
       
   115     \row \o onPinch \o point \o centerPoint \o the midpoint between the two input points
       
   116     \row \o onPinch \o point \o lastCenterPoint \o the previous value of centerPoint
       
   117     \row \o onPinch \o point \o startCenterPoint \o the first value of centerPoint
       
   118     \row \o onPinch \o real \o rotationAngle \o the angle covered by the gesture motion
       
   119     \row \o onPinch \o real \o lastRotationAngle \o the previous value of rotationAngle
       
   120     \row \o onPinch \o real \o totalRotationAngle \o the complete angle covered by the gesture
       
   121     \row \o onPinch \o real \o scaleFactor \o the change in distance between the two input points
       
   122     \row \o onPinch \o real \o lastScaleFactor \o the previous value of scaleFactor
       
   123     \row \o onPinch \o real \o totalScaleFactor \o the complete scale factor of the gesture
       
   124     \row \o onSwipe \o real \o swipeAngle \o the angle of the swipe
       
   125     \endtable
       
   126 
       
   127     Custom gestures, handled by onGesture, will have custom properties.
       
   128 
       
   129     GestureArea is an invisible item: it is never painted.
       
   130 
       
   131     \sa Gesture, MouseArea
       
   132 */
       
   133 
       
   134 /*!
       
   135     \internal
       
   136     \class QDeclarativeGestureArea
       
   137     \brief The QDeclarativeGestureArea class provides simple gesture handling.
       
   138 
       
   139 */
       
   140 QDeclarativeGestureArea::QDeclarativeGestureArea(QDeclarativeItem *parent) :
       
   141     QDeclarativeItem(*(new QDeclarativeGestureAreaPrivate), parent)
       
   142 {
       
   143     setAcceptedMouseButtons(Qt::LeftButton);
       
   144     setAcceptTouchEvents(true);
       
   145 }
       
   146 
       
   147 QDeclarativeGestureArea::~QDeclarativeGestureArea()
       
   148 {
       
   149 }
       
   150 
       
   151 QByteArray
       
   152 QDeclarativeGestureAreaParser::compile(const QList<QDeclarativeCustomParserProperty> &props)
       
   153 {
       
   154     QByteArray rv;
       
   155     QDataStream ds(&rv, QIODevice::WriteOnly);
       
   156 
       
   157     for(int ii = 0; ii < props.count(); ++ii)
       
   158     {
       
   159         QString propName = QString::fromUtf8(props.at(ii).name());
       
   160         Qt::GestureType type;
       
   161 
       
   162         if (propName == QLatin1String("onTap")) {
       
   163             type = Qt::TapGesture;
       
   164         } else if (propName == QLatin1String("onTapAndHold")) {
       
   165             type = Qt::TapAndHoldGesture;
       
   166         } else if (propName == QLatin1String("onPan")) {
       
   167             type = Qt::PanGesture;
       
   168         } else if (propName == QLatin1String("onPinch")) {
       
   169             type = Qt::PinchGesture;
       
   170         } else if (propName == QLatin1String("onSwipe")) {
       
   171             type = Qt::SwipeGesture;
       
   172         } else if (propName == QLatin1String("onGesture")) {
       
   173             type = Qt::CustomGesture;
       
   174         } else {
       
   175             error(props.at(ii), QDeclarativeGestureArea::tr("Cannot assign to non-existent property \"%1\"").arg(propName));
       
   176             return QByteArray();
       
   177         }
       
   178 
       
   179         QList<QVariant> values = props.at(ii).assignedValues();
       
   180 
       
   181         for (int i = 0; i < values.count(); ++i) {
       
   182             const QVariant &value = values.at(i);
       
   183 
       
   184             if (value.userType() == qMetaTypeId<QDeclarativeCustomParserNode>()) {
       
   185                 error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: nested objects not allowed"));
       
   186                 return QByteArray();
       
   187             } else if (value.userType() == qMetaTypeId<QDeclarativeCustomParserProperty>()) {
       
   188                 error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: syntax error"));
       
   189                 return QByteArray();
       
   190             } else {
       
   191                 QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(value);
       
   192                 if (v.isScript()) {
       
   193                     ds << propName;
       
   194                     ds << int(type);
       
   195                     ds << v.asScript();
       
   196                 } else {
       
   197                     error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: script expected"));
       
   198                     return QByteArray();
       
   199                 }
       
   200             }
       
   201         }
       
   202     }
       
   203 
       
   204     return rv;
       
   205 }
       
   206 
       
   207 void QDeclarativeGestureAreaParser::setCustomData(QObject *object,
       
   208                                             const QByteArray &data)
       
   209 {
       
   210     QDeclarativeGestureArea *ga = static_cast<QDeclarativeGestureArea*>(object);
       
   211     ga->d_func()->data = data;
       
   212 }
       
   213 
       
   214 
       
   215 void QDeclarativeGestureArea::connectSignals()
       
   216 {
       
   217     Q_D(QDeclarativeGestureArea);
       
   218     if (!d->componentcomplete)
       
   219         return;
       
   220 
       
   221     QDataStream ds(d->data);
       
   222     while (!ds.atEnd()) {
       
   223         QString propName;
       
   224         ds >> propName;
       
   225         int gesturetype;
       
   226         ds >> gesturetype;
       
   227         QString script;
       
   228         ds >> script;
       
   229         QDeclarativeExpression *exp = new QDeclarativeExpression(qmlContext(this), 0, script);
       
   230         d->bindings.insert(Qt::GestureType(gesturetype),exp);
       
   231         grabGesture(Qt::GestureType(gesturetype));
       
   232     }
       
   233 }
       
   234 
       
   235 void QDeclarativeGestureArea::componentComplete()
       
   236 {
       
   237     QDeclarativeItem::componentComplete();
       
   238     Q_D(QDeclarativeGestureArea);
       
   239     d->componentcomplete=true;
       
   240     connectSignals();
       
   241 }
       
   242 
       
   243 QGesture *QDeclarativeGestureArea::gesture() const
       
   244 {
       
   245     Q_D(const QDeclarativeGestureArea);
       
   246     return d->gesture;
       
   247 }
       
   248 
       
   249 bool QDeclarativeGestureArea::sceneEvent(QEvent *event)
       
   250 {
       
   251     Q_D(QDeclarativeGestureArea);
       
   252     if (event->type() == QEvent::Gesture)
       
   253         return d->gestureEvent(static_cast<QGestureEvent*>(event));
       
   254     return QDeclarativeItem::sceneEvent(event);
       
   255 }
       
   256 
       
   257 bool QDeclarativeGestureAreaPrivate::gestureEvent(QGestureEvent *event)
       
   258 {
       
   259     bool accept = true;
       
   260     for (Bindings::Iterator it = bindings.begin(); it != bindings.end(); ++it) {
       
   261         if ((gesture = event->gesture(it.key()))) {
       
   262             it.value()->evaluate();
       
   263             event->setAccepted(true); // XXX only if value returns true?
       
   264         }
       
   265     }
       
   266     return accept;
       
   267 }
       
   268 
       
   269 QT_END_NAMESPACE