Improve the hit testing of an interactive PageIndicator

The Universal style has relatively large spacing between the dots.
The small dots are hard to hit => select the nearest dot.

Change-Id: I2207e887706be38c1a6091bd8aca13d26b9957a8
Reviewed-by: Mitch Curtis <mitch.curtis@theqtcompany.com>
This commit is contained in:
J-P Nurmi 2015-10-30 16:40:07 +01:00
parent 304cf22b96
commit 2ee0e8770b
2 changed files with 46 additions and 4 deletions

View File

@ -37,6 +37,8 @@
#include "qquickpageindicator_p.h"
#include "qquickcontrol_p_p.h"
#include <QtCore/qmath.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickitemchangelistener_p.h>
QT_BEGIN_NAMESPACE
@ -86,11 +88,33 @@ public:
QQuickItem *QQuickPageIndicatorPrivate::itemAt(const QPoint &pos) const
{
Q_Q(const QQuickPageIndicator);
if (contentItem) {
QPointF mapped = q->mapToItem(contentItem, pos);
return contentItem->childAt(mapped.x(), mapped.y());
if (!contentItem || !q->contains(pos))
return Q_NULLPTR;
QPointF contentPos = q->mapToItem(contentItem, pos);
QQuickItem *item = contentItem->childAt(contentPos.x(), contentPos.y());
while (item && item->parentItem() != contentItem)
item = item->parentItem();
if (item && !QQuickItemPrivate::get(item)->isTransparentForPositioner())
return item;
// find the nearest
qreal distance = qInf();
QQuickItem *nearest = Q_NULLPTR;
foreach (QQuickItem *child, contentItem->childItems()) {
if (QQuickItemPrivate::get(child)->isTransparentForPositioner())
continue;
QPointF center = child->boundingRect().center();
QPointF pt = contentItem->mapToItem(child, contentPos);
qreal len = QLineF(center, pt).length();
if (len < distance) {
distance = len;
nearest = child;
}
}
return Q_NULLPTR;
return nearest;
}
void QQuickPageIndicatorPrivate::updatePressed(bool pressed, const QPoint &pos)

View File

@ -93,6 +93,24 @@ TestCase {
mouseClick(control, control.width / 2, control.height / 2, Qt.LeftButton)
compare(control.currentIndex, 2)
// test also clicking outside delegates => the nearest should be selected
control.padding = 10
control.spacing = 10
for (var i = 0; i < control.count; ++i) {
var child = control.contentItem.children[i]
for (var x = -2; x <= child.width + 2; ++x) {
for (var y = -2; y <= child.height + 2; ++y) {
control.currentIndex = -1
compare(control.currentIndex, -1)
var pos = control.mapFromItem(child, x, y)
mouseClick(control, pos.x, pos.y, Qt.LeftButton)
compare(control.currentIndex, i)
}
}
}
control.destroy()
}
}