Rebuild Displays around the canvas, and let the transaction keep color
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user