// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Linq; using System.Windows; using ManagedCommon; using Microsoft.Win32; namespace Wox.Plugin { public class ThemeManager : IDisposable { private readonly Application _app; private const string LightTheme = "Light.Accent1"; private const string DarkTheme = "Dark.Accent1"; private const string HighContrastOneTheme = "HighContrast.Accent2"; private const string HighContrastTwoTheme = "HighContrast.Accent3"; private const string HighContrastBlackTheme = "HighContrast.Accent4"; private const string HighContrastWhiteTheme = "HighContrast.Accent5"; private Theme currentTheme; private bool _disposed; public event ThemeChangedHandler ThemeChanged; public ThemeManager(Application app) { _app = app; Uri highContrastOneThemeUri = new Uri("pack://application:,,,/Themes/HighContrast1.xaml"); Uri highContrastTwoThemeUri = new Uri("pack://application:,,,/Themes/HighContrast2.xaml"); Uri highContrastBlackThemeUri = new Uri("pack://application:,,,/Themes/HighContrastWhite.xaml"); Uri highContrastWhiteThemeUri = new Uri("pack://application:,,,/Themes/HighContrastBlack.xaml"); Uri lightThemeUri = new Uri("pack://application:,,,/Themes/Light.xaml"); Uri darkThemeUri = new Uri("pack://application:,,,/Themes/Dark.xaml"); ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( new ControlzEx.Theming.LibraryTheme( highContrastOneThemeUri, CustomLibraryThemeProvider.DefaultInstance)); ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( new ControlzEx.Theming.LibraryTheme( highContrastTwoThemeUri, CustomLibraryThemeProvider.DefaultInstance)); ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( new ControlzEx.Theming.LibraryTheme( highContrastBlackThemeUri, CustomLibraryThemeProvider.DefaultInstance)); ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( new ControlzEx.Theming.LibraryTheme( highContrastWhiteThemeUri, CustomLibraryThemeProvider.DefaultInstance)); ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( new ControlzEx.Theming.LibraryTheme( lightThemeUri, CustomLibraryThemeProvider.DefaultInstance)); ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( new ControlzEx.Theming.LibraryTheme( darkThemeUri, CustomLibraryThemeProvider.DefaultInstance)); ControlzEx.Theming.ThemeManager.Current.ThemeChanged += Current_ThemeChanged; // Currently there is an issue in ControlzEx, so we must use SyncAll to sync also HighContrast themes. // We can change this after using next release. ControlzEx.Theming.ThemeManager.Current.ThemeSyncMode = ControlzEx.Theming.ThemeSyncMode.SyncAll; ControlzEx.Theming.ThemeManager.Current.SyncTheme(); } public Theme GetCurrentTheme() { return currentTheme; } private static Theme GetHighContrastBaseType() { string registryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes"; string theme = (string)Registry.GetValue(registryKey, "CurrentTheme", string.Empty); theme = theme.Split('\\').Last().Split('.').First().ToString(); switch (theme) { case "hc1": return Theme.HighContrastOne; case "hc2": return Theme.HighContrastTwo; case "hcwhite": return Theme.HighContrastWhite; case "hcblack": return Theme.HighContrastBlack; default: return Theme.HighContrastOne; } } private void ResetTheme() { ChangeTheme(currentTheme, false); } public void ChangeTheme(Theme theme, bool forceSystem) { Theme oldTheme = currentTheme; if (theme == Theme.System) { currentTheme = Theme.System; if (ControlzEx.Theming.WindowsThemeHelper.IsHighContrastEnabled()) { Theme highContrastBaseType = GetHighContrastBaseType(); ChangeTheme(highContrastBaseType, true); } else { string baseColor = ControlzEx.Theming.WindowsThemeHelper.GetWindowsBaseColor(); ChangeTheme((Theme)Enum.Parse(typeof(Theme), baseColor), true); } } else if (theme == Theme.HighContrastOne) { currentTheme = Theme.HighContrastOne; ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastOneTheme, true); } else if (theme == Theme.HighContrastTwo) { currentTheme = Theme.HighContrastTwo; ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastTwoTheme, true); } else if (theme == Theme.HighContrastWhite) { currentTheme = Theme.HighContrastWhite; ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastWhiteTheme, true); } else if (theme == Theme.HighContrastBlack) { currentTheme = Theme.HighContrastBlack; ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastBlackTheme, true); } else if (theme == Theme.Light) { currentTheme = Theme.Light; ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, LightTheme); } else if (theme == Theme.Dark) { currentTheme = Theme.Dark; ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, DarkTheme); } ThemeChanged?.Invoke(oldTheme, currentTheme); if (forceSystem) { currentTheme = Theme.System; } } private void Current_ThemeChanged(object sender, ControlzEx.Theming.ThemeChangedEventArgs e) { ControlzEx.Theming.ThemeManager.Current.ThemeChanged -= Current_ThemeChanged; try { ResetTheme(); } finally { ControlzEx.Theming.ThemeManager.Current.ThemeChanged += Current_ThemeChanged; } } protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { ControlzEx.Theming.ThemeManager.Current.ThemeChanged -= Current_ThemeChanged; _disposed = true; } } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } public delegate void ThemeChangedHandler(Theme oldTheme, Theme newTheme); }