Files

125 lines
4.2 KiB
QML

// A segmented choice that is NOT schema-bound.
//
// ChoiceRow reads its options from the preference schema. This one is handed
// them, for choices that describe system state rather than a Panama setting.
import QtQuick
import qs.config
SettingRow {
id: root
// [{ value, label }]
property var options: []
property var value: null
property bool enabled: true
signal selected(value: var)
controlWidth: Math.max(150, root.options.length * 92)
readonly property var currentOption:
root.options.find(option => option.value === root.value) ?? null
// One segment along, never wrapping -- the same neighbour a click would
// have picked, asked for in the same way.
function stepChoice(delta: int): void {
if (!root.enabled || root.options.length === 0)
return;
const at = root.options.findIndex(option => option.value === root.value);
const from = at < 0 ? 0 : at;
const next = Math.max(0, Math.min(root.options.length - 1, from + delta));
if (next === at)
return;
root.selected(root.options[next].value);
}
// Sibling of the strip rather than a child of it: a Rectangle inside a Row
// would be laid out as one more segment.
Rectangle {
anchors.fill: strip
anchors.margins: -3
radius: 12
z: -1
color: "transparent"
visible: strip.activeFocus
border.width: 2
border.color: Theme.accentSecondary
}
Row {
id: strip
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: 6
opacity: root.enabled ? 1 : 0.45
activeFocusOnTab: root.enabled
Accessible.role: Accessible.ComboBox
Accessible.name: root.label
Accessible.description: {
const chosen = root.currentOption
? String(root.currentOption.label ?? "")
: "nothing selected";
return root.detail === "" ? chosen : `${root.detail} ${chosen}`;
}
Accessible.focusable: root.enabled
Accessible.focused: strip.activeFocus
Keys.onLeftPressed: root.stepChoice(-1)
Keys.onUpPressed: root.stepChoice(-1)
Keys.onRightPressed: root.stepChoice(1)
Keys.onDownPressed: root.stepChoice(1)
Repeater {
model: root.options
delegate: Rectangle {
id: segment
required property var modelData
readonly property bool current: root.value === segment.modelData.value
width: Math.max(84, segmentLabel.implicitWidth + 22)
height: 30
radius: 9
color: segment.current
? Theme.alpha(Theme.accent, 0.22)
: Theme.alpha(Theme.fg, segmentMouse.containsMouse ? 0.12 : 0.06)
border.width: 1
border.color: segment.current
? Theme.alpha(Theme.accent, 0.5)
: Theme.alpha(Theme.fg, 0.08)
// Named individually so the reader says which option it is on.
// Not a Tab stop: the strip is one stop and the arrows walk it.
Accessible.role: Accessible.RadioButton
Accessible.name: String(segment.modelData.label ?? "")
Accessible.checked: segment.current
Text {
id: segmentLabel
anchors.centerIn: parent
text: String(segment.modelData.label ?? "")
color: segment.current ? Theme.fg : Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: segment.current ? Font.DemiBold : Font.Medium
}
MouseArea {
id: segmentMouse
anchors.fill: parent
hoverEnabled: true
enabled: root.enabled && !segment.current
cursorShape: Qt.PointingHandCursor
onClicked: root.selected(segment.modelData.value)
}
}
}
}
}