From 00ea8f2a60264255a303ef5baaf68b3abc0879ac Mon Sep 17 00:00:00 2001 From: Marterich <47688561+Marterich@users.noreply.github.com> Date: Thu, 8 May 2025 13:54:52 +0200 Subject: [PATCH] More Cleanup, and simplification. Also added support for screenreaders --- config/appnavigation.json | 64 +++++++++---------- .../private/Initalize-InstallAppEntry.ps1 | 5 +- .../private/Initialize-InstallAppArea.ps1 | 17 +++-- .../Initialize-InstallAppsMainElement.ps1 | 28 -------- functions/public/Invoke-WPFButton.ps1 | 1 + functions/public/Invoke-WPFUIApps.ps1 | 12 ++-- functions/public/Invoke-WPFUIElements.ps1 | 6 -- 7 files changed, 54 insertions(+), 79 deletions(-) delete mode 100644 functions/private/Initialize-InstallAppsMainElement.ps1 diff --git a/config/appnavigation.json b/config/appnavigation.json index 7f5cfedb..d7782162 100644 --- a/config/appnavigation.json +++ b/config/appnavigation.json @@ -1,10 +1,24 @@ { - "WPFGetInstalled": { - "Content": "Get Installed", + "WPFInstall": { + "Content": "Install/Upgrade Applications", "Category": "____Actions", "Type": "Button", - "Order": "4", - "Description": "Show installed applications" + "Order": "1", + "Description": "Install or upgrade the selected applications" + }, + "WPFUninstall": { + "Content": "Uninstall Applications", + "Category": "____Actions", + "Type": "Button", + "Order": "2", + "Description": "Uninstall the selected applications" + }, + "WPFInstallUpgrade": { + "Content": "Upgrade all Applications", + "Category": "____Actions", + "Type": "Button", + "Order": "3", + "Description": "Upgrade all applications to the latest version" }, "WingetRadioButton": { "Content": "Winget", @@ -24,39 +38,25 @@ "Order": "2", "Description": "Use Chocolatey for package management" }, - "WPFInstall": { - "Content": "Install/Upgrade Applications", - "Category": "____Actions", - "Type": "Button", - "Order": "5", - "Description": "Install or upgrade the selected applications" - }, - "WPFInstallUpgrade": { - "Content": "Upgrade all Applications", - "Category": "____Actions", - "Type": "Button", - "Order": "6", - "Description": "Upgrade all applications to the latest version" - }, - "WPFUninstall": { - "Content": "Uninstall Applications", - "Category": "____Actions", - "Type": "Button", - "Order": "7", - "Description": "Uninstall the selected applications" - }, - "WPFselectedAppsButton": { - "Content": "Selected Apps: 0", - "Category": "__Selection", - "Type": "Button", - "Order": "2", - "Description": "Show the selected applications" - }, "WPFClearInstallSelection": { "Content": "Clear Selection", "Category": "__Selection", "Type": "Button", "Order": "1", "Description": "Clear the selection of applications" + }, + "WPFGetInstalled": { + "Content": "Get Installed", + "Category": "__Selection", + "Type": "Button", + "Order": "2", + "Description": "Show installed applications" + }, + "WPFselectedAppsButton": { + "Content": "Selected Apps: 0", + "Category": "__Selection", + "Type": "Button", + "Order": "3", + "Description": "Show the selected applications" } } diff --git a/functions/private/Initalize-InstallAppEntry.ps1 b/functions/private/Initalize-InstallAppEntry.ps1 index 806926cb..eef4f8ba 100644 --- a/functions/private/Initalize-InstallAppEntry.ps1 +++ b/functions/private/Initalize-InstallAppEntry.ps1 @@ -33,7 +33,6 @@ function Initialize-InstallAppEntry { } }) - # Create the CheckBox, vertically centered $checkBox = New-Object Windows.Controls.CheckBox $checkBox.Name = $appKey $checkbox.Style = $sync.Form.Resources.AppEntryCheckboxStyle @@ -57,6 +56,10 @@ function Initialize-InstallAppEntry { # Add the name to the Checkbox $checkBox.Content = $appName + # Add accessibility properties to make the elements screen reader friendly + $checkBox.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $Apps.$appKey.content) + $border.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $Apps.$appKey.content) + $border.Child = $checkBox # Add the border to the corresponding Category $TargetElement.Children.Add($border) | Out-Null diff --git a/functions/private/Initialize-InstallAppArea.ps1 b/functions/private/Initialize-InstallAppArea.ps1 index 3e79d56d..ea2f7ee0 100644 --- a/functions/private/Initialize-InstallAppArea.ps1 +++ b/functions/private/Initialize-InstallAppArea.ps1 @@ -10,27 +10,36 @@ #> param($TargetElement) + $targetGrid = $sync.Form.FindName($TargetElement) + $null = $targetGrid.Children.Clear() + + # Create the outer Border for the aren where the apps will be placed + $Border = New-Object Windows.Controls.Border + $Border.VerticalAlignment = "Stretch" + $Border.SetResourceReference([Windows.Controls.Control]::StyleProperty, "BorderStyle") + + # Add a ScrollViewer, because the ItemsControl does not support scrolling by itself $scrollViewer = New-Object Windows.Controls.ScrollViewer $scrollViewer.VerticalScrollBarVisibility = 'Auto' $scrollViewer.HorizontalAlignment = 'Stretch' $scrollViewer.VerticalAlignment = 'Stretch' $scrollViewer.CanContentScroll = $true + ## Create the ItemsControl, which will be the parent of all the app entries $itemsControl = New-Object Windows.Controls.ItemsControl $itemsControl.HorizontalAlignment = 'Stretch' $itemsControl.VerticalAlignment = 'Stretch' + # Enable virtualization for the ItemsControl to improve performance (It's hard to test if this is actually working, so if you know what you're doing, please check this) $itemsPanelTemplate = New-Object Windows.Controls.ItemsPanelTemplate $factory = New-Object Windows.FrameworkElementFactory ([Windows.Controls.VirtualizingStackPanel]) $itemsPanelTemplate.VisualTree = $factory $itemsControl.ItemsPanel = $itemsPanelTemplate - $itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::IsVirtualizingProperty, $true) $itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::VirtualizationModeProperty, [Windows.Controls.VirtualizationMode]::Recycling) $scrollViewer.Content = $itemsControl - - [Windows.Controls.DockPanel]::SetDock($scrollViewer, [Windows.Controls.Dock]::Bottom) - $null = $TargetElement.Children.Add($scrollViewer) + $Border.Child = $scrollViewer + $null = $targetGrid.Children.Add($Border) return $itemsControl } diff --git a/functions/private/Initialize-InstallAppsMainElement.ps1 b/functions/private/Initialize-InstallAppsMainElement.ps1 deleted file mode 100644 index 818a6343..00000000 --- a/functions/private/Initialize-InstallAppsMainElement.ps1 +++ /dev/null @@ -1,28 +0,0 @@ -function Initialize-InstallAppsMainElement { - <# - .SYNOPSIS - Clears the given WPF Grid and creates a [Windows.Controls.Border] containing a [Windows.Controls.StackPanel] - Used to as part of the Install Tab UI generation - .PARAMETER TargetGridName - The WPF Grid name - .OUTPUTS - Returns the created [Windows.Controls.StackPanel] element - #> - param( - [Parameter(Mandatory)] - [string]$TargetGridName - ) - $targetGrid = $sync.Form.FindName($TargetGridName) - $null = $targetGrid.Children.Clear() - - $Border = New-Object Windows.Controls.Border - $Border.VerticalAlignment = "Stretch" - $Border.SetResourceReference([Windows.Controls.Control]::StyleProperty, "BorderStyle") - - $dockPanel = New-Object Windows.Controls.DockPanel - $Border.Child = $dockPanel - - $null = $targetGrid.Children.Add($Border) - - return $dockPanel -} diff --git a/functions/public/Invoke-WPFButton.ps1 b/functions/public/Invoke-WPFButton.ps1 index f76680f8..bad13090 100644 --- a/functions/public/Invoke-WPFButton.ps1 +++ b/functions/public/Invoke-WPFButton.ps1 @@ -61,5 +61,6 @@ function Invoke-WPFButton { "WPFWinUtilInstallPSProfile" {Invoke-WinUtilInstallPSProfile} "WPFWinUtilUninstallPSProfile" {Invoke-WinUtilUninstallPSProfile} "WPFWinUtilSSHServer" {Invoke-WPFSSHServer} + "WPFselectedAppsButton" {$sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen} } } diff --git a/functions/public/Invoke-WPFUIApps.ps1 b/functions/public/Invoke-WPFUIApps.ps1 index ef66fc63..255c28a6 100644 --- a/functions/public/Invoke-WPFUIApps.ps1 +++ b/functions/public/Invoke-WPFUIApps.ps1 @@ -9,15 +9,14 @@ function Invoke-WPFUIApps { switch ($TargetGridName) { "appspanel" { - $dockPanel = Initialize-InstallAppsMainElement -TargetGridName $TargetGridName - # $null = Initialize-InstallHeader -TargetElement $dockPanel - + # Create and configure a popup for displaying selected apps $selectedAppsPopup = New-Object Windows.Controls.Primitives.Popup $selectedAppsPopup.IsOpen = $false $selectedAppsPopup.PlacementTarget = $sync.WPFselectedAppsButton $selectedAppsPopup.Placement = [System.Windows.Controls.Primitives.PlacementMode]::Bottom $selectedAppsPopup.AllowsTransparency = $true + # Style the popup with a border and background $selectedAppsBorder = New-Object Windows.Controls.Border $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "MainBackgroundColor") $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BorderBrushProperty, "MainForegroundColor") @@ -27,13 +26,10 @@ function Invoke-WPFUIApps { $selectedAppsPopup.Child = $selectedAppsBorder $sync.selectedAppsPopup = $selectedAppsPopup + # Add a stack panel inside the popup's border to organize its child elements $sync.selectedAppsstackPanel = New-Object Windows.Controls.StackPanel $selectedAppsBorder.Child = $sync.selectedAppsstackPanel - # Toggle selectedAppsPopup open/close with button - $sync.WPFselectedAppsButton.Add_Click({ - $sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen - }) # Close selectedAppsPopup when mouse leaves both button and selectedAppsPopup $sync.WPFselectedAppsButton.Add_MouseLeave({ if (-not $sync.selectedAppsPopup.IsMouseOver) { @@ -45,7 +41,7 @@ function Invoke-WPFUIApps { $sync.selectedAppsPopup.IsOpen = $false } }) - $sync.ItemsControl = Initialize-InstallAppArea -TargetElement $dockPanel + $sync.ItemsControl = Initialize-InstallAppArea -TargetElement $TargetGridName Initialize-InstallCategoryAppList -TargetElement $sync.ItemsControl -Apps $Apps } default { diff --git a/functions/public/Invoke-WPFUIElements.ps1 b/functions/public/Invoke-WPFUIElements.ps1 index cfbf662b..09764404 100644 --- a/functions/public/Invoke-WPFUIElements.ps1 +++ b/functions/public/Invoke-WPFUIElements.ps1 @@ -93,12 +93,6 @@ function Invoke-WPFUIElements { # 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 - } - } # Initialize panel count