2024-09-20 08:34:10 -05:00
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
2024-09-20 09:03:18 -05:00
if ( $systemUsesDarkMode ) {
2024-09-20 08:34:10 -05:00
Set-WinutilTheme -currentTheme " Dark "
}
else {
Set-WinutilTheme -currentTheme " Light "
}
2024-09-20 09:03:18 -05:00
2024-09-20 08:34:10 -05:00
$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
}