feat(ui/modules/Common/Menus/DropDownDynamicMenu): use Popup component

This commit is contained in:
Ronan Abhamon 2017-05-16 14:22:00 +02:00
parent 78de78982e
commit b0fc92164d
11 changed files with 107 additions and 211 deletions

View file

@ -223,14 +223,13 @@
<file>ui/modules/Common/Indicators/VuMeter.qml</file>
<file>ui/modules/Common/Menus/ActionMenuEntry.qml</file>
<file>ui/modules/Common/Menus/ActionMenu.qml</file>
<file>ui/modules/Common/Menus/DropDownDynamicMenu.qml</file>
<file>ui/modules/Common/Menus/Menu.qml</file>
<file>ui/modules/Common/Misc/Borders.qml</file>
<file>ui/modules/Common/Misc/Collapse.qml</file>
<file>ui/modules/Common/Misc/ForceScrollBar.qml</file>
<file>ui/modules/Common/Misc/Paned.qml</file>
<file>ui/modules/Common/Popup/AbstractDropDownMenu.qml</file>
<file>ui/modules/Common/Popup/DesktopPopup.qml</file>
<file>ui/modules/Common/Popup/DropDownDynamicMenu.qml</file>
<file>ui/modules/Common/Popup/Popup.qml</file>
<file>ui/modules/Common/Popup/PopupShadow.qml</file>
<file>ui/modules/Common/qmldir</file>

View file

@ -28,6 +28,8 @@
#include <QtDebug>
#include <QTimer>
#include "gitversion.h"
#include "../components/Components.hpp"
#include "../Utils.hpp"
@ -37,7 +39,6 @@
#include "translator/DefaultTranslator.hpp"
#include "App.hpp"
#include "gitversion.h"
#define DEFAULT_LOCALE "en"
@ -51,7 +52,7 @@
#define QML_VIEW_SPLASH_SCREEN "qrc:/ui/views/App/SplashScreen/SplashScreen.qml"
#define SELF_TEST_DELAY 60000
#define SELF_TEST_DELAY 300000
#ifndef LINPHONE_QT_GIT_VERSION
#define LINPHONE_QT_GIT_VERSION "unknown"
@ -153,10 +154,10 @@ void App::initContentApp () {
// Init engine content.
mEngine = new QQmlApplicationEngine();
qInfo() << QStringLiteral("Activated selectors:") << QQmlFileSelector::get(mEngine)->selector()->allSelectors();
// Provide `+custom` folders for custom components.
(new QQmlFileSelector(mEngine, mEngine))->setExtraSelectors(QStringList("custom"));
qInfo() << QStringLiteral("Activated selectors:") << QQmlFileSelector::get(mEngine)->selector()->allSelectors();
// Set modules paths.
mEngine->addImportPath(":/ui/modules");

View file

@ -89,10 +89,8 @@ Item {
DropDownDynamicMenu {
id: menu
launcher: searchField
relativeTo: searchField
relativeY: searchField.height
width: searchField.width
// If the menu is focused, the main window loses the active status.
// So It's necessary to map the keys events.
@ -103,8 +101,8 @@ Item {
ScrollableListView {
id: list
anchors.fill: parent
headerPositioning: header ? ListView.OverlayHeader : ListView.InlineFooter
width: searchField.width
}
}
}
@ -123,7 +121,7 @@ Item {
ScriptAction {
script: {
menu.showMenu()
menu.show()
searchBox.menuOpened()
}
@ -136,7 +134,7 @@ Item {
ScriptAction {
script: {
menu.hideMenu()
menu.hide()
searchField.focus = false
searchBox.menuClosed()

View file

@ -123,9 +123,6 @@ Item {
DropDownDynamicMenu {
id: menu
launcher: searchField
width: searchField.width
// If the menu is focused, the main window loses the active status.
// So It's necessary to map the keys events.
Keys.forwardTo: searchField
@ -135,8 +132,8 @@ Item {
ScrollableListView {
id: list
anchors.fill: parent
headerPositioning: header ? ListView.OverlayHeader : ListView.InlineFooter
width: searchField.width
}
}
}
@ -156,7 +153,7 @@ Item {
ScriptAction {
script: {
menu.showMenu()
menu.show()
desktopPopup.show()
searchBox.menuOpened()
@ -170,7 +167,7 @@ Item {
ScriptAction {
script: {
menu.hideMenu()
menu.hide()
searchField.focus = false
desktopPopup.hide()

View file

@ -0,0 +1,85 @@
import QtQuick 2.7
import Common 1.0
import Utils 1.0
// =============================================================================
Item {
id: menu
// ---------------------------------------------------------------------------
property alias relativeTo: popup.relativeTo
property alias relativeX: popup.relativeX
property alias relativeY: popup.relativeY
// Can be computed, but for performance usage, it must be given in attribute.
property int entryHeight
property int maxMenuHeight
default property alias _content: menuContent.data
// ---------------------------------------------------------------------------
signal menuClosed
signal menuOpened
// ---------------------------------------------------------------------------
function show () {
popup.show()
}
function hide () {
popup.hide()
}
// ---------------------------------------------------------------------------
function _computeHeight () {
Utils.assert(_content != null && _content.length > 0, '`_content` cannot be null and must exists.')
var list = _content[0]
Utils.assert(list != null, 'No list found.')
Utils.assert(
Utils.qmlTypeof(list, 'QQuickListView') || Utils.qmlTypeof(list, 'ScrollableListView'),
'No list view parameter.'
)
var height = list.count * entryHeight
if (list.headerPositioning === ListView.OverlayHeader) {
// Workaround to force header layout.
list.headerItem.z = Constants.zMax
height += list.headerItem.height
}
return (maxMenuHeight !== undefined && height > maxMenuHeight)
? maxMenuHeight
: height
}
// ---------------------------------------------------------------------------
Popup {
id: popup
onShown: menu.menuOpened()
onHidden: menu.menuClosed()
Item {
id: menuContent
height: menu._computeHeight()
width: menu._content[0].width
}
}
Binding {
property: 'height'
target: menu._content[0]
value: menuContent.height
}
}

View file

@ -1,154 +0,0 @@
import QtQuick 2.7
import Common 1.0
import Common.Styles 1.0
import Utils 1.0
// =============================================================================
// Low component to display a list/menu in a popup.
// =============================================================================
Item {
id: menu
// ---------------------------------------------------------------------------
// Optionnal parameter, if defined and if a click is detected
// on it, menu is not closed.
property var launcher
// Optionnal parameters, set the position of Menu relative
// to this item.
property var relativeTo
property int relativeX: 0
property int relativeY: 0
default property alias _content: content.data
property bool _isOpen: false
// ---------------------------------------------------------------------------
signal menuClosed
signal menuOpened
// ---------------------------------------------------------------------------
function isOpen () {
return _isOpen
}
function showMenu () {
if (_isOpen) {
return
}
if (relativeTo != null) {
this.x = relativeTo.mapToItem(null, relativeX, relativeY).x
this.y = relativeTo.mapToItem(null, relativeX, relativeY).y
}
_isOpen = true
}
function hideMenu () {
if (!_isOpen) {
return
}
_isOpen = false
}
function _computeHeight () {
throw new Error('Virtual method must be implemented.')
}
// ---------------------------------------------------------------------------
implicitHeight: 0
opacity: 0
visible: false
z: Constants.zPopup
Keys.onEscapePressed: hideMenu()
// Set parent menu to root.
Component.onCompleted: {
if (relativeTo != null) {
parent = Utils.getTopParent(this)
}
}
// Handle clicks, wheel... below menu.
MouseArea {
anchors.fill: parent
hoverEnabled: true
onWheel: {}
}
// Menu content.
Rectangle {
id: content
anchors.fill: parent
color: PopupStyle.backgroundColor
layer {
enabled: true
effect: PopupShadow {}
}
}
// Inverted mouse area to detect click outside menu.
InvertedMouseArea {
anchors.fill: parent
enabled: parent.visible
onPressed: {
if (launcher == null || !pointIsInItem(launcher)) {
hideMenu()
}
}
}
// ---------------------------------------------------------------------------
states: State {
name: 'opened'
when: _isOpen
PropertyChanges {
focus: true // Necessary to use `Keys.onEscapePressed`.
implicitHeight: _computeHeight()
opacity: 1.0
target: menu
}
}
transitions: [
Transition {
from: ''
to: 'opened'
ScriptAction {
script: {
menu.visible = true
menuOpened()
}
}
},
Transition {
from: 'opened'
to: ''
SequentialAnimation {
ScriptAction {
script: {
menuClosed()
visible = false
}
}
}
}
]
}

View file

@ -1,38 +0,0 @@
import QtQuick 2.7
import Common 1.0
import Utils 1.0
// =============================================================================
// Menu which supports `ListView`.
// =============================================================================
AbstractDropDownMenu {
// Can be computed, but for performance usage, it must be given in attribute.
property int entryHeight
property int maxMenuHeight
function _computeHeight () {
Utils.assert(_content != null && _content.length > 0, '`_content` cannot be null and must exists.')
var list = _content[0]
Utils.assert(list != null, 'No list found.')
Utils.assert(
Utils.qmlTypeof(list, 'QQuickListView') || Utils.qmlTypeof(list, 'ScrollableListView'),
'No list view parameter.'
)
var height = list.count * entryHeight
if (list.headerPositioning === ListView.OverlayHeader) {
// Workaround to force header layout.
list.headerItem.z = Constants.zMax
height += list.headerItem.height
}
return (maxMenuHeight !== undefined && height > maxMenuHeight)
? maxMenuHeight
: height
}
}

View file

@ -18,6 +18,11 @@ Item {
// ---------------------------------------------------------------------------
signal hidden
signal shown
// ---------------------------------------------------------------------------
visible: false
function show () {
@ -79,5 +84,8 @@ Item {
padding: 0
Component.onCompleted: parent = Utils.getTopParent(this)
onClosed: wrapper.hidden()
onOpened: wrapper.shown()
}
}

View file

@ -63,6 +63,7 @@ VuMeter 1.0 Indicators/VuMeter.qml
ActionMenu 1.0 Menus/ActionMenu.qml
ActionMenuEntry 1.0 Menus/ActionMenuEntry.qml
DropDownDynamicMenu 1.0 Menus/DropDownDynamicMenu.qml
Menu 1.0 Menus/Menu.qml
Borders 1.0 Misc/Borders.qml
@ -71,7 +72,6 @@ ForceScrollBar 1.0 Misc/ForceScrollBar.qml
Paned 1.0 Misc/Paned.qml
DesktopPopup 1.0 Popup/DesktopPopup.qml
DropDownDynamicMenu 1.0 Popup/DropDownDynamicMenu.qml
Popup 1.0 Popup/Popup.qml
PopupShadow 1.0 Popup/PopupShadow.qml

View file

@ -4,7 +4,7 @@
.pragma library
.import QtQuick 2.0 as QtQuick
.import QtQuick 2.7 as QtQuick
.import 'port-tools.js' as PortTools
.import 'uri-tools.js' as UriTools

View file

@ -1,5 +1,5 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Controls 2.1
import QtQuick.Window 2.2
import Utils 1.0