From 851dbc76b3ba533b128e4d42d25560a95d6d3722 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 25 Sep 2026 20:12:48 +0200 Subject: 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 --- keybinds/PadPanel.qml | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 keybinds/PadPanel.qml (limited to 'keybinds/PadPanel.qml') 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. +// +// 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 + } + } + } + } + } +} -- cgit v1.2.3