summaryrefslogtreecommitdiffstats
path: root/src/controls/Menu.qml
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@digia.com>2013-06-05 21:45:04 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 16:35:08 +0200
commit1f8ee02fbc06f822ee131fdd395c8e8cd244601d (patch)
tree8846593196d96701741a5a5fba046d13e851ca43 /src/controls/Menu.qml
parent7adeff65148a3967af7b2ec44764a2c275dcd3fe (diff)
ComboBox: Make popup scrollable
We factor out part the menu item container logic from Menu into ColumnMenuContent, which takes care of scrolling and mouse hovering, and selection. This makes possible to extend the menu items layout. The pop-over and pull-down look is specified by the menu style component by overriding the ScrollView style. The popup's maximum height is also specified by the menu style. The gallery example can finally use a font families combo box. Task-number: QTBUG-31568 Change-Id: I34a7278f476471c0eb51ef51dde3dd83e13002fe Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
Diffstat (limited to 'src/controls/Menu.qml')
-rw-r--r--src/controls/Menu.qml209
1 files changed, 87 insertions, 122 deletions
diff --git a/src/controls/Menu.qml b/src/controls/Menu.qml
index 4c3bc1be7..949b6a915 100644
--- a/src/controls/Menu.qml
+++ b/src/controls/Menu.qml
@@ -152,14 +152,14 @@ MenuPrivate {
property Component __menuComponent: Loader {
id: menuFrameLoader
- property Style __style: styleLoader.item
- property Component menuItemStyle: __style ? __style.menuItem : null
+ readonly property Style __style: styleLoader.item
+ readonly property Component menuItemStyle: __style ? __style.menuItem : null
- property var control: root
- property alias contentWidth: column.width
- property alias contentHeight: column.height
+ readonly property var control: root
+ property alias contentWidth: content.width
+ property alias contentHeight: content.height
- property int subMenuXPos: width + (item && item["subMenuOverlap"] || 0)
+ readonly property int subMenuXPos: width + (item && item["subMenuOverlap"] || 0)
visible: status === Loader.Ready
sourceComponent: __style ? __style.frame : undefined
@@ -204,17 +204,19 @@ MenuPrivate {
for (var i = root.__currentIndex + 1;
i < root.items.length && !canBeHovered(i); i++)
;
+ event.accepted = true
}
Keys.onUpPressed: {
for (var i = root.__currentIndex - 1;
i >= 0 && !canBeHovered(i); i--)
;
+ event.accepted = true
}
function canBeHovered(index) {
- var item = itemsRepeater.itemAt(index)
- if (!item["isSeparator"] && item.enabled) {
+ var item = content.menuItemAt(index)
+ if (item && !item["isSeparator"] && item.enabled) {
root.__currentIndex = index
return true
}
@@ -227,20 +229,24 @@ MenuPrivate {
}
Keys.onRightPressed: {
- var item = itemsRepeater.itemAt(root.__currentIndex)
+ var item = content.menuItemAt(root.__currentIndex)
if ((event.accepted = (item && item.isSubmenu))) {
item.showSubMenu(true)
item.menuItem.__currentIndex = 0
}
}
- Keys.onSpacePressed: menuFrameLoader.triggerAndDismiss()
- Keys.onReturnPressed: menuFrameLoader.triggerAndDismiss()
- Keys.onEnterPressed: menuFrameLoader.triggerAndDismiss()
+ Keys.onSpacePressed: triggerCurrent()
+ Keys.onReturnPressed: triggerCurrent()
+ Keys.onEnterPressed: triggerCurrent()
+
+ function triggerCurrent() {
+ var item = content.menuItemAt(root.__currentIndex)
+ if (item)
+ content.triggered(item)
+ }
function triggerAndDismiss(item) {
- if (!item)
- item = itemsRepeater.itemAt(root.__currentIndex)
if (item && !item.isSeparator) {
root.__dismissMenu()
if (!item.isSubmenu)
@@ -250,126 +256,85 @@ MenuPrivate {
Binding {
// Make sure the styled frame is in the background
- target: menuFrameLoader.item
+ target: item
property: "z"
- value: menuMouseArea.z - 1
+ value: content.z - 1
}
- MouseArea {
- id: menuMouseArea
- anchors.fill: parent
- hoverEnabled: true
- acceptedButtons: Qt.AllButtons
-
- onPositionChanged: updateCurrentItem(mouse)
- onReleased: menuFrameLoader.triggerAndDismiss()
- onExited: {
- if (currentItem && !currentItem.menuItem.__popupVisible) {
- currentItem = null
- root.__currentIndex = -1
- }
- }
-
- property Item currentItem: null
-
- function updateCurrentItem(mouse) {
- var pos = mapToItem(column, mouse.x, mouse.y)
- if (!currentItem || !currentItem.contains(Qt.point(pos.x - currentItem.x, pos.y - currentItem.y))) {
- if (currentItem && !pressed && currentItem.isSubmenu)
- currentItem.closeSubMenu()
- var itemUnderMouse = column.childAt(pos.x, pos.y)
- if (itemUnderMouse) {
- currentItem = itemUnderMouse
- } else if (currentItem) {
- var itemItem = currentItem.item
- if (!itemItem.contains(itemItem.mapFromItem(column, pos)))
- currentItem = null
- }
+ ColumnMenuContent {
+ id: content
+ menuItemDelegate: menuItemComponent
+ scrollerStyle: __style ? __style.scrollerStyle : undefined
+ itemsModel: root.items
+ margin: menuFrameLoader.item ? menuFrameLoader.item.margin : 0
+ minWidth: root.__minimumWidth
+ maxHeight: menuFrameLoader.item ? menuFrameLoader.item.maxHeight : 0
+ onTriggered: triggerAndDismiss(item)
+ }
- if (currentItem) {
- root.__currentIndex = currentItem.menuItemIndex
- if (currentItem.isSubmenu && !currentItem.menuItem.__popupVisible)
- currentItem.showSubMenu(false)
+ Component {
+ id: menuItemComponent
+ Loader {
+ id: menuItemLoader
+
+ property var menuItem: modelData
+ readonly property bool isSeparator: !!menuItem && menuItem.type === MenuItemType.Separator
+ readonly property bool isSubmenu: !!menuItem && menuItem.type === MenuItemType.Menu
+ property bool selected: !(isSeparator || !!scrollerDirection) && root.__currentIndex === index
+ property string text: isSubmenu ? menuItem.title : !(isSeparator || !!scrollerDirection) ? menuItem.text : ""
+ property bool showUnderlined: __contentItem.altPressed
+ readonly property var scrollerDirection: menuItem["scrollerDirection"]
+
+ property int menuItemIndex: index
+
+ sourceComponent: menuFrameLoader.menuItemStyle
+ enabled: visible && !isSeparator && !!menuItem && menuItem.enabled
+ visible: menuItem.visible
+ active: visible
+
+ function showSubMenu(immediately) {
+ if (immediately) {
+ if (root.__currentIndex === menuItemIndex)
+ menuItem.__popup(menuFrameLoader.subMenuXPos, 0, -1)
} else {
- root.__currentIndex = -1
+ openMenuTimer.start()
}
}
- }
- // Each menu item has its own mouse area, and for events to be
- // propagated to the menu mouse area, they need to be embedded.
- Column {
- id: column
-
- Repeater {
- id: itemsRepeater
- model: root.items
-
- Loader {
- id: menuItemLoader
-
- property var menuItem: modelData
- readonly property bool isSeparator: !!menuItem && menuItem.type === MenuItemType.Separator
- readonly property bool isSubmenu: !!menuItem && menuItem.type === MenuItemType.Menu
- property bool selected: !isSeparator && root.__currentIndex === index
- property string text: isSubmenu ? menuItem.title : !isSeparator ? menuItem.text : ""
- property bool showUnderlined: __contentItem.altPressed
-
- property int menuItemIndex: index
-
- sourceComponent: menuFrameLoader.menuItemStyle
- enabled: visible && !isSeparator && !!menuItem && menuItem.enabled
- visible: menuItem.visible
- active: visible
-
- function showSubMenu(immediately) {
- if (immediately) {
- if (root.__currentIndex === menuItemIndex) {
- if (Qt.application.layoutDirection === Qt.RightToLeft)
- menuItem.__popup(0, 0, -1)
- else
- menuItem.__popup(menuFrameLoader.subMenuXPos, 0, -1)
- }
- } else {
- openMenuTimer.start()
- }
- }
-
- Timer {
- id: openMenuTimer
- interval: 50
- onTriggered: menuItemLoader.showSubMenu(true)
- }
-
- function closeSubMenu() { closeMenuTimer.start() }
-
- Timer {
- id: closeMenuTimer
- interval: 1
- onTriggered: {
- if (root.__currentIndex !== menuItemIndex)
- menuItem.__closeMenu()
- }
- }
-
- Component.onCompleted: {
- menuItem.__visualItem = menuItemLoader
-
- var title = text
- var ampersandPos = title.indexOf("&")
- if (ampersandPos !== -1)
- menuFrameLoader.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = menuItemLoader
- }
- }
+ Timer {
+ id: openMenuTimer
+ interval: 50
+ onTriggered: menuItemLoader.showSubMenu(true)
}
- onWidthChanged: {
- for (var i = 0; i < children.length; i++) {
- var item = children[i]["item"]
- if (item)
- item.implicitWidth = Math.max(root.__minimumWidth, implicitWidth)
+ function closeSubMenu() { closeMenuTimer.start() }
+
+ Timer {
+ id: closeMenuTimer
+ interval: 1
+ onTriggered: {
+ if (root.__currentIndex !== menuItemIndex)
+ menuItem.__closeMenu()
}
}
+
+ onLoaded: {
+ menuItem.__visualItem = menuItemLoader
+
+ if (content.width < item.implicitWidth)
+ content.width = item.implicitWidth
+
+ var title = text
+ var ampersandPos = title.indexOf("&")
+ if (ampersandPos !== -1)
+ menuFrameLoader.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = menuItemLoader
+ }
+
+ Binding {
+ target: menuItemLoader.item
+ property: "width"
+ value: Math.max(root.__minimumWidth, content.width)
+ }
}
}
}