From bfb2b044bb52670480548cc3269cdf8b55ff907a Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Mon, 5 Dec 2022 15:43:05 +0100 Subject: [PATCH 01/20] nested popups will always try to take up the same vertical area as it's parent. If the popup is small than it's parent it won't go below or above the parent. If it is longer than the parent, the bottom will extend past the parent. CURA-9793 --- resources/qml/Menus/MaterialBrandMenu.qml | 44 ++++++++++++++++------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index e256e75904..35a48e4b2c 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -94,16 +94,27 @@ Cura.MenuItem x: parent.width - UM.Theme.getSize("default_lining").width y: { - // Checks if popup is more than halfway down the screen AND further than 400 down (this avoids popup going off the top of screen) - // If it is then the popup will push up instead of down - // This fixes the popups appearing bellow the bottom of the screen. + var popupHeight = materialTypesModel.material_types.count * UM.Theme.getSize("menu").height + var spaceToBottom = materialBrandMenu.parent.height - parent.y // Space from hovered item to bottom of list +// +// print(materialTypesModel) +// print(materialTypesModel.material_types) +// print(materialTypesModel.material_types.count) +// print("popupHeight: " + popupHeight) +// print("parentHeight: " + parentHeight) +// print("parent.y: " + parent.y) - if (materialBrandMenu.parent.height / 2 < parent.y && parent.y > 400) { - flipped = true - return -UM.Theme.getSize("default_lining").width - height + UM.Theme.getSize("menu").height + if (popupHeight < spaceToBottom) + { + return -UM.Theme.getSize("default_lining").width + } + else + { + // The popup is longer than the distance between the hovered item and the bottom of the item list. + // This pushes the popup upwards until the bottom lines up with the parent bottom. + // Only when popup is longer than the parent, the popup will flow out below the parent. + return -Math.max(parent.y - (materialBrandMenu.parent.height - popupHeight), 0) + (3 * UM.Theme.getSize("default_lining").height) } - flipped = false - return -UM.Theme.getSize("default_lining").width } padding: background.border.width @@ -243,11 +254,20 @@ Cura.MenuItem height: materialColorsList.height + padding * 2 x: parent.width y: { - // If flipped the popup should push up rather than down from the parent - if (brandMaterialBase.isFlipped) { - return -height + UM.Theme.getSize("menu").height + UM.Theme.getSize("default_lining").width + var popupHeight = model.colors.count * UM.Theme.getSize("menu").height + var spaceToBottom = materialTypesList.height - parent.y // Space from hovered item to bottom of list + + if (popupHeight < spaceToBottom) + { + return -UM.Theme.getSize("default_lining").width + } + else + { + // The popup is longer than the distance between the hovered item and the bottom of the item list. + // This pushes the popup upwards until the bottom lines up with the parent bottom. + // Only when popup is longer than the parent, the popup will flow out below the parent. + return -Math.max(parent.y - (materialTypesList.height - popupHeight), 0) } - return -UM.Theme.getSize("default_lining").width } property int itemHovered: 0 From 7185b898a3d821e6394e60890cbbcdab945a4b87 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Mon, 5 Dec 2022 15:44:27 +0100 Subject: [PATCH 02/20] remove comments CURA-9793 --- resources/qml/Menus/MaterialBrandMenu.qml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index 35a48e4b2c..f4f2fb5458 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -96,13 +96,6 @@ Cura.MenuItem y: { var popupHeight = materialTypesModel.material_types.count * UM.Theme.getSize("menu").height var spaceToBottom = materialBrandMenu.parent.height - parent.y // Space from hovered item to bottom of list -// -// print(materialTypesModel) -// print(materialTypesModel.material_types) -// print(materialTypesModel.material_types.count) -// print("popupHeight: " + popupHeight) -// print("parentHeight: " + parentHeight) -// print("parent.y: " + parent.y) if (popupHeight < spaceToBottom) { From d2ff62485d915d8b8bffd8f3a64288f6828eb4fe Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Mon, 5 Dec 2022 16:18:03 +0100 Subject: [PATCH 03/20] Fix popups not maxing height at top of parent CURA-9793 --- resources/qml/Menus/MaterialBrandMenu.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index f4f2fb5458..e096847016 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -106,7 +106,8 @@ Cura.MenuItem // The popup is longer than the distance between the hovered item and the bottom of the item list. // This pushes the popup upwards until the bottom lines up with the parent bottom. // Only when popup is longer than the parent, the popup will flow out below the parent. - return -Math.max(parent.y - (materialBrandMenu.parent.height - popupHeight), 0) + (3 * UM.Theme.getSize("default_lining").height) + var topOfParent = parent.y + (3 * UM.Theme.getSize("default_lining").height) + return -Math.min(parent.y - (materialBrandMenu.parent.height - popupHeight ), topOfParent) } } @@ -259,7 +260,8 @@ Cura.MenuItem // The popup is longer than the distance between the hovered item and the bottom of the item list. // This pushes the popup upwards until the bottom lines up with the parent bottom. // Only when popup is longer than the parent, the popup will flow out below the parent. - return -Math.max(parent.y - (materialTypesList.height - popupHeight), 0) + var topOfParent = parent.y + (3 * UM.Theme.getSize("default_lining").height) + return -Math.min(parent.y - (materialTypesList.height - popupHeight), parent.y) } } From e5baa6e2bf6f862ccceca324cc416777f073787c Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 6 Dec 2022 15:18:32 +0100 Subject: [PATCH 04/20] Update resources/qml/Menus/MaterialBrandMenu.qml Co-authored-by: Jelle Spijker --- resources/qml/Menus/MaterialBrandMenu.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index e096847016..4afc197eba 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -99,7 +99,7 @@ Cura.MenuItem if (popupHeight < spaceToBottom) { - return -UM.Theme.getSize("default_lining").width + return -UM.Theme.getSize("default_lining").height } else { From 3dff780215d6488729f7c8ad7dd3e1993dc07ef5 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 6 Dec 2022 15:36:55 +0100 Subject: [PATCH 05/20] Adjust location of popups so they align with their parent popup. CURA-9793 --- resources/qml/Menus/MaterialBrandMenu.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index e096847016..396a7c2123 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -106,7 +106,7 @@ Cura.MenuItem // The popup is longer than the distance between the hovered item and the bottom of the item list. // This pushes the popup upwards until the bottom lines up with the parent bottom. // Only when popup is longer than the parent, the popup will flow out below the parent. - var topOfParent = parent.y + (3 * UM.Theme.getSize("default_lining").height) + var topOfParent = parent.y + UM.Theme.getSize("narrow_margin").height return -Math.min(parent.y - (materialBrandMenu.parent.height - popupHeight ), topOfParent) } } @@ -260,8 +260,8 @@ Cura.MenuItem // The popup is longer than the distance between the hovered item and the bottom of the item list. // This pushes the popup upwards until the bottom lines up with the parent bottom. // Only when popup is longer than the parent, the popup will flow out below the parent. - var topOfParent = parent.y + (3 * UM.Theme.getSize("default_lining").height) - return -Math.min(parent.y - (materialTypesList.height - popupHeight), parent.y) + var topOfParent = parent.y + UM.Theme.getSize("default_lining").height + return -Math.min(parent.y - (materialTypesList.height - popupHeight - UM.Theme.getSize("default_lining").height), topOfParent) } } From 4f4d2431fa57b1473654bdde49575b5a333f3f94 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Thu, 8 Dec 2022 16:18:58 +0100 Subject: [PATCH 06/20] The third nested popup will now always try to stay withen the vertical space of the root materials popup. See CURA-9522 for diagrams and more information. CURA-9522 --- resources/qml/Menus/MaterialBrandMenu.qml | 28 +++++++++++++++++++---- resources/qml/Menus/MaterialMenu.qml | 1 + 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index 66cc337f9d..ef1d0b30a3 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -16,6 +16,7 @@ Cura.MenuItem id: materialBrandMenu overrideShowArrow: true + property var rootHeight property var materialTypesModel text: materialTypesModel.name @@ -36,6 +37,7 @@ Cura.MenuItem UM.Label { + id: brandLableText text: replaceText(materialBrandMenu.text) Layout.fillWidth: true Layout.fillHeight:true @@ -248,6 +250,8 @@ Cura.MenuItem height: materialColorsList.height + padding * 2 x: parent.width y: { + // This popup will always try to stay within the vertical space of the parent of MaterialBrandMenu + // If it is larger than the parent, it will expand downwards. var popupHeight = model.colors.count * UM.Theme.getSize("menu").height var spaceToBottom = materialTypesList.height - parent.y // Space from hovered item to bottom of list @@ -257,11 +261,25 @@ Cura.MenuItem } else { - // The popup is longer than the distance between the hovered item and the bottom of the item list. - // This pushes the popup upwards until the bottom lines up with the parent bottom. - // Only when popup is longer than the parent, the popup will flow out below the parent. - var topOfParent = parent.y + UM.Theme.getSize("default_lining").height - return -Math.min(parent.y - (materialTypesList.height - popupHeight - UM.Theme.getSize("default_lining").height), topOfParent) + var yAlignedWithTopOfRootPopup = - materialBrandMenu.y - UM.Theme.getSize("default_lining").height + + if (popupHeight > rootHeight && popupHeight > menuPopup.height) + { + // The popup is taller than the root material popup and the popup is taller than it's parent popup + // This means it should align with the top of the root popup + if (menuPopup.height < rootHeight) + { + //The root is larger than than the parent popup. Align with root top + return -materialBrandMenu.y - UM.Theme.getSize("default_lining").height + } + else + { + // The parent popup is larger than the root we only have to align to the top of the parent + return -brandMaterialBase.y - UM.Theme.getSize("default_lining").height + } + } + // The bottom of the popup is aligned with the bottom of the parent popup + return materialTypesList.height - parent.y - popupHeight - UM.Theme.getSize("default_lining").height } } diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index cee28cee6a..94092dc4a7 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -101,6 +101,7 @@ Cura.Menu delegate: Cura.MaterialBrandMenu { materialTypesModel: model + rootHeight: materialMenu.height } onObjectAdded: function(index, object) { materialMenu.insertItem(index + 4, object)} onObjectRemoved: function(index, object) { materialMenu.removeItem(index) } From 7174861bba9bdbe502dab4fc3e2d19d5f39099f3 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 15:26:46 +0100 Subject: [PATCH 07/20] Move popups back on screen after opening them. CURA-6867 --- resources/qml/Cura.qml | 3 ++ resources/qml/Menus/MaterialBrandMenu.qml | 63 ++++++----------------- 2 files changed, 20 insertions(+), 46 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 6e36587b23..503caf2384 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -17,6 +17,9 @@ UM.MainWindow { id: base + property var main_window_height: base.height + readonly property var mainWindow: base + // Cura application window title title: { diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index ef1d0b30a3..cf94eb5238 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -94,23 +94,17 @@ Cura.MenuItem property var flipped: false - x: parent.width - UM.Theme.getSize("default_lining").width - y: { + onOpened: + { var popupHeight = materialTypesModel.material_types.count * UM.Theme.getSize("menu").height - var spaceToBottom = materialBrandMenu.parent.height - parent.y // Space from hovered item to bottom of list + var parentGlobalY = parent.mapToItem(null, 0, 0).y + var overflowY = (parentGlobalY + popupHeight) - mainWindow.height + y = overflowY > 0 ? -overflowY : 0 - if (popupHeight < spaceToBottom) - { - return -UM.Theme.getSize("default_lining").height - } - else - { - // The popup is longer than the distance between the hovered item and the bottom of the item list. - // This pushes the popup upwards until the bottom lines up with the parent bottom. - // Only when popup is longer than the parent, the popup will flow out below the parent. - var topOfParent = parent.y + UM.Theme.getSize("narrow_margin").height - return -Math.min(parent.y - (materialBrandMenu.parent.height - popupHeight ), topOfParent) - } + var defaultX = parent.width - UM.Theme.getSize("default_lining").width + var parentGlobalX = parent.mapToItem(null, 0, 0).x + var overflowX = (parentGlobalX + defaultX + menuPopup.width) - mainWindow.width + x = overflowX > 0 ? overflowX : defaultX } padding: background.border.width @@ -248,39 +242,16 @@ Cura.MenuItem id: colorPopup width: materialColorsList.width + padding * 2 height: materialColorsList.height + padding * 2 - x: parent.width - y: { - // This popup will always try to stay within the vertical space of the parent of MaterialBrandMenu - // If it is larger than the parent, it will expand downwards. + onOpened: + { var popupHeight = model.colors.count * UM.Theme.getSize("menu").height - var spaceToBottom = materialTypesList.height - parent.y // Space from hovered item to bottom of list + var parentGlobalY = parent.mapToItem(null, 0, 0).y + var overflowY = (parentGlobalY + popupHeight) - mainWindow.height + y = overflowY > 0 ? - overflowY - UM.Theme.getSize("default_lining").height: - UM.Theme.getSize("default_lining").height - if (popupHeight < spaceToBottom) - { - return -UM.Theme.getSize("default_lining").width - } - else - { - var yAlignedWithTopOfRootPopup = - materialBrandMenu.y - UM.Theme.getSize("default_lining").height - - if (popupHeight > rootHeight && popupHeight > menuPopup.height) - { - // The popup is taller than the root material popup and the popup is taller than it's parent popup - // This means it should align with the top of the root popup - if (menuPopup.height < rootHeight) - { - //The root is larger than than the parent popup. Align with root top - return -materialBrandMenu.y - UM.Theme.getSize("default_lining").height - } - else - { - // The parent popup is larger than the root we only have to align to the top of the parent - return -brandMaterialBase.y - UM.Theme.getSize("default_lining").height - } - } - // The bottom of the popup is aligned with the bottom of the parent popup - return materialTypesList.height - parent.y - popupHeight - UM.Theme.getSize("default_lining").height - } + var parentGlobalX = materialTypesList.mapToItem(null, 0, 0).x + var overflowX = (parentGlobalX + parent.width + colorPopup.width) - mainWindow.width + x = overflowX > 0 ? parent.width - overflowX : parent.width } property int itemHovered: 0 From d4679515b674ccca5dcb6476430553c0d62c8420 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 17:45:28 +0100 Subject: [PATCH 08/20] Add scrollview to material list CURA-6867 --- resources/qml/Menus/MaterialBrandMenu.qml | 145 +++++++++++++--------- 1 file changed, 85 insertions(+), 60 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index cf94eb5238..37d5ed81b5 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -244,6 +244,8 @@ Cura.MenuItem height: materialColorsList.height + padding * 2 onOpened: { + // This will be resolved before opening the popup if directly assigned to the properties + // This forces these values to update whenever a popup is opened var popupHeight = model.colors.count * UM.Theme.getSize("menu").height var parentGlobalY = parent.mapToItem(null, 0, 0).y var overflowY = (parentGlobalY + popupHeight) - mainWindow.height @@ -252,6 +254,10 @@ Cura.MenuItem var parentGlobalX = materialTypesList.mapToItem(null, 0, 0).x var overflowX = (parentGlobalX + parent.width + colorPopup.width) - mainWindow.width x = overflowX > 0 ? parent.width - overflowX : parent.width + + var popupHeight = model.colors.count * UM.Theme.getSize("menu").height + scrollView.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight + colorPopup.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight } property int itemHovered: 0 @@ -263,79 +269,98 @@ Cura.MenuItem border.color: UM.Theme.getColor("lining") border.width: UM.Theme.getSize("default_lining").width } - - Column + ScrollView { - id: materialColorsList - property var brandColors: model.colors - spacing: 0 + id: scrollView + width: UM.Theme.getSize("menu").width + scrollbar.width + height: parent.height + clip: true - Repeater + ScrollBar.vertical: UM.ScrollBar { - model: parent.brandColors + id: scrollbar + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + } - delegate: Rectangle + Column + { + id: materialColorsList + property var brandColors: model.colors + width: UM.Theme.getSize("menu").width + height: parent.height + spacing: 0 + + Repeater { - height: UM.Theme.getSize("menu").height - width: UM.Theme.getSize("menu").width + model: parent.brandColors - color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("background_1") - - Item + delegate: Rectangle { - opacity: materialBrandMenu.enabled ? 1 : 0.5 - anchors.fill: parent + height: UM.Theme.getSize("menu").height + width: parent.width - //Checkmark, if the material is selected. - UM.ColorImage +// color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("background_1") + + Rectangle { - id: checkmark - visible: model.id === materialMenu.activeMaterialId - height: UM.Theme.getSize("default_arrow").height - width: height - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.verticalCenter: parent.verticalCenter - source: UM.Theme.getIcon("Check", "low") - color: UM.Theme.getColor("setting_control_text") + height: parent.height + width: parent.width + opacity: materialBrandMenu.enabled ? 1 : 0.5 + anchors.fill: parent + + //Checkmark, if the material is selected. + UM.ColorImage + { + id: checkmark + visible: model.id === materialMenu.activeMaterialId + height: UM.Theme.getSize("default_arrow").height + width: height + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.verticalCenter: parent.verticalCenter + source: UM.Theme.getIcon("Check", "low") + color: UM.Theme.getColor("setting_control_text") + } + + UM.Label + { + text: model.name + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("default_arrow").height + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + + elide: Label.ElideRight + wrapMode: Text.NoWrap + } } - UM.Label + MouseArea { - text: model.name - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("default_arrow").height - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width + id: materialColorButton + anchors.fill: parent - elide: Label.ElideRight - wrapMode: Text.NoWrap - } - } - - MouseArea - { - id: materialColorButton - anchors.fill: parent - - hoverEnabled: true - onClicked: - { - Cura.MachineManager.setMaterial(extruderIndex, model.container_node); - menuPopup.close(); - colorPopup.close(); - materialMenu.close(); - } - onEntered: - { - menuPopup.itemHovered += 1; - colorPopup.itemHovered += 1; - } - onExited: - { - menuPopup.itemHovered -= 1; - colorPopup.itemHovered -= 1; + hoverEnabled: true + onClicked: + { + Cura.MachineManager.setMaterial(extruderIndex, model.container_node); + menuPopup.close(); + colorPopup.close(); + materialMenu.close(); + } + onEntered: + { + menuPopup.itemHovered += 1; + colorPopup.itemHovered += 1; + } + onExited: + { + menuPopup.itemHovered -= 1; + colorPopup.itemHovered -= 1; + } } } } From e0a091e768fcb313093a9bbd676dd561eb1826a8 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 18:06:40 +0100 Subject: [PATCH 09/20] Add scrollview to nested material list CURA-6867 --- resources/qml/Menus/MaterialBrandMenu.qml | 426 +++++++++++----------- 1 file changed, 223 insertions(+), 203 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index 37d5ed81b5..5d55b59582 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -105,6 +105,9 @@ Cura.MenuItem var parentGlobalX = parent.mapToItem(null, 0, 0).x var overflowX = (parentGlobalX + defaultX + menuPopup.width) - mainWindow.width x = overflowX > 0 ? overflowX : defaultX + + scrollViewMaterialType.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight + menuPopup.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight } padding: background.border.width @@ -128,238 +131,255 @@ Cura.MenuItem border.width: UM.Theme.getSize("default_lining").width } - Column + ScrollView { - id: materialTypesList - spacing: 0 + id: scrollViewMaterialType + width: UM.Theme.getSize("menu").width + scrollbar.width + height: parent.height + clip: true - property var brandMaterials: materialTypesModel.material_types - - Repeater + ScrollBar.vertical: UM.ScrollBar { - model: parent.brandMaterials + id: scrollbar + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + } - //Use a MouseArea and Rectangle, not a button, because the button grabs mouse events which makes the parent pop-up think it's no longer being hovered. - //With a custom MouseArea, we can prevent the events from being accepted. - delegate: Rectangle + Column + { + id: materialTypesList + width: UM.Theme.getSize("menu").width + height: parent.height + spacing: 0 + + property var brandMaterials: materialTypesModel.material_types + + Repeater { - id: brandMaterialBase - height: UM.Theme.getSize("menu").height - width: UM.Theme.getSize("menu").width + model: parent.brandMaterials - color: materialTypeButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("background_1") - - property var isFlipped: menuPopup.flipped - - RowLayout + //Use a MouseArea and Rectangle, not a button, because the button grabs mouse events which makes the parent pop-up think it's no longer being hovered. + //With a custom MouseArea, we can prevent the events from being accepted. + delegate: Rectangle { - spacing: 0 - opacity: materialBrandMenu.enabled ? 1 : 0.5 - height: parent.height - width: parent.width + id: brandMaterialBase + height: UM.Theme.getSize("menu").height + width: UM.Theme.getSize("menu").width - Item + color: materialTypeButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("background_1") + + property var isFlipped: menuPopup.flipped + + RowLayout { - // Spacer - width: UM.Theme.getSize("default_margin").width - } - - UM.Label - { - text: model.name - Layout.fillWidth: true - Layout.fillHeight: true - elide: Label.ElideRight - wrapMode: Text.NoWrap - } - - Item - { - Layout.fillWidth: true - } - - UM.ColorImage - { - height: UM.Theme.getSize("default_arrow").height - width: UM.Theme.getSize("default_arrow").width - color: UM.Theme.getColor("setting_control_text") - source: UM.Theme.getIcon("ChevronSingleRight") - } - - Item - { - // Right side margin - width: UM.Theme.getSize("default_margin").width - } - } - - MouseArea - { - id: materialTypeButton - anchors.fill: parent - - hoverEnabled: true - acceptedButtons: Qt.NoButton - - onEntered: - { - menuPopup.itemHovered += 1; - showSubTimer.restartTimer(); - } - onExited: - { - menuPopup.itemHovered -= 1; - hideSubTimer.restartTimer(); - } - } - Timer - { - id: showSubTimer - interval: 250 - function restartTimer() - { - restart(); - running = Qt.binding(function() { return materialTypeButton.containsMouse; }); - hideSubTimer.running = false; - } - onTriggered: colorPopup.open() - } - Timer - { - id: hideSubTimer - interval: 250 - function restartTimer() //Restart but re-evaluate the running property then. - { - restart(); - running = Qt.binding(function() { return !materialTypeButton.containsMouse && !colorPopup.itemHovered > 0; }); - showSubTimer.running = false; - } - onTriggered: colorPopup.close() - } - - Popup - { - id: colorPopup - width: materialColorsList.width + padding * 2 - height: materialColorsList.height + padding * 2 - onOpened: - { - // This will be resolved before opening the popup if directly assigned to the properties - // This forces these values to update whenever a popup is opened - var popupHeight = model.colors.count * UM.Theme.getSize("menu").height - var parentGlobalY = parent.mapToItem(null, 0, 0).y - var overflowY = (parentGlobalY + popupHeight) - mainWindow.height - y = overflowY > 0 ? - overflowY - UM.Theme.getSize("default_lining").height: - UM.Theme.getSize("default_lining").height - - var parentGlobalX = materialTypesList.mapToItem(null, 0, 0).x - var overflowX = (parentGlobalX + parent.width + colorPopup.width) - mainWindow.width - x = overflowX > 0 ? parent.width - overflowX : parent.width - - var popupHeight = model.colors.count * UM.Theme.getSize("menu").height - scrollView.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight - colorPopup.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight - } - - property int itemHovered: 0 - padding: background.border.width - - background: Rectangle - { - color: UM.Theme.getColor("main_background") - border.color: UM.Theme.getColor("lining") - border.width: UM.Theme.getSize("default_lining").width - } - ScrollView - { - id: scrollView - width: UM.Theme.getSize("menu").width + scrollbar.width + spacing: 0 + opacity: materialBrandMenu.enabled ? 1 : 0.5 height: parent.height - clip: true + width: parent.width - ScrollBar.vertical: UM.ScrollBar + Item { - id: scrollbar - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom + // Spacer + width: UM.Theme.getSize("default_margin").width } - Column + UM.Label { - id: materialColorsList - property var brandColors: model.colors - width: UM.Theme.getSize("menu").width + text: model.name + Layout.fillWidth: true + Layout.fillHeight: true + elide: Label.ElideRight + wrapMode: Text.NoWrap + } + + Item + { + Layout.fillWidth: true + } + + UM.ColorImage + { + height: UM.Theme.getSize("default_arrow").height + width: UM.Theme.getSize("default_arrow").width + color: UM.Theme.getColor("setting_control_text") + source: UM.Theme.getIcon("ChevronSingleRight") + } + + Item + { + // Right side margin + width: UM.Theme.getSize("default_margin").width + } + } + + MouseArea + { + id: materialTypeButton + anchors.fill: parent + + hoverEnabled: true + acceptedButtons: Qt.NoButton + + onEntered: + { + menuPopup.itemHovered += 1; + showSubTimer.restartTimer(); + } + onExited: + { + menuPopup.itemHovered -= 1; + hideSubTimer.restartTimer(); + } + } + Timer + { + id: showSubTimer + interval: 250 + function restartTimer() + { + restart(); + running = Qt.binding(function() { return materialTypeButton.containsMouse; }); + hideSubTimer.running = false; + } + onTriggered: colorPopup.open() + } + Timer + { + id: hideSubTimer + interval: 250 + function restartTimer() //Restart but re-evaluate the running property then. + { + restart(); + running = Qt.binding(function() { return !materialTypeButton.containsMouse && !colorPopup.itemHovered > 0; }); + showSubTimer.running = false; + } + onTriggered: colorPopup.close() + } + + Popup + { + id: colorPopup + width: materialColorsList.width + padding * 2 + height: materialColorsList.height + padding * 2 + onOpened: + { + // This will be resolved before opening the popup if directly assigned to the properties + // This forces these values to update whenever a popup is opened + var popupHeight = model.colors.count * UM.Theme.getSize("menu").height + var parentGlobalY = parent.mapToItem(null, 0, 0).y + var overflowY = (parentGlobalY + popupHeight) - mainWindow.height + y = overflowY > 0 ? - overflowY - UM.Theme.getSize("default_lining").height: - UM.Theme.getSize("default_lining").height + + var parentGlobalX = materialTypesList.mapToItem(null, 0, 0).x + var overflowX = (parentGlobalX + parent.width + colorPopup.width) - mainWindow.width + x = overflowX > 0 ? parent.width - overflowX : parent.width + + scrollView.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight + colorPopup.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight + } + + property int itemHovered: 0 + padding: background.border.width + + background: Rectangle + { + color: UM.Theme.getColor("main_background") + border.color: UM.Theme.getColor("lining") + border.width: UM.Theme.getSize("default_lining").width + } + ScrollView + { + id: scrollView + width: UM.Theme.getSize("menu").width + scrollbar.width height: parent.height - spacing: 0 + clip: true - Repeater + ScrollBar.vertical: UM.ScrollBar { - model: parent.brandColors + id: scrollbar + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + } - delegate: Rectangle + Column + { + id: materialColorsList + property var brandColors: model.colors + width: UM.Theme.getSize("menu").width + height: parent.height + spacing: 0 + + Repeater { - height: UM.Theme.getSize("menu").height - width: parent.width + model: parent.brandColors -// color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("background_1") - - Rectangle + delegate: Rectangle { - height: parent.height + height: UM.Theme.getSize("menu").height width: parent.width - opacity: materialBrandMenu.enabled ? 1 : 0.5 - anchors.fill: parent - //Checkmark, if the material is selected. - UM.ColorImage + color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("background_1") + + Rectangle { - id: checkmark - visible: model.id === materialMenu.activeMaterialId - height: UM.Theme.getSize("default_arrow").height - width: height - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.verticalCenter: parent.verticalCenter - source: UM.Theme.getIcon("Check", "low") - color: UM.Theme.getColor("setting_control_text") + height: parent.height + width: parent.width + opacity: materialBrandMenu.enabled ? 1 : 0.5 + anchors.fill: parent + + //Checkmark, if the material is selected. + UM.ColorImage + { + id: checkmark + visible: model.id === materialMenu.activeMaterialId + height: UM.Theme.getSize("default_arrow").height + width: height + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.verticalCenter: parent.verticalCenter + source: UM.Theme.getIcon("Check", "low") + color: UM.Theme.getColor("setting_control_text") + } + + UM.Label + { + text: model.name + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("default_arrow").height + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + + elide: Label.ElideRight + wrapMode: Text.NoWrap + } } - UM.Label + MouseArea { - text: model.name - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("default_arrow").height - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width + id: materialColorButton + anchors.fill: parent - elide: Label.ElideRight - wrapMode: Text.NoWrap - } - } - - MouseArea - { - id: materialColorButton - anchors.fill: parent - - hoverEnabled: true - onClicked: - { - Cura.MachineManager.setMaterial(extruderIndex, model.container_node); - menuPopup.close(); - colorPopup.close(); - materialMenu.close(); - } - onEntered: - { - menuPopup.itemHovered += 1; - colorPopup.itemHovered += 1; - } - onExited: - { - menuPopup.itemHovered -= 1; - colorPopup.itemHovered -= 1; + hoverEnabled: true + onClicked: + { + Cura.MachineManager.setMaterial(extruderIndex, model.container_node); + menuPopup.close(); + colorPopup.close(); + materialMenu.close(); + } + onEntered: + { + menuPopup.itemHovered += 1; + colorPopup.itemHovered += 1; + } + onExited: + { + menuPopup.itemHovered -= 1; + colorPopup.itemHovered -= 1; + } } } } From 93a51b6da9a4fd06af91ff88c85580f73e8c4837 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 23 Dec 2022 13:40:20 +0100 Subject: [PATCH 10/20] Remove unused property CURA-9522 --- resources/qml/Cura.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 503caf2384..cb570fce46 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -17,7 +17,6 @@ UM.MainWindow { id: base - property var main_window_height: base.height readonly property var mainWindow: base // Cura application window title From 15761b6c5981bba5b1030cb4a7e7441dfaf4a82b Mon Sep 17 00:00:00 2001 From: Casper Lamboo Date: Fri, 23 Dec 2022 13:51:32 +0100 Subject: [PATCH 11/20] Code style CURA-9522 --- resources/qml/Menus/MaterialBrandMenu.qml | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index 5d55b59582..f31df33425 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -16,7 +16,7 @@ Cura.MenuItem id: materialBrandMenu overrideShowArrow: true - property var rootHeight + property int rootHeight property var materialTypesModel text: materialTypesModel.name @@ -99,15 +99,15 @@ Cura.MenuItem var popupHeight = materialTypesModel.material_types.count * UM.Theme.getSize("menu").height var parentGlobalY = parent.mapToItem(null, 0, 0).y var overflowY = (parentGlobalY + popupHeight) - mainWindow.height - y = overflowY > 0 ? -overflowY : 0 + menuPopup.y = overflowY > 0 ? -overflowY : 0 var defaultX = parent.width - UM.Theme.getSize("default_lining").width var parentGlobalX = parent.mapToItem(null, 0, 0).x var overflowX = (parentGlobalX + defaultX + menuPopup.width) - mainWindow.width - x = overflowX > 0 ? overflowX : defaultX + menuPopup.x = overflowX > 0 ? overflowX : defaultX - scrollViewMaterialType.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight - menuPopup.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight + scrollViewMaterialType.height = popupHeight > mainWindow.height ? mainWindow.height : popupHeight + menuPopup.height = popupHeight > mainWindow.height ? mainWindow.heigh : popupHeight } padding: background.border.width @@ -169,7 +169,7 @@ Cura.MenuItem color: materialTypeButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("background_1") - property var isFlipped: menuPopup.flipped + property bool isFlipped: menuPopup.flipped RowLayout { @@ -206,7 +206,7 @@ Cura.MenuItem source: UM.Theme.getIcon("ChevronSingleRight") } - Item + Item { // Right side margin width: UM.Theme.getSize("default_margin").width @@ -269,14 +269,14 @@ Cura.MenuItem var popupHeight = model.colors.count * UM.Theme.getSize("menu").height var parentGlobalY = parent.mapToItem(null, 0, 0).y var overflowY = (parentGlobalY + popupHeight) - mainWindow.height - y = overflowY > 0 ? - overflowY - UM.Theme.getSize("default_lining").height: - UM.Theme.getSize("default_lining").height + colorPopup.y = overflowY > 0 ? - overflowY - UM.Theme.getSize("default_lining").height : -UM.Theme.getSize("default_lining").height var parentGlobalX = materialTypesList.mapToItem(null, 0, 0).x var overflowX = (parentGlobalX + parent.width + colorPopup.width) - mainWindow.width - x = overflowX > 0 ? parent.width - overflowX : parent.width + colorPopup.x = overflowX > 0 ? parent.width - overflowX : parent.width - scrollView.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight - colorPopup.height = popupHeight > mainWindow.height ? mainWindow.height: popupHeight + scrollView.height = popupHeight > mainWindow.height ? mainWindow.height : popupHeight + colorPopup.height = popupHeight > mainWindow.height ? mainWindow.height : popupHeight } property int itemHovered: 0 @@ -306,7 +306,7 @@ Cura.MenuItem Column { id: materialColorsList - property var brandColors: model.colors + property color brandColors: model.colors width: UM.Theme.getSize("menu").width height: parent.height spacing: 0 From 92e6d5007fe5d0873ff9520ba7d280a14d4692ff Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 23 Dec 2022 14:21:12 +0100 Subject: [PATCH 12/20] Remove unused property CURA-9793 --- resources/qml/Menus/MaterialBrandMenu.qml | 1 - resources/qml/Menus/MaterialMenu.qml | 1 - 2 files changed, 2 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index f31df33425..9ae3ed4cab 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -16,7 +16,6 @@ Cura.MenuItem id: materialBrandMenu overrideShowArrow: true - property int rootHeight property var materialTypesModel text: materialTypesModel.name diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 94092dc4a7..cee28cee6a 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -101,7 +101,6 @@ Cura.Menu delegate: Cura.MaterialBrandMenu { materialTypesModel: model - rootHeight: materialMenu.height } onObjectAdded: function(index, object) { materialMenu.insertItem(index + 4, object)} onObjectRemoved: function(index, object) { materialMenu.removeItem(index) } From 5a8bf7f37bf285a5d29acb4515cdc065d0c6d492 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 23 Dec 2022 16:11:06 +0100 Subject: [PATCH 13/20] Fix material colors not showing up CURA-9522 --- resources/qml/Menus/MaterialBrandMenu.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index 9ae3ed4cab..71d6434a8b 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -305,7 +305,7 @@ Cura.MenuItem Column { id: materialColorsList - property color brandColors: model.colors + property var brandColors: model.colors width: UM.Theme.getSize("menu").width height: parent.height spacing: 0 From 0ecfdd063dd38ab2bc7c697685ea79544c04de22 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 23 Dec 2022 16:12:25 +0100 Subject: [PATCH 14/20] Show bottom border of material brands CURA-9522 --- resources/qml/Menus/MaterialBrandMenu.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index 71d6434a8b..6cf3c74cfb 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -166,7 +166,7 @@ Cura.MenuItem height: UM.Theme.getSize("menu").height width: UM.Theme.getSize("menu").width - color: materialTypeButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("background_1") + color: materialTypeButton.containsMouse ? "transparent" : UM.Theme.getColor("background_1") property bool isFlipped: menuPopup.flipped @@ -319,7 +319,7 @@ Cura.MenuItem height: UM.Theme.getSize("menu").height width: parent.width - color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("background_1") + color: materialColorButton.containsMouse ? "transparent" : UM.Theme.getColor("background_1") Rectangle { From ab49dcceb5fa4282c44df12e27f54be94e6a7b49 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 23 Dec 2022 16:16:19 +0100 Subject: [PATCH 15/20] Show bottom border of material brands CURA-9522 --- resources/qml/Menus/MaterialBrandMenu.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index 6cf3c74cfb..0820ec2f2d 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -166,7 +166,7 @@ Cura.MenuItem height: UM.Theme.getSize("menu").height width: UM.Theme.getSize("menu").width - color: materialTypeButton.containsMouse ? "transparent" : UM.Theme.getColor("background_1") + color: materialTypeButton.containsMouse ? UM.Theme.getColor("background_2") : "transparent" property bool isFlipped: menuPopup.flipped @@ -319,7 +319,7 @@ Cura.MenuItem height: UM.Theme.getSize("menu").height width: parent.width - color: materialColorButton.containsMouse ? "transparent" : UM.Theme.getColor("background_1") + color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : "transparent" Rectangle { From 20fdf22e35abc984d2fdd9824a5d14dee84a4a70 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 23 Dec 2022 16:18:33 +0100 Subject: [PATCH 16/20] Show bottom border of material brands CURA-9522 --- resources/qml/Menus/MaterialBrandMenu.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index 0820ec2f2d..b0d09eacae 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -321,7 +321,7 @@ Cura.MenuItem color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : "transparent" - Rectangle + Item { height: parent.height width: parent.width From e490250d9d2c809c83f07551a044172e1dee02c4 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 23 Dec 2022 19:40:27 +0100 Subject: [PATCH 17/20] Clean up code Create separate re-usable component for `MaterialBrandSubMenu` CURA-9522 --- resources/qml/Cura.qml | 6 +- resources/qml/Menus/MaterialBrandMenu.qml | 426 ++++++++----------- resources/qml/Menus/MaterialBrandSubMenu.qml | 117 +++++ 3 files changed, 291 insertions(+), 258 deletions(-) create mode 100644 resources/qml/Menus/MaterialBrandSubMenu.qml diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index cb570fce46..669fd1041e 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -17,7 +17,11 @@ UM.MainWindow { id: base - readonly property var mainWindow: base + Item + { + id: mainWindow + anchors.fill: parent + } // Cura application window title title: diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index b0d09eacae..e514de04a4 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Ultimaker B.V. +// Copyright (c) 2022 UltiMaker // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 @@ -85,35 +85,15 @@ Cura.MenuItem onTriggered: menuPopup.close() } - Popup + MaterialBrandSubMenu { id: menuPopup - width: materialTypesList.width + padding * 2 - height: materialTypesList.height + padding * 2 - property var flipped: false - - onOpened: - { - var popupHeight = materialTypesModel.material_types.count * UM.Theme.getSize("menu").height - var parentGlobalY = parent.mapToItem(null, 0, 0).y - var overflowY = (parentGlobalY + popupHeight) - mainWindow.height - menuPopup.y = overflowY > 0 ? -overflowY : 0 - - var defaultX = parent.width - UM.Theme.getSize("default_lining").width - var parentGlobalX = parent.mapToItem(null, 0, 0).x - var overflowX = (parentGlobalX + defaultX + menuPopup.width) - mainWindow.width - menuPopup.x = overflowX > 0 ? overflowX : defaultX - - scrollViewMaterialType.height = popupHeight > mainWindow.height ? mainWindow.height : popupHeight - menuPopup.height = popupHeight > mainWindow.height ? mainWindow.heigh : popupHeight - } - - padding: background.border.width // Nasty hack to ensure that we can keep track if the popup contains the mouse. // Since we also want a hover for the sub items (and these events are sent async) // We have to keep a count of itemHovered (instead of just a bool) property int itemHovered: 0 + MouseArea { id: submenuArea @@ -123,263 +103,195 @@ Cura.MenuItem onEntered: hideTimer.restartTimer() } - background: Rectangle + Column { - color: UM.Theme.getColor("main_background") - border.color: UM.Theme.getColor("lining") - border.width: UM.Theme.getSize("default_lining").width - } + id: materialTypesList + width: UM.Theme.getSize("menu").width + height: childrenRect.height + spacing: 0 - ScrollView - { - id: scrollViewMaterialType - width: UM.Theme.getSize("menu").width + scrollbar.width - height: parent.height - clip: true + property var brandMaterials: materialTypesModel.material_types - ScrollBar.vertical: UM.ScrollBar + Repeater { - id: scrollbar - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom - } + model: parent.brandMaterials - Column - { - id: materialTypesList - width: UM.Theme.getSize("menu").width - height: parent.height - spacing: 0 - - property var brandMaterials: materialTypesModel.material_types - - Repeater + //Use a MouseArea and Rectangle, not a button, because the button grabs mouse events which makes the parent pop-up think it's no longer being hovered. + //With a custom MouseArea, we can prevent the events from being accepted. + delegate: Rectangle { - model: parent.brandMaterials + id: brandMaterialBase + height: UM.Theme.getSize("menu").height + width: UM.Theme.getSize("menu").width - //Use a MouseArea and Rectangle, not a button, because the button grabs mouse events which makes the parent pop-up think it's no longer being hovered. - //With a custom MouseArea, we can prevent the events from being accepted. - delegate: Rectangle + color: materialTypeButton.containsMouse ? UM.Theme.getColor("background_2") : "transparent" + + RowLayout { - id: brandMaterialBase - height: UM.Theme.getSize("menu").height - width: UM.Theme.getSize("menu").width + spacing: 0 + opacity: materialBrandMenu.enabled ? 1 : 0.5 + height: parent.height + width: parent.width - color: materialTypeButton.containsMouse ? UM.Theme.getColor("background_2") : "transparent" - - property bool isFlipped: menuPopup.flipped - - RowLayout + Item { + // Spacer + width: UM.Theme.getSize("default_margin").width + } + + UM.Label + { + text: model.name + Layout.fillWidth: true + Layout.fillHeight: true + elide: Label.ElideRight + wrapMode: Text.NoWrap + } + + Item + { + Layout.fillWidth: true + } + + UM.ColorImage + { + height: UM.Theme.getSize("default_arrow").height + width: UM.Theme.getSize("default_arrow").width + color: UM.Theme.getColor("setting_control_text") + source: UM.Theme.getIcon("ChevronSingleRight") + } + + Item + { + // Right side margin + width: UM.Theme.getSize("default_margin").width + } + } + + MouseArea + { + id: materialTypeButton + anchors.fill: parent + + hoverEnabled: true + acceptedButtons: Qt.NoButton + + onEntered: + { + menuPopup.itemHovered += 1; + showSubTimer.restartTimer(); + } + onExited: + { + menuPopup.itemHovered -= 1; + hideSubTimer.restartTimer(); + } + } + Timer + { + id: showSubTimer + interval: 250 + function restartTimer() + { + restart(); + running = Qt.binding(function() { return materialTypeButton.containsMouse; }); + hideSubTimer.running = false; + } + onTriggered: colorPopup.open() + } + Timer + { + id: hideSubTimer + interval: 250 + function restartTimer() //Restart but re-evaluate the running property then. + { + restart(); + running = Qt.binding(function() { return !materialTypeButton.containsMouse && !colorPopup.itemHovered > 0; }); + showSubTimer.running = false; + } + onTriggered: colorPopup.close() + } + + MaterialBrandSubMenu + { + id: colorPopup + property int itemHovered: 0 + + Column + { + id: materialColorsList + property var brandColors: model.colors + width: UM.Theme.getSize("menu").width + height: childrenRect.height spacing: 0 - opacity: materialBrandMenu.enabled ? 1 : 0.5 - height: parent.height - width: parent.width - Item + Repeater { - // Spacer - width: UM.Theme.getSize("default_margin").width - } + model: parent.brandColors - UM.Label - { - text: model.name - Layout.fillWidth: true - Layout.fillHeight: true - elide: Label.ElideRight - wrapMode: Text.NoWrap - } - - Item - { - Layout.fillWidth: true - } - - UM.ColorImage - { - height: UM.Theme.getSize("default_arrow").height - width: UM.Theme.getSize("default_arrow").width - color: UM.Theme.getColor("setting_control_text") - source: UM.Theme.getIcon("ChevronSingleRight") - } - - Item - { - // Right side margin - width: UM.Theme.getSize("default_margin").width - } - } - - MouseArea - { - id: materialTypeButton - anchors.fill: parent - - hoverEnabled: true - acceptedButtons: Qt.NoButton - - onEntered: - { - menuPopup.itemHovered += 1; - showSubTimer.restartTimer(); - } - onExited: - { - menuPopup.itemHovered -= 1; - hideSubTimer.restartTimer(); - } - } - Timer - { - id: showSubTimer - interval: 250 - function restartTimer() - { - restart(); - running = Qt.binding(function() { return materialTypeButton.containsMouse; }); - hideSubTimer.running = false; - } - onTriggered: colorPopup.open() - } - Timer - { - id: hideSubTimer - interval: 250 - function restartTimer() //Restart but re-evaluate the running property then. - { - restart(); - running = Qt.binding(function() { return !materialTypeButton.containsMouse && !colorPopup.itemHovered > 0; }); - showSubTimer.running = false; - } - onTriggered: colorPopup.close() - } - - Popup - { - id: colorPopup - width: materialColorsList.width + padding * 2 - height: materialColorsList.height + padding * 2 - onOpened: - { - // This will be resolved before opening the popup if directly assigned to the properties - // This forces these values to update whenever a popup is opened - var popupHeight = model.colors.count * UM.Theme.getSize("menu").height - var parentGlobalY = parent.mapToItem(null, 0, 0).y - var overflowY = (parentGlobalY + popupHeight) - mainWindow.height - colorPopup.y = overflowY > 0 ? - overflowY - UM.Theme.getSize("default_lining").height : -UM.Theme.getSize("default_lining").height - - var parentGlobalX = materialTypesList.mapToItem(null, 0, 0).x - var overflowX = (parentGlobalX + parent.width + colorPopup.width) - mainWindow.width - colorPopup.x = overflowX > 0 ? parent.width - overflowX : parent.width - - scrollView.height = popupHeight > mainWindow.height ? mainWindow.height : popupHeight - colorPopup.height = popupHeight > mainWindow.height ? mainWindow.height : popupHeight - } - - property int itemHovered: 0 - padding: background.border.width - - background: Rectangle - { - color: UM.Theme.getColor("main_background") - border.color: UM.Theme.getColor("lining") - border.width: UM.Theme.getSize("default_lining").width - } - ScrollView - { - id: scrollView - width: UM.Theme.getSize("menu").width + scrollbar.width - height: parent.height - clip: true - - ScrollBar.vertical: UM.ScrollBar + delegate: Rectangle { - id: scrollbar - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom - } + height: UM.Theme.getSize("menu").height + width: parent.width - Column - { - id: materialColorsList - property var brandColors: model.colors - width: UM.Theme.getSize("menu").width - height: parent.height - spacing: 0 + color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("main_background") - Repeater + MouseArea { - model: parent.brandColors - - delegate: Rectangle + id: materialColorButton + anchors.fill: parent + hoverEnabled: true + onClicked: { - height: UM.Theme.getSize("menu").height - width: parent.width + Cura.MachineManager.setMaterial(extruderIndex, model.container_node); + menuPopup.close(); + colorPopup.close(); + materialMenu.close(); + } + onEntered: + { + menuPopup.itemHovered += 1; + colorPopup.itemHovered += 1; + } + onExited: + { + menuPopup.itemHovered -= 1; + colorPopup.itemHovered -= 1; + } + } - color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : "transparent" + Item + { + height: parent.height + width: parent.width + opacity: materialBrandMenu.enabled ? 1 : 0.5 + anchors.fill: parent - Item - { - height: parent.height - width: parent.width - opacity: materialBrandMenu.enabled ? 1 : 0.5 - anchors.fill: parent + //Checkmark, if the material is selected. + UM.ColorImage + { + id: checkmark + visible: model.id === materialMenu.activeMaterialId + height: UM.Theme.getSize("default_arrow").height + width: height + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.verticalCenter: parent.verticalCenter + source: UM.Theme.getIcon("Check", "low") + color: UM.Theme.getColor("setting_control_text") + } - //Checkmark, if the material is selected. - UM.ColorImage - { - id: checkmark - visible: model.id === materialMenu.activeMaterialId - height: UM.Theme.getSize("default_arrow").height - width: height - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.verticalCenter: parent.verticalCenter - source: UM.Theme.getIcon("Check", "low") - color: UM.Theme.getColor("setting_control_text") - } + UM.Label + { + text: model.name + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("default_arrow").height + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width - UM.Label - { - text: model.name - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("default_arrow").height - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - - elide: Label.ElideRight - wrapMode: Text.NoWrap - } - } - - MouseArea - { - id: materialColorButton - anchors.fill: parent - - hoverEnabled: true - onClicked: - { - Cura.MachineManager.setMaterial(extruderIndex, model.container_node); - menuPopup.close(); - colorPopup.close(); - materialMenu.close(); - } - onEntered: - { - menuPopup.itemHovered += 1; - colorPopup.itemHovered += 1; - } - onExited: - { - menuPopup.itemHovered -= 1; - colorPopup.itemHovered -= 1; - } - } + elide: Label.ElideRight + wrapMode: Text.NoWrap } } } diff --git a/resources/qml/Menus/MaterialBrandSubMenu.qml b/resources/qml/Menus/MaterialBrandSubMenu.qml new file mode 100644 index 0000000000..787a945766 --- /dev/null +++ b/resources/qml/Menus/MaterialBrandSubMenu.qml @@ -0,0 +1,117 @@ +// Copyright (c) 2022 UltiMaker +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.4 +import QtQuick.Layouts 2.7 + +import UM 1.5 as UM +import Cura 1.7 as Cura + +Popup +{ + id: materialBrandSubMenu + + bottomPadding: UM.Theme.getSize("thin_margin").height + topPadding: UM.Theme.getSize("thin_margin").height + + implicitWidth: scrollViewContent.width + scrollbar.width + leftPadding + rightPadding + implicitHeight: scrollViewContent.height + bottomPadding + topPadding + + // offset position relative to the parent + property int implicitX: parent.width + property int implicitY: -UM.Theme.getSize("thin_margin").height + + default property alias contents: scrollViewContent.children + + x: implicitX + y: implicitY + + // needed for the `mapToItem` function to work; apparently a Popup is not an Item + Item + { + id: materialBrandSubMenu + anchors.fill: parent + } + + onOpened: + { + // we want to make sure here that the popup never goes out side the window so we adjust the x and y position + // based on the width/height of the mainWindow/popup. QML is a bit weird here though, as the globalPosition + // is in absolute coordinates relative to the origin of the mainWindow while setting the x and y coordinates + // of the popup only changes the position relative to the parent. + + // reset position, the remainder of the function asumes this position and size + materialBrandSubMenu.x = implicitX; + materialBrandSubMenu.y = implicitY; + materialBrandSubMenu.width = implicitWidth; + materialBrandSubMenu.height = implicitHeight; + + const globalPosition = materialBrandSubMenu.mapToItem(null, 0, 0); + + if (globalPosition.y > mainWindow.height - materialBrandSubMenu.height) + { + if (mainWindow.height > materialBrandSubMenu.height) + { + const targetY = mainWindow.height - materialBrandSubMenu.height; + const deltaY = globalPosition.y - targetY; + materialBrandSubMenu.y = implicitY - deltaY; + } + else + { + // if popup is taller then the the component, limit + // the components height and set the position to + // y = 0 (in absolute coordinates) + materialBrandSubMenu.y = implicitY - globalPosition.y; + materialBrandSubMenu.height = mainWindow.height; + } + } + + if (globalPosition.x > mainWindow.width - materialBrandSubMenu.width) + { + if (mainWindow.width > materialBrandSubMenu.width) + { + const targetY = mainWindow.width - materialBrandSubMenu.width; + const deltaX = globalPosition.x - targetY; + materialBrandSubMenu.x = implicitX - deltaX; + } + else + { + materialBrandSubMenu.x = implicitX - globalPosition.x; + materialBrandSubMenu.width = mainWindow.width; + } + } + } + + padding: background.border.width + + background: Rectangle + { + color: UM.Theme.getColor("main_background") + border.color: UM.Theme.getColor("lining") + border.width: UM.Theme.getSize("default_lining").width + } + + ScrollView + { + id: scrollView + anchors.fill: parent + contentHeight: scrollViewContent.height + clip: true + + ScrollBar.vertical: UM.ScrollBar + { + id: scrollbar + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + } + + Rectangle + { + id: scrollViewContent + width: childrenRect.width + height: childrenRect.height + } + } +} \ No newline at end of file From 634288a37ce14566ffbafa1155752fe94325cb44 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 27 Dec 2022 12:09:47 +0100 Subject: [PATCH 18/20] Fix spelling mistakes. part of CURA-9522 --- resources/qml/Menus/MaterialBrandMenu.qml | 2 +- resources/qml/Menus/MaterialBrandSubMenu.qml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml index e514de04a4..83a6959183 100644 --- a/resources/qml/Menus/MaterialBrandMenu.qml +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -36,7 +36,7 @@ Cura.MenuItem UM.Label { - id: brandLableText + id: brandLabelText text: replaceText(materialBrandMenu.text) Layout.fillWidth: true Layout.fillHeight:true diff --git a/resources/qml/Menus/MaterialBrandSubMenu.qml b/resources/qml/Menus/MaterialBrandSubMenu.qml index 787a945766..e2c76518f7 100644 --- a/resources/qml/Menus/MaterialBrandSubMenu.qml +++ b/resources/qml/Menus/MaterialBrandSubMenu.qml @@ -71,8 +71,8 @@ Popup { if (mainWindow.width > materialBrandSubMenu.width) { - const targetY = mainWindow.width - materialBrandSubMenu.width; - const deltaX = globalPosition.x - targetY; + const targetX = mainWindow.width - materialBrandSubMenu.width; + const deltaX = globalPosition.x - targetX; materialBrandSubMenu.x = implicitX - deltaX; } else From d351458b109d964d577edb016b9cb538fdce8e5d Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 27 Dec 2022 12:11:21 +0100 Subject: [PATCH 19/20] Make identifier unique and call the correct one. Wouldn't start for me without (from source, on Windows). part of CURA-9522 --- resources/qml/Menus/MaterialBrandSubMenu.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Menus/MaterialBrandSubMenu.qml b/resources/qml/Menus/MaterialBrandSubMenu.qml index e2c76518f7..c2cbd7f911 100644 --- a/resources/qml/Menus/MaterialBrandSubMenu.qml +++ b/resources/qml/Menus/MaterialBrandSubMenu.qml @@ -30,7 +30,7 @@ Popup // needed for the `mapToItem` function to work; apparently a Popup is not an Item Item { - id: materialBrandSubMenu + id: materialBrandSubMenuItem anchors.fill: parent } @@ -47,7 +47,7 @@ Popup materialBrandSubMenu.width = implicitWidth; materialBrandSubMenu.height = implicitHeight; - const globalPosition = materialBrandSubMenu.mapToItem(null, 0, 0); + const globalPosition = materialBrandSubMenuItem.mapToItem(null, 0, 0); if (globalPosition.y > mainWindow.height - materialBrandSubMenu.height) { From a8570920bd3740c789e3243db1902e122771e93b Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 27 Dec 2022 12:32:23 +0100 Subject: [PATCH 20/20] Make it work in dark-mode again. part of CURA-9522 --- resources/qml/Menus/MaterialBrandSubMenu.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/Menus/MaterialBrandSubMenu.qml b/resources/qml/Menus/MaterialBrandSubMenu.qml index c2cbd7f911..af7e6cfb0e 100644 --- a/resources/qml/Menus/MaterialBrandSubMenu.qml +++ b/resources/qml/Menus/MaterialBrandSubMenu.qml @@ -112,6 +112,7 @@ Popup id: scrollViewContent width: childrenRect.width height: childrenRect.height + color: UM.Theme.getColor("main_background") } } } \ No newline at end of file