MaterialBrandMenu.qml 12 KB

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