diff options
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 + } + } + } + } + } +} |
