Files
Panama/config/dot/quickshell/modules/settings/DisplayChips.qml
T

165 lines
5.7 KiB
QML

// The connected displays, as chips under the arrangement canvas.
//
// This replaces the "Connected display" picker card. Selecting a display is not
// a setting -- it decides which display everything below the canvas is talking
// about -- so it reads as a row of tabs rather than as a preference with a
// value. Clicking a tile on the canvas does the same thing; this is the same
// choice for anyone who would rather read names than shapes.
//
// Hidden for a single display, because a chooser offering one option is not a
// choice.
import QtQuick
import qs.config
Flow {
id: root
// [{ value, label, detail, primary }]
property var options: []
property string current: ""
property bool enabled: true
signal picked(string value)
visible: root.options.length > 1
width: parent ? parent.width : 620
height: root.visible ? implicitHeight : 0
spacing: 10
// Chips share the width evenly while they fit; below that they wrap into
// rows of whatever does fit, so a dock with four outputs is still legible
// in a half-screen window.
readonly property int columns: Math.max(1,
Math.min(root.options.length, Math.floor(root.width / 210)))
readonly property real chipWidth: root.columns > 0
? (root.width - root.spacing * (root.columns - 1)) / root.columns
: root.width
Repeater {
model: root.options
Rectangle {
id: chip
required property var modelData
required property int index
readonly property bool selected: String(chip.modelData.value) === root.current
width: root.chipWidth
implicitHeight: 52
radius: Theme.cardRadius
opacity: root.enabled ? 1 : 0.5
color: chip.selected
? Theme.alpha(Theme.accent, 0.1)
: Theme.alpha(Theme.bgPanel, chipHover.hovered && root.enabled ? 0.9 : 0.72)
border.width: chip.selected || chip.activeFocus ? 2 : 1
border.color: chip.activeFocus
? Theme.accentSecondary
: (chip.selected ? Theme.alpha(Theme.accent, 0.55) : Theme.alpha(Theme.fg, 0.07))
activeFocusOnTab: root.enabled
Accessible.role: Accessible.Button
Accessible.name: "Select " + String(chip.modelData.label ?? "")
Accessible.focusable: true
Accessible.focused: chip.activeFocus
function choose(): void {
if (root.enabled)
root.picked(String(chip.modelData.value));
}
Keys.onReturnPressed: chip.choose()
Keys.onSpacePressed: chip.choose()
// A screen, small. The second display gets the other end of the
// palette so the two chips are told apart at a glance rather than
// by reading them.
Rectangle {
id: thumbnail
anchors.left: parent.left
anchors.leftMargin: 13
anchors.verticalCenter: parent.verticalCenter
width: 34
height: 24
radius: 5
border.width: 1
border.color: Theme.alpha(Theme.fg, 0.25)
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop {
position: 0.0
color: Theme.alpha(chip.index % 2 === 0 ? Theme.accent : Theme.teal, 0.5)
}
GradientStop {
position: 1.0
color: Theme.alpha(chip.index % 2 === 0 ? Theme.accentSecondary : Theme.cyan, 0.4)
}
}
}
Column {
anchors.left: thumbnail.right
anchors.leftMargin: 11
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
spacing: 1
Row {
width: parent.width
spacing: 5
Text {
width: Math.max(0, parent.width - (star.visible ? star.width + 5 : 0))
text: String(chip.modelData.label ?? "")
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
elide: Text.ElideRight
}
Text {
id: star
visible: chip.modelData.primary === true
width: visible ? implicitWidth : 0
text: "★"
color: Theme.warn
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
}
Text {
width: parent.width
visible: text !== ""
text: String(chip.modelData.detail ?? "")
color: Theme.fgDim
font.family: Theme.fontFamily
font.features: Theme.tabularFigures
font.pixelSize: Math.max(9, Theme.fontSizeSmall - 1)
elide: Text.ElideRight
}
}
HoverHandler {
id: chipHover
enabled: root.enabled
cursorShape: Qt.PointingHandCursor
}
TapHandler {
enabled: root.enabled && !chip.selected
onTapped: {
chip.choose();
chip.forceActiveFocus();
}
}
}
}
}