SpinBox.qml 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright (C) 2024 The Qt Company Ltd.
  2. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
  3. // Qt-Security score:significant reason:default
  4. import QtQuick
  5. import QtQuick.Controls.impl
  6. import QtQuick.Controls.FluentWinUI3.impl as Impl
  7. import QtQuick.Templates as T
  8. T.SpinBox {
  9. id: control
  10. implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
  11. contentItem.implicitWidth + leftPadding + rightPadding)
  12. implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
  13. implicitContentHeight + topPadding + bottomPadding,
  14. up.implicitIndicatorHeight, down.implicitIndicatorHeight)
  15. property string __controlState: [
  16. enabled && (down.hovered || down.pressed) && "down",
  17. enabled && (up.hovered || up.pressed) && !(down.hovered || down.pressed) && "up",
  18. enabled && (hovered || down.hovered || up.hovered) && !(down.pressed || up.pressed) && "hovered",
  19. enabled && (down.pressed || up.pressed) && "pressed",
  20. !enabled && "disabled"
  21. ].filter(Boolean).join("_") || "normal"
  22. readonly property var __config: Config.controls.spinbox[__controlState] || {}
  23. readonly property var __downConfig: value == from ? Config.controls.spinbox["atlimit"] : __config
  24. readonly property var __upConfig: value == to ? Config.controls.spinbox["atlimit"] : __config
  25. readonly property bool __isHighContrast: Application.styleHints.accessibility.contrastPreference === Qt.HighContrast
  26. spacing: __config.contentItem.spacing || 0
  27. leftPadding: ((!mirrored ? __config.leftPadding : __config.rightPadding) || 0) + (mirrored ? (up.indicator ? up.indicator.width * 2 : 0) : 0)
  28. rightPadding: ((!mirrored ? __config.rightPadding : __config.leftPadding) || 0) + (!mirrored ? (up.indicator ? up.indicator.width * 2 : 0) : 0)
  29. topPadding: __config.topPadding || 0
  30. bottomPadding: __config?.bottomPadding || 0
  31. topInset: -__config.topInset || 0
  32. bottomInset: -__config.bottomInset || 0
  33. leftInset: -__config.leftInset || 0
  34. rightInset: -__config.rightInset || 0
  35. validator: IntValidator {
  36. locale: control.locale.name
  37. bottom: Math.min(control.from, control.to)
  38. top: Math.max(control.from, control.to)
  39. }
  40. contentItem: TextInput {
  41. clip: width < implicitWidth
  42. text: control.displayText
  43. opacity: control.enabled ? 1 : 0.3
  44. font: control.font
  45. color: control.palette.buttonText
  46. selectionColor: control.palette.highlight
  47. selectedTextColor: control.palette.highlightedText
  48. horizontalAlignment: control.mirrored ? Text.AlignRight : Text.AlignLeft
  49. verticalAlignment: Text.AlignVCenter
  50. readOnly: !control.editable
  51. validator: control.validator
  52. inputMethodHints: control.inputMethodHints
  53. ContextMenu.menu: Impl.TextEditingContextMenu {
  54. editor: parent
  55. }
  56. }
  57. down.indicator: ItemGroup {
  58. x: !control.mirrored ? control.up.indicator ? (control.up.indicator.x - width) : 0
  59. : control.__config.rightPadding
  60. y: control.topPadding
  61. Impl.StyleImage {
  62. height: control.availableHeight
  63. visible: !control.__isHighContrast
  64. imageConfig: control.__downConfig.indicator_down_background
  65. }
  66. Rectangle {
  67. height: control.availableHeight
  68. visible: control.__isHighContrast && control.down.pressed
  69. color: control.down.pressed ? control.palette.highlight : control.palette.button
  70. radius: control.__config.indicator_down_background.bottomOffset
  71. }
  72. ColorImage {
  73. // Hack: Use Math.ceil/floor to avoid subpixel rendering issues
  74. x: Math.ceil((parent.width - width) / 2)
  75. y: Math.floor((parent.height - height) / 2)
  76. width: implicitWidth
  77. height: implicitHeight
  78. source: control.__downConfig.indicator_down_icon.filePath
  79. color: !control.__isHighContrast ? defaultColor : control.down.pressed ? control.palette.button : control.palette.buttonText
  80. }
  81. }
  82. up.indicator: ItemGroup {
  83. x: control.mirrored ? control.__config.rightPadding + (control.down.indicator ? control.down.indicator.width : 0)
  84. : control.width - width - control.__config.rightPadding
  85. y: control.topPadding
  86. Impl.StyleImage {
  87. height: control.availableHeight
  88. visible: !control.__isHighContrast
  89. imageConfig: control.__upConfig.indicator_up_background
  90. }
  91. Rectangle {
  92. visible: control.__isHighContrast && control.up.pressed
  93. height: control.availableHeight
  94. color: control.up.pressed ? control.palette.highlight : control.palette.button
  95. radius: control.__config.indicator_up_background.bottomOffset
  96. }
  97. ColorImage {
  98. // Hack: Use Math.ceil/floor to avoid subpixel rendering issues
  99. x: Math.ceil((parent.width - width) / 2)
  100. y: Math.floor((parent.height - height) / 2)
  101. width: implicitWidth
  102. height: implicitHeight
  103. source: control.__upConfig.indicator_up_icon.filePath
  104. color: !control.__isHighContrast ? defaultColor : control.up.pressed ? control.palette.button : control.palette.buttonText
  105. }
  106. }
  107. background: ItemGroup {
  108. Impl.StyleImage {
  109. visible: !control.__isHighContrast
  110. imageConfig: control.__config.background
  111. Item {
  112. visible: control.activeFocus
  113. width: parent.width
  114. height: 2
  115. y: parent.height - height
  116. Impl.FocusStroke {
  117. width: parent.width
  118. height: parent.height
  119. radius: control.__config.background.bottomOffset
  120. color: control.palette.accent
  121. }
  122. }
  123. }
  124. Rectangle {
  125. visible: control.__isHighContrast
  126. color: control.palette.window
  127. border.color: control.enabled && control.hovered || control.activeFocus ? control.palette.accent : control.palette.buttonText
  128. border.width: control.editable && control.activeFocus ? 2 : 1
  129. radius: control.__config.background.bottomOffset
  130. }
  131. }
  132. }