diff --git a/demo/Semi.Avalonia.Demo/App.axaml.cs b/demo/Semi.Avalonia.Demo/App.axaml.cs index 1dccc74..305563c 100644 --- a/demo/Semi.Avalonia.Demo/App.axaml.cs +++ b/demo/Semi.Avalonia.Demo/App.axaml.cs @@ -1,10 +1,7 @@ -using System.Runtime.InteropServices; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Data.Core.Plugins; using Avalonia.Markup.Xaml; -using Avalonia.Media; -using Avalonia.Platform; using Semi.Avalonia.Demo.Views; namespace Semi.Avalonia.Demo; @@ -31,30 +28,7 @@ public partial class App : Application break; } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - var setting = PlatformSettings?.GetColorValues(); - if (setting?.ContrastPreference is ColorContrastPreference.High) - { - if (setting.AccentColor1 == Color.Parse("#8EE3F0")) - { - RequestedThemeVariant = SemiTheme.Aquatic; - } - else if (setting.AccentColor1 == Color.Parse("#903909")) - { - RequestedThemeVariant = SemiTheme.Desert; - } - else if (setting.AccentColor1 == Color.Parse("#A1BFDE")) - { - RequestedThemeVariant = SemiTheme.Dusk; - } - else if (setting.AccentColor1 == Color.Parse("#D6B4FD")) - { - RequestedThemeVariant = SemiTheme.NightSky; - } - } - } - + this.RegisterFollowSystemTheme(); base.OnFrameworkInitializationCompleted(); } } \ No newline at end of file diff --git a/demo/Semi.Avalonia.Demo/Views/MainView.axaml.cs b/demo/Semi.Avalonia.Demo/Views/MainView.axaml.cs index 6407176..307554b 100644 --- a/demo/Semi.Avalonia.Demo/Views/MainView.axaml.cs +++ b/demo/Semi.Avalonia.Demo/Views/MainView.axaml.cs @@ -33,9 +33,14 @@ public partial class MainViewModel : ObservableObject [ new MenuItemViewModel { - Header = "High Contrast Theme", + Header = "Theme", Items = [ + new MenuItemViewModel + { + Header = "Auto", + Command = FollowSystemThemeCommand + }, new MenuItemViewModel { Header = "Aquatic", @@ -62,10 +67,10 @@ public partial class MainViewModel : ObservableObject }, ] }, - new MenuItemViewModel() + new MenuItemViewModel { Header = "Locale", - Items= + Items = [ new MenuItemViewModel { @@ -114,6 +119,12 @@ public partial class MainViewModel : ObservableObject ]; } + [RelayCommand] + private void FollowSystemTheme() + { + Application.Current?.RegisterFollowSystemTheme(); + } + [RelayCommand] private void ToggleTheme() { @@ -121,26 +132,24 @@ public partial class MainViewModel : ObservableObject if (app is null) return; var theme = app.ActualThemeVariant; app.RequestedThemeVariant = theme == ThemeVariant.Dark ? ThemeVariant.Light : ThemeVariant.Dark; + app.UnregisterFollowSystemTheme(); } [RelayCommand] private void SelectTheme(object? obj) { var app = Application.Current; - if (app is not null) - { - app.RequestedThemeVariant = obj as ThemeVariant; - } + if (app is null) return; + app.RequestedThemeVariant = obj as ThemeVariant; + app.UnregisterFollowSystemTheme(); } - + [RelayCommand] private void SelectLocale(object? obj) { var app = Application.Current; - if (app is not null) - { - SemiTheme.OverrideLocaleResources(app, obj as System.Globalization.CultureInfo); - } + if (app is null) return; + SemiTheme.OverrideLocaleResources(app, obj as CultureInfo); } [RelayCommand] diff --git a/src/Semi.Avalonia/Extensions/ApplicationExtension.cs b/src/Semi.Avalonia/Extensions/ApplicationExtension.cs new file mode 100644 index 0000000..760b1da --- /dev/null +++ b/src/Semi.Avalonia/Extensions/ApplicationExtension.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Avalonia; +using Avalonia.Media; +using Avalonia.Platform; +using Avalonia.Styling; + +namespace Semi.Avalonia; + +public static class ApplicationExtension +{ + private static Application _app = null!; + + private static readonly Dictionary ColorThemeMap = new() + { + [Color.Parse("#8EE3F0")] = SemiTheme.Aquatic, + [Color.Parse("#903909")] = SemiTheme.Desert, + [Color.Parse("#A1BFDE")] = SemiTheme.Dusk, + [Color.Parse("#D6B4FD")] = SemiTheme.NightSky + }; + + public static void RegisterFollowSystemTheme(this Application app) + { + _app = app; + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return; + if (app.PlatformSettings is null) return; + app.PlatformSettings.ColorValuesChanged -= OnColorValuesChanged; + app.PlatformSettings.ColorValuesChanged += OnColorValuesChanged; + OnColorValuesChanged(null, app.PlatformSettings?.GetColorValues()); + } + + public static void UnregisterFollowSystemTheme(this Application app) + { + _app = app; + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return; + if (app.PlatformSettings is null) return; + app.PlatformSettings.ColorValuesChanged -= OnColorValuesChanged; + } + + private static void OnColorValuesChanged(object? _, PlatformColorValues? args) + { + ThemeVariant result; + if (args?.ContrastPreference is ColorContrastPreference.High) + { + result = ColorThemeMap.TryGetValue(args.AccentColor1, out var theme) ? theme : ThemeVariant.Default; + } + else + { + result = args?.ThemeVariant switch + { + PlatformThemeVariant.Light => ThemeVariant.Light, + PlatformThemeVariant.Dark => ThemeVariant.Dark, + _ => ThemeVariant.Default + }; + } + + _app.RequestedThemeVariant = result; + } +} \ No newline at end of file