Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Marquee Text Control #4523

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
181e461
Added basic MarqueeText control and style
Avid29 Mar 22, 2022
04b9bbe
Added MarqueeText control to sample app
Avid29 Mar 22, 2022
1f13cd0
Added basic Marquee scroll
Avid29 Mar 22, 2022
10b3139
Bound MarqueeStoryboard to VisualState
Avid29 Mar 22, 2022
e1a9921
Added MarqueeText.IsActive property binding to sample
Avid29 Mar 22, 2022
e74160a
Added resuming position to Marquee animation
Avid29 Mar 22, 2022
b4aefcc
Added MarqueeText.IsWrapping property to sample app
Avid29 Mar 22, 2022
d8ccff0
Implemented MarqueeText.IsWrapping property
Avid29 Mar 22, 2022
21153e4
Improved wrapping behavior for MarqueeText
Avid29 Mar 22, 2022
694c235
Handled SizeChanged for MarqueeText
Avid29 Mar 22, 2022
ac78482
Removed MarqueeText.IsActive as binding property
Avid29 Mar 22, 2022
71b8182
Added MarqueeBegan, MarqueeStopped, and MarqueeCompleted events
Avid29 Mar 22, 2022
2853760
Adjusted speed range in MarqueeText sample app demo
Avid29 Mar 22, 2022
51b5526
Removed Storyboard from VisualStates
Avid29 Mar 22, 2022
c256301
Added clipping to Canvas in MarqueeText
Avid29 Mar 23, 2022
734a97e
Verbose property handling for MarqueeText control
Avid29 Mar 23, 2022
86993ae
Added TextDecorations property to MarqueeText
Avid29 Mar 23, 2022
f9688a4
Added toolkit header to relevent files
Avid29 Mar 23, 2022
37a1227
Fixed Marquee clipping without CornerRadius
Avid29 Mar 23, 2022
723d707
Renamed CanvasPart, IsWrapping, and IsRepeating properties to Marquee…
Avid29 Mar 23, 2022
1d947be
Added Direction property to MarqueeText
Avid29 Mar 23, 2022
9d70abb
Added MarqueeDirection binding in sample app
Avid29 Mar 23, 2022
58439e1
Abstracted MarqueeDirection handling by axis and inversion
Avid29 Mar 23, 2022
18ca424
Added MarqueeBehavior as an enum
Avid29 Mar 24, 2022
09d0585
Added behavior VisualStates to MarqueeText
Avid29 Mar 24, 2022
87d4c94
Fixed MarqueeText VisualStates upon loading
Avid29 Mar 24, 2022
d199bce
Fixed typos in private fields
Avid29 Oct 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,10 @@
<Content Include="SamplePages\Graph\LoginButton.png" />
<Content Include="SamplePages\Graph\PeoplePicker.png" />
<Content Include="SamplePages\Graph\PersonView.png" />
<Content Include="SamplePages\RichSuggestBox\RichSuggestBox.png" />
<Content Include="SamplePages\Primitives\ConstrainedBox.png" />
<Content Include="SamplePages\Primitives\SwitchPresenter.png" />
<Content Include="SamplePages\RichSuggestBox\RichSuggestBox.png" />
<Content Include="SamplePages\MarqueeText\MarqueeText.png" />
<Content Include="SamplePages\TabbedCommandBar\TabbedCommandBar.png" />
<Content Include="SamplePages\Animations\Effects\FadeBehavior.png" />
<Content Include="SamplePages\ColorPicker\ColorPicker.png" />
Expand Down Expand Up @@ -647,6 +648,7 @@
<Content Include="SamplePages\Animations\Shadows\AnimatedCardShadowXaml.bind" />
<Content Include="SamplePages\KeyDownTriggerBehavior\KeyDownTriggerBehaviorXaml.bind" />
<Content Include="SamplePages\RichSuggestBox\RichSuggestBoxCode.bind" />
<Content Include="SamplePages\MarqueeText\MarqueeTextXaml.bind" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d">

<Grid>
<controls:MarqueeText Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
Speed="@[Speed:Slider:96:32-256]"
Behavior="@[Behavior:Enum:MarqueeBehavior.Ticker]"
Direction="@[Direction:Enum:MarqueeDirection.Left]"
RepeatBehavior="2x"
FontSize="18"/>
</Grid>
</Page>
9 changes: 9 additions & 0 deletions Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,15 @@
"XamlCodeFile": "RichSuggestBoxXaml.bind",
"Icon": "/SamplePages/RichSuggestBox/RichSuggestBox.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/RichSuggestBox.md"
},
{
"Name": "MarqueeText",
"Subcategory": "Status and Info",
"About": "A text control that shows a marquee scrolling across the screen.",
//"CodeUrl": ,
"XamlCodeFile": "MarqueeTextXaml.bind",
"Icon": "/SamplePages/MarqueeText/MarqueeText.png"
//"DocumentationUrl":
}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// How the Marquee moves.
/// </summary>
public enum MarqueeBehavior
{
/// <summary>
/// The text flows across the screen from start to finish.
/// </summary>
Ticker,

/// <summary>
/// As the text flows across the screen a duplicate follows.
/// </summary>
/// <remarks>
/// Looping text won't move if all the text already fits on the screen.
/// </remarks>
Looping,

/// <summary>
/// The text bounces back and forth across the screen.
/// </summary>
Bouncing,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// The direction a Marquee moves.
/// </summary>
public enum MarqueeDirection
{
/// <summary>
/// The text will flow from left to right.
/// </summary>
Left,

/// <summary>
/// The text will flow from right to left.
/// </summary>
Right,

/// <summary>
/// The text will flow from bottom to top.
/// </summary>
Up,

/// <summary>
/// The text will flow from top to bottom.
/// </summary>
Down,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;

namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// A Control that displays Text in a Marquee style.
/// </summary>
public partial class MarqueeText
{
/// <summary>
/// Event raised when the Marquee begins scrolling.
/// </summary>
public event EventHandler MarqueeBegan;

/// <summary>
/// Event raised when the Marquee stops scrolling for any reason.
/// </summary>
public event EventHandler MarqueeStopped;

/// <summary>
/// Event raised when the Marquee completes scrolling.
/// </summary>
public event EventHandler MarqueeCompleted;

private void MarqueeText_Unloaded(object sender, RoutedEventArgs e)
{
this.Unloaded -= MarqueeText_Unloaded;
_marqueeContainer.SizeChanged -= Container_SizeChanged;

if (_marqueeStoryboard != null)
{
_marqueeStoryboard.Completed -= StoryBoard_Completed;
}
}

private void Container_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (_marqueeContainer != null)
{
RectangleGeometry clip = new RectangleGeometry();
clip.Rect = new Rect(0, 0, e.NewSize.Width, e.NewSize.Height);
_marqueeContainer.Clip = clip;
}

StartMarquee();
}

private void StoryBoard_Completed(object sender, object e)
{
StopMarquee(true);
MarqueeCompleted?.Invoke(this, EventArgs.Empty);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Windows.UI.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media.Animation;

namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// A Control that displays Text in a Marquee style.
/// </summary>
public partial class MarqueeText
{
private static readonly DependencyProperty TextProperty =
DependencyProperty.Register(nameof(Text), typeof(string), typeof(MarqueeText), new PropertyMetadata(null, PropertyChanged));

private static readonly DependencyProperty SpeedProperty =
DependencyProperty.Register(nameof(Speed), typeof(double), typeof(MarqueeText), new PropertyMetadata(32d, PropertyChanged));

private static readonly DependencyProperty RepeatBehaviorProperty =
DependencyProperty.Register(nameof(RepeatBehavior), typeof(RepeatBehavior), typeof(MarqueeText), new PropertyMetadata(new RepeatBehavior(1), PropertyChanged));

private static readonly DependencyProperty BehaviorProperty =
DependencyProperty.Register(nameof(Behavior), typeof(MarqueeBehavior), typeof(MarqueeText), new PropertyMetadata(false, BehaviorPropertyChanged));

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

private static readonly DependencyProperty TextDecorationsProperty =
DependencyProperty.Register(nameof(TextDecorations), typeof(TextDecorations), typeof(MarqueeText), new PropertyMetadata(TextDecorations.None));

/// <summary>
/// Gets or sets the text being displayed in Marquee.
/// </summary>
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}

/// <summary>
/// Gets or sets the speed the text moves in the Marquee.
/// </summary>
public double Speed
{
get { return (double)GetValue(SpeedProperty); }
set { SetValue(SpeedProperty, value); }
}

/// <summary>
/// Gets or sets a value indicating whether or not the marquee scroll repeats.
/// </summary>
public RepeatBehavior RepeatBehavior
{
get { return (RepeatBehavior)GetValue(RepeatBehaviorProperty); }
set { SetValue(RepeatBehaviorProperty, value); }
}

/// <summary>
/// Gets or sets the marquee behavior.
/// </summary>
public MarqueeBehavior Behavior
{
get { return (MarqueeBehavior)GetValue(BehaviorProperty); }
set { SetValue(BehaviorProperty, value); }
}

private bool IsTicker => Behavior == MarqueeBehavior.Ticker;

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

private bool IsBouncing => Behavior == MarqueeBehavior.Bouncing;

/// <summary>
/// Gets or sets a value indicating whether or not the marquee text wraps.
/// </summary>
/// <remarks>
/// Wrappping text won't scroll if the text can already fit in the screen.
/// </remarks>
public MarqueeDirection Direction
{
get { return (MarqueeDirection)GetValue(DirectionProperty); }
set { SetValue(DirectionProperty, value); }
}

private bool IsDirectionHorizontal => Direction == MarqueeDirection.Left || Direction == MarqueeDirection.Right;

private bool IsDirectionInverse => Direction == MarqueeDirection.Up || Direction == MarqueeDirection.Right;

/// <summary>
/// Gets or sets a value that indicates what decorations are applied to the text.
/// </summary>
public TextDecorations TextDecorations
{
get { return (TextDecorations)GetValue(TextDecorationsProperty); }
set { SetValue(TextDecorationsProperty, value); }
}

private static void BehaviorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as MarqueeText;
bool active = control._isActive;
var newBehavior = (MarqueeBehavior)e.NewValue;

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

control.StopMarquee(false);
if (active)
{
control.StartMarquee();
}
}

private static void DirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as MarqueeText;
bool active = control._isActive;
var oldDirection = (MarqueeDirection)e.OldValue;
var newDirection = (MarqueeDirection)e.NewValue;
bool oldAxisX = oldDirection == MarqueeDirection.Left || oldDirection == MarqueeDirection.Right;
bool newAxisX = newDirection == MarqueeDirection.Left || newDirection == MarqueeDirection.Right;

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

if (oldAxisX != newAxisX)
{
control.StopMarquee(false);
}

if (active)
{
control.StartMarquee();
}
}

private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as MarqueeText;
control.UpdateAnimation(true);
}
}
}
Loading