aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/island/PanelSlider.qml
blob: bbc087270628e3a885dc30b7367e394ff4cc7b61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

import Quickshell
import Quickshell.Widgets
import QtQuick
import ".."

// An icon, a track and a label: drag or click sets, the wheel steps one per
// notch. Shared by the headphones and Sonix panels. The width is the user's.
Row {
    id: row
    property int cp: 0
    property string icon: ""
    property real value: 0
    property bool muted: false
    property string label: ""
    signal moved(real v)
    signal stepped(int d)
    signal iconClicked()

    spacing: 10

    Item {
        anchors.verticalCenter: parent.verticalCenter
        width: 20
        height: 20

        Text {
            visible: row.icon === ""
            anchors.centerIn: parent
            text: String.fromCodePoint(row.cp)
            font { family: Theme.iconFamily; pixelSize: 20 }
            color: Theme.subtext
        }

        IconImage {
            visible: row.icon !== ""
            anchors.centerIn: parent
            implicitSize: 18
            source: row.icon !== "" ? Quickshell.iconPath(row.icon, true) : ""
        }

        MouseArea {
            anchors.fill: parent
            enabled: row.enabled
            cursorShape: Qt.PointingHandCursor
            onClicked: row.iconClicked()
        }
    }

    Rectangle {
        anchors.verticalCenter: parent.verticalCenter
        width: row.width - 20 - 44 - row.spacing * 2
        height: 8
        radius: 4
        color: Theme.surface

        Rectangle {
            height: parent.height
            radius: parent.radius
            width: parent.width * Math.max(0, Math.min(1, row.value))
            color: row.muted ? Theme.red : Theme.accent
            opacity: row.muted ? 0.5 : 1
        }

        // Taller than the track so it is easy to hit. A MouseArea for the
        // wheel, not a WheelHandler (AGENTS.md); one step per notch (120),
        // since a touchpad sends many small deltas.
        MouseArea {
            anchors { fill: parent; topMargin: -8; bottomMargin: -8 }
            enabled: row.enabled
            preventStealing: true
            cursorShape: Qt.PointingHandCursor
            property real acc: 0
            function at(x) { return Math.max(0, Math.min(1, x / width)); }
            onPressed: mouse => row.moved(at(mouse.x))
            onPositionChanged: mouse => { if (pressed) row.moved(at(mouse.x)); }
            onWheel: wheel => {
                acc += wheel.angleDelta.y;
                while (Math.abs(acc) >= 120) {
                    row.stepped(acc > 0 ? 1 : -1);
                    acc -= acc > 0 ? 120 : -120;
                }
                wheel.accepted = true;
            }
        }
    }

    Text {
        anchors.verticalCenter: parent.verticalCenter
        width: 44
        horizontalAlignment: Text.AlignRight
        text: row.label
        font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 }
        color: row.muted ? Theme.red : Theme.subtext
    }
}