now the api is similar to what webkit offers and horizontal and vertical
scroll is done in pixels and in a single pass. we have 3 properties in widgets that wants to support scroll: scrollPosition viewportGeometry constentsSize svn path=/trunk/KDE/kdelibs/; revision=1032821
This commit is contained in:
parent
2ea0319b74
commit
38884ccd1a
@ -27,6 +27,8 @@
|
||||
#include <QGraphicsWidget>
|
||||
#include <QPoint>
|
||||
|
||||
#include <kdebug.h>
|
||||
|
||||
#include "kineticscroll_p.h"
|
||||
|
||||
/* TODO:
|
||||
@ -44,9 +46,20 @@ namespace Plasma
|
||||
class KineticScrollingPrivate
|
||||
{
|
||||
public:
|
||||
KineticScrollingPrivate(): timerID(0),
|
||||
overshoot(20), bounceFlag(0), hasOvershoot(true),
|
||||
friction(0.8)
|
||||
enum Direction {
|
||||
None,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right
|
||||
};
|
||||
|
||||
KineticScrollingPrivate()
|
||||
: timerID(0),
|
||||
overshoot(20),
|
||||
bounceFlag(0),
|
||||
hasOvershoot(true),
|
||||
friction(0.8)
|
||||
{
|
||||
maximum = 100 + overshoot;
|
||||
minimum = -overshoot;
|
||||
@ -59,22 +72,48 @@ public:
|
||||
|
||||
void applyFriction()
|
||||
{
|
||||
qreal tmp(kinMovement.y());
|
||||
tmp *= friction;
|
||||
kinMovement.setY(tmp);
|
||||
kinMovement *= friction;
|
||||
}
|
||||
|
||||
void syncViewportRect()
|
||||
{
|
||||
contentsSize = parent->property("contentsSize").toSizeF();
|
||||
viewportGeometry = parent->property("viewportGeometry").toRectF();
|
||||
//TODO: overshoot and friction will have to be independent horizontal and vertical
|
||||
overshoot = 20*(1.0 - viewportGeometry.height()/contentsSize.height());
|
||||
}
|
||||
|
||||
bool canScroll(Direction direction, bool hasOvershoot = false) const
|
||||
{
|
||||
QPointF scrollPosition = -parent->property("scrollPosition").value<QPointF>();
|
||||
int offset = (hasOvershoot?overshoot*2:0);
|
||||
|
||||
switch (direction) {
|
||||
case Up:
|
||||
return (scrollPosition.y() < offset);
|
||||
case Down:
|
||||
return (scrollPosition.y() + contentsSize.height() + offset >= viewportGeometry.bottom());
|
||||
case Left:
|
||||
return (scrollPosition.x() < offset);
|
||||
case Right:
|
||||
return (scrollPosition.x() + contentsSize.width() + offset >= viewportGeometry.right());
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int timeDelta;
|
||||
qreal scrollVelocity;
|
||||
QPointF kinMovement;
|
||||
|
||||
enum { None, Up, Down };
|
||||
|
||||
int timerID, overshoot, direction;
|
||||
QPointF cposition;
|
||||
char bounceFlag;
|
||||
bool hasOvershoot;
|
||||
QObject *parent;
|
||||
QRectF geo;
|
||||
QRectF viewportGeometry;
|
||||
QSizeF contentsSize;
|
||||
int maximum, minimum;
|
||||
qreal friction;
|
||||
|
||||
@ -104,6 +143,8 @@ void KineticScrolling::duration()
|
||||
|
||||
void KineticScrolling::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
d->syncViewportRect();
|
||||
d->cposition = -d->parent->property("scrollPosition").value<QPointF>();
|
||||
doneOvershoot();
|
||||
Q_UNUSED(event);
|
||||
d->count();
|
||||
@ -114,11 +155,12 @@ void KineticScrolling::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
void KineticScrolling::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
QPointF temp = event->lastPos().toPoint() - event->pos().toPoint();
|
||||
|
||||
if (!temp.isNull()) {
|
||||
d->kinMovement += temp;
|
||||
}
|
||||
/* After */
|
||||
setKineticScrollValue(d->kinMovement/4);
|
||||
setKineticScrollValue(d->kinMovement);
|
||||
}
|
||||
|
||||
void KineticScrolling::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
@ -127,13 +169,13 @@ void KineticScrolling::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
duration();
|
||||
/* slow down a bit */
|
||||
d->kinMovement /= 4;
|
||||
d->kinMovement *= d->geo.height();
|
||||
|
||||
if (d->timeDelta > 600) {
|
||||
if (d->kinMovement.y() > 0)
|
||||
d->kinMovement.setY(6 * d->geo.height());
|
||||
else
|
||||
d->kinMovement.setY(-6 * d->geo.height());
|
||||
if (d->kinMovement.y() > 0) {
|
||||
d->kinMovement.setY(6);
|
||||
} else {
|
||||
d->kinMovement.setY(-6);
|
||||
}
|
||||
}
|
||||
|
||||
d->direction = KineticScrollingPrivate::None;
|
||||
@ -143,16 +185,12 @@ void KineticScrolling::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
void KineticScrolling::wheelReleaseEvent(QGraphicsSceneWheelEvent *event)
|
||||
{
|
||||
doneOvershoot();
|
||||
d->geo = d->parent->property("viewport").toRectF();
|
||||
d->syncViewportRect();
|
||||
if (d->direction == KineticScrollingPrivate::None) {
|
||||
mousePressEvent(0);
|
||||
duration();
|
||||
/* scroll down is negative in pixels */
|
||||
qreal temp = event->delta();
|
||||
if (temp < 0)
|
||||
temp = d->geo.height() * 30;
|
||||
else
|
||||
temp = d->geo.height() * -30;
|
||||
|
||||
int temp = -event->delta();
|
||||
|
||||
d->kinMovement.setY(kinMovement().y() + temp);
|
||||
|
||||
@ -168,40 +206,55 @@ void KineticScrolling::startAnimationTimer(int interval)
|
||||
d->timerID = 0;
|
||||
}
|
||||
|
||||
/* factor in friction X viewport/widget ratio */
|
||||
if (d->geo.height() < 0.30)
|
||||
d->friction = 0.85;
|
||||
else
|
||||
d->friction = 0.80;
|
||||
d->syncViewportRect();
|
||||
|
||||
d->geo = d->parent->property("viewport").toRectF();
|
||||
d->timerID = QObject::startTimer(interval);
|
||||
}
|
||||
|
||||
void KineticScrolling::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
d->cposition.setY(d->parent->property("verticalScrollValue").value<qreal>());
|
||||
d->cposition = -d->parent->property("scrollPosition").value<QPointF>();
|
||||
|
||||
if (d->direction == KineticScrollingPrivate::None) {
|
||||
if ((qAbs(d->kinMovement.y()) < 2)) {
|
||||
if ((d->cposition.y() > 100) ||
|
||||
(d->cposition.y() < 0)) {
|
||||
if (d->cposition.y() < 0)
|
||||
d->kinMovement.setY(1.0);
|
||||
else
|
||||
d->kinMovement.setY(-1.0);
|
||||
|
||||
d->parent->setProperty("verticalScrollValue", d->cposition.y()
|
||||
+ d->kinMovement.y());
|
||||
if (qAbs(d->kinMovement.y()) < 5.0 &&
|
||||
qAbs(d->kinMovement.x()) < 5.0 ) {
|
||||
|
||||
d->kinMovement = QPoint(0,0);
|
||||
|
||||
if (d->canScroll(KineticScrollingPrivate::Down) && !d->canScroll(KineticScrollingPrivate::Up)) {
|
||||
if (d->cposition.y() > 2) {
|
||||
d->kinMovement.setY(-2);
|
||||
}
|
||||
} else if (d->canScroll(KineticScrollingPrivate::Up) && !d->canScroll(KineticScrollingPrivate::Down)) {
|
||||
if (d->cposition.y() + d->contentsSize.height() < d->viewportGeometry.bottom()) {
|
||||
d->kinMovement.setY(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (d->canScroll(KineticScrollingPrivate::Right) && !d->canScroll(KineticScrollingPrivate::Left)) {
|
||||
if (d->cposition.x() > 2) {
|
||||
d->kinMovement.setX(-2);
|
||||
}
|
||||
} else if (d->canScroll(KineticScrollingPrivate::Left) && !d->canScroll(KineticScrollingPrivate::Right)) {
|
||||
if (d->cposition.x() + d->contentsSize.width() < d->viewportGeometry.right()) {
|
||||
d->kinMovement.setX(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (!d->kinMovement.isNull()) {
|
||||
d->parent->setProperty("scrollPosition", -(d->cposition
|
||||
+ d->kinMovement));
|
||||
return;
|
||||
}
|
||||
if (d->timerID) {
|
||||
killTimer(d->timerID);
|
||||
}
|
||||
|
||||
} else
|
||||
} else {
|
||||
d->applyFriction();
|
||||
}
|
||||
|
||||
setKineticScrollValue(d->kinMovement);
|
||||
|
||||
@ -212,26 +265,41 @@ void KineticScrolling::timerEvent(QTimerEvent *event)
|
||||
|
||||
void KineticScrolling::setKineticScrollValue(QPointF value)
|
||||
{
|
||||
if (!(d->geo.height())) {
|
||||
d->kinMovement.setY(0);
|
||||
if (d->viewportGeometry.isEmpty()) {
|
||||
d->kinMovement = QPoint();
|
||||
return;
|
||||
}
|
||||
|
||||
qreal movement = value.y();
|
||||
qreal final;
|
||||
QPointF scrollPosition = -d->parent->property("scrollPosition").value<QPointF>();
|
||||
|
||||
movement += d->cposition.y();
|
||||
QPointF movement = d->cposition - value;
|
||||
|
||||
if (movement > d->maximum) {
|
||||
d->kinMovement.setY(-(d->overshoot) * d->geo.height());
|
||||
} else if (movement < d->minimum) {
|
||||
d->kinMovement.setY(d->overshoot * d->geo.height());
|
||||
} else {
|
||||
final = qBound((qreal)d->minimum, movement, (qreal)d->maximum);
|
||||
d->parent->setProperty("verticalScrollValue", final);
|
||||
if (d->kinMovement.y() < 0 && !d->canScroll(KineticScrollingPrivate::Up, true)) {
|
||||
if (d->canScroll(KineticScrollingPrivate::Down, false)) {
|
||||
d->kinMovement.setY(d->overshoot/2);
|
||||
}
|
||||
movement.setY(scrollPosition.y());
|
||||
} else if (d->kinMovement.y() > 0 && !d->canScroll(KineticScrollingPrivate::Down, true)) {
|
||||
if (d->canScroll(KineticScrollingPrivate::Up, false)) {
|
||||
d->kinMovement.setY(-d->overshoot/2);
|
||||
}
|
||||
movement.setY(scrollPosition.y());
|
||||
}
|
||||
|
||||
/* TODO: use 'ScrollWidget::HorizontalScrollValue */
|
||||
if (d->kinMovement.x() < 0 && !d->canScroll(KineticScrollingPrivate::Left, true)) {
|
||||
if (d->canScroll(KineticScrollingPrivate::Right, false)) {
|
||||
d->kinMovement.setX(d->overshoot/2);
|
||||
}
|
||||
movement.setX(scrollPosition.x());
|
||||
} else if (d->kinMovement.x() > 0 && !d->canScroll(KineticScrollingPrivate::Right, true)) {
|
||||
if (d->canScroll(KineticScrollingPrivate::Left, false)) {
|
||||
d->kinMovement.setX(-d->overshoot/2);
|
||||
}
|
||||
movement.setX(scrollPosition.x());
|
||||
}
|
||||
|
||||
d->parent->setProperty("scrollPosition", -movement);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -343,58 +343,29 @@ void ScrollWidget::ensureItemVisible(QGraphicsItem *item)
|
||||
QTimer::singleShot(0, this, SLOT(makeRectVisible()));
|
||||
}
|
||||
|
||||
qreal ScrollWidget::horizontalScrollValue() const
|
||||
{
|
||||
if (!d->widget) {
|
||||
return 0;
|
||||
}
|
||||
return (d->widget->x()*100)/(d->widget->size().width() -
|
||||
d->scrollingWidget->size().width());
|
||||
}
|
||||
|
||||
void ScrollWidget::setHorizontalScrollValue(qreal value)
|
||||
{
|
||||
if (!d->widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->widget->setPos((value * (d->widget->size().width() -
|
||||
d->scrollingWidget->size().width()))/100,
|
||||
d->widget->pos().y());
|
||||
}
|
||||
|
||||
qreal ScrollWidget::verticalScrollValue() const
|
||||
{
|
||||
if (!d->widget) {
|
||||
return 0;
|
||||
}
|
||||
return (-1 * d->widget->y()*100)/(d->widget->size().height() -
|
||||
d->scrollingWidget->size().height());
|
||||
}
|
||||
|
||||
void ScrollWidget::setVerticalScrollValue(qreal value)
|
||||
{
|
||||
|
||||
if (!d->widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->widget->setPos(d->widget->pos().x(),
|
||||
(-1 * value * (d->widget->size().height() -
|
||||
d->scrollingWidget->size().height()))/100);
|
||||
}
|
||||
|
||||
QRectF ScrollWidget::viewport() const
|
||||
QRectF ScrollWidget::viewportGeometry() const
|
||||
{
|
||||
QRectF result;
|
||||
if (!d->widget) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = d->scrollingWidget->boundingRect();
|
||||
result.setHeight(result.height()/d->widget->boundingRect().height());
|
||||
result.setWidth(result.width()/d->widget->boundingRect().width());
|
||||
return result;
|
||||
return d->scrollingWidget->boundingRect();
|
||||
}
|
||||
|
||||
QSizeF ScrollWidget::contentsSize() const
|
||||
{
|
||||
return d->widget->size();
|
||||
}
|
||||
|
||||
void ScrollWidget::setScrollPosition(const QPointF &position)
|
||||
{
|
||||
d->widget->setPos(-position);
|
||||
}
|
||||
|
||||
QPointF ScrollWidget::scrollPosition() const
|
||||
{
|
||||
return -d->widget->pos();
|
||||
}
|
||||
|
||||
void ScrollWidget::setStyleSheet(const QString &styleSheet)
|
||||
|
@ -45,9 +45,9 @@ class PLASMA_EXPORT ScrollWidget : public QGraphicsWidget
|
||||
Q_PROPERTY(QGraphicsWidget *widget READ widget WRITE setWidget)
|
||||
Q_PROPERTY(Qt::ScrollBarPolicy horizontalScrollBarPolicy READ horizontalScrollBarPolicy WRITE setHorizontalScrollBarPolicy)
|
||||
Q_PROPERTY(Qt::ScrollBarPolicy verticalScrollBarPolicy READ verticalScrollBarPolicy WRITE setVerticalScrollBarPolicy)
|
||||
Q_PROPERTY(qreal horizontalScrollValue READ horizontalScrollValue WRITE setHorizontalScrollValue)
|
||||
Q_PROPERTY(qreal verticalScrollValue READ verticalScrollValue WRITE setVerticalScrollValue)
|
||||
Q_PROPERTY(QRectF viewport READ viewport)
|
||||
Q_PROPERTY(QPointF scrollPosition READ scrollPosition WRITE setScrollPosition)
|
||||
Q_PROPERTY(QSizeF contentsSize READ contentsSize)
|
||||
Q_PROPERTY(QRectF viewportGeometry READ viewportGeometry)
|
||||
Q_PROPERTY(QString styleSheet READ styleSheet WRITE setStyleSheet)
|
||||
|
||||
public:
|
||||
@ -114,35 +114,31 @@ public:
|
||||
*/
|
||||
void ensureItemVisible(QGraphicsItem *item);
|
||||
|
||||
/**
|
||||
* The horizontal scroll value, between 0 and 100
|
||||
/**
|
||||
* The geometry of the viewport.
|
||||
* @since 4.4
|
||||
*/
|
||||
qreal horizontalScrollValue() const;
|
||||
QRectF viewportGeometry() const;
|
||||
|
||||
|
||||
/**
|
||||
* Set the horizontal scroll value, between 0 and 100
|
||||
* @return the size of the internal widget
|
||||
* @since 4.4
|
||||
*/
|
||||
void setHorizontalScrollValue(qreal value);
|
||||
QSizeF contentsSize() const;
|
||||
|
||||
/**
|
||||
* The horizontal scroll value, between 0 and 100
|
||||
* Sets the position of the internal widget relative to this widget
|
||||
* @since 4.4
|
||||
*/
|
||||
qreal verticalScrollValue() const;
|
||||
void setScrollPosition(const QPointF &position);
|
||||
|
||||
/**
|
||||
* Set the horizontal scroll value, between 0 and 100
|
||||
* @return the position of the internal widget relative to this widget
|
||||
* @since 4.4
|
||||
*/
|
||||
void setVerticalScrollValue(qreal value);
|
||||
QPointF scrollPosition() const;
|
||||
|
||||
/**
|
||||
* The scrollable widget size.
|
||||
* @since 4.4
|
||||
*/
|
||||
QRectF viewport() const;
|
||||
|
||||
/**
|
||||
* Sets the stylesheet used to control the visual display of this ScrollWidget
|
||||
|
@ -134,82 +134,41 @@ QRectF WebView::geometry() const
|
||||
return QGraphicsWidget::geometry();
|
||||
}
|
||||
|
||||
qreal WebView::horizontalScrollValue() const
|
||||
QSizeF WebView::contentsSize() const
|
||||
{
|
||||
if (!d->page) {
|
||||
return 0;
|
||||
return QSizeF();
|
||||
} else {
|
||||
return d->page->mainFrame()->contentsSize();
|
||||
}
|
||||
|
||||
const qreal value = d->page->mainFrame()->contentsSize().width() -
|
||||
d->page->mainFrame()->geometry().width();
|
||||
|
||||
if(!value)
|
||||
return 0;
|
||||
|
||||
return ((d->page->mainFrame()->geometry().x()*100)/value);
|
||||
}
|
||||
|
||||
void WebView::setHorizontalScrollValue(qreal value)
|
||||
void WebView::setScrollPosition(const QPointF &position)
|
||||
{
|
||||
if (!d->page) {
|
||||
return;
|
||||
} else {
|
||||
d->page->mainFrame()->setScrollPosition(position.toPoint());
|
||||
}
|
||||
|
||||
qreal xValue = value * (d->page->mainFrame()->contentsSize().width() -
|
||||
d->page->mainFrame()->geometry().width())/100;
|
||||
|
||||
if (!xValue)
|
||||
xValue = 0;
|
||||
|
||||
d->page->mainFrame()->setScrollBarValue(Qt::Horizontal, xValue);
|
||||
}
|
||||
|
||||
qreal WebView::verticalScrollValue() const
|
||||
QPointF WebView::scrollPosition() const
|
||||
{
|
||||
if (!d->page) {
|
||||
return 0;
|
||||
return QPointF();
|
||||
} else {
|
||||
return d->page->mainFrame()->scrollPosition();
|
||||
}
|
||||
|
||||
const qreal value = d->page->mainFrame()->contentsSize().height() -
|
||||
d->page->mainFrame()->geometry().height();
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
return ((d->page->mainFrame()->scrollPosition().y()*100)/value);
|
||||
}
|
||||
|
||||
void WebView::setVerticalScrollValue(qreal value)
|
||||
{
|
||||
|
||||
if (!d->page) {
|
||||
return;
|
||||
}
|
||||
|
||||
qreal yValue = value *
|
||||
(d->page->mainFrame()->contentsSize().height() -
|
||||
d->page->mainFrame()->geometry().height())/100;
|
||||
|
||||
if (!yValue)
|
||||
yValue = 0;
|
||||
|
||||
const QPoint point(d->page->mainFrame()->scrollPosition().x(), yValue);
|
||||
|
||||
d->page->mainFrame()->setScrollPosition(point);
|
||||
}
|
||||
|
||||
QRectF WebView::viewport() const
|
||||
QRectF WebView::viewportGeometry() const
|
||||
{
|
||||
QRectF result;
|
||||
if (!d->page) {
|
||||
return result;
|
||||
} else {
|
||||
return d->page->mainFrame()->geometry();
|
||||
}
|
||||
|
||||
result.setWidth(d->page->mainFrame()->contentsSize().width());
|
||||
result.setHeight(d->page->mainFrame()->contentsSize().height());
|
||||
result.setHeight(d->page->mainFrame()->geometry().height()/result.height());
|
||||
result.setWidth(d->page->mainFrame()->geometry().width()/result.width());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,9 +50,9 @@ class PLASMA_EXPORT WebView : public QGraphicsWidget
|
||||
Q_PROPERTY(KUrl url READ url WRITE setUrl)
|
||||
Q_PROPERTY(QString html READ html WRITE setHtml)
|
||||
Q_PROPERTY(bool dragToScroll READ dragToScroll WRITE setDragToScroll)
|
||||
Q_PROPERTY(int horizontalScrollValue READ horizontalScrollValue WRITE setHorizontalScrollValue)
|
||||
Q_PROPERTY(int verticalScrollValue READ verticalScrollValue WRITE setVerticalScrollValue)
|
||||
Q_PROPERTY(QRectF viewport READ viewport)
|
||||
Q_PROPERTY(QPointF scrollPosition READ scrollPosition WRITE setScrollPosition)
|
||||
Q_PROPERTY(QSizeF contentsSize READ contentsSize)
|
||||
Q_PROPERTY(QRectF viewportGeometry READ viewportGeometry)
|
||||
|
||||
public:
|
||||
explicit WebView(QGraphicsItem *parent = 0);
|
||||
@ -97,35 +97,31 @@ class PLASMA_EXPORT WebView : public QGraphicsWidget
|
||||
* Reimplementation
|
||||
*/
|
||||
QRectF geometry() const;
|
||||
/**
|
||||
* The horizontal scroll value, between 0 and 100
|
||||
* @since 4.4
|
||||
*/
|
||||
qreal horizontalScrollValue() const;
|
||||
|
||||
/**
|
||||
* Set the horizontal scroll value, between 0 and 100
|
||||
* @return the size of the internal widget
|
||||
* @since 4.4
|
||||
*/
|
||||
void setHorizontalScrollValue(qreal value);
|
||||
QSizeF contentsSize() const;
|
||||
|
||||
/**
|
||||
* The horizontal scroll value, between 0 and 100
|
||||
* Sets the position of the webpage relative to this widget
|
||||
* @since 4.4
|
||||
*/
|
||||
qreal verticalScrollValue() const;
|
||||
void setScrollPosition(const QPointF &position);
|
||||
|
||||
/**
|
||||
* Set the horizontal scroll value, between 0 and 100
|
||||
* @return the position of the webpage relative to this widget
|
||||
* @since 4.4
|
||||
*/
|
||||
void setVerticalScrollValue(qreal value);
|
||||
QPointF scrollPosition() const;
|
||||
|
||||
/**
|
||||
* The scrollable widget size.
|
||||
* The geometry of the area that actually displays the web page
|
||||
* @since 4.4
|
||||
*/
|
||||
QRectF viewport() const;
|
||||
QRectF viewportGeometry() const;
|
||||
|
||||
/**
|
||||
* Sets the page to use in this item. The owner of the webpage remains,
|
||||
* however if this WebView object is the owner of the current page,
|
||||
|
Loading…
x
Reference in New Issue
Block a user