6import QGroundControl.Controls
10 width: indicatorCanvas.width
19 property real _sliderMaxVal: 0
20 property real _sliderMinVal: 0
21 property int _sliderType: GuidedValueSlider.SliderType.Altitude
22 property string _displayText: ""
24 property var _unitsSettings: QGroundControl.settingsManager.unitsSettings
25 property real _indicatorCenterPos: sliderFlickable.height / 2
27 property int _fullSliderRangeIndex: 2
28 property var _rgValueRanges: [ 400, 200, 100, 50, 25, 10 ]
29 property var _rgValidMajorTickSteps: [ 10, 25, 50, 100 ]
30 property int _fullSliderValueRange: _rgValueRanges[_fullSliderRangeIndex]
31 property int _halfSliderValueRange: _fullSliderValueRange / 2
33 property real _majorTickWidth: ScreenTools.largeFontPixelWidth * 2
34 property real _majorTickPixelHeight: ScreenTools.largeFontPixelHeight * 2
35 property real _tickValueRightMargin: ScreenTools.defaultFontPixelWidth / 2
36 property real _minorTickWidth: _majorTickWidth / 2
37 property real _sliderValuePerPixel: _majorTickValueStep / _majorTickPixelHeight
39 property int _majorTickValueStep: 10
40 property int _minorTickValueStep: _majorTickValueStep / 2
42 property real _sliderValue: _firstPixelValue - ((sliderFlickable.contentY + _indicatorCenterPos) * _sliderValuePerPixel)
44 // Calculate the full range of the slider. We have been given a min/max but that is for clamping the selected slider values.
45 // We need expand that range to take into account additional values that must be displayed above/below the value indicator
46 // when it is at min/max.
48 // Add additional major ticks above/below min/max to ensure we can display the full visual range of the slider
49 property int _majorTicksVisibleAboveIndicator: Math.floor(_indicatorCenterPos / _majorTickPixelHeight)
50 property int _majorTickAdjustment: _majorTicksVisibleAboveIndicator * _majorTickValueStep
52 // Calculate the next major tick above/below min/max
53 property int _majorTickMaxValue: Math.ceil((_sliderMaxVal + _majorTickAdjustment)/ _majorTickValueStep) * _majorTickValueStep
54 property int _majorTickMinValue: Math.floor((_sliderMinVal - _majorTickAdjustment)/ _majorTickValueStep) * _majorTickValueStep
56 // Now calculate the position we draw the first tick mark such that we are not allowed to flick above the max value
57 property real _firstTickPixelOffset: _indicatorCenterPos - ((_majorTickMaxValue - _sliderMaxVal) / _sliderValuePerPixel)
58 property real _firstPixelValue: _majorTickMaxValue + (_firstTickPixelOffset * _sliderValuePerPixel)
60 // Calculate the slider height such that we can flick below the min value
61 property real _sliderHeight: (_firstPixelValue - _sliderMinVal) / _sliderValuePerPixel + (sliderFlickable.height - _indicatorCenterPos)
63 property int _cMajorTicks: (_majorTickMaxValue - _majorTickMinValue) / _majorTickValueStep + 1
65 property var _qgcPal: QGroundControl.globalPalette
67 function setCurrentValue(currentValue, animate = true) {
68 // Position the slider such that the indicator is pointing to the current value
69 var contentY = (_firstPixelValue - currentValue) / _sliderValuePerPixel - _indicatorCenterPos
71 flickableAnimation.from = sliderFlickable.contentY
72 flickableAnimation.to = contentY
73 flickableAnimation.start()
75 sliderFlickable.contentY = contentY
79 /// Slider values should be in converted app units.
80 function setupSlider(sliderType, minValue, maxValue, currentValue, displayText) {
81 //console.log("setupSlider: sliderType: ", sliderType, " minValue: ", minValue, " maxValue: ", maxValue, " currentValue: ", currentValue, " displayText: ", displayText)
82 _sliderType = sliderType
83 _sliderMinVal = minValue
84 _sliderMaxVal = maxValue
85 _displayText = displayText
86 setCurrentValue(currentValue, false)
89 function _clampedSliderValueString(value) {
91 if (_unitsSettings.verticalDistanceUnits.rawValue === UnitsSettings.VerticalDistanceUnitsMeters) {
94 return Math.min(Math.max(value , _sliderMinVal), _sliderMaxVal).toFixed(decimalPlaces)
97 function getOutputValue() {
98 return parseFloat(_clampedSliderValueString(_sliderValue))
107 color: _qgcPal.window
116 Layout.fillWidth: true
117 horizontalAlignment: Text.AlignHCenter
118 font.pointSize: ScreenTools.smallFontPointSize
124 Layout.fillWidth: true
125 Layout.fillHeight: true
126 contentWidth: sliderContainer.width
127 contentHeight: sliderContainer.height
128 flickableDirection: Flickable.VerticalFlick
130 // The default deceleration is too fast for the slider. We need to slow it down a bit. This allows for large movements of the slider
131 // to set large altitudes.
132 Component.onCompleted: flickDeceleration = flickDeceleration / 2
134 PropertyAnimation on contentY {
135 id: flickableAnimation
139 easing.type: Easing.OutCubic
142 property real fromValue
143 property real toValue
149 height: _sliderHeight
156 width: sliderContainer.width
158 y: _majorTickPixelHeight * index + _firstTickPixelOffset
159 opacity: tickValue < _sliderMinVal || tickValue > _sliderMaxVal ? 0.5 : 1
161 property real tickValue: _majorTickMaxValue - (_majorTickValueStep * index)
165 width: _majorTickWidth
171 anchors.margins: _tickValueRightMargin
172 anchors.right: parent.right
173 anchors.verticalCenter: majorTick.verticalCenter
174 text: parent.tickValue
175 font.pointSize: ScreenTools.largeFontPointSize
182 model: _cMajorTicks * 2
185 y: _majorTickPixelHeight / 2 * index + + _firstTickPixelOffset
186 width: _minorTickWidth
189 opacity: tickValue < _sliderMinVal || tickValue > _sliderMaxVal ? 0.5 : 1
190 visible: index % 2 === 1
192 property real tickValue: _majorTickMaxValue - ((_majorTickValueStep / 2) * index)
202 y: sliderFlickable.y + _indicatorCenterPos - height / 2
203 width: Math.max(minIndicatorWidth, maxMajorTickDisplayWidth)
204 height: indicatorHeight
208 id: maxDigitsTextMeasure
210 font.pointSize: ScreenTools.largeFontPointSize
214 property real indicatorValueMargins: ScreenTools.defaultFontPixelWidth / 2
215 property real indicatorHeight: valueLabel.contentHeight
216 property real pointerWidth: ScreenTools.defaultFontPixelWidth
217 property real minIndicatorWidth: pointerWidth + (indicatorValueMargins * 2) + valueLabel.contentWidth
218 property real maxDigitsWidth: maxDigitsTextMeasure.contentWidth
219 property real intraTickDigitSpacing: ScreenTools.defaultFontPixelWidth
220 property real maxMajorTickDisplayWidth: _majorTickWidth + intraTickDigitSpacing + maxDigitsWidth + _tickValueRightMargin
223 var ctx = getContext("2d")
224 ctx.strokeStyle = _qgcPal.text
225 ctx.fillStyle = _qgcPal.window
228 ctx.moveTo(0, indicatorHeight / 2)
229 ctx.lineTo(pointerWidth, indicatorHeight / 4)
230 ctx.lineTo(pointerWidth, 1)
231 ctx.lineTo(width - 1, 1)
232 ctx.lineTo(width - 1, indicatorHeight - 1)
233 ctx.lineTo(pointerWidth, indicatorHeight - 1)
234 ctx.lineTo(pointerWidth, indicatorHeight / 4 * 3)
240 // Repaint when palette changes
243 function onPaletteChanged() {
244 indicatorCanvas.requestPaint()
250 anchors.margins: indicatorCanvas.indicatorValueMargins
251 anchors.right: parent.right
252 anchors.verticalCenter: parent.verticalCenter
253 horizontalAlignment: Text.AlignRight
254 verticalAlignment: Text.AlignVCenter
255 text: _clampedSliderValueString(_sliderValue) + " " + unitsString
256 font.pointSize: ScreenTools.largeFontPointSize
258 property var unitsString: _sliderType === GuidedValueSlider.Speed ?
259 QGroundControl.unitsConversion.appSettingsSpeedUnitsString :
260 QGroundControl.unitsConversion.appSettingsVerticalDistanceUnitsString
266 sliderValueTextField.text = _clampedSliderValueString(_sliderValue)
267 sliderValueTextField.visible = true
268 sliderValueTextField.forceActiveFocus()
273 id: sliderValueTextField
274 anchors.leftMargin: indicatorCanvas.pointerWidth
277 unitsLabel: valueLabel.unitsString
279 numericValuesOnly: true
284 setCurrentValue(parseFloat(_clampedSliderValueString(parseFloat(text))))
289 function on_SliderValueChanged() { sliderValueTextField.visible = false }
296 anchors.bottom: parent.bottom