Skip to content

Commit

Permalink
Added the TyperLabel control
Browse files Browse the repository at this point in the history
  • Loading branch information
jonteohr committed Apr 22, 2024
1 parent 95e661a commit 5300e78
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 86 deletions.
42 changes: 22 additions & 20 deletions ExampleApp/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
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="clr-namespace:GradientTheme.Controls;assembly=GradientTheme"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MyApp" Height="450" Width="800"
MouseDown="MainWindow_OnMouseDown"
Expand Down Expand Up @@ -47,31 +49,31 @@
</Grid>
<!-- .Toolbar Grid -->

<!-- ContentGrid -->
<!-- Title header -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="70*" />
<ColumnDefinition Width="20*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="10*" />
<RowDefinition Height="60*" />
<RowDefinition Height="30*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Title header -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="70*" />
<ColumnDefinition Width="20*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Label Grid.Column="1" Content="{Binding Path=WindowTitle}" Name="TitleLabel" Style="{DynamicResource TitleStyle}" />
<Label Grid.Row="1" Grid.Column="1" Content="A nice subdescription" Style="{DynamicResource SubheaderStyle}" />
</Grid>

<controls:TyperLabel Grid.Row="0" Grid.Column="1" Style="{DynamicResource TitleStyle}" >
<!-- Important that we supply at least one title, if not we will crash! -->
<controls:TyperLabel.Titles>
<x:Array Type="{x:Type sys:String}">
<sys:String>One Title</sys:String>
<sys:String>Another Title</sys:String>
<sys:String>Great Title</sys:String>
</x:Array>
</controls:TyperLabel.Titles>
</controls:TyperLabel>

<Label Grid.Row="1" Grid.Column="1" Content="A nice subdescription" Style="{DynamicResource SubheaderStyle}" />
</Grid>

</Grid>
</DockPanel>
</Border>
Expand Down
67 changes: 1 addition & 66 deletions ExampleApp/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,65 +21,11 @@ public partial class MainWindow : Window
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

private int m_typeSpeed = 150;
private int m_timerspeed = 3;
private bool m_typing;

public string WindowTitle { get; private set; }
private string[] Titles =
[
"A nice app",
"App title",
"Cool title",
"Useful stuff!",
"This title changes",
"Captivating title",
"Lorem ipsum"
];

public MainWindow()
{
WindowTitle = GetRandomTitle();

InitializeComponent();
DataContext = this;

var timer = new Timer();
timer.Interval = m_timerspeed * 1000;
timer.AutoReset = true;
timer.Elapsed += TimerOnElapsed;
timer.Enabled = true;
timer.Start();
}

private void TimerOnElapsed(object? sender, ElapsedEventArgs e)
{
while (!m_typing)
{
m_typing = true;
for (var i = WindowTitle.Length - 1; i < WindowTitle.Length; i--)
{
if (i < 0)
break;

WindowTitle = WindowTitle.Remove(i);
SafeThreadInvoker(() => TitleLabel.Content = WindowTitle);
Thread.Sleep(m_typeSpeed);
}

WindowTitle = GetRandomTitle();

for (var i = 0; i <= WindowTitle.Length; i++)
{
var tmp = WindowTitle.Substring(0, i);
SafeThreadInvoker(() => TitleLabel.Content = tmp);
Thread.Sleep(m_typeSpeed);
}

break;
}

m_typing = false;
DataContext = this;
}

private void CloseBtn_OnClick(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -108,15 +54,4 @@ private void SafeThreadInvoker(Action a)
else
a();
}

private string GetRandomTitle()
{
var rand = new Random();

var generated = Titles[rand.Next(0, Titles.Length)];
while (generated == WindowTitle)
generated = Titles[rand.Next(0, Titles.Length)];

return generated;
}
}
94 changes: 94 additions & 0 deletions GradientTheme/Controls/TyperLabel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System.Timers;
using Timer = System.Timers.Timer;
using System.Windows.Controls;
using System.Windows.Data;

namespace GradientTheme.Controls;

public class TyperLabel : Label
{
private const int TypeSpeed = 150;
private const int TimerSpeed = 3;
private bool m_typing;
private string WindowTitle { get; set; }
private string m_lastTitle;

private string[] m_titles;
public string[] Titles
{
get => m_titles;
set
{
m_titles = value;
Content = WindowTitle = GetRandomTitle();
}
}

public TyperLabel()
{
var binding = new Binding("WindowTitle");
BindingOperations.SetBinding(this, TyperLabel.ContentProperty, binding);

var timer = new Timer();
timer.Interval = TimerSpeed * 1000;
timer.AutoReset = true;
timer.Elapsed += TimerOnElapsed;
timer.Enabled = true;
timer.Start();
}

private void TimerOnElapsed(object? sender, ElapsedEventArgs e)
{
while (!m_typing)
{
m_typing = true;

m_lastTitle = WindowTitle;

for (var i = WindowTitle.Length - 1; i < WindowTitle.Length; i--)
{
if (i < 0)
break;

WindowTitle = WindowTitle.Remove(i);
SafeThreadInvoker(() => Content = WindowTitle);
Thread.Sleep(TypeSpeed);
}

WindowTitle = GetRandomTitle();

for (var i = 0; i <= WindowTitle.Length; i++)
{
var tmp = WindowTitle.Substring(0, i);
SafeThreadInvoker(() => Content = tmp);
Thread.Sleep(TypeSpeed);
}

break;
}

m_typing = false;
}

private void SafeThreadInvoker(Action a)
{
if (!CheckAccess())
Dispatcher.Invoke(a);
else
a();
}

private string GetRandomTitle()
{
var rand = new Random();

string generated;
do
{
generated = Titles[rand.Next(0, Titles.Length)];
}
while (generated == m_lastTitle);

return generated;
}
}

0 comments on commit 5300e78

Please sign in to comment.