MaterialBrandMenu.qml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. // Copyright (c) 2022 UltiMaker
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.7
  4. import QtQuick.Controls 2.4
  5. import QtQuick.Layouts 2.7
  6. import UM 1.5 as UM
  7. import Cura 1.7 as Cura
  8. /* This element is a workaround for MacOS, where it can crash in Qt6 when nested menus are closed.
  9. Instead we'll use a pop-up which doesn't seem to have that problem. */
  10. Cura.MenuItem
  11. {
  12. id: materialBrandMenu
  13. height: UM.Theme.getSize("menu").height + UM.Theme.getSize("narrow_margin").height
  14. overrideShowArrow: true
  15. property var materialTypesModel
  16. text: materialTypesModel.name
  17. contentItem: MouseArea
  18. {
  19. hoverEnabled: true
  20. RowLayout
  21. {
  22. spacing: 0
  23. opacity: materialBrandMenu.enabled ? 1 : 0.5
  24. Item
  25. {
  26. // Spacer
  27. width: UM.Theme.getSize("default_margin").width
  28. }
  29. UM.Label
  30. {
  31. id: brandLabelText
  32. text: replaceText(materialBrandMenu.text)
  33. Layout.fillWidth: true
  34. Layout.fillHeight:true
  35. elide: Label.ElideRight
  36. wrapMode: Text.NoWrap
  37. }
  38. Item
  39. {
  40. Layout.fillWidth: true
  41. }
  42. Item
  43. {
  44. // Right side margin
  45. width: UM.Theme.getSize("default_margin").width
  46. }
  47. }
  48. onEntered: showTimer.restartTimer()
  49. onExited: hideTimer.restartTimer()
  50. }
  51. Timer
  52. {
  53. id: showTimer
  54. interval: 250
  55. function restartTimer()
  56. {
  57. restart();
  58. running = Qt.binding(function() { return materialBrandMenu.enabled && materialBrandMenu.contentItem.containsMouse; });
  59. hideTimer.running = false;
  60. }
  61. onTriggered: menuPopup.open()
  62. }
  63. Timer
  64. {
  65. id: hideTimer
  66. interval: 250
  67. function restartTimer() //Restart but re-evaluate the running property then.
  68. {
  69. restart();
  70. running = Qt.binding(function() { return materialBrandMenu.enabled && !materialBrandMenu.contentItem.containsMouse && !menuPopup.itemHovered > 0; });
  71. showTimer.running = false;
  72. }
  73. onTriggered: menuPopup.close()
  74. }
  75. MaterialBrandSubMenu
  76. {
  77. id: menuPopup
  78. // Nasty hack to ensure that we can keep track if the popup contains the mouse.
  79. // Since we also want a hover for the sub items (and these events are sent async)
  80. // We have to keep a count of itemHovered (instead of just a bool)
  81. property int itemHovered: 0
  82. MouseArea
  83. {
  84. id: submenuArea
  85. anchors.fill: parent
  86. hoverEnabled: true
  87. onEntered: hideTimer.restartTimer()
  88. }
  89. Column
  90. {
  91. id: materialTypesList
  92. width: UM.Theme.getSize("menu").width
  93. height: childrenRect.height
  94. spacing: 0
  95. property var brandMaterials: materialTypesModel.material_types
  96. Repeater
  97. {
  98. model: parent.brandMaterials
  99. //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.
  100. //With a custom MouseArea, we can prevent the events from being accepted.
  101. delegate: Rectangle
  102. {
  103. id: brandMaterialBase
  104. height: UM.Theme.getSize("menu").height
  105. width: UM.Theme.getSize("menu").width
  106. color: materialTypeButton.containsMouse ? UM.Theme.getColor("background_2") : "transparent"
  107. RowLayout
  108. {
  109. spacing: 0
  110. opacity: materialBrandMenu.enabled ? 1 : 0.5
  111. height: parent.height
  112. width: parent.width
  113. Item
  114. {
  115. // Spacer
  116. width: UM.Theme.getSize("default_margin").width
  117. }
  118. UM.Label
  119. {
  120. text: model.name
  121. Layout.fillWidth: true
  122. Layout.fillHeight: true
  123. elide: Label.ElideRight
  124. wrapMode: Text.NoWrap
  125. }
  126. Item
  127. {
  128. Layout.fillWidth: true
  129. }
  130. UM.ColorImage
  131. {
  132. height: UM.Theme.getSize("default_arrow").height
  133. width: UM.Theme.getSize("default_arrow").width
  134. color: UM.Theme.getColor("setting_control_text")
  135. source: UM.Theme.getIcon("ChevronSingleRight")
  136. }
  137. Item
  138. {
  139. // Right side margin
  140. width: UM.Theme.getSize("default_margin").width
  141. }
  142. }
  143. MouseArea
  144. {
  145. id: materialTypeButton
  146. anchors.fill: parent
  147. hoverEnabled: true
  148. acceptedButtons: Qt.NoButton
  149. onEntered:
  150. {
  151. menuPopup.itemHovered += 1;
  152. showSubTimer.restartTimer();
  153. }
  154. onExited:
  155. {
  156. menuPopup.itemHovered -= 1;
  157. hideSubTimer.restartTimer();
  158. }
  159. }
  160. Timer
  161. {
  162. id: showSubTimer
  163. interval: 250
  164. function restartTimer()
  165. {
  166. restart();
  167. running = Qt.binding(function() { return materialTypeButton.containsMouse; });
  168. hideSubTimer.running = false;
  169. }
  170. onTriggered: colorPopup.open()
  171. }
  172. Timer
  173. {
  174. id: hideSubTimer
  175. interval: 250
  176. function restartTimer() //Restart but re-evaluate the running property then.
  177. {
  178. restart();
  179. running = Qt.binding(function() { return !materialTypeButton.containsMouse && !colorPopup.itemHovered > 0; });
  180. showSubTimer.running = false;
  181. }
  182. onTriggered: colorPopup.close()
  183. }
  184. MaterialBrandSubMenu
  185. {
  186. id: colorPopup
  187. implicitX: parent.width
  188. property int itemHovered: 0
  189. Column
  190. {
  191. id: materialColorsList
  192. property var brandColors: model.colors
  193. width: UM.Theme.getSize("menu").width
  194. height: childrenRect.height
  195. spacing: 0
  196. Repeater
  197. {
  198. model: parent.brandColors
  199. delegate: Rectangle
  200. {
  201. height: UM.Theme.getSize("menu").height
  202. width: parent.width
  203. color: materialColorButton.containsMouse ? UM.Theme.getColor("background_2") : UM.Theme.getColor("main_background")
  204. MouseArea
  205. {
  206. id: materialColorButton
  207. anchors.fill: parent
  208. hoverEnabled: true
  209. onClicked:
  210. {
  211. Cura.MachineManager.setMaterial(extruderIndex, model.container_node);
  212. menuPopup.close();
  213. colorPopup.close();
  214. materialMenu.close();
  215. }
  216. onEntered:
  217. {
  218. menuPopup.itemHovered += 1;
  219. colorPopup.itemHovered += 1;
  220. }
  221. onExited:
  222. {
  223. menuPopup.itemHovered -= 1;
  224. colorPopup.itemHovered -= 1;
  225. }
  226. }
  227. Item
  228. {
  229. height: parent.height
  230. width: parent.width
  231. opacity: materialBrandMenu.enabled ? 1 : 0.5
  232. anchors.fill: parent
  233. //Checkmark, if the material is selected.
  234. UM.ColorImage
  235. {
  236. id: checkmark
  237. visible: model.id === materialMenu.activeMaterialId
  238. height: UM.Theme.getSize("default_arrow").height
  239. width: height
  240. anchors.left: parent.left
  241. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  242. anchors.verticalCenter: parent.verticalCenter
  243. source: UM.Theme.getIcon("Check", "low")
  244. color: UM.Theme.getColor("setting_control_text")
  245. }
  246. UM.Label
  247. {
  248. text: model.name
  249. anchors.left: parent.left
  250. anchors.leftMargin: UM.Theme.getSize("default_margin").width + UM.Theme.getSize("default_arrow").height
  251. anchors.verticalCenter: parent.verticalCenter
  252. anchors.right: parent.right
  253. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  254. elide: Label.ElideRight
  255. wrapMode: Text.NoWrap
  256. }
  257. }
  258. }
  259. }
  260. }
  261. }
  262. }
  263. }
  264. }
  265. }
  266. }