aboutsummaryrefslogtreecommitdiffstats
path: root/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qtquick1/graphicsitems/qdeclarativelistview.cpp')
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativelistview.cpp150
1 files changed, 89 insertions, 61 deletions
diff --git a/src/qtquick1/graphicsitems/qdeclarativelistview.cpp b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
index 5119c0e1fb..7b9cb12e90 100644
--- a/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
@@ -52,10 +52,13 @@
#include <qmath.h>
#include <QKeyEvent>
+#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE
-
+#ifndef QML_FLICK_SNAPONETHRESHOLD
+#define QML_FLICK_SNAPONETHRESHOLD 30
+#endif
void QDeclarative1ViewSection::setProperty(const QString &property)
{
@@ -235,21 +238,6 @@ public:
return visibleItems.count() ? visibleItems.first() : 0;
}
- FxListItem1 *nextVisibleItem() const {
- const qreal pos = isRightToLeft() ? -position()-size() : position();
- bool foundFirst = false;
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxListItem1 *item = visibleItems.at(i);
- if (item->index != -1) {
- if (foundFirst)
- return item;
- else if (item->position() < pos && item->endPosition() > pos)
- foundFirst = true;
- }
- }
- return 0;
- }
-
// Returns the item before modelIndex, if created.
// May return an item marked for removal.
FxListItem1 *itemBefore(int modelIndex) const {
@@ -1013,7 +1001,7 @@ void QDeclarative1ListViewPrivate::updateHighlight()
{
if ((!currentItem && highlight) || (currentItem && !highlight))
createHighlight();
- if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
+ if (currentItem && autoHighlight && highlight && !hData.moving && !vData.moving) {
// auto-update highlight
highlightPosAnimator->to = isRightToLeft()
? -currentItem->itemPosition()-currentItem->itemSize()
@@ -1308,6 +1296,7 @@ void QDeclarative1ListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal
correctFlick = false;
fixupMode = moveReason == Mouse ? fixupMode : Immediate;
+ bool strictHighlightRange = haveHighlightRange && highlightRange == QDeclarative1ListView::StrictlyEnforceRange;
qreal highlightStart;
qreal highlightEnd;
@@ -1323,35 +1312,36 @@ void QDeclarative1ListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal
highlightEnd = highlightRangeEnd;
}
- if (currentItem && haveHighlightRange && highlightRange == QDeclarative1ListView::StrictlyEnforceRange
- && moveReason != QDeclarative1ListViewPrivate::SetIndex) {
- updateHighlight();
- qreal pos = currentItem->itemPosition();
- if (viewPos < pos + currentItem->itemSize() - highlightEnd)
- viewPos = pos + currentItem->itemSize() - highlightEnd;
- if (viewPos > pos - highlightStart)
- viewPos = pos - highlightStart;
- if (isRightToLeft())
- viewPos = -viewPos-size();
-
- timeline.reset(data.move);
- if (viewPos != position()) {
- if (fixupMode != Immediate) {
- timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
- data.fixingUp = true;
- } else {
- timeline.set(data.move, -viewPos);
- }
- }
- vTime = timeline.time();
- } else if (snapMode != QDeclarative1ListView::NoSnap && moveReason != QDeclarative1ListViewPrivate::SetIndex) {
+ if (snapMode != QDeclarative1ListView::NoSnap && moveReason != QDeclarative1ListViewPrivate::SetIndex) {
qreal tempPosition = isRightToLeft() ? -position()-size() : position();
+ if (snapMode == QDeclarative1ListView::SnapOneItem && moveReason == Mouse) {
+ // if we've been dragged < averageSize/2 then bias towards the next item
+ qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal bias = 0;
+ if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < averageSize/2)
+ bias = averageSize/2;
+ else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -averageSize/2)
+ bias = -averageSize/2;
+ if (isRightToLeft())
+ bias = -bias;
+ tempPosition -= bias;
+ }
FxListItem1 *topItem = snapItemAt(tempPosition+highlightStart);
+ if (!topItem && strictHighlightRange && currentItem) {
+ // StrictlyEnforceRange always keeps an item in range
+ updateHighlight();
+ topItem = currentItem;
+ }
FxListItem1 *bottomItem = snapItemAt(tempPosition+highlightEnd);
+ if (!bottomItem && strictHighlightRange && currentItem) {
+ // StrictlyEnforceRange always keeps an item in range
+ updateHighlight();
+ bottomItem = currentItem;
+ }
qreal pos;
- bool isInBounds = -position() > maxExtent && -position() < minExtent;
- if (topItem && isInBounds) {
- if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2) {
+ bool isInBounds = -position() > maxExtent && -position() <= minExtent;
+ if (topItem && (isInBounds || strictHighlightRange)) {
+ if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2 && !strictHighlightRange) {
pos = isRightToLeft() ? - header->position() + highlightStart - size() : header->position() - highlightStart;
} else {
if (isRightToLeft())
@@ -1361,9 +1351,9 @@ void QDeclarative1ListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal
}
} else if (bottomItem && isInBounds) {
if (isRightToLeft())
- pos = qMax(qMin(-bottomItem->position() + highlightStart - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-bottomItem->position() + highlightEnd - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent);
+ pos = qMax(qMin(bottomItem->position() - highlightEnd, -maxExtent), -minExtent);
} else {
QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
return;
@@ -1380,6 +1370,27 @@ void QDeclarative1ListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal
}
vTime = timeline.time();
}
+ } else if (currentItem && strictHighlightRange
+ && moveReason != QDeclarative1ListViewPrivate::SetIndex) {
+ updateHighlight();
+ qreal pos = currentItem->itemPosition();
+ if (viewPos < pos + currentItem->itemSize() - highlightEnd)
+ viewPos = pos + currentItem->itemSize() - highlightEnd;
+ if (viewPos > pos - highlightStart)
+ viewPos = pos - highlightStart;
+ if (isRightToLeft())
+ viewPos = -viewPos-size();
+
+ timeline.reset(data.move);
+ if (viewPos != position()) {
+ if (fixupMode != Immediate) {
+ timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ data.fixingUp = true;
+ } else {
+ timeline.set(data.move, -viewPos);
+ }
+ }
+ vTime = timeline.time();
} else {
QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
}
@@ -1401,12 +1412,19 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal
}
qreal maxDistance = 0;
qreal dataValue = isRightToLeft() ? -data.move.value()+size() : data.move.value();
+ qreal highlightStart = isRightToLeft() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
// -ve velocity means list is moving up/left
if (velocity > 0) {
if (data.move.value() < minExtent) {
- if (snapMode == QDeclarative1ListView::SnapOneItem) {
- if (FxListItem1 *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem())
- maxDistance = qAbs(item->position() + dataValue);
+ if (snapMode == QDeclarative1ListView::SnapOneItem && !hData.flicking && !vData.flicking) {
+ // if we've been dragged < averageSize/2 then bias towards the next item
+ qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal bias = dist < averageSize/2 ? averageSize/2 : 0;
+ if (isRightToLeft())
+ bias = -bias;
+ data.flickTarget = -snapPosAt(-(dataValue - highlightStart) - bias) + highlightStart;
+ maxDistance = qAbs(data.flickTarget - data.move.value());
+ velocity = maxVelocity;
} else {
maxDistance = qAbs(minExtent - data.move.value());
}
@@ -1415,9 +1433,15 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal
data.flickTarget = minExtent;
} else {
if (data.move.value() > maxExtent) {
- if (snapMode == QDeclarative1ListView::SnapOneItem) {
- if (FxListItem1 *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem())
- maxDistance = qAbs(item->position() + dataValue);
+ if (snapMode == QDeclarative1ListView::SnapOneItem && !hData.flicking && !vData.flicking) {
+ // if we've been dragged < averageSize/2 then bias towards the next item
+ qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal bias = -dist < averageSize/2 ? averageSize/2 : 0;
+ if (isRightToLeft())
+ bias = -bias;
+ data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + bias) + highlightStart;
+ maxDistance = qAbs(data.flickTarget - data.move.value());
+ velocity = -maxVelocity;
} else {
maxDistance = qAbs(maxExtent - data.move.value());
}
@@ -1427,7 +1451,6 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal
}
bool overShoot = boundsBehavior == QDeclarative1Flickable::DragAndOvershootBounds;
- qreal highlightStart = isRightToLeft() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
if (maxDistance > 0 || overShoot) {
// These modes require the list to stop exactly on an item boundary.
@@ -1441,7 +1464,7 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal
else
v = maxVelocity;
}
- if (!flickingHorizontally && !flickingVertically) {
+ if (!hData.flicking && !vData.flicking) {
// the initial flick - estimate boundary
qreal accel = deceleration;
qreal v2 = v * v;
@@ -1453,8 +1476,10 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal
if (v > 0)
dist = -dist;
if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarative1ListView::SnapOneItem) {
- qreal distTemp = isRightToLeft() ? -dist : dist;
- data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart;
+ if (snapMode != QDeclarative1ListView::SnapOneItem) {
+ qreal distTemp = isRightToLeft() ? -dist : dist;
+ data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart;
+ }
data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
if (overShoot) {
if (data.flickTarget >= minExtent) {
@@ -1492,14 +1517,14 @@ void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal
timeline.reset(data.move);
timeline.accel(data.move, v, accel, maxDistance + overshootDist);
timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this));
- if (!flickingHorizontally && q->xflick()) {
- flickingHorizontally = true;
+ if (!hData.flicking && q->xflick()) {
+ hData.flicking = true;
emit q->flickingChanged();
emit q->flickingHorizontallyChanged();
emit q->flickStarted();
}
- if (!flickingVertically && q->yflick()) {
- flickingVertically = true;
+ if (!vData.flicking && q->yflick()) {
+ vData.flicking = true;
emit q->flickingChanged();
emit q->flickingVerticallyChanged();
emit q->flickStarted();
@@ -1876,6 +1901,8 @@ void QDeclarative1ListView::setCurrentIndex(int index)
if (index == d->currentIndex)
return;
if (isComponentComplete() && d->isValid()) {
+ if (d->layoutScheduled)
+ d->layout();
d->moveReason = QDeclarative1ListViewPrivate::SetIndex;
d->updateCurrent(index);
} else if (d->currentIndex != index) {
@@ -2568,7 +2595,8 @@ bool QDeclarative1ListView::event(QEvent *event)
{
Q_D(QDeclarative1ListView);
if (event->type() == QEvent::User) {
- d->layout();
+ if (d->layoutScheduled)
+ d->layout();
return true;
}
@@ -2587,7 +2615,7 @@ void QDeclarative1ListView::viewportMoved()
d->inViewportMoved = true;
d->lazyRelease = true;
refill();
- if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
+ if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
d->moveReason = QDeclarative1ListViewPrivate::Mouse;
if (d->moveReason != QDeclarative1ListViewPrivate::SetIndex) {
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
@@ -2621,7 +2649,7 @@ void QDeclarative1ListView::viewportMoved()
}
}
- if ((d->flickingHorizontally || d->flickingVertically) && d->correctFlick && !d->inFlickCorrection) {
+ if ((d->hData.flicking || d->vData.flicking) && d->correctFlick && !d->inFlickCorrection) {
d->inFlickCorrection = true;
// Near an end and it seems that the extent has changed?
// Recalculate the flick so that we don't end up in an odd position.