Merge lp:~zsombi/ubuntu-ui-toolkit/increasedSensingArea into lp:ubuntu-ui-toolkit/staging

Proposed by Zsombor Egri
Status: Merged
Approved by: Tim Peeters
Approved revision: 1731
Merged at revision: 1866
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/increasedSensingArea
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 565 lines (+375/-0)
8 files modified
components.api (+7/-0)
src/Ubuntu/Components/plugin/plugin.cpp (+1/-0)
src/Ubuntu/Components/plugin/plugin.pri (+1/-0)
src/Ubuntu/Components/plugin/ucabstractbutton.cpp (+135/-0)
src/Ubuntu/Components/plugin/ucabstractbutton.h (+9/-0)
src/Ubuntu/Components/plugin/ucabstractbutton_p.h (+2/-0)
src/Ubuntu/Components/plugin/ucmargins.h (+76/-0)
tests/unit_x11/tst_components/tst_abstractbutton13.qml (+144/-0)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/increasedSensingArea
Reviewer Review Type Date Requested Status
ubuntu-sdk-build-bot continuous-integration Approve
Tim Peeters Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+277450@code.launchpad.net

Commit message

AbstractButton handles 4x4GU minimal sensing area, exposes sensingMargins to extend sensing area even further.

To post a comment you must log in.
Revision history for this message
Andrea Bernabei (faenil) wrote :

left some comments :)

Revision history for this message
Zsombor Egri (zsombi) wrote :

> left some comments :)

See my replies inline.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> > left some comments :)
>
> See my replies inline.

Ehm... seems the comments got vanished :/

Anyways, the comments were applied, see below, except the 8mm not being 4GU, we measured it, it is approximately 4GU everywhere. Remember, the GU is chosen to show the same size everywhere. And N10 is NOT (and I really mean it!!!!) 90 GU for sure! N7 is, but N10 is NOT. Please!!! It's like Bq and Meizu having the same GU width/height!!! Forget that, it's bullshit!!!

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

         function cleanup() {
417 + buttonWithSensing.sensingMargins.left =
418 + buttonWithSensing.sensingMargins.top =
419 + buttonWithSensing.sensingMargins.right =
420 + buttonWithSensing.sensingMargins.bottom =
421 + buttonWithSensing.sensingMargins.all = 0;
422 + buttonWithSensing.width = 0;
423 + buttonWithSensing.height = 0;
424 + signalSpy.target = absButton;

I suggest to use some indentation here to make it not misleading for a human reader.

Revision history for this message
Tim Peeters (tpeeters) wrote :

^or add 0; to each line.

Revision history for this message
Tim Peeters (tpeeters) wrote :

There is no unit test for:
1. Negative sensing margins
2. Initializing a component with sensor margins (without setting them in JS afterwards)

review: Needs Fixing
Revision history for this message
Zsombor Egri (zsombi) wrote :

> There is no unit test for:
> 1. Negative sensing margins

This makes sense. Will add a test case for that!

> 2. Initializing a component with sensor margins (without setting them in JS
> afterwards)

What is the difference? They both call the setters...

1728. By Zsombor Egri

more tests added

1729. By Zsombor Egri

getting branch head in sync

Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
1730. By Zsombor Egri

roll back a floating change

1731. By Zsombor Egri

staging sync

Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

Looks good, thanks.

review: Approve
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'components.api'
2--- components.api 2016-02-17 12:57:49 +0000
3+++ components.api 2016-02-24 06:31:56 +0000
4@@ -8,6 +8,7 @@
5 signal clicked()
6 signal pressAndHold()
7 readonly property bool pressed
8+ readonly property UCMargins sensingMargins
9 Ubuntu.Components.Action 1.3 1.0 0.1 UCAction: QtObject
10 property string description
11 property bool enabled
12@@ -1557,6 +1558,12 @@
13 UCListItemExpansion: QtObject
14 property bool expanded
15 property double height
16+UCMargins: QtObject
17+ property double all
18+ property double bottom
19+ property double left
20+ property double right
21+ property double top
22 UCStateSaverAttached: QtObject
23 property bool enabled
24 property string properties
25
26=== modified file 'src/Ubuntu/Components/plugin/plugin.cpp'
27--- src/Ubuntu/Components/plugin/plugin.cpp 2016-02-12 13:46:51 +0000
28+++ src/Ubuntu/Components/plugin/plugin.cpp 2016-02-24 06:31:56 +0000
29@@ -222,6 +222,7 @@
30 qmlRegisterType<UCProportionalShape>(uri, 1, 3, "ProportionalShape");
31 qmlRegisterType<LiveTimer>(uri, 1, 3, "LiveTimer");
32 qmlRegisterType<UCAbstractButton>(uri, 1, 3, "AbstractButton");
33+ qmlRegisterType<UCMargins>();
34 qmlRegisterUncreatableType<UCSlotsAttached>(uri, 1, 3, "SlotsAttached", "Not instantiable");
35 qmlRegisterUncreatableType<UCSlotsLayoutPadding>(uri, 1, 3, "SlotsLayoutPadding", "Not instantiable");
36 qmlRegisterType<UCListItemLayout>(uri, 1, 3, "ListItemLayout");
37
38=== modified file 'src/Ubuntu/Components/plugin/plugin.pri'
39--- src/Ubuntu/Components/plugin/plugin.pri 2016-02-08 12:47:32 +0000
40+++ src/Ubuntu/Components/plugin/plugin.pri 2016-02-24 06:31:56 +0000
41@@ -90,6 +90,7 @@
42 $$PWD/uchaptics.h \
43 $$PWD/ucabstractbutton.h \
44 $$PWD/ucabstractbutton_p.h \
45+ $$PWD/ucmargins.h \
46 $$PWD/ucthemingextension.h \
47 $$PWD/ucheader.h \
48 $$PWD/uclabel.h \
49
50=== modified file 'src/Ubuntu/Components/plugin/ucabstractbutton.cpp'
51--- src/Ubuntu/Components/plugin/ucabstractbutton.cpp 2016-02-11 08:54:26 +0000
52+++ src/Ubuntu/Components/plugin/ucabstractbutton.cpp 2016-02-24 06:31:56 +0000
53@@ -17,11 +17,15 @@
54 #include "ucabstractbutton.h"
55 #include "ucabstractbutton_p.h"
56 #include "uchaptics.h"
57+#include "ucunits.h"
58 #include "ucaction.h"
59 #include <QtQuick/private/qquickitem_p.h>
60 #include <QtQuick/private/qquickmousearea_p.h>
61 #include <QtQml/private/qqmlglobal_p.h>
62
63+#define MIN_SENSING_WIDTH_GU 4
64+#define MIN_SENSING_HEIGHT_GU 4
65+
66 UCAbstractButtonPrivate::UCAbstractButtonPrivate()
67 : UCActionItemPrivate()
68 , mouseArea(new QQuickMouseArea)
69@@ -39,6 +43,7 @@
70 /*!
71 \qmltype AbstractButton
72 \instantiates UCAbstractButton
73+ \inherits ActionItem
74 \inqmlmodule Ubuntu.Components 1.1
75 \ingroup ubuntu
76 \brief The AbstractButton class defines the behavior of the button.
77@@ -49,6 +54,34 @@
78 If an action is specified, the button's clicked signal will trigger the action.
79 Subclasses of AbstractButton can use other properties of action (for example
80 the text and iconName).
81+
82+ \section2 Sensing area
83+ It has been proven that, on touch devices in order to properly aim an active
84+ component a minimum of 8x8 millimeters (i.e. 4x4 grid units) area has to be
85+ provided. However not all the visuals are of that size, as Icons for example
86+ are defaulted to be 2x2 grid units, but a component containing a single Icon
87+ still has to be able to capture the press events. Therefore AbstractButton
88+ makes sure this rule of 4x4 grid units for the sensing area is provided. In
89+ addition it exposes the \l sensingMargins property which extends the component's
90+ sensing area in all the directions, so other use cases when the sensing area
91+ needs to be extended outside of the component's area, or restricted on a
92+ given area of the component can be implemented. The following example extends
93+ the sensing area on the left, top and bottom with 1 grid units, and on the
94+ right with 10 grid units.
95+ \qml
96+ AbstractButton {
97+ width: units.gu(2)
98+ height: units.gu(2)
99+ sensingMargins {
100+ left: units.gu(1)
101+ top: units.gu(1)
102+ bottom: units.gu(1)
103+ right: units.gu(10)
104+ }
105+ }
106+ \endqml
107+ \note Do not set clipping for the component as that will restrict the sensing
108+ area to be available on the visual area only.
109 */
110
111 /*!
112@@ -111,6 +144,9 @@
113 UCActionItemPrivate::completeComponentInitialization();
114 Q_Q(UCAbstractButton);
115
116+ // adjust sensing area
117+ _q_adjustSensingArea();
118+
119 // bind mouse area
120 QObject::connect(mouseArea, &QQuickMouseArea::pressedChanged, q, &UCAbstractButton::pressedChanged);
121 QObject::connect(mouseArea, &QQuickMouseArea::hoveredChanged, q, &UCAbstractButton::hoveredChanged);
122@@ -122,6 +158,9 @@
123 // may not be available on compoennt completion
124 void UCAbstractButtonPrivate::_q_mouseAreaPressed()
125 {
126+ if (!mouseArea->pressed()) {
127+ return;
128+ }
129 bool longPressConnected = isPressAndHoldConnected();
130 Q_Q(UCAbstractButton);
131 if (longPressConnected && !pressAndHoldConnected) {
132@@ -175,6 +214,48 @@
133 }
134 }
135
136+void UCAbstractButtonPrivate::_q_adjustSensingArea()
137+{
138+ Q_Q(UCAbstractButton);
139+ if (!componentComplete) {
140+ // we do not hammer the component until completion
141+ return;
142+ }
143+ // use the sensingMargins in the minimum calculation
144+ qreal minimumWidth = UCUnits::instance()->gu(MIN_SENSING_WIDTH_GU);
145+ qreal minimumHeight = UCUnits::instance()->gu(MIN_SENSING_HEIGHT_GU);
146+ qreal hDelta = minimumWidth
147+ - (q->width() + (sensingMargins ? (sensingMargins->left() + sensingMargins->right()) : 0.0));
148+ qreal vDelta = minimumHeight
149+ - (q->height() + (sensingMargins ? (sensingMargins->top() + sensingMargins->bottom()) : 0.0));
150+ // adjust the sensing area
151+ QQuickAnchors *mouseAreaAnchors = QQuickItemPrivate::get(mouseArea)->anchors();
152+ if (hDelta >= 0) {
153+ // the horizontal size is still smaller than the minimum
154+ mouseAreaAnchors->setLeftMargin(-(hDelta / 2 + (sensingMargins ? sensingMargins->left() : 0.0)));
155+ mouseAreaAnchors->setRightMargin(-(hDelta / 2 + (sensingMargins ? sensingMargins->right() : 0.0)));
156+ } else if (sensingMargins) {
157+ mouseAreaAnchors->setLeftMargin(-sensingMargins->left());
158+ mouseAreaAnchors->setRightMargin(-sensingMargins->right());
159+ }
160+ if (vDelta >= 0) {
161+ // the vertical size is still smaller than the minimum
162+ mouseAreaAnchors->setTopMargin(-(vDelta / 2 + (sensingMargins ? sensingMargins->top() : 0.0)));
163+ mouseAreaAnchors->setBottomMargin(-(vDelta / 2 + (sensingMargins ? sensingMargins->bottom() : 0.0)));
164+ } else if (sensingMargins) {
165+ mouseAreaAnchors->setTopMargin(-sensingMargins->top());
166+ mouseAreaAnchors->setBottomMargin(-sensingMargins->bottom());
167+ }
168+}
169+
170+void UCAbstractButton::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
171+{
172+ UCActionItem::geometryChanged(newGeometry, oldGeometry);
173+
174+ // adjust internal mouse area's size
175+ d_func()->_q_adjustSensingArea();
176+}
177+
178 /*!
179 * \qmlproperty bool AbstractButton::pressed
180 * True if the user presses a mouse button in the button's mouse area.
181@@ -212,4 +293,58 @@
182 return d->mouseArea;
183 }
184
185+/*!
186+ * \qmlpropertygroup ::AbstractButton::sensingMargins
187+ * \qmlproperty real AbstractButton::sensingMargins.left
188+ * \qmlproperty real AbstractButton::sensingMargins.right
189+ * \qmlproperty real AbstractButton::sensingMargins.top
190+ * \qmlproperty real AbstractButton::sensingMargins.bottom
191+ * \qmlproperty real AbstractButton::sensingMargins.all
192+ * The property group specifies the margins extending the visual area where the
193+ * touch and mouse events are sensed. Positive values mean the area will be extended
194+ * on the specified direction outside of the visual area, negative values mean
195+ * the sensing will fall under the component's visual border.
196+ * All values default to 0.
197+ *
198+ * \note If the visual area and the sensing margins are not reaching the 4x4 grid
199+ * units limit, the component will fall back to these minimum limits.
200+ * For example, extending a 2x2 grid unit visual component into 5x4 grid units
201+ * sensing area would look as follows:
202+ * \qml
203+ * AbstractButton {
204+ * width: units.gu(2)
205+ * height: units.gu(2)
206+ * Icon {
207+ * name: "settings"
208+ * }
209+ * sensingArea {
210+ * // no need to set the vertical direction as the minimum of
211+ * // 4 grid units will be taken automatically
212+ * leftMargin: units.gu(1)
213+ * // we only have to add 2 grid units as the width + left margin
214+ * // already gives us 3 grid units out of 5
215+ * rightMargin: units.gu(2)
216+ * }
217+ * }
218+ * \endqml
219+ */
220+UCMargins *UCAbstractButton::sensingMargins()
221+{
222+ Q_D(UCAbstractButton);
223+ if (!d->sensingMargins) {
224+ d->sensingMargins = new UCMargins(this);
225+
226+ // as this is the first time we create the sensing margins we only
227+ // connect now to grid unit changes to keep sensing area size in sync
228+ connect(UCUnits::instance(), SIGNAL(gridUnitChanged()), this, SLOT(_q_adjustSensingArea()));
229+ // also connect to the margin changes
230+ connect(d->sensingMargins, SIGNAL(leftChanged()), this, SLOT(_q_adjustSensingArea()));
231+ connect(d->sensingMargins, SIGNAL(rightChanged()), this, SLOT(_q_adjustSensingArea()));
232+ connect(d->sensingMargins, SIGNAL(topChanged()), this, SLOT(_q_adjustSensingArea()));
233+ connect(d->sensingMargins, SIGNAL(bottomChanged()), this, SLOT(_q_adjustSensingArea()));
234+ connect(d->sensingMargins, SIGNAL(allChanged()), this, SLOT(_q_adjustSensingArea()));
235+ }
236+ return d->sensingMargins;
237+}
238+
239 #include "moc_ucabstractbutton.cpp"
240
241=== modified file 'src/Ubuntu/Components/plugin/ucabstractbutton.h'
242--- src/Ubuntu/Components/plugin/ucabstractbutton.h 2015-12-17 13:00:10 +0000
243+++ src/Ubuntu/Components/plugin/ucabstractbutton.h 2016-02-24 06:31:56 +0000
244@@ -18,6 +18,8 @@
245 #define UCABSTRACTBUTTON_H
246
247 #include "ucactionitem.h"
248+#include "ucmargins.h"
249+#include <QtQuick/private/qquickevents_p_p.h>
250
251 class QQuickMouseArea;
252 class QQuickMouseEvent;
253@@ -27,6 +29,7 @@
254 Q_OBJECT
255 Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
256 Q_PROPERTY(bool hovered READ hovered NOTIFY hoveredChanged)
257+ Q_PROPERTY(UCMargins *sensingMargins READ sensingMargins CONSTANT FINAL)
258
259 // internal, declared to support the deprecated ListItem module
260 Q_PROPERTY(bool __acceptEvents READ acceptEvents WRITE setAcceptEvents)
261@@ -36,6 +39,7 @@
262
263 bool pressed() const;
264 bool hovered() const;
265+ UCMargins *sensingMargins();
266
267 bool privateAcceptEvents() const;
268 void setPrivateAcceptEvents(bool accept);
269@@ -45,6 +49,8 @@
270
271 protected:
272 void classBegin();
273+ virtual void geometryChanged(const QRectF &newGeometry,
274+ const QRectF &oldGeometry);
275 void keyReleaseEvent(QKeyEvent *key);
276
277 Q_SIGNALS:
278@@ -60,6 +66,9 @@
279 Q_PRIVATE_SLOT(d_func(), void _q_mouseAreaPressed())
280 Q_PRIVATE_SLOT(d_func(), void _q_mouseAreaClicked())
281 Q_PRIVATE_SLOT(d_func(), void _q_mouseAreaPressAndHold())
282+ Q_PRIVATE_SLOT(d_func(), void _q_adjustSensingArea())
283 };
284
285+QML_DECLARE_TYPE(UCMargins)
286+
287 #endif // UCABSTRACTBUTTON_H
288
289=== modified file 'src/Ubuntu/Components/plugin/ucabstractbutton_p.h'
290--- src/Ubuntu/Components/plugin/ucabstractbutton_p.h 2015-12-17 13:00:10 +0000
291+++ src/Ubuntu/Components/plugin/ucabstractbutton_p.h 2016-02-24 06:31:56 +0000
292@@ -41,8 +41,10 @@
293 void _q_mouseAreaPressed();
294 void _q_mouseAreaClicked();
295 void _q_mouseAreaPressAndHold();
296+ void _q_adjustSensingArea();
297
298 QQuickMouseArea *mouseArea;
299+ UCMargins *sensingMargins = nullptr;
300 bool acceptEvents:1;
301 bool pressAndHoldConnected:1;
302 };
303
304=== added file 'src/Ubuntu/Components/plugin/ucmargins.h'
305--- src/Ubuntu/Components/plugin/ucmargins.h 1970-01-01 00:00:00 +0000
306+++ src/Ubuntu/Components/plugin/ucmargins.h 2016-02-24 06:31:56 +0000
307@@ -0,0 +1,76 @@
308+/*
309+ * Copyright 2015 Canonical Ltd.
310+ *
311+ * This program is free software; you can redistribute it and/or modify
312+ * it under the terms of the GNU Lesser General Public License as published by
313+ * the Free Software Foundation; version 3.
314+ *
315+ * This program is distributed in the hope that it will be useful,
316+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
317+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
318+ * GNU Lesser General Public License for more details.
319+ *
320+ * You should have received a copy of the GNU Lesser General Public License
321+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
322+ */
323+
324+#ifndef UCMARGINS_H
325+#define UCMARGINS_H
326+
327+#include <QtCore/QObject>
328+#include <QtQuick/QQuickItem>
329+
330+class UCMargins : public QObject
331+{
332+ Q_OBJECT
333+ Q_PROPERTY(qreal left MEMBER m_left NOTIFY leftChanged FINAL)
334+ Q_PROPERTY(qreal top MEMBER m_top NOTIFY topChanged FINAL)
335+ Q_PROPERTY(qreal right MEMBER m_right NOTIFY rightChanged FINAL)
336+ Q_PROPERTY(qreal bottom MEMBER m_bottom NOTIFY bottomChanged FINAL)
337+ Q_PROPERTY(qreal all MEMBER m_all NOTIFY allChanged FINAL)
338+public:
339+ UCMargins(QObject *parent = 0);
340+
341+ qreal left() const;
342+ qreal top() const;
343+ qreal right() const;
344+ qreal bottom() const;
345+
346+Q_SIGNALS:
347+ void leftChanged();
348+ void topChanged();
349+ void rightChanged();
350+ void bottomChanged();
351+ void allChanged();
352+
353+private:
354+ qreal m_left = 0.0;
355+ qreal m_top = 0.0;
356+ qreal m_right = 0.0;
357+ qreal m_bottom = 0.0;
358+ qreal m_all = 0.0;
359+};
360+
361+inline UCMargins::UCMargins(QObject *parent) : QObject(parent) {}
362+
363+inline qreal UCMargins::left() const
364+{
365+ return qFuzzyIsNull(m_left) ? m_all : m_left;
366+}
367+
368+inline qreal UCMargins::top() const
369+{
370+ return qFuzzyIsNull(m_top) ? m_all : m_top;
371+}
372+
373+inline qreal UCMargins::right() const
374+{
375+ return qFuzzyIsNull(m_right) ? m_all : m_right;
376+}
377+
378+inline qreal UCMargins::bottom() const
379+{
380+ return qFuzzyIsNull(m_bottom) ? m_all : m_bottom;
381+}
382+
383+#endif // UCMARGINS_H
384
385=== modified file 'tests/unit_x11/tst_components/tst_abstractbutton13.qml'
386--- tests/unit_x11/tst_components/tst_abstractbutton13.qml 2015-12-12 07:22:08 +0000
387+++ tests/unit_x11/tst_components/tst_abstractbutton13.qml 2016-02-24 06:31:56 +0000
388@@ -41,6 +41,41 @@
389 height: width
390 function trigger() {}
391 }
392+ Item {
393+ // have enough space for the test subject
394+ width: units.gu(10)
395+ height: units.gu(10)
396+ AbstractButton {
397+ id: buttonWithSensing
398+ anchors.centerIn: parent
399+ }
400+ }
401+ Rectangle {
402+ color: "red"
403+ width: units.gu(10)
404+ height: units.gu(10)
405+ AbstractButton {
406+ id: increasedSensing
407+ anchors.centerIn: parent
408+ width: units.gu(4)
409+ height: units.gu(4)
410+ sensingMargins {
411+ left: units.gu(2)
412+ right: units.gu(2)
413+ top: units.gu(2)
414+ bottom: units.gu(2)
415+ }
416+ style: Item {
417+ anchors.fill: parent
418+ Rectangle {
419+ color: "blue"
420+ parent: styledItem.__mouseArea
421+ anchors.fill: parent
422+ }
423+ }
424+ }
425+ }
426+
427 AbstractButton {
428 id: suppressTrigger2
429 width: units.gu(10)
430@@ -53,6 +88,7 @@
431 height: width
432 function trigger(v) { triggered(v) }
433 }
434+
435 Loader {
436 id: loader
437 width: units.gu(10)
438@@ -103,6 +139,14 @@
439 when: windowShown
440
441 function cleanup() {
442+ buttonWithSensing.sensingMargins.left = 0;
443+ buttonWithSensing.sensingMargins.top = 0;
444+ buttonWithSensing.sensingMargins.right = 0;
445+ buttonWithSensing.sensingMargins.bottom = 0;
446+ buttonWithSensing.sensingMargins.all = 0;
447+ buttonWithSensing.width = 0;
448+ buttonWithSensing.height = 0;
449+ signalSpy.target = absButton;
450 signalSpy.clear();
451 signalSpy.target = absButton;
452 triggeredSpy.clear();
453@@ -110,6 +154,14 @@
454 loader.longPress = false;
455 }
456
457+ function initTestCase() {
458+ compare(buttonWithSensing.sensingMargins.left, 0);
459+ compare(buttonWithSensing.sensingMargins.right, 0);
460+ compare(buttonWithSensing.sensingMargins.top, 0);
461+ compare(buttonWithSensing.sensingMargins.bottom, 0);
462+ compare(buttonWithSensing.sensingMargins.all, 0);
463+ }
464+
465 function test_action() {
466 compare(absButton.action, null,"Action is null by default")
467 absButton.action = action1
468@@ -184,5 +236,97 @@
469 mouseClick(loader.item, centerOf(loader.item).x, centerOf(loader.item).y);
470 compare(loader.click, true, "clicked not captured by Connection");
471 }
472+
473+ function test_sensing_area_data() {
474+ return [
475+ // margins is [left, top, right, bottom]
476+ {tag: "zero size, no margins, click in visual", sizeGU: [0, 0], clickGU: [0, 0], sensingGU: [4, 4]},
477+ {tag: "zero size, no margins, click in sensing", sizeGU: [0, 0], clickGU: [4, 4], sensingGU: [4, 4]},
478+ {tag: "zero size, 1GU margins, click in visual", sizeGU: [0, 0], marginsGU: [1, 1, 1, 1], clickGU: [0, 0], sensingGU: [4, 4]},
479+ {tag: "zero size, 1GU margins, click in sensing", sizeGU: [0, 0], marginsGU: [1, 1, 1, 1], clickGU: [4, 4], sensingGU: [4, 4]},
480+ {tag: "zero size, 3GU margins horizontal, click in sensing", sizeGU: [0, 0], marginsGU: [3, 0, 3, 0], clickGU: [4, 4], sensingGU: [6, 4]},
481+ {tag: "zero size, 3GU margins vertical, click in sensing", sizeGU: [0, 0], marginsGU: [0, 3, 0, 3], clickGU: [4, 4], sensingGU: [4, 6]},
482+ {tag: "zero size, 3GU margins around, click in sensing", sizeGU: [0, 0], marginsGU: [3, 3, 3, 3], clickGU: [4, 4], sensingGU: [6, 6]},
483+
484+ {tag: "3x3GU size, no margins, click in visual", sizeGU: [3, 3], clickGU: [0, 0], sensingGU: [4, 4]},
485+ {tag: "3x3GU size, no margins, click in sensing", sizeGU: [3, 3], clickGU: [4, 4], sensingGU: [4, 4]},
486+ {tag: "3x3GU size, 1GU margins, click in visual", sizeGU: [3, 3], marginsGU: [1, 1, 1, 1], clickGU: [0, 0], sensingGU: [5, 5]},
487+ {tag: "3x3GU size, 1GU margins, click in sensing", sizeGU: [3, 3], marginsGU: [1, 1, 1, 1], clickGU: [4, 4], sensingGU: [5, 5]},
488+ {tag: "3x3GU size, 3GU margins horizontal, click in sensing", sizeGU: [3, 3], marginsGU: [3, 0, 3, 0], clickGU: [4, 4], sensingGU: [9, 4]},
489+ {tag: "3x3GU size, 3GU margins vertical, click in sensing", sizeGU: [3, 3], marginsGU: [0, 3, 0, 3], clickGU: [4, 4], sensingGU: [4, 9]},
490+ {tag: "3x3GU size, 3GU margins around, click in sensing", sizeGU: [3, 3], marginsGU: [3, 3, 3, 3], clickGU: [4, 4], sensingGU: [9, 9]},
491+
492+ {tag: "5x5GU size, no margins, click in visual", sizeGU: [5, 5], clickGU: [0, 0], sensingGU: [5, 5]},
493+ {tag: "5x5GU size, no margins, click in sensing", sizeGU: [5, 5], clickGU: [4, 4], sensingGU: [5, 5]},
494+ {tag: "5x5GU size, 1GU margins, click in visual", sizeGU: [5, 5], marginsGU: [1, 1, 1, 1], clickGU: [0, 0], sensingGU: [7, 7]},
495+ {tag: "5x5GU size, 1GU margins, click in sensing", sizeGU: [5, 5], marginsGU: [1, 1, 1, 1], clickGU: [4, 4], sensingGU: [7, 7]},
496+ {tag: "5x5GU size, 3GU margins horizontal, click in sensing", sizeGU: [5, 5], marginsGU: [3, 0, 3, 0], clickGU: [4, 4], sensingGU: [11, 5]},
497+ {tag: "5x5GU size, 3GU margins vertical, click in sensing", sizeGU: [5, 5], marginsGU: [0, 3, 0, 3], clickGU: [4, 4], sensingGU: [5, 11]},
498+ {tag: "5x5GU size, 3GU margins around, click in sensing", sizeGU: [5, 5], marginsGU: [3, 3, 3, 3], clickGU: [4, 4], sensingGU: [11, 11]},
499+
500+ {tag: "zero size, no margins, click out of sensing area", sizeGU: [0, 0], clickGU: [5, 5], sensingGU: [4, 4], fail: true},
501+ {tag: "2x2GU size, no margins, click out of sensing area", sizeGU: [2, 2], clickGU: [5, 5], sensingGU: [4, 4], fail: true},
502+ {tag: "4x4GU size, no margins, click out of sensing area", sizeGU: [4, 4], clickGU: [5, 5], sensingGU: [4, 4], fail: true},
503+ {tag: "2x2GU size, 1GU margins around, click out of sensing area", sizeGU: [2, 2], marginsGU: [1, 1, 1, 1], clickGU: [5, 5], sensingGU: [4, 4], fail: true},
504+ {tag: "4x4GU size, 1GU margins around, click out of sensing area", sizeGU: [4, 4], marginsGU: [1, 1, 1, 1], clickGU: [6.1, 6.1], sensingGU: [6, 6], fail: true},
505+
506+ // test margins.all
507+ {tag: "zero size, 5GU margins.all, click in sensing area", sizeGU: [0, 0], marginsAll: units.gu(5), clickGU: [5, 5], sensingGU: [10, 10]},
508+ {tag: "2x2 size, 2GU margins.all, click in sensing area", sizeGU: [2, 2], marginsAll: units.gu(2), clickGU: [6, 6], sensingGU: [6, 6]},
509+ {tag: "zero size, 5GU margins.all, click out of sensing area", sizeGU: [0, 0], marginsAll: units.gu(5), clickGU: [10.1, 10.1], sensingGU: [10, 10], fail: true},
510+ {tag: "2x2 size, 2GU margins.all, click out of sensing area", sizeGU: [2, 2], marginsAll: units.gu(2), clickGU: [6.1, 6.1], sensingGU: [6, 6], fail: true},
511+
512+ // test negative margins
513+ {tag: "zero size, -1GU margins.all, click in sensing area", sizeGU: [0, 0], marginsAll: -units.gu(1), clickGU: [4, 4], sensingGU: [4, 4]},
514+ {tag: "2x2 size, -1GU margins.all, click in sensing area", sizeGU: [2, 2], marginsAll: -units.gu(1), clickGU: [4, 4], sensingGU: [4, 4]},
515+ {tag: "zero size, -1GU margins horizontal, click in sensing area", sizeGU: [0, 0], marginsGU: [-1, 0, -1, 0], clickGU: [4, 4], sensingGU: [4, 4]},
516+ {tag: "zero size, -1GU margins vertical, click in sensing area", sizeGU: [0, 0], marginsGU: [0, -1, 0, -1], clickGU: [4, 4], sensingGU: [4, 4]},
517+ {tag: "2x2 size, -1GU margins horizontal, click in sensing area", sizeGU: [2, 2], marginsGU: [-1, 0, -1, 0], clickGU: [4, 4], sensingGU: [4, 4]},
518+ {tag: "2x2 size, -1GU margins vertical, click in sensing area", sizeGU: [2, 2], marginsGU: [0, -1, 0, -1], clickGU: [4, 4], sensingGU: [4, 4]},
519+ {tag: "4x4 size, -1GU margins.all, click in sensing area", sizeGU: [4, 4], marginsAll: -units.gu(1), clickGU: [4, 4], sensingGU: [4, 4]},
520+ {tag: "4x4 size, -1GU margins horizontal, click in sensing area", sizeGU: [4, 4], marginsGU: [-1, 0, -1, 0], clickGU: [4, 4], sensingGU: [4, 4]},
521+ {tag: "4x4 size, -1GU margins vertical, click in sensing area", sizeGU: [4, 4], marginsGU: [0, -1, 0, -1], clickGU: [4, 4], sensingGU: [4, 4]},
522+
523+ // bigger size than minimum, decrease sensing area
524+ {tag: "5x5 size, -1GU margins.all, click in sensing area", sizeGU: [5, 5], marginsAll: -units.gu(1), clickGU: [4, 4], sensingGU: [4, 4]},
525+ {tag: "5x5 size, -1GU margins horizontal, click in sensing area", sizeGU: [5, 5], marginsGU: [-1, 0, -1, 0], clickGU: [4, 5], sensingGU: [4, 5]},
526+ {tag: "5x5 size, -1GU margins vertical, click in sensing area", sizeGU: [5, 5], marginsGU: [0, -1, 0, -1], clickGU: [5, 4], sensingGU: [5, 4]},
527+ ];
528+ }
529+ function test_sensing_area(data) {
530+ signalSpy.target = buttonWithSensing;
531+ buttonWithSensing.objectName = data.tag;
532+ buttonWithSensing.width = units.gu(data.sizeGU[0]);
533+ buttonWithSensing.height = units.gu(data.sizeGU[1]);
534+ if (data.marginsGU) {
535+ buttonWithSensing.sensingMargins.left = units.gu(data.marginsGU[0]);
536+ buttonWithSensing.sensingMargins.top = units.gu(data.marginsGU[1]);
537+ buttonWithSensing.sensingMargins.right = units.gu(data.marginsGU[2]);
538+ buttonWithSensing.sensingMargins.bottom = units.gu(data.marginsGU[3]);
539+ } else if (data.marginsAll) {
540+ buttonWithSensing.sensingMargins.all = data.marginsAll;
541+ }
542+
543+ if (data.sensingGU) {
544+ compare(buttonWithSensing.__mouseArea.width, units.gu(data.sensingGU[0]), "unexpected horizontal sensing size");
545+ compare(buttonWithSensing.__mouseArea.height, units.gu(data.sensingGU[1]), "unexpected vertical sensing size");
546+ }
547+ if (data.fail) {
548+ expectFailContinue(data.tag, "no signal");
549+ }
550+ mouseClick(buttonWithSensing.__mouseArea, units.gu(data.clickGU[0]), units.gu(data.clickGU[1]));
551+ signalSpy.wait(500);
552+ }
553+
554+ function test_predeclared_sensing_area() {
555+ var point = centerOf(increasedSensing.parent);
556+ // move the point to the edge of the sensing area
557+ point.x -= increasedSensing.sensingMargins.left;
558+ point.y -= increasedSensing.sensingMargins.top;
559+ // click
560+ signalSpy.target = increasedSensing;
561+ mouseClick(increasedSensing.parent, point.x, point.y);
562+ signalSpy.wait(500);
563+ }
564 }
565 }

Subscribers

People subscribed via source and target branches