/* * 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 } }