LayerView.qml 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. // Copyright (c) 2015 Ultimaker B.V.
  2. // Cura is released under the terms of the AGPLv3 or higher.
  3. import QtQuick 2.2
  4. import QtQuick.Controls 1.2
  5. import QtQuick.Layouts 1.1
  6. import QtQuick.Controls.Styles 1.1
  7. import UM 1.0 as UM
  8. import Cura 1.0 as Cura
  9. Item
  10. {
  11. width: {
  12. if (UM.LayerView.compatibilityMode) {
  13. return UM.Theme.getSize("layerview_menu_size_compatibility").width;
  14. } else {
  15. return UM.Theme.getSize("layerview_menu_size").width;
  16. }
  17. }
  18. height: {
  19. if (UM.LayerView.compatibilityMode) {
  20. return UM.Theme.getSize("layerview_menu_size_compatibility").height;
  21. } else {
  22. return UM.Theme.getSize("layerview_menu_size").height + UM.LayerView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
  23. }
  24. }
  25. Rectangle {
  26. id: layerViewMenu
  27. anchors.left: parent.left
  28. anchors.top: parent.top
  29. width: parent.width
  30. height: parent.height
  31. z: slider.z - 1
  32. color: UM.Theme.getColor("tool_panel_background")
  33. ColumnLayout {
  34. id: view_settings
  35. property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
  36. property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
  37. property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
  38. property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
  39. property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
  40. // if we are in compatibility mode, we only show the "line type"
  41. property bool show_legend: UM.LayerView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type") == 1
  42. property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
  43. property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
  44. anchors.top: parent.top
  45. anchors.topMargin: UM.Theme.getSize("default_margin").height
  46. anchors.left: parent.left
  47. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  48. spacing: UM.Theme.getSize("layerview_row_spacing").height
  49. Label
  50. {
  51. id: layersLabel
  52. anchors.left: parent.left
  53. text: catalog.i18nc("@label","View Mode: Layers")
  54. font.bold: true
  55. color: UM.Theme.getColor("text")
  56. }
  57. Label
  58. {
  59. id: spaceLabel
  60. anchors.left: parent.left
  61. text: " "
  62. font.pointSize: 0.5
  63. }
  64. Label
  65. {
  66. id: layerViewTypesLabel
  67. anchors.left: parent.left
  68. text: catalog.i18nc("@label","Color scheme")
  69. visible: !UM.LayerView.compatibilityMode
  70. Layout.fillWidth: true
  71. color: UM.Theme.getColor("text")
  72. }
  73. ListModel // matches LayerView.py
  74. {
  75. id: layerViewTypes
  76. }
  77. Component.onCompleted:
  78. {
  79. layerViewTypes.append({
  80. text: catalog.i18nc("@label:listbox", "Material Color"),
  81. type_id: 0
  82. })
  83. layerViewTypes.append({
  84. text: catalog.i18nc("@label:listbox", "Line Type"),
  85. type_id: 1 // these ids match the switching in the shader
  86. })
  87. }
  88. ComboBox
  89. {
  90. id: layerTypeCombobox
  91. anchors.left: parent.left
  92. Layout.fillWidth: true
  93. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  94. model: layerViewTypes
  95. visible: !UM.LayerView.compatibilityMode
  96. style: UM.Theme.styles.combobox
  97. onActivated:
  98. {
  99. UM.Preferences.setValue("layerview/layer_view_type", index);
  100. }
  101. Component.onCompleted:
  102. {
  103. currentIndex = UM.LayerView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
  104. updateLegends(currentIndex);
  105. }
  106. function updateLegends(type_id)
  107. {
  108. // update visibility of legends
  109. view_settings.show_legend = UM.LayerView.compatibilityMode || (type_id == 1);
  110. }
  111. }
  112. Label
  113. {
  114. id: compatibilityModeLabel
  115. anchors.left: parent.left
  116. text: catalog.i18nc("@label","Compatibility Mode")
  117. visible: UM.LayerView.compatibilityMode
  118. Layout.fillWidth: true
  119. Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
  120. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  121. }
  122. Label
  123. {
  124. id: space2Label
  125. anchors.left: parent.left
  126. text: " "
  127. font.pointSize: 0.5
  128. }
  129. Connections {
  130. target: UM.Preferences
  131. onPreferenceChanged:
  132. {
  133. layerTypeCombobox.currentIndex = UM.LayerView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
  134. layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex);
  135. view_settings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|");
  136. view_settings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves");
  137. view_settings.show_helpers = UM.Preferences.getValue("layerview/show_helpers");
  138. view_settings.show_skin = UM.Preferences.getValue("layerview/show_skin");
  139. view_settings.show_infill = UM.Preferences.getValue("layerview/show_infill");
  140. view_settings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers");
  141. view_settings.top_layer_count = UM.Preferences.getValue("view/top_layer_count");
  142. }
  143. }
  144. Repeater {
  145. model: Cura.ExtrudersModel{}
  146. CheckBox {
  147. checked: view_settings.extruder_opacities[index] > 0.5 || view_settings.extruder_opacities[index] == undefined || view_settings.extruder_opacities[index] == ""
  148. onClicked: {
  149. view_settings.extruder_opacities[index] = checked ? 1.0 : 0.0
  150. UM.Preferences.setValue("layerview/extruder_opacities", view_settings.extruder_opacities.join("|"));
  151. }
  152. text: model.name
  153. visible: !UM.LayerView.compatibilityMode
  154. enabled: index + 1 <= 4
  155. Rectangle {
  156. anchors.verticalCenter: parent.verticalCenter
  157. anchors.right: parent.right
  158. width: UM.Theme.getSize("layerview_legend_size").width
  159. height: UM.Theme.getSize("layerview_legend_size").height
  160. color: model.color
  161. border.width: UM.Theme.getSize("default_lining").width
  162. border.color: UM.Theme.getColor("lining")
  163. visible: !view_settings.show_legend
  164. }
  165. Layout.fillWidth: true
  166. Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
  167. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  168. style: UM.Theme.styles.checkbox
  169. }
  170. }
  171. Repeater {
  172. model: ListModel {
  173. id: typesLegenModel
  174. Component.onCompleted:
  175. {
  176. typesLegenModel.append({
  177. label: catalog.i18nc("@label", "Show Travels"),
  178. initialValue: view_settings.show_travel_moves,
  179. preference: "layerview/show_travel_moves",
  180. colorId: "layerview_move_combing"
  181. });
  182. typesLegenModel.append({
  183. label: catalog.i18nc("@label", "Show Helpers"),
  184. initialValue: view_settings.show_helpers,
  185. preference: "layerview/show_helpers",
  186. colorId: "layerview_support"
  187. });
  188. typesLegenModel.append({
  189. label: catalog.i18nc("@label", "Show Shell"),
  190. initialValue: view_settings.show_skin,
  191. preference: "layerview/show_skin",
  192. colorId: "layerview_inset_0"
  193. });
  194. typesLegenModel.append({
  195. label: catalog.i18nc("@label", "Show Infill"),
  196. initialValue: view_settings.show_infill,
  197. preference: "layerview/show_infill",
  198. colorId: "layerview_infill"
  199. });
  200. }
  201. }
  202. CheckBox {
  203. checked: model.initialValue
  204. onClicked: {
  205. UM.Preferences.setValue(model.preference, checked);
  206. }
  207. text: label
  208. Rectangle {
  209. anchors.verticalCenter: parent.verticalCenter
  210. anchors.right: parent.right
  211. width: UM.Theme.getSize("layerview_legend_size").width
  212. height: UM.Theme.getSize("layerview_legend_size").height
  213. color: UM.Theme.getColor(model.colorId)
  214. border.width: UM.Theme.getSize("default_lining").width
  215. border.color: UM.Theme.getColor("lining")
  216. visible: view_settings.show_legend
  217. }
  218. Layout.fillWidth: true
  219. Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
  220. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  221. style: UM.Theme.styles.checkbox
  222. }
  223. }
  224. CheckBox {
  225. checked: view_settings.only_show_top_layers
  226. onClicked: {
  227. UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0);
  228. }
  229. text: catalog.i18nc("@label", "Only Show Top Layers")
  230. visible: UM.LayerView.compatibilityMode
  231. style: UM.Theme.styles.checkbox
  232. }
  233. CheckBox {
  234. checked: view_settings.top_layer_count == 5
  235. onClicked: {
  236. UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1);
  237. }
  238. text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
  239. visible: UM.LayerView.compatibilityMode
  240. style: UM.Theme.styles.checkbox
  241. }
  242. Repeater {
  243. model: ListModel {
  244. id: typesLegenModelNoCheck
  245. Component.onCompleted:
  246. {
  247. typesLegenModelNoCheck.append({
  248. label: catalog.i18nc("@label", "Top / Bottom"),
  249. colorId: "layerview_skin",
  250. });
  251. typesLegenModelNoCheck.append({
  252. label: catalog.i18nc("@label", "Inner Wall"),
  253. colorId: "layerview_inset_x",
  254. });
  255. }
  256. }
  257. Label {
  258. text: label
  259. visible: view_settings.show_legend
  260. Rectangle {
  261. anchors.verticalCenter: parent.verticalCenter
  262. anchors.right: parent.right
  263. width: UM.Theme.getSize("layerview_legend_size").width
  264. height: UM.Theme.getSize("layerview_legend_size").height
  265. color: UM.Theme.getColor(model.colorId)
  266. border.width: UM.Theme.getSize("default_lining").width
  267. border.color: UM.Theme.getColor("lining")
  268. visible: view_settings.show_legend
  269. }
  270. Layout.fillWidth: true
  271. Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
  272. Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
  273. color: UM.Theme.getColor("text")
  274. }
  275. }
  276. }
  277. Item
  278. {
  279. id: slider
  280. width: handleSize
  281. height: parent.height - 2*UM.Theme.getSize("slider_layerview_margin").height
  282. anchors.top: parent.top
  283. anchors.topMargin: UM.Theme.getSize("slider_layerview_margin").height
  284. anchors.right: layerViewMenu.right
  285. anchors.rightMargin: UM.Theme.getSize("slider_layerview_margin").width
  286. property real handleSize: UM.Theme.getSize("slider_handle").width
  287. property real handleRadius: handleSize / 2
  288. property real minimumRangeHandleSize: UM.Theme.getSize("slider_handle").width / 2
  289. property real trackThickness: UM.Theme.getSize("slider_groove").width
  290. property real trackRadius: trackThickness / 2
  291. property real trackBorderWidth: UM.Theme.getSize("default_lining").width
  292. property color upperHandleColor: UM.Theme.getColor("slider_handle")
  293. property color lowerHandleColor: UM.Theme.getColor("slider_handle")
  294. property color rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
  295. property color trackColor: UM.Theme.getColor("slider_groove")
  296. property color trackBorderColor: UM.Theme.getColor("slider_groove_border")
  297. property real maximumValue: UM.LayerView.numLayers
  298. property real minimumValue: 0
  299. property real minimumRange: 0
  300. property bool roundValues: true
  301. property var activeHandle: upperHandle
  302. property bool layersVisible: UM.LayerView.layerActivity && CuraApplication.platformActivity ? true : false
  303. function getUpperValueFromHandle()
  304. {
  305. var result = upperHandle.y / (height - (2 * handleSize + minimumRangeHandleSize));
  306. result = maximumValue + result * (minimumValue - (maximumValue - minimumRange));
  307. result = roundValues ? Math.round(result) | 0 : result;
  308. return result;
  309. }
  310. function getLowerValueFromHandle()
  311. {
  312. var result = (lowerHandle.y - (handleSize + minimumRangeHandleSize)) / (height - (2 * handleSize + minimumRangeHandleSize));
  313. result = maximumValue - minimumRange + result * (minimumValue - (maximumValue - minimumRange));
  314. result = roundValues ? Math.round(result) : result;
  315. return result;
  316. }
  317. function setUpperValue(value)
  318. {
  319. var value = (value - maximumValue) / (minimumValue - maximumValue);
  320. var new_upper_y = Math.round(value * (height - (2 * handleSize + minimumRangeHandleSize)));
  321. if(new_upper_y != upperHandle.y)
  322. {
  323. upperHandle.y = new_upper_y;
  324. }
  325. rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height);
  326. }
  327. function setLowerValue(value)
  328. {
  329. var value = (value - maximumValue) / (minimumValue - maximumValue);
  330. var new_lower_y = Math.round((handleSize + minimumRangeHandleSize) + value * (height - (2 * handleSize + minimumRangeHandleSize)));
  331. if(new_lower_y != lowerHandle.y)
  332. {
  333. lowerHandle.y = new_lower_y;
  334. }
  335. rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height);
  336. }
  337. Connections
  338. {
  339. target: UM.LayerView
  340. onMinimumLayerChanged: slider.setLowerValue(UM.LayerView.minimumLayer)
  341. onCurrentLayerChanged: slider.setUpperValue(UM.LayerView.currentLayer)
  342. }
  343. Rectangle {
  344. width: parent.trackThickness
  345. height: parent.height - parent.handleSize
  346. radius: parent.trackRadius
  347. anchors.centerIn: parent
  348. color: parent.trackColor
  349. border.width: parent.trackBorderWidth;
  350. border.color: parent.trackBorderColor;
  351. }
  352. Item {
  353. id: rangeHandle
  354. y: upperHandle.y + upperHandle.height
  355. width: parent.handleSize
  356. height: parent.minimumRangeHandleSize
  357. anchors.horizontalCenter: parent.horizontalCenter
  358. visible: slider.layersVisible
  359. property real value: UM.LayerView.currentLayer
  360. function setValue(value)
  361. {
  362. var range = upperHandle.value - lowerHandle.value;
  363. value = Math.min(value, slider.maximumValue);
  364. value = Math.max(value, slider.minimumValue + range);
  365. UM.LayerView.setCurrentLayer(value);
  366. UM.LayerView.setMinimumLayer(value - range);
  367. }
  368. Rectangle {
  369. anchors.centerIn: parent
  370. width: parent.parent.trackThickness - 2 * parent.parent.trackBorderWidth
  371. height: parent.height + parent.parent.handleSize
  372. color: parent.parent.rangeHandleColor
  373. }
  374. MouseArea {
  375. anchors.fill: parent
  376. drag.target: parent
  377. drag.axis: Drag.YAxis
  378. drag.minimumY: upperHandle.height
  379. drag.maximumY: parent.parent.height - (parent.height + lowerHandle.height)
  380. onPressed: parent.parent.activeHandle = rangeHandle
  381. onPositionChanged:
  382. {
  383. upperHandle.y = parent.y - upperHandle.height
  384. lowerHandle.y = parent.y + parent.height
  385. var upper_value = slider.getUpperValueFromHandle();
  386. var lower_value = upper_value - (upperHandle.value - lowerHandle.value);
  387. UM.LayerView.setCurrentLayer(upper_value);
  388. UM.LayerView.setMinimumLayer(lower_value);
  389. }
  390. }
  391. }
  392. Rectangle {
  393. id: upperHandle
  394. y: parent.height - (parent.minimumRangeHandleSize + 2 * parent.handleSize)
  395. width: parent.handleSize
  396. height: parent.handleSize
  397. anchors.horizontalCenter: parent.horizontalCenter
  398. radius: parent.handleRadius
  399. color: parent.upperHandleColor
  400. visible: slider.layersVisible
  401. property real value: UM.LayerView.currentLayer
  402. function setValue(value)
  403. {
  404. UM.LayerView.setCurrentLayer(value);
  405. }
  406. MouseArea {
  407. anchors.fill: parent
  408. drag.target: parent
  409. drag.axis: Drag.YAxis
  410. drag.minimumY: 0
  411. drag.maximumY: parent.parent.height - (2 * parent.parent.handleSize + parent.parent.minimumRangeHandleSize)
  412. onPressed: parent.parent.activeHandle = upperHandle
  413. onPositionChanged:
  414. {
  415. if(lowerHandle.y - (upperHandle.y + upperHandle.height) < parent.parent.minimumRangeHandleSize)
  416. {
  417. lowerHandle.y = upperHandle.y + upperHandle.height + parent.parent.minimumRangeHandleSize;
  418. }
  419. rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height);
  420. UM.LayerView.setCurrentLayer(slider.getUpperValueFromHandle());
  421. }
  422. }
  423. }
  424. Rectangle {
  425. id: lowerHandle
  426. y: parent.height - parent.handleSize
  427. width: parent.handleSize
  428. height: parent.handleSize
  429. anchors.horizontalCenter: parent.horizontalCenter
  430. radius: parent.handleRadius
  431. color: parent.lowerHandleColor
  432. visible: slider.layersVisible
  433. property real value: UM.LayerView.minimumLayer
  434. function setValue(value)
  435. {
  436. UM.LayerView.setMinimumLayer(value);
  437. }
  438. MouseArea {
  439. anchors.fill: parent
  440. drag.target: parent
  441. drag.axis: Drag.YAxis
  442. drag.minimumY: upperHandle.height + parent.parent.minimumRangeHandleSize
  443. drag.maximumY: parent.parent.height - parent.height
  444. onPressed: parent.parent.activeHandle = lowerHandle
  445. onPositionChanged:
  446. {
  447. if(lowerHandle.y - (upperHandle.y + upperHandle.height) < parent.parent.minimumRangeHandleSize)
  448. {
  449. upperHandle.y = lowerHandle.y - (upperHandle.height + parent.parent.minimumRangeHandleSize);
  450. }
  451. rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height)
  452. UM.LayerView.setMinimumLayer(slider.getLowerValueFromHandle());
  453. }
  454. }
  455. }
  456. UM.PointingRectangle
  457. {
  458. x: parent.width + UM.Theme.getSize("slider_layerview_background").width / 2;
  459. y: Math.floor(slider.activeHandle.y + slider.activeHandle.height / 2 - height / 2);
  460. target: Qt.point(0, slider.activeHandle.y + slider.activeHandle.height / 2)
  461. arrowSize: UM.Theme.getSize("default_arrow").width
  462. height: (Math.floor(UM.Theme.getSize("slider_handle").height + UM.Theme.getSize("default_margin").height) / 2) * 2 // Make sure height has an integer middle so drawing a pointy border is easier
  463. width: valueLabel.width + UM.Theme.getSize("default_margin").width
  464. Behavior on height { NumberAnimation { duration: 50; } }
  465. color: UM.Theme.getColor("lining");
  466. visible: slider.layersVisible
  467. UM.PointingRectangle
  468. {
  469. color: UM.Theme.getColor("tool_panel_background")
  470. target: Qt.point(0, height / 2 + UM.Theme.getSize("default_lining").width)
  471. arrowSize: UM.Theme.getSize("default_arrow").width
  472. anchors.fill: parent
  473. anchors.margins: UM.Theme.getSize("default_lining").width
  474. MouseArea //Catch all mouse events (so scene doesnt handle them)
  475. {
  476. anchors.fill: parent
  477. }
  478. }
  479. TextField
  480. {
  481. id: valueLabel
  482. property string maxValue: slider.maximumValue + 1
  483. text: slider.activeHandle.value + 1
  484. horizontalAlignment: TextInput.AlignRight;
  485. onEditingFinished:
  486. {
  487. // Ensure that the cursor is at the first position. On some systems the text isn't fully visible
  488. // Seems to have to do something with different dpi densities that QML doesn't quite handle.
  489. // Another option would be to increase the size even further, but that gives pretty ugly results.
  490. cursorPosition = 0;
  491. if(valueLabel.text != '')
  492. {
  493. slider.activeHandle.setValue(valueLabel.text - 1);
  494. }
  495. }
  496. validator: IntValidator { bottom: 1; top: slider.maximumValue + 1; }
  497. anchors.left: parent.left;
  498. anchors.leftMargin: UM.Theme.getSize("default_margin").width / 2;
  499. anchors.verticalCenter: parent.verticalCenter;
  500. width: Math.max(UM.Theme.getSize("line").width * maxValue.length + 2, 20);
  501. style: TextFieldStyle
  502. {
  503. textColor: UM.Theme.getColor("setting_control_text");
  504. font: UM.Theme.getFont("default");
  505. background: Item { }
  506. }
  507. Keys.onUpPressed: slider.activeHandle.setValue(slider.activeHandle.value + ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
  508. Keys.onDownPressed: slider.activeHandle.setValue(slider.activeHandle.value - ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
  509. }
  510. BusyIndicator
  511. {
  512. id: busyIndicator;
  513. anchors.left: parent.right;
  514. anchors.leftMargin: UM.Theme.getSize("default_margin").width / 2;
  515. anchors.verticalCenter: parent.verticalCenter;
  516. width: UM.Theme.getSize("slider_handle").height;
  517. height: width;
  518. running: UM.LayerView.busy;
  519. visible: UM.LayerView.busy;
  520. }
  521. }
  522. }
  523. }
  524. }