Skip to content

Commit 21c14ea

Browse files
committed
Merge branch 'main' into marquee
2 parents c4431cf + 7ae98c6 commit 21c14ea

File tree

5 files changed

+52
-21
lines changed

5 files changed

+52
-21
lines changed

labs/MarqueeText/samples/MarqueeText.Samples/MarqueeText.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ subcategory: StatusAndInfo
1212
# MarqueeText
1313

1414
For more information about this experiment see:
15+
1516
- Discussion: https://github.com/CommunityToolkit/Labs-Windows/discussions/231
17+
1618
- Issue: TODO: PASTE LINK HERE
1719

1820
The MarqueeText control allows text to scroll in a marquee fashion. The control is heavily templated and many changes can be made by modifying the style.

labs/MarqueeText/src/MarqueeBehavior.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ public enum MarqueeBehavior
2222
/// </remarks>
2323
Looping,
2424

25+
#if !HAS_UNO
2526
/// <summary>
2627
/// The text bounces back and forth across the screen.
2728
/// </summary>
2829
Bouncing,
30+
#endif
2931
}

labs/MarqueeText/src/MarqueeText.Events.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,24 @@ private void MarqueeText_Unloaded(object sender, RoutedEventArgs e)
3333
_marqueeContainer.SizeChanged -= Container_SizeChanged;
3434
}
3535

36-
if (this._marqueeStoryboard is not null)
36+
if (_marqueeStoryboard is not null)
3737
{
38-
this._marqueeStoryboard.Completed -= StoryBoard_Completed;
38+
_marqueeStoryboard.Completed -= StoryBoard_Completed;
3939
}
4040
}
4141

4242
private void Container_SizeChanged(object sender, SizeChangedEventArgs e)
4343
{
4444
if (_marqueeContainer is not null)
4545
{
46-
RectangleGeometry clip = new RectangleGeometry();
47-
clip.Rect = new Rect(0, 0, e.NewSize.Width, e.NewSize.Height);
48-
_marqueeContainer.Clip = clip;
46+
// Clip the marquee within its bounds
47+
_marqueeContainer.Clip = new RectangleGeometry
48+
{
49+
Rect = new Rect(0, 0, e.NewSize.Width, e.NewSize.Height)
50+
};
4951
}
5052

53+
// The marquee should run when the size changes in case the text gets cutoff
5154
StartMarquee();
5255
}
5356

labs/MarqueeText/src/MarqueeText.Properties.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,23 +69,27 @@ public MarqueeBehavior Behavior
6969

7070
private bool IsLooping => Behavior == MarqueeBehavior.Looping;
7171

72+
#if !HAS_UNO
7273
private bool IsBouncing => Behavior == MarqueeBehavior.Bouncing;
74+
#else
75+
private bool IsBouncing => false;
76+
#endif
7377

7478
/// <summary>
7579
/// Gets or sets a value indicating whether or not the marquee text wraps.
7680
/// </summary>
7781
/// <remarks>
78-
/// Wrappping text won't scroll if the text can already fit in the screen.
82+
/// Wrapping text won't scroll if the text can already fit in the screen.
7983
/// </remarks>
8084
public MarqueeDirection Direction
8185
{
8286
get => (MarqueeDirection)GetValue(DirectionProperty);
8387
set => SetValue(DirectionProperty, value);
8488
}
8589

86-
private bool IsDirectionHorizontal => Direction == MarqueeDirection.Left || Direction == MarqueeDirection.Right;
90+
private bool IsDirectionHorizontal => Direction is MarqueeDirection.Left or MarqueeDirection.Right;
8791

88-
private bool IsDirectionInverse => Direction == MarqueeDirection.Up || Direction == MarqueeDirection.Right;
92+
private bool IsDirectionInverse => Direction is MarqueeDirection.Up or MarqueeDirection.Right;
8993

9094
/// <summary>
9195
/// Gets or sets a value that indicates what decorations are applied to the text.
@@ -125,8 +129,8 @@ private static void DirectionPropertyChanged(DependencyObject d, DependencyPrope
125129
bool active = control._isActive;
126130
var oldDirection = (MarqueeDirection)e.OldValue;
127131
var newDirection = (MarqueeDirection)e.NewValue;
128-
bool oldAxisX = oldDirection == MarqueeDirection.Left || oldDirection == MarqueeDirection.Right;
129-
bool newAxisX = newDirection == MarqueeDirection.Left || newDirection == MarqueeDirection.Right;
132+
bool oldAxisX = oldDirection is MarqueeDirection.Left or MarqueeDirection.Right;
133+
bool newAxisX = newDirection is MarqueeDirection.Left or MarqueeDirection.Right;
130134

131135
VisualStateManager.GoToState(control, GetVisualStateName(newDirection), true);
132136

labs/MarqueeText/src/MarqueeText.cs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ private static string GetVisualStateName(MarqueeBehavior behavior)
9393
{
9494
MarqueeBehavior.Ticker => TickerVisualStateName,
9595
MarqueeBehavior.Looping => LoopingVisualStateName,
96+
#if !HAS_UNO
9697
MarqueeBehavior.Bouncing => BouncingVisualStateName,
98+
#endif
9799
_ => TickerVisualStateName,
98100
};
99101
}
@@ -134,6 +136,10 @@ private void StopMarquee(bool stopping)
134136
}
135137
}
136138

139+
/// <summary>
140+
/// Updates the animation to match the current control state.
141+
/// </summary>
142+
/// <param name="resume">True if animation should resume from its current position, false if it should restart.</param>
137143
/// <returns>True if the Animation is now playing</returns>
138144
private bool UpdateAnimation(bool resume = true)
139145
{
@@ -171,22 +177,30 @@ _segment1 is null ||
171177
{
172178
containerSize = _marqueeContainer.ActualHeight;
173179
segmentSize = _segment1.ActualHeight;
174-
value = this._marqueeTransform.Y;
180+
value = _marqueeTransform.Y;
175181
property = "(TranslateTransform.Y)";
176182
}
177183

178184
if (IsLooping && segmentSize < containerSize)
179185
{
186+
// If the text segment is smaller than the area provided,
187+
// it does not need to run in looping mode.
180188
StopMarquee(resume);
181189
_segment2.Visibility = Visibility.Collapsed;
182190
return false;
183191
}
184192

185-
double start = IsLooping || IsBouncing ? 0 : containerSize;
193+
// The start position is offset 100% if ticker
194+
// Otherwise it's 0
195+
double start = IsTicker ? containerSize : 0;
196+
// The end is when the end of the text reaches the border if bounding
197+
// Otherwise it is when the first set of text is 100% out of view
186198
double end = IsBouncing ? containerSize - segmentSize : -segmentSize;
199+
200+
// The distance is used for calculating the duration and the progress if resuming
187201
double distance = Math.Abs(start - end);
188202

189-
if (distance == 0)
203+
if (distance is 0)
190204
{
191205
return false;
192206
}
@@ -197,29 +211,34 @@ _segment1 is null ||
197211
(start, end) = (end, start);
198212
}
199213

214+
// The second segment of text should be hidden if the marquee is not in looping mode.
200215
_segment2.Visibility = IsLooping ? Visibility.Visible : Visibility.Collapsed;
201216

202217
TimeSpan duration = TimeSpan.FromSeconds(distance / Speed);
203218

204-
if (this._marqueeStoryboard is not null)
219+
if (_marqueeStoryboard is not null)
205220
{
206-
this._marqueeStoryboard.Completed -= StoryBoard_Completed;
221+
_marqueeStoryboard.Completed -= StoryBoard_Completed;
207222
}
208223

209-
this._marqueeStoryboard = new Storyboard()
224+
_marqueeStoryboard = new Storyboard()
210225
{
211226
Duration = duration,
212227
RepeatBehavior = RepeatBehavior,
228+
#if !HAS_UNO
213229
AutoReverse = IsBouncing,
230+
#endif
214231
};
215232

216-
this._marqueeStoryboard.Completed += StoryBoard_Completed;
233+
_marqueeStoryboard.Completed += StoryBoard_Completed;
217234

218235
var animation = new DoubleAnimationUsingKeyFrames
219236
{
220237
Duration = duration,
221238
RepeatBehavior = RepeatBehavior,
239+
#if !HAS_UNO
222240
AutoReverse = IsBouncing,
241+
#endif
223242
};
224243
var frame1 = new DiscreteDoubleKeyFrame
225244
{
@@ -234,17 +253,18 @@ _segment1 is null ||
234253

235254
animation.KeyFrames.Add(frame1);
236255
animation.KeyFrames.Add(frame2);
237-
this._marqueeStoryboard.Children.Add(animation);
238-
Storyboard.SetTarget(animation, this._marqueeTransform);
256+
_marqueeStoryboard.Children.Add(animation);
257+
Storyboard.SetTarget(animation, _marqueeTransform);
239258
Storyboard.SetTargetProperty(animation, property);
240259

241260
VisualStateManager.GoToState(this, MarqueeActiveState, true);
242-
this._marqueeStoryboard.Begin();
261+
_marqueeStoryboard.Begin();
243262

244263
if (resume)
245264
{
265+
// Seek the animation so the text is in the same position.
246266
double progress = Math.Abs(start - value) / distance;
247-
this._marqueeStoryboard.Seek(TimeSpan.FromTicks((long)(duration.Ticks * progress)));
267+
_marqueeStoryboard.Seek(TimeSpan.FromTicks((long)(duration.Ticks * progress)));
248268
}
249269

250270
return true;

0 commit comments

Comments
 (0)