123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- /****************************************************************************
- **
- ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- ** All rights reserved.
- ** Contact: Nokia Corporation (qt-info@nokia.com)
- **
- ** This file is part of the QtDeclarative module of the Qt Toolkit.
- **
- ** $QT_BEGIN_LICENSE:LGPL$
- ** No Commercial Usage
- ** This file contains pre-release code and may not be distributed.
- ** You may use this file in accordance with the terms and conditions
- ** contained in the Technology Preview License Agreement accompanying
- ** this package.
- **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file. Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Nokia gives you certain additional
- ** rights. These rights are described in the Nokia Qt LGPL Exception
- ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
- **
- ** If you have questions regarding the use of this file, please contact
- ** Nokia at qt-info@nokia.com.
- **
- **
- **
- **
- **
- **
- **
- **
- ** $QT_END_LICENSE$
- **
- ****************************************************************************/
- #include "qdeclarativepincharea.h"
- #include <QApplication>
- #include <QGraphicsScene>
- #include <QGraphicsSceneMouseEvent>
- #include <float.h>
- #include <math.h>
- QT_BEGIN_NAMESPACE
- QDeclarativePinch::QDeclarativePinch()
- : m_target(0), m_minScale(1.0), m_maxScale(1.0)
- , m_minRotation(0.0), m_maxRotation(0.0)
- , m_axis(NoDrag), m_xmin(-FLT_MAX), m_xmax(FLT_MAX)
- , m_ymin(-FLT_MAX), m_ymax(FLT_MAX), m_active(false)
- {
- }
- QDeclarativePinchArea::QDeclarativePinchArea(QDeclarativeItem *parent)
- : QDeclarativeItem(parent), absorb(true), stealMouse(false), inPinch(false)
- , pinchRejected(false), pinch_(0)
- {
- setAcceptedMouseButtons(Qt::LeftButton);
- setAcceptTouchEvents(true);
- setFiltersChildEvents(true);
- }
- QDeclarativePinchArea::~QDeclarativePinchArea()
- {
- }
- bool QDeclarativePinchArea::isEnabled() const
- {
- return absorb;
- }
- void QDeclarativePinchArea::setEnabled(bool a)
- {
- if (a != absorb) {
- absorb = a;
- emit enabledChanged();
- }
- }
- bool QDeclarativePinchArea::event(QEvent *event)
- {
- if (!absorb || !isVisible())
- return QDeclarativeItem::event(event);
- switch (event->type()) {
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate: {
- QTouchEvent *touch = static_cast<QTouchEvent*>(event);
- touchPoints.clear();
- for (int i = 0; i < touch->touchPoints().count(); ++i) {
- if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased)) {
- touchPoints << touch->touchPoints().at(i);
- }
- }
- updatePinch();
- }
- return true;
- case QEvent::TouchEnd:
- touchPoints.clear();
- updatePinch();
- break;
- default:
- return QDeclarativeItem::event(event);
- }
- return QDeclarativeItem::event(event);
- }
- void QDeclarativePinchArea::updatePinch()
- {
- if (touchPoints.count() != 2) {
- if (inPinch) {
- stealMouse = false;
- setKeepMouseGrab(false);
- inPinch = false;
- const qreal rotationAngle = pinchStartAngle - pinchLastAngle;
- QPointF pinchCenter = mapFromScene(sceneLastCenter);
- QDeclarativePinchEvent pe(pinchCenter, pinchLastScale, pinchLastAngle, rotationAngle);
- pe.setStartCenter(pinchStartCenter);
- pe.setLastCenter(pinchCenter);
- pe.setLastAngle(pinchLastAngle);
- pe.setLastScale(pinchLastScale);
- pe.setStartPoint1(mapFromScene(sceneStartPoint1));
- pe.setStartPoint2(mapFromScene(sceneStartPoint2));
- pe.setPoint1(lastPoint1);
- pe.setPoint2(lastPoint2);
- emit pinchFinished(&pe);
- if (pinch_ && pinch_->target())
- pinch_->setActive(false);
- }
- return;
- }
- if (touchPoints.at(0).state() & Qt::TouchPointPressed
- || touchPoints.at(1).state() & Qt::TouchPointPressed) {
- sceneStartPoint1 = touchPoints.at(0).scenePos();
- sceneStartPoint2 = touchPoints.at(1).scenePos();
- inPinch = false;
- pinchRejected = false;
- } else if (!pinchRejected){
- QDeclarativeItem *grabber = scene() ? qobject_cast<QDeclarativeItem*>(scene()->mouseGrabberItem()) : 0;
- if (grabber == this || !grabber || !grabber->keepMouseGrab()) {
- const int dragThreshold = QApplication::startDragDistance();
- QPointF p1 = touchPoints.at(0).scenePos();
- QPointF p2 = touchPoints.at(1).scenePos();
- qreal dx = p1.x() - p2.x();
- qreal dy = p1.y() - p2.y();
- qreal dist = sqrt(dx*dx + dy*dy);
- QPointF sceneCenter = (p1 + p2)/2;
- qreal angle = QLineF(p1, p2).angle();
- if (angle > 180)
- angle -= 360;
- if (!inPinch) {
- if (qAbs(p1.x()-sceneStartPoint1.x()) > dragThreshold
- || qAbs(p1.y()-sceneStartPoint1.y()) > dragThreshold
- || qAbs(p2.x()-sceneStartPoint2.x()) > dragThreshold
- || qAbs(p2.y()-sceneStartPoint2.y()) > dragThreshold) {
- sceneStartCenter = sceneCenter;
- sceneLastCenter = sceneCenter;
- pinchStartCenter = mapFromScene(sceneCenter);
- pinchStartDist = dist;
- pinchStartAngle = angle;
- pinchLastScale = 1.0;
- pinchLastAngle = angle;
- lastPoint1 = touchPoints.at(0).pos();
- lastPoint2 = touchPoints.at(1).pos();
- QDeclarativePinchEvent pe(pinchStartCenter, 1.0, angle, 0.0);
- pe.setStartCenter(pinchStartCenter);
- pe.setLastCenter(pinchStartCenter);
- pe.setLastAngle(pinchLastAngle);
- pe.setLastScale(pinchLastScale);
- pe.setStartPoint1(mapFromScene(sceneStartPoint1));
- pe.setStartPoint2(mapFromScene(sceneStartPoint2));
- pe.setPoint1(lastPoint1);
- pe.setPoint2(lastPoint2);
- emit pinchStarted(&pe);
- if (pe.accepted()) {
- inPinch = true;
- stealMouse = true;
- grabMouse();
- setKeepMouseGrab(true);
- if (pinch_ && pinch_->target()) {
- pinchStartPos = pinch()->target()->pos();
- pinchStartScale = pinch()->target()->scale();
- pinchStartRotation = pinch()->target()->rotation();
- pinch_->setActive(true);
- }
- } else {
- pinchRejected = true;
- }
- }
- } else if (pinchStartDist > 0) {
- qreal scale = dist / pinchStartDist;
- qreal rotationAngle = pinchStartAngle - angle;
- if (rotationAngle > 180)
- rotationAngle -= 360;
- QPointF pinchCenter = mapFromScene(sceneCenter);
- QDeclarativePinchEvent pe(pinchCenter, scale, angle, rotationAngle);
- pe.setStartCenter(pinchStartCenter);
- pe.setLastCenter(mapFromScene(sceneLastCenter));
- pe.setLastAngle(pinchLastAngle);
- pe.setLastScale(pinchLastScale);
- pe.setStartPoint1(mapFromScene(sceneStartPoint1));
- pe.setStartPoint2(mapFromScene(sceneStartPoint2));
- pe.setPoint1(touchPoints.at(0).pos());
- pe.setPoint2(touchPoints.at(1).pos());
- pinchLastScale = scale;
- sceneLastCenter = sceneCenter;
- pinchLastAngle = angle;
- lastPoint1 = touchPoints.at(0).pos();
- lastPoint2 = touchPoints.at(1).pos();
- emit pinchChanged(&pe);
- if (pinch_ && pinch_->target()) {
- qreal s = pinchStartScale * scale;
- s = qMin(qMax(pinch()->minimumScale(),s), pinch()->maximumScale());
- pinch()->target()->setScale(s);
- QPointF pos = sceneCenter - sceneStartCenter + pinchStartPos;
- if (pinch()->axis() & QDeclarativePinch::XAxis) {
- qreal x = pos.x();
- if (x < pinch()->xmin())
- x = pinch()->xmin();
- else if (x > pinch()->xmax())
- x = pinch()->xmax();
- pinch()->target()->setX(x);
- }
- if (pinch()->axis() & QDeclarativePinch::YAxis) {
- qreal y = pos.y();
- if (y < pinch()->ymin())
- y = pinch()->ymin();
- else if (y > pinch()->ymax())
- y = pinch()->ymax();
- pinch()->target()->setY(y);
- }
- if (pinchStartRotation >= pinch()->minimumRotation()
- && pinchStartRotation <= pinch()->maximumRotation()) {
- qreal r = rotationAngle + pinchStartRotation;
- r = qMin(qMax(pinch()->minimumRotation(),r), pinch()->maximumRotation());
- pinch()->target()->setRotation(r);
- }
- }
- }
- }
- }
- }
- void QDeclarativePinchArea::mousePressEvent(QGraphicsSceneMouseEvent *event)
- {
- stealMouse = false;
- if (!absorb)
- QDeclarativeItem::mousePressEvent(event);
- else {
- setKeepMouseGrab(false);
- event->setAccepted(true);
- }
- }
- void QDeclarativePinchArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
- {
- if (!absorb) {
- QDeclarativeItem::mouseMoveEvent(event);
- return;
- }
- }
- void QDeclarativePinchArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
- {
- stealMouse = false;
- if (!absorb) {
- QDeclarativeItem::mouseReleaseEvent(event);
- } else {
- QGraphicsScene *s = scene();
- if (s && s->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepMouseGrab(false);
- }
- }
- bool QDeclarativePinchArea::sceneEvent(QEvent *event)
- {
- bool rv = QDeclarativeItem::sceneEvent(event);
- if (event->type() == QEvent::UngrabMouse) {
- setKeepMouseGrab(false);
- }
- return rv;
- }
- bool QDeclarativePinchArea::sendMouseEvent(QGraphicsSceneMouseEvent *event)
- {
- QGraphicsSceneMouseEvent mouseEvent(event->type());
- QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
- QGraphicsScene *s = scene();
- QDeclarativeItem *grabber = s ? qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem()) : 0;
- bool stealThisEvent = stealMouse;
- if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
- mouseEvent.setAccepted(false);
- for (int i = 0x1; i <= 0x10; i <<= 1) {
- if (event->buttons() & i) {
- Qt::MouseButton button = Qt::MouseButton(i);
- mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
- }
- }
- mouseEvent.setScenePos(event->scenePos());
- mouseEvent.setLastScenePos(event->lastScenePos());
- mouseEvent.setPos(mapFromScene(event->scenePos()));
- mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
- switch(mouseEvent.type()) {
- case QEvent::GraphicsSceneMouseMove:
- mouseMoveEvent(&mouseEvent);
- break;
- case QEvent::GraphicsSceneMousePress:
- qDebug() << "mouse press";
- mousePressEvent(&mouseEvent);
- break;
- case QEvent::GraphicsSceneMouseRelease:
- mouseReleaseEvent(&mouseEvent);
- break;
- default:
- break;
- }
- grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem());
- if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
- grabMouse();
- return stealThisEvent;
- }
- if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
- stealMouse = false;
- if (s && s->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepMouseGrab(false);
- }
- return false;
- }
- bool QDeclarativePinchArea::sceneEventFilter(QGraphicsItem *i, QEvent *e)
- {
- if (!absorb || !isVisible())
- return QDeclarativeItem::sceneEventFilter(i, e);
- switch (e->type()) {
- case QEvent::GraphicsSceneMousePress:
- case QEvent::GraphicsSceneMouseMove:
- case QEvent::GraphicsSceneMouseRelease:
- return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
- break;
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate: {
- QTouchEvent *touch = static_cast<QTouchEvent*>(e);
- touchPoints.clear();
- for (int i = 0; i < touch->touchPoints().count(); ++i)
- if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased))
- touchPoints << touch->touchPoints().at(i);
- updatePinch();
- }
- return inPinch;
- case QEvent::TouchEnd:
- touchPoints.clear();
- updatePinch();
- break;
- default:
- break;
- }
- return QDeclarativeItem::sceneEventFilter(i, e);
- }
- void QDeclarativePinchArea::geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry)
- {
- QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
- }
- QVariant QDeclarativePinchArea::itemChange(GraphicsItemChange change,
- const QVariant &value)
- {
- return QDeclarativeItem::itemChange(change, value);
- }
- QDeclarativePinch *QDeclarativePinchArea::pinch()
- {
- if (!pinch_)
- pinch_ = new QDeclarativePinch;
- return pinch_;
- }
- QT_END_NAMESPACE
|