mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 06:13:09 +00:00
119 lines
4.1 KiB
QML
119 lines
4.1 KiB
QML
// SPDX-FileCopyrightText: 2022 Yari Polla <skilvingr@gmail.com>
|
|
// SPDX-FileCopyrightText: 2025 Micah Stanley <stanleymicah@proton.me>
|
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
|
|
|
import QtQuick 2.15
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import QtQuick.Effects
|
|
|
|
import org.kde.kirigami as Kirigami
|
|
import org.kde.plasma.components 3.0 as PlasmaComponents
|
|
import Qt5Compat.GraphicalEffects
|
|
|
|
/**
|
|
* This is a simple marquee (flowing) label based on PlasmaComponents Label.
|
|
*/
|
|
|
|
OpacityMask {
|
|
id: root
|
|
height: row.height
|
|
|
|
// label values
|
|
required property string inputText
|
|
property font font
|
|
property var textFormat: Text.RichText
|
|
// properties for the marquee label scroll speed and wait duration
|
|
readonly property real scrollSpeed: 0.025
|
|
readonly property int waitDuration: 2000
|
|
|
|
readonly property string filteredText: inputText.replace(/\n/g, ' ') // remove new line characters
|
|
readonly property bool charactersOverflowing: txtMeter.advanceWidth > root.width // true when text is overflowing
|
|
|
|
// update animation values and text positions whenever the label overflows or changes
|
|
onFilteredTextChanged: if (root.charactersOverflowing) { textAnimationLoop.restart() }
|
|
onCharactersOverflowingChanged: if (charactersOverflowing) { row.scrollPosition = 0 }
|
|
|
|
Item {
|
|
id: rowContaner
|
|
anchors.fill: parent
|
|
height: row.height
|
|
opacity: 0 // we display with the opacity gradient below
|
|
|
|
// use two identical labels for scrolling so we can give the illusion of infinite scrolling
|
|
RowLayout {
|
|
id: row
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
|
|
property real scrollPosition: 0
|
|
|
|
transform: [
|
|
Translate {
|
|
x: row.scrollPosition
|
|
}
|
|
]
|
|
|
|
spacing: 32
|
|
|
|
PlasmaComponents.Label {
|
|
id: label
|
|
font: root.font
|
|
textFormat: root.textFormat
|
|
text: filteredText
|
|
|
|
Layout.alignment: Qt.AlignLeft
|
|
|
|
TextMetrics {
|
|
id: txtMeter
|
|
font: root.font
|
|
text: filteredText
|
|
}
|
|
}
|
|
|
|
PlasmaComponents.Label {
|
|
// hide this label when the text is not overflowing so the user never sees both labels
|
|
visible: textAnimationLoop.running
|
|
font: root.font
|
|
textFormat: root.textFormat
|
|
text: filteredText
|
|
|
|
Layout.alignment: Qt.AlignLeft
|
|
Layout.fillWidth: true
|
|
}
|
|
}
|
|
}
|
|
|
|
// setting the gradient mask source
|
|
source: rowContaner
|
|
|
|
// if the label is overflowing, this animation in a loop smoothly scrolling thought the text
|
|
SequentialAnimation {
|
|
id: textAnimationLoop
|
|
running: root.charactersOverflowing && root.visible
|
|
onRunningChanged: row.scrollPosition = 0
|
|
loops: Animation.Infinite
|
|
PauseAnimation { duration: root.waitDuration }
|
|
NumberAnimation { target: row; property: "scrollPosition"; from: 0; to: -txtMeter.advanceWidth - row.spacing; duration: (txtMeter.advanceWidth + row.spacing) / root.scrollSpeed }
|
|
}
|
|
|
|
// gradient mask to smoothly fade the ends of the label when it is scrolling
|
|
maskSource: Rectangle {
|
|
id: mask
|
|
width: root.width
|
|
height: root.height
|
|
|
|
property real gradientPct: (Kirigami.Units.gridUnit * 0.35) / root.width
|
|
|
|
gradient: Gradient {
|
|
orientation: Gradient.Horizontal
|
|
|
|
GradientStop { position: 0; color: row.scrollPosition == 0 || row.scrollPosition < -txtMeter.advanceWidth ? 'white' : 'transparent' } // remove the beginning of the gradient when at the start of the label so the front text is fully visible
|
|
GradientStop { position: 0 + mask.gradientPct; color: 'white' }
|
|
GradientStop { position: 1.0 - mask.gradientPct; color: 'white' }
|
|
GradientStop { position: 1.0; color: 'transparent' }
|
|
}
|
|
}
|
|
}
|
|
|