quickshell-toki-night/custom/CustomFilledSlider.qml

156 lines
4.6 KiB
QML

import qs.services
import qs.config
import QtQuick
import QtQuick.Controls
Slider {
id: root
required property string icon
required property color color
property real oldValue
property bool initializing: true
Timer {
id: initDelay
running: true
interval: 100
onTriggered: root.initializing = false
}
orientation: Qt.Vertical
background: CustomRect {
color: Config.colors.container
radius: 1000
CustomRect {
implicitWidth: root.orientation === Qt.Horizontal ? root.handle.x + root.handle.width : root.handle.width
y: root.orientation === Qt.Vertical ? root.handle.y : 0
implicitHeight: root.orientation === Qt.Vertical ? parent.height - y : root.handle.height
color: root.color
opacity: 0.8
radius: parent.radius
}
}
handle: Item {
id: handle
property bool moving: false
x: root.orientation === Qt.Horizontal ? root.visualPosition * (root.availableWidth - width) : 0
y: root.orientation === Qt.Vertical ? root.visualPosition * (root.availableHeight - height) : 0
implicitWidth: root.orientation === Qt.Horizontal ? root.height : root.width
implicitHeight: implicitWidth
Elevation {
anchors.fill: parent
radius: rect.radius
level: handleInteraction.containsMouse ? 2 : 1
}
CustomRect {
id: rect
anchors.fill: parent
color: root.color
radius: 1000
MouseArea {
id: handleInteraction
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.NoButton
}
MaterialIcon {
id: icon
property bool moving: handle.moving
property bool stoppingMove: false
function update(): void {
text = moving ? Qt.binding(() => Math.round(root.value * 100)) : Qt.binding(() => root.icon);
font.family = moving ? Config.font.family.sans : Config.font.family.material;
font.pointSize = moving ? Config.font.size.smaller : Config.font.size.larger;
}
animate: !moving && !stoppingMove
animateDuration: Config.anim.durations.small
text: root.icon
font.pointSize: Config.font.size.larger
color: Config.colors.primaryDark
anchors.centerIn: parent
Behavior on moving {
enabled: icon.moving !== targetValue
SequentialAnimation {
PropertyAction {
target: icon
property: "stoppingMove"
value: true
}
Anim {
target: icon
property: "scale"
from: 1
to: 0
duration: Config.anim.durations.small / 2
easing.bezierCurve: Config.anim.curves.standardAccel
}
ScriptAction {
script: icon.update()
}
Anim {
target: icon
property: "scale"
from: 0
to: 1
duration: Config.anim.durations.small / 2
easing.bezierCurve: Config.anim.curves.standardDecel
}
PropertyAction {
target: icon
property: "stoppingMove"
value: false
}
}
}
}
}
}
onPressedChanged: handle.moving = pressed
onValueChanged: {
if (Math.abs(value - oldValue) < 0.01)
return;
if (!initializing) {
oldValue = value;
handle.moving = true;
stateChangeDelay.restart();
}
}
Timer {
id: stateChangeDelay
interval: 600
onTriggered: {
if (!root.pressed)
handle.moving = false;
}
}
Behavior on value {
enabled: !root.initializing
Anim {
duration: Config.anim.durations.normal
}
}
}