Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / src / imports / gestures / qdeclarativegesturearea.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 #ifndef QT_NO_GESTURES
59
60 QT_BEGIN_NAMESPACE
61
62 class QDeclarativeGestureAreaPrivate : public QDeclarativeItemPrivate
63 {
64     Q_DECLARE_PUBLIC(QDeclarativeGestureArea)
65 public:
66     QDeclarativeGestureAreaPrivate() : componentcomplete(false), gesture(0) {}
67
68     typedef QMap<Qt::GestureType,QDeclarativeExpression*> Bindings;
69     Bindings bindings;
70
71     bool componentcomplete;
72
73     QByteArray data;
74
75     QGesture *gesture;
76
77     bool gestureEvent(QGestureEvent *event);
78 };
79
80 /*!
81     \qmlclass GestureArea QDeclarativeGestureArea
82     \ingroup qml-basic-interaction-elements
83
84     \brief The GestureArea item enables simple gesture handling.
85     \inherits Item
86
87     A GestureArea is like a MouseArea, but it has signals for gesture events.
88
89     \warning Elements in the Qt.labs module are not guaranteed to remain compatible
90     in future versions.
91
92     \warning GestureArea is an experimental element whose development has
93     been discontinued.  PinchArea is available in QtQuick 1.1 and handles
94     two finger gesture input.
95
96     \note This element is only functional on devices with touch input.
97
98     \qml
99     import Qt.labs.gestures 1.0
100
101     GestureArea {
102         anchors.fill: parent
103      // onPan:        ... gesture.acceleration ...
104      // onPinch:      ... gesture.rotationAngle ...
105      // onSwipe:      ...
106      // onTapAndHold: ...
107      // onTap:        ...
108      // onGesture:    ...
109     }
110     \endqml
111
112     Each signal has a \e gesture parameter that has the
113     properties of the gesture.
114
115     \table
116     \header \o Signal \o Type \o Property \o Description
117     \row \o onTap \o point \o position \o the position of the tap
118     \row \o onTapAndHold \o point \o position \o the position of the tap
119     \row \o onPan \o real \o acceleration \o the acceleration of the pan
120     \row \o onPan \o point \o delta \o the offset from the previous input position to the current input
121     \row \o onPan \o point \o offset \o the total offset from the first input position to the current input position
122     \row \o onPan \o point \o lastOffset \o the previous value of offset
123     \row \o onPinch \o point \o centerPoint \o the midpoint between the two input points
124     \row \o onPinch \o point \o lastCenterPoint \o the previous value of centerPoint
125     \row \o onPinch \o point \o startCenterPoint \o the first value of centerPoint
126     \row \o onPinch \o real \o rotationAngle \o the angle covered by the gesture motion
127     \row \o onPinch \o real \o lastRotationAngle \o the previous value of rotationAngle
128     \row \o onPinch \o real \o totalRotationAngle \o the complete angle covered by the gesture
129     \row \o onPinch \o real \o scaleFactor \o the change in distance between the two input points
130     \row \o onPinch \o real \o lastScaleFactor \o the previous value of scaleFactor
131     \row \o onPinch \o real \o totalScaleFactor \o the complete scale factor of the gesture
132     \row \o onSwipe \o real \o swipeAngle \o the angle of the swipe
133     \endtable
134
135     Custom gestures, handled by onGesture, will have custom properties.
136
137     GestureArea is an invisible item: it is never painted.
138
139     \sa MouseArea
140 */
141
142 /*!
143     \internal
144     \class QDeclarativeGestureArea
145     \brief The QDeclarativeGestureArea class provides simple gesture handling.
146
147 */
148 QDeclarativeGestureArea::QDeclarativeGestureArea(QDeclarativeItem *parent) :
149     QDeclarativeItem(*(new QDeclarativeGestureAreaPrivate), parent)
150 {
151     setAcceptedMouseButtons(Qt::LeftButton);
152     setAcceptTouchEvents(true);
153 }
154
155 QDeclarativeGestureArea::~QDeclarativeGestureArea()
156 {
157 }
158
159 QByteArray
160 QDeclarativeGestureAreaParser::compile(const QList<QDeclarativeCustomParserProperty> &props)
161 {
162     QByteArray rv;
163     QDataStream ds(&rv, QIODevice::WriteOnly);
164
165     for(int ii = 0; ii < props.count(); ++ii)
166     {
167         QString propName = QString::fromUtf8(props.at(ii).name());
168         Qt::GestureType type;
169
170         if (propName == QLatin1String("onTap")) {
171             type = Qt::TapGesture;
172         } else if (propName == QLatin1String("onTapAndHold")) {
173             type = Qt::TapAndHoldGesture;
174         } else if (propName == QLatin1String("onPan")) {
175             type = Qt::PanGesture;
176         } else if (propName == QLatin1String("onPinch")) {
177             type = Qt::PinchGesture;
178         } else if (propName == QLatin1String("onSwipe")) {
179             type = Qt::SwipeGesture;
180         } else if (propName == QLatin1String("onGesture")) {
181             type = Qt::CustomGesture;
182         } else {
183             error(props.at(ii), QDeclarativeGestureArea::tr("Cannot assign to non-existent property \"%1\"").arg(propName));
184             return QByteArray();
185         }
186
187         QList<QVariant> values = props.at(ii).assignedValues();
188
189         for (int i = 0; i < values.count(); ++i) {
190             const QVariant &value = values.at(i);
191
192             if (value.userType() == qMetaTypeId<QDeclarativeCustomParserNode>()) {
193                 error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: nested objects not allowed"));
194                 return QByteArray();
195             } else if (value.userType() == qMetaTypeId<QDeclarativeCustomParserProperty>()) {
196                 error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: syntax error"));
197                 return QByteArray();
198             } else {
199                 QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(value);
200                 if (v.isScript()) {
201                     ds << propName;
202                     ds << int(type);
203                     ds << v.asScript();
204                 } else {
205                     error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: script expected"));
206                     return QByteArray();
207                 }
208             }
209         }
210     }
211
212     return rv;
213 }
214
215 void QDeclarativeGestureAreaParser::setCustomData(QObject *object,
216                                             const QByteArray &data)
217 {
218     QDeclarativeGestureArea *ga = static_cast<QDeclarativeGestureArea*>(object);
219     ga->d_func()->data = data;
220 }
221
222
223 void QDeclarativeGestureArea::connectSignals()
224 {
225     Q_D(QDeclarativeGestureArea);
226     if (!d->componentcomplete)
227         return;
228
229     QDataStream ds(d->data);
230     while (!ds.atEnd()) {
231         QString propName;
232         ds >> propName;
233         int gesturetype;
234         ds >> gesturetype;
235         QString script;
236         ds >> script;
237         QDeclarativeExpression *exp = new QDeclarativeExpression(qmlContext(this), this, script);
238         d->bindings.insert(Qt::GestureType(gesturetype),exp);
239         grabGesture(Qt::GestureType(gesturetype));
240     }
241 }
242
243 void QDeclarativeGestureArea::componentComplete()
244 {
245     QDeclarativeItem::componentComplete();
246     Q_D(QDeclarativeGestureArea);
247     d->componentcomplete=true;
248     connectSignals();
249 }
250
251 QGesture *QDeclarativeGestureArea::gesture() const
252 {
253     Q_D(const QDeclarativeGestureArea);
254     return d->gesture;
255 }
256
257 bool QDeclarativeGestureArea::sceneEvent(QEvent *event)
258 {
259     Q_D(QDeclarativeGestureArea);
260     if (event->type() == QEvent::Gesture)
261         return d->gestureEvent(static_cast<QGestureEvent*>(event));
262     return QDeclarativeItem::sceneEvent(event);
263 }
264
265 bool QDeclarativeGestureAreaPrivate::gestureEvent(QGestureEvent *event)
266 {
267     bool accept = true;
268     for (Bindings::Iterator it = bindings.begin(); it != bindings.end(); ++it) {
269         if ((gesture = event->gesture(it.key()))) {
270             QDeclarativeExpression *expr = it.value();
271             expr->evaluate();
272             if (expr->hasError())
273                 qmlInfo(q_func()) << expr->error();
274             event->setAccepted(true); // XXX only if value returns true?
275         }
276     }
277     return accept;
278 }
279
280 QT_END_NAMESPACE
281
282 #endif // QT_NO_GESTURES