fix overshoot condition values
[kineticlist.git] / kineticview.cpp
blob30f9fca1372d7f2f10b9c7123effc288366cf890
1 /////////////////////////////////////////////////////////////////////////
2 // kineticview.cpp //
3 // //
4 // Copyright(C) 2009 Igor Trindade Oliveira <igor.oliveira@indt.org.br>//
5 // Copyright(C) 2009 Adenilson Cavalcanti <adenilson.silva@idnt.org.br>//
6 // //
7 // This library is free software; you can redistribute it and/or //
8 // modify it under the terms of the GNU Lesser General Public //
9 // License as published by the Free Software Foundation; either //
10 // version 2.1 of the License, or (at your option) any later version. //
11 // //
12 // This library is distributed in the hope that it will be useful, //
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
15 // Lesser General Public License for more details. //
16 // //
17 // You should have received a copy of the GNU Lesser General Public //
18 // License along with this library; if not, write to the Free Software //
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA //
20 // 02110-1301 USA //
21 /////////////////////////////////////////////////////////////////////////
22 #include "kineticview.h"
23 #include "scrollbar.h"
25 #include <QObject>
26 #include <QDebug>
27 #include <QGraphicsGridLayout>
28 #include <QScrollBar>
29 #include <QPropertyAnimation>
30 #include <QTime>
32 /* TODO:
33 * - fix velocity( create a new easing curve? )
34 * - kinetic velocity parameterized upon count of list items
35 * - horizontal scrolling
36 * - parameterize dimensions
37 * - ringbuffer (minimize number of items in the QGV).
40 class KineticScrollingPrivate
42 public:
43 KineticScrollingPrivate(): mScrollVelocity(0), timerID(0),
44 overshoot(40), bounceFlag(0)
45 { }
47 void count()
49 t = QTime::currentTime();
50 t.start();
53 unsigned int elapsed()
55 return t.restart();
58 void verticalScroll(int value)
60 widget->setPos(QPoint(0, -value*10));
63 void horizontalScroll(int value)
65 widget->setPos(QPoint(-value*10, 0));
68 /* Just for backport sake */
69 int normalMovement()
71 return movement;
74 int kinMovement()
76 return kin_movement;
79 qreal duration()
81 return timeDelta;
84 void mousePressEvent(QGraphicsSceneMouseEvent *event)
86 Q_UNUSED(event);
87 count();
88 scrollVelocity = 0;
89 movement = 0;
90 kin_movement = 0;
93 void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
95 int temp = event->lastPos().y() - event->pos().y();
96 if (temp) {
97 movement = temp;
98 kin_movement += temp;
102 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
104 timeDelta = elapsed();
105 int temp = event->lastPos().y() - event->pos().y();
106 if (temp)
107 kin_movement += temp;
109 if (timeDelta > 200) {
110 if (kin_movement > 0)
111 kin_movement = 3;
112 else
113 kin_movement = -3;
117 void wheelReleaseEvent(QGraphicsSceneWheelEvent *event)
119 timeDelta = elapsed();
120 int temp = event->delta();
121 temp *= -1;
122 kin_movement += temp;
124 /* Just for backport sake */
126 unsigned int timeDelta;
127 qreal scrollVelocity;
128 int movement;
129 int kin_movement;
131 qreal mScrollVelocity;
132 enum { None, Up, Down };
133 int timerID, overshoot, cposition, direction, minimalPos, maximumPos;
134 char bounceFlag;
136 QGraphicsWidget *widget;
137 QGraphicsWidget *scrollingWidget;
139 protected:
140 QTime t;
143 KineticView::KineticView(QGraphicsWidget *parent)
144 : QGraphicsWidget(parent)
146 d = new KineticScrollingPrivate;
147 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
148 d->scrollingWidget = new QGraphicsWidget(this);
149 d->scrollingWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
150 d->scrollingWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
151 layout = new QGraphicsGridLayout(this);
152 layout->addItem(d->scrollingWidget, 0, 0);
154 verticalScrollbar = new ScrollBar(this);
155 connect(verticalScrollbar, SIGNAL(valueChanged(int)), this, SLOT(setVerticalScrollValue(int)));
156 layout->addItem(verticalScrollbar, 0, 1);
158 setAcceptedMouseButtons(Qt::LeftButton);
161 KineticView::~KineticView()
163 delete d->widget;
164 delete d;
165 delete scrollAnimation;
168 void KineticView::adjustScrollBar()
170 verticalScrollbar->setMaximum( qMax( 0,
171 int( d->widget->size().height() - d->scrollingWidget->size().height())));
174 void KineticView::setWidget(QGraphicsWidget *item)
176 d->widget = item;
177 d->widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
178 d->widget->setParentItem(d->scrollingWidget);
179 d->widget->setPos(0, 0);
180 d->widget->setAcceptedMouseButtons(Qt::LeftButton);
182 scrollAnimation = new QPropertyAnimation(d->widget, "geometry");
183 connect(scrollAnimation, SIGNAL(finished()), this, SLOT(overshoot()));
184 scrollAnimation->setEasingCurve(QEasingCurve::OutCirc);
186 d->widget->installEventFilter( this );
187 adjustScrollBar();
188 update();
191 void KineticView::overshoot()
193 qDebug() << "animation is over...";
194 /* Detect if bouncer */
195 qDebug()<<d->cposition<<" "<<d->minimalPos;
196 if (d->cposition > 0) {
197 qDebug() << "UP";
199 } else if (d->cposition < d->minimalPos + d->overshoot) {
200 qDebug() << "DOWN";
205 void KineticView::setVerticalScrollValue(int value)
207 const int pos = thresholdPosition( -value );
208 d->widget->setPos(0, pos);
210 if( ( pos == d->overshoot ) && ( pos == d->minimalPos ) )
211 overshoot();
214 int KineticView::thresholdPosition(int value)
217 d->minimalPos = -d->widget->size().height() + d->scrollingWidget->size().height()
218 -d->overshoot;
219 d->minimalPos = qMin(d->overshoot, d->minimalPos);
220 d->maximumPos = value;
222 d->cposition = qBound(d->minimalPos, d->maximumPos, d->overshoot);
224 return d->cposition;
227 void KineticView::resetAnimation(int duration)
229 if (scrollAnimation->state() != QAbstractAnimation::Stopped)
230 scrollAnimation->stop();
231 QRectF tmpGeometry = d->widget->geometry();
232 scrollAnimation->setStartValue(tmpGeometry);
233 d->cposition = thresholdPosition(tmpGeometry.y() - d->kinMovement()*6);
234 tmpGeometry.setY(d->cposition);
235 scrollAnimation->setEndValue(tmpGeometry);
236 scrollAnimation->setDuration(duration);
237 scrollAnimation->start();
242 void KineticView::mousePressEvent(QGraphicsSceneMouseEvent *event)
244 if (scrollAnimation->state() != QAbstractAnimation::Stopped)
245 scrollAnimation->stop();
247 event->accept();
248 d->mousePressEvent(event);
251 void KineticView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
253 d->mouseMoveEvent(event);
254 setVerticalScrollValue(-(d->widget->pos().y() - d->normalMovement()));
255 QGraphicsWidget::mouseMoveEvent(event);
258 void KineticView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
261 d->mouseReleaseEvent(event);
262 resetAnimation(d->duration()*8);
266 void KineticView::wheelEvent(QGraphicsSceneWheelEvent *event)
268 event->accept();
269 d->mousePressEvent(NULL);
270 d->wheelReleaseEvent(event);
271 resetAnimation(900);
274 void KineticView::resizeEvent(QGraphicsSceneResizeEvent *event)
276 if (d->widget)
277 adjustScrollBar();
278 QGraphicsWidget::resizeEvent(event);
281 bool KineticView::eventFilter(QObject *watched, QEvent *event)
283 if (!d->widget) {
284 return false;
287 if (watched == d->widget && event->type() == QEvent::GraphicsSceneMove) {
288 verticalScrollbar->blockSignals(true);
289 verticalScrollbar->setValue(d->widget->pos().y());
290 verticalScrollbar->blockSignals(false);
293 return false;