mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2025-06-28 09:04:47 -05:00
Add the option to change the UI Theme at runtime (#2693)
* Setup for testing * Working Example for Background * Almost all MainBackgrounColor working * Random Color PoC * Fix DBorderColor * prevent old logic from replacing colors in memory at startup * Comment out resources in xaml * Finish new Button * Remove Pulse, Load Windows default Theme * Fix Colors * Fix Toggle Colors * working version, with shared still being mostly applied be replace instead of resouces * Load all entries in themes.json as Resource and reference them in inputXML.xaml * Rename File to match Function Name * Hotfix for Sync with main * Remove Static Set-WinUtilUITheme function/file * Rename File and Function * Cleanup and Stuff * Unify Button Theme with rest of UI * Refactor/Optimazation * Performance optimization * Add Comments * Rename Functions and Variables to be more concise and descriptive * Add persistence to the user Theme Preference across winutil restarts * Reimplement Theme Chagnes from #2722 * Add AUTO option to follow window theme and add dropdown instead toggle * Formatting and deleting temp file * Fix small display bug where Dropdown would remain open for settings and themes * Remove terniary operators because only PS7+ is supported
This commit is contained in:
180
functions/private/Invoke-WinutilThemeChange.ps1
Normal file
180
functions/private/Invoke-WinutilThemeChange.ps1
Normal file
@ -0,0 +1,180 @@
|
||||
function Invoke-WinutilThemeChange {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Toggles between light and dark themes for a Windows utility application.
|
||||
|
||||
.DESCRIPTION
|
||||
This function toggles the theme of the user interface between 'Light' and 'Dark' modes,
|
||||
modifying various UI elements such as colors, margins, corner radii, font families, etc.
|
||||
If the '-init' switch is used, it initializes the theme based on the system's current dark mode setting.
|
||||
|
||||
.PARAMETER init
|
||||
A switch parameter. If set to $true, the function initializes the theme based on the system’s current dark mode setting.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-WinutilThemeChange
|
||||
# Toggles the theme between 'Light' and 'Dark'.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-WinutilThemeChange -init
|
||||
# Initializes the theme based on the system's dark mode and applies the shared theme.
|
||||
#>
|
||||
param (
|
||||
[switch]$init = $false,
|
||||
[string]$theme
|
||||
)
|
||||
|
||||
function Set-WinutilTheme {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Applies the specified theme to the application's user interface.
|
||||
|
||||
.DESCRIPTION
|
||||
This internal function applies the given theme by setting the relevant properties
|
||||
like colors, font families, corner radii, etc., in the UI. It uses the
|
||||
'Set-ThemeResourceProperty' helper function to modify the application's resources.
|
||||
|
||||
.PARAMETER currentTheme
|
||||
The name of the theme to be applied. Common values are "Light", "Dark", or "shared".
|
||||
#>
|
||||
param (
|
||||
[string]$currentTheme
|
||||
)
|
||||
|
||||
function Set-ThemeResourceProperty {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sets a specific UI property in the application's resources.
|
||||
|
||||
.DESCRIPTION
|
||||
This helper function sets a property (e.g., color, margin, corner radius) in the
|
||||
application's resources, based on the provided type and value. It includes
|
||||
error handling to manage potential issues while setting a property.
|
||||
|
||||
.PARAMETER Name
|
||||
The name of the resource property to modify (e.g., "MainBackgroundColor", "ButtonBackgroundMouseoverColor").
|
||||
|
||||
.PARAMETER Value
|
||||
The value to assign to the resource property (e.g., "#FFFFFF" for a color).
|
||||
|
||||
.PARAMETER Type
|
||||
The type of the resource, such as "ColorBrush", "CornerRadius", "GridLength", or "FontFamily".
|
||||
#>
|
||||
param($Name, $Value, $Type)
|
||||
try {
|
||||
# Set the resource property based on its type
|
||||
$sync.Form.Resources[$Name] = switch ($Type) {
|
||||
"ColorBrush" { [Windows.Media.SolidColorBrush]::new($Value) }
|
||||
"Color" {
|
||||
# Convert hex string to RGB values
|
||||
$hexColor = $Value.TrimStart("#")
|
||||
$r = [Convert]::ToInt32($hexColor.Substring(0,2), 16)
|
||||
$g = [Convert]::ToInt32($hexColor.Substring(2,2), 16)
|
||||
$b = [Convert]::ToInt32($hexColor.Substring(4,2), 16)
|
||||
[Windows.Media.Color]::FromRgb($r, $g, $b)
|
||||
}
|
||||
"CornerRadius" { [System.Windows.CornerRadius]::new($Value) }
|
||||
"GridLength" { [System.Windows.GridLength]::new($Value) }
|
||||
"Thickness" {
|
||||
# Parse the Thickness value (supports 1, 2, or 4 inputs)
|
||||
$values = $Value -split ","
|
||||
switch ($values.Count) {
|
||||
1 { [System.Windows.Thickness]::new([double]$values[0]) }
|
||||
2 { [System.Windows.Thickness]::new([double]$values[0], [double]$values[1]) }
|
||||
4 { [System.Windows.Thickness]::new([double]$values[0], [double]$values[1], [double]$values[2], [double]$values[3]) }
|
||||
}
|
||||
}
|
||||
"FontFamily" { [Windows.Media.FontFamily]::new($Value) }
|
||||
"Double" { [double]$Value }
|
||||
default { $Value }
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# Log a warning if there's an issue setting the property
|
||||
Write-Warning "Failed to set property $($Name): $_"
|
||||
}
|
||||
}
|
||||
|
||||
# Retrieve all theme properties from the theme configuration
|
||||
$themeProperties = $sync.configs.themes.$currentTheme.PSObject.Properties
|
||||
foreach ($_ in $themeProperties) {
|
||||
# Apply properties that deal with colors
|
||||
if ($_.Name -like "*color*") {
|
||||
Set-ThemeResourceProperty -Name $_.Name -Value $_.Value -Type "ColorBrush"
|
||||
# For certain color properties, also set complementary values (e.g., BorderColor -> CBorderColor) This is required because e.g DropShadowEffect requires a <Color> and not a <SolidColorBrush> object
|
||||
if ($_.Name -in @("BorderColor", "ButtonBackgroundMouseoverColor")) {
|
||||
Set-ThemeResourceProperty -Name "C$($_.Name)" -Value $_.Value -Type "Color"
|
||||
}
|
||||
}
|
||||
# Apply corner radius properties
|
||||
elseif ($_.Name -like "*Radius*") {
|
||||
Set-ThemeResourceProperty -Name $_.Name -Value $_.Value -Type "CornerRadius"
|
||||
}
|
||||
# Apply row height properties
|
||||
elseif ($_.Name -like "*RowHeight*") {
|
||||
Set-ThemeResourceProperty -Name $_.Name -Value $_.Value -Type "GridLength"
|
||||
}
|
||||
# Apply thickness or margin properties
|
||||
elseif (($_.Name -like "*Thickness*") -or ($_.Name -like "*margin")) {
|
||||
Set-ThemeResourceProperty -Name $_.Name -Value $_.Value -Type "Thickness"
|
||||
}
|
||||
# Apply font family properties
|
||||
elseif ($_.Name -like "*FontFamily*") {
|
||||
Set-ThemeResourceProperty -Name $_.Name -Value $_.Value -Type "FontFamily"
|
||||
}
|
||||
# Apply any other properties as doubles (numerical values)
|
||||
else {
|
||||
Set-ThemeResourceProperty -Name $_.Name -Value $_.Value -Type "Double"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$LightPreferencePath = "$env:LOCALAPPDATA\winutil\LightTheme.ini"
|
||||
$DarkPreferencePath = "$env:LOCALAPPDATA\winutil\DarkTheme.ini"
|
||||
|
||||
if ($init) {
|
||||
Set-WinutilTheme -currentTheme "shared"
|
||||
if (Test-Path $LightPreferencePath) {
|
||||
$theme = "Light"
|
||||
}
|
||||
elseif (Test-Path $DarkPreferencePath) {
|
||||
$theme = "Dark"
|
||||
}
|
||||
else {
|
||||
$theme = "Auto"
|
||||
}
|
||||
}
|
||||
|
||||
switch ($theme) {
|
||||
"Auto" {
|
||||
$systemUsesDarkMode = Get-WinUtilToggleStatus WPFToggleDarkMode
|
||||
if ($systemUsesDarkMode){
|
||||
Set-WinutilTheme -currentTheme "Dark"
|
||||
}
|
||||
else{
|
||||
Set-WinutilTheme -currentTheme "Light"
|
||||
}
|
||||
|
||||
|
||||
$themeButtonIcon = [char]0xF08C
|
||||
Remove-Item $LightPreferencePath -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item $DarkPreferencePath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
"Dark" {
|
||||
Set-WinutilTheme -currentTheme $theme
|
||||
$themeButtonIcon = [char]0xE708
|
||||
$null = New-Item $DarkPreferencePath -Force
|
||||
Remove-Item $LightPreferencePath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
"Light" {
|
||||
Set-WinutilTheme -currentTheme $theme
|
||||
$themeButtonIcon = [char]0xE706
|
||||
$null = New-Item $LightPreferencePath -Force
|
||||
Remove-Item $DarkPreferencePath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
# Update the theme selector button with the appropriate icon
|
||||
$ThemeButton = $sync.Form.FindName("ThemeButton")
|
||||
$ThemeButton.Content = [string]$themeButtonIcon
|
||||
}
|
Reference in New Issue
Block a user