RangeSlider.qml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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.RangeSlider {
  9. id: control
  10. implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
  11. first.implicitHandleWidth + leftPadding + rightPadding,
  12. second.implicitHandleWidth + leftPadding + rightPadding)
  13. implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
  14. first.implicitHandleHeight + topPadding + bottomPadding,
  15. second.implicitHandleHeight + topPadding + bottomPadding)
  16. topPadding: horizontal ? __config.topPadding : __config.leftPadding || 0
  17. leftPadding: horizontal ? __config.leftPadding : __config.bottomPadding || 0
  18. rightPadding: horizontal ? __config.rightPadding : __config.topPadding || 0
  19. bottomPadding: horizontal ? __config.bottomPadding : __config.rightPadding || 0
  20. readonly property string __controlState: [
  21. !control.enabled && "disabled",
  22. control.enabled && control.hovered && !(first.pressed || second.pressed) && "hovered",
  23. ].filter(Boolean).join("_") || "normal"
  24. readonly property var __config: Config.controls.rangeslider[__controlState] || {}
  25. readonly property real __steps: Math.abs(to - from) / stepSize
  26. readonly property bool __isDiscrete: stepSize >= Number.EPSILON
  27. && Math.abs(Math.round(__steps) - __steps) < Number.EPSILON
  28. readonly property bool __isHighContrast: Application.styleHints.accessibility.contrastPreference === Qt.HighContrast
  29. property string __firstHandleState: [
  30. !control.enabled && "disabled",
  31. first.hovered && !first.pressed && "hovered",
  32. first.pressed && "handle_pressed",
  33. ].filter(Boolean).join("_") || "normal"
  34. readonly property var __firstHandleConfig: Config.controls.rangeslider[__firstHandleState] || {}
  35. property string __secondHandleState: [
  36. !control.enabled && "disabled",
  37. second.hovered && !second.pressed && "hovered",
  38. second.pressed && "handle_pressed",
  39. ].filter(Boolean).join("_") || "normal"
  40. readonly property var __secondHandleConfig: Config.controls.rangeslider[__secondHandleState] || {}
  41. readonly property Item __focusFrameControl: control
  42. readonly property Item __focusFrameTarget: control
  43. first.handle: ItemGroup {
  44. x: Math.round(control.leftPadding + (control.horizontal
  45. ? control.first.visualPosition * (control.availableWidth - width)
  46. : (control.availableWidth - width) / 2))
  47. y: Math.round(control.topPadding + (control.horizontal
  48. ? (control.availableHeight - height) / 2
  49. : control.first.visualPosition * (control.availableHeight - height)))
  50. Impl.StyleImage {
  51. visible: !control.__isHighContrast
  52. imageConfig: control.__firstHandleConfig.first_handle
  53. readonly property Item __focusFrameTarget: control
  54. }
  55. Rectangle {
  56. visible: control.__isHighContrast
  57. implicitWidth: control.__secondHandleConfig.first_handle.width
  58. implicitHeight: control.__secondHandleConfig.first_handle.height
  59. color: control.palette.buttonText
  60. radius: width / 2
  61. }
  62. property Rectangle indicator: Rectangle {
  63. property real diameter: !control.enabled ? 10
  64. : control.first.pressed ? 8
  65. : control.__isHighContrast && !control.hovered ? 0
  66. : control.first.hovered ? 14 : 10
  67. parent: control.first.handle
  68. width: diameter
  69. height: diameter
  70. radius: diameter * 0.5
  71. x: (control.__secondHandleConfig.first_handle.width - width) / 2
  72. y: (control.__secondHandleConfig.first_handle.height - height) / 2
  73. color: control.enabled ? (control.first.hovered ? Qt.rgba(control.palette.accent.r, control.palette.accent.g, control.palette.accent.b, 0.9020)
  74. : control.first.pressed ? Qt.rgba(control.palette.accent.r, control.palette.accent.g, control.palette.accent.b, 0.8)
  75. : control.palette.accent)
  76. : control.palette.accent
  77. Behavior on diameter {
  78. // From WindowsUI 3 Animation Values
  79. NumberAnimation {
  80. duration: 167
  81. easing.type: Easing.OutCubic
  82. }
  83. }
  84. }
  85. }
  86. second.handle: ItemGroup {
  87. x: Math.round(control.leftPadding + (control.horizontal
  88. ? control.second.visualPosition * (control.availableWidth - width)
  89. : (control.availableWidth - width) / 2))
  90. y: Math.round(control.topPadding + (control.horizontal
  91. ? (control.availableHeight - height) / 2
  92. : control.second.visualPosition * (control.availableHeight - height)))
  93. Impl.StyleImage {
  94. visible: !control.__isHighContrast
  95. imageConfig: control.__secondHandleConfig.second_handle
  96. readonly property Item __focusFrameTarget: control
  97. }
  98. Rectangle {
  99. visible: control.__isHighContrast
  100. implicitWidth: control.__secondHandleConfig.second_handle.width
  101. implicitHeight: control.__secondHandleConfig.second_handle.height
  102. color: control.palette.buttonText
  103. radius: width / 2
  104. }
  105. property Rectangle indicator: Rectangle {
  106. property real diameter: !control.enabled ? 10
  107. : control.second.pressed ? 8
  108. : control.__isHighContrast && !control.hovered ? 0
  109. : control.second.hovered ? 14 : 10
  110. parent: control.second.handle
  111. width: diameter
  112. height: diameter
  113. radius: diameter * 0.5
  114. x: (control.__secondHandleConfig.second_handle.width - width) / 2
  115. y: (control.__secondHandleConfig.second_handle.height - height) / 2
  116. color: control.enabled ? (control.second.hovered ? Qt.rgba(control.palette.accent.r, control.palette.accent.g, control.palette.accent.b, 0.9020)
  117. : control.second.pressed ? Qt.rgba(control.palette.accent.r, control.palette.accent.g, control.palette.accent.b, 0.8)
  118. : control.palette.accent)
  119. : control.palette.accent
  120. Behavior on diameter {
  121. // From WindowsUI 3 Animation Values
  122. NumberAnimation{
  123. duration: 167
  124. easing.type: Easing.OutCubic
  125. }
  126. }
  127. }
  128. }
  129. background: Item {
  130. implicitWidth: control.horizontal
  131. ? (_background.implicitWidth || _background.groove.implicitWidth)
  132. : (_background.implicitHeight || _background.groove.implicitHeight)
  133. implicitHeight: control.horizontal
  134. ? (_background.implicitHeight || _background.groove.implicitHeight)
  135. : (_background.implicitWidth || _background.groove.implicitWidth)
  136. property Item _background: Impl.StyleImage {
  137. visible: !control.__isHighContrast
  138. parent: control.background
  139. width: parent.width
  140. height: parent.width
  141. imageConfig: control.__config.background
  142. property Item groove: Impl.StyleImage {
  143. parent: control.background._background
  144. x: control.leftPadding - control.leftInset + (control.horizontal
  145. ? control.__firstHandleConfig.first_handle.width / 2
  146. : (control.availableWidth - width) / 2)
  147. y: control.topPadding - control.rightInset + (control.horizontal
  148. ? ((control.availableHeight - height) / 2)
  149. : control.__firstHandleConfig.first_handle.height / 2)
  150. width: control.horizontal
  151. ? control.availableWidth
  152. - (control.__firstHandleConfig.first_handle.width / 2) - (control.__secondHandleConfig.second_handle.width / 2)
  153. : implicitWidth
  154. height: control.horizontal
  155. ? implicitHeight
  156. : control.availableHeight
  157. - (control.__firstHandleConfig.first_handle.width / 2) - (control.__secondHandleConfig.second_handle.width / 2)
  158. imageConfig: control.__config.groove
  159. horizontal: control.horizontal
  160. property Rectangle track: Rectangle {
  161. parent: control.background._background.groove
  162. x: control.horizontal ? parent.width * control.first.position : 0
  163. y: control.horizontal ? 0 : parent.height - (parent.height * control.second.position)
  164. implicitWidth: control.horizontal ? control.__config.track.width : control.__config.track.height
  165. implicitHeight: control.horizontal ? control.__config.track.height : control.__config.track.width
  166. width: control.horizontal
  167. ? parent.width * (control.second.position - control.first.position)
  168. : parent.width
  169. height: control.horizontal
  170. ? parent.height
  171. : parent.height * (control.second.position - control.first.position)
  172. radius: control.__config.track.height * 0.5
  173. color: control.palette.accent
  174. }
  175. }
  176. property Repeater ticksTop: Repeater {
  177. parent: control.__isHighContrast ? control.background._highContrastBackground : control.background._background.groove
  178. model: control.__isDiscrete ? Math.floor(control.__steps) + 1 : 0
  179. delegate: Rectangle {
  180. width: control.horizontal ? 1 : 4
  181. height: control.horizontal ? 4 : 1
  182. x: control.horizontal
  183. ? 6 + index * (parent.width - 2 * 6 - width) / (control.background._background.ticksTop.model - 1)
  184. : -4 - width
  185. y: control.horizontal
  186. ? -4 - height
  187. : 6 + index * (parent.height - 2 * 6 - height) / (control.background._background.ticksTop.model - 1)
  188. color: Application.styleHints.colorScheme === Qt.Light ? "#9C000000" : "#9AFFFFFF"
  189. required property int index
  190. }
  191. }
  192. property Repeater ticksBottom: Repeater {
  193. parent: control.__isHighContrast ? control.background._highContrastBackground : control.background._background.groove
  194. model: control.__isDiscrete ? Math.floor(control.__steps) + 1 : 0
  195. delegate: Rectangle {
  196. width: control.horizontal ? 1 : 4
  197. height: control.horizontal ? 4 : 1
  198. x: control.horizontal
  199. ? 6 + index * (parent.width - 2 * 6 - width) / (control.background._background.ticksBottom.model - 1)
  200. : parent.width + 4
  201. y: control.horizontal
  202. ? parent.height + 4
  203. : 6 + index * (parent.height - 2 * 6 - height) / (control.background._background.ticksBottom.model - 1)
  204. color: Application.styleHints.colorScheme === Qt.Light ? "#9C000000" : "#9AFFFFFF"
  205. required property int index
  206. }
  207. }
  208. }
  209. property Item _highContrastBackground: Rectangle {
  210. parent: control.background
  211. visible: control.__isHighContrast
  212. implicitWidth: control.horizontal ? 200 : 4
  213. implicitHeight: control.horizontal ? 4 : 200
  214. x: control.leftPadding - control.leftInset + (control.horizontal
  215. ? control.__firstHandleConfig.first_handle.width / 2
  216. : (control.availableWidth - width) / 2)
  217. y: control.topPadding - control.topInset + (control.horizontal
  218. ? ((control.availableHeight - height) / 2)
  219. : control.__firstHandleConfig.first_handle.height / 2)
  220. width: control.horizontal
  221. ? control.availableWidth - control.__firstHandleConfig.first_handle.width
  222. : implicitWidth
  223. height: control.horizontal
  224. ? implicitHeight
  225. : control.availableHeight - control.__firstHandleConfig.first_handle.width
  226. radius: 2
  227. color: control.palette.buttonText
  228. scale: control.horizontal && control.mirrored ? -1 : 1
  229. Rectangle {
  230. x: control.horizontal ? parent.width * control.first.position : 0
  231. y: control.horizontal ? 0 : parent.height - (parent.height * control.second.position)
  232. implicitWidth: control.horizontal ? parent.width * (control.second.position - control.first.position) : parent.width
  233. implicitHeight: control.horizontal ? parent.height : parent.height * (control.second.position - control.first.position)
  234. radius: 2
  235. color: control.palette.highlight
  236. }
  237. }
  238. }
  239. }