Last active
December 31, 2025 06:14
-
-
Save JustLinuxUser/36541b38f8dcd0e2cf22cab392568fad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import QtQuick | |
| import QtQuick.Layouts | |
| /* This one is used like so: | |
| AltScrollText { | |
| NText { | |
| pointSize: Style.fontSizeS | |
| // here I can use any NText properties | |
| } | |
| maxWidth: 200 | |
| text: root.statusText | |
| scrollMode: "always" | |
| } | |
| */ | |
| // TODO: ScrollMode enum | |
| Item { | |
| id: root | |
| required property string text | |
| default property Component delegate | |
| property real maxWidth: Infinity | |
| property string scrollMode: "never" | |
| // animation controls | |
| // TODO: Take into account the animation speed | |
| property real waitBeforeScrolling: 1000 | |
| property real scrollCycleDuration: Math.max(4000, root.text.length * 120) | |
| property real resettingDuration: 300 | |
| clip: true | |
| implicitHeight: titleText.height | |
| enum ScrollState { | |
| None = 0, | |
| Scrolling = 1, | |
| Resetting = 2 | |
| } | |
| property int state: AltScrollText.ScrollState.None | |
| onTextChanged: { | |
| if (titleText.item) | |
| titleText.item.text = text; | |
| if (loopingText.item) | |
| loopingText.item.text = text; | |
| // reset state | |
| root.implicitWidth = Math.min(root.maxWidth, titleText.width); | |
| root.state = AltScrollText.ScrollState.None; | |
| scrollContainer.x = 0; | |
| scrollTimer.restart(); | |
| root.updateState(); | |
| } | |
| Timer { | |
| id: scrollTimer | |
| interval: root.waitBeforeScrolling | |
| onTriggered: { | |
| root.state = AltScrollText.ScrollState.Scrolling; | |
| root.updateState(); | |
| } | |
| } | |
| MouseArea { | |
| id: hoverArea | |
| anchors.fill: parent | |
| hoverEnabled: true | |
| acceptedButtons: Qt.NoButton | |
| onEntered: root.updateState() | |
| onExited: root.updateState() | |
| } | |
| function ensureReset() { | |
| if (state === AltScrollText.ScrollState.Scrolling) | |
| state = AltScrollText.ScrollState.Resetting; | |
| } | |
| function updateState() { | |
| if (titleText.width <= root.maxWidth || scrollMode === "never") { | |
| state = AltScrollText.ScrollState.None; | |
| return; | |
| } | |
| if (scrollMode === "always") { | |
| if (hoverArea.containsMouse) { | |
| ensureReset(); | |
| } else { | |
| scrollTimer.restart(); | |
| } | |
| } else if (scrollMode === "hover") { | |
| if (hoverArea.containsMouse) | |
| state = AltScrollText.ScrollState.Scrolling; | |
| else | |
| ensureReset(); | |
| } | |
| } | |
| RowLayout { | |
| id: scrollContainer | |
| height: parent.height | |
| x: 0 | |
| spacing: 50 | |
| Loader { | |
| id: titleText | |
| sourceComponent: root.delegate | |
| onLoaded: this.item.text = root.text | |
| } | |
| Loader { | |
| id: loopingText | |
| sourceComponent: root.delegate | |
| visible: root.state === AltScrollText.ScrollState.Scrolling | |
| onLoaded: this.item.text = root.text | |
| } | |
| NumberAnimation on x { | |
| running: root.state === AltScrollText.ScrollState.Resetting | |
| to: 0 | |
| duration: root.resettingDuration | |
| easing.type: Easing.OutQuad | |
| onFinished: { | |
| root.state = AltScrollText.ScrollState.None; | |
| root.updateState(); | |
| } | |
| } | |
| NumberAnimation on x { | |
| running: root.state === AltScrollText.ScrollState.Scrolling | |
| from: 0 | |
| to: -(titleText.width + scrollContainer.spacing) | |
| duration: root.scrollCycleDuration | |
| loops: Animation.Infinite | |
| easing.type: Easing.Linear | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment