/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: openBossa - INdT (renato.chencarek@openbossa.org) ** ** $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 ** the openBossa stream from INdT (renato.chencarek@openbossa.org). ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include "kineticscroll.h" #define MAX_SPEED 2000 class KineticScrollPrivate { public: QTimer *animation; qreal animationSpeed; QTime animationITime; qreal animationAccel; qreal accelConstant; QTime time; QTime lastTime; int value; int lastValue; }; KineticScroll::KineticScroll(QObject *parent) : QObject(parent), d(new KineticScrollPrivate) { d->animation = 0; d->accelConstant = 0.3; d->value = d->lastValue = -1; d->time = d->lastTime = QTime::currentTime(); } KineticScroll::~KineticScroll() { delete d; } void KineticScroll::mouseUp(int value) { if (d->lastValue < 0 || d->animation) return; QTime t = QTime::currentTime(); qreal dv = value - d->lastValue; qreal dt = (qreal)d->lastTime.msecsTo(t) / 1000; if (dt == 0) return; kineticStart(dv / dt); mouseCancel(); } bool KineticScroll::mouseDown(int value) { bool r = true; if (d->animation) { d->animation->stop(); d->animation->deleteLater(); d->animation = 0; r = false; } d->lastValue = d->value = value; d->lastTime = d->time = QTime::currentTime(); return r; } void KineticScroll::mouseMove(int value) { if (d->lastValue < 0) return; int dv = value - d->value; QTime t = QTime::currentTime(); d->lastValue = d->value; d->lastTime = d->time; d->value = value; d->time = t; emit signalMoveOffset(dv); } void KineticScroll::mouseCancel() { d->value = -1; d->lastValue = -1; } void KineticScroll::kineticStop() { if (d->animation) { d->animation->stop(); d->animation->deleteLater(); } d->animation = 0; } void KineticScroll::kineticStart(qreal speed) { d->animationSpeed = qBound(-MAX_SPEED, speed, MAX_SPEED); d->animationITime = QTime::currentTime(); d->animationAccel = -d->animationSpeed * d->accelConstant; d->animation = new QTimer(); connect(d->animation, SIGNAL(timeout()), this, SLOT(animator())); d->animation->start(10); } void KineticScroll::animator() { QTime now = QTime::currentTime(); qreal dt = (qreal)d->animationITime.msecsTo(now) / 1000; qreal speed = d->animationSpeed + d->animationAccel * dt; qreal value = d->animationSpeed * dt + d->animationAccel * dt * dt / 2; if (d->animationAccel * speed > 0) { // just to notify animation finish emit signalMoveOffset(0); kineticStop(); } else { emit signalMoveOffset(qRound(value)); d->animationSpeed = speed; d->animationITime = now; } }