SpinBox.qml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2016 The Qt Company Ltd.
  4. ** Contact: https://www.qt.io/licensing/
  5. **
  6. ** This file is part of the Qt Quick Controls module of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:LGPL$
  9. ** Commercial License Usage
  10. ** Licensees holding valid commercial Qt licenses may use this file in
  11. ** accordance with the commercial license agreement provided with the
  12. ** Software or, alternatively, in accordance with the terms contained in
  13. ** a written agreement between you and The Qt Company. For licensing terms
  14. ** and conditions see https://www.qt.io/terms-conditions. For further
  15. ** information use the contact form at https://www.qt.io/contact-us.
  16. **
  17. ** GNU Lesser General Public License Usage
  18. ** Alternatively, this file may be used under the terms of the GNU Lesser
  19. ** General Public License version 3 as published by the Free Software
  20. ** Foundation and appearing in the file LICENSE.LGPL3 included in the
  21. ** packaging of this file. Please review the following information to
  22. ** ensure the GNU Lesser General Public License version 3 requirements
  23. ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
  24. **
  25. ** GNU General Public License Usage
  26. ** Alternatively, this file may be used under the terms of the GNU
  27. ** General Public License version 2.0 or (at your option) the GNU General
  28. ** Public license version 3 or any later version approved by the KDE Free
  29. ** Qt Foundation. The licenses are as published by the Free Software
  30. ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
  31. ** included in the packaging of this file. Please review the following
  32. ** information to ensure the GNU General Public License requirements will
  33. ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
  34. ** https://www.gnu.org/licenses/gpl-3.0.html.
  35. **
  36. ** $QT_END_LICENSE$
  37. **
  38. ****************************************************************************/
  39. import QtQuick 2.2
  40. import QtQuick.Controls 1.2
  41. import QtQuick.Controls.Private 1.0
  42. /*!
  43. \qmltype SpinBox
  44. \inqmlmodule QtQuick.Controls
  45. \since 5.1
  46. \ingroup controls
  47. \brief Provides a spin box control.
  48. \image spinbox.png
  49. SpinBox allows the user to choose a value by clicking the up or down buttons, or by
  50. pressing up or down on the keyboard. The user can also type the value in manually.
  51. By default the SpinBox provides discrete values in the range [0-99] with a \l stepSize of 1 and 0 \l decimals.
  52. \code
  53. SpinBox {
  54. id: spinbox
  55. }
  56. \endcode
  57. Note that if you require decimal values you will need to set the \l decimals to a non 0 value.
  58. \code
  59. SpinBox {
  60. id: spinbox
  61. decimals: 2
  62. }
  63. \endcode
  64. */
  65. Control {
  66. id: spinbox
  67. /*!
  68. \qmlproperty real SpinBox::value
  69. The value of this SpinBox, clamped to \l minimumValue and \l maximumValue.
  70. The default value is \c{0.0}.
  71. */
  72. property alias value: validator.value
  73. /*!
  74. \qmlproperty real SpinBox::minimumValue
  75. The minimum value of the SpinBox range.
  76. The \l value is clamped to this value.
  77. The default value is \c{0.0}.
  78. */
  79. property alias minimumValue: validator.minimumValue
  80. /*!
  81. \qmlproperty real SpinBox::maximumValue
  82. The maximum value of the SpinBox range.
  83. The \l value is clamped to this value. If maximumValue is smaller than
  84. \l minimumValue, \l minimumValue will be enforced.
  85. The default value is \c{99}.
  86. */
  87. property alias maximumValue: validator.maximumValue
  88. /*! \qmlproperty real SpinBox::stepSize
  89. The amount by which the \l value is incremented/decremented when a
  90. spin button is pressed.
  91. The default value is \c{1.0}.
  92. */
  93. property alias stepSize: validator.stepSize
  94. /*! \qmlproperty string SpinBox::suffix
  95. The suffix for the value. I.e "cm" */
  96. property alias suffix: validator.suffix
  97. /*! \qmlproperty string SpinBox::prefix
  98. The prefix for the value. I.e "$" */
  99. property alias prefix: validator.prefix
  100. /*! \qmlproperty int SpinBox::decimals
  101. This property indicates the amount of decimals.
  102. Note that if you enter more decimals than specified, they will
  103. be truncated to the specified amount of decimal places.
  104. The default value is \c{0}.
  105. */
  106. property alias decimals: validator.decimals
  107. /*! \qmlproperty font SpinBox::font
  108. This property indicates the current font used by the SpinBox.
  109. */
  110. property alias font: input.font
  111. /*!
  112. \qmlproperty int SpinBox::cursorPosition
  113. \since QtQuick.Controls 1.5
  114. This property holds the position of the cursor in the SpinBox.
  115. */
  116. property alias cursorPosition: input.cursorPosition
  117. /*! This property indicates whether the Spinbox should get active
  118. focus when pressed.
  119. The default value is \c true.
  120. */
  121. property bool activeFocusOnPress: true
  122. /*! \qmlproperty enumeration horizontalAlignment
  123. \since QtQuick.Controls 1.1
  124. This property indicates how the content is horizontally aligned
  125. within the text field.
  126. The supported values are:
  127. \list
  128. \li Qt.AlignLeft
  129. \li Qt.AlignHCenter
  130. \li Qt.AlignRight
  131. \endlist
  132. The default value is style dependent.
  133. */
  134. property int horizontalAlignment: __panel ? __panel.horizontalAlignment : Qt.AlignLeft
  135. /*!
  136. \qmlproperty bool SpinBox::hovered
  137. This property indicates whether the control is being hovered.
  138. */
  139. readonly property bool hovered: mouseArea.containsMouse || input.containsMouse
  140. || mouseUp.containsMouse || mouseDown.containsMouse
  141. /*!
  142. \qmlsignal SpinBox::editingFinished()
  143. \since QtQuick.Controls 1.1
  144. This signal is emitted when the Return or Enter key is pressed or
  145. the control loses focus.
  146. The corresponding handler is \c onEditingFinished.
  147. */
  148. signal editingFinished()
  149. /*!
  150. \qmlproperty bool SpinBox::selectByMouse
  151. \since QtQuick.Controls 1.3
  152. This property determines if the user can select the text with the
  153. mouse.
  154. The default value is \c true.
  155. */
  156. property bool selectByMouse: true
  157. /*!
  158. \qmlproperty bool SpinBox::inputMethodComposing
  159. \since QtQuick.Controls 1.3
  160. This property holds whether the SpinBox has partial text input from an input method.
  161. While it is composing an input method may rely on mouse or key events from the SpinBox
  162. to edit or commit the partial text. This property can be used to determine when to disable
  163. events handlers that may interfere with the correct operation of an input method.
  164. */
  165. readonly property bool inputMethodComposing: !!input.inputMethodComposing
  166. /*!
  167. \since QtQuick.Controls 1.3
  168. This property contains the edit \l Menu for working
  169. with text selection. Set it to \c null if no menu
  170. is wanted.
  171. */
  172. property Component menu: input.editMenu.defaultMenu
  173. style: Settings.styleComponent(Settings.style, "SpinBoxStyle.qml", spinbox)
  174. /*! \internal */
  175. function __increment() {
  176. validator.increment()
  177. if (activeFocus)
  178. input.selectValue()
  179. }
  180. /*! \internal */
  181. function __decrement() {
  182. validator.decrement()
  183. if (activeFocus)
  184. input.selectValue()
  185. }
  186. /*! \internal */
  187. property alias __text: input.text
  188. /*! \internal */
  189. property alias __baselineOffset: input.baselineOffset
  190. __styleData: QtObject {
  191. readonly property bool upEnabled: value != maximumValue;
  192. readonly property alias upHovered: mouseUp.containsMouse
  193. readonly property alias upPressed: mouseUp.pressed
  194. readonly property bool downEnabled: value != minimumValue;
  195. readonly property alias downPressed: mouseDown.pressed
  196. readonly property alias downHovered: mouseDown.containsMouse
  197. readonly property int contentHeight: Math.max(input.implicitHeight, 16)
  198. readonly property int contentWidth: Math.max(maxSizeHint.implicitWidth, minSizeHint.implicitWidth)
  199. }
  200. Text {
  201. id: maxSizeHint
  202. text: prefix + maximumValue.toFixed(decimals) + suffix
  203. font: input.font
  204. visible: false
  205. }
  206. Text {
  207. id: minSizeHint
  208. text: prefix + minimumValue.toFixed(decimals) + suffix
  209. font: input.font
  210. visible: false
  211. }
  212. activeFocusOnTab: true
  213. onActiveFocusChanged: if (activeFocus) input.selectValue()
  214. Accessible.name: input.text
  215. Accessible.role: Accessible.SpinBox
  216. Accessible.editable: true
  217. MouseArea {
  218. id: mouseArea
  219. anchors.fill: parent
  220. hoverEnabled: Settings.hoverEnabled
  221. onPressed: if (activeFocusOnPress) input.forceActiveFocus()
  222. onWheel: {
  223. if (wheel.angleDelta.y > 0)
  224. __increment();
  225. else
  226. __decrement();
  227. }
  228. }
  229. TextInputWithHandles {
  230. id: input
  231. clip: contentWidth > width
  232. anchors.fill: parent
  233. anchors.leftMargin: __style ? __style.padding.left : 0
  234. anchors.topMargin: __style ? __style.padding.top : 0
  235. anchors.rightMargin: __style ? __style.padding.right: 0
  236. anchors.bottomMargin: __style ? __style.padding.bottom: 0
  237. control: spinbox
  238. cursorHandle: __style ? __style.__cursorHandle : undefined
  239. selectionHandle: __style ? __style.__selectionHandle : undefined
  240. focus: true
  241. activeFocusOnPress: spinbox.activeFocusOnPress
  242. horizontalAlignment: spinbox.horizontalAlignment
  243. verticalAlignment: __panel ? __panel.verticalAlignment : Qt.AlignVCenter
  244. inputMethodHints: Qt.ImhFormattedNumbersOnly
  245. validator: SpinBoxValidator {
  246. id: validator
  247. property bool ready: false // Delay validation until all properties are ready
  248. onTextChanged: if (ready) input.text = validator.text
  249. Component.onCompleted: {input.text = validator.text ; ready = true}
  250. }
  251. onAccepted: {
  252. input.text = validator.text
  253. selectValue()
  254. }
  255. Keys.forwardTo: spinbox
  256. onEditingFinished: spinbox.editingFinished()
  257. font: __panel ? __panel.font : TextSingleton.font
  258. color: __panel ? __panel.foregroundColor : "black"
  259. selectionColor: __panel ? __panel.selectionColor : "black"
  260. selectedTextColor: __panel ? __panel.selectedTextColor : "black"
  261. opacity: parent.enabled ? 1 : 0.5
  262. renderType: __style ? __style.renderType : Text.NativeRendering
  263. function selectValue() {
  264. select(prefix.length, text.length - suffix.length)
  265. }
  266. }
  267. // Spinbox increment button
  268. MouseArea {
  269. id: mouseUp
  270. objectName: "mouseUp"
  271. hoverEnabled: Settings.hoverEnabled
  272. property var upRect: __panel ? __panel.upRect : null
  273. anchors.left: parent.left
  274. anchors.top: parent.top
  275. anchors.leftMargin: upRect ? upRect.x : 0
  276. anchors.topMargin: upRect ? upRect.y : 0
  277. width: upRect ? upRect.width : 0
  278. height: upRect ? upRect.height : 0
  279. onClicked: __increment()
  280. onPressed: if (!Settings.hasTouchScreen && activeFocusOnPress) input.forceActiveFocus()
  281. property bool autoincrement: false;
  282. onReleased: autoincrement = false
  283. onExited: autoincrement = false
  284. Timer { running: mouseUp.pressed; interval: 350 ; onTriggered: mouseUp.autoincrement = true }
  285. Timer { running: mouseUp.autoincrement && mouseUp.containsMouse; interval: 60 ; repeat: true ; onTriggered: __increment() }
  286. }
  287. // Spinbox decrement button
  288. MouseArea {
  289. id: mouseDown
  290. objectName: "mouseDown"
  291. hoverEnabled: Settings.hoverEnabled
  292. onClicked: __decrement()
  293. onPressed: if (!Settings.hasTouchScreen && activeFocusOnPress) input.forceActiveFocus()
  294. property var downRect: __panel ? __panel.downRect : null
  295. anchors.left: parent.left
  296. anchors.top: parent.top
  297. anchors.leftMargin: downRect ? downRect.x : 0
  298. anchors.topMargin: downRect ? downRect.y : 0
  299. width: downRect ? downRect.width : 0
  300. height: downRect ? downRect.height : 0
  301. property bool autoincrement: false;
  302. onReleased: autoincrement = false
  303. onExited: autoincrement = false
  304. Timer { running: mouseDown.pressed; interval: 350 ; onTriggered: mouseDown.autoincrement = true }
  305. Timer { running: mouseDown.autoincrement && mouseDown.containsMouse; interval: 60 ; repeat: true ; onTriggered: __decrement() }
  306. }
  307. Keys.onUpPressed: __increment()
  308. Keys.onDownPressed: __decrement()
  309. }