mirror of
https://github.com/Orbmu2k/nvidiaProfileInspector.git
synced 2026-04-29 10:35:43 -04:00
refactored thememanager
This commit is contained in:
@@ -30,6 +30,8 @@ namespace nvidiaProfileInspector.Common.Helper
|
||||
|
||||
public List<uint> FavoriteSettingIds { get; set; } = new List<uint>();
|
||||
|
||||
public string Theme { get; set; } = "DarkTheme.xaml";
|
||||
|
||||
private static string GetSettingsFilename()
|
||||
{
|
||||
var fiPortalbleSettings = new FileInfo("settings.xml");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
@@ -6,143 +7,49 @@ using nvidiaProfileInspector.Common.Helper;
|
||||
|
||||
namespace nvidiaProfileInspector.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages application themes including loading, saving, and switching themes.
|
||||
/// </summary>
|
||||
public class ThemeManager
|
||||
{
|
||||
private const string DarkTheme = "DarkTheme.xaml";
|
||||
private const string LightTheme = "LightTheme.xaml";
|
||||
private const string SlateLightTheme = "SlateLightTheme.xaml";
|
||||
|
||||
private static readonly string[] ValidThemes = { DarkTheme, LightTheme, SlateLightTheme };
|
||||
private static readonly string[] ValidThemes = {
|
||||
DarkTheme,
|
||||
SlateLightTheme
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current theme name.
|
||||
/// </summary>
|
||||
public string CurrentTheme { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ThemeManager class.
|
||||
/// </summary>
|
||||
public ThemeManager()
|
||||
{
|
||||
LoadSavedTheme();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the saved theme from user settings or defaults to DarkTheme.
|
||||
/// </summary>
|
||||
public void LoadSavedTheme()
|
||||
{
|
||||
try
|
||||
{
|
||||
var settings = UserSettings.LoadSettings();
|
||||
var themeName = settings.Theme ?? DarkTheme;
|
||||
|
||||
// Ensure themeName has .xaml extension
|
||||
if (!themeName.EndsWith(".xaml"))
|
||||
themeName = DarkTheme;
|
||||
|
||||
// Validate theme
|
||||
if (!ValidThemes.Contains(themeName))
|
||||
themeName = DarkTheme;
|
||||
|
||||
CurrentTheme = themeName;
|
||||
ApplyTheme(themeName);
|
||||
ApplyAndPersistTheme(NormalizeThemeName(settings.Theme), savePreference: false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Default to dark theme on error
|
||||
CurrentTheme = DarkTheme;
|
||||
ApplyTheme(DarkTheme);
|
||||
ApplyAndPersistTheme(DarkTheme, savePreference: false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles to the next theme in the sequence: Dark -> Light -> SlateLight -> Dark.
|
||||
/// </summary>
|
||||
public void ToggleTheme()
|
||||
{
|
||||
try
|
||||
{
|
||||
var app = Application.Current;
|
||||
if (app == null) return;
|
||||
|
||||
var mergedDicts = app.Resources.MergedDictionaries;
|
||||
var existingTheme = mergedDicts.FirstOrDefault(d =>
|
||||
d.Source != null && (d.Source.OriginalString.Contains(DarkTheme) ||
|
||||
d.Source.OriginalString.Contains(LightTheme) ||
|
||||
d.Source.OriginalString.Contains(SlateLightTheme)));
|
||||
|
||||
string newSource;
|
||||
if (existingTheme != null)
|
||||
{
|
||||
if (existingTheme.Source.OriginalString.Contains(DarkTheme))
|
||||
newSource = LightTheme;
|
||||
else if (existingTheme.Source.OriginalString.Contains(LightTheme))
|
||||
newSource = SlateLightTheme;
|
||||
else if (existingTheme.Source.OriginalString.Contains(SlateLightTheme))
|
||||
newSource = DarkTheme;
|
||||
else
|
||||
newSource = DarkTheme; // fallback
|
||||
|
||||
// Update the theme dictionary
|
||||
mergedDicts.Remove(existingTheme);
|
||||
mergedDicts.Add(new ResourceDictionary { Source = new Uri($"/UI/Themes/{newSource}", UriKind.Relative) });
|
||||
}
|
||||
else
|
||||
{
|
||||
// No theme found, apply dark theme
|
||||
newSource = DarkTheme;
|
||||
ApplyTheme(newSource);
|
||||
}
|
||||
|
||||
// Save the new theme preference
|
||||
CurrentTheme = newSource;
|
||||
SaveThemePreference(newSource);
|
||||
var currentTheme = GetCurrentAppliedThemeName();
|
||||
ApplyAndPersistTheme(GetNextThemeName(currentTheme), savePreference: true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log error but don't crash
|
||||
System.Diagnostics.Debug.WriteLine($"Error toggling theme: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the specified theme to the application resources.
|
||||
/// </summary>
|
||||
/// <param name="themeName">The name of the theme to apply.</param>
|
||||
private void ApplyTheme(string themeName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var app = Application.Current;
|
||||
if (app == null) return;
|
||||
|
||||
var mergedDicts = app.Resources.MergedDictionaries;
|
||||
var themeDict = mergedDicts.FirstOrDefault(d =>
|
||||
d.Source != null && (d.Source.OriginalString.Contains("DarkTheme.xaml") ||
|
||||
d.Source.OriginalString.Contains("LightTheme.xaml") ||
|
||||
d.Source.OriginalString.Contains("SlateLightTheme.xaml")));
|
||||
|
||||
if (themeDict != null)
|
||||
{
|
||||
string newSource = $"/UI/Themes/{themeName}";
|
||||
mergedDicts.Remove(themeDict);
|
||||
mergedDicts.Add(new ResourceDictionary { Source = new Uri(newSource, UriKind.Relative) });
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Error applying theme: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the theme preference to user settings.
|
||||
/// </summary>
|
||||
/// <param name="themeName">The name of the theme to save.</param>
|
||||
private void SaveThemePreference(string themeName)
|
||||
{
|
||||
try
|
||||
@@ -156,5 +63,97 @@ namespace nvidiaProfileInspector.Services
|
||||
System.Diagnostics.Debug.WriteLine($"Error saving theme preference: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static ResourceDictionary GetThemeDictionary(IList<ResourceDictionary> mergedDicts)
|
||||
{
|
||||
return mergedDicts.FirstOrDefault(d => GetThemeName(d.Source) != null);
|
||||
}
|
||||
|
||||
private static string GetCurrentAppliedThemeName()
|
||||
{
|
||||
var app = Application.Current;
|
||||
if (app == null)
|
||||
return null;
|
||||
|
||||
return GetThemeName(GetThemeDictionary(app.Resources.MergedDictionaries)?.Source);
|
||||
}
|
||||
|
||||
private static string GetThemeName(Uri source)
|
||||
{
|
||||
if (source == null)
|
||||
return null;
|
||||
|
||||
var themeName = Path.GetFileName(source.OriginalString);
|
||||
return ValidThemes.FirstOrDefault(validTheme =>
|
||||
string.Equals(validTheme, themeName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private static string NormalizeThemeName(string themeName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(themeName))
|
||||
return DarkTheme;
|
||||
|
||||
if (!themeName.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase))
|
||||
return DarkTheme;
|
||||
|
||||
return ValidThemes.FirstOrDefault(validTheme =>
|
||||
string.Equals(validTheme, themeName, StringComparison.OrdinalIgnoreCase))
|
||||
?? DarkTheme;
|
||||
}
|
||||
|
||||
private static string GetNextThemeName(string currentTheme)
|
||||
{
|
||||
if (ValidThemes.Length == 0)
|
||||
return DarkTheme;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(currentTheme))
|
||||
return ValidThemes[0];
|
||||
|
||||
var currentThemeIndex = Array.FindIndex(
|
||||
ValidThemes,
|
||||
theme => string.Equals(theme, currentTheme, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (currentThemeIndex < 0)
|
||||
return ValidThemes[0];
|
||||
|
||||
var nextThemeIndex = (currentThemeIndex + 1) % ValidThemes.Length;
|
||||
return ValidThemes[nextThemeIndex];
|
||||
}
|
||||
|
||||
private void ApplyAndPersistTheme(string themeName, bool savePreference)
|
||||
{
|
||||
var app = Application.Current;
|
||||
if (app == null)
|
||||
return;
|
||||
|
||||
var normalizedThemeName = NormalizeThemeName(themeName);
|
||||
var mergedDicts = app.Resources.MergedDictionaries;
|
||||
var themeDict = GetThemeDictionary(mergedDicts);
|
||||
|
||||
ReplaceThemeDictionary(mergedDicts, themeDict, normalizedThemeName);
|
||||
|
||||
CurrentTheme = normalizedThemeName;
|
||||
|
||||
if (savePreference)
|
||||
SaveThemePreference(normalizedThemeName);
|
||||
}
|
||||
|
||||
private static void ReplaceThemeDictionary(IList<ResourceDictionary> mergedDicts, ResourceDictionary existingTheme, string themeName)
|
||||
{
|
||||
var newThemeDictionary = new ResourceDictionary
|
||||
{
|
||||
Source = new Uri($"/UI/Themes/{themeName}", UriKind.Relative)
|
||||
};
|
||||
|
||||
if (existingTheme == null)
|
||||
{
|
||||
mergedDicts.Add(newThemeDictionary);
|
||||
return;
|
||||
}
|
||||
|
||||
var index = mergedDicts.IndexOf(existingTheme);
|
||||
mergedDicts.RemoveAt(index);
|
||||
mergedDicts.Insert(index, newThemeDictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource ApplicationRemoveBrush}" />
|
||||
<Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource ErrorBrush}" />
|
||||
<Setter TargetName="Text" Property="Foreground" Value="White" />
|
||||
<Setter TargetName="Text" Property="Foreground" Value="{DynamicResource ApplicationRemoveForegroundBrush}" />
|
||||
<Setter TargetName="Icon" Property="Data" Value="{StaticResource IconDelete}" />
|
||||
<Setter TargetName="Icon" Property="Fill" Value="White" />
|
||||
<Setter TargetName="Icon" Property="Fill" Value="{DynamicResource ApplicationRemoveForegroundBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter Property="Opacity" Value="0.7" />
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
<SolidColorBrush x:Key="ScrollBarThumbPressedBrush" Color="#80FFFFFF" />
|
||||
|
||||
<SolidColorBrush x:Key="ApplicationRemoveBrush" Color="#3D2B2B" />
|
||||
<SolidColorBrush x:Key="ApplicationRemoveForegroundBrush" Color="#FFFFFF" />
|
||||
<SolidColorBrush x:Key="ApplicationAddBrush" Color="#154CC331" />
|
||||
<SolidColorBrush x:Key="ApplicationAddHoverBrush" Color="#254CC331" />
|
||||
<SolidColorBrush x:Key="ListViewAlternatingRowBrush" Color="#252525" />
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<SolidColorBrush x:Key="QuestionBrush" Color="{StaticResource QuestionColor}" />
|
||||
<SolidColorBrush x:Key="LabBrush" Color="{StaticResource LabColor}" />
|
||||
|
||||
<!-- Overlay / Transparency Brushes -->
|
||||
<!-- Overlay / Transparency Brushes -->
|
||||
<SolidColorBrush x:Key="HighlightOverlayBrush" Color="#08000000" />
|
||||
<SolidColorBrush x:Key="HoverOverlayBrush" Color="#0D000000" />
|
||||
<SolidColorBrush x:Key="PressedOverlayBrush" Color="#1A000000" />
|
||||
@@ -66,7 +66,7 @@
|
||||
<SolidColorBrush x:Key="ScrollBarThumbPressedBrush" Color="#50000000" />
|
||||
|
||||
<SolidColorBrush x:Key="ApplicationRemoveBrush" Color="#FFEBEB" />
|
||||
<SolidColorBrush x:Key="ApplicationAddBrush" Color="#E8F8E8" />
|
||||
<SolidColorBrush x:Key="ApplicationRemoveForegroundBrush" Color="#1A1A1A" />
|
||||
<SolidColorBrush x:Key="ApplicationAddHoverBrush" Color="#D1F1D1" />
|
||||
<SolidColorBrush x:Key="ListViewAlternatingRowBrush" Color="#08000000" />
|
||||
<SolidColorBrush x:Key="ModifiedSettingBackgroundBrush" Color="#15000000" />
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<Color x:Key="Layer3BackgroundColor">#E8EAED</Color>
|
||||
|
||||
<!-- NVIDIA Green Brand Colors -->
|
||||
<Color x:Key="NvidiaGreenColor">#76B900</Color>
|
||||
<Color x:Key="NvidiaGreenColor">#66A900</Color>
|
||||
<Color x:Key="NvidiaGreenHoverColor">#8AD400</Color>
|
||||
<Color x:Key="NvidiaGreenPressedColor">#659F00</Color>
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
|
||||
<!-- Special Purpose Brushes -->
|
||||
<SolidColorBrush x:Key="ApplicationRemoveBrush" Color="#FEF2F2" />
|
||||
<SolidColorBrush x:Key="ApplicationRemoveForegroundBrush" Color="#1A1D21" />
|
||||
<SolidColorBrush x:Key="ApplicationAddBrush" Color="#ECFDF5" />
|
||||
<SolidColorBrush x:Key="ApplicationAddHoverBrush" Color="#D1FAE5" />
|
||||
<SolidColorBrush x:Key="ListViewAlternatingRowBrush" Color="#F9FAFB" />
|
||||
|
||||
@@ -956,6 +956,7 @@ using System.Windows.Input;
|
||||
{
|
||||
var themeManager = App.Bootstrapper.Resolve<ThemeManager>();
|
||||
themeManager.ToggleTheme();
|
||||
RefreshCurrentProfile();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user