feat: introduce Mode and IsThreeState property to deal with system default theme.

This commit is contained in:
rabbitism
2024-03-18 18:26:52 +08:00
parent af13b9a539
commit 3be5d4d810
7 changed files with 129 additions and 50 deletions

View File

@@ -9,42 +9,87 @@ using Ursa.Common;
namespace Ursa.Controls;
[TemplatePart(PART_ThemeToggleButton, typeof(ToggleButton))]
[TemplatePart(PART_ThemeButton, typeof(Button))]
[PseudoClasses(PC_Dark, PC_Light, PC_Default)]
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;
public const string PART_ThemeButton = "PART_ThemeButton";
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
_currentTheme = this.ActualThemeVariant;
}
public const string PC_Light = ":light";
public const string PC_Dark = ":dark";
public const string PC_Default = ":default";
private Button? _button;
private bool? _state;
public static readonly StyledProperty<bool> IsThreeStateProperty = AvaloniaProperty.Register<ThemeToggleButton, bool>(
nameof(IsThreeState));
public bool IsThreeState
{
get => GetValue(IsThreeStateProperty);
set => SetValue(IsThreeStateProperty, value);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
Button.ClickEvent.RemoveHandler(OnButtonClickedChanged, _button);
_button = e.NameScope.Get<ToggleButton>(PART_ThemeToggleButton);
Button.ClickEvent.AddHandler(OnButtonClickedChanged, _button);
ToggleButton.IsCheckedProperty.SetValue(_currentTheme == ThemeVariant.Light, _button);
Button.ClickEvent.RemoveHandler(OnButtonClicked, _button);
_button = e.NameScope.Get<Button>(PART_ThemeButton);
Button.ClickEvent.AddHandler(OnButtonClicked, _button);
// ToggleButton.IsCheckedProperty.SetValue(_currentTheme == ThemeVariant.Light, _button);
}
private void OnButtonClickedChanged(object sender, RoutedEventArgs e)
private void OnButtonClicked(object sender, RoutedEventArgs e)
{
var newTheme = (sender as ToggleButton)!.IsChecked;
if (newTheme is null) return;
SetCurrentValue(SelectedThemeProperty, newTheme.Value ? ThemeVariant.Light : ThemeVariant.Dark);
bool? currentState = _state;
if (IsThreeState)
{
_state = currentState switch
{
true => false,
false => null,
null => true,
};
}
else
{
_state = currentState switch
{
true => false,
false => true,
null => true,
};
}
if (_state == true)
{
SelectedTheme = ThemeVariant.Light;
}
else if (_state == false)
{
SelectedTheme = ThemeVariant.Dark;
}
else
{
SelectedTheme = ThemeVariant.Default;
}
if (Mode == ThemeSelectorMode.Controller)
{
PseudoClasses.Set(PC_Light, SelectedTheme == ThemeVariant.Light);
PseudoClasses.Set(PC_Dark, SelectedTheme == ThemeVariant.Dark);
PseudoClasses.Set(PC_Default, SelectedTheme == null || SelectedTheme == ThemeVariant.Default);
}
}
protected override void SyncThemeFromScope(ThemeVariant? theme)
{
base.SyncThemeFromScope(theme);
ToggleButton.IsCheckedProperty.SetValue(theme == ThemeVariant.Light, _button);
if (Mode == ThemeSelectorMode.Indicator)
{
PseudoClasses.Set(PC_Light, theme == ThemeVariant.Light);
PseudoClasses.Set(PC_Dark, theme == ThemeVariant.Dark);
PseudoClasses.Set(PC_Default, theme == null || SelectedTheme == ThemeVariant.Default);
}
}
}