NumericTextFieldWithUnit.qml 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // Copyright (c) 2019 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 valueValidator: textFieldWithUnit.validator
  30. property alias editingFinishedFunction: textFieldWithUnit.editingFinishedFunction
  31. property string tooltipText: propertyProvider.properties.description
  32. // whether negative value is allowed. This affects the validation of the input field.
  33. property bool allowNegativeValue: false
  34. // whether positive value is allowed. This affects the validation of the input field.
  35. property bool allowPositiveValue: true
  36. // callback functions
  37. property var afterOnEditingFinishedFunction: dummy_func
  38. property var forceUpdateOnChangeFunction: dummy_func
  39. property var setValueFunction: null
  40. // a dummy function for default property values
  41. function dummy_func() {}
  42. UM.SettingPropertyProvider
  43. {
  44. id: propertyProvider
  45. watchedProperties: [ "value", "description" ]
  46. }
  47. Label
  48. {
  49. id: fieldLabel
  50. anchors.left: parent.left
  51. anchors.verticalCenter: textFieldWithUnit.verticalCenter
  52. visible: text != ""
  53. font: UM.Theme.getFont("default")
  54. color: UM.Theme.getColor("text")
  55. renderType: Text.NativeRendering
  56. }
  57. TextField
  58. {
  59. id: textFieldWithUnit
  60. anchors.left: fieldLabel.right
  61. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  62. width: numericTextFieldWithUnit.controlWidth
  63. height: numericTextFieldWithUnit.controlHeight
  64. // Background is a rounded-cornered box with filled color as state indication (normal, warning, error, etc.)
  65. background: Rectangle
  66. {
  67. anchors.fill: parent
  68. anchors.margins: Math.round(UM.Theme.getSize("default_lining").width)
  69. radius: UM.Theme.getSize("setting_control_radius").width
  70. border.color:
  71. {
  72. if (!textFieldWithUnit.enabled)
  73. {
  74. return UM.Theme.getColor("setting_control_disabled_border")
  75. }
  76. switch (propertyProvider.properties.validationState)
  77. {
  78. case "ValidatorState.Exception":
  79. case "ValidatorState.MinimumError":
  80. case "ValidatorState.MaximumError":
  81. return UM.Theme.getColor("setting_validation_error")
  82. case "ValidatorState.MinimumWarning":
  83. case "ValidatorState.MaximumWarning":
  84. return UM.Theme.getColor("setting_validation_warning")
  85. }
  86. // Validation is OK.
  87. if (textFieldWithUnit.hovered || textFieldWithUnit.activeFocus)
  88. {
  89. return UM.Theme.getColor("setting_control_border_highlight")
  90. }
  91. return UM.Theme.getColor("setting_control_border")
  92. }
  93. color:
  94. {
  95. if (!textFieldWithUnit.enabled)
  96. {
  97. return UM.Theme.getColor("setting_control_disabled")
  98. }
  99. switch (propertyProvider.properties.validationState)
  100. {
  101. case "ValidatorState.Exception":
  102. case "ValidatorState.MinimumError":
  103. case "ValidatorState.MaximumError":
  104. return UM.Theme.getColor("setting_validation_error_background")
  105. case "ValidatorState.MinimumWarning":
  106. case "ValidatorState.MaximumWarning":
  107. return UM.Theme.getColor("setting_validation_warning_background")
  108. case "ValidatorState.Valid":
  109. return UM.Theme.getColor("setting_validation_ok")
  110. default:
  111. return UM.Theme.getColor("setting_control")
  112. }
  113. }
  114. }
  115. hoverEnabled: true
  116. selectByMouse: true
  117. font: UM.Theme.getFont("default")
  118. color: UM.Theme.getColor("text")
  119. renderType: Text.NativeRendering
  120. // When the textbox gets focused by TAB, select all text
  121. onActiveFocusChanged:
  122. {
  123. if (activeFocus && (focusReason == Qt.TabFocusReason || focusReason == Qt.BacktabFocusReason))
  124. {
  125. selectAll()
  126. }
  127. }
  128. text:
  129. {
  130. const value = propertyProvider.properties.value
  131. return value ? value : ""
  132. }
  133. validator: DoubleValidator
  134. {
  135. bottom: allowNegativeValue ? Number.NEGATIVE_INFINITY : 0
  136. top: allowPositiveValue ? Number.POSITIVE_INFINITY : 0
  137. decimals: 6
  138. notation: DoubleValidator.StandardNotation
  139. }
  140. onEditingFinished: editingFinishedFunction()
  141. property var editingFinishedFunction: defaultEditingFinishedFunction
  142. function defaultEditingFinishedFunction()
  143. {
  144. if (propertyProvider && text != propertyProvider.properties.value)
  145. {
  146. // For some properties like the extruder-compatible material diameter, they need to
  147. // trigger many updates, such as the available materials, the current material may
  148. // need to be switched, etc. Although setting the diameter can be done directly via
  149. // the provider, all the updates that need to be triggered then need to depend on
  150. // the metadata update, a signal that can be fired way too often. The update functions
  151. // can have if-checks to filter out the irrelevant updates, but still it incurs unnecessary
  152. // overhead.
  153. // The ExtruderStack class has a dedicated function for this call "setCompatibleMaterialDiameter()",
  154. // and it triggers the diameter update signals only when it is needed. Here it is optionally
  155. // choose to use setCompatibleMaterialDiameter() or other more specific functions that
  156. // are available.
  157. if (setValueFunction !== null)
  158. {
  159. setValueFunction(text)
  160. }
  161. else
  162. {
  163. propertyProvider.setPropertyValue("value", text)
  164. }
  165. forceUpdateOnChangeFunction()
  166. afterOnEditingFinishedFunction()
  167. }
  168. }
  169. Label
  170. {
  171. id: unitLabel
  172. anchors.right: parent.right
  173. anchors.rightMargin: Math.round(UM.Theme.getSize("setting_unit_margin").width)
  174. anchors.verticalCenter: parent.verticalCenter
  175. text: unitText
  176. textFormat: Text.PlainText
  177. verticalAlignment: Text.AlignVCenter
  178. renderType: Text.NativeRendering
  179. color: UM.Theme.getColor("setting_unit")
  180. font: UM.Theme.getFont("default")
  181. }
  182. }
  183. }