From bc5e73d371b53d81f27f0827142cc8a8fe637df3 Mon Sep 17 00:00:00 2001 From: Deterous <138427222+Deterous@users.noreply.github.com> Date: Wed, 26 Jun 2024 05:27:38 +0900 Subject: [PATCH] Custom theme colors (#712) * Custom theme colors * Use Convert.ToByte --- CHANGELIST.md | 1 + MPF.Frontend/Options.cs | 18 +++++++ MPF.UI/Themes/CustomTheme.cs | 88 +++++++++++++++++++++++++++++++ MPF.UI/Themes/PurpModeTheme.cs | 66 ----------------------- MPF.UI/Windows/MainWindow.xaml.cs | 55 ++++++++++++++++++- 5 files changed, 160 insertions(+), 68 deletions(-) create mode 100644 MPF.UI/Themes/CustomTheme.cs delete mode 100644 MPF.UI/Themes/PurpModeTheme.cs diff --git a/CHANGELIST.md b/CHANGELIST.md index dfd905b0..bba492fc 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -26,6 +26,7 @@ - Blindly assume the path exists - Add CLI status output on runtime - Ensure tracks are assigned in Aaru +- Custom theme colors ### 3.2.0 (2024-06-20) diff --git a/MPF.Frontend/Options.cs b/MPF.Frontend/Options.cs index f550f4a9..d85d8cc6 100644 --- a/MPF.Frontend/Options.cs +++ b/MPF.Frontend/Options.cs @@ -92,6 +92,24 @@ namespace MPF.Frontend set { Settings["EnablePurpMode"] = value.ToString(); } } + /// + /// Custom color setting + /// + public string? CustomBackgroundColor + { + get { return GetStringSetting(Settings, "CustomBackgroundColor", null); } + set { Settings["CustomBackgroundColor"] = value; } + } + + /// + /// Custom color setting + /// + public string? CustomTextColor + { + get { return GetStringSetting(Settings, "CustomTextColor", null); } + set { Settings["CustomTextColor"] = value; } + } + /// /// Check for updates on startup /// diff --git a/MPF.UI/Themes/CustomTheme.cs b/MPF.UI/Themes/CustomTheme.cs new file mode 100644 index 00000000..d565cf27 --- /dev/null +++ b/MPF.UI/Themes/CustomTheme.cs @@ -0,0 +1,88 @@ +using System; +using System.Windows.Media; + +namespace MPF.UI.Themes +{ + /// + /// Custom colour theme + /// + public sealed class CustomTheme : Theme + { + public CustomTheme(string? backgroundColor, string? foregroundColor) + { + // Convert hex colors to byte values + byte backgroundR; + byte backgroundG; + byte backgroundB; + byte foregroundR; + byte foregroundG; + byte foregroundB; + try + { + backgroundR = Convert.ToByte(backgroundColor!.Substring(0, 2), 16); + backgroundG = Convert.ToByte(backgroundColor!.Substring(2, 2), 16); + backgroundB = Convert.ToByte(backgroundColor!.Substring(4, 2), 16); + foregroundR = Convert.ToByte(foregroundColor!.Substring(0, 2), 16); + foregroundG = Convert.ToByte(foregroundColor!.Substring(2, 2), 16); + foregroundB = Convert.ToByte(foregroundColor!.Substring(4, 2), 16); + } + catch + { + return; + } + + // Setup needed brushes + var backgroundBrush = new SolidColorBrush { Color = Color.FromArgb(0xff, backgroundR, backgroundG, backgroundB) }; + var foregroundBrush = new SolidColorBrush { Color = Color.FromArgb(0xff, foregroundR, foregroundG, foregroundB) }; + + // Handle application-wide resources + this.ActiveBorderBrush = foregroundBrush; + this.ControlBrush = backgroundBrush; + this.ControlTextBrush = foregroundBrush; + this.GrayTextBrush = foregroundBrush; + this.WindowBrush = backgroundBrush; + this.WindowTextBrush = foregroundBrush; + + // Handle Button-specific resources + this.Button_Disabled_Background = backgroundBrush; + this.Button_MouseOver_Background = backgroundBrush; + this.Button_Pressed_Background = backgroundBrush; + this.Button_Static_Background = backgroundBrush; + + // Handle ComboBox-specific resources + this.ComboBox_Disabled_Background = backgroundBrush; + this.ComboBox_Disabled_Editable_Background = backgroundBrush; + this.ComboBox_Disabled_Editable_Button_Background = backgroundBrush; + this.ComboBox_MouseOver_Background = backgroundBrush; + this.ComboBox_MouseOver_Editable_Background = backgroundBrush; + this.ComboBox_MouseOver_Editable_Button_Background = backgroundBrush; + this.ComboBox_Pressed_Background = backgroundBrush; + this.ComboBox_Pressed_Editable_Background = backgroundBrush; + this.ComboBox_Pressed_Editable_Button_Background = backgroundBrush; + this.ComboBox_Static_Background = backgroundBrush; + this.ComboBox_Static_Editable_Background = backgroundBrush; + this.ComboBox_Static_Editable_Button_Background = backgroundBrush; + + // Handle CustomMessageBox-specific resources + this.CustomMessageBox_Static_Background = backgroundBrush; + + // Handle MenuItem-specific resources + this.MenuItem_SubMenu_Background = backgroundBrush; + this.MenuItem_SubMenu_Border = Brushes.DarkGray; + + // Handle ProgressBar-specific resources + this.ProgressBar_Background = backgroundBrush; + + // Handle ScrollViewer-specific resources + this.ScrollViewer_ScrollBar_Background = backgroundBrush; + + // Handle TabItem-specific resources + this.TabItem_Selected_Background = backgroundBrush; + this.TabItem_Static_Background = backgroundBrush; + this.TabItem_Static_Border = Brushes.DarkGray; + + // Handle TextBox-specific resources + this.TextBox_Static_Background = backgroundBrush; + } + } +} diff --git a/MPF.UI/Themes/PurpModeTheme.cs b/MPF.UI/Themes/PurpModeTheme.cs deleted file mode 100644 index fe838799..00000000 --- a/MPF.UI/Themes/PurpModeTheme.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System.Windows.Media; - -namespace MPF.UI.Themes -{ - /// - /// Default purple-mode theme - /// - public sealed class PurpModeTheme : Theme - { - public PurpModeTheme() - { - // Setup needed brushes - var darkPurpBrush = new SolidColorBrush { Color = Color.FromArgb(0xff, 0x11, 0x11, 0x11) }; - var lightPurpBrush = new SolidColorBrush { Color = Color.FromArgb(0xff, 0x9a, 0x5e, 0xc0) }; - - // Handle application-wide resources - this.ActiveBorderBrush = lightPurpBrush; - this.ControlBrush = darkPurpBrush; - this.ControlTextBrush = lightPurpBrush; - this.GrayTextBrush = lightPurpBrush; - this.WindowBrush = darkPurpBrush; - this.WindowTextBrush = lightPurpBrush; - - // Handle Button-specific resources - this.Button_Disabled_Background = darkPurpBrush; - this.Button_MouseOver_Background = darkPurpBrush; - this.Button_Pressed_Background = darkPurpBrush; - this.Button_Static_Background = darkPurpBrush; - - // Handle ComboBox-specific resources - this.ComboBox_Disabled_Background = darkPurpBrush; - this.ComboBox_Disabled_Editable_Background = darkPurpBrush; - this.ComboBox_Disabled_Editable_Button_Background = darkPurpBrush; - this.ComboBox_MouseOver_Background = darkPurpBrush; - this.ComboBox_MouseOver_Editable_Background = darkPurpBrush; - this.ComboBox_MouseOver_Editable_Button_Background = darkPurpBrush; - this.ComboBox_Pressed_Background = darkPurpBrush; - this.ComboBox_Pressed_Editable_Background = darkPurpBrush; - this.ComboBox_Pressed_Editable_Button_Background = darkPurpBrush; - this.ComboBox_Static_Background = darkPurpBrush; - this.ComboBox_Static_Editable_Background = darkPurpBrush; - this.ComboBox_Static_Editable_Button_Background = darkPurpBrush; - - // Handle CustomMessageBox-specific resources - this.CustomMessageBox_Static_Background = darkPurpBrush; - - // Handle MenuItem-specific resources - this.MenuItem_SubMenu_Background = darkPurpBrush; - this.MenuItem_SubMenu_Border = Brushes.DarkGray; - - // Handle ProgressBar-specific resources - this.ProgressBar_Background = darkPurpBrush; - - // Handle ScrollViewer-specific resources - this.ScrollViewer_ScrollBar_Background = darkPurpBrush; - - // Handle TabItem-specific resources - this.TabItem_Selected_Background = darkPurpBrush; - this.TabItem_Static_Background = darkPurpBrush; - this.TabItem_Static_Border = Brushes.DarkGray; - - // Handle TextBox-specific resources - this.TextBox_Static_Background = darkPurpBrush; - } - } -} diff --git a/MPF.UI/Windows/MainWindow.xaml.cs b/MPF.UI/Windows/MainWindow.xaml.cs index 2300d123..e5cefeef 100644 --- a/MPF.UI/Windows/MainWindow.xaml.cs +++ b/MPF.UI/Windows/MainWindow.xaml.cs @@ -399,14 +399,65 @@ namespace MPF.UI.Windows if (MainViewModel.Options.EnableDarkMode) theme = new DarkModeTheme(); else if (MainViewModel.Options.EnablePurpMode) - theme = new PurpModeTheme(); + theme = new CustomTheme("111111", "9A5EC0"); + else if (IsHexColor(MainViewModel.Options.CustomBackgroundColor) && IsHexColor(MainViewModel.Options.CustomTextColor)) + theme = new CustomTheme(MainViewModel.Options.CustomBackgroundColor, MainViewModel.Options.CustomTextColor); else theme = new LightModeTheme(); theme.Apply(); } -#endregion + /// + /// Check whether a string represents a valid hex color + /// + public static bool IsHexColor(string? color) + { + if (string.IsNullOrWhiteSpace(color)) + return false; + + if (color!.Length == 7 && color[0] == '#') + color = color.Substring(1); + + if (color.Length != 6) + return false; + + for (int i = 0; i < color.Length; i++) + { + switch (color[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + continue; + default: + break; + } + } + + return true; + } + + #endregion #region Event Handlers