4pragma ComponentBehavior: Bound
19 objectName: "sliderTrack"
20 Accessible.ignored:
true
22 required
property bool horizontal
23 required
property bool mirrored
24 required
property bool centered
25 required
property bool rangeMode
26 required
property bool controlEnabled
27 required
property real visualPosition
28 required
property real secondVisualPosition
29 required
property real rangeFrom
30 required
property real rangeTo
31 required
property real stepSize
32 required
property int tickVisibilityMode
33 required
property int autoLimitMode
34 required
property int autoHideMode
35 required
property int hiddenMode
36 required
property real trackHeight
37 required
property real trackOuterCornerRadius
38 required
property real handleHeight
39 required
property real effectiveHandleWidth
40 required
property real labelSpace
41 required
property color activeTrackColor
42 required
property color inactiveTrackColor
43 required
property color activeTickColor
44 required
property color inactiveTickColor
45 required
property real activeTrackOpacity
46 required
property real inactiveTrackOpacity
47 required
property string trackIconActiveStart
48 required
property string trackIconActiveEnd
49 required
property string trackIconInactiveStart
50 required
property string trackIconInactiveEnd
51 required
property color trackIconActiveColor
52 required
property color trackIconInactiveColor
53 required
property real trackIconSize
54 required
property real trackIconPadding
56 readonly
property real baseCrossSize: Math.max(MD.Tokens.slider.minimumInteractiveSize, trackHeight, handleHeight)
57 implicitWidth: horizontal ? MD.Tokens.slider.defaultLength : baseCrossSize + labelSpace
58 implicitHeight: horizontal ? baseCrossSize + labelSpace : MD.Tokens.slider.defaultLength
60 readonly
property real axisLength: horizontal ? width : height
61 readonly
property real crossLength: horizontal ? height : width
62 readonly
property real crossCenter: {
64 return root.labelSpace + (root.height - root.labelSpace) / 2;
66 return (root.width - root.labelSpace) / 2;
67 return root.labelSpace + (root.width - root.labelSpace) / 2;
69 readonly
property real handleContainerSize: trackOuterCornerRadius * 2
70 readonly
property real handleTravel: Math.max(0, axisLength - handleContainerSize)
71 readonly
property real handleCenter: trackOuterCornerRadius + visualPosition * handleTravel
72 readonly
property real secondHandleCenter: trackOuterCornerRadius + secondVisualPosition * handleTravel
73 readonly
property real rangeStartHandleCenter: Math.min(handleCenter, secondHandleCenter)
74 readonly
property real rangeEndHandleCenter: Math.max(handleCenter, secondHandleCenter)
75 readonly
property real handleGap: effectiveHandleWidth / 2 + MD.Tokens.slider.activeHandleLeadingSpace
76 readonly
property real centerPosition: axisLength / 2
77 readonly
property real centerGap: MD.Tokens.slider.activeHandleLeadingSpace
78 readonly
property bool handleBeforeCenter: handleCenter < centerPosition
79 readonly
property bool handleAfterCenter: handleCenter > centerPosition
80 readonly
property bool mirroredHorizontal: horizontal && mirrored
82 readonly
property real activeStart: {
84 return root.rangeStartHandleCenter + root.handleGap;
86 return root.mirroredHorizontal ? root.handleCenter + root.handleGap : 0;
87 if (root.handleBeforeCenter)
88 return root.handleCenter + root.handleGap;
89 if (root.handleAfterCenter)
90 return root.centerPosition + root.centerGap;
91 return root.centerPosition;
93 readonly
property real activeEnd: {
95 return root.rangeEndHandleCenter - root.handleGap;
97 return root.mirroredHorizontal ? root.axisLength : root.handleCenter - root.handleGap;
98 if (root.handleBeforeCenter)
99 return root.centerPosition - root.centerGap;
100 if (root.handleAfterCenter)
101 return root.handleCenter - root.handleGap;
102 return root.centerPosition;
104 readonly
property real leadingInactiveStart: 0
105 readonly
property real leadingInactiveEnd: {
107 return root.rangeStartHandleCenter - root.handleGap;
109 return root.mirroredHorizontal ? root.handleCenter - root.handleGap : 0;
110 if (root.handleBeforeCenter)
111 return root.handleCenter - root.handleGap;
112 if (!root.handleAfterCenter)
113 return root.centerPosition - root.handleGap;
114 return root.centerPosition - root.centerGap;
116 readonly
property real trailingInactiveStart: {
118 return root.rangeEndHandleCenter + root.handleGap;
120 return root.mirroredHorizontal ? root.axisLength : root.handleCenter + root.handleGap;
121 if (root.handleAfterCenter)
122 return root.handleCenter + root.handleGap;
123 if (!root.handleBeforeCenter)
124 return root.centerPosition + root.handleGap;
125 return root.centerPosition + root.centerGap;
127 readonly
property real trailingInactiveEnd: root.axisLength
128 readonly
property real inactiveStart: mirroredHorizontal ? leadingInactiveStart : trailingInactiveStart
129 readonly
property real inactiveEnd: mirroredHorizontal ? leadingInactiveEnd : trailingInactiveEnd
131 readonly
property int desiredTickCount: {
132 if (root.stepSize <= 0 || root.rangeTo <= root.rangeFrom)
134 return Math.floor((root.rangeTo - root.rangeFrom) / root.stepSize + Number.EPSILON) + 1;
136 readonly
property real lastTickPosition: {
137 if (root.desiredTickCount <= 1)
139 return (root.desiredTickCount - 1) * root.stepSize / (root.rangeTo - root.rangeFrom);
141 readonly
property real tickSpanLength: handleTravel * lastTickPosition
142 readonly
property int maxTickCount: {
143 if (root.desiredTickCount <= 0 || root.handleTravel <= 0)
145 if (root.desiredTickCount === 1)
147 return Math.floor(root.tickSpanLength / MD.Tokens.slider.tickMinSpacing) + 1;
149 readonly
property int tickCount: {
150 if (root.desiredTickCount <= 0 || root.maxTickCount <= 0)
152 if (root.tickVisibilityMode === root.autoLimitMode)
153 return Math.min(root.desiredTickCount, root.maxTickCount);
154 if (root.tickVisibilityMode === root.autoHideMode)
155 return root.desiredTickCount <= root.maxTickCount ? root.desiredTickCount : 0;
156 if (root.tickVisibilityMode === root.hiddenMode)
160 readonly
property bool iconsAllowed: stepSize <= 0 && !centered && !rangeMode && trackIconSize > 0
161 readonly
property real iconRequiredLength: trackIconSize + root.trackIconPadding * 2
163 function tickStepIndex(displayIndex) {
164 if (root.tickCount <= 1)
166 return Math.round(displayIndex * (root.desiredTickCount - 1) / (root.tickCount - 1));
169 function tickAxisPosition(displayIndex) {
170 const logicalPosition = root.tickStepIndex(displayIndex) * root.stepSize / (root.rangeTo - root.rangeFrom);
171 const visual = root.mirroredHorizontal ? 1 - logicalPosition : logicalPosition;
172 return root.trackOuterCornerRadius + visual * root.handleTravel;
175 function pointIsActive(point) {
176 return point >= root.activeStart && point <= root.activeEnd;
179 function pointOverlapsGap(point) {
180 if (Math.abs(point - root.handleCenter) < root.handleGap)
182 if (root.rangeMode && Math.abs(point - root.secondHandleCenter) < root.handleGap)
184 return root.centered && Math.abs(point - root.centerPosition) < root.centerGap;
187 component TrackSegment: Rectangle {
188 required
property real segmentStart
189 required
property real segmentEnd
190 required
property real startCornerRadius
191 required
property real endCornerRadius
193 readonly
property real segmentLength: Math.max(0, segmentEnd - segmentStart)
194 readonly
property real boundedStartRadius: Math.min(startCornerRadius, segmentLength / 2, root.trackHeight / 2)
195 readonly
property real boundedEndRadius: Math.min(endCornerRadius, segmentLength / 2, root.trackHeight / 2)
197 visible: segmentLength > 0
198 x: root.horizontal ? segmentStart : root.crossCenter - root.trackHeight / 2
199 y: root.horizontal ? root.crossCenter - root.trackHeight / 2 : segmentStart
200 width: root.horizontal ? segmentLength : root.trackHeight
201 height: root.horizontal ? root.trackHeight : segmentLength
203 topLeftRadius: root.horizontal ? boundedStartRadius : boundedStartRadius
204 bottomLeftRadius: root.horizontal ? boundedStartRadius : boundedEndRadius
205 topRightRadius: root.horizontal ? boundedEndRadius : boundedStartRadius
206 bottomRightRadius: root.horizontal ? boundedEndRadius : boundedEndRadius
210 duration: MD.Tokens.motion.duration.short2
214 Behavior on opacity {
216 duration: MD.Tokens.motion.duration.short2
222 id: leadingInactiveTrack
223 objectName:
"inactiveTrackLeading"
224 segmentStart: root.leadingInactiveStart
225 segmentEnd: root.leadingInactiveEnd
226 startCornerRadius: root.trackOuterCornerRadius
227 endCornerRadius: MD.Tokens.slider.trackInsideCornerRadius
228 color: root.inactiveTrackColor
229 opacity: root.inactiveTrackOpacity
234 objectName:
"activeTrack"
235 segmentStart: root.activeStart
236 segmentEnd: root.activeEnd
237 startCornerRadius: segmentStart <= 0 ? root.trackOuterCornerRadius : MD.Tokens.slider.trackInsideCornerRadius
238 endCornerRadius: segmentEnd >= root.axisLength ? root.trackOuterCornerRadius : MD.Tokens.slider.trackInsideCornerRadius
239 color: root.activeTrackColor
240 opacity: root.activeTrackOpacity
244 id: trailingInactiveTrack
245 objectName:
"inactiveTrackTrailing"
246 segmentStart: root.trailingInactiveStart
247 segmentEnd: root.trailingInactiveEnd
248 startCornerRadius: MD.Tokens.slider.trackInsideCornerRadius
249 endCornerRadius: root.trackOuterCornerRadius
250 color: root.inactiveTrackColor
251 opacity: root.inactiveTrackOpacity
256 objectName:
"tickRepeater"
257 model: root.tickCount
259 delegate: Rectangle {
261 required
property int index
263 readonly
property real axisPosition: root.tickAxisPosition(index)
265 objectName:
"sliderTick"
266 visible: !root.pointOverlapsGap(axisPosition)
267 x: root.horizontal ? axisPosition - width / 2 : root.crossCenter - width / 2
268 y: root.horizontal ? root.crossCenter - height / 2 : axisPosition - height / 2
269 width: MD.Tokens.slider.tickSize
270 height: MD.Tokens.slider.tickSize
272 color: root.pointIsActive(axisPosition) ? root.activeTickColor : root.inactiveTickColor
273 opacity: MD.Tokens.slider.visibleOpacity
277 component StopIndicator: Rectangle {
278 required
property real axisPosition
280 width: MD.Tokens.slider.stopIndicatorSize
281 height: MD.Tokens.slider.stopIndicatorSize
283 x: root.horizontal ? axisPosition - width / 2 : root.crossCenter - width / 2
284 y: root.horizontal ? root.crossCenter - height / 2 : axisPosition - height / 2
285 color: root.inactiveTickColor
286 opacity: MD.Tokens.slider.visibleOpacity
290 objectName:
"startStopIndicator"
291 axisPosition: root.trackOuterCornerRadius
292 visible: (root.centered || root.rangeMode) && !root.pointOverlapsGap(axisPosition)
296 objectName:
"endStopIndicator"
297 axisPosition: root.axisLength - root.trackOuterCornerRadius
298 visible: (root.centered || root.rangeMode || !root.mirroredHorizontal) && !root.pointOverlapsGap(axisPosition)
302 objectName:
"mirroredEndStopIndicator"
303 axisPosition: root.trackOuterCornerRadius
304 visible: !root.centered && !root.rangeMode && root.mirroredHorizontal && !root.pointOverlapsGap(axisPosition)
307 component TrackIcon: MD.Symbol {
308 required
property bool activeSegment
309 required
property bool logicalStart
311 readonly
property real segmentStart: activeSegment ? root.activeStart : root.inactiveStart
312 readonly
property real segmentEnd: activeSegment ? root.activeEnd : root.inactiveEnd
313 readonly
property bool logicalForward: !root.mirroredHorizontal
314 readonly
property real axisPosition: {
315 const fromStart = logicalStart === logicalForward;
317 return segmentStart + root.trackIconPadding + root.trackIconSize / 2;
318 return segmentEnd - root.trackIconPadding - root.trackIconSize / 2;
321 visible: root.iconsAllowed && name.length > 0 && segmentEnd - segmentStart >= root.iconRequiredLength
322 x: root.horizontal ? axisPosition - width / 2 : root.crossCenter - width / 2
323 y: root.horizontal ? root.crossCenter - height / 2 : axisPosition - height / 2
324 iconWidth: root.trackIconSize
325 iconHeight: root.trackIconSize
329 objectName:
"activeStartIcon"
332 name: root.trackIconActiveStart
333 color: root.trackIconActiveColor
337 objectName:
"activeEndIcon"
340 name: root.trackIconActiveEnd
341 color: root.trackIconActiveColor
345 objectName:
"inactiveStartIcon"
348 name: root.trackIconInactiveStart
349 color: root.trackIconInactiveColor
353 objectName:
"inactiveEndIcon"
356 name: root.trackIconInactiveEnd
357 color: root.trackIconInactiveColor