diff options
| author | Zeno Albisser <zeno.albisser@nokia.com> | 2011-01-06 16:19:29 +0100 |
|---|---|---|
| committer | Zeno Albisser <zeno.albisser@nokia.com> | 2011-01-06 16:24:55 +0100 |
| commit | 263bd4640cf4a4b02dc672991dfa10832fe66906 (patch) | |
| tree | 50026d3489d887b2ef6a56f64bbaeace3ccb1748 | |
added source code for TouchArea
| -rw-r--r-- | TouchArea/TouchArea.pro | 24 | ||||
| -rw-r--r-- | TouchArea/qdeclarativetoucharea.cpp | 166 | ||||
| -rw-r--r-- | TouchArea/qdeclarativetoucharea.h | 165 | ||||
| -rw-r--r-- | TouchArea/qmldir | 1 | ||||
| -rw-r--r-- | TouchArea/touchareaplugin.cpp | 12 | ||||
| -rw-r--r-- | TouchArea/touchareaplugin.h | 15 |
6 files changed, 383 insertions, 0 deletions
diff --git a/TouchArea/TouchArea.pro b/TouchArea/TouchArea.pro new file mode 100644 index 0000000..0a38537 --- /dev/null +++ b/TouchArea/TouchArea.pro @@ -0,0 +1,24 @@ +TEMPLATE = lib +CONFIG += qt plugin +QT += declarative +TARGET = $$qtLibraryTarget(qmltouchareaplugin) + +TARGETPATH = Qt/labs/toucharea +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/imports/$$TARGETPATH +else:DESTDIR = imports/$$TARGETPATH +target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH + +qmldir.files += $$PWD/qmldir +qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH + +HEADERS += \ + touchareaplugin.h \ + qdeclarativetoucharea.h + +SOURCES += \ + touchareaplugin.cpp \ + qdeclarativetoucharea.cpp + +QMAKE_POST_LINK=$(COPY_FILE) $$PWD/qmldir $$DESTDIR + +INSTALLS += target qmldir diff --git a/TouchArea/qdeclarativetoucharea.cpp b/TouchArea/qdeclarativetoucharea.cpp new file mode 100644 index 0000000..470fead --- /dev/null +++ b/TouchArea/qdeclarativetoucharea.cpp @@ -0,0 +1,166 @@ + +#include "qdeclarativetoucharea.h" +#include "qevent.h" +#include "qsharedpointer.h" +#include <math.h> + +int QDeclarativeTouchArea::_globalTouchActive = 0; + +QDeclarativeTouchArea::QDeclarativeTouchArea(QDeclarativeItem *parent) + : QDeclarativeItem(parent), + _minimumTouches(0), + _maximumTouches(INT_MAX), + _scaleFactor(1.0), + _rotationAngle(0.0), + _topTouchArea(this), + _active(false) +{ + setAcceptTouchEvents(true); + setAcceptedMouseButtons(Qt::LeftButton); + setFiltersChildEvents(true); +} + +void QDeclarativeTouchArea::updateTopTouchArea() { + for (QDeclarativeItem* pItem = parentItem(); pItem != 0; pItem = pItem->parentItem()) { + if (QDeclarativeTouchArea* ta = qobject_cast<QDeclarativeTouchArea*>(pItem)) { + _topTouchArea = ta; + } + } +} + +QDeclarativeTouchArea::~QDeclarativeTouchArea() { +} + +bool QDeclarativeTouchArea::sceneEvent(QEvent *event) { + switch (event->type()) { + case QEvent::TouchBegin: + updateTopTouchArea(); + if (_globalTouchActive == 0 || _topTouchArea->_active) { + _topTouchArea->_active = true; + updateTouchData(event); + _globalTouchActive++; + return true; + } + break; + case QEvent::TouchUpdate: + updateTouchData(event); + return true; + case QEvent::TouchEnd: { + updateTouchData(event); + _globalTouchActive--; + if (_globalTouchActive == 0) + _topTouchArea->_active = false; + return true; + } + default: + break; + } + return QDeclarativeItem::sceneEvent(event); +} + +void QDeclarativeTouchArea::updateTouchData(QEvent *event) { + bool ended = false; + bool moved = false; + bool started = false; + + QTouchEvent *e = static_cast<QTouchEvent*>(event); + clearChangedAndReleasedTouches(); + + QList<QTouchEvent::TouchPoint> touchPoints = e->touchPoints(); + int numTouchPoints = touchPoints.count(); + if (numTouchPoints >= _minimumTouches && numTouchPoints <= _maximumTouches) { + foreach (QTouchEvent::TouchPoint p, touchPoints) { + Qt::TouchPointState touchPointState = p.state(); + int id = p.id(); + if (touchPointState & Qt::TouchPointReleased) { + QDeclarativeTouchPoint* dtp = static_cast<QDeclarativeTouchPoint*>(_touches[id]); + _changedTouches.insert(id,dtp); + _releasedTouches.append(dtp); + _touches.remove(id); + ended = true; + } else if (touchPointState & Qt::TouchPointMoved) { + updateTouchPoint(static_cast<QDeclarativeTouchPoint*>(_touches[id]),&p); + updatePinch(&touchPoints); + moved = true; + } else if (!_touches.contains(id)) { + addTouchPoint(&p); + started = true; + } + } + if (ended) emit(touchEnd()); + if (moved) emit(touchMove()); + if (started) emit(touchStart()); + } + event->accept(); +} + +void QDeclarativeTouchArea::clearChangedAndReleasedTouches() { + foreach (QObject *p, _releasedTouches) { + QDeclarativeTouchPoint* dtp = static_cast<QDeclarativeTouchPoint*>(p); + if (!dtp->isQmlReferenced()) + delete dtp; + else + dtp->setValid(false); + } + _changedTouches.clear(); + _releasedTouches.clear(); +} + +void QDeclarativeTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p) { + QDeclarativeTouchPoint *dtp = 0; + foreach (QObject* proto, _touchPrototypes) { + QDeclarativeTouchPoint* tp = static_cast<QDeclarativeTouchPoint*>(proto); + if (!tp->isValid()) { + tp->setValid(true); + dtp = tp; + break; + } + } + + if (dtp == 0) + dtp = new QDeclarativeTouchPoint(false); + dtp->setId(p->id()); + updateTouchPoint(dtp,p); + _touches.insert(p->id(),dtp); +} + +void QDeclarativeTouchArea::addTouchPrototype(QDeclarativeTouchPoint *prototype) { + int id = _touchPrototypes.count(); + prototype->setId(id); + _touchPrototypes.insert(id, prototype); +} + +void QDeclarativeTouchArea::updateTouchPoint(QDeclarativeTouchPoint *dtp, const QTouchEvent::TouchPoint *p) { + dtp->setX(p->pos().x()); + dtp->setY(p->pos().y()); + dtp->setSceneX(p->scenePos().x()); + dtp->setSceneY(p->scenePos().y()); + _changedTouches.insert(dtp->id(),dtp); +} + +void QDeclarativeTouchArea::updatePinch(QList<QTouchEvent::TouchPoint> *touchPoints) { + if (touchPoints->count()==2) { + QTouchEvent::TouchPoint tp1 = touchPoints->at(0); + QTouchEvent::TouchPoint tp2 = touchPoints->at(1); + + QPointF tp1LastPos = tp1.lastPos(); + QPointF tp2LastPos = tp2.lastPos(); + QPointF tp1Pos = tp1.pos(); + QPointF tp2Pos = tp2.pos(); + + QPointF deltaA = tp1LastPos - tp2LastPos; + QPointF deltaB = tp1Pos - tp2Pos; + + qreal distanceA = sqrt(pow(deltaA.x(),2.0)+pow(deltaA.y(),2.0)); + qreal distanceB = sqrt(pow(deltaB.x(),2.0)+pow(deltaB.y(),2.0)); + _scaleFactor*=(distanceB/distanceA); + emit(scaleFactorChanged()); + + QLineF lineA(tp1LastPos, tp2LastPos); + QLineF lineB(tp1Pos,tp2Pos); + _rotationAngle-=lineA.angleTo(lineB); + emit(rotationAngleChanged()); + } + +} + diff --git a/TouchArea/qdeclarativetoucharea.h b/TouchArea/qdeclarativetoucharea.h new file mode 100644 index 0000000..58ed399 --- /dev/null +++ b/TouchArea/qdeclarativetoucharea.h @@ -0,0 +1,165 @@ +#ifndef QDECLARATIVETOUCHAREA_H +#define QDECLARATIVETOUCHAREA_H + +#include "qdeclarativeitem.h" +#include "qevent.h" + +#include <QMap> +#include <QList> + +class QDeclarativeTouchPoint : public QObject { + Q_OBJECT + Q_PROPERTY(int id READ id) + Q_PROPERTY(qreal x READ x NOTIFY xChanged) + Q_PROPERTY(qreal y READ y NOTIFY yChanged) + Q_PROPERTY(qreal sceneX READ sceneX NOTIFY sceneXChanged) + Q_PROPERTY(qreal sceneY READ sceneY NOTIFY sceneYChanged) + Q_PROPERTY(bool valid READ isValid NOTIFY validityChanged) +public: + QDeclarativeTouchPoint(bool qmlReference = true) + : _id(0), + _x(0.0), + _y(0.0), + _sceneX(0.0), + _sceneY(0.0), + _qmlReferenced(qmlReference), + _valid(!qmlReference) + {} + + int id() const { return _id; } + void setId(int id) { _id = id; } + + qreal x() const { return _x; } + void setX(qreal x) { + _x = x; + emit(xChanged()); + } + + qreal y() const { return _y; } + void setY(qreal y) { + _y = y; + emit(yChanged()); + } + + qreal sceneX() const { return _sceneX; } + void setSceneX(qreal sceneX) { + _sceneX = sceneX; + emit(sceneXChanged()); + } + + qreal sceneY() const { return _sceneY; } + void setSceneY(qreal sceneY) { + _sceneY = sceneY; + emit(sceneYChanged()); + } + + bool isQmlReferenced() { return _qmlReferenced; } + + bool isValid() { return _valid; } + void setValid(bool valid) { + _valid = valid; + emit(validityChanged()); + } + +Q_SIGNALS: + void xChanged(); + void yChanged(); + void sceneXChanged(); + void sceneYChanged(); + void validityChanged(); + +private: + int _id; + qreal _x; + qreal _y; + qreal _sceneX; + qreal _sceneY; + bool _qmlReferenced; + bool _valid; +}; + + + +class QDeclarativeTouchArea : public QDeclarativeItem +{ + Q_OBJECT + + Q_PROPERTY(QList<QObject*> touches READ touches) + Q_PROPERTY(QList<QObject*> changedTouches READ changedTouches) + Q_PROPERTY(QDeclarativeListProperty<QDeclarativeTouchPoint> touchPoints READ touchPoints NOTIFY touchPointsChanged) + Q_PROPERTY(int minimumTouches READ minimumTouches WRITE setMinimumTouches) + Q_PROPERTY(int maximumTouches READ maximumTouches WRITE setMaximumTouches) + Q_PROPERTY(qreal scaleFactor READ scaleFactor NOTIFY scaleFactorChanged) + Q_PROPERTY(qreal rotationAngle READ rotationAngle NOTIFY rotationAngleChanged) + +public: + QDeclarativeTouchArea(QDeclarativeItem *parent=0); + ~QDeclarativeTouchArea(); + + int minimumTouches() const { return _minimumTouches; } + void setMinimumTouches(int num) { _minimumTouches = num; } + int maximumTouches() const { return _maximumTouches; } + void setMaximumTouches(int num) { _maximumTouches = num; } + + qreal scaleFactor() const { return _scaleFactor; } + qreal rotationAngle() const { return _rotationAngle; } + + QList<QObject*> touches() { return _touches.values(); } + QList<QObject*> changedTouches() { return _changedTouches.values(); } + + QDeclarativeListProperty<QDeclarativeTouchPoint> touchPoints() { + return QDeclarativeListProperty<QDeclarativeTouchPoint>(this, 0, QDeclarativeTouchArea::touchPoint_append, QDeclarativeTouchArea::touchPoint_count, QDeclarativeTouchArea::touchPoint_at, 0); + } + + static void touchPoint_append(QDeclarativeListProperty<QDeclarativeTouchPoint> *list, QDeclarativeTouchPoint* touch) { + QDeclarativeTouchArea *q = static_cast<QDeclarativeTouchArea*>(list->object); + q->addTouchPrototype(touch); + } + + static int touchPoint_count(QDeclarativeListProperty<QDeclarativeTouchPoint> *list) { + QDeclarativeTouchArea *q = static_cast<QDeclarativeTouchArea*>(list->object); + return q->_touchPrototypes.count(); + } + + static QDeclarativeTouchPoint* touchPoint_at(QDeclarativeListProperty<QDeclarativeTouchPoint> *list, int index) { + QDeclarativeTouchArea *q = static_cast<QDeclarativeTouchArea*>(list->object); + return static_cast<QDeclarativeTouchPoint*>(q->_touchPrototypes[index]); + } + + +Q_SIGNALS: + void touchStart(); + void touchMove(); + void touchEnd(); + void touchPointsChanged(); + void scaleFactorChanged(); + void rotationAngleChanged(); + +protected: + bool sceneEvent(QEvent *); + void updateTouchPoint(QDeclarativeTouchPoint*, const QTouchEvent::TouchPoint*); + void updatePinch(QList<QTouchEvent::TouchPoint> *touchPoints); + void addTouchPrototype(QDeclarativeTouchPoint* prototype); + void addTouchPoint(const QTouchEvent::TouchPoint *p); + void clearChangedAndReleasedTouches(); + void updateTopTouchArea(); + void updateTouchData(QEvent*); + +private: + QMap<int,QObject*> _touchPrototypes; + QMap<int,QObject*> _touches; + QMap<int,QObject*> _changedTouches; + QList<QObject*> _releasedTouches; + int _minimumTouches; + int _maximumTouches; + qreal _scaleFactor; + qreal _rotationAngle; + QDeclarativeTouchArea* _topTouchArea; + bool _active; + static int _globalTouchActive; + +}; + +QML_DECLARE_TYPE(QDeclarativeTouchPoint) + +#endif // QDECLARATIVETOUCHAREA_H diff --git a/TouchArea/qmldir b/TouchArea/qmldir new file mode 100644 index 0000000..43db22b --- /dev/null +++ b/TouchArea/qmldir @@ -0,0 +1 @@ +plugin qmltouchareaplugin diff --git a/TouchArea/touchareaplugin.cpp b/TouchArea/touchareaplugin.cpp new file mode 100644 index 0000000..337442d --- /dev/null +++ b/TouchArea/touchareaplugin.cpp @@ -0,0 +1,12 @@ +#include "qdeclarativetoucharea.h" +#include "touchareaplugin.h" +#include <qdeclarative.h> + +void TouchAreaPlugin::registerTypes(const char *uri) +{ + qmlRegisterType<QDeclarativeTouchArea>(uri,1,0,"TouchArea"); + qmlRegisterType<QDeclarativeTouchPoint>(uri,1,0,"TouchPoint"); +} + +Q_EXPORT_PLUGIN2(qmltouchareaplugin, TouchAreaPlugin); + diff --git a/TouchArea/touchareaplugin.h b/TouchArea/touchareaplugin.h new file mode 100644 index 0000000..63a6a83 --- /dev/null +++ b/TouchArea/touchareaplugin.h @@ -0,0 +1,15 @@ +#ifndef TOUCHAREAPLUGIN_H +#define TOUCHAREAPLUGIN_H + +#include <QDeclarativeExtensionPlugin> + +class TouchAreaPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + void registerTypes(const char *uri); +}; + + + +#endif // TOUCHAREAPLUGIN_H |
