From 9dd89136e8f512cf827c024f0870029ac322af00 Mon Sep 17 00:00:00 2001 From: Marterich <47688561+Marterich@users.noreply.github.com> Date: Tue, 15 Oct 2024 23:27:56 +0200 Subject: [PATCH] First Try at implementing a Compact Mode for the App page --- functions/public/Invoke-WPFButton.ps1 | 2 +- functions/public/Invoke-WPFUIApps.ps1 | 199 +++++++++++++++++++------- scripts/main.ps1 | 26 ++++ scripts/start.ps1 | 2 +- xaml/inputXML.xaml | 2 +- 5 files changed, 176 insertions(+), 55 deletions(-) diff --git a/functions/public/Invoke-WPFButton.ps1 b/functions/public/Invoke-WPFButton.ps1 index ee4d0421..522ed8b0 100644 --- a/functions/public/Invoke-WPFButton.ps1 +++ b/functions/public/Invoke-WPFButton.ps1 @@ -26,7 +26,7 @@ function Invoke-WPFButton { "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*"} + "WPFClearInstallSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFInstall*"; if ($sync.ShowOnlySelected -eq $true) {Show-OnlyCheckedApps -ItemsControl $sync.ItemsControl}} "WPFtweaksbutton" {Invoke-WPFtweaksbutton} "WPFOOSUbutton" {Invoke-WPFOOSU} "WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enable"} diff --git a/functions/public/Invoke-WPFUIApps.ps1 b/functions/public/Invoke-WPFUIApps.ps1 index 8abe89d9..7990fcbf 100644 --- a/functions/public/Invoke-WPFUIApps.ps1 +++ b/functions/public/Invoke-WPFUIApps.ps1 @@ -1,3 +1,22 @@ +function Collapse-AllCategories { + param( + [Parameter(Mandatory=$true)] + [System.Windows.Controls.ItemsControl]$ItemsControl + ) + $sync.Buttons | Where-Object {$_.Tag -like "CategoryToggleButton"} | ForEach-Object { + $_.IsChecked = $false + } +} +function Expand-AllCategories { + param( + [Parameter(Mandatory=$true)] + [System.Windows.Controls.ItemsControl]$ItemsControl + ) + $sync.Buttons | Where-Object {$_.Tag -like "CategoryToggleButton"} | ForEach-Object { + $_.IsChecked = $true + } +} + function Toggle-CategoryVisibility { param( [Parameter(Mandatory=$true)] @@ -7,15 +26,9 @@ function Toggle-CategoryVisibility { [Parameter(Mandatory=$true)] [bool]$isChecked ) - - $appsInCategory = $ItemsControl.Items | Where-Object { - if ($null -ne $_.Tag) { - $sync.configs.applicationsHashtable.$($_.Tag).Category -eq $Category - } - } - - foreach ($appEntry in $appsInCategory) { - $appEntry.Visibility = if ($isChecked) { + # Show or hide the category, based on if it was clicked or not + $ItemsControl.Items | Where-Object {($_.Tag -eq "CategoryWrapPanel_$Category")} | ForEach-Object { + $_.Visibility = if ($isChecked) { [Windows.Visibility]::Visible } else { [Windows.Visibility]::Collapsed @@ -30,28 +43,48 @@ function Search-AppsByNameOrDescription { [Parameter(Mandatory=$false)] [System.Windows.Controls.ItemsControl]$ItemsControl = $sync.ItemsControl ) - $Apps = $ItemsControl.Items if ([string]::IsNullOrWhiteSpace($SearchString)) { - $Apps | ForEach-Object { - if ($null -ne $_.Tag) { - $_.Visibility = 'Collapsed' - } else { - $_.Visibility = 'Visible' + # Reset all categories when a search is cleared + $sync.Buttons | Where-Object {$_.Tag -like "CategoryToggleButton"} | ForEach-Object { + $_.IsChecked = $false + } + + $ItemsControl.Items | ForEach-Object { + if ($_.Tag -like "CategoryWrapPanel_*") { + # Reset CategoryWrapPanel visibility + $_.Visibility = [Windows.Visibility]::Collapsed + # Reset Items visibility + $_.Children | ForEach-Object {$_.Visibility = [Windows.Visibility]::Visible} } - } - } else { - $Apps | ForEach-Object { - if ($null -ne $_.Tag) { - if ($sync.configs.applicationsHashtable.$($_.Tag).Content -like "*$SearchString*") { - $_.Visibility = 'Visible' - } else { - $_.Visibility = 'Collapsed' - } + else { + # Reset Rest (Category Label) visibility + $_.Visibility = [Windows.Visibility]::Visible } } } + else { + $ItemsControl.Items | ForEach-Object { + if ($_.Tag -like "CategoryWrapPanel_*") { + $_.Visibility = [Windows.Visibility]::Visible + # Search for Apps that match the search string + $_.Children | Foreach-Object { + if ($sync.configs.applicationsHashtable.$($_.Tag).Content -like "*$SearchString*") { + $_.Visibility = [Windows.Visibility]::Visible + } + else { + $_.Visibility = [Windows.Visibility]::Collapsed + } + } + } + else { + # Hide all Category Labels + $_.Visibility = [Windows.Visibility]::Collapsed + } + } + } } + function Show-OnlyCheckedApps { param ( [Parameter(Mandatory=$false)] @@ -63,19 +96,51 @@ function Show-OnlyCheckedApps { if (($false -eq $sync.ShowOnlySelected) -and ($appKeys.Count -eq 0)) { return } - $sync.ShowOnlySelected = -not $sync.ShowOnlySelected - if ($sync.ShowOnlySelected) { - $sync.Buttons.ShowSelectedAppsButton.Content = "Show All" - foreach ($item in $ItemsControl.Items) { - if ($appKeys -contains $item.Tag) { - $item.Visibility = [Windows.Visibility]::Visible - } else { - $item.Visibility = [Windows.Visibility]::Collapsed + $sync.ShowOnlySelected = -not $sync.ShowOnlySelected + if ($sync.ShowOnlySelected) { + $sync.Buttons | Where-Object {$_.Name -like "ShowSelectedAppsButton"} | ForEach-Object { + $_.Content = "Show All" + } + + $ItemsControl.Items | Foreach-Object { + # Search for App Container and set them to visible + if ($_.Tag -like "CategoryWrapPanel_*") { + $_.Visibility = [Windows.Visibility]::Visible + # Iterate through all the apps in the container and set them to visible if they are in the appKeys array + $_.Children | ForEach-Object { + if ($appKeys -contains $_.Tag) { + $_.Visibility = [Windows.Visibility]::Visible + } + else { + $_.Visibility = [Windows.Visibility]::Collapsed + } + } + } + else { + # Set all other items to collapsed + $_.Visibility = [Windows.Visibility]::Collapsed } } } else { - $sync.Buttons.ShowSelectedAppsButton.Content = "Show Selected" - $ItemsControl.Items | ForEach-Object { $_.Visibility = [Windows.Visibility]::Visible } + $sync.Buttons | Where-Object {$_.Name -like "ShowSelectedAppsButton"} | ForEach-Object { + $_.Content = "Show Selected" + } + # Reset all CategoryToggleButtons to unchecked + $sync.Buttons | Where-Object {$_.Tag -like "CategoryToggleButton"} | ForEach-Object { + $_.IsChecked = $false + } + $ItemsControl.Items | Foreach-Object { + # Reset App Containers to visible + if ($_.Tag -like "CategoryWrapPanel_*") { + $_.Visibility = [Windows.Visibility]::Collapsed + # Reset Apps to visible + $_.Children | ForEach-Object {$_.Visibility = [Windows.Visibility]::Visible} + } + else { + # Reset all other items to visible + $_.Visibility = [Windows.Visibility]::Visible + } + } } } function Invoke-WPFUIApps { @@ -157,9 +222,26 @@ function Invoke-WPFUIApps { $showSelectedAppsButton.Add_Click({ Show-OnlyCheckedApps -appKeys $sync.SelectedApps -ItemsControl $sync.ItemsControl }) - $sync.Buttons.ShowSelectedAppsButton = $showSelectedAppsButton + $sync.Buttons.Add($showSelectedAppsButton) + $null = $wrapPanelTop.Children.Add($showSelectedAppsButton) + $compactViewButton = New-Object Windows.Controls.Button + $compactViewButton.Name = "CompactViewButton" + $compactViewButton.Content = "Compact View" + $compactViewButton.Add_Click({ + $sync.CompactView = -not $sync.CompactView + Update-AppTileProperties + if ($sync.CompactView) { + Expand-AllCategories -ItemsControl $sync.ItemsControl + $this.Content = "Expanded View" + } + else { + Collapse-AllCategories -ItemsControl $sync.ItemsControl + $this.Content = "Compact View" + } + }) + $null = $wrapPanelTop.Children.Add($compactViewButton) [Windows.Controls.DockPanel]::SetDock($wrapPanelTop, [Windows.Controls.Dock]::Top) $null = $dockPanel.Children.Add($wrapPanelTop) return $dockPanel @@ -172,6 +254,7 @@ function Invoke-WPFUIApps { $scrollViewer.HorizontalAlignment = 'Stretch' $scrollViewer.VerticalAlignment = 'Stretch' $scrollViewer.CanContentScroll = $true + $scrollViewer.Margin = 0 $itemsControl = New-Object Windows.Controls.ItemsControl $itemsControl.HorizontalAlignment = 'Stretch' @@ -200,15 +283,18 @@ function Invoke-WPFUIApps { $toggleButton = New-Object Windows.Controls.Primitives.ToggleButton $toggleButton.Content = "$Category" + $toggleButton.Tag = "CategoryToggleButton" $toggleButton.Cursor = [System.Windows.Input.Cursors]::Hand $toggleButton.Style = $window.FindResource("CategoryToggleButtonStyle") - - - $toggleButton.Add_Click({ + $sync.Buttons.Add($toggleButton) + $toggleButton.Add_Checked({ # Clear the search bar when a category is clicked $sync.SearchBar.Text = "" Toggle-CategoryVisibility -Category $this.Content -ItemsControl $this.Parent -isChecked $this.IsChecked }) + $toggleButton.Add_Unchecked({ + Toggle-CategoryVisibility -Category $this.Content -ItemsControl $this.Parent -isChecked $this.IsChecked + }) $null = $ItemsControl.Items.Add($toggleButton) } @@ -235,8 +321,16 @@ function Invoke-WPFUIApps { $categories = $Apps.Values | Select-Object -ExpandProperty category -Unique | Sort-Object foreach ($category in $categories) { Add-Category -Category $category -ItemsControl $itemsControl + $wrapPanel = New-Object Windows.Controls.WrapPanel + $wrapPanel.Orientation = "Horizontal" + $wrapPanel.HorizontalAlignment = "Stretch" + $wrapPanel.VerticalAlignment = "Center" + $wrapPanel.Margin = New-Object Windows.Thickness(0, 0, 0, 20) + $wrapPanel.Visibility = [Windows.Visibility]::Collapsed + $wrapPanel.Tag = "CategoryWrapPanel_$category" + $null = $itemsControl.Items.Add($wrapPanel) $Apps.Keys | Where-Object { $Apps.$_.Category -eq $category } | Sort-Object | ForEach-Object { - New-AppEntry -ItemsControl $itemsControl -AppKey $_ -Hidden $true + New-AppEntry -WrapPanel $wrapPanel -AppKey $_ } } }) @@ -244,25 +338,23 @@ function Invoke-WPFUIApps { function New-AppEntry { param( - $ItemsControl, - $AppKey, - [bool]$Hidden + $WrapPanel, + $AppKey ) $App = $Apps.$AppKey # Create the outer Border for the application type $border = New-Object Windows.Controls.Border $border.BorderBrush = [Windows.Media.Brushes]::Gray - $border.BorderThickness = 1 + $border.SetResourceReference([Windows.Controls.Control]::BorderThicknessProperty, "AppTileBorderThickness") $border.CornerRadius = 5 - $border.Padding = New-Object Windows.Thickness(10) - $border.HorizontalAlignment = "Stretch" + $border.SetResourceReference([Windows.Controls.Control]::PaddingProperty, "AppTileMargins") + $border.SetResourceReference([Windows.Controls.Control]::WidthProperty, "AppTileWidth") $border.VerticalAlignment = "Top" - $border.Margin = New-Object Windows.Thickness(0, 10, 0, 0) + $border.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") $border.Cursor = [System.Windows.Input.Cursors]::Hand $border.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor") $border.Tag = $Appkey $border.ToolTip = $App.description - $border.Visibility = if ($Hidden) {[Windows.Visibility]::Collapsed} else {[Windows.Visibility]::Visible} $border.Add_MouseUp({ $childCheckbox = ($this.Child.Children | Where-Object {$_.Template.TargetType -eq [System.Windows.Controls.Checkbox]})[0] $childCheckBox.isChecked = -not $childCheckbox.IsChecked @@ -278,7 +370,7 @@ function Invoke-WPFUIApps { $checkBox.Background = "Transparent" $checkBox.HorizontalAlignment = "Left" $checkBox.VerticalAlignment = "Center" - $checkBox.Margin = New-Object Windows.Thickness(5, 0, 10, 0) + $checkBox.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") $checkBox.SetResourceReference([Windows.Controls.Control]::StyleProperty, "CollapsedCheckBoxStyle") $checkbox.Add_Checked({ Invoke-WPFSelectedLabelUpdate -type "Add" -checkbox $this @@ -310,16 +402,18 @@ function Invoke-WPFUIApps { $image.Clip.Rect = New-Object Windows.Rect(0, 0, $image.Width, $image.Height) $image.Clip.RadiusX = 5 $image.Clip.RadiusY = 5 + $image.SetResourceReference([Windows.Controls.Control]::VisibilityProperty, "AppTileCompactVisibility") $imageAndNamePanel.Children.Add($image) | Out-Null # Create the TextBlock for the application name $appName = New-Object Windows.Controls.TextBlock $appName.Text = $App.Content - $appName.FontSize = 16 + $appName.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "AppTileFontSize") $appName.FontWeight = [Windows.FontWeights]::Bold + $appName.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") $appName.VerticalAlignment = "Center" - $appName.Margin = New-Object Windows.Thickness(5, 0, 0, 0) + $appName.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") $appName.Background = "Transparent" $imageAndNamePanel.Children.Add($appName) | Out-Null @@ -335,7 +429,8 @@ function Invoke-WPFUIApps { $buttonPanel.Orientation = "Horizontal" $buttonPanel.HorizontalAlignment = "Right" $buttonPanel.VerticalAlignment = "Center" - $buttonPanel.Margin = New-Object Windows.Thickness(10, 0, 0, 0) + $buttonPanel.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") + $buttonPanel.SetResourceReference([Windows.Controls.Control]::VisibilityProperty, "AppTileCompactVisibility") [Windows.Controls.DockPanel]::SetDock($buttonPanel, [Windows.Controls.Dock]::Right) # Create the "Install" button @@ -417,7 +512,7 @@ function Invoke-WPFUIApps { $dockPanel.Children.Add($buttonPanel) | Out-Null # Add the border to the main items control in the grid - $itemsControl.Items.Add($border) | Out-Null + $wrapPanel.Children.Add($border) | Out-Null } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index f7d26b9d..bed342c4 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -195,6 +195,32 @@ Invoke-WPFRunspace -ScriptBlock { # Print the logo Invoke-WPFFormVariables +$sync.CompactView = $false +$sync.Form.Resources.AppTileWidth = [double]::NaN +$sync.Form.Resources.AppTileCompactVisibility = [Windows.Visibility]::Visible +$sync.Form.Resources.AppTileFontSize = [double]16 +$sync.Form.Resources.AppTileMargins = [Windows.Thickness]5 +$sync.Form.Resources.AppTileBorderThickness = [Windows.Thickness]0 +function Update-AppTileProperties { + if ($sync.CompactView -eq $true) { + $sync.Form.Resources.AppTileWidth = [double]::NaN + $sync.Form.Resources.AppTileCompactVisibility = [Windows.Visibility]::Collapsed + $sync.Form.Resources.AppTileFontSize = [double]12 + $sync.Form.Resources.AppTileMargins = [Windows.Thickness]2 + $sync.Form.Resources.AppTileBorderThickness = [Windows.Thickness]0 + } + else { + $sync.Form.Resources.AppTileWidth = $sync.ItemsControl.ActualWidth -20 + $sync.Form.Resources.AppTileCompactVisibility = [Windows.Visibility]::Visible + $sync.Form.Resources.AppTileFontSize = [double]16 + $sync.Form.Resources.AppTileMargins = [Windows.Thickness]5 + $sync.Form.Resources.AppTileBorderThickness = [Windows.Thickness]1 + } +} +# We need to update the app tile properties when the form is resized because to fill a WrapPanel update the width of the elemenmt manually (afaik) +$sync.Form.Add_SizeChanged({ + Update-AppTileProperties +}) # Progress bar in taskbaritem > Set-WinUtilProgressbar $sync["Form"].TaskbarItemInfo = New-Object System.Windows.Shell.TaskbarItemInfo diff --git a/scripts/start.ps1 b/scripts/start.ps1 index 1b6a9a57..37512ebf 100644 --- a/scripts/start.ps1 +++ b/scripts/start.ps1 @@ -37,7 +37,7 @@ $sync = [Hashtable]::Synchronized(@{}) $sync.PSScriptRoot = $PSScriptRoot $sync.version = "#{replaceme}" $sync.configs = @{} -$sync.Buttons = @{} +$sync.Buttons = [System.Collections.Generic.List[PSObject]]::new() $sync.ProcessRunning = $false $sync.selectedApps = [System.Collections.Generic.List[string]]::new() $sync.ShowOnlySeleced = $false diff --git a/xaml/inputXML.xaml b/xaml/inputXML.xaml index 0c79abcf..7b942aec 100644 --- a/xaml/inputXML.xaml +++ b/xaml/inputXML.xaml @@ -212,7 +212,7 @@