Merge branch 'ChrisTitusTech:main' into microwinisodownloader

This commit is contained in:
MyDrift
2024-09-01 15:43:29 +02:00
committed by GitHub
37 changed files with 1189 additions and 727 deletions

View File

@ -1,221 +0,0 @@
function Get-TabXaml {
<#
.SYNOPSIS
Generates XAML for a tab in the WinUtil GUI
This function is used to generate the XAML for the applications tab in the WinUtil GUI
It takes the tabname and the number of columns to display the applications in as input and returns the XAML for the tab as output
.PARAMETER tabname
The name of the tab to generate XAML for
Note: the 'tabname' parameter must equal one of the json files found in $sync.configs variable
Otherwise, it'll throw an exception
.PARAMETER columncount
The number of columns to display the applications in, default is 0
.OUTPUTS
The XAML for the tab
.EXAMPLE
Get-TabXaml "applications" 3
#>
param(
[Parameter(Mandatory, position=0)]
[string]$tabname,
[Parameter(position=1)]
[ValidateRange(0,10)] # 10 panels as max number is more then enough
[int]$columncount = 0
)
# Validate tabname
if ($sync.configs.$tabname -eq $null) {
throw "Invalid parameter passed, can't find '$tabname' in '`$sync.configs' variable, please double check any calls to 'Get-TabXaml' function."
}
$organizedData = @{}
# Iterate through JSON data and organize by panel and category
foreach ($appName in $sync.configs.$tabname.PSObject.Properties.Name) {
$appInfo = $sync.configs.$tabname.$appName
# Create an object for the application
$appObject = [PSCustomObject]@{
Name = $appName
Category = $appInfo.Category
Content = $appInfo.Content
Choco = $appInfo.choco
Winget = $appInfo.winget
Panel = if ($columncount -gt 0 ) { "0" } else {$appInfo.panel}
Link = $appInfo.link
Description = $appInfo.description
# Type is (Checkbox,Toggle,Button,Combobox ) (Default is Checkbox)
Type = $appInfo.type
ComboItems = $appInfo.ComboItems
# Checked is the property to set startup checked status of checkbox (Default is false)
Checked = $appInfo.Checked
ButtonWidth = $appInfo.ButtonWidth
}
if (-not $organizedData.ContainsKey($appObject.panel)) {
$organizedData[$appObject.panel] = @{}
}
if (-not $organizedData[$appObject.panel].ContainsKey($appObject.Category)) {
$organizedData[$appObject.panel][$appObject.Category] = @{}
}
# Store application data in a sub-array under the category
# Add Order property to keep the original order of tweaks and features
$organizedData[$appObject.panel][$appInfo.Category]["$($appInfo.order)$appName"] = $appObject
}
# Same tab amount in last line of 'inputXML.xaml' file
# TODO: Get the base repeat (amount) of tabs from last line (or even lines)
# so it can dynamicly react to whatever is before this generated XML string.
# .. may be solve this even before calling this function, and pass the result as a parameter?
$tab_repeat = 7
$spaces_per_tab = 4 # The convenction used across the code base
$tab_as_spaces = $(" " * $spaces_per_tab)
$precal_indent = $($tab_as_spaces * $tab_repeat)
$precal_indent_p1 = $($tab_as_spaces * ($tab_repeat + 1))
$precal_indent_p2 = $($tab_as_spaces * ($tab_repeat + 2))
$precal_indent_m1 = $($tab_as_spaces * ($tab_repeat - 1))
$precal_indent_m2 = $($tab_as_spaces * ($tab_repeat - 2))
# Calculate the needed number of panels
$panelcount = 0
$paneltotal = $organizedData.Keys.Count
if ($columncount -gt 0) {
$appcount = $sync.configs.$tabname.PSObject.Properties.Name.count + $organizedData["0"].Keys.count
$maxcount = [Math]::Round( $appcount / $columncount + 0.5)
$paneltotal = $columncount
}
# add ColumnDefinitions to evenly draw colums
$blockXml = "<Grid.ColumnDefinitions>"
$blockXml += $("`r`n" + " " * ($spaces_per_tab * $tab_repeat) +
"<ColumnDefinition Width=""*""/>") * $paneltotal
$blockXml += $("`r`n" + " " * ($spaces_per_tab * ($tab_repeat - 1))) +
"</Grid.ColumnDefinitions>" + "`r`n"
# Iterate through 'organizedData' by panel, category, and application
$count = 0
foreach ($panel in ($organizedData.Keys | Sort-Object)) {
$blockXml += $precal_indent_m1 + "<Border Grid.Row=""1"" Grid.Column=""$panelcount"">" + "`r`n"
$blockXml += $precal_indent + "<StackPanel Background=""{MainBackgroundColor}"" SnapsToDevicePixels=""True"">" + "`r`n"
$panelcount++
foreach ($category in ($organizedData[$panel].Keys | Sort-Object)) {
$count++
if ($columncount -gt 0) {
$panelcount2 = [Int](($count)/$maxcount-0.5)
if ($panelcount -eq $panelcount2 ) {
$blockXml += $precal_indent_p2 + "</StackPanel>" + "`r`n"
$blockXml += $precal_indent_p1 + "</Border>" + "`r`n"
$blockXml += $precal_indent_p1 + "<Border Grid.Row=""1"" Grid.Column=""$panelcount"">" + "`r`n"
$blockXml += $precal_indent_p2 + "<StackPanel Background=""{MainBackgroundColor}"" SnapsToDevicePixels=""True"">" + "`r`n"
$panelcount++
}
}
# Dot-source the Get-WPFObjectName function
. "$($sync.PSScriptRoot)\functions\private\Get-WPFObjectName.ps1"
$categorycontent = $($category -replace '^.__', '')
$categoryname = Get-WPFObjectName -type "Label" -name $categorycontent
$blockXml += $("`r`n" + " " * ($spaces_per_tab * $tab_repeat)) +
"<Label Name=""$categoryname"" Content=""$categorycontent""" + " " +
"FontSize=""{FontSizeHeading}"" FontFamily=""{HeaderFontFamily}""/>" + "`r`n" + "`r`n"
$sortedApps = $organizedData[$panel][$category].Keys | Sort-Object
foreach ($appName in $sortedApps) {
$count++
if ($columncount -gt 0) {
$panelcount2 = [Int](($count)/$maxcount-0.5)
# Verify the indentation actually works...
if ($panelcount -eq $panelcount2 ) {
$blockXml += $precal_indent_m1 +
"</StackPanel>" + "`r`n"
$blockXml += $precal_indent_m2 +
"</Border>" + "`r`n"
$blockXml += $precal_indent_m2 +
"<Border Grid.Row=""1"" Grid.Column=""$panelcount"">" + "`r`n"
$blockXml += $precal_indent_m1 +
"<StackPanel Background=""{MainBackgroundColor}"" SnapsToDevicePixels=""True"">" + "`r`n"
$panelcount++
}
}
$appInfo = $organizedData[$panel][$category][$appName]
switch ($appInfo.Type) {
"Toggle" {
$blockXml += $precal_indent_m1 +
"<DockPanel LastChildFill=""True"">" + "`r`n"
$blockXml += $precal_indent +
"<CheckBox Name=""$($appInfo.Name)"" Style=""{StaticResource ColorfulToggleSwitchStyle}"" Margin=""4,0""" + " " +
"HorizontalAlignment=""Right"" FontSize=""{FontSize}""/>" + "`r`n"
$blockXml += $precal_indent +
"<Label Content=""$($appInfo.Content)"" ToolTip=""$($appInfo.Description)""" + " " +
"HorizontalAlignment=""Left"" FontSize=""{FontSize}""/>" + "`r`n"
$blockXml += $precal_indent_m1 +
"</DockPanel>" + "`r`n"
}
"Combobox" {
$blockXml += $precal_indent_m1 +
"<StackPanel Orientation=""Horizontal"" Margin=""0,5,0,0"">" + "`r`n"
$blockXml += $precal_indent + "<Label Content=""$($appInfo.Content)"" HorizontalAlignment=""Left""" + " " +
"VerticalAlignment=""Center"" FontSize=""{FontSize}""/>" + "`r`n"
$blockXml += $precal_indent +
"<ComboBox Name=""$($appInfo.Name)"" Height=""32"" Width=""186"" HorizontalAlignment=""Left""" + " " +
"VerticalAlignment=""Center"" Margin=""5,5"" FontSize=""{FontSize}"">" + "`r`n"
$addfirst="IsSelected=""True"""
foreach ($comboitem in ($appInfo.ComboItems -split " ")) {
$blockXml += $precal_indent_p1 +
"<ComboBoxItem $addfirst Content=""$comboitem"" FontSize=""{FontSize}""/>" + "`r`n"
$addfirst=""
}
$blockXml += $precal_indent_p1 + "</ComboBox>" + "`r`n"
$blockXml += $precal_indent + "</StackPanel>" + "`r`n"
}
"Button" {
if ($appInfo.ButtonWidth -ne $null) {
$ButtonWidthStr = "Width=""$($appInfo.ButtonWidth)"""
}
$blockXml += $precal_indent +
"<Button Name=""$($appInfo.Name)"" Content=""$($appInfo.Content)""" + " " +
"HorizontalAlignment=""Left"" Margin=""5"" Padding=""20,5"" $($ButtonWidthStr)/>" + "`r`n"
}
# else it is a checkbox
default {
$checkedStatus = If ($appInfo.Checked -eq $null) {""} else {" IsChecked=""$($appInfo.Checked)"""}
if ($appInfo.Link -eq $null) {
$blockXml += $precal_indent +
"<CheckBox Name=""$($appInfo.Name)"" Content=""$($appInfo.Content)""$($checkedStatus) Margin=""5,0""" + " " +
"ToolTip=""$($appInfo.Description)""/>" + "`r`n"
} else {
$blockXml += $precal_indent +
"<StackPanel Orientation=""Horizontal"">" + "`r`n"
$blockXml += $precal_indent_p1 +
"<CheckBox Name=""$($appInfo.Name)"" Content=""$($appInfo.Content)""$($checkedStatus)" + " " +
"ToolTip=""$($appInfo.Description)"" Margin=""0,0,2,0""/>" + "`r`n"
$blockXml += $precal_indent_p1 +
"<TextBlock Name=""$($appInfo.Name)Link"" Style=""{StaticResource HoverTextBlockStyle}"" Text=""(?)""" + " " +
"ToolTip=""$($appInfo.Link)""/>" + "`r`n"
$blockXml += $precal_indent +
"</StackPanel>" + "`r`n"
}
}
}
}
}
$blockXml += $precal_indent_p1 + "</StackPanel>" + "`r`n"
$blockXml += $precal_indent + "</Border>" + "`r`n"
}
return ($blockXml)
}

View File

@ -7,7 +7,9 @@ function Invoke-WinUtilGPU {
"*NVIDIA GeForce*Laptop*",
"*NVIDIA GeForce*GT*",
"*AMD Radeon(TM)*",
"*Intel(R) HD Graphics*",
"*UHD*"
)
foreach ($gpu in $gpuInfo) {
@ -18,4 +20,4 @@ function Invoke-WinUtilGPU {
}
}
return $true
}
}

View File

@ -109,6 +109,7 @@ function Remove-Features() {
Write-Host "You can re-enable the disabled features at any time, using either Windows Update or the SxS folder in <installation media>\Sources."
} catch {
Write-Host "Unable to get information about the features. MicroWin processing will continue, but features will not be processed"
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
@ -156,6 +157,8 @@ function Remove-Packages {
$_ -NotLike "*Wifi*"
}
$failedCount = 0
foreach ($pkg in $pkglist) {
try {
$status = "Removing $pkg"
@ -164,12 +167,18 @@ function Remove-Packages {
} catch {
# This can happen if the package that is being removed is a permanent one, like FodMetadata
Write-Host "Could not remove OS package $($pkg)"
$failedCount += 1
continue
}
}
Write-Progress -Activity "Removing Apps" -Status "Ready" -Completed
if ($failedCount -gt 0)
{
Write-Host "Some packages could not be removed. Do not worry: your image will still work fine. This can happen if the package is permanent or has been superseded by a newer one."
}
} catch {
Write-Host "Unable to get information about the packages. MicroWin processing will continue, but packages will not be processed"
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
@ -225,6 +234,7 @@ function Remove-ProvisionedPackages() {
{
# This can happen if getting AppX packages fails
Write-Host "Unable to get information about the AppX packages. MicroWin processing will continue, but AppX packages will not be processed"
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
}
}

View File

@ -14,7 +14,7 @@ function Invoke-WinUtilSnapFlyout {
Write-Host "Disabling Snap Assist Flyout On startup"
$value = 0
}
# taskkill.exe /F /IM "explorer.exe"
$Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
taskkill.exe /F /IM "explorer.exe"
Set-ItemProperty -Path $Path -Name EnableSnapAssistFlyout -Value $value

View File

@ -0,0 +1,83 @@
function Set-WinUtilUITheme {
<#
.SYNOPSIS
Sets the theme of the XAML file
.PARAMETER inputXML
A string representing the XAML object to modify
.PARAMETER customThemeName
The name of the custom theme to set the XAML to. Defaults to 'matrix'
.PARAMETER defaultThemeName
The name of the default theme to use when setting the XAML. Defaults to '_default'
.EXAMPLE
$returnVal = Set-WinUtilUITheme -inputXAML $inputXAML
if ($returnVal[0] -eq "") {
Write-Host "Failed to process inputXML"
} else {
$inputXML = $returnVal[0]
}
# to know which theme this function has used, access the second item in returned value.
Write-Host "Theme used in processing: $($returnVal[1])"
#>
param (
[Parameter(Mandatory, position=0)]
[string]$inputXML,
[Parameter(position=1)]
[string]$customThemeName = 'matrix',
[Parameter(position=2)]
[string]$defaultThemeName = '_default'
)
try {
# Note:
# Reason behind not caching the '$sync.configs.themes` object into a variable,
# because this code can modify the themes object.. meaning it's better to access it
# using the more verbose way, rather than introduce possible bugs into the code, just for the sake of readability.
#
if (-NOT $sync.configs.themes) {
throw [GenericException]::new("[Set-WinUtilTheme] Did not find 'config.themes' inside `$sync variable.")
}
if (-NOT $sync.configs.themes.$defaultThemeName) {
throw [GenericException]::new("[Set-WinUtilTheme] Did not find '$defaultThemeName' theme in the themes config file.")
}
$themeToUse = $customThemeName
if ($sync.configs.themes.$themeToUse) {
# Loop through every default theme option, and modify the custom theme in $sync variable,
# so that it has full options available for other functions to use.
foreach ($option in $sync.configs.themes.$defaultThemeName.PSObject.Properties) {
$optionName = $option.Name
$optionValue = $option.Value
if (-NOT $sync.configs.themes.$themeToUse.$optionName) {
$sync.configs.themes.$themeToUse | Add-Member -MemberType NoteProperty -Name $optionName -Value $optionValue
}
}
} else {
Write-Debug "[Set-WinUtilTheme] Theme '$customThemeName' was not found, using '$defaultThemeName' instead."
$themeToUse = $defaultThemeName
}
foreach ($property in $sync.configs.themes.$themeToUse.PSObject.Properties) {
$key = $property.Name
$value = $property.Value
# Add curly braces around the key
$formattedKey = "{$key}"
# Replace the key with the value in the input XML
$inputXML = $inputXML.Replace($formattedKey, $value)
}
}
catch {
Write-Host "[Set-WinUtilTheme] Unable to apply theme" -ForegroundColor Red
Write-Host "$($psitem.Exception.Message)" -ForegroundColor Red
$inputXML = "" # Make inputXML equal an empty string, indicating something went wrong to the function caller.
}
return @($inputXML, $themeToUse);
}

View File

@ -1,50 +0,0 @@
function Set-WinUtilUITheme {
<#
.SYNOPSIS
Sets the theme of the XAML file
.PARAMETER inputXML
A string representing the XAML object to modify
.PARAMETER themeName
The name of the theme to set the XAML to. Defaults to 'matrix'
.EXAMPLE
Set-WinUtilUITheme -inputXAML $inputXAML
#>
param
(
[Parameter(Mandatory, position=0)]
[string]$inputXML,
[Parameter(position=1)]
[string]$themeName = 'matrix'
)
try {
# Convert the JSON to a PowerShell object
$themes = $sync.configs.themes
# Select the specified theme
$selectedTheme = $themes.$themeName
if ($selectedTheme) {
# Loop through all key-value pairs in the selected theme
foreach ($property in $selectedTheme.PSObject.Properties) {
$key = $property.Name
$value = $property.Value
# Add curly braces around the key
$formattedKey = "{$key}"
# Replace the key with the value in the input XML
$inputXML = $inputXML.Replace($formattedKey, $value)
}
} else {
Write-Host "Theme '$themeName' not found."
}
} catch {
Write-Warning "Unable to apply theme"
Write-Warning $psitem.Exception.StackTrace
}
return $inputXML;
}

View File

@ -11,7 +11,7 @@ Function Update-WinUtilProgramWinget {
$host.ui.RawUI.WindowTitle = """Winget Install"""
Start-Transcript $ENV:TEMP\winget-update.log -Append
Start-Transcript "$logdir\winget-update_$dateTime.log" -Append
winget upgrade --all --accept-source-agreements --accept-package-agreements --scope=machine --silent
}

View File

@ -21,13 +21,13 @@ function Invoke-WPFButton {
Switch -Wildcard ($Button) {
"WPFTab?BT" {Invoke-WPFTab $Button}
"WPFinstall" {Invoke-WPFInstall}
"WPFuninstall" {Invoke-WPFUnInstall}
"WPFInstall" {Invoke-WPFInstall}
"WPFUninstall" {Invoke-WPFUnInstall}
"WPFInstallUpgrade" {Invoke-WPFInstallUpgrade}
"WPFstandard" {Invoke-WPFPresets "Standard"}
"WPFminimal" {Invoke-WPFPresets "Minimal"}
"WPFclear" {Invoke-WPFPresets -preset $null -imported $true}
"WPFclearWinget" {Invoke-WPFPresets -preset $null -imported $true -CheckBox "WPFInstall"}
"WPFStandard" {Invoke-WPFPresets "Standard" -checkboxfilterpattern "WPFTweak*"}
"WPFMinimal" {Invoke-WPFPresets "Minimal" -checkboxfilterpattern "WPFTweak*"}
"WPFClearTweaksSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFTweak*"}
"WPFClearInstallSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFInstall*"}
"WPFtweaksbutton" {Invoke-WPFtweaksbutton}
"WPFOOSUbutton" {Invoke-WPFOOSU}
"WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enable"}

View File

@ -41,6 +41,8 @@ function Invoke-WPFImpex {
if ($type -eq "export") {
$jsonFile = Get-WinUtilCheckBoxes -unCheck $false
$jsonFile | ConvertTo-Json | Out-File $FileBrowser.FileName -Force
$runscript = "iex ""& { `$(irm christitus.com/win) } -Config '$($FileBrowser.FileName)'"""
$runscript | Set-Clipboard
}
if ($type -eq "import") {
$jsonFile = Get-Content $Config | ConvertFrom-Json

View File

@ -10,29 +10,36 @@ function Invoke-WPFPresets {
.PARAMETER imported
If the preset is imported from a file, defaults to false
.PARAMETER checkbox
The checkbox to set the options to, defaults to 'WPFTweaks'
.PARAMETER checkboxfilterpattern
The Pattern to use when filtering through CheckBoxes, defaults to "**"
#>
param(
$preset,
[bool]$imported = $false
param (
[Parameter(position=0)]
[string]$preset = "",
[Parameter(position=1)]
[bool]$imported = $false,
[Parameter(position=2)]
[string]$checkboxfilterpattern = "**"
)
if($imported -eq $true) {
if ($imported -eq $true) {
$CheckBoxesToCheck = $preset
} else {
$CheckBoxesToCheck = $sync.configs.preset.$preset
}
$CheckBoxes = $sync.GetEnumerator() | Where-Object { $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" }
Write-Debug "Getting checkboxes to set $($CheckBoxes.Count)"
$CheckBoxes = ($sync.GetEnumerator()).where{ $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" -and $_.Name -like "$checkboxfilterpattern"}
Write-Debug "Getting checkboxes to set, number of checkboxes: $($CheckBoxes.Count)"
$CheckBoxesToCheck | ForEach-Object {
if ($_ -ne $null) {
Write-Debug $_
}
if ($CheckBoxesToCheck -ne "") {
$debugMsg = "CheckBoxes to Check are: "
$CheckBoxesToCheck | ForEach-Object { $debugMsg += "$_, " }
$debugMsg = $debugMsg -replace (',\s*$', '')
Write-Debug "$debugMsg"
}
foreach ($CheckBox in $CheckBoxes) {

View File

@ -15,23 +15,25 @@ function Invoke-WPFToggle {
# Use this to get the name of the button
#[System.Windows.MessageBox]::Show("$Button","Chris Titus Tech's Windows Utility","OK","Info")
$ToggleStatus = (Get-WinUtilToggleStatus $Button)
Switch -Wildcard ($Button) {
"WPFToggleDarkMode" {Invoke-WinUtilDarkMode -DarkMoveEnabled $(Get-WinUtilToggleStatus WPFToggleDarkMode)}
"WPFToggleBingSearch" {Invoke-WinUtilBingSearch $(Get-WinUtilToggleStatus WPFToggleBingSearch)}
"WPFToggleNumLock" {Invoke-WinUtilNumLock $(Get-WinUtilToggleStatus WPFToggleNumLock)}
"WPFToggleVerboseLogon" {Invoke-WinUtilVerboseLogon $(Get-WinUtilToggleStatus WPFToggleVerboseLogon)}
"WPFToggleShowExt" {Invoke-WinUtilShowExt $(Get-WinUtilToggleStatus WPFToggleShowExt)}
"WPFToggleSnapWindow" {Invoke-WinUtilSnapWindow $(Get-WinUtilToggleStatus WPFToggleSnapWindow)}
"WPFToggleSnapFlyout" {Invoke-WinUtilSnapFlyout $(Get-WinUtilToggleStatus WPFToggleSnapFlyout)}
"WPFToggleSnapSuggestion" {Invoke-WinUtilSnapSuggestion $(Get-WinUtilToggleStatus WPFToggleSnapSuggestion)}
"WPFToggleMouseAcceleration" {Invoke-WinUtilMouseAcceleration $(Get-WinUtilToggleStatus WPFToggleMouseAcceleration)}
"WPFToggleStickyKeys" {Invoke-WinUtilStickyKeys $(Get-WinUtilToggleStatus WPFToggleStickyKeys)}
"WPFToggleTaskbarWidgets" {Invoke-WinUtilTaskbarWidgets $(Get-WinUtilToggleStatus WPFToggleTaskbarWidgets)}
"WPFToggleTaskbarSearch" {Invoke-WinUtilTaskbarSearch $(Get-WinUtilToggleStatus WPFToggleTaskbarSearch)}
"WPFToggleTaskView" {Invoke-WinUtilTaskView $(Get-WinUtilToggleStatus WPFToggleTaskView)}
"WPFToggleHiddenFiles" {Invoke-WinUtilHiddenFiles $(Get-WinUtilToggleStatus WPFToggleHiddenFiles)}
"WPFToggleTaskbarAlignment" {Invoke-WinUtilTaskbarAlignment $(Get-WinUtilToggleStatus WPFToggleTaskbarAlignment)}
"WPFToggleDetailedBSoD" {Invoke-WinUtilDetailedBSoD $(Get-WinUtilToggleStatus WPFToggleDetailedBSoD)}
"WPFToggleDarkMode" {Invoke-WinUtilDarkMode $ToggleStatus}
"WPFToggleBingSearch" {Invoke-WinUtilBingSearch $ToggleStatus}
"WPFToggleNumLock" {Invoke-WinUtilNumLock $ToggleStatus}
"WPFToggleVerboseLogon" {Invoke-WinUtilVerboseLogon $ToggleStatus}
"WPFToggleShowExt" {Invoke-WinUtilShowExt $ToggleStatus}
"WPFToggleSnapWindow" {Invoke-WinUtilSnapWindow $ToggleStatus}
"WPFToggleSnapFlyout" {Invoke-WinUtilSnapFlyout $ToggleStatus}
"WPFToggleSnapSuggestion" {Invoke-WinUtilSnapSuggestion $ToggleStatus}
"WPFToggleMouseAcceleration" {Invoke-WinUtilMouseAcceleration $ToggleStatus}
"WPFToggleStickyKeys" {Invoke-WinUtilStickyKeys $ToggleStatus}
"WPFToggleTaskbarWidgets" {Invoke-WinUtilTaskbarWidgets $ToggleStatus}
"WPFToggleTaskbarSearch" {Invoke-WinUtilTaskbarSearch $ToggleStatus}
"WPFToggleTaskView" {Invoke-WinUtilTaskView $ToggleStatus}
"WPFToggleHiddenFiles" {Invoke-WinUtilHiddenFiles $ToggleStatus}
"WPFToggleTaskbarAlignment" {Invoke-WinUtilTaskbarAlignment $ToggleStatus}
"WPFToggleDetailedBSoD" {Invoke-WinUtilDetailedBSoD $ToggleStatus}
}
}

View File

@ -0,0 +1,326 @@
function Invoke-WPFUIElements {
<#
.SYNOPSIS
Adds UI elements to a specified Grid in the WinUtil GUI based on a JSON configuration.
.PARAMETER configVariable
The variable/link containing the JSON configuration.
.PARAMETER targetGridName
The name of the grid to which the UI elements should be added.
.PARAMETER columncount
The number of columns to be used in the Grid. If not provided, a default value is used based on the panel.
.EXAMPLE
Invoke-WPFUIElements -configVariable $sync.configs.applications -targetGridName "install" -columncount 5
.NOTES
Future me/contributer: If possible please wrap this into a runspace to make it load all panels at the same time.
#>
param(
[Parameter(Mandatory, position=0)]
[PSCustomObject]$configVariable,
[Parameter(Mandatory, position=1)]
[string]$targetGridName,
[Parameter(Mandatory, position=2)]
[int]$columncount
)
$window = $sync["Form"]
$theme = $sync.configs.themes.$ctttheme
$borderstyle = $window.FindResource("BorderStyle")
$HoverTextBlockStyle = $window.FindResource("HoverTextBlockStyle")
$ColorfulToggleSwitchStyle = $window.FindResource("ColorfulToggleSwitchStyle")
if (!$borderstyle -or !$HoverTextBlockStyle -or !$ColorfulToggleSwitchStyle) {
throw "Failed to retrieve Styles using 'FindResource' from main window element."
}
$targetGrid = $window.FindName($targetGridName)
if (!$targetGrid) {
throw "Failed to retrieve Target Grid by name, provided name: $targetGrid"
}
# Clear existing ColumnDefinitions and Children
$targetGrid.ColumnDefinitions.Clear() | Out-Null
$targetGrid.Children.Clear() | Out-Null
# Add ColumnDefinitions to the target Grid
for ($i = 0; $i -lt $columncount; $i++) {
$colDef = New-Object Windows.Controls.ColumnDefinition
$colDef.Width = New-Object Windows.GridLength(1, [Windows.GridUnitType]::Star)
$targetGrid.ColumnDefinitions.Add($colDef) | Out-Null
}
# Convert PSCustomObject to Hashtable
$configHashtable = @{}
$configVariable.PSObject.Properties.Name | ForEach-Object {
$configHashtable[$_] = $configVariable.$_
}
$organizedData = @{}
# Iterate through JSON data and organize by panel and category
foreach ($entry in $configHashtable.Keys) {
$entryInfo = $configHashtable[$entry]
# Create an object for the application
$entryObject = [PSCustomObject]@{
Name = $entry
Order = $entryInfo.order
Category = $entryInfo.Category
Content = $entryInfo.Content
Choco = $entryInfo.choco
Winget = $entryInfo.winget
Panel = if ($entryInfo.Panel) { $entryInfo.Panel } else { "0" }
Link = $entryInfo.link
Description = $entryInfo.description
Type = $entryInfo.type
ComboItems = $entryInfo.ComboItems
Checked = $entryInfo.Checked
ButtonWidth = $entryInfo.ButtonWidth
}
if (-not $organizedData.ContainsKey($entryObject.Panel)) {
$organizedData[$entryObject.Panel] = @{}
}
if (-not $organizedData[$entryObject.Panel].ContainsKey($entryObject.Category)) {
$organizedData[$entryObject.Panel][$entryObject.Category] = @()
}
# Store application data in an array under the category
$organizedData[$entryObject.Panel][$entryObject.Category] += $entryObject
# Only apply the logic for distributing entries across columns if the targetGridName is "appspanel"
if ($targetGridName -eq "appspanel") {
$panelcount = 0
$entrycount = $configHashtable.Keys.Count + $organizedData["0"].Keys.Count
$maxcount = [Math]::Round($entrycount / $columncount + 0.5)
}
}
# Iterate through 'organizedData' by panel, category, and application
$count = 0
foreach ($panelKey in ($organizedData.Keys | Sort-Object)) {
# Create a Border for each column
$border = New-Object Windows.Controls.Border
$border.VerticalAlignment = "Stretch" # Ensure the border stretches vertically
[System.Windows.Controls.Grid]::SetColumn($border, $panelcount)
$border.style = $borderstyle
$targetGrid.Children.Add($border) | Out-Null
# Create a StackPanel inside the Border
$stackPanel = New-Object Windows.Controls.StackPanel
$stackPanel.Background = [Windows.Media.Brushes]::Transparent
$stackPanel.SnapsToDevicePixels = $true
$stackPanel.VerticalAlignment = "Stretch" # Ensure the stack panel stretches vertically
$border.Child = $stackPanel
$panelcount++
foreach ($category in ($organizedData[$panelKey].Keys | Sort-Object)) {
$count++
if ($targetGridName -eq "appspanel" -and $columncount -gt 0) {
$panelcount2 = [Int](($count) / $maxcount - 0.5)
if ($panelcount -eq $panelcount2) {
# Create a new Border for the new column
$border = New-Object Windows.Controls.Border
$border.VerticalAlignment = "Stretch" # Ensure the border stretches vertically
[System.Windows.Controls.Grid]::SetColumn($border, $panelcount)
$border.style = $borderstyle
$targetGrid.Children.Add($border) | Out-Null
# Create a new StackPanel inside the Border
$stackPanel = New-Object Windows.Controls.StackPanel
$stackPanel.Background = [Windows.Media.Brushes]::Transparent
$stackPanel.SnapsToDevicePixels = $true
$stackPanel.VerticalAlignment = "Stretch" # Ensure the stack panel stretches vertically
$border.Child = $stackPanel
$panelcount++
}
}
$label = New-Object Windows.Controls.Label
$label.Content = $category -replace ".*__", ""
$label.FontSize = $theme.FontSizeHeading
$label.FontFamily = $theme.HeaderFontFamily
$stackPanel.Children.Add($label) | Out-Null
$sync[$category] = $label
# Sort entries by Order and then by Name, but only display Name
$entries = $organizedData[$panelKey][$category] | Sort-Object Order, Name
foreach ($entryInfo in $entries) {
$count++
if ($targetGridName -eq "appspanel" -and $columncount -gt 0) {
$panelcount2 = [Int](($count) / $maxcount - 0.5)
if ($panelcount -eq $panelcount2) {
# Create a new Border for the new column
$border = New-Object Windows.Controls.Border
$border.VerticalAlignment = "Stretch" # Ensure the border stretches vertically
[System.Windows.Controls.Grid]::SetColumn($border, $panelcount)
$border.style = $borderstyle
$targetGrid.Children.Add($border) | Out-Null
# Create a new StackPanel inside the Border
$stackPanel = New-Object Windows.Controls.StackPanel
$stackPanel.Background = [Windows.Media.Brushes]::Transparent
$stackPanel.SnapsToDevicePixels = $true
$stackPanel.VerticalAlignment = "Stretch" # Ensure the stack panel stretches vertically
$border.Child = $stackPanel
$panelcount++
}
}
switch ($entryInfo.Type) {
"Toggle" {
$dockPanel = New-Object Windows.Controls.DockPanel
$checkBox = New-Object Windows.Controls.CheckBox
$checkBox.Name = $entryInfo.Name
$checkBox.HorizontalAlignment = "Right"
$dockPanel.Children.Add($checkBox) | Out-Null
$checkBox.Style = $ColorfulToggleSwitchStyle
$label = New-Object Windows.Controls.Label
$label.Content = $entryInfo.Content
$label.ToolTip = $entryInfo.Description
$label.HorizontalAlignment = "Left"
$label.FontSize = $theme.FontSize
$label.Foreground = $theme.MainForegroundColor
$dockPanel.Children.Add($label) | Out-Null
$stackPanel.Children.Add($dockPanel) | Out-Null
$sync[$entryInfo.Name] = $checkBox
$sync[$entryInfo.Name].IsChecked = Get-WinUtilToggleStatus $sync[$entryInfo.Name].Name
$sync[$entryInfo.Name].Add_Click({
[System.Object]$Sender = $args[0]
Invoke-WPFToggle $Sender.name
})
}
"ToggleButton" {
$toggleButton = New-Object Windows.Controls.ToggleButton
$toggleButton.Name = $entryInfo.Name
$toggleButton.Name = "WPFTab" + ($stackPanel.Children.Count + 1) + "BT"
$toggleButton.HorizontalAlignment = "Left"
$toggleButton.Height = $theme.TabButtonHeight
$toggleButton.Width = $theme.TabButtonWidth
$toggleButton.Background = $theme.ButtonInstallBackgroundColor
$toggleButton.Foreground = [Windows.Media.Brushes]::White
$toggleButton.FontWeight = [Windows.FontWeights]::Bold
$textBlock = New-Object Windows.Controls.TextBlock
$textBlock.FontSize = $theme.TabButtonFontSize
$textBlock.Background = [Windows.Media.Brushes]::Transparent
$textBlock.Foreground = $theme.ButtonInstallForegroundColor
$underline = New-Object Windows.Documents.Underline
$underline.Inlines.Add($entryInfo.name -replace "(.).*", "`$1")
$run = New-Object Windows.Documents.Run
$run.Text = $entryInfo.name -replace "^.", ""
$textBlock.Inlines.Add($underline)
$textBlock.Inlines.Add($run)
$toggleButton.Content = $textBlock
$stackPanel.Children.Add($toggleButton) | Out-Null
$sync[$entryInfo.Name] = $toggleButton
}
"Combobox" {
$horizontalStackPanel = New-Object Windows.Controls.StackPanel
$horizontalStackPanel.Orientation = "Horizontal"
$horizontalStackPanel.Margin = "0,5,0,0"
$label = New-Object Windows.Controls.Label
$label.Content = $entryInfo.Content
$label.HorizontalAlignment = "Left"
$label.VerticalAlignment = "Center"
$label.FontSize = $theme.ButtonFontSize
$horizontalStackPanel.Children.Add($label) | Out-Null
$comboBox = New-Object Windows.Controls.ComboBox
$comboBox.Name = $entryInfo.Name
$comboBox.Height = $theme.ButtonHeight
$comboBox.Width = $theme.ButtonWidth
$comboBox.HorizontalAlignment = "Left"
$comboBox.VerticalAlignment = "Center"
$comboBox.Margin = $theme.ButtonMargin
foreach ($comboitem in ($entryInfo.ComboItems -split " ")) {
$comboBoxItem = New-Object Windows.Controls.ComboBoxItem
$comboBoxItem.Content = $comboitem
$comboBoxItem.FontSize = $theme.ButtonFontSize
$comboBox.Items.Add($comboBoxItem) | Out-Null
}
$horizontalStackPanel.Children.Add($comboBox) | Out-Null
$stackPanel.Children.Add($horizontalStackPanel) | Out-Null
$comboBox.SelectedIndex = 0
$sync[$entryInfo.Name] = $comboBox
}
"Button" {
$button = New-Object Windows.Controls.Button
$button.Name = $entryInfo.Name
$button.Content = $entryInfo.Content
$button.HorizontalAlignment = "Left"
$button.Margin = $theme.ButtonMargin
$button.FontSize = $theme.ButtonFontSize
if ($entryInfo.ButtonWidth) {
$button.Width = $entryInfo.ButtonWidth
}
$stackPanel.Children.Add($button) | Out-Null
$sync[$entryInfo.Name] = $button
}
default {
$horizontalStackPanel = New-Object Windows.Controls.StackPanel
$horizontalStackPanel.Orientation = "Horizontal"
$checkBox = New-Object Windows.Controls.CheckBox
$checkBox.Name = $entryInfo.Name
$checkBox.Content = $entryInfo.Content
$checkBox.FontSize = $theme.FontSize
$checkBox.ToolTip = $entryInfo.Description
$checkBox.Margin = $theme.CheckBoxMargin
if ($entryInfo.Checked) {
$checkBox.IsChecked = $entryInfo.Checked
}
$horizontalStackPanel.Children.Add($checkBox) | Out-Null
if ($entryInfo.Link) {
$textBlock = New-Object Windows.Controls.TextBlock
$textBlock.Name = $checkBox.Name + "Link"
$textBlock.Text = "(?)"
$textBlock.ToolTip = $entryInfo.Link
$textBlock.Style = $HoverTextBlockStyle
# Add event handler for click to open link
$handler = [System.Windows.Input.MouseButtonEventHandler]{
param($sender, $e)
Start-Process $sender.ToolTip.ToString()
}
$textBlock.AddHandler([Windows.Controls.TextBlock]::MouseLeftButtonUpEvent, $handler)
$horizontalStackPanel.Children.Add($textBlock) | Out-Null
$sync[$textBlock.Name] = $textBlock
}
$stackPanel.Children.Add($horizontalStackPanel) | Out-Null
$sync[$entryInfo.Name] = $checkBox
}
}
}
}
}
}