Build the Panama Hyprland desktop
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
// A GNOME-style slider: a thick rounded track with an inline leading icon,
|
||||
// used for volume and brightness in the quick settings panel.
|
||||
//
|
||||
// Deliberately not QtQuick.Controls.Slider — that pulls in a style plugin and
|
||||
// fights the theme. This is ~50 lines and does exactly what's needed.
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import qs.config
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property real value: 0 // 0.0 .. 1.0
|
||||
property string icon: ""
|
||||
property bool enabled: true
|
||||
|
||||
// Emitted continuously while dragging.
|
||||
signal moved(real value)
|
||||
|
||||
implicitWidth: 240
|
||||
implicitHeight: 32
|
||||
|
||||
opacity: enabled ? 1.0 : 0.45
|
||||
|
||||
// ThemedIcon, not a bare IconImage — see the note in Toggle.qml: Adwaita
|
||||
// symbolic icons have a hardcoded near-black fill that Qt will not recolour.
|
||||
ThemedIcon {
|
||||
id: leadingIcon
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 18
|
||||
icon: root.icon
|
||||
tint: Theme.fg
|
||||
visible: root.icon !== ""
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: track
|
||||
anchors.left: leadingIcon.visible ? leadingIcon.right : parent.left
|
||||
anchors.leftMargin: leadingIcon.visible ? 10 : 0
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: 10
|
||||
radius: height / 2
|
||||
color: Theme.alpha(Theme.fg, 0.12)
|
||||
border.width: 0
|
||||
|
||||
Rectangle {
|
||||
id: fill
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width * Math.max(0, Math.min(1, root.value))
|
||||
radius: parent.radius
|
||||
border.width: 0
|
||||
|
||||
// The gradient is anchored to the full track, not to the fill, so
|
||||
// the colour at a given position never moves as the value changes —
|
||||
// dragging reveals the prism rather than squashing it.
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop {
|
||||
position: 0.0
|
||||
color: Theme.accent
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: Theme.mix(Theme.accent, Theme.accentSecondary, Math.max(0.001, Math.min(1, root.value)))
|
||||
}
|
||||
}
|
||||
|
||||
// Only animates when the value changes from outside (e.g. a media
|
||||
// key); dragging sets it directly and reads as instant.
|
||||
Behavior on width {
|
||||
enabled: !drag.pressed
|
||||
NumberAnimation {
|
||||
duration: Theme.durFast
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: knob
|
||||
width: 16
|
||||
height: 16
|
||||
radius: 8
|
||||
border.width: 0
|
||||
color: Theme.fg
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: Math.max(0, Math.min(parent.width - width, fill.width - width / 2))
|
||||
visible: drag.containsMouse || drag.pressed
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: drag
|
||||
anchors.fill: parent
|
||||
anchors.margins: -8 // easier to grab than a 10px track
|
||||
enabled: root.enabled
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
function apply(mouseX) {
|
||||
const ratio = Math.max(0, Math.min(1, (mouseX + 8) / track.width));
|
||||
root.moved(ratio);
|
||||
}
|
||||
|
||||
onPressed: event => apply(event.x)
|
||||
onPositionChanged: event => {
|
||||
if (pressed)
|
||||
apply(event.x);
|
||||
}
|
||||
onWheel: event => {
|
||||
const step = event.angleDelta.y > 0 ? 0.05 : -0.05;
|
||||
root.moved(Math.max(0, Math.min(1, root.value + step)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user