From 3be5d4d810fcbaad83a727c47827b544264fd90e Mon Sep 17 00:00:00 2001 From: rabbitism Date: Mon, 18 Mar 2024 18:26:52 +0800 Subject: [PATCH] feat: introduce Mode and IsThreeState property to deal with system default theme. --- demo/Ursa.Demo/Pages/ThemeTogglerDemo.axaml | 2 + demo/Ursa.Demo/Views/MainView.axaml | 2 + .../Controls/ThemeSelector.axaml | 38 ++++---- .../Themes/Shared/ThemeSelector.axaml | 5 +- .../ThemeSelector/ThemeSelectorBase.cs | 36 ++++++-- .../ThemeSelector/ThemeSelectorMode.cs | 7 ++ .../ThemeSelector/ThemeToggleButton.cs | 89 ++++++++++++++----- 7 files changed, 129 insertions(+), 50 deletions(-) create mode 100644 src/Ursa/Controls/ThemeSelector/ThemeSelectorMode.cs diff --git a/demo/Ursa.Demo/Pages/ThemeTogglerDemo.axaml b/demo/Ursa.Demo/Pages/ThemeTogglerDemo.axaml index 021c289..a4aa5b7 100644 --- a/demo/Ursa.Demo/Pages/ThemeTogglerDemo.axaml +++ b/demo/Ursa.Demo/Pages/ThemeTogglerDemo.axaml @@ -10,6 +10,8 @@ + + diff --git a/demo/Ursa.Demo/Views/MainView.axaml b/demo/Ursa.Demo/Views/MainView.axaml index cf1e8eb..9e31e57 100644 --- a/demo/Ursa.Demo/Views/MainView.axaml +++ b/demo/Ursa.Demo/Views/MainView.axaml @@ -92,6 +92,8 @@ - - - - - - - - + + + + diff --git a/src/Ursa.Themes.Semi/Themes/Shared/ThemeSelector.axaml b/src/Ursa.Themes.Semi/Themes/Shared/ThemeSelector.axaml index 7ba95b8..d40b263 100644 --- a/src/Ursa.Themes.Semi/Themes/Shared/ThemeSelector.axaml +++ b/src/Ursa.Themes.Semi/Themes/Shared/ThemeSelector.axaml @@ -1,6 +1,7 @@  - M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM17 15C17.476 15 17.9408 14.9525 18.3901 14.862C17.296 17.3011 14.8464 19 12 19C8.13401 19 5 15.866 5 12C5 8.60996 7.40983 5.78277 10.6099 5.13803C10.218 6.01173 10 6.98041 10 8C10 11.866 13.134 15 17 15Z - M3.55 19.09L4.96 20.5L6.76 18.71L5.34 17.29M12 6C8.69 6 6 8.69 6 12S8.69 18 12 18 18 15.31 18 12C18 8.68 15.31 6 12 6M20 13H23V11H20M17.24 18.71L19.04 20.5L20.45 19.09L18.66 17.29M20.45 5L19.04 3.6L17.24 5.39L18.66 6.81M13 1H11V4H13M6.76 5.39L4.96 3.6L3.55 5L5.34 6.81L6.76 5.39M1 13H4V11H1M13 20H11V23H13 + M9,2C7.95,2 6.95,2.16 6,2.46C10.06,3.73 13,7.5 13,12C13,16.5 10.06,20.27 6,21.54C6.95,21.84 7.95,22 9,22A10,10 0 0,0 19,12A10,10 0 0,0 9,2Z + M12,8A4,4 0 0,0 8,12A4,4 0 0,0 12,16A4,4 0 0,0 16,12A4,4 0 0,0 12,8M12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31L23.31,12L20,8.69Z + M12,18V6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,15.31L23.31,12L20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31Z diff --git a/src/Ursa/Controls/ThemeSelector/ThemeSelectorBase.cs b/src/Ursa/Controls/ThemeSelector/ThemeSelectorBase.cs index affb2c4..343b7cc 100644 --- a/src/Ursa/Controls/ThemeSelector/ThemeSelectorBase.cs +++ b/src/Ursa/Controls/ThemeSelector/ThemeSelectorBase.cs @@ -23,6 +23,15 @@ public abstract class ThemeSelectorBase: TemplatedControl set => SetValue(SelectedThemeProperty, value); } + public static readonly StyledProperty ModeProperty = AvaloniaProperty.Register( + nameof(Mode)); + + public ThemeSelectorMode Mode + { + get => GetValue(ModeProperty); + set => SetValue(ModeProperty, value); + } + public static readonly StyledProperty TargetScopeProperty = AvaloniaProperty.Register( nameof(TargetScope)); @@ -57,15 +66,21 @@ public abstract class ThemeSelectorBase: TemplatedControl _syncFromScope = true; if (this.TargetScope is { } target) { - SyncThemeFromScope(target.ActualThemeVariant); + SyncThemeFromScope(Mode == ThemeSelectorMode.Controller + ? target.RequestedThemeVariant + : target.ActualThemeVariant); } else if (this._scope is { } scope) { - SyncThemeFromScope(scope.ActualThemeVariant); + SyncThemeFromScope(Mode == ThemeSelectorMode.Controller + ? scope.RequestedThemeVariant + : scope.ActualThemeVariant); } else if (_application is { } app) { - SyncThemeFromScope(app.ActualThemeVariant); + SyncThemeFromScope(Mode == ThemeSelectorMode.Controller + ? app.RequestedThemeVariant + : app.ActualThemeVariant); } _syncFromScope = false; } @@ -79,21 +94,29 @@ public abstract class ThemeSelectorBase: TemplatedControl { base.OnAttachedToVisualTree(e); _application = Application.Current; + _syncFromScope = true; if (_application is not null) { _application.ActualThemeVariantChanged += OnScopeThemeChanged; - SyncThemeFromScope(_application.ActualThemeVariant); + SyncThemeFromScope(Mode == ThemeSelectorMode.Controller + ? _application.RequestedThemeVariant + : _application.ActualThemeVariant); } _scope = this.GetLogicalAncestors().FirstOrDefault(a => a is ThemeVariantScope) as ThemeVariantScope; if (_scope is not null) { _scope.ActualThemeVariantChanged += OnScopeThemeChanged; - SyncThemeFromScope(_scope.ActualThemeVariant); + SyncThemeFromScope(Mode == ThemeSelectorMode.Controller + ? _scope.RequestedThemeVariant + : _scope.ActualThemeVariant); } if (TargetScope is not null) { - SyncThemeFromScope(TargetScope.ActualThemeVariant); + SyncThemeFromScope(Mode == ThemeSelectorMode.Controller + ? TargetScope.RequestedThemeVariant + : TargetScope.ActualThemeVariant); } + _syncFromScope = false; } protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) @@ -113,7 +136,6 @@ public abstract class ThemeSelectorBase: TemplatedControl { if (_syncFromScope) return; ThemeVariant? newTheme = args.NewValue.Value; - if (newTheme is null) return; if (TargetScope is not null) { TargetScope.RequestedThemeVariant = newTheme; diff --git a/src/Ursa/Controls/ThemeSelector/ThemeSelectorMode.cs b/src/Ursa/Controls/ThemeSelector/ThemeSelectorMode.cs new file mode 100644 index 0000000..6e3e870 --- /dev/null +++ b/src/Ursa/Controls/ThemeSelector/ThemeSelectorMode.cs @@ -0,0 +1,7 @@ +namespace Ursa.Controls; + +public enum ThemeSelectorMode +{ + Controller, + Indicator, +} \ No newline at end of file diff --git a/src/Ursa/Controls/ThemeSelector/ThemeToggleButton.cs b/src/Ursa/Controls/ThemeSelector/ThemeToggleButton.cs index 27503d3..0f7cfd6 100644 --- a/src/Ursa/Controls/ThemeSelector/ThemeToggleButton.cs +++ b/src/Ursa/Controls/ThemeSelector/ThemeToggleButton.cs @@ -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"; - - /// - /// This button IsChecked=true means ThemeVariant.Light, IsChecked=false means ThemeVariant.Dark. - /// - 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 IsThreeStateProperty = AvaloniaProperty.Register( + 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(PART_ThemeToggleButton); - Button.ClickEvent.AddHandler(OnButtonClickedChanged, _button); - ToggleButton.IsCheckedProperty.SetValue(_currentTheme == ThemeVariant.Light, _button); + Button.ClickEvent.RemoveHandler(OnButtonClicked, _button); + _button = e.NameScope.Get