NumericTextFieldWithUnit.qml 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright (c) 2020 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.10
  4. import QtQuick.Controls 2.3
  5. import UM 1.3 as UM
  6. import Cura 1.1 as Cura
  7. //
  8. // TextField widget with validation for editing numeric data in the Machine Settings dialog.
  9. //
  10. UM.TooltipArea
  11. {
  12. id: numericTextFieldWithUnit
  13. UM.I18nCatalog { id: catalog; name: "cura"; }
  14. height: childrenRect.height
  15. width: childrenRect.width
  16. property int controlWidth: UM.Theme.getSize("setting_control").width
  17. property int controlHeight: UM.Theme.getSize("setting_control").height
  18. text: tooltipText
  19. property alias containerStackId: propertyProvider.containerStackId
  20. property alias settingKey: propertyProvider.key
  21. property alias settingStoreIndex: propertyProvider.storeIndex
  22. property alias propertyProvider: propertyProvider
  23. property alias labelText: fieldLabel.text
  24. property alias labelFont: fieldLabel.font
  25. property alias labelWidth: fieldLabel.width
  26. property alias unitText: unitLabel.text
  27. property alias textField: textFieldWithUnit
  28. property alias valueText: textFieldWithUnit.text
  29. property alias editingFinishedFunction: textFieldWithUnit.editingFinishedFunction
  30. property string tooltipText: propertyProvider.properties.description ? propertyProvider.properties.description : ""
  31. property real minimum: 0
  32. property real maximum: Number.POSITIVE_INFINITY
  33. property int decimals: 6
  34. // callback functions
  35. property var afterOnEditingFinishedFunction: dummy_func
  36. property var forceUpdateOnChangeFunction: dummy_func
  37. property var setValueFunction: null
  38. // a dummy function for default property values
  39. function dummy_func() {}
  40. UM.SettingPropertyProvider
  41. {
  42. id: propertyProvider
  43. watchedProperties: [ "value", "description" ]
  44. }
  45. Label
  46. {
  47. id: fieldLabel
  48. anchors.left: parent.left
  49. anchors.verticalCenter: textFieldWithUnit.verticalCenter
  50. visible: text != ""
  51. font: UM.Theme.getFont("default")
  52. color: UM.Theme.getColor("text")
  53. renderType: Text.NativeRendering
  54. }
  55. TextField
  56. {
  57. id: textFieldWithUnit
  58. anchors.left: fieldLabel.right
  59. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  60. verticalAlignment: Text.AlignVCenter
  61. padding: 0
  62. leftPadding: UM.Theme.getSize("narrow_margin").width
  63. width: numericTextFieldWithUnit.controlWidth
  64. height: numericTextFieldWithUnit.controlHeight
  65. // Background is a rounded-cornered box with filled color as state indication (normal, warning, error, etc.)
  66. background: Rectangle
  67. {
  68. anchors.fill: parent
  69. anchors.margins: Math.round(UM.Theme.getSize("default_lining").width)
  70. radius: UM.Theme.getSize("setting_control_radius").width
  71. border.color:
  72. {
  73. if (!textFieldWithUnit.enabled)
  74. {
  75. return UM.Theme.getColor("setting_control_disabled_border")
  76. }
  77. switch (propertyProvider.properties.validationState)
  78. {
  79. case "ValidatorState.Exception":
  80. case "ValidatorState.MinimumError":
  81. case "ValidatorState.MaximumError":
  82. return UM.Theme.getColor("setting_validation_error")
  83. case "ValidatorState.MinimumWarning":
  84. case "ValidatorState.MaximumWarning":
  85. return UM.Theme.getColor("setting_validation_warning")
  86. }
  87. // Validation is OK.
  88. if (textFieldWithUnit.hovered || textFieldWithUnit.activeFocus)
  89. {
  90. return UM.Theme.getColor("setting_control_border_highlight")
  91. }
  92. return UM.Theme.getColor("setting_control_border")
  93. }
  94. color:
  95. {
  96. if (!textFieldWithUnit.enabled)
  97. {
  98. return UM.Theme.getColor("setting_control_disabled")
  99. }
  100. switch (propertyProvider.properties.validationState)
  101. {
  102. case "ValidatorState.Exception":
  103. case "ValidatorState.MinimumError":
  104. case "ValidatorState.MaximumError":
  105. return UM.Theme.getColor("setting_validation_error_background")
  106. case "ValidatorState.MinimumWarning":
  107. case "ValidatorState.MaximumWarning":
  108. return UM.Theme.getColor("setting_validation_warning_background")
  109. case "ValidatorState.Valid":
  110. return UM.Theme.getColor("setting_validation_ok")
  111. default:
  112. return UM.Theme.getColor("setting_control")
  113. }
  114. }
  115. }
  116. hoverEnabled: true
  117. selectByMouse: true
  118. font: UM.Theme.getFont("default")
  119. color: UM.Theme.getColor("text")
  120. renderType: Text.NativeRendering
  121. // When the textbox gets focused by TAB, select all text
  122. onActiveFocusChanged:
  123. {
  124. if (activeFocus && (focusReason == Qt.TabFocusReason || focusReason == Qt.BacktabFocusReason))
  125. {
  126. selectAll()
  127. }
  128. }
  129. text:
  130. {
  131. const value = propertyProvider.properties.value
  132. return value ? value : ""
  133. }
  134. validator: DoubleValidator
  135. {
  136. bottom: numericTextFieldWithUnit.minimum
  137. top: numericTextFieldWithUnit.maximum
  138. decimals: numericTextFieldWithUnit.decimals
  139. notation: DoubleValidator.StandardNotation
  140. }
  141. //Enforce actual minimum and maximum values.
  142. //The DoubleValidator allows intermediate values, which essentially means that the maximum gets rounded up to the nearest power of 10.
  143. //This is not accurate at all, so here if the value exceeds the maximum or the minimum we disallow it.
  144. property string previousText
  145. onTextChanged:
  146. {
  147. var value = Number(text);
  148. if(value < numericTextFieldWithUnit.minimum || value > numericTextFieldWithUnit.maximum)
  149. {
  150. text = previousText;
  151. }
  152. previousText = text;
  153. }
  154. onEditingFinished: editingFinishedFunction()
  155. property var editingFinishedFunction: defaultEditingFinishedFunction
  156. function defaultEditingFinishedFunction()
  157. {
  158. if (propertyProvider && text != propertyProvider.properties.value)
  159. {
  160. // For some properties like the extruder-compatible material diameter, they need to
  161. // trigger many updates, such as the available materials, the current material may
  162. // need to be switched, etc. Although setting the diameter can be done directly via
  163. // the provider, all the updates that need to be triggered then need to depend on
  164. // the metadata update, a signal that can be fired way too often. The update functions
  165. // can have if-checks to filter out the irrelevant updates, but still it incurs unnecessary
  166. // overhead.
  167. // The ExtruderStack class has a dedicated function for this call "setCompatibleMaterialDiameter()",
  168. // and it triggers the diameter update signals only when it is needed. Here it is optionally
  169. // choose to use setCompatibleMaterialDiameter() or other more specific functions that
  170. // are available.
  171. if (setValueFunction !== null)
  172. {
  173. setValueFunction(text)
  174. }
  175. else
  176. {
  177. propertyProvider.setPropertyValue("value", text)
  178. }
  179. forceUpdateOnChangeFunction()
  180. afterOnEditingFinishedFunction()
  181. }
  182. }
  183. Label
  184. {
  185. id: unitLabel
  186. anchors.right: parent.right
  187. anchors.rightMargin: Math.round(UM.Theme.getSize("setting_unit_margin").width)
  188. anchors.verticalCenter: parent.verticalCenter
  189. text: unitText
  190. textFormat: Text.PlainText
  191. verticalAlignment: Text.AlignVCenter
  192. renderType: Text.NativeRendering
  193. color: UM.Theme.getColor("setting_unit")
  194. font: UM.Theme.getFont("default")
  195. }
  196. }
  197. }