From eca28cc5aeea84d917eefb061cfc6bf4501bf5ae Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Tue, 25 Oct 2016 11:46:33 +0200 Subject: [PATCH] fix(Popup/DropDownMenu): don't hide menu if launcher button is clicked again --- tests/ui/modules/Common/InvertedMouseArea.qml | 28 ++++++++----------- .../ui/modules/Common/Popup/DropDownMenu.qml | 8 +++++- tests/ui/modules/Common/SearchBox.qml | 1 + .../ui/modules/Linphone/Call/CallControls.qml | 1 + tests/ui/scripts/Utils/utils.js | 18 ++++++++++++ 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/tests/ui/modules/Common/InvertedMouseArea.qml b/tests/ui/modules/Common/InvertedMouseArea.qml index 7925eb9ce..401caff8f 100644 --- a/tests/ui/modules/Common/InvertedMouseArea.qml +++ b/tests/ui/modules/Common/InvertedMouseArea.qml @@ -4,7 +4,7 @@ import Common 1.0 import Utils 1.0 // =================================================================== -// Helper to handle button click outside a component. +// Helper to handle button click outside an item. // =================================================================== Item { @@ -12,7 +12,9 @@ Item { property var _mouseArea - signal pressed + // When emitted, returns a function to test if the click + // is on a specific item. It takes only a item parameter. + signal pressed (var pointIsInItem) function _createMouseArea () { if (_mouseArea == null) { @@ -29,15 +31,6 @@ Item { } } - function _isInItem (point) { - return ( - point.x >= item.x && - point.y >= item.y && - point.x < item.x + item.width && - point.y < item.y + item.height - ) - } - // It's necessary to use a `enabled` variable. // See: http://doc.qt.io/qt-5/qml-qtqml-component.html#completed-signal // @@ -70,9 +63,7 @@ Item { mouse.accepted = false // Click is outside or not. - if (!_isInItem( - mapToItem(item.parent, mouse.x, mouse.y) - )) { + if (!Utils.pointIsInItem(this, item, mouse)) { if (_timeout != null) { // Remove existing timeout to avoid the creation of // many children. @@ -87,9 +78,12 @@ Item { // call. // // The timeout is destroyed with the `MouseArea` component. - _timeout = Utils.setTimeout( - this, 0, item.pressed.bind(this) - ) + _timeout = Utils.setTimeout(this, 0, item.pressed.bind( + this, + (function (point, item) { + return Utils.pointIsInItem(this, item, point) + }).bind(this, { x: mouse.x, y: mouse.y }) + )) } } } diff --git a/tests/ui/modules/Common/Popup/DropDownMenu.qml b/tests/ui/modules/Common/Popup/DropDownMenu.qml index c659e3135..fd7e623c7 100644 --- a/tests/ui/modules/Common/Popup/DropDownMenu.qml +++ b/tests/ui/modules/Common/Popup/DropDownMenu.qml @@ -12,6 +12,7 @@ Rectangle { property bool drawOnRoot: false property int entryHeight // Only with a ListView child. property int maxMenuHeight // Only with a ListView child. + property var launcher property var relativeTo default property alias _content: content.data @@ -82,6 +83,11 @@ Rectangle { anchors.fill: parent enabled: parent.visible - onPressed: hideMenu() + onPressed: { + if (launcher != null && pointIsInItem(launcher)) { + return + } + hideMenu() + } } } diff --git a/tests/ui/modules/Common/SearchBox.qml b/tests/ui/modules/Common/SearchBox.qml index 6aab9e4a8..cd315d91e 100644 --- a/tests/ui/modules/Common/SearchBox.qml +++ b/tests/ui/modules/Common/SearchBox.qml @@ -67,6 +67,7 @@ Item { id: menu anchors.top: searchField.bottom + launcher: searchField width: searchField.width onMenuClosed: _hideMenu() diff --git a/tests/ui/modules/Linphone/Call/CallControls.qml b/tests/ui/modules/Linphone/Call/CallControls.qml index 8240c5439..972e31756 100644 --- a/tests/ui/modules/Linphone/Call/CallControls.qml +++ b/tests/ui/modules/Linphone/Call/CallControls.qml @@ -55,6 +55,7 @@ RowLayout { entryHeight: 22 height: 100 width: 120 + launcher: button relativeTo: button Rectangle { diff --git a/tests/ui/scripts/Utils/utils.js b/tests/ui/scripts/Utils/utils.js index 32c66126c..20bc18cd2 100644 --- a/tests/ui/scripts/Utils/utils.js +++ b/tests/ui/scripts/Utils/utils.js @@ -136,6 +136,24 @@ function qmlTypeof (object, className) { // ------------------------------------------------------------------- +// Test if a point is in a item. +// +// `source` is the item that generated the point. +// `target` is the item to test. +// `point` is the point to test. +function pointIsInItem (source, target, point) { + point = source.mapToItem(target.parent, point.x, point.y) + + return ( + point.x >= target.x && + point.y >= target.y && + point.x < target.x + target.width && + point.y < target.y + target.height + ) +} + +// ------------------------------------------------------------------- + // Invoke a `cb` function with each value of the interval: `[0, n[`. // Return a mapped array created with the returned values of `cb`. function times (n, cb, context) {