greeter test
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
import QtQuick
|
||||
import qs.Config
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property alias anim: marqueeAnim
|
||||
property bool animate: false
|
||||
property color color: DynamicColors.palette.m3onSurface
|
||||
property int fadeStrengthAnimMs: 180
|
||||
property real fadeStrengthIdle: 0.0
|
||||
property real fadeStrengthMoving: 1.0
|
||||
property alias font: elideText.font
|
||||
property int gap: 40
|
||||
property alias horizontalAlignment: elideText.horizontalAlignment
|
||||
property bool leftFadeEnabled: false
|
||||
property real leftFadeStrength: overflowing && leftFadeEnabled ? fadeStrengthMoving : fadeStrengthIdle
|
||||
property int leftFadeWidth: 28
|
||||
property bool marqueeEnabled: true
|
||||
readonly property bool overflowing: metrics.width > root.width
|
||||
property int pauseMs: 1200
|
||||
property real pixelsPerSecond: 40
|
||||
property real rightFadeStrength: overflowing ? fadeStrengthMoving : fadeStrengthIdle
|
||||
property int rightFadeWidth: 28
|
||||
property bool sliding: false
|
||||
property alias text: elideText.text
|
||||
|
||||
function durationForDistance(px): int {
|
||||
return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000));
|
||||
}
|
||||
|
||||
function resetMarquee() {
|
||||
marqueeAnim.stop();
|
||||
strip.x = 0;
|
||||
root.sliding = false;
|
||||
root.leftFadeEnabled = false;
|
||||
|
||||
if (root.marqueeEnabled && root.overflowing && root.visible) {
|
||||
marqueeAnim.restart();
|
||||
}
|
||||
}
|
||||
|
||||
clip: true
|
||||
implicitHeight: elideText.implicitHeight
|
||||
|
||||
Behavior on leftFadeStrength {
|
||||
Anim {
|
||||
}
|
||||
}
|
||||
Behavior on rightFadeStrength {
|
||||
Anim {
|
||||
}
|
||||
}
|
||||
|
||||
onTextChanged: resetMarquee()
|
||||
onVisibleChanged: if (!visible)
|
||||
resetMarquee()
|
||||
onWidthChanged: resetMarquee()
|
||||
|
||||
TextMetrics {
|
||||
id: metrics
|
||||
|
||||
font: elideText.font
|
||||
text: elideText.text
|
||||
}
|
||||
|
||||
CustomText {
|
||||
id: elideText
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
animate: root.animate
|
||||
animateProp: "scale,opacity"
|
||||
color: root.color
|
||||
elide: Text.ElideNone
|
||||
visible: !root.overflowing
|
||||
width: root.width
|
||||
}
|
||||
|
||||
Item {
|
||||
id: marqueeViewport
|
||||
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
layer.enabled: true
|
||||
visible: root.overflowing
|
||||
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: rightFadeMask
|
||||
}
|
||||
|
||||
Item {
|
||||
id: strip
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: t1.implicitHeight
|
||||
width: t1.width + root.gap + t2.width
|
||||
x: 0
|
||||
|
||||
CustomText {
|
||||
id: t1
|
||||
|
||||
animate: root.animate
|
||||
animateProp: "opacity"
|
||||
color: root.color
|
||||
text: elideText.text
|
||||
}
|
||||
|
||||
CustomText {
|
||||
id: t2
|
||||
|
||||
animate: root.animate
|
||||
animateProp: "opacity"
|
||||
color: root.color
|
||||
text: t1.text
|
||||
x: t1.width + root.gap
|
||||
}
|
||||
}
|
||||
|
||||
SequentialAnimation {
|
||||
id: marqueeAnim
|
||||
|
||||
running: false
|
||||
|
||||
onFinished: pauseTimer.restart()
|
||||
|
||||
ScriptAction {
|
||||
script: {
|
||||
root.sliding = true;
|
||||
root.leftFadeEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
Anim {
|
||||
duration: root.durationForDistance(t1.width)
|
||||
easing.bezierCurve: Easing.Linear
|
||||
easing.type: Easing.Linear
|
||||
from: 0
|
||||
property: "x"
|
||||
target: strip
|
||||
to: -t1.width
|
||||
}
|
||||
|
||||
ScriptAction {
|
||||
script: {
|
||||
root.leftFadeEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
Anim {
|
||||
duration: root.durationForDistance(root.gap)
|
||||
easing.bezierCurve: Easing.Linear
|
||||
easing.type: Easing.Linear
|
||||
from: -t1.width
|
||||
property: "x"
|
||||
target: strip
|
||||
to: -(t1.width + root.gap)
|
||||
}
|
||||
|
||||
ScriptAction {
|
||||
script: {
|
||||
root.sliding = false;
|
||||
strip.x = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: pauseTimer
|
||||
|
||||
interval: root.pauseMs
|
||||
repeat: false
|
||||
running: true
|
||||
|
||||
onTriggered: {
|
||||
if (root.marqueeEnabled)
|
||||
marqueeAnim.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rightFadeMask
|
||||
|
||||
readonly property real fadeStartPos: {
|
||||
const w = Math.max(1, width);
|
||||
return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w));
|
||||
}
|
||||
readonly property real leftFadeEndPos: {
|
||||
const w = Math.max(1, width);
|
||||
return Math.max(0, Math.min(1, root.leftFadeWidth / w));
|
||||
}
|
||||
|
||||
anchors.fill: marqueeViewport
|
||||
layer.enabled: true
|
||||
visible: false
|
||||
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
|
||||
GradientStop {
|
||||
color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength)
|
||||
position: 0.0
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
color: Qt.rgba(1, 1, 1, 1.0)
|
||||
position: rightFadeMask.leftFadeEndPos
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
color: Qt.rgba(1, 1, 1, 1.0)
|
||||
position: rightFadeMask.fadeStartPos
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength)
|
||||
position: 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user