Skip to content

Commit 0d8b18f

Browse files
committed
Added pausing to Marquee and improved state transition logic
1 parent 5539a1e commit 0d8b18f

File tree

4 files changed

+226
-83
lines changed

4 files changed

+226
-83
lines changed

components/Marquee/src/Marquee.Events.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,26 @@ public partial class Marquee
1212
/// <summary>
1313
/// Event raised when the Marquee begins scrolling.
1414
/// </summary>
15-
public event EventHandler? MarqueeBegan;
15+
/// <remarks>
16+
/// Could be started. Could be resumed.
17+
/// </remarks>
18+
public event EventHandler? MarqueeStarted;
1619

1720
/// <summary>
18-
/// Event raised when the Marquee stops scrolling for any reason.
21+
/// Event raised when the Marquee is stopped manually or completed.
1922
/// </summary>
2023
public event EventHandler? MarqueeStopped;
2124

25+
/// <summary>
26+
/// Event raised when the Marquee is resumed from a pause.
27+
/// </summary>
28+
public event EventHandler? MarqueeResumed;
29+
30+
/// <summary>
31+
/// Event raised when the Marquee is paused.
32+
/// </summary>
33+
public event EventHandler? MarqueePaused;
34+
2235
/// <summary>
2336
/// Event raised when the Marquee completes scrolling.
2437
/// </summary>
@@ -72,8 +85,15 @@ private void Container_SizeChanged(object sender, SizeChangedEventArgs e)
7285
Rect = new Rect(0, 0, e.NewSize.Width, e.NewSize.Height)
7386
};
7487

88+
// Update animation on the fly
89+
UpdateMarquee(true);
90+
7591
// The marquee should run when the size changes in case the text gets cutoff
76-
StartMarquee();
92+
// and auto play is enabled.
93+
if (AutoPlay)
94+
{
95+
StartMarquee();
96+
}
7797
}
7898

7999
private void Segment_SizeChanged(object sender, SizeChangedEventArgs e)
@@ -85,12 +105,12 @@ private void Segment_SizeChanged(object sender, SizeChangedEventArgs e)
85105

86106
// If the segment size changes, we need to update the storyboard,
87107
// and seek to the correct position to maintain a smooth animation.
88-
UpdateAnimation(true);
108+
UpdateMarquee(true);
89109
}
90110

91111
private void StoryBoard_Completed(object? sender, object e)
92112
{
93-
StopMarquee(true);
113+
StopMarquee();
94114
MarqueeCompleted?.Invoke(this, EventArgs.Empty);
95115
}
96116
}

components/Marquee/src/Marquee.Properties.cs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,30 @@ namespace CommunityToolkit.WinUI.Controls;
1111
/// </summary>
1212
public partial class Marquee
1313
{
14+
private static readonly DependencyProperty AutoPlayProperty =
15+
DependencyProperty.Register(nameof(AutoPlay), typeof(bool), typeof(Marquee), new PropertyMetadata(false));
16+
1417
private static readonly DependencyProperty SpeedProperty =
1518
DependencyProperty.Register(nameof(Speed), typeof(double), typeof(Marquee), new PropertyMetadata(32d, PropertyChanged));
1619

1720
private static readonly DependencyProperty RepeatBehaviorProperty =
1821
DependencyProperty.Register(nameof(RepeatBehavior), typeof(RepeatBehavior), typeof(Marquee), new PropertyMetadata(new RepeatBehavior(1), PropertyChanged));
1922

2023
private static readonly DependencyProperty BehaviorProperty =
21-
DependencyProperty.Register(nameof(Behavior), typeof(MarqueeBehavior), typeof(Marquee), new PropertyMetadata(0, BehaviorPropertyChanged));
24+
DependencyProperty.Register(nameof(Behavior), typeof(MarqueeBehavior), typeof(Marquee), new PropertyMetadata(MarqueeBehavior.Ticker, BehaviorPropertyChanged));
2225

2326
private static readonly DependencyProperty DirectionProperty =
2427
DependencyProperty.Register(nameof(Direction), typeof(MarqueeDirection), typeof(Marquee), new PropertyMetadata(MarqueeDirection.Left, DirectionPropertyChanged));
2528

29+
/// <summary>
30+
/// Gets or sets whether or not the Marquee plays immediately upon loading or updating a property.
31+
/// </summary>
32+
public bool AutoPlay
33+
{
34+
get => (bool)GetValue(AutoPlayProperty);
35+
set => SetValue(AutoPlayProperty, value);
36+
}
37+
2638
/// <summary>
2739
/// Gets or sets the speed the text moves in the Marquee.
2840
/// </summary>
@@ -79,17 +91,16 @@ public MarqueeDirection Direction
7991
private static void BehaviorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
8092
{
8193
if (d is not Marquee control)
82-
{
8394
return;
84-
}
8595

86-
bool active = control._isActive;
8796
var newBehavior = (MarqueeBehavior)e.NewValue;
8897

8998
VisualStateManager.GoToState(control, GetVisualStateName(newBehavior), true);
9099

91-
control.StopMarquee(false);
92-
if (active)
100+
// It is always impossible to perform an on the fly behavior change.
101+
control.UpdateMarquee(false);
102+
103+
if (control.AutoPlay)
93104
{
94105
control.StartMarquee();
95106
}
@@ -98,24 +109,20 @@ private static void BehaviorPropertyChanged(DependencyObject d, DependencyProper
98109
private static void DirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
99110
{
100111
if (d is not Marquee control)
101-
{
102112
return;
103-
}
104113

105-
bool active = control._isActive;
106114
var oldDirection = (MarqueeDirection)e.OldValue;
107115
var newDirection = (MarqueeDirection)e.NewValue;
108116
bool oldAxisX = oldDirection is MarqueeDirection.Left or MarqueeDirection.Right;
109117
bool newAxisX = newDirection is MarqueeDirection.Left or MarqueeDirection.Right;
110118

111119
VisualStateManager.GoToState(control, GetVisualStateName(newDirection), true);
112120

113-
if (oldAxisX != newAxisX)
114-
{
115-
control.StopMarquee(false);
116-
}
121+
// If the axis changed we cannot update the animation on the fly.
122+
// Otherwise, the animation can be updated and resumed seamlessly
123+
control.UpdateMarquee(oldAxisX == newAxisX);
117124

118-
if (active)
125+
if (control.AutoPlay)
119126
{
120127
control.StartMarquee();
121128
}
@@ -124,10 +131,15 @@ private static void DirectionPropertyChanged(DependencyObject d, DependencyPrope
124131
private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
125132
{
126133
if (d is not Marquee control)
127-
{
128134
return;
129-
}
130135

131-
control.UpdateAnimation();
136+
// It is always possible to update these properties on the fly.
137+
// NOTE: The RepeatBehavior will reset its count though. Can this be fixed?
138+
control.UpdateMarquee(true);
139+
140+
if (control.AutoPlay)
141+
{
142+
control.StartMarquee();
143+
}
132144
}
133145
}

0 commit comments

Comments
 (0)