v1.2.0: add split-flap board and nixie tube display modes with display style config

This commit is contained in:
ArnoldCordewiner
2026-09-05 20:22:59 +02:00
parent 944b7587bc
commit 361a319d94
9 changed files with 385 additions and 31 deletions
+144
View File
@@ -0,0 +1,144 @@
/*
* Split-flap display mode — airport departure board style.
* White characters on black cells with a flap split line;
* changed characters flip with a cascading animation.
* Pure QtQuick so it can be tested outside the plasmoid shell.
*/
import QtQuick 2.15
Row {
id: root
// wired by the parent loader
property string display: "--"
property color trendColor: "#9e9e9e"
spacing: height * 0.06
property var chars: []
property bool ready: false
readonly property real cellFont: height * 0.72
readonly property real cellWidth: cellFont * 0.80
Component.onCompleted: {
chars = display.split("");
ready = true;
}
onDisplayChanged: {
if (!ready) {
return;
}
var nc = display.split("");
var n = Math.max(chars.length, nc.length);
for (var i = 0; i < n; i++) {
var from = i < chars.length ? chars[i] : "";
var to = i < nc.length ? nc[i] : "";
if (from !== to) {
var cell = rep.itemAt(i);
if (cell) {
cell.flipTo(to, i * 45);
}
}
}
chars = nc;
}
Repeater {
id: rep
model: root.chars.length
delegate: Rectangle {
id: cell
width: root.cellWidth
height: root.height
radius: 2
color: "#0b0b0d"
border.color: "#26262b"
border.width: 1
// plain property (not a binding) so the flip animation
// controls when the character actually changes
property string ch: ""
property string pendingCh: ""
Component.onCompleted: {
ch = root.chars[index] !== undefined ? root.chars[index] : "";
}
function flipTo(newCh, delay) {
if (newCh === ch) {
return;
}
pendingCh = newCh;
delayTimer.interval = Math.max(0, delay);
delayTimer.restart();
}
Timer {
id: delayTimer
interval: 0
onTriggered: flipAnim.start()
}
transform: Scale {
id: scaleTransform
origin.y: cell.height / 2
yScale: 1
}
SequentialAnimation {
id: flipAnim
NumberAnimation {
target: scaleTransform
property: "yScale"
to: 0.06
duration: 130
easing.type: Easing.InQuad
}
ScriptAction {
script: cell.ch = cell.pendingCh
}
NumberAnimation {
target: scaleTransform
property: "yScale"
to: 1
duration: 130
easing.type: Easing.OutQuad
}
}
Text {
anchors.centerIn: parent
text: cell.ch
color: "#f2f2f2"
font.family: "DejaVu Sans Mono"
font.pixelSize: root.cellFont
}
// the flap split line across the middle
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
y: parent.height / 2 - 1
width: parent.width
height: 2
color: "#000000"
opacity: 0.55
}
}
}
// trend LED (green/red/grey) — boards are monochrome, so the
// trend shows here instead of in the letter color
Rectangle {
width: root.height * 0.14
height: width
radius: width / 2
anchors.verticalCenter: parent.verticalCenter
color: root.trendColor
border.color: "#26262b"
border.width: 1
}
}