feat: Theme toggler
This commit is contained in:
65
src/Ursa/Controls/ThemeSelector/ThemeSelectorBase.cs
Normal file
65
src/Ursa/Controls/ThemeSelector/ThemeSelectorBase.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public abstract class ThemeSelectorBase: TemplatedControl
|
||||
{
|
||||
private Application? _application;
|
||||
private ThemeVariantScope? _scope;
|
||||
|
||||
public static readonly StyledProperty<ThemeVariant?> SelectedThemeProperty = AvaloniaProperty.Register<ThemeSelectorBase, ThemeVariant?>(
|
||||
nameof(SelectedTheme));
|
||||
|
||||
public ThemeVariant? SelectedTheme
|
||||
{
|
||||
get => GetValue(SelectedThemeProperty);
|
||||
set => SetValue(SelectedThemeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<ThemeVariantScope?> TargetScopeProperty =
|
||||
AvaloniaProperty.Register<ThemeSelectorBase, ThemeVariantScope?>(
|
||||
nameof(TargetScope));
|
||||
|
||||
public ThemeVariantScope? TargetScope
|
||||
{
|
||||
get => GetValue(TargetScopeProperty);
|
||||
set => SetValue(TargetScopeProperty, value);
|
||||
}
|
||||
|
||||
static ThemeSelectorBase()
|
||||
{
|
||||
SelectedThemeProperty.Changed.AddClassHandler<ThemeSelectorBase, ThemeVariant?>((s, e) => s.OnSelectedThemeChanged(e));
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
_application = Application.Current;
|
||||
_scope = this.GetLogicalAncestors().FirstOrDefault(a => a is ThemeVariantScope) as ThemeVariantScope;
|
||||
}
|
||||
|
||||
protected virtual void OnSelectedThemeChanged(AvaloniaPropertyChangedEventArgs<ThemeVariant?> args)
|
||||
{
|
||||
ThemeVariant? newTheme = args.NewValue.Value;
|
||||
if (newTheme is null) return;
|
||||
if (TargetScope is not null)
|
||||
{
|
||||
TargetScope.RequestedThemeVariant = newTheme;
|
||||
return;
|
||||
}
|
||||
if (_scope is not null)
|
||||
{
|
||||
_scope.RequestedThemeVariant = newTheme;
|
||||
return;
|
||||
}
|
||||
if (_application is not null)
|
||||
{
|
||||
_application.RequestedThemeVariant = newTheme;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/Ursa/Controls/ThemeSelector/ThemeToggleButton.cs
Normal file
45
src/Ursa/Controls/ThemeSelector/ThemeToggleButton.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Styling;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[TemplatePart(PART_ThemeToggleButton, typeof(ToggleButton))]
|
||||
public class ThemeToggleButton: ThemeSelectorBase
|
||||
{
|
||||
public const string PART_ThemeToggleButton = "PART_ThemeToggleButton";
|
||||
|
||||
/// <summary>
|
||||
/// This button IsChecked=true means ThemeVariant.Light, IsChecked=false means ThemeVariant.Dark.
|
||||
/// </summary>
|
||||
private ToggleButton? _button;
|
||||
private ThemeVariant? _currentTheme;
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
_currentTheme = this.ActualThemeVariant;
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
EventHelper.UnregisterEvent(ToggleButton.IsCheckedChangedEvent, OnButtonCheckedChanged, _button);
|
||||
_button = e.NameScope.Get<ToggleButton>(PART_ThemeToggleButton);
|
||||
EventHelper.RegisterEvent(ToggleButton.IsCheckedChangedEvent, OnButtonCheckedChanged, _button);
|
||||
PropertyHelper.SetValue(ToggleButton.IsCheckedProperty, _currentTheme == ThemeVariant.Light, _button);
|
||||
}
|
||||
|
||||
private void OnButtonCheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var newTheme = (sender as ToggleButton)!.IsChecked;
|
||||
if (newTheme is null) return;
|
||||
SelectedTheme = newTheme.Value ? ThemeVariant.Light : ThemeVariant.Dark;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user