diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-25 20:12:48 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-25 20:12:48 +0200 |
| commit | 851dbc76b3ba533b128e4d42d25560a95d6d3722 (patch) | |
| tree | ced834871dfa997e8be3142ce36b322b28326ccd /keybinds/PadPanel.qml | |
| parent | 85206cf2939109b2b28044b35b37be510ad2b3fa (diff) | |
| download | quickshell-851dbc76b3ba533b128e4d42d25560a95d6d3722.tar.gz quickshell-851dbc76b3ba533b128e4d42d25560a95d6d3722.zip | |
feat(keybinds): draw the macropad beside the list
The pad glyph on each row was too small to read. The left fifth of the
overlay now draws the pad at size, each key labelled with its plain
action; hovering a key or an encoder lists everything it does, held
keys and turn direction spelled out. padActions() in Binds.js inverts
the grouped rows into that per-key list, and PAD's turn values became
words for it. The panel is pinned at a fixed height: centred, it moved
whenever the hovered key's list changed length.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'keybinds/PadPanel.qml')
| -rw-r--r-- | keybinds/PadPanel.qml | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/keybinds/PadPanel.qml b/keybinds/PadPanel.qml new file mode 100644 index 0000000..04c95a5 --- /dev/null +++ b/keybinds/PadPanel.qml @@ -0,0 +1,162 @@ +// 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 QtQuick + +// The macropad as it sits on the desk: twelve keys in three rows of four, +// the two encoders to their right. Each key carries its plain action; +// hovering a key or an encoder lists everything it does underneath. The +// last one hovered stays listed, so moving the pointer off does not blank it. +Item { + id: panel + + // Binds.padActions(): "k1".."k12", "top", "bottom" to [{ how, label }]. + property var actions: ({}) + property string hovered: "" + + // Keys are unit wide; the pad is four of them, three gaps, a gap and an + // encoder: 5.56 units, fitted to most of the panel's width. + readonly property int unit: Math.floor(width * 0.85 / 5.56) + readonly property int padWidth: Math.round(unit * 5.56) + + function plain(id) { + const a = (actions[id] ?? []).find(x => x.how === "Press"); + return a ? a.label : ""; + } + + function title(id) { + if (id === "top") return "Top encoder"; + if (id === "bottom") return "Bottom encoder"; + return "Key " + id.slice(1); + } + + // Pinned at a fixed height rather than centred: centred, the pad moved + // every time the list under it changed length. + Column { + anchors.horizontalCenter: parent.horizontalCenter + y: parent.height * 0.3 + spacing: panel.unit * 0.5 + + Row { + spacing: panel.unit * 0.3 + + Grid { + id: keys + columns: 4 + spacing: panel.unit * 0.12 + + Repeater { + model: 12 + + Rectangle { + required property int index + readonly property string padId: "k" + (index + 1) + + width: panel.unit + height: panel.unit + radius: panel.unit * 0.12 + color: panel.hovered === padId ? Theme.surfaceAlt : Theme.surface + border.color: panel.hovered === padId ? Theme.accent : "transparent" + border.width: 2 + + Text { + anchors.fill: parent + anchors.margins: 4 + text: panel.plain(parent.padId) + wrapMode: Text.Wrap + elide: Text.ElideRight + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: Theme.text + font.family: Theme.fontFamily + font.pixelSize: Math.max(10, panel.unit * 0.16) + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: panel.hovered = parent.padId + } + } + } + } + + // One encoder level with the top row, one with the bottom. + Item { + width: panel.unit * 0.9 + height: keys.height + + Repeater { + model: ["top", "bottom"] + + Rectangle { + required property string modelData + + y: modelData === "top" ? 0 : parent.height - height + width: parent.width + height: width + radius: width / 2 + color: panel.hovered === modelData ? Theme.surfaceAlt : Theme.surface + border.color: panel.hovered === modelData ? Theme.accent : Theme.overlay + border.width: 2 + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: panel.hovered = parent.modelData + } + } + } + } + } + + Column { + width: panel.padWidth + spacing: 6 + + Text { + text: panel.hovered ? panel.title(panel.hovered) : "Hover a key or an encoder" + color: Theme.accent + font.family: Theme.fontFamily + font.pixelSize: 18 + font.bold: true + bottomPadding: 4 + } + + Repeater { + model: panel.actions[panel.hovered] ?? [] + + // Fixed widths summing to the column's: a Row sizes to its + // children. + Row { + required property var modelData + spacing: 12 + + Text { + width: panel.padWidth * 0.4 + text: modelData.how + color: Theme.subtext + font.family: Theme.fontFamily + font.pixelSize: 15 + } + Text { + width: panel.padWidth * 0.6 - 12 + text: modelData.label + wrapMode: Text.Wrap + color: Theme.text + font.family: Theme.fontFamily + font.pixelSize: 15 + } + } + } + } + } +} |
