Files

151 lines
5.6 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import qs.Common
import qs.Modules.OSD
import qs.DCommon.Widgets
Item {
id: root
required property var systemModel
property bool isVertical: false
property real iconSize: 36
readonly property int maximum: Math.max(root.systemModel.minimum + 1, Math.round(root.systemModel.maximum))
readonly property real fillRatio: Math.max(0, Math.min(1, (root.systemModel.value - root.systemModel.minimum) / Math.max(1, root.maximum - root.systemModel.minimum)))
// DSlider's own metrics, transposed, so the two orientations read as the same control.
readonly property real trackThickness: 12
readonly property real handleThickness: 4
readonly property real handleBreadth: 20
readonly property real fillHandleGap: 3
function trackFraction(localY) {
if (track.travel <= 0)
return 0;
return 1 - (localY - root.handleThickness / 2) / track.travel;
}
function applyFraction(fraction) {
const clamped = Math.max(0, Math.min(1, fraction));
const level = root.systemModel.minimum + clamped * (root.maximum - root.systemModel.minimum);
root.systemModel.setRatio(level / Math.max(1, root.maximum));
}
OsdLevelRow {
anchors.fill: parent
visible: !root.isVertical
iconName: root.systemModel.iconName
tonalIcon: false
iconInteractive: root.systemModel.mutable
iconLabel: root.systemModel.muted ? I18n.tr("Unmute") : I18n.tr("Mute")
value: Math.round(root.systemModel.value)
minimum: root.systemModel.minimum
maximum: root.maximum
unit: root.systemModel.unit
displayText: root.systemModel.displayValue
sliderEnabled: root.systemModel.available
onIconClicked: root.systemModel.toggleMute()
onSliderValueChanged: newValue => root.systemModel.setRatio(newValue / Math.max(1, root.maximum))
}
// DSlider is horizontal only, so a side strip gets its own stacked track.
Item {
id: verticalFace
anchors.fill: parent
anchors.topMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingS
visible: root.isVertical
DIcon {
id: levelIcon
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
name: root.systemModel.iconName
size: Math.min(Theme.iconSize, root.iconSize)
color: root.systemModel.mutable ? Theme.surfaceText : Theme.primary
MouseArea {
anchors.fill: parent
enabled: root.systemModel.mutable
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: root.systemModel.toggleMute()
}
}
StyledText {
id: levelLabel
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
text: root.systemModel.displayValue.length > 0 ? root.systemModel.displayValue : (Math.round(root.systemModel.value) + root.systemModel.unit)
color: Theme.surfaceText
font.pixelSize: Theme.fontSizeSmall
font.weight: Theme.fontWeightMedium
}
Item {
id: track
readonly property real travel: Math.max(0, height - root.handleThickness)
readonly property real handleOffset: track.travel * root.fillRatio
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: levelIcon.bottom
anchors.topMargin: Theme.spacingS
anchors.bottom: levelLabel.top
anchors.bottomMargin: Theme.spacingS
width: root.handleBreadth
Rectangle {
id: groove
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.bottom: parent.bottom
width: root.trackThickness
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.outline, Theme.foregroundAlpha)
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: Math.max(0, Math.min(parent.height, track.handleOffset - root.fillHandleGap))
radius: Theme.cornerRadius
topLeftRadius: 0
topRightRadius: 0
color: root.systemModel.available ? Theme.primary : Theme.withAlpha(Theme.surfaceText, 0.12)
}
}
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
y: track.travel - track.handleOffset
width: root.handleBreadth
height: root.handleThickness
radius: Theme.cornerRadius
color: root.systemModel.available ? Theme.primary : Theme.withAlpha(Theme.surfaceText, 0.12)
}
MouseArea {
id: trackArea
readonly property real grabPad: Theme.spacingS
anchors.fill: parent
anchors.margins: -grabPad
enabled: root.systemModel.available
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onPressed: mouse => root.applyFraction(root.trackFraction(mouse.y - grabPad))
onPositionChanged: mouse => {
if (pressed)
root.applyFraction(root.trackFraction(mouse.y - grabPad));
}
}
}
}
}