Adding a kinetic scrolling class and using it in plasma::ScrollWidget.
ATM, it uses timers to do the animation, the idea is to use factory pattern and implement the animation with QProperyAnimation too (using Qt 4.6). svn path=/trunk/KDE/kdelibs/; revision=1024929
This commit is contained in:
parent
28a8bde40d
commit
974df6773a
@ -89,6 +89,7 @@ set(plasma_LIB_SRCS
|
||||
private/tooltip.cpp
|
||||
private/wallpaperrenderthread.cpp
|
||||
private/windowpreview.cpp
|
||||
private/kineticscroll.cpp
|
||||
querymatch.cpp
|
||||
remote/accessmanager.cpp
|
||||
remote/accessappletjob.cpp
|
||||
|
305
private/kineticscroll.cpp
Normal file
305
private/kineticscroll.cpp
Normal file
@ -0,0 +1,305 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// kineticscroll.cpp //
|
||||
// //
|
||||
// Copyright(C) 2009 Igor Trindade Oliveira <igor.oliveira@indt.org.br>//
|
||||
// Copyright(C) 2009 Adenilson Cavalcanti <adenilson.silva@idnt.org.br>//
|
||||
// //
|
||||
// This library is free software; you can redistribute it and/or //
|
||||
// modify it under the terms of the GNU Lesser General Public //
|
||||
// License as published by the Free Software Foundation; either //
|
||||
// version 2.1 of the License, or (at your option) any later version. //
|
||||
// //
|
||||
// This library is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
|
||||
// Lesser General Public License for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU Lesser General Public //
|
||||
// License along with this library; if not, write to the Free Software //
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA //
|
||||
// 02110-1301 USA //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <QGraphicsWidget>
|
||||
#include "kineticscroll_p.h"
|
||||
|
||||
/* TODO:
|
||||
* - write a factory to animation/state object
|
||||
* - move timer based code to an implementation of the factory
|
||||
* - write another implementation using QPropertyAnimation Qt 4.6
|
||||
* - generalize code concerning viewport and other parameters
|
||||
* - swap the 'magic numbers' for consts
|
||||
* - consider if direct access to control state/velocity variables should
|
||||
* be done directly or using functions
|
||||
* - implement horizontal scrolling (simultaneously with vertical)
|
||||
*/
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class KineticScrollingPrivate
|
||||
{
|
||||
public:
|
||||
KineticScrollingPrivate(): mScrollVelocity(0), timerID(0),
|
||||
overshut(40), bounceFlag(0)
|
||||
{ }
|
||||
|
||||
void count()
|
||||
{
|
||||
t = QTime::currentTime();
|
||||
t.start();
|
||||
}
|
||||
|
||||
unsigned int elapsed()
|
||||
{
|
||||
return t.restart();
|
||||
}
|
||||
|
||||
void verticalScroll(int value)
|
||||
{
|
||||
widget->setPos(QPoint(0, -value*10));
|
||||
}
|
||||
|
||||
void horizontalScroll(int value)
|
||||
{
|
||||
widget->setPos(QPoint(-value*10, 0));
|
||||
}
|
||||
|
||||
|
||||
unsigned int timeDelta;
|
||||
qreal scrollVelocity;
|
||||
int movement;
|
||||
int kinMovement;
|
||||
|
||||
qreal mScrollVelocity;
|
||||
enum { None, Up, Down };
|
||||
int timerID, overshut, cposition, direction, minimalPos, maximumPos;
|
||||
char bounceFlag;
|
||||
|
||||
QGraphicsWidget *widget;
|
||||
QGraphicsWidget *scrollingWidget;
|
||||
|
||||
protected:
|
||||
QTime t;
|
||||
};
|
||||
|
||||
|
||||
KineticScrolling::KineticScrolling(): d(0)
|
||||
{
|
||||
d = new KineticScrollingPrivate;
|
||||
}
|
||||
|
||||
KineticScrolling::~KineticScrolling()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
int KineticScrolling::movement()
|
||||
{
|
||||
return d->movement;
|
||||
}
|
||||
|
||||
int KineticScrolling::kinMovement()
|
||||
{
|
||||
return d->kinMovement;
|
||||
}
|
||||
|
||||
qreal KineticScrolling::duration()
|
||||
{
|
||||
return d->timeDelta;
|
||||
}
|
||||
|
||||
void KineticScrolling::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
doneOvershut();
|
||||
|
||||
Q_UNUSED(event);
|
||||
d->count();
|
||||
d->scrollVelocity = 0;
|
||||
d->movement = 0;
|
||||
d->kinMovement = 0;
|
||||
}
|
||||
|
||||
void KineticScrolling::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
int temp = event->lastPos().y() - event->pos().y();
|
||||
if (temp) {
|
||||
d->movement = temp;
|
||||
d->kinMovement += temp;
|
||||
}
|
||||
/* After */
|
||||
setKineticScrollValue(movement());
|
||||
}
|
||||
|
||||
void KineticScrolling::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
d->timeDelta = d->elapsed();
|
||||
int temp = event->lastPos().y() - event->pos().y();
|
||||
if (temp)
|
||||
d->kinMovement += temp;
|
||||
|
||||
if (d->timeDelta > 600) {
|
||||
if (d->kinMovement > 0)
|
||||
d->kinMovement = 3;
|
||||
else
|
||||
d->kinMovement = -3;
|
||||
}
|
||||
|
||||
/* The after */
|
||||
if (d->cposition > 0) {
|
||||
d->direction = KineticScrollingPrivate::Up;
|
||||
} else if (abs(d->cposition) >
|
||||
abs(d->scrollingWidget->size().height() - d->widget->size().height())) {
|
||||
d->direction = KineticScrollingPrivate::Down;
|
||||
} else {
|
||||
d->direction = KineticScrollingPrivate::None;
|
||||
d->mScrollVelocity = kinMovement();
|
||||
startAnimationTimer(30);
|
||||
return;
|
||||
}
|
||||
|
||||
d->mScrollVelocity = 5;
|
||||
killTimer(d->timerID);
|
||||
startAnimationTimer(50);
|
||||
|
||||
}
|
||||
|
||||
void KineticScrolling::wheelReleaseEvent(QGraphicsSceneWheelEvent *event)
|
||||
{
|
||||
|
||||
mousePressEvent(0);
|
||||
|
||||
/* Core */
|
||||
d->timeDelta = d->elapsed();
|
||||
int temp = event->delta();
|
||||
temp *= -0.5;
|
||||
d->kinMovement += temp;
|
||||
|
||||
/* After */
|
||||
d->mScrollVelocity = kinMovement();
|
||||
startAnimationTimer(30);
|
||||
|
||||
}
|
||||
|
||||
void KineticScrolling::startAnimationTimer(int interval)
|
||||
{
|
||||
if (d->timerID) {
|
||||
killTimer(d->timerID);
|
||||
d->timerID = 0;
|
||||
}
|
||||
|
||||
d->timerID = QObject::startTimer(interval);
|
||||
}
|
||||
|
||||
void KineticScrolling::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
if (d->direction == KineticScrollingPrivate::None) {
|
||||
d->mScrollVelocity *= 0.9;
|
||||
if (qAbs(d->mScrollVelocity) < 5.0) {
|
||||
if (d->timerID)
|
||||
killTimer(d->timerID);
|
||||
|
||||
}
|
||||
setKineticScrollValue(qRound(d->mScrollVelocity));
|
||||
} else {
|
||||
if ((d->timerID != 0) && (d->direction != KineticScrollingPrivate::None)) {
|
||||
bounceTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KineticScrolling::setKineticScrollValue(int value)
|
||||
{
|
||||
|
||||
d->minimalPos = (-(d->widget->size().height())) + d->scrollingWidget->size().height()
|
||||
-(d->overshut);
|
||||
d->minimalPos = qMin(d->overshut, d->minimalPos);
|
||||
d->maximumPos = d->widget->pos().y() - value;
|
||||
|
||||
d->cposition = qBound(d->minimalPos, d->maximumPos, d->overshut);
|
||||
d->widget->setPos(0, d->cposition);
|
||||
d->verticalScroll(-d->cposition/10);
|
||||
|
||||
if (d->cposition == d->overshut) {
|
||||
d->direction = KineticScrollingPrivate::Up;
|
||||
killTimer(d->timerID);
|
||||
d->mScrollVelocity = 5;
|
||||
startAnimationTimer(30);
|
||||
|
||||
} else if (d->cposition == d->minimalPos) {
|
||||
d->direction = KineticScrollingPrivate::Down;
|
||||
killTimer(d->timerID);
|
||||
d->mScrollVelocity = 5;
|
||||
startAnimationTimer(30);
|
||||
|
||||
} else
|
||||
d->direction = KineticScrollingPrivate::None;
|
||||
|
||||
}
|
||||
|
||||
void KineticScrolling::bounceTimer()
|
||||
{
|
||||
int delta = 5;
|
||||
if ((d->direction == KineticScrollingPrivate::Up) && (d->bounceFlag == 0))
|
||||
delta = -5;
|
||||
else if ((d->direction == KineticScrollingPrivate::Up) && (d->bounceFlag == 1))
|
||||
delta = -2;
|
||||
else if ((d->direction == KineticScrollingPrivate::Down) && (d->bounceFlag == 0))
|
||||
delta = 5;
|
||||
else if ((d->direction == KineticScrollingPrivate::Down) && (d->bounceFlag == 1))
|
||||
delta = 2;
|
||||
|
||||
d->cposition += delta;
|
||||
d->widget->setPos(0, d->cposition);
|
||||
|
||||
if ((d->direction == KineticScrollingPrivate::Up) && (d->cposition < 0)) {
|
||||
if (!d->bounceFlag) {
|
||||
d->cposition = d->overshut/4;
|
||||
d->bounceFlag = 1;
|
||||
d->widget->setPos(0, d->cposition);
|
||||
return;
|
||||
} else {
|
||||
d->bounceFlag = 0;
|
||||
d->cposition = 0;
|
||||
doneOvershut() ;
|
||||
}
|
||||
|
||||
} else if ((d->direction == KineticScrollingPrivate::Down) &&
|
||||
((d->cposition - d->overshut) > d->minimalPos)) {
|
||||
if (!d->bounceFlag) {
|
||||
d->cposition = d->minimalPos + d->overshut/4;
|
||||
d->bounceFlag = 1;
|
||||
d->widget->setPos(0, d->cposition);
|
||||
return;
|
||||
} else {
|
||||
d->bounceFlag = 0;
|
||||
d->cposition = d->minimalPos + d->overshut;
|
||||
doneOvershut();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void KineticScrolling::doneOvershut(void)
|
||||
{
|
||||
d->direction = KineticScrollingPrivate::None;
|
||||
d->mScrollVelocity = 0;
|
||||
killTimer(d->timerID);
|
||||
d->timerID = 0;
|
||||
}
|
||||
|
||||
void KineticScrolling::setWidgets(QGraphicsWidget *widget,
|
||||
QGraphicsWidget *scrolling)
|
||||
{
|
||||
d->widget = widget;
|
||||
d->scrollingWidget = scrolling;
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
62
private/kineticscroll_p.h
Normal file
62
private/kineticscroll_p.h
Normal file
@ -0,0 +1,62 @@
|
||||
/***********************************************************************/
|
||||
/* kineticscroll.h */
|
||||
/* */
|
||||
/* Copyright(C) 2009 Igor Trindade Oliveira <igor.oliveira@indt.org.br>*/
|
||||
/* Copyright(C) 2009 Adenilson Cavalcanti <adenilson.silva@idnt.org.br>*/
|
||||
/* */
|
||||
/* This library is free software; you can redistribute it and/or */
|
||||
/* modify it under the terms of the GNU Lesser General Public */
|
||||
/* License as published by the Free Software Foundation; either */
|
||||
/* version 2.1 of the License, or (at your option) any later version. */
|
||||
/* */
|
||||
/* This library is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
|
||||
/* Lesser General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU Lesser General Public */
|
||||
/* License along with this library; if not, write to the Free Software */
|
||||
/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA */
|
||||
/* 02110-1301 USA */
|
||||
/***********************************************************************/
|
||||
#ifndef PLASMA_KINETICSCROLLING_H
|
||||
#define PLASMA_KINETICSCROLLING_H
|
||||
|
||||
class QGraphicsSceneMouseEvent;
|
||||
class QGraphicsWidget;
|
||||
#include <QObject>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class KineticScrollingPrivate;
|
||||
|
||||
class KineticScrolling: public QObject
|
||||
{
|
||||
public:
|
||||
KineticScrolling();
|
||||
~KineticScrolling();
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||
void wheelReleaseEvent(QGraphicsSceneWheelEvent *event);
|
||||
void setWidgets(QGraphicsWidget *widget, QGraphicsWidget *scrolling);
|
||||
|
||||
private:
|
||||
KineticScrollingPrivate *d;
|
||||
void timerEvent(QTimerEvent *event);
|
||||
void bounceTimer();
|
||||
qreal duration();
|
||||
int movement();
|
||||
int kinMovement();
|
||||
void startAnimationTimer(int interval);
|
||||
void doneOvershut(void);
|
||||
|
||||
public Q_SLOTS:
|
||||
void setKineticScrollValue(int value);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "scrollwidget.h"
|
||||
|
||||
#include "private/kineticscroll_p.h"
|
||||
//Qt
|
||||
#include <QGraphicsSceneResizeEvent>
|
||||
#include <QGraphicsGridLayout>
|
||||
@ -37,7 +37,7 @@
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ScrollWidgetPrivate
|
||||
class ScrollWidgetPrivate: public KineticScrolling
|
||||
{
|
||||
public:
|
||||
ScrollWidgetPrivate(ScrollWidget *parent)
|
||||
@ -209,7 +209,6 @@ ScrollWidget::~ScrollWidget()
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
void ScrollWidget::setWidget(QGraphicsWidget *widget)
|
||||
{
|
||||
if (d->widget && d->widget != widget) {
|
||||
@ -218,6 +217,7 @@ void ScrollWidget::setWidget(QGraphicsWidget *widget)
|
||||
}
|
||||
|
||||
d->widget = widget;
|
||||
d->setWidgets(widget, d->scrollingWidget);
|
||||
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
widget->setParentItem(d->scrollingWidget);
|
||||
widget->setPos(QPoint(0,0));
|
||||
@ -303,31 +303,25 @@ void ScrollWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
QPointF deltaPos = event->pos() - event->lastPos();
|
||||
|
||||
d->widget->setPos(qBound(qMin((qreal)0,-d->widget->size().width()+d->scrollingWidget->size().width()), d->widget->pos().x()+deltaPos.x(), (qreal)0),
|
||||
qBound(qMin((qreal)0,-d->widget->size().height()+d->scrollingWidget->size().height()), d->widget->pos().y()+deltaPos.y(), (qreal)0));
|
||||
|
||||
d->dragging = true;
|
||||
d->horizontalScrollBar->setValue(-d->widget->pos().x()/10);
|
||||
d->verticalScrollBar->setValue(-d->widget->pos().y()/10);
|
||||
d->dragging = false;
|
||||
|
||||
d->mouseMoveEvent(event);
|
||||
QGraphicsWidget::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void ScrollWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
event->accept();
|
||||
d->mousePressEvent(event);
|
||||
}
|
||||
|
||||
void ScrollWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
d->mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void ScrollWidget::wheelEvent(QGraphicsSceneWheelEvent *event)
|
||||
{
|
||||
if (event->delta() < 0) {
|
||||
d->verticalScrollBar->setValue(d->verticalScrollBar->value()+10);
|
||||
} else {
|
||||
d->verticalScrollBar->setValue(d->verticalScrollBar->value()-10);
|
||||
}
|
||||
event->accept();
|
||||
d->wheelReleaseEvent( event );
|
||||
QGraphicsWidget::wheelEvent(event);
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,7 @@ protected:
|
||||
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||
void wheelEvent(QGraphicsSceneWheelEvent *event);
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
@ -126,6 +127,7 @@ private:
|
||||
|
||||
Q_PRIVATE_SLOT(d, void verticalScroll(int value))
|
||||
Q_PRIVATE_SLOT(d, void horizontalScroll(int value))
|
||||
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
Loading…
Reference in New Issue
Block a user