diff options
Diffstat (limited to 'src/declarative/graphicsitems/qmlgraphicsflickable.cpp')
-rw-r--r-- | src/declarative/graphicsitems/qmlgraphicsflickable.cpp | 1324 |
1 files changed, 0 insertions, 1324 deletions
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp deleted file mode 100644 index e92fea4..0000000 --- a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp +++ /dev/null @@ -1,1324 +0,0 @@ -/**************************************************************************** -** -** 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 "qmlgraphicsflickable_p.h" -#include "qmlgraphicsflickable_p_p.h" - -#include <QGraphicsSceneMouseEvent> -#include <QPointer> -#include <QTimer> - -QT_BEGIN_NAMESPACE - - -// FlickThreshold determines how far the "mouse" must have moved -// before we perform a flick. -static const int FlickThreshold = 20; - -// Really slow flicks can be annoying. -static const int minimumFlickVelocity = 200; - -QmlGraphicsFlickableVisibleArea::QmlGraphicsFlickableVisibleArea(QmlGraphicsFlickable *parent) - : QObject(parent), flickable(parent), m_xPosition(0.), m_widthRatio(0.) - , m_yPosition(0.), m_heightRatio(0.) -{ -} - -qreal QmlGraphicsFlickableVisibleArea::widthRatio() const -{ - return m_widthRatio; -} - -qreal QmlGraphicsFlickableVisibleArea::xPosition() const -{ - return m_xPosition; -} - -qreal QmlGraphicsFlickableVisibleArea::heightRatio() const -{ - return m_heightRatio; -} - -qreal QmlGraphicsFlickableVisibleArea::yPosition() const -{ - return m_yPosition; -} - -void QmlGraphicsFlickableVisibleArea::updateVisible() -{ - QmlGraphicsFlickablePrivate *p = static_cast<QmlGraphicsFlickablePrivate *>(QGraphicsItemPrivate::get(flickable)); - bool pageChange = false; - - // Vertical - const qreal viewheight = flickable->height(); - const qreal maxyextent = -flickable->maxYExtent() + flickable->minYExtent(); - qreal pagePos = (-p->_moveY.value() + flickable->minYExtent()) / (maxyextent + viewheight); - qreal pageSize = viewheight / (maxyextent + viewheight); - - if (pageSize != m_heightRatio) { - m_heightRatio = pageSize; - pageChange = true; - } - if (pagePos != m_yPosition) { - m_yPosition = pagePos; - pageChange = true; - } - - // Horizontal - const qreal viewwidth = flickable->width(); - const qreal maxxextent = -flickable->maxXExtent() + flickable->minXExtent(); - pagePos = (-p->_moveX.value() + flickable->minXExtent()) / (maxxextent + viewwidth); - pageSize = viewwidth / (maxxextent + viewwidth); - - if (pageSize != m_widthRatio) { - m_widthRatio = pageSize; - pageChange = true; - } - if (pagePos != m_xPosition) { - m_xPosition = pagePos; - pageChange = true; - } - if (pageChange) - emit pageChanged(); -} - - -QmlGraphicsFlickablePrivate::QmlGraphicsFlickablePrivate() - : viewport(new QmlGraphicsItem) - , _moveX(this, &QmlGraphicsFlickablePrivate::setRoundedViewportX) - , _moveY(this, &QmlGraphicsFlickablePrivate::setRoundedViewportY) - , vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false) - , pressed(false), atXEnd(false), atXBeginning(true), atYEnd(false), atYBeginning(true) - , interactive(true), deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100) - , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(200) - , horizontalVelocity(this), verticalVelocity(this), vTime(0), visibleArea(0) - , flickDirection(QmlGraphicsFlickable::AutoFlickDirection) -{ -} - -void QmlGraphicsFlickablePrivate::init() -{ - Q_Q(QmlGraphicsFlickable); - viewport->setParent(q); - QObject::connect(&timeline, SIGNAL(updated()), q, SLOT(ticked())); - QObject::connect(&timeline, SIGNAL(completed()), q, SLOT(movementEnding())); - q->setAcceptedMouseButtons(Qt::LeftButton); - q->setFiltersChildEvents(true); - QObject::connect(viewport, SIGNAL(xChanged()), q, SIGNAL(positionXChanged())); - QObject::connect(viewport, SIGNAL(yChanged()), q, SIGNAL(positionYChanged())); - QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(heightChange())); - QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(widthChange())); -} - -void QmlGraphicsFlickablePrivate::flickX(qreal velocity) -{ - Q_Q(QmlGraphicsFlickable); - qreal maxDistance = -1; - // -ve velocity means list is moving up - if (velocity > 0) { - const qreal minX = q->minXExtent(); - if (_moveX.value() < minX) - maxDistance = qAbs(minX -_moveX.value() + (overShoot?30:0)); - flickTargetX = minX; - } else { - const qreal maxX = q->maxXExtent(); - if (_moveX.value() > maxX) - maxDistance = qAbs(maxX - _moveX.value()) + (overShoot?30:0); - flickTargetX = maxX; - } - if (maxDistance > 0) { - qreal v = velocity; - if (maxVelocity != -1 && maxVelocity < qAbs(v)) { - if (v < 0) - v = -maxVelocity; - else - v = maxVelocity; - } - timeline.reset(_moveX); - timeline.accel(_moveX, v, deceleration, maxDistance); - timeline.callback(QmlTimeLineCallback(&_moveX, fixupX_callback, this)); - if (!flicked) { - flicked = true; - emit q->flickingChanged(); - emit q->flickStarted(); - } - } else { - timeline.reset(_moveX); - fixupX(); - } -} - -void QmlGraphicsFlickablePrivate::flickY(qreal velocity) -{ - Q_Q(QmlGraphicsFlickable); - qreal maxDistance = -1; - // -ve velocity means list is moving up - if (velocity > 0) { - const qreal minY = q->minYExtent(); - if (_moveY.value() < minY) - maxDistance = qAbs(minY -_moveY.value() + (overShoot?30:0)); - flickTargetY = minY; - } else { - const qreal maxY = q->maxYExtent(); - if (_moveY.value() > maxY) - maxDistance = qAbs(maxY - _moveY.value()) + (overShoot?30:0); - flickTargetY = maxY; - } - if (maxDistance > 0) { - qreal v = velocity; - if (maxVelocity != -1 && maxVelocity < qAbs(v)) { - if (v < 0) - v = -maxVelocity; - else - v = maxVelocity; - } - timeline.reset(_moveY); - timeline.accel(_moveY, v, deceleration, maxDistance); - timeline.callback(QmlTimeLineCallback(&_moveY, fixupY_callback, this)); - if (!flicked) { - flicked = true; - emit q->flickingChanged(); - emit q->flickStarted(); - } - } else { - timeline.reset(_moveY); - fixupY(); - } -} - -void QmlGraphicsFlickablePrivate::fixupX() -{ - Q_Q(QmlGraphicsFlickable); - if (!q->xflick() || _moveX.timeLine()) - return; - - if (_moveX.value() > q->minXExtent() || (q->maxXExtent() > q->minXExtent())) { - timeline.reset(_moveX); - if (_moveX.value() != q->minXExtent()) { - if (fixupDuration) - timeline.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); - else - _moveY.setValue(q->minYExtent()); - } - //emit flickingChanged(); - } else if (_moveX.value() < q->maxXExtent()) { - timeline.reset(_moveX); - if (fixupDuration) - timeline.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); - else - _moveY.setValue(q->maxYExtent()); - //emit flickingChanged(); - } else { - flicked = false; - } - - vTime = timeline.time(); -} - -void QmlGraphicsFlickablePrivate::fixupY_callback(void *data) -{ - ((QmlGraphicsFlickablePrivate *)data)->fixupY(); -} - -void QmlGraphicsFlickablePrivate::fixupX_callback(void *data) -{ - ((QmlGraphicsFlickablePrivate *)data)->fixupX(); -} - -void QmlGraphicsFlickablePrivate::fixupY() -{ - Q_Q(QmlGraphicsFlickable); - if (!q->yflick() || _moveY.timeLine()) - return; - - if (_moveY.value() > q->minYExtent() || (q->maxYExtent() > q->minYExtent())) { - timeline.reset(_moveY); - if (_moveY.value() != q->minYExtent()) { - if (fixupDuration) - timeline.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); - else - _moveY.setValue(q->minYExtent()); - } - //emit flickingChanged(); - } else if (_moveY.value() < q->maxYExtent()) { - timeline.reset(_moveY); - if (fixupDuration) - timeline.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::InOutQuad), fixupDuration); - else - _moveY.setValue(q->maxYExtent()); - //emit flickingChanged(); - } else { - flicked = false; - } - - vTime = timeline.time(); -} - -void QmlGraphicsFlickablePrivate::updateBeginningEnd() -{ - Q_Q(QmlGraphicsFlickable); - bool atBoundaryChange = false; - - // Vertical - const int maxyextent = int(-q->maxYExtent()); - const qreal ypos = -_moveY.value(); - bool atBeginning = (ypos <= -q->minYExtent()); - bool atEnd = (maxyextent <= ypos); - - if (atBeginning != atYBeginning) { - atYBeginning = atBeginning; - atBoundaryChange = true; - } - if (atEnd != atYEnd) { - atYEnd = atEnd; - atBoundaryChange = true; - } - - // Horizontal - const int maxxextent = int(-q->maxXExtent()); - const qreal xpos = -_moveX.value(); - atBeginning = (xpos <= -q->minXExtent()); - atEnd = (maxxextent <= xpos); - - if (atBeginning != atXBeginning) { - atXBeginning = atBeginning; - atBoundaryChange = true; - } - if (atEnd != atXEnd) { - atXEnd = atEnd; - atBoundaryChange = true; - } - - if (atBoundaryChange) - emit q->isAtBoundaryChanged(); - - if (visibleArea) - visibleArea->updateVisible(); -} - -/*! - \qmlclass Flickable QmlGraphicsFlickable - \brief The Flickable item provides a surface that can be "flicked". - \inherits Item - - Flickable places its children on a surface that can be dragged and flicked. - - \code - Flickable { - width: 200; height: 200; viewportWidth: image.width; viewportHeight: image.height - Image { id: image; source: "bigimage.png" } - } - \endcode - - \image flickable.gif - - \note Flickable does not automatically clip its contents. If - it is not full-screen it is likely that \c clip should be set - to true. - - \note Due to an implementation detail items placed inside a flickable cannot anchor to it by - id, use 'parent' instead. -*/ - -/*! - \qmlsignal Flickable::onMovementStarted() - - This handler is called when the view begins moving due to user - interaction. -*/ - -/*! - \qmlsignal Flickable::onMovementEnded() - - This handler is called when the view stops moving due to user - interaction. If a flick was generated, this handler will - be triggered once the flick stops. If a flick was not - generated, the handler will be triggered when the - user stops dragging - i.e. a mouse or touch release. -*/ - -/*! - \qmlsignal Flickable::onFlickStarted() - - This handler is called when the view is flicked. A flick - starts from the point that the mouse or touch is released, - while still in motion. -*/ - -/*! - \qmlsignal Flickable::onFlickEnded() - - This handler is called when the view stops moving due to a flick. -*/ - -/*! - \qmlproperty real Flickable::visibleArea.xPosition - \qmlproperty real Flickable::visibleArea.widthRatio - \qmlproperty real Flickable::visibleArea.yPosition - \qmlproperty real Flickable::visibleArea.heightRatio - - These properties describe the position and size of the currently viewed area. - The size is defined as the percentage of the full view currently visible, - scaled to 0.0 - 1.0. The page position is in the range 0.0 (beginning) to - size ratio (end), i.e. yPosition is in the range 0.0 - heightRatio. - - These properties are typically used to draw a scrollbar, for example: - \code - Rectangle { - opacity: 0.5; anchors.right: MyListView.right-2; width: 6 - y: MyListView.visibleArea.yPosition * MyListView.height - height: MyListView.visibleArea.heightRatio * MyListView.height - } - \endcode -*/ - -QmlGraphicsFlickable::QmlGraphicsFlickable(QmlGraphicsItem *parent) - : QmlGraphicsItem(*(new QmlGraphicsFlickablePrivate), parent) -{ - Q_D(QmlGraphicsFlickable); - d->init(); -} - -QmlGraphicsFlickable::QmlGraphicsFlickable(QmlGraphicsFlickablePrivate &dd, QmlGraphicsItem *parent) - : QmlGraphicsItem(dd, parent) -{ - Q_D(QmlGraphicsFlickable); - d->init(); -} - -QmlGraphicsFlickable::~QmlGraphicsFlickable() -{ -} - -/*! - \qmlproperty int Flickable::viewportX - \qmlproperty int Flickable::viewportY - - These properties hold the surface coordinate currently at the top-left - corner of the Flickable. For example, if you flick an image up 100 pixels, - \c yPosition will be 100. -*/ -qreal QmlGraphicsFlickable::viewportX() const -{ - Q_D(const QmlGraphicsFlickable); - return -d->_moveX.value(); -} - -void QmlGraphicsFlickable::setViewportX(qreal pos) -{ - Q_D(QmlGraphicsFlickable); - pos = qRound(pos); - d->timeline.reset(d->_moveX); - d->vTime = d->timeline.time(); - if (-pos != d->_moveX.value()) { - d->_moveX.setValue(-pos); - viewportMoved(); - } -} - -qreal QmlGraphicsFlickable::viewportY() const -{ - Q_D(const QmlGraphicsFlickable); - return -d->_moveY.value(); -} - -void QmlGraphicsFlickable::setViewportY(qreal pos) -{ - Q_D(QmlGraphicsFlickable); - pos = qRound(pos); - d->timeline.reset(d->_moveY); - d->vTime = d->timeline.time(); - if (-pos != d->_moveY.value()) { - d->_moveY.setValue(-pos); - viewportMoved(); - } -} - -/*! - \qmlproperty bool Flickable::interactive - - A user cannot drag or flick a Flickable that is not interactive. - - This property is useful for temporarily disabling flicking. This allows - special interaction with Flickable's children: for example, you might want to - freeze a flickable map while viewing detailed information on a location popup that is a child of the Flickable. -*/ -bool QmlGraphicsFlickable::isInteractive() const -{ - Q_D(const QmlGraphicsFlickable); - return d->interactive; -} - -void QmlGraphicsFlickable::setInteractive(bool interactive) -{ - Q_D(QmlGraphicsFlickable); - if (interactive != d->interactive) { - d->interactive = interactive; - if (!interactive && d->flicked) { - d->timeline.clear(); - d->vTime = d->timeline.time(); - d->flicked = false; - emit flickingChanged(); - emit flickEnded(); - } - emit interactiveChanged(); - } -} - -/*! - \qmlproperty real Flickable::horizontalVelocity - \qmlproperty real Flickable::verticalVelocity - \qmlproperty real Flickable::reportedVelocitySmoothing - - The instantaneous velocity of movement along the x and y axes, in pixels/sec. - - The reported velocity is smoothed to avoid erratic output. - reportedVelocitySmoothing determines how much smoothing is applied. -*/ -qreal QmlGraphicsFlickable::horizontalVelocity() const -{ - Q_D(const QmlGraphicsFlickable); - return d->horizontalVelocity.value(); -} - -qreal QmlGraphicsFlickable::verticalVelocity() const -{ - Q_D(const QmlGraphicsFlickable); - return d->verticalVelocity.value(); -} - -/*! - \qmlproperty bool Flickable::atXBeginning - \qmlproperty bool Flickable::atXEnd - \qmlproperty bool Flickable::atYBeginning - \qmlproperty bool Flickable::atYEnd - - These properties are true if the flickable view is positioned at the beginning, - or end respecively. -*/ -bool QmlGraphicsFlickable::isAtXEnd() const -{ - Q_D(const QmlGraphicsFlickable); - return d->atXEnd; -} - -bool QmlGraphicsFlickable::isAtXBeginning() const -{ - Q_D(const QmlGraphicsFlickable); - return d->atXBeginning; -} - -bool QmlGraphicsFlickable::isAtYEnd() const -{ - Q_D(const QmlGraphicsFlickable); - return d->atYEnd; -} - -bool QmlGraphicsFlickable::isAtYBeginning() const -{ - Q_D(const QmlGraphicsFlickable); - return d->atYBeginning; -} - -void QmlGraphicsFlickable::ticked() -{ - viewportMoved(); -} - -QmlGraphicsItem *QmlGraphicsFlickable::viewport() -{ - Q_D(QmlGraphicsFlickable); - return d->viewport; -} - -QmlGraphicsFlickableVisibleArea *QmlGraphicsFlickable::visibleArea() -{ - Q_D(QmlGraphicsFlickable); - if (!d->visibleArea) - d->visibleArea = new QmlGraphicsFlickableVisibleArea(this); - return d->visibleArea; -} - -/*! - \qmlproperty enumeration Flickable::flickDirection - - This property determines which directions the view can be flicked. - - \list - \o AutoFlickDirection (default) - allows flicking vertically if the - \e viewportHeight is not equal to the \e height of the Flickable. - Allows flicking horizontally if the \e viewportWidth is not equal - to the \e width of the Flickable. - \o HorizontalFlick - allows flicking horizontally. - \o VerticalFlick - allows flicking vertically. - \o HorizontalAndVerticalFlick - allows flicking in both directions. - \endlist -*/ -QmlGraphicsFlickable::FlickDirection QmlGraphicsFlickable::flickDirection() const -{ - Q_D(const QmlGraphicsFlickable); - return d->flickDirection; -} - -void QmlGraphicsFlickable::setFlickDirection(FlickDirection direction) -{ - Q_D(QmlGraphicsFlickable); - if (direction != d->flickDirection) { - d->flickDirection = direction; - emit flickDirectionChanged(); - } -} - -void QmlGraphicsFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if (interactive && timeline.isActive() && (qAbs(velocityX) > 10 || qAbs(velocityY) > 10)) - stealMouse = true; // If we've been flicked then steal the click. - else - stealMouse = false; - pressed = true; - timeline.clear(); - velocityX = 0; - velocityY = 0; - lastPos = QPoint(); - QmlGraphicsItemPrivate::start(lastPosTime); - pressPos = event->pos(); - pressX = _moveX.value(); - pressY = _moveY.value(); - flicked = false; - QmlGraphicsItemPrivate::start(pressTime); - QmlGraphicsItemPrivate::start(velocityTime); -} - -void QmlGraphicsFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - Q_Q(QmlGraphicsFlickable); - if (!interactive || lastPosTime.isNull()) - return; - bool rejectY = false; - bool rejectX = false; - bool moved = false; - - if (q->yflick()) { - int dy = int(event->pos().y() - pressPos.y()); - if (qAbs(dy) > QApplication::startDragDistance() || QmlGraphicsItemPrivate::elapsed(pressTime) > 200) { - qreal newY = dy + pressY; - const qreal minY = q->minYExtent(); - const qreal maxY = q->maxYExtent(); - if (newY > minY) - newY = minY + (newY - minY) / 2; - if (newY < maxY && maxY - minY <= 0) - newY = maxY + (newY - maxY) / 2; - if (!q->overShoot() && (newY > minY || newY < maxY)) { - if (newY > minY) - newY = minY; - else if (newY < maxY) - newY = maxY; - else - rejectY = true; - } - if (!rejectY) { - _moveY.setValue(newY); - moved = true; - } - if (qAbs(dy) > QApplication::startDragDistance()) - stealMouse = true; - } - } - - if (q->xflick()) { - int dx = int(event->pos().x() - pressPos.x()); - if (qAbs(dx) > QApplication::startDragDistance() || QmlGraphicsItemPrivate::elapsed(pressTime) > 200) { - qreal newX = dx + pressX; - const qreal minX = q->minXExtent(); - const qreal maxX = q->maxXExtent(); - if (newX > minX) - newX = minX + (newX - minX) / 2; - if (newX < maxX && maxX - minX <= 0) - newX = maxX + (newX - maxX) / 2; - if (!q->overShoot() && (newX > minX || newX < maxX)) { - if (newX > minX) - newX = minX; - else if (newX < maxX) - newX = maxX; - else - rejectX = true; - } - if (!rejectX) { - _moveX.setValue(newX); - moved = true; - } - - if (qAbs(dx) > QApplication::startDragDistance()) - stealMouse = true; - } - } - - if (!lastPos.isNull()) { - qreal elapsed = qreal(QmlGraphicsItemPrivate::restart(lastPosTime)) / 1000.; - if (elapsed <= 0) - elapsed = 1; - if (q->yflick()) { - qreal diff = event->pos().y() - lastPos.y(); - // average to reduce the effect of spurious moves - velocityY += diff / elapsed; - velocityY /= 2; - } - - if (q->xflick()) { - qreal diff = event->pos().x() - lastPos.x(); - // average to reduce the effect of spurious moves - velocityX += diff / elapsed; - velocityX /= 2; - } - } - - if (rejectY) velocityY = 0; - if (rejectX) velocityX = 0; - - if (moved) { - q->movementStarting(); - q->viewportMoved(); - } - - lastPos = event->pos(); -} - -void QmlGraphicsFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - Q_Q(QmlGraphicsFlickable); - pressed = false; - if (lastPosTime.isNull()) - return; - - if (QmlGraphicsItemPrivate::elapsed(lastPosTime) > 100) { - // if we drag then pause before release we should not cause a flick. - velocityX = 0.0; - velocityY = 0.0; - } - - vTime = timeline.time(); - if (qAbs(velocityY) > 10 && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) { - qreal velocity = velocityY; - if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks. - velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity; - flickY(velocity); - } else { - fixupY(); - } - - if (qAbs(velocityX) > 10 && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) { - qreal velocity = velocityX; - if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks. - velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity; - flickX(velocity); - } else { - fixupX(); - } - - stealMouse = false; - lastPosTime = QTime(); - - if (!timeline.isActive()) - q->movementEnding(); -} - -void QmlGraphicsFlickable::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - Q_D(QmlGraphicsFlickable); - if (d->interactive) { - d->handleMousePressEvent(event); - event->accept(); - } else { - QmlGraphicsItem::mousePressEvent(event); - } -} - -void QmlGraphicsFlickable::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - Q_D(QmlGraphicsFlickable); - if (d->interactive) { - d->handleMouseMoveEvent(event); - event->accept(); - } else { - QmlGraphicsItem::mouseMoveEvent(event); - } -} - -void QmlGraphicsFlickable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - Q_D(QmlGraphicsFlickable); - if (d->interactive) { - d->clearDelayedPress(); - d->handleMouseReleaseEvent(event); - event->accept(); - ungrabMouse(); - } else { - QmlGraphicsItem::mouseReleaseEvent(event); - } -} - -void QmlGraphicsFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) -{ - Q_D(QmlGraphicsFlickable); - if (!d->interactive) { - QmlGraphicsItem::wheelEvent(event); - } else if (yflick()) { - if (event->delta() > 0) - d->velocityY = qMax(event->delta() - d->verticalVelocity.value(), qreal(250.0)); - else - d->velocityY = qMin(event->delta() - d->verticalVelocity.value(), qreal(-250.0)); - d->flicked = false; - d->flickY(d->velocityY); - event->accept(); - } else if (xflick()) { - if (event->delta() > 0) - d->velocityX = qMax(event->delta() - d->horizontalVelocity.value(), qreal(250.0)); - else - d->velocityX = qMin(event->delta() - d->horizontalVelocity.value(), qreal(-250.0)); - d->flicked = false; - d->flickX(d->velocityX); - event->accept(); - } else { - QmlGraphicsItem::wheelEvent(event); - } -} - -void QmlGraphicsFlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event) -{ - Q_Q(QmlGraphicsFlickable); - if (!q->scene() || pressDelay <= 0) - return; - delayedPressTarget = q->scene()->mouseGrabberItem(); - delayedPressEvent = new QGraphicsSceneMouseEvent(event->type()); - delayedPressEvent->setAccepted(false); - for (int i = 0x1; i <= 0x10; i <<= 1) { - if (event->buttons() & i) { - Qt::MouseButton button = Qt::MouseButton(i); - delayedPressEvent->setButtonDownPos(button, event->buttonDownPos(button)); - delayedPressEvent->setButtonDownScenePos(button, event->buttonDownScenePos(button)); - delayedPressEvent->setButtonDownScreenPos(button, event->buttonDownScreenPos(button)); - } - } - delayedPressEvent->setButtons(event->buttons()); - delayedPressEvent->setButton(event->button()); - delayedPressEvent->setPos(event->pos()); - delayedPressEvent->setScenePos(event->scenePos()); - delayedPressEvent->setScreenPos(event->screenPos()); - delayedPressEvent->setLastPos(event->lastPos()); - delayedPressEvent->setLastScenePos(event->lastScenePos()); - delayedPressEvent->setLastScreenPos(event->lastScreenPos()); - delayedPressEvent->setModifiers(event->modifiers()); - delayedPressTimer.start(pressDelay, q); -} - -void QmlGraphicsFlickablePrivate::clearDelayedPress() -{ - if (delayedPressEvent) { - delayedPressTimer.stop(); - delete delayedPressEvent; - delayedPressEvent = 0; - } -} - -void QmlGraphicsFlickablePrivate::setRoundedViewportX(qreal x) -{ - viewport->setX(qRound(x)); -} - -void QmlGraphicsFlickablePrivate::setRoundedViewportY(qreal y) -{ - viewport->setY(qRound(y)); -} - -void QmlGraphicsFlickable::timerEvent(QTimerEvent *event) -{ - Q_D(QmlGraphicsFlickable); - if (event->timerId() == d->delayedPressTimer.timerId()) { - d->delayedPressTimer.stop(); - if (d->delayedPressEvent) { - QmlGraphicsItem *grabber = scene() ? qobject_cast<QmlGraphicsItem*>(scene()->mouseGrabberItem()) : 0; - if (!grabber || grabber != this) - scene()->sendEvent(d->delayedPressTarget, d->delayedPressEvent); - delete d->delayedPressEvent; - d->delayedPressEvent = 0; - } - } -} - -qreal QmlGraphicsFlickable::minYExtent() const -{ - return 0.0; -} - -qreal QmlGraphicsFlickable::minXExtent() const -{ - return 0.0; -} - -/* returns -ve */ -qreal QmlGraphicsFlickable::maxXExtent() const -{ - return width() - vWidth(); -} -/* returns -ve */ -qreal QmlGraphicsFlickable::maxYExtent() const -{ - return height() - vHeight(); -} - -void QmlGraphicsFlickable::viewportMoved() -{ - Q_D(QmlGraphicsFlickable); - - int elapsed = QmlGraphicsItemPrivate::restart(d->velocityTime); - if (!elapsed) - return; - - qreal prevY = d->lastFlickablePosition.x(); - qreal prevX = d->lastFlickablePosition.y(); - d->velocityTimeline.clear(); - if (d->pressed) { - qreal horizontalVelocity = (prevX - d->_moveX.value()) * 1000 / elapsed; - qreal verticalVelocity = (prevY - d->_moveY.value()) * 1000 / elapsed; - d->velocityTimeline.move(d->horizontalVelocity, horizontalVelocity, d->reportedVelocitySmoothing); - d->velocityTimeline.move(d->horizontalVelocity, 0, d->reportedVelocitySmoothing); - d->velocityTimeline.move(d->verticalVelocity, verticalVelocity, d->reportedVelocitySmoothing); - d->velocityTimeline.move(d->verticalVelocity, 0, d->reportedVelocitySmoothing); - } else { - if (d->timeline.time() > d->vTime) { - qreal horizontalVelocity = (prevX - d->_moveX.value()) * 1000 / (d->timeline.time() - d->vTime); - qreal verticalVelocity = (prevY - d->_moveY.value()) * 1000 / (d->timeline.time() - d->vTime); - d->horizontalVelocity.setValue(horizontalVelocity); - d->verticalVelocity.setValue(verticalVelocity); - } - } - - d->lastFlickablePosition = QPointF(d->_moveY.value(), d->_moveX.value()); - - d->vTime = d->timeline.time(); - d->updateBeginningEnd(); -} - -void QmlGraphicsFlickable::cancelFlick() -{ - Q_D(QmlGraphicsFlickable); - d->timeline.reset(d->_moveX); - d->timeline.reset(d->_moveY); - movementEnding(); -} - -void QmlGraphicsFlickablePrivate::data_append(QmlListProperty<QObject> *prop, QObject *o) -{ - QmlGraphicsItem *i = qobject_cast<QmlGraphicsItem *>(o); - if (i) - i->setParentItem(static_cast<QmlGraphicsFlickablePrivate*>(prop->data)->viewport); - else - o->setParent(prop->object); -} - -QmlListProperty<QObject> QmlGraphicsFlickable::flickableData() -{ - Q_D(QmlGraphicsFlickable); - return QmlListProperty<QObject>(this, (void *)d, QmlGraphicsFlickablePrivate::data_append); -} - -QmlListProperty<QmlGraphicsItem> QmlGraphicsFlickable::flickableChildren() -{ - Q_D(QmlGraphicsFlickable); - return d->viewport->fxChildren(); -} - -/*! - \qmlproperty bool Flickable::overShoot - This property holds the number of pixels the surface may overshoot the - Flickable's boundaries when flicked. - - If overShoot is non-zero the contents can be flicked beyond the boundary - of the Flickable before being moved back to the boundary. This provides - the feeling that the edges of the view are soft, rather than a hard - physical boundary. -*/ -bool QmlGraphicsFlickable::overShoot() const -{ - Q_D(const QmlGraphicsFlickable); - return d->overShoot; -} - -void QmlGraphicsFlickable::setOverShoot(bool o) -{ - Q_D(QmlGraphicsFlickable); - if (d->overShoot == o) - return; - d->overShoot = o; - emit overShootChanged(); -} - -/*! - \qmlproperty int Flickable::viewportWidth - \qmlproperty int Flickable::viewportHeight - - The dimensions of the viewport (the surface controlled by Flickable). Typically this - should be set to the combined size of the items placed in the Flickable. - - \code - Flickable { - width: 320; height: 480; viewportWidth: image.width; viewportHeight: image.height - Image { id: image; source: "bigimage.png" } - } - \endcode -*/ -qreal QmlGraphicsFlickable::viewportWidth() const -{ - Q_D(const QmlGraphicsFlickable); - return d->vWidth; -} - -void QmlGraphicsFlickable::setViewportWidth(qreal w) -{ - Q_D(QmlGraphicsFlickable); - if (d->vWidth == w) - return; - d->vWidth = w; - if (w < 0) - d->viewport->setWidth(width()); - else - d->viewport->setWidth(w); - // Make sure that we're entirely in view. - if (!d->pressed) - d->fixupX(); - emit viewportWidthChanged(); - d->updateBeginningEnd(); -} - -void QmlGraphicsFlickable::widthChange() -{ - Q_D(QmlGraphicsFlickable); - if (d->vWidth < 0) { - d->viewport->setWidth(width()); - emit viewportWidthChanged(); - } - d->updateBeginningEnd(); -} - -void QmlGraphicsFlickable::heightChange() -{ - Q_D(QmlGraphicsFlickable); - if (d->vHeight < 0) { - d->viewport->setHeight(height()); - emit viewportHeightChanged(); - } - d->updateBeginningEnd(); -} - -qreal QmlGraphicsFlickable::viewportHeight() const -{ - Q_D(const QmlGraphicsFlickable); - return d->vHeight; -} - -void QmlGraphicsFlickable::setViewportHeight(qreal h) -{ - Q_D(QmlGraphicsFlickable); - if (d->vHeight == h) - return; - d->vHeight = h; - if (h < 0) - d->viewport->setHeight(height()); - else - d->viewport->setHeight(h); - // Make sure that we're entirely in view. - if (!d->pressed) - d->fixupY(); - emit viewportHeightChanged(); - d->updateBeginningEnd(); -} - -qreal QmlGraphicsFlickable::vWidth() const -{ - Q_D(const QmlGraphicsFlickable); - if (d->vWidth < 0) - return width(); - else - return d->vWidth; -} - -qreal QmlGraphicsFlickable::vHeight() const -{ - Q_D(const QmlGraphicsFlickable); - if (d->vHeight < 0) - return height(); - else - return d->vHeight; -} - -bool QmlGraphicsFlickable::xflick() const -{ - Q_D(const QmlGraphicsFlickable); - if (d->flickDirection == QmlGraphicsFlickable::AutoFlickDirection) - return vWidth() != width(); - return d->flickDirection & QmlGraphicsFlickable::HorizontalFlick; -} - -bool QmlGraphicsFlickable::yflick() const -{ - Q_D(const QmlGraphicsFlickable); - if (d->flickDirection == QmlGraphicsFlickable::AutoFlickDirection) - return vHeight() != height(); - return d->flickDirection & QmlGraphicsFlickable::VerticalFlick; -} - -bool QmlGraphicsFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) -{ - Q_D(QmlGraphicsFlickable); - QGraphicsSceneMouseEvent mouseEvent(event->type()); - QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect(); - - QGraphicsScene *s = scene(); - QmlGraphicsItem *grabber = s ? qobject_cast<QmlGraphicsItem*>(s->mouseGrabberItem()) : 0; - if ((d->stealMouse || 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: - d->handleMouseMoveEvent(&mouseEvent); - break; - case QEvent::GraphicsSceneMousePress: - if (d->delayedPressEvent) - return false; - - d->handleMousePressEvent(&mouseEvent); - d->captureDelayedPress(event); - break; - case QEvent::GraphicsSceneMouseRelease: - if (d->delayedPressEvent) { - scene()->sendEvent(d->delayedPressTarget, d->delayedPressEvent); - d->clearDelayedPress(); - } - d->handleMouseReleaseEvent(&mouseEvent); - break; - default: - break; - } - grabber = qobject_cast<QmlGraphicsItem*>(s->mouseGrabberItem()); - if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this) { - d->clearDelayedPress(); - grabMouse(); - } - - return d->stealMouse || d->delayedPressEvent; - } else if (!d->lastPosTime.isNull()) { - d->lastPosTime = QTime(); - } - if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) - d->clearDelayedPress(); - return false; -} - -bool QmlGraphicsFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e) -{ - Q_D(QmlGraphicsFlickable); - if (!isVisible() || !d->interactive) - return QmlGraphicsItem::sceneEventFilter(i, e); - switch (e->type()) { - case QEvent::GraphicsSceneMousePress: - case QEvent::GraphicsSceneMouseMove: - case QEvent::GraphicsSceneMouseRelease: - return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e)); - default: - break; - } - - return QmlGraphicsItem::sceneEventFilter(i, e); -} - -/*! - \qmlproperty real Flickable::maximumFlickVelocity - This property holds the maximum velocity that the user can flick the view in pixels/second. - - The default is 2000 pixels/s -*/ -qreal QmlGraphicsFlickable::maximumFlickVelocity() const -{ - Q_D(const QmlGraphicsFlickable); - return d->maxVelocity; -} - -void QmlGraphicsFlickable::setMaximumFlickVelocity(qreal v) -{ - Q_D(QmlGraphicsFlickable); - if (v == d->maxVelocity) - return; - d->maxVelocity = v; - emit maximumFlickVelocityChanged(); -} - -/*! - \qmlproperty real Flickable::flickDeceleration - This property holds the rate at which a flick will decelerate. - - The default is 500. -*/ -qreal QmlGraphicsFlickable::flickDeceleration() const -{ - Q_D(const QmlGraphicsFlickable); - return d->deceleration; -} - -void QmlGraphicsFlickable::setFlickDeceleration(qreal deceleration) -{ - Q_D(QmlGraphicsFlickable); - if (deceleration == d->deceleration) - return; - d->deceleration = deceleration; - emit flickDecelerationChanged(); -} - -/*! - \qmlproperty bool Flickable::flicking - - This property holds whether the view is currently moving due to - the user flicking the view. -*/ -bool QmlGraphicsFlickable::isFlicking() const -{ - Q_D(const QmlGraphicsFlickable); - return d->flicked; -} - -/*! - \qmlproperty int Flickable::pressDelay - - This property holds the time to delay (ms) delivering a press to - children of the Flickable. This can be useful where reacting - to a press before a flicking action has undesireable effects. - - If the flickable is dragged/flicked before the delay times out - the press event will not be delivered. If the button is released - within the timeout, both the press and release will be delivered. -*/ -int QmlGraphicsFlickable::pressDelay() const -{ - Q_D(const QmlGraphicsFlickable); - return d->pressDelay; -} - -void QmlGraphicsFlickable::setPressDelay(int delay) -{ - Q_D(QmlGraphicsFlickable); - if (d->pressDelay == delay) - return; - d->pressDelay = delay; - emit pressDelayChanged(); -} - -qreal QmlGraphicsFlickable::reportedVelocitySmoothing() const -{ - Q_D(const QmlGraphicsFlickable); - return d->reportedVelocitySmoothing; -} - -void QmlGraphicsFlickable::setReportedVelocitySmoothing(qreal reportedVelocitySmoothing) -{ - Q_D(QmlGraphicsFlickable); - Q_ASSERT(reportedVelocitySmoothing >= 0); - if (reportedVelocitySmoothing == d->reportedVelocitySmoothing) - return; - d->reportedVelocitySmoothing = reportedVelocitySmoothing; - emit reportedVelocitySmoothingChanged(reportedVelocitySmoothing); -} - -/*! - \qmlproperty bool Flickable::moving - - This property holds whether the view is currently moving due to - the user either dragging or flicking the view. -*/ -bool QmlGraphicsFlickable::isMoving() const -{ - Q_D(const QmlGraphicsFlickable); - return d->moving; -} - -void QmlGraphicsFlickable::movementStarting() -{ - Q_D(QmlGraphicsFlickable); - if (!d->moving) { - d->moving = true; - emit movingChanged(); - emit movementStarted(); - } -} - -void QmlGraphicsFlickable::movementEnding() -{ - Q_D(QmlGraphicsFlickable); - if (d->moving) { - d->moving = false; - emit movingChanged(); - emit movementEnded(); - } - if (d->flicked) { - d->flicked = false; - emit flickingChanged(); - emit flickEnded(); - } - d->horizontalVelocity.setValue(0); - d->verticalVelocity.setValue(0); -} - -void QmlGraphicsFlickablePrivate::updateVelocity() -{ - Q_Q(QmlGraphicsFlickable); - emit q->horizontalVelocityChanged(); - emit q->verticalVelocityChanged(); -} - -QT_END_NAMESPACE |