Merge lp:~tpeeters/ubuntu-ui-toolkit/panel-hideTimer into lp:ubuntu-ui-toolkit

Proposed by Tim Peeters
Status: Merged
Approved by: Cris Dywan
Approved revision: 892
Merged at revision: 879
Proposed branch: lp:~tpeeters/ubuntu-ui-toolkit/panel-hideTimer
Merge into: lp:ubuntu-ui-toolkit
Diff against target: 305 lines (+104/-36)
6 files modified
CHANGES (+1/-0)
components.api (+1/-0)
modules/Ubuntu/Components/Panel.qml (+54/-6)
modules/Ubuntu/Components/Toolbar.qml (+1/-22)
tests/unit_x11/tst_components/tst_panel.qml (+33/-7)
tests/unit_x11/tst_components/tst_toolbar.qml (+14/-1)
To merge this branch: bzr merge lp:~tpeeters/ubuntu-ui-toolkit/panel-hideTimer
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Cris Dywan Approve
Review via email: mp+197442@code.launchpad.net

Commit message

Reset hide timer when user interacts with toolbar or toolbar buttons.

Description of the change

Move the hide timer from Toolbar to Panel, trigger it when open() is called, and restart it on user interaction.

The timer was moved because open() is defined in Panel, and user interaction (pressing and releasing on top of the panel) are dealt with in Panel, not Toolbar, and open() and user interactions need to reset the timer. To keep backwards UX compatibility for Panel, the default hideTimeout was set to -1 ==> no timer.

To post a comment you must log in.
887. By Tim Peeters

fix conditional restart

888. By Tim Peeters

clean

889. By Tim Peeters

update panel unit tests

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

Tested gallery-app and webbrowser-app on maguro, and executed ubuntuuitoolkit AP tests on same device. All good.

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

Webbrowser AP tests also pass on device

Revision history for this message
Cris Dywan (kalikiana) wrote :

What's the motivation behind these numbers? "wait(3*panel.hideTimeout/4);"

review: Needs Information
890. By Tim Peeters

improved test and explained it better

891. By Tim Peeters

improve toolbar tests

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

> What's the motivation behind these numbers? "wait(3*panel.hideTimeout/4);"

I simplified it to *0.6, and added explanation in the code.
Basically, in total you want to wait > 1.0*hideTimeout, but with user interaction inbetween, so you wait twice < hideTimeout, and you check that because of the user interaction the toolbar/panel is not closed.

Revision history for this message
Cris Dywan (kalikiana) wrote :

That makes sense. I guessed it would be something like that but it's good to be clear so everyone doesn't have to ponder what it does. Thanks for adding the explanations.

> + compare(panel.opened, false, "Toolbar automatically closes after timeout");
s/Toolbar/Panel
> + the panel frmo detecting interaction and the timer will not be reset.
s/frmo/from

review: Needs Fixing
892. By Tim Peeters

fix typos

Revision history for this message
Cris Dywan (kalikiana) wrote :

Nice!

review: Approve
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) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CHANGES'
--- CHANGES 2013-11-28 15:07:31 +0000
+++ CHANGES 2013-12-03 18:38:40 +0000
@@ -79,6 +79,7 @@
79* CHANGED IN Header: property Component contents TO property Item contents79* CHANGED IN Header: property Component contents TO property Item contents
80* ADDED IN Panel: function open()80* ADDED IN Panel: function open()
81* ADDED IN Panel: function close()81* ADDED IN Panel: function close()
82* ADDED IN Panel: property int hideTimeout
82* DEPRECATED IN Panel: writable property opened. Will be made read-only.83* DEPRECATED IN Panel: writable property opened. Will be made read-only.
83* ADDED IN: Empty: property bool waitingConfirmationForRemoval84* ADDED IN: Empty: property bool waitingConfirmationForRemoval
84* ADDED IN: Empty: function cancelItemRemoval()85* ADDED IN: Empty: function cancelItemRemoval()
8586
=== modified file 'components.api'
--- components.api 2013-12-02 19:14:03 +0000
+++ components.api 2013-12-03 18:38:40 +0000
@@ -234,6 +234,7 @@
234 property bool opened234 property bool opened
235 function open()235 function open()
236 function close()236 function close()
237 property int hideTimeout
237 property bool locked238 property bool locked
238 property real hintSize239 property real hintSize
239 property real triggerSize240 property real triggerSize
240241
=== modified file 'modules/Ubuntu/Components/Panel.qml'
--- modules/Ubuntu/Components/Panel.qml 2013-11-27 14:54:05 +0000
+++ modules/Ubuntu/Components/Panel.qml 2013-12-03 18:38:40 +0000
@@ -103,8 +103,7 @@
103 Any Items can be placed inside the Panel, but MouseAreas can block mouse events from reaching103 Any Items can be placed inside the Panel, but MouseAreas can block mouse events from reaching
104 the panel and thus obstruct the swiping behavior for hiding the panel. As a result, the user cannot104 the panel and thus obstruct the swiping behavior for hiding the panel. As a result, the user cannot
105 start swiping on the buttons in the examples above in order to hide the panel. To remedy this, clicked()105 start swiping on the buttons in the examples above in order to hide the panel. To remedy this, clicked()
106 signals are forwarded from the panel to its children. The children's clicked() signal does not have106 signals are forwarded from the panel by calling the child's trigger() function. Example:
107 a mouse parameter. Example:
108 \qml107 \qml
109 import QtQuick 2.0108 import QtQuick 2.0
110 import Ubuntu.Components 0.1109 import Ubuntu.Components 0.1
@@ -130,15 +129,17 @@
130 width: units.gu(8)129 width: units.gu(8)
131 height: units.gu(4)130 height: units.gu(4)
132 anchors.centerIn: parent131 anchors.centerIn: parent
133 color: Theme.palette.normal.foreground132 color: "red"
134 signal clicked()133 function trigger() {
135 onClicked: print("The red rectangle was clicked");134 print("The red rectangle was clicked");
135 }
136 }136 }
137 }137 }
138 }138 }
139 Component.onCompleted: panel.open();
139 }140 }
140 \endqml141 \endqml
141 Like this, the red rectangle accepts clicked() events, but the user can still swipe down on top142 Like this, the red rectangle accepts click events, but the user can still swipe down on top
142 of the rectangle in order to hide the panel.143 of the rectangle in order to hide the panel.
143*/144*/
144Item {145Item {
@@ -208,6 +209,7 @@
208 // FIXME: When opened is made readonly, openedChangedWarning must be removed209 // FIXME: When opened is made readonly, openedChangedWarning must be removed
209 internal.openedChangedWarning = false;210 internal.openedChangedWarning = false;
210 panel.state = "spread";211 panel.state = "spread";
212 hideTimer.conditionalRestart();
211 }213 }
212214
213 /*!215 /*!
@@ -217,9 +219,21 @@
217 // FIXME: When opened is made readonly, openedChangedWarning must be removed.219 // FIXME: When opened is made readonly, openedChangedWarning must be removed.
218 internal.openedChangedWarning = false;220 internal.openedChangedWarning = false;
219 panel.state = "";221 panel.state = "";
222 hideTimer.stop();
220 }223 }
221224
222 /*!225 /*!
226 The time in milliseconds before the panel automatically hides after inactivity
227 when it is not locked. Interacting with the panel resets the timer.
228 Note that adding contents to the panel that accepts mouse events will prevent
229 the panel from detecting interaction and the timer will not be reset.
230 Setting a negative value will disable automatic hiding.
231 Default value: -1 (automatic hiding is disabled).
232 \qmlproperty int hideTimeout
233 */
234 property alias hideTimeout: hideTimer.interval
235
236 /*!
223 Disable edge swipe to open/close the panel. False by default.237 Disable edge swipe to open/close the panel. False by default.
224 */238 */
225 property bool locked: false239 property bool locked: false
@@ -228,6 +242,35 @@
228 if (state == "hint" || state == "moving") {242 if (state == "hint" || state == "moving") {
229 draggingArea.finishMoving();243 draggingArea.finishMoving();
230 }244 }
245 if (!hideTimer.conditionalRestart()) {
246 hideTimer.stop();
247 }
248 }
249
250 Timer {
251 id: hideTimer
252 interval: -1
253 running: panel.opened && !panel.locked && interval >= 0
254
255 function conditionalRestart() {
256 if (hideTimer.interval >= 0) {
257 if (!panel.locked && panel.opened) {
258 hideTimer.restart();
259 return true;
260 }
261 }
262 return false;
263 }
264 onIntervalChanged: {
265 if (!conditionalRestart()) {
266 hideTimer.stop();
267 }
268 }
269 onTriggered: {
270 if (!panel.locked) {
271 panel.close();
272 }
273 }
231 }274 }
232275
233 /*!276 /*!
@@ -485,6 +528,7 @@
485528
486 property int initialPosition529 property int initialPosition
487 onPressed: {530 onPressed: {
531 hideTimer.stop();
488 pressedItem = getTriggerableItem(mouse);532 pressedItem = getTriggerableItem(mouse);
489 if (panel.locked) return;533 if (panel.locked) return;
490 initialPosition = getMousePosition();534 initialPosition = getMousePosition();
@@ -514,12 +558,16 @@
514 onReleased: {558 onReleased: {
515 if (panel.state == "moving" || panel.state == "hint") {559 if (panel.state == "moving" || panel.state == "hint") {
516 finishMoving();560 finishMoving();
561 } else {
562 hideTimer.conditionalRestart();
517 }563 }
518 }564 }
519 // Mouse cursor moving out of the window while pressed on desktop565 // Mouse cursor moving out of the window while pressed on desktop
520 onCanceled: {566 onCanceled: {
521 if (panel.state == "moving" || panel.state == "hint") {567 if (panel.state == "moving" || panel.state == "hint") {
522 finishMoving();568 finishMoving();
569 } else {
570 hideTimer.conditionalRestart();
523 }571 }
524 }572 }
525573
526574
=== modified file 'modules/Ubuntu/Components/Toolbar.qml'
--- modules/Ubuntu/Components/Toolbar.qml 2013-11-08 18:38:25 +0000
+++ modules/Ubuntu/Components/Toolbar.qml 2013-12-03 18:38:40 +0000
@@ -42,12 +42,7 @@
42 */42 */
43 property Item tools: null43 property Item tools: null
4444
45 /*!45 hideTimeout: 5000
46 \preliminary
47 The time in milliseconds before the toolbar automatically hides after inactivity
48 when it is not locked.
49 */
50 property int hideTimeout: 5000
5146
52 /*! \internal */47 /*! \internal */
53 onToolsChanged: {48 onToolsChanged: {
@@ -66,10 +61,6 @@
66 if (tools && tools.hasOwnProperty("opened")) {61 if (tools && tools.hasOwnProperty("opened")) {
67 tools.opened = toolbar.opened;62 tools.opened = toolbar.opened;
68 }63 }
69
70 if (!toolbar.locked) {
71 hideTimer.restart();
72 }
73 } else { // no tools64 } else { // no tools
74 locked = true;65 locked = true;
75 toolbar.close();66 toolbar.close();
@@ -79,22 +70,10 @@
79 // if tools is not specified, lock the toolbar in closed position70 // if tools is not specified, lock the toolbar in closed position
80 locked: tools && tools.hasOwnProperty("locked") ? tools.locked : false71 locked: tools && tools.hasOwnProperty("locked") ? tools.locked : false
8172
82 Timer {
83 id: hideTimer
84 interval: toolbar.hideTimeout
85 running: toolbar.opened && !toolbar.locked
86 onTriggered: {
87 if (!toolbar.locked) {
88 toolbar.close();
89 }
90 }
91 }
92
93 onOpenedChanged: {73 onOpenedChanged: {
94 if (tools && tools.hasOwnProperty("opened")) {74 if (tools && tools.hasOwnProperty("opened")) {
95 tools.opened = toolbar.opened;75 tools.opened = toolbar.opened;
96 }76 }
97 if (!toolbar.locked) hideTimer.restart();
98 }77 }
9978
100 Connections {79 Connections {
10180
=== modified file 'tests/unit_x11/tst_components/tst_panel.qml'
--- tests/unit_x11/tst_components/tst_panel.qml 2013-09-09 18:59:35 +0000
+++ tests/unit_x11/tst_components/tst_panel.qml 2013-12-03 18:38:40 +0000
@@ -31,6 +31,10 @@
31 right: parent.right31 right: parent.right
32 }32 }
33 height: parent.height / 233 height: parent.height / 2
34 Rectangle {
35 color: "pink"
36 anchors.fill: parent
37 }
34 }38 }
3539
36 TestCase {40 TestCase {
@@ -162,6 +166,35 @@
162 panel.align = Qt.AlignBottom;166 panel.align = Qt.AlignBottom;
163 }167 }
164168
169 function test_clickToDeactivate() {
170 panel.open();
171 compare(panel.opened && panel.align === Qt.AlignBottom, true, "Panel is opened and bottom-aligned");
172 mouseClick(root, root.width / 2, 5, Qt.LeftButton);
173 compare(panel.opened, false, "Panel is deactivated by clicking in the view outside of the panel");
174 }
175
176 function test_hideTimeout_bug1249031() {
177 compare(panel.hideTimeout, -1, "Panel hide timeout is initially negative (no timeout)");
178 panel.hideTimeout = 2000;
179 panel.open();
180 compare(panel.opened, true, "Panel can be made opened");
181 wait(panel.hideTimeout + 500); // add 500 ms margin
182 compare(panel.opened, false, "Panel automatically closes after timeout");
183
184 // now, wait in total more than hideTimeout, but less than 2*hideTimeout,
185 // and have user interaction half-way to verify that the interaction
186 // resets the timer and the panel is not closed.
187 panel.open();
188 wait(0.6*panel.hideTimeout);
189 mouseClick(panel, panel.width/2, panel.height/2);
190 wait(0.6*panel.hideTimeout);
191 compare(panel.opened, true, "Interacting with panel contents resets the hide timer");
192 // verify that the timer is still running by waiting a bit longer:
193 wait(0.6*panel.hideTimeout);
194 compare(panel.opened, false, "Interacting with the panel contents does not stop the timer")
195 panel.hideTimeout = -1;
196 }
197
165 QtObject {198 QtObject {
166 id: swipeTests199 id: swipeTests
167200
@@ -239,13 +272,6 @@
239 testCase.mouseRelease(panel, x - dx, y - dy, Qt.LeftButton);272 testCase.mouseRelease(panel, x - dx, y - dy, Qt.LeftButton);
240 testCase.compare(panel.opened, false, "Top-aligned panel deactivated by swiping up (delay: "+moveDelay+"");273 testCase.compare(panel.opened, false, "Top-aligned panel deactivated by swiping up (delay: "+moveDelay+"");
241 }274 }
242
243 function test_clickToDeactivate() {
244 panel.open();
245 compare(panel.opened && panel.align === Qt.AlignBottom, true, "Panel is opened and bottom-aligned");
246 mouseClick(root, root.width / 2, 5, Qt.LeftButton);
247 compare(panel.opened, false, "Panel is deactivated by clicking in the view outside of the panel");
248 }
249 }275 }
250 }276 }
251}277}
252278
=== modified file 'tests/unit_x11/tst_components/tst_toolbar.qml'
--- tests/unit_x11/tst_components/tst_toolbar.qml 2013-11-08 18:32:39 +0000
+++ tests/unit_x11/tst_components/tst_toolbar.qml 2013-12-03 18:38:40 +0000
@@ -36,6 +36,7 @@
36 tools: ToolbarItems {36 tools: ToolbarItems {
37 id: toolbarItems37 id: toolbarItems
38 ToolbarButton {38 ToolbarButton {
39 id: toolbarButton
39 text: "action1"40 text: "action1"
40 }41 }
41 }42 }
@@ -74,12 +75,24 @@
74 compare(mainView.__propagated.toolbar.opened, false, "Toolbar can be made closed by setting page.tools.opened to false");75 compare(mainView.__propagated.toolbar.opened, false, "Toolbar can be made closed by setting page.tools.opened to false");
75 }76 }
7677
77 function test_hideTimeout() {78 function test_hideTimeout_bug1249031() {
78 compare(mainView.__propagated.toolbar.hideTimeout, 5000, "Toolbar hide timeout is initially 5 seconds.");79 compare(mainView.__propagated.toolbar.hideTimeout, 5000, "Toolbar hide timeout is initially 5 seconds.");
79 mainView.__propagated.toolbar.open();80 mainView.__propagated.toolbar.open();
80 compare(mainView.__propagated.toolbar.opened, true, "Toolbar can be made opened");81 compare(mainView.__propagated.toolbar.opened, true, "Toolbar can be made opened");
81 wait(mainView.__propagated.toolbar.hideTimeout + 500); // add 500 ms margin82 wait(mainView.__propagated.toolbar.hideTimeout + 500); // add 500 ms margin
82 compare(mainView.__propagated.toolbar.opened, false, "Toolbar automatically closes after timeout");83 compare(mainView.__propagated.toolbar.opened, false, "Toolbar automatically closes after timeout");
84
85 // now, wait in total more than hideTimeout, but less than 2*hideTimeout,
86 // and have user interaction half-way to verify that the interaction
87 // resets the timer and the toolbar is not closed.
88 mainView.__propagated.toolbar.open();
89 wait(0.6*mainView.__propagated.toolbar.hideTimeout);
90 mouseClick(toolbarButton, toolbarButton.width/2, toolbarButton.height/2);
91 wait(0.6*mainView.__propagated.toolbar.hideTimeout);
92 compare(mainView.__propagated.toolbar.opened, true, "Interacting with toolbar contents resets the hide timer");
93 // verify that the timer is still running by waiting a bit longer:
94 wait(0.6*mainView.__propagated.toolbar.hideTimeout);
95 compare(mainView.__propagated.toolbar.opened, false, "Interacting with the toolbar contents does not stop the timer")
83 }96 }
8497
85 function test_locked() {98 function test_locked() {

Subscribers

People subscribed via source and target branches

to status/vote changes: