From 4b7e815c68f952823e4b5512c7f47005e13bb101 Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT <53497092+rbalsleyMSFT@users.noreply.github.com> Date: Thu, 19 Jun 2025 18:38:53 -0700 Subject: [PATCH] Refactor Applications tab UI event handling Consolidates the scattered event handlers for the Applications tab checkboxes into a single, centralized function and a shared event handler. This new approach manages the visibility of all dependent UI panels based on the state of the checkboxes. This refactoring simplifies the codebase, eliminates redundant logic, and ensures a more consistent and predictable user interface state. Additionally, this change fixes bugs where clearing list views for Winget results and drivers did not properly update their "select all" header checkboxes. --- FFUDevelopment/BuildFFUVM_UI.ps1 | 9 -- .../FFUUI.Core/FFUUI.Core.Handlers.psm1 | 105 ++++++------------ .../FFUUI.Core/FFUUI.Core.Initialize.psm1 | 4 +- FFUDevelopment/FFUUI.Core/FFUUI.Core.psm1 | 40 +++++++ 4 files changed, 74 insertions(+), 84 deletions(-) diff --git a/FFUDevelopment/BuildFFUVM_UI.ps1 b/FFUDevelopment/BuildFFUVM_UI.ps1 index d8eb6cb..7d8ffa8 100644 --- a/FFUDevelopment/BuildFFUVM_UI.ps1 +++ b/FFUDevelopment/BuildFFUVM_UI.ps1 @@ -135,15 +135,6 @@ $window.Add_Loaded({ Register-EventHandlers -State $script:uiState - # APPLICATIONS tab UI logic (Keep existing logic) - $script:uiState.Controls.chkInstallWingetApps.Visibility = if ($script:uiState.Controls.chkInstallApps.IsChecked) { 'Visible' } else { 'Collapsed' } - $script:uiState.Controls.applicationPathPanel.Visibility = if ($script:uiState.Controls.chkInstallApps.IsChecked) { 'Visible' } else { 'Collapsed' } - $script:uiState.Controls.appListJsonPathPanel.Visibility = if ($script:uiState.Controls.chkInstallApps.IsChecked) { 'Visible' } else { 'Collapsed' } - $script:uiState.Controls.chkBringYourOwnApps.Visibility = if ($script:uiState.Controls.chkInstallApps.IsChecked) { 'Visible' } else { 'Collapsed' } - $script:uiState.Controls.byoApplicationPanel.Visibility = if ($script:uiState.Controls.chkBringYourOwnApps.IsChecked) { 'Visible' } else { 'Collapsed' } - $script:uiState.Controls.wingetPanel.Visibility = if ($script:uiState.Controls.chkInstallWingetApps.IsChecked) { 'Visible' } else { 'Collapsed' } - $script:uiState.Controls.wingetSearchPanel.Visibility = 'Collapsed' # Keep search hidden initially - # BYO Apps ListView setup (Keep existing logic, ensure CopyStatus column $byoGridView = $script:uiState.Controls.lstApplications.View if ($byoGridView -is [System.Windows.Controls.GridView]) { diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 index 504272d..b5e092d 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 @@ -227,33 +227,22 @@ function Register-EventHandlers { }) # Applications Tab Event Handlers - $State.Controls.chkInstallApps.Add_Checked({ - param($eventSource, $routedEventArgs) - $window = [System.Windows.Window]::GetWindow($eventSource) - $localState = $window.Tag - $localState.Controls.chkInstallWingetApps.Visibility = 'Visible' - $localState.Controls.applicationPathPanel.Visibility = 'Visible' - $localState.Controls.appListJsonPathPanel.Visibility = 'Visible' - $localState.Controls.chkBringYourOwnApps.Visibility = 'Visible' - $localState.Controls.chkDefineAppsScriptVariables.Visibility = 'Visible' - }) - $State.Controls.chkInstallApps.Add_Unchecked({ - param($eventSource, $routedEventArgs) - $window = [System.Windows.Window]::GetWindow($eventSource) - $localState = $window.Tag - $localState.Controls.chkInstallWingetApps.IsChecked = $false - $localState.Controls.chkBringYourOwnApps.IsChecked = $false - $localState.Controls.chkInstallWingetApps.Visibility = 'Collapsed' - $localState.Controls.applicationPathPanel.Visibility = 'Collapsed' - $localState.Controls.appListJsonPathPanel.Visibility = 'Collapsed' - $localState.Controls.chkBringYourOwnApps.Visibility = 'Collapsed' - $localState.Controls.wingetPanel.Visibility = 'Collapsed' - $localState.Controls.wingetSearchPanel.Visibility = 'Collapsed' - $localState.Controls.byoApplicationPanel.Visibility = 'Collapsed' - $localState.Controls.chkDefineAppsScriptVariables.IsChecked = $false - $localState.Controls.chkDefineAppsScriptVariables.Visibility = 'Collapsed' - $localState.Controls.appsScriptVariablesPanel.Visibility = 'Collapsed' - }) + # Define a single handler for interdependent application panel checkboxes + $appPanelUpdateHandler = { + param($eventSource, $routedEventArgs) + $window = [System.Windows.Window]::GetWindow($eventSource) + if ($null -ne $window) { + Update-ApplicationPanelVisibility -State $window.Tag -TriggeringControlName $eventSource.Name + } + } + + # Attach the handler to all relevant checkboxes + $State.Controls.chkInstallApps.Add_Checked($appPanelUpdateHandler) + $State.Controls.chkInstallApps.Add_Unchecked($appPanelUpdateHandler) + $State.Controls.chkBringYourOwnApps.Add_Checked($appPanelUpdateHandler) + $State.Controls.chkBringYourOwnApps.Add_Unchecked($appPanelUpdateHandler) + $State.Controls.chkInstallWingetApps.Add_Checked($appPanelUpdateHandler) + $State.Controls.chkInstallWingetApps.Add_Unchecked($appPanelUpdateHandler) $State.Controls.btnBrowseApplicationPath.Add_Click({ param($eventSource, $routedEventArgs) @@ -321,37 +310,6 @@ function Register-EventHandlers { Update-CopyButtonState -State $localState } }) - - $State.Controls.chkBringYourOwnApps.Add_Checked({ - param($eventSource, $routedEventArgs) - $window = [System.Windows.Window]::GetWindow($eventSource) - $localState = $window.Tag - $localState.Controls.byoApplicationPanel.Visibility = 'Visible' - }) - $State.Controls.chkBringYourOwnApps.Add_Unchecked({ - param($eventSource, $routedEventArgs) - $window = [System.Windows.Window]::GetWindow($eventSource) - $localState = $window.Tag - $localState.Controls.byoApplicationPanel.Visibility = 'Collapsed' - $localState.Controls.txtAppName.Text = '' - $localState.Controls.txtAppCommandLine.Text = '' - $localState.Controls.txtAppArguments.Text = '' - $localState.Controls.txtAppSource.Text = '' - }) - - $State.Controls.chkInstallWingetApps.Add_Checked({ - param($eventSource, $routedEventArgs) - $window = [System.Windows.Window]::GetWindow($eventSource) - $localState = $window.Tag - $localState.Controls.wingetPanel.Visibility = 'Visible' - }) - $State.Controls.chkInstallWingetApps.Add_Unchecked({ - param($eventSource, $routedEventArgs) - $window = [System.Windows.Window]::GetWindow($eventSource) - $localState = $window.Tag - $localState.Controls.wingetPanel.Visibility = 'Collapsed' - $localState.Controls.wingetSearchPanel.Visibility = 'Collapsed' - }) $State.Controls.btnClearBYOApplications.Add_Click({ param($eventSource, $routedEventArgs) @@ -402,18 +360,9 @@ function Register-EventHandlers { }) # Apps Script Variables Event Handlers - $State.Controls.chkDefineAppsScriptVariables.Add_Checked({ - param($eventSource, $routedEventArgs) - $window = [System.Windows.Window]::GetWindow($eventSource) - $localState = $window.Tag - $localState.Controls.appsScriptVariablesPanel.Visibility = 'Visible' - }) - $State.Controls.chkDefineAppsScriptVariables.Add_Unchecked({ - param($eventSource, $routedEventArgs) - $window = [System.Windows.Window]::GetWindow($eventSource) - $localState = $window.Tag - $localState.Controls.appsScriptVariablesPanel.Visibility = 'Collapsed' - }) + # Attach the handler to the script variables checkbox + $State.Controls.chkDefineAppsScriptVariables.Add_Checked($appPanelUpdateHandler) + $State.Controls.chkDefineAppsScriptVariables.Add_Unchecked($appPanelUpdateHandler) $State.Controls.btnAddAppsScriptVariable.Add_Click({ param($eventSource, $routedEventArgs) @@ -435,7 +384,6 @@ function Register-EventHandlers { $localState = $window.Tag $postClearScriptBlock = { - # This scriptblock inherits the $localState variable from its parent scope. $headerChk = $localState.Controls.chkSelectAllAppsScriptVariables if ($null -ne $headerChk) { Update-SelectAllHeaderCheckBoxState -ListView $localState.Controls.lstAppsScriptVariables -HeaderCheckBox $headerChk @@ -541,9 +489,9 @@ function Register-EventHandlers { $localState = $window.Tag $postClearScriptBlock = { - $headerChk = $State.Controls.chkSelectAllWingetResults + $headerChk = $localState.Controls.chkSelectAllWingetResults if ($null -ne $headerChk) { - Update-SelectAllHeaderCheckBoxState -ListView $ListViewControl -HeaderCheckBox $headerChk + Update-SelectAllHeaderCheckBoxState -ListView $localState.Controls.lstWingetResults -HeaderCheckBox $headerChk } } @@ -919,6 +867,14 @@ function Register-EventHandlers { param($eventSource, $routedEventArgs) $window = [System.Windows.Window]::GetWindow($eventSource) $localState = $window.Tag + + $postClearScriptBlock = { + # This scriptblock inherits the $localState variable from its parent scope. + $headerChk = $localState.Controls.chkSelectAllDriverModels + if ($null -ne $headerChk) { + Update-SelectAllHeaderCheckBoxState -ListView $localState.Controls.lstDriverModels -HeaderCheckBox $headerChk + } + } Clear-ListViewContent -State $localState ` -ListViewControl $localState.Controls.lstDriverModels ` @@ -926,7 +882,8 @@ function Register-EventHandlers { -ConfirmationTitle "Clear Driver List" ` -ConfirmationMessage "Are you sure you want to clear the driver list?" ` -StatusMessage "Driver list cleared." ` - -TextBoxesToClear @($localState.Controls.txtModelFilter) + -TextBoxesToClear @($localState.Controls.txtModelFilter)` + -PostClearAction $postClearScriptBlock }) $State.Controls.btnSaveDriversJson.Add_Click({ diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1 index 24c9b5d..8d81a1d 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1 @@ -261,7 +261,9 @@ function Initialize-UIDefaults { # Set initial state for Office panel visibility Update-OfficePanelVisibility -State $State - + + # Set initial state for Application panel visibility + Update-ApplicationPanelVisibility -State $State } function Initialize-DynamicUIElements { diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.psm1 index 08ed5cb..284ba3d 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.psm1 @@ -189,6 +189,46 @@ function Get-USBDrives { } } +# Function to manage the visibility of the application UI panels +function Update-ApplicationPanelVisibility { + param( + [PSCustomObject]$State, + [string]$TriggeringControlName # Optional: to know which control initiated the change + ) + + $installAppsChecked = $State.Controls.chkInstallApps.IsChecked + + # If the main 'Install Apps' is unchecked, everything below it gets hidden and reset. + if ($TriggeringControlName -eq 'chkInstallApps' -and -not $installAppsChecked) { + $State.Controls.chkInstallWingetApps.IsChecked = $false + $State.Controls.chkBringYourOwnApps.IsChecked = $false + $State.Controls.chkDefineAppsScriptVariables.IsChecked = $false + } + + $byoAppsChecked = $State.Controls.chkBringYourOwnApps.IsChecked + $wingetAppsChecked = $State.Controls.chkInstallWingetApps.IsChecked + $defineVarsChecked = $State.Controls.chkDefineAppsScriptVariables.IsChecked + + # Visibility of primary sub-options + $subOptionVisibility = if ($installAppsChecked) { 'Visible' } else { 'Collapsed' } + $State.Controls.applicationPathPanel.Visibility = $subOptionVisibility + $State.Controls.appListJsonPathPanel.Visibility = $subOptionVisibility + $State.Controls.chkInstallWingetApps.Visibility = $subOptionVisibility + $State.Controls.chkBringYourOwnApps.Visibility = $subOptionVisibility + $State.Controls.chkDefineAppsScriptVariables.Visibility = $subOptionVisibility + + # Visibility of panels dependent on sub-options + $State.Controls.byoApplicationPanel.Visibility = if ($installAppsChecked -and $byoAppsChecked) { 'Visible' } else { 'Collapsed' } + $State.Controls.wingetPanel.Visibility = if ($installAppsChecked -and $wingetAppsChecked) { 'Visible' } else { 'Collapsed' } + $State.Controls.appsScriptVariablesPanel.Visibility = if ($installAppsChecked -and $defineVarsChecked) { 'Visible' } else { 'Collapsed' } + + # Special handling for wingetSearchPanel, which is shown by another button. + # We only collapse it if its parent becomes invisible. + if (-not ($installAppsChecked -and $wingetAppsChecked)) { + $State.Controls.wingetSearchPanel.Visibility = 'Collapsed' + } +} + # Function to manage the state of the main "Install Apps" checkbox based on selections in Updates/Office function Update-InstallAppsState { param([PSCustomObject]$State)