From cf2f74140874acffb6fde402bb3ff9c925d318f3 Mon Sep 17 00:00:00 2001 From: Marterich <47688561+Marterich@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:53:03 +0100 Subject: [PATCH] Split up the functions to seperate files like the rest of the repo --- .../private/Add-SelectedAppsMenuItem.ps1 | 50 ++ .../private/Find-AppsByNameOrDescription.ps1 | 35 ++ .../private/Initalize-InstallAppEntry.ps1 | 197 +++++++ .../private/Initialize-AppStackPanel.ps1 | 26 + .../private/Initialize-InstallAppArea.ps1 | 36 ++ .../Initialize-InstallCategoryAppList.ps1 | 72 +++ .../private/Initialize-InstallHeader.ps1 | 92 ++++ functions/private/Set-CategoryVisibility.ps1 | 44 ++ functions/private/Show-OnlyCheckedApps.ps1 | 54 ++ functions/public/Invoke-WPFButton.ps1 | 3 +- functions/public/Invoke-WPFGetInstalled.ps1 | 2 +- .../public/Invoke-WPFSelectedAppsUpdate.ps1 | 49 -- functions/public/Invoke-WPFUIApps.ps1 | 519 +----------------- scripts/main.ps1 | 6 +- 14 files changed, 614 insertions(+), 571 deletions(-) create mode 100644 functions/private/Add-SelectedAppsMenuItem.ps1 create mode 100644 functions/private/Find-AppsByNameOrDescription.ps1 create mode 100644 functions/private/Initalize-InstallAppEntry.ps1 create mode 100644 functions/private/Initialize-AppStackPanel.ps1 create mode 100644 functions/private/Initialize-InstallAppArea.ps1 create mode 100644 functions/private/Initialize-InstallCategoryAppList.ps1 create mode 100644 functions/private/Initialize-InstallHeader.ps1 create mode 100644 functions/private/Set-CategoryVisibility.ps1 create mode 100644 functions/private/Show-OnlyCheckedApps.ps1 diff --git a/functions/private/Add-SelectedAppsMenuItem.ps1 b/functions/private/Add-SelectedAppsMenuItem.ps1 new file mode 100644 index 00000000..58183792 --- /dev/null +++ b/functions/private/Add-SelectedAppsMenuItem.ps1 @@ -0,0 +1,50 @@ + function Add-SelectedAppsMenuItem { + <# + .SYNOPSIS + This is a helper function that generates and adds the Menu Items to the Selected Apps Popup. + + .Parameter name + The actual Name of an App like "Chrome" or "Brave" + This name is contained in the "Content" property inside the applications.json + .PARAMETER key + The key which identifies an app object in applications.json + For Chrome this would be "WPFInstallchrome" because "WPFInstall" is prepended automatically for each key in applications.json + #> + + param ([string]$name, [string]$key) + + $selectedAppGrid = New-Object Windows.Controls.Grid + + $selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "*"})) + $selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "30"})) + + # Sets the name to the Content as well as the Tooltip, because the parent Popup Border has a fixed width and text could "overflow". + # With the tooltip, you can still read the whole entry on hover + $selectedAppLabel = New-Object Windows.Controls.Label + $selectedAppLabel.Content = $name + $selectedAppLabel.ToolTip = $name + $selectedAppLabel.HorizontalAlignment = "Left" + $selectedAppLabel.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + [System.Windows.Controls.Grid]::SetColumn($selectedAppLabel, 0) + $selectedAppGrid.Children.Add($selectedAppLabel) + + $selectedAppRemoveButton = New-Object Windows.Controls.Button + $selectedAppRemoveButton.FontFamily = "Segoe MDL2 Assets" + $selectedAppRemoveButton.Content = [string]([char]0xE711) + $selectedAppRemoveButton.HorizontalAlignment = "Center" + $selectedAppRemoveButton.Tag = $key + $selectedAppRemoveButton.ToolTip = "Remove the App from Selection" + $selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::StyleProperty, "HoverButtonStyle") + + # Highlight the Remove icon on Hover + $selectedAppRemoveButton.Add_MouseEnter({ $this.Foreground = "Red" }) + $selectedAppRemoveButton.Add_MouseLeave({ $this.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") }) + $selectedAppRemoveButton.Add_Click({ + $sync.($this.Tag).isChecked = $false # On click of the remove button, we only have to uncheck the corresponding checkbox. This will kick of all neccessary changes to update the UI + }) + [System.Windows.Controls.Grid]::SetColumn($selectedAppRemoveButton, 1) + $selectedAppGrid.Children.Add($selectedAppRemoveButton) + # Add new Element to Popup + $sync.selectedAppsstackPanel.Children.Add($selectedAppGrid) + } \ No newline at end of file diff --git a/functions/private/Find-AppsByNameOrDescription.ps1 b/functions/private/Find-AppsByNameOrDescription.ps1 new file mode 100644 index 00000000..21b777ac --- /dev/null +++ b/functions/private/Find-AppsByNameOrDescription.ps1 @@ -0,0 +1,35 @@ +function Find-AppsByNameOrDescription { + <# + .SYNOPSIS + Searches through the Apps on the Install Tab and hides all entries that do not match the string + + .PARAMETER SearchString + The string to be searched for + #> + param( + [Parameter(Mandatory=$false)] + [string]$SearchString = "" + ) + # Reset the visibility if the search string is empty or the search is cleared + if ([string]::IsNullOrWhiteSpace($SearchString)) { + Set-CategoryVisibility -Category "*" + return + } + $sync.ItemsControl.Items | ForEach-Object { + # Hide all CategoryWrapPanel and ToggleButton + $_.Visibility = [Windows.Visibility]::Collapsed + if ($_.Tag -like "CategoryWrapPanel_*") { + # Search for Apps that match the search string + $_.Children | Foreach-Object { + if ($sync.configs.applicationsHashtable.$($_.Tag).Content -like "*$SearchString*") { + # Show the App and the parent CategoryWrapPanel if the string is found + $_.Visibility = [Windows.Visibility]::Visible + $_.parent.Visibility = [Windows.Visibility]::Visible + } + else { + $_.Visibility = [Windows.Visibility]::Collapsed + } + } + } + } +} \ No newline at end of file diff --git a/functions/private/Initalize-InstallAppEntry.ps1 b/functions/private/Initalize-InstallAppEntry.ps1 new file mode 100644 index 00000000..8ac1379f --- /dev/null +++ b/functions/private/Initalize-InstallAppEntry.ps1 @@ -0,0 +1,197 @@ +function Initialize-InstallAppEntry { + <# + .SYNOPSIS + Creates the app entry to be placed on the isntall tab for a given app + Used to as part of the Install Tab UI generation + .PARAMETER TargetElement + The Element into which the Apps should be placed + .PARAMETER AppKey + The Key of the app inside the $sync.configs.applicationsHashtable + #> + param( + [Windows.Controls.WrapPanel]$TargetElement, + $AppKey + ) + $App = $sync.configs.applicationsHashtable.$AppKey + # Create the outer Border for the application type + $border = New-Object Windows.Controls.Border + $border.BorderBrush = [Windows.Media.Brushes]::Gray + $border.SetResourceReference([Windows.Controls.Control]::BorderThicknessProperty, "AppTileBorderThickness") + $border.CornerRadius = 5 + $border.SetResourceReference([Windows.Controls.Control]::PaddingProperty, "AppTileMargins") + $border.SetResourceReference([Windows.Controls.Control]::WidthProperty, "AppTileWidth") + $border.VerticalAlignment = "Top" + $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.Add_MouseUp({ + $childCheckbox = ($this.Child.Children | Where-Object {$_.Template.TargetType -eq [System.Windows.Controls.Checkbox]})[0] + $childCheckBox.isChecked = -not $childCheckbox.IsChecked + }) + $border.Add_MouseEnter({ + if (($sync.$($this.Tag).IsChecked) -eq $false) { + $this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallHighlightedColor") + } + }) + $border.Add_MouseLeave({ + if (($sync.$($this.Tag).IsChecked) -eq $false) { + $this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor") + } + }) + # Create a DockPanel inside the Border + $dockPanel = New-Object Windows.Controls.DockPanel + $dockPanel.LastChildFill = $true + $border.Child = $dockPanel + + # Create the CheckBox, vertically centered + $checkBox = New-Object Windows.Controls.CheckBox + $checkBox.Name = $AppKey + $checkBox.Background = "Transparent" + $checkBox.HorizontalAlignment = "Left" + $checkBox.VerticalAlignment = "Center" + $checkBox.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") + $checkBox.SetResourceReference([Windows.Controls.Control]::StyleProperty, "CollapsedCheckBoxStyle") + $checkbox.Add_Checked({ + Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $this + $borderElement = $this.Parent.Parent + $borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallSelectedColor") + }) + + $checkbox.Add_Unchecked({ + Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this + $borderElement = $this.Parent.Parent + $borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor") + }) + $sync.$($checkBox.Name) = $checkBox + # Create a StackPanel for the image and name + $imageAndNamePanel = New-Object Windows.Controls.StackPanel + $imageAndNamePanel.Orientation = "Horizontal" + $imageAndNamePanel.VerticalAlignment = "Center" + + # Create the Image and set a placeholder + $image = New-Object Windows.Controls.Image + # $image.Name = "wpfapplogo" + $App.Name + $image.Width = 40 + $image.Height = 40 + $image.Margin = New-Object Windows.Thickness(0, 0, 10, 0) + $image.Source = $noimage # Ensure $noimage is defined in your script + + # Clip the image corners + $image.Clip = New-Object Windows.Media.RectangleGeometry + $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.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "AppTileFontSize") + $appName.FontWeight = [Windows.FontWeights]::Bold + $appName.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $appName.VerticalAlignment = "Center" + $appName.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") + $appName.Background = "Transparent" + $imageAndNamePanel.Children.Add($appName) | Out-Null + + # Add the image and name panel to the Checkbox + $checkBox.Content = $imageAndNamePanel + + # Add the checkbox to the DockPanel + [Windows.Controls.DockPanel]::SetDock($checkBox, [Windows.Controls.Dock]::Left) + $dockPanel.Children.Add($checkBox) | Out-Null + + # Create the StackPanel for the buttons and dock it to the right + $buttonPanel = New-Object Windows.Controls.StackPanel + $buttonPanel.Orientation = "Horizontal" + $buttonPanel.HorizontalAlignment = "Right" + $buttonPanel.VerticalAlignment = "Center" + $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 + $installButton = New-Object Windows.Controls.Button + $installButton.Width = 45 + $installButton.Height = 35 + $installButton.Margin = New-Object Windows.Thickness(0, 0, 10, 0) + + $installIcon = New-Object Windows.Controls.TextBlock + $installIcon.Text = [char]0xE118 # Install Icon + $installIcon.FontFamily = "Segoe MDL2 Assets" + $installIcon.FontSize = 20 + $installIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $installIcon.Background = "Transparent" + $installIcon.HorizontalAlignment = "Center" + $installIcon.VerticalAlignment = "Center" + + $installButton.Content = $installIcon + $installButton.ToolTip = "Install or Upgrade the application" + $buttonPanel.Children.Add($installButton) | Out-Null + + # Add Click event for the "Install" button + $installButton.Add_Click({ + $appKey = $this.Parent.Parent.Parent.Tag + $appObject = $sync.configs.applicationsHashtable.$appKey + Invoke-WPFInstall -PackagesToInstall $appObject + }) + + # Create the "Uninstall" button + $uninstallButton = New-Object Windows.Controls.Button + $uninstallButton.Width = 45 + $uninstallButton.Height = 35 + + $uninstallIcon = New-Object Windows.Controls.TextBlock + $uninstallIcon.Text = [char]0xE74D # Uninstall Icon + $uninstallIcon.FontFamily = "Segoe MDL2 Assets" + $uninstallIcon.FontSize = 20 + $uninstallIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $uninstallIcon.Background = "Transparent" + $uninstallIcon.HorizontalAlignment = "Center" + $uninstallIcon.VerticalAlignment = "Center" + + $uninstallButton.Content = $uninstallIcon + $buttonPanel.Children.Add($uninstallButton) | Out-Null + + $uninstallButton.ToolTip = "Uninstall the application" + $uninstallButton.Add_Click({ + $appKey = $this.Parent.Parent.Parent.Tag + $appObject = $sync.configs.applicationsHashtable.$appKey + Invoke-WPFUnInstall -PackagesToUninstall $appObject + }) + + # Create the "Info" button + $infoButton = New-Object Windows.Controls.Button + $infoButton.Width = 45 + $infoButton.Height = 35 + $infoButton.Margin = New-Object Windows.Thickness(10, 0, 0, 0) + + $infoIcon = New-Object Windows.Controls.TextBlock + $infoIcon.Text = [char]0xE946 # Info Icon + $infoIcon.FontFamily = "Segoe MDL2 Assets" + $infoIcon.FontSize = 20 + $infoIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $infoIcon.Background = "Transparent" + $infoIcon.HorizontalAlignment = "Center" + $infoIcon.VerticalAlignment = "Center" + + $infoButton.Content = $infoIcon + $infoButton.ToolTip = "Open the application's website in your default browser" + $buttonPanel.Children.Add($infoButton) | Out-Null + + $infoButton.Add_Click({ + $appKey = $this.Parent.Parent.Parent.Tag + $appObject = $sync.configs.applicationsHashtable.$appKey + Start-Process $appObject.link + }) + + # Add the button panel to the DockPanel + $dockPanel.Children.Add($buttonPanel) | Out-Null + + # Add the border to the corresponding Category + $TargetElement.Children.Add($border) | Out-Null + } \ No newline at end of file diff --git a/functions/private/Initialize-AppStackPanel.ps1 b/functions/private/Initialize-AppStackPanel.ps1 new file mode 100644 index 00000000..0e2dd313 --- /dev/null +++ b/functions/private/Initialize-AppStackPanel.ps1 @@ -0,0 +1,26 @@ +function Initialize-AppStackPanel { + <# + .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") + $StackPanel = New-Object Windows.Controls.StackPanel + $Border.Child = $StackPanel + $null = $targetGrid.Children.Add($Border) + + return $StackPanel +} \ No newline at end of file diff --git a/functions/private/Initialize-InstallAppArea.ps1 b/functions/private/Initialize-InstallAppArea.ps1 new file mode 100644 index 00000000..0e4650f0 --- /dev/null +++ b/functions/private/Initialize-InstallAppArea.ps1 @@ -0,0 +1,36 @@ + function Initialize-InstallAppArea { + <# + .SYNOPSIS + Creates a [Windows.Controls.ScrollViewer] containing a [Windows.Controls.ItemsControl] which is setup to use Virtualization to only load the visible elements for performance reasons. + This is used as the parent object for all category and app entries on the install tab + Used to as part of the Install Tab UI generation + + .PARAMETER TargetElement + The element to which the AppArea shoud be added + + #> + param($TargetElement) + $scrollViewer = New-Object Windows.Controls.ScrollViewer + $scrollViewer.VerticalScrollBarVisibility = 'Auto' + $scrollViewer.HorizontalAlignment = 'Stretch' + $scrollViewer.VerticalAlignment = 'Stretch' + $scrollViewer.CanContentScroll = $true + + $itemsControl = New-Object Windows.Controls.ItemsControl + $itemsControl.HorizontalAlignment = 'Stretch' + $itemsControl.VerticalAlignment = 'Stretch' + + $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) + return $itemsControl + } \ No newline at end of file diff --git a/functions/private/Initialize-InstallCategoryAppList.ps1 b/functions/private/Initialize-InstallCategoryAppList.ps1 new file mode 100644 index 00000000..4ab1b28e --- /dev/null +++ b/functions/private/Initialize-InstallCategoryAppList.ps1 @@ -0,0 +1,72 @@ +function Initialize-InstallCategoryAppList { + <# + .SYNOPSIS + Clears the Target Element and sets up a "Loading" message. This is done, because loading of all apps can take a bit of time in some scenarios + Iterates through all Categories and Apps and adds them to the UI + Used to as part of the Install Tab UI generation + .PARAMETER TargetElement + The Element into which the Categories and Apps should be placed + .PARAMETER Apps + The Hashtable of Apps to be added to the UI + The Categories are also extracted from the Apps Hashtable + + #> + param( + $TargetElement, + $Apps + ) + function Add-Category { + param( + [string]$Category, + [Windows.Controls.ItemsControl]$TargetElement + ) + + $toggleButton = New-Object Windows.Controls.Primitives.ToggleButton + $toggleButton.Content = "$Category" + $toggleButton.Tag = "CategoryToggleButton" + $toggleButton.Cursor = [System.Windows.Input.Cursors]::Hand + $toggleButton.SetResourceReference([Windows.Controls.Control]::StyleProperty, "CategoryToggleButtonStyle") + $sync.Buttons.Add($toggleButton) + $toggleButton.Add_Checked({ + # Clear the search bar when a category is clicked + $sync.SearchBar.Text = "" + Set-CategoryVisibility -Category $this.Content -overrideState Expand + }) + $toggleButton.Add_Unchecked({ + Set-CategoryVisibility -Category $this.Content -overrideState Collapse + }) + $null = $TargetElement.Items.Add($toggleButton) + } + + $loadingLabel = New-Object Windows.Controls.Label + $loadingLabel.Content = "Loading, please wait..." + $loadingLabel.HorizontalAlignment = "Center" + $loadingLabel.VerticalAlignment = "Center" + $loadingLabel.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading") + $loadingLabel.FontWeight = [Windows.FontWeights]::Bold + $loadingLabel.Foreground = [Windows.Media.Brushes]::Gray + $sync.LoadingLabel = $loadingLabel + + $TargetElement.Items.Clear() + $null = $TargetElement.Items.Add($sync.LoadingLabel) + # Use the Dispatcher to make sure the Loading message is shown before the logic loading the apps starts, and only is removed when the loading is complete and the apps are added to the UI + $TargetElement.Dispatcher.Invoke([System.Windows.Threading.DispatcherPriority]::Background, [action]{ + + $TargetElement.Items.Clear() # Remove the loading message + $categories = $Apps.Values | Select-Object -ExpandProperty category -Unique | Sort-Object + foreach ($category in $categories) { + Add-Category -Category $category -TargetElement $TargetElement + $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 = $TargetElement.Items.Add($wrapPanel) + $Apps.Keys | Where-Object { $Apps.$_.Category -eq $category } | Sort-Object | ForEach-Object { + Initialize-InstallAppEntry -TargetElement $wrapPanel -AppKey $_ + } + } + }) + } \ No newline at end of file diff --git a/functions/private/Initialize-InstallHeader.ps1 b/functions/private/Initialize-InstallHeader.ps1 new file mode 100644 index 00000000..9a37f24b --- /dev/null +++ b/functions/private/Initialize-InstallHeader.ps1 @@ -0,0 +1,92 @@ +function Initialize-InstallHeader { + <# + .SYNOPSIS + Creates the Multi Selection Header Elements on the Install Tab + Used to as part of the Install Tab UI generation + .PARAMETER TargetElement + The Parent Element into which the Header should be placed + #> + param($TargetElement) + $dockPanel = New-Object Windows.Controls.DockPanel + $TargetElement.Children.Add($dockPanel) + + function New-WPFButton { + param ( + [string]$Name, + [string]$Content + ) + $button = New-Object Windows.Controls.Button + $button.Name = $Name + $button.Content = $Content + $button.Margin = New-Object Windows.Thickness(2) + $button.HorizontalAlignment = "Stretch" + return $button + } + + $wrapPanelTop = New-Object Windows.Controls.WrapPanel + $wrapPanelTop.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "MainBackgroundColor") + $wrapPanelTop.HorizontalAlignment = "Left" + $wrapPanelTop.VerticalAlignment = "Top" + $wrapPanelTop.Orientation = "Horizontal" + $wrapPanelTop.SetResourceReference([Windows.Controls.Control]::MarginProperty, "TabContentMargin") + $buttonConfigs = @( + @{Name="WPFInstall"; Content="Install/Upgrade Selected"}, + @{Name="WPFInstallUpgrade"; Content="Upgrade All"}, + @{Name="WPFUninstall"; Content="Uninstall Selected"} + ) + + foreach ($config in $buttonConfigs) { + $button = New-WPFButton -Name $config.Name -Content $config.Content + $null = $wrapPanelTop.Children.Add($button) + $sync[$config.Name] = $button + } + + $selectedAppsButton = New-Object Windows.Controls.Button + $selectedAppsButton.Name = "WPFselectedAppsButton" + $selectedAppsButton.Content = "Selected Apps: 0" + $selectedAppsButton.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading") + $selectedAppsButton.SetResourceReference([Windows.Controls.Control]::MarginProperty, "TabContentMargin") + $selectedAppsButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $selectedAppsButton.HorizontalAlignment = "Center" + $selectedAppsButton.VerticalAlignment = "Center" + + $selectedAppsPopup = New-Object Windows.Controls.Primitives.Popup + $selectedAppsPopup.IsOpen = $false + $selectedAppsPopup.PlacementTarget = $selectedAppsButton + $selectedAppsPopup.Placement = [System.Windows.Controls.Primitives.PlacementMode]::Bottom + $selectedAppsPopup.AllowsTransparency = $true + + $selectedAppsBorder = New-Object Windows.Controls.Border + $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "MainBackgroundColor") + $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BorderBrushProperty, "MainForegroundColor") + $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BorderThicknessProperty, "ButtonBorderThickness") + $selectedAppsBorder.Width = 200 + $selectedAppsBorder.Padding = 5 + $selectedAppsPopup.Child = $selectedAppsBorder + $sync.selectedAppsPopup = $selectedAppsPopup + + $sync.selectedAppsstackPanel = New-Object Windows.Controls.StackPanel + $selectedAppsBorder.Child = $sync.selectedAppsstackPanel + + # Toggle selectedAppsPopup open/close with button + $selectedAppsButton.Add_Click({ + $sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen + }) + # Close selectedAppsPopup when mouse leaves both button and selectedAppsPopup + $selectedAppsButton.Add_MouseLeave({ + if (-not $sync.selectedAppsPopup.IsMouseOver) { + $sync.selectedAppsPopup.IsOpen = $false + } + }) + $selectedAppsPopup.Add_MouseLeave({ + if (-not $selectedAppsButton.IsMouseOver) { + $sync.selectedAppsPopup.IsOpen = $false + } + }) + + $null = $wrapPanelTop.Children.Add($selectedAppsButton) + $sync.$($selectedAppsButton.Name) = $selectedAppsButton + + [Windows.Controls.DockPanel]::SetDock($wrapPanelTop, [Windows.Controls.Dock]::Top) + $null = $dockPanel.Children.Add($wrapPanelTop) +} \ No newline at end of file diff --git a/functions/private/Set-CategoryVisibility.ps1 b/functions/private/Set-CategoryVisibility.ps1 new file mode 100644 index 00000000..2d2bdc93 --- /dev/null +++ b/functions/private/Set-CategoryVisibility.ps1 @@ -0,0 +1,44 @@ +function Set-CategoryVisibility { + <# + .SYNOPSIS + Used to expand or collapse categories and corresponding apps on the install tab + + .PARAMETER Category + Can eigther be a specific category name like "Browsers" OR "*" to affect all categories at once + + .PARAMETER overrideState + "Expand" => expands the corresponding elements + "Collapse" => collapses the corresponding elements + N/A => if compactView is active expand, otherwise collapse elements + #> + param( + [Parameter(Mandatory=$true)] + [string]$Category, + [ValidateSet("Expand", "Collapse")] + [string]$overrideState + ) + + switch ($overrideState){ + "Expand" {$state = $true} + "Collapse" {$state = $false} + default {$state = $sync.CompactView} + } + + # If all the Categories are affected, update the Checked state of the ToggleButtons. + # Otherwise, the state is not synced when toggling between the display modes + if ($category -eq "*") { + $items = $sync.ItemsControl.Items | Where-Object {($_.Tag -like "CategoryWrapPanel_*")} + $sync.ItemsControl.Items | Where-Object {($_.Tag -eq "CategoryToggleButton")} | Foreach-Object { $_.Visibility = [Windows.Visibility]::Visible; $_.IsChecked = $state } + + } else { + $items = $sync.ItemsControl.Items | Where-Object {($_.Tag -eq "CategoryWrapPanel_$Category")} + } + + $elementVisibility = if ($state -eq $true) {[Windows.Visibility]::Visible} else {[Windows.Visibility]::Collapsed} + $items | ForEach-Object { + $_.Visibility = $elementVisibility + } + $items.Children | ForEach-Object { + $_.Visibility = $elementVisibility + } +} \ No newline at end of file diff --git a/functions/private/Show-OnlyCheckedApps.ps1 b/functions/private/Show-OnlyCheckedApps.ps1 new file mode 100644 index 00000000..55dc2fb3 --- /dev/null +++ b/functions/private/Show-OnlyCheckedApps.ps1 @@ -0,0 +1,54 @@ +function Show-OnlyCheckedApps { + <# + .SYNOPSIS + Toggle between showing only the actively selected apps on the Install Tab and hiding everything else and displaying every app. + If no apps are selected, dont do anything + .PARAMETER appKeys + Expects a List of appKeys that are selected at the moment + If not provided, or empty, the function exits without any visual change to the ui + .EXAMPLE + Show-OnlyCheckedApps -appKeys $sync.SelectedApps + Show-OnlyCheckedApps -appKeys ("WPFInstallChrome", "WPFInstall7zip") + #> + param ( + [Parameter(Mandatory=$false)] + [String[]]$appKeys + ) + # If no apps are selected, do not allow switching to show only selected + if (($false -eq $sync.ShowOnlySelected) -and ($appKeys.Length -eq 0)) { + Write-Host "No apps selected" + $sync.wpfselectedfilter.IsChecked = $false + return + } + $sync.ShowOnlySelected = -not $sync.ShowOnlySelected + if ($sync.ShowOnlySelected) { + $sync.Buttons | Where-Object {$_.Name -like "ShowSelectedAppsButton"} | ForEach-Object { + $_.Content = "Show All" + } + + $sync.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 | Where-Object {$_.Name -like "ShowSelectedAppsButton"} | ForEach-Object { + $_.Content = "Show Selected" + } + Set-CategoryVisibility -Category "*" + } +} \ No newline at end of file diff --git a/functions/public/Invoke-WPFButton.ps1 b/functions/public/Invoke-WPFButton.ps1 index 4ff0e06e..5007fac2 100644 --- a/functions/public/Invoke-WPFButton.ps1 +++ b/functions/public/Invoke-WPFButton.ps1 @@ -26,7 +26,8 @@ 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*"; if ($sync.ShowOnlySelected -eq $true) {Show-OnlyCheckedApps -ItemsControl $sync.ItemsControl}; $sync.wpfselectedfilter.IsChecked = $false} + "WPFClearInstallSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFInstall*"; Show-OnlyCheckedApps; $sync.wpfselectedfilter.IsChecked = $false} + "WPFSelectedFilter" {Show-OnlyCheckedApps -appKeys $sync.SelectedApps} "WPFtweaksbutton" {Invoke-WPFtweaksbutton} "WPFOOSUbutton" {Invoke-WPFOOSU} "WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enable"} diff --git a/functions/public/Invoke-WPFGetInstalled.ps1 b/functions/public/Invoke-WPFGetInstalled.ps1 index 53daaab3..d22b1674 100644 --- a/functions/public/Invoke-WPFGetInstalled.ps1 +++ b/functions/public/Invoke-WPFGetInstalled.ps1 @@ -48,7 +48,7 @@ function Invoke-WPFGetInstalled { } }) $sync.ItemsControl.Dispatcher.Invoke([action] { - $ShowOnlyCheckedApps.Invoke($sync.SelectedApps, $sync.ItemsControl) + $ShowOnlyCheckedApps.Invoke($sync.SelectedApps) $sync.ItemsControl.Items.Remove($sync.LoadingLabel) }) Write-Host "Done..." diff --git a/functions/public/Invoke-WPFSelectedAppsUpdate.ps1 b/functions/public/Invoke-WPFSelectedAppsUpdate.ps1 index 25c8245b..de60912f 100644 --- a/functions/public/Invoke-WPFSelectedAppsUpdate.ps1 +++ b/functions/public/Invoke-WPFSelectedAppsUpdate.ps1 @@ -17,56 +17,7 @@ function Invoke-WPFSelectedAppsUpdate { $type, $checkbox ) - function Add-SelectedAppsMenuItem { - <# - .SYNOPSIS - This is a helper function that generates and adds the Menu Items to the Selected Apps Popup. - - .Parameter name - The actual Name of an App like "Chrome" or "Brave" - This name is contained in the "Content" property inside the applications.json - .PARAMETER key - The key which identifies an app object in applications.json - For Chrome this would be "WPFInstallchrome" because "WPFInstall" is prepended automatically for each key in applications.json - #> - param ([string]$name, [string]$key) - - $selectedAppGrid = New-Object Windows.Controls.Grid - - $selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "*"})) - $selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "30"})) - - # Sets the name to the Content as well as the Tooltip, because the parent Popup Border has a fixed width and text could "overflow". - # With the tooltip, you can still read the whole entry on hover - $selectedAppLabel = New-Object Windows.Controls.Label - $selectedAppLabel.Content = $name - $selectedAppLabel.ToolTip = $name - $selectedAppLabel.HorizontalAlignment = "Left" - $selectedAppLabel.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") - [System.Windows.Controls.Grid]::SetColumn($selectedAppLabel, 0) - $selectedAppGrid.Children.Add($selectedAppLabel) - - $selectedAppRemoveButton = New-Object Windows.Controls.Button - $selectedAppRemoveButton.FontFamily = "Segoe MDL2 Assets" - $selectedAppRemoveButton.Content = [string]([char]0xE711) - $selectedAppRemoveButton.HorizontalAlignment = "Center" - $selectedAppRemoveButton.Tag = $key - $selectedAppRemoveButton.ToolTip = "Remove the App from Selection" - $selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") - $selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::StyleProperty, "HoverButtonStyle") - - # Highlight the Remove icon on Hover - $selectedAppRemoveButton.Add_MouseEnter({ $this.Foreground = "Red" }) - $selectedAppRemoveButton.Add_MouseLeave({ $this.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") }) - $selectedAppRemoveButton.Add_Click({ - $sync.($this.Tag).isChecked = $false # On click of the remove button, we only have to uncheck the corresponding checkbox. This will kick of all neccessary changes to update the UI - }) - [System.Windows.Controls.Grid]::SetColumn($selectedAppRemoveButton, 1) - $selectedAppGrid.Children.Add($selectedAppRemoveButton) - # Add new Element to Popup - $sync.selectedAppsstackPanel.Children.Add($selectedAppGrid) - } $selectedAppsButton = $sync.WPFselectedAppsButton # Get the actual Name from the selectedAppLabel inside the Checkbox $appKey = $checkbox.Parent.Parent.Tag diff --git a/functions/public/Invoke-WPFUIApps.ps1 b/functions/public/Invoke-WPFUIApps.ps1 index 22be82a9..aad96145 100644 --- a/functions/public/Invoke-WPFUIApps.ps1 +++ b/functions/public/Invoke-WPFUIApps.ps1 @@ -1,130 +1,3 @@ -function Set-CategoryVisibility { - param( - [Parameter(Mandatory=$true)] - [string]$Category, - [Parameter(Mandatory=$true)] - [System.Windows.Controls.ItemsControl]$ItemsControl, - [bool]$isChecked = $true, - [switch]$automaticVisibility - ) - if ($automaticVisibility) { - $isChecked = $sync.CompactView - } - - # If all the Categories are affected, update the Checked state of the ToggleButtons. - # Otherwise, the state is not synced when toggling between the display modes - if ($category -eq "*") { - $items = $ItemsControl.Items | Where-Object {($_.Tag -like "CategoryWrapPanel_*")} - $ItemsControl.Items | Where-Object {($_.Tag -eq "CategoryToggleButton")} | Foreach-Object { $_.Visibility = [Windows.Visibility]::Visible; $_.IsChecked = $isChecked } - } else { - $items = $ItemsControl.Items | Where-Object {($_.Tag -eq "CategoryWrapPanel_$Category")} - } - - $elementVisibility = if ($isChecked -eq $true) {[Windows.Visibility]::Visible} else {[Windows.Visibility]::Collapsed} - $items | ForEach-Object { - $_.Visibility = $elementVisibility - } - $items.Children | ForEach-Object { - $_.Visibility = $elementVisibility - } -} - -function Find-AppsByNameOrDescription { - param( - [Parameter(Mandatory=$false)] - [string]$SearchString = "", - [Parameter(Mandatory=$false)] - [System.Windows.Controls.ItemsControl]$ItemsControl = $sync.ItemsControl - ) - - if ([string]::IsNullOrWhiteSpace($SearchString)) { - Set-CategoryVisibility -Category "*" -ItemsControl $ItemsControl -automaticVisibility - - - $ItemsControl.Items | ForEach-Object { - if ($_.Tag -like "CategoryWrapPanel_*") { - # If CompactView is enabled, show all Apps when the search bar is empty - # otherwise, hide all Apps - if ($sync.CompactView -eq $true) { - $_.Visibility = [Windows.Visibility]::Visible - } else { - $_.Visibility = [Windows.Visibility]::Collapsed - } - # Reset Items visibility - $_.Children | ForEach-Object {$_.Visibility = [Windows.Visibility]::Visible} - } - else { - # Reset Rest (Category Label) visibility - $_.Visibility = [Windows.Visibility]::Visible - } - } - } else { - $ItemsControl.Items | ForEach-Object { - # Hide all CategoryWrapPanel and ToggleButton - $_.Visibility = [Windows.Visibility]::Collapsed - if ($_.Tag -like "CategoryWrapPanel_*") { - # Search for Apps that match the search string - $_.Children | Foreach-Object { - if ($sync.configs.applicationsHashtable.$($_.Tag).Content -like "*$SearchString*") { - # Show the App and the parent CategoryWrapPanel - $_.Visibility = [Windows.Visibility]::Visible - $_.parent.Visibility = [Windows.Visibility]::Visible - } - else { - $_.Visibility = [Windows.Visibility]::Collapsed - } - } - } - } - } -} - -function Show-OnlyCheckedApps { - param ( - [Parameter(Mandatory=$false)] - [String[]]$appKeys, - [Parameter(Mandatory=$true)] - [System.Windows.Controls.ItemsControl]$ItemsControl - ) - # If no apps are selected, do not allow switching to show only selected - if (($false -eq $sync.ShowOnlySelected) -and ($appKeys.Count -eq 0)) { - Write-Host "No apps selected" - $sync.wpfselectedfilter.IsChecked = $false - return - } - $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 | Where-Object {$_.Name -like "ShowSelectedAppsButton"} | ForEach-Object { - $_.Content = "Show Selected" - } - Set-CategoryVisibility -Category "*" -ItemsControl $ItemsControl -automaticVisibility - } -} - function Invoke-WPFUIApps { [OutputType([void])] param( @@ -134,396 +7,12 @@ function Invoke-WPFUIApps { [string]$TargetGridName ) - function Initialize-StackPanel { - $targetGrid = $window.FindName($TargetGridName) - $borderStyle = $window.FindResource("BorderStyle") - - $null = $targetGrid.Children.Clear() - - $mainBorder = New-Object Windows.Controls.Border - $mainBorder.VerticalAlignment = "Stretch" - $mainBorder.Style = $borderStyle - - $null = $targetGrid.Children.Add($mainBorder) - return $targetGrid - } - - function Initialize-Header { - param($TargetGrid) - $mainBorder = $TargetGrid.Children[0] - $dockPanel = New-Object Windows.Controls.DockPanel - $mainBorder.Child = $dockPanel - - function New-WPFButton { - param ( - [string]$Name, - [string]$Content - ) - $button = New-Object Windows.Controls.Button - $button.Name = $Name - $button.Content = $Content - $button.Margin = New-Object Windows.Thickness(2) - $button.HorizontalAlignment = "Stretch" - return $button - } - - $wrapPanelTop = New-Object Windows.Controls.WrapPanel - $wrapPanelTop.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "MainBackgroundColor") - $wrapPanelTop.HorizontalAlignment = "Left" - $wrapPanelTop.VerticalAlignment = "Top" - $wrapPanelTop.Orientation = "Horizontal" - $wrapPanelTop.Margin = $window.FindResource("TabContentMargin") - - $buttonConfigs = @( - @{Name="WPFInstall"; Content="Install/Upgrade Selected"}, - @{Name="WPFInstallUpgrade"; Content="Upgrade All"}, - @{Name="WPFUninstall"; Content="Uninstall Selected"} - ) - - foreach ($config in $buttonConfigs) { - $button = New-WPFButton -Name $config.Name -Content $config.Content - $null = $wrapPanelTop.Children.Add($button) - $sync[$config.Name] = $button - } - - $selectedAppsButton = New-Object Windows.Controls.Button - $selectedAppsButton.Name = "WPFselectedAppsButton" - $selectedAppsButton.Content = "Selected Apps: 0" - $selectedAppsButton.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading") - $selectedAppsButton.SetResourceReference([Windows.Controls.Control]::MarginProperty, "TabContentMargin") - $selectedAppsButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") - $selectedAppsButton.HorizontalAlignment = "Center" - $selectedAppsButton.VerticalAlignment = "Center" - - $selectedAppsPopup = New-Object Windows.Controls.Primitives.Popup - $selectedAppsPopup.IsOpen = $false - $selectedAppsPopup.PlacementTarget = $selectedAppsButton - $selectedAppsPopup.Placement = [System.Windows.Controls.Primitives.PlacementMode]::Bottom - $selectedAppsPopup.AllowsTransparency = $true - - $selectedAppsBorder = New-Object Windows.Controls.Border - $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "MainBackgroundColor") - $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BorderBrushProperty, "MainForegroundColor") - $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BorderThicknessProperty, "ButtonBorderThickness") - $selectedAppsBorder.Width = 200 - $selectedAppsBorder.Padding = 5 - $selectedAppsPopup.Child = $selectedAppsBorder - $sync.selectedAppsPopup = $selectedAppsPopup - - $sync.selectedAppsstackPanel = New-Object Windows.Controls.StackPanel - $selectedAppsBorder.Child = $sync.selectedAppsstackPanel - - # Toggle selectedAppsPopup open/close with button - $selectedAppsButton.Add_Click({ - $sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen - }) - # Close selectedAppsPopup when mouse leaves both button and selectedAppsPopup - $selectedAppsButton.Add_MouseLeave({ - if (-not $sync.selectedAppsPopup.IsMouseOver) { - $sync.selectedAppsPopup.IsOpen = $false - } - }) - $selectedAppsPopup.Add_MouseLeave({ - if (-not $selectedAppsButton.IsMouseOver) { - $sync.selectedAppsPopup.IsOpen = $false - } - }) - - $null = $wrapPanelTop.Children.Add($selectedAppsButton) - $sync.$($selectedAppsButton.Name) = $selectedAppsButton - - [Windows.Controls.DockPanel]::SetDock($wrapPanelTop, [Windows.Controls.Dock]::Top) - $null = $dockPanel.Children.Add($wrapPanelTop) - return $dockPanel - } - - function Initialize-AppArea { - param($TargetGrid) - $scrollViewer = New-Object Windows.Controls.ScrollViewer - $scrollViewer.VerticalScrollBarVisibility = 'Auto' - $scrollViewer.HorizontalAlignment = 'Stretch' - $scrollViewer.VerticalAlignment = 'Stretch' - $scrollViewer.CanContentScroll = $true - - $itemsControl = New-Object Windows.Controls.ItemsControl - $itemsControl.HorizontalAlignment = 'Stretch' - $itemsControl.VerticalAlignment = 'Stretch' - - $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 = $TargetGrid.Children.Add($scrollViewer) - return $itemsControl - } - - function Add-Category { - param( - [string]$Category, - $ItemsControl - ) - - $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") - $sync.Buttons.Add($toggleButton) - $toggleButton.Add_Checked({ - # Clear the search bar when a category is clicked - $sync.SearchBar.Text = "" - Set-CategoryVisibility -Category $this.Content -ItemsControl $this.Parent -isChecked $true - }) - $toggleButton.Add_Unchecked({ - Set-CategoryVisibility -Category $this.Content -ItemsControl $this.Parent -isChecked $false - }) - $null = $ItemsControl.Items.Add($toggleButton) - } - - function New-CategoryAppList { - param( - $TargetGrid, - $Apps - ) - $loadingLabel = New-Object Windows.Controls.Label - $loadingLabel.Content = "Loading, please wait..." - $loadingLabel.HorizontalAlignment = "Center" - $loadingLabel.VerticalAlignment = "Center" - $loadingLabel.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading") - $loadingLabel.FontWeight = [Windows.FontWeights]::Bold - $loadingLabel.Foreground = [Windows.Media.Brushes]::Gray - $sync.LoadingLabel = $loadingLabel - - $itemsControl.Items.Clear() - $null = $itemsControl.Items.Add($sync.LoadingLabel) - - $itemsControl.Dispatcher.Invoke([System.Windows.Threading.DispatcherPriority]::Background, [action]{ - $itemsControl.Items.Clear() - - $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 -WrapPanel $wrapPanel -AppKey $_ - } - } - }) - } - - function New-AppEntry { - param( - $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.SetResourceReference([Windows.Controls.Control]::BorderThicknessProperty, "AppTileBorderThickness") - $border.CornerRadius = 5 - $border.SetResourceReference([Windows.Controls.Control]::PaddingProperty, "AppTileMargins") - $border.SetResourceReference([Windows.Controls.Control]::WidthProperty, "AppTileWidth") - $border.VerticalAlignment = "Top" - $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.Add_MouseUp({ - $childCheckbox = ($this.Child.Children | Where-Object {$_.Template.TargetType -eq [System.Windows.Controls.Checkbox]})[0] - $childCheckBox.isChecked = -not $childCheckbox.IsChecked - }) - $border.Add_MouseEnter({ - if (($sync.$($this.Tag).IsChecked) -eq $false) { - $this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallHighlightedColor") - } - }) - $border.Add_MouseLeave({ - if (($sync.$($this.Tag).IsChecked) -eq $false) { - $this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor") - } - }) - # Create a DockPanel inside the Border - $dockPanel = New-Object Windows.Controls.DockPanel - $dockPanel.LastChildFill = $true - $border.Child = $dockPanel - - # Create the CheckBox, vertically centered - $checkBox = New-Object Windows.Controls.CheckBox - $checkBox.Name = $AppKey - $checkBox.Background = "Transparent" - $checkBox.HorizontalAlignment = "Left" - $checkBox.VerticalAlignment = "Center" - $checkBox.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") - $checkBox.SetResourceReference([Windows.Controls.Control]::StyleProperty, "CollapsedCheckBoxStyle") - $checkbox.Add_Checked({ - Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $this - $borderElement = $this.Parent.Parent - $borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallSelectedColor") - }) - - $checkbox.Add_Unchecked({ - Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this - $borderElement = $this.Parent.Parent - $borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor") - }) - $sync.$($checkBox.Name) = $checkBox - # Create a StackPanel for the image and name - $imageAndNamePanel = New-Object Windows.Controls.StackPanel - $imageAndNamePanel.Orientation = "Horizontal" - $imageAndNamePanel.VerticalAlignment = "Center" - - # Create the Image and set a placeholder - $image = New-Object Windows.Controls.Image - # $image.Name = "wpfapplogo" + $App.Name - $image.Width = 40 - $image.Height = 40 - $image.Margin = New-Object Windows.Thickness(0, 0, 10, 0) - $image.Source = $noimage # Ensure $noimage is defined in your script - - # Clip the image corners - $image.Clip = New-Object Windows.Media.RectangleGeometry - $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.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "AppTileFontSize") - $appName.FontWeight = [Windows.FontWeights]::Bold - $appName.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") - $appName.VerticalAlignment = "Center" - $appName.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") - $appName.Background = "Transparent" - $imageAndNamePanel.Children.Add($appName) | Out-Null - - # Add the image and name panel to the Checkbox - $checkBox.Content = $imageAndNamePanel - - # Add the checkbox to the DockPanel - [Windows.Controls.DockPanel]::SetDock($checkBox, [Windows.Controls.Dock]::Left) - $dockPanel.Children.Add($checkBox) | Out-Null - - # Create the StackPanel for the buttons and dock it to the right - $buttonPanel = New-Object Windows.Controls.StackPanel - $buttonPanel.Orientation = "Horizontal" - $buttonPanel.HorizontalAlignment = "Right" - $buttonPanel.VerticalAlignment = "Center" - $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 - $installButton = New-Object Windows.Controls.Button - $installButton.Width = 45 - $installButton.Height = 35 - $installButton.Margin = New-Object Windows.Thickness(0, 0, 10, 0) - - $installIcon = New-Object Windows.Controls.TextBlock - $installIcon.Text = [char]0xE118 # Install Icon - $installIcon.FontFamily = "Segoe MDL2 Assets" - $installIcon.FontSize = 20 - $installIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") - $installIcon.Background = "Transparent" - $installIcon.HorizontalAlignment = "Center" - $installIcon.VerticalAlignment = "Center" - - $installButton.Content = $installIcon - $installButton.ToolTip = "Install or Upgrade the application" - $buttonPanel.Children.Add($installButton) | Out-Null - - # Add Click event for the "Install" button - $installButton.Add_Click({ - $appKey = $this.Parent.Parent.Parent.Tag - $appObject = $sync.configs.applicationsHashtable.$appKey - Invoke-WPFInstall -PackagesToInstall $appObject - }) - - # Create the "Uninstall" button - $uninstallButton = New-Object Windows.Controls.Button - $uninstallButton.Width = 45 - $uninstallButton.Height = 35 - - $uninstallIcon = New-Object Windows.Controls.TextBlock - $uninstallIcon.Text = [char]0xE74D # Uninstall Icon - $uninstallIcon.FontFamily = "Segoe MDL2 Assets" - $uninstallIcon.FontSize = 20 - $uninstallIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") - $uninstallIcon.Background = "Transparent" - $uninstallIcon.HorizontalAlignment = "Center" - $uninstallIcon.VerticalAlignment = "Center" - - $uninstallButton.Content = $uninstallIcon - $buttonPanel.Children.Add($uninstallButton) | Out-Null - - $uninstallButton.ToolTip = "Uninstall the application" - $uninstallButton.Add_Click({ - $appKey = $this.Parent.Parent.Parent.Tag - $appObject = $sync.configs.applicationsHashtable.$appKey - Invoke-WPFUnInstall -PackagesToUninstall $appObject - }) - - # Create the "Info" button - $infoButton = New-Object Windows.Controls.Button - $infoButton.Width = 45 - $infoButton.Height = 35 - $infoButton.Margin = New-Object Windows.Thickness(10, 0, 0, 0) - - $infoIcon = New-Object Windows.Controls.TextBlock - $infoIcon.Text = [char]0xE946 # Info Icon - $infoIcon.FontFamily = "Segoe MDL2 Assets" - $infoIcon.FontSize = 20 - $infoIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") - $infoIcon.Background = "Transparent" - $infoIcon.HorizontalAlignment = "Center" - $infoIcon.VerticalAlignment = "Center" - - $infoButton.Content = $infoIcon - $infoButton.ToolTip = "Open the application's website in your default browser" - $buttonPanel.Children.Add($infoButton) | Out-Null - - $infoButton.Add_Click({ - $appKey = $this.Parent.Parent.Parent.Tag - $appObject = $sync.configs.applicationsHashtable.$appKey - Start-Process $appObject.link - }) - - # Add the button panel to the DockPanel - $dockPanel.Children.Add($buttonPanel) | Out-Null - - # Add the border to the main items control in the grid - $wrapPanel.Children.Add($border) | Out-Null - } - - - $window = $sync.Form - switch ($TargetGridName) { "appspanel" { - $targetGrid = Initialize-StackPanel - $dockPanelContainer = Initialize-Header -TargetGrid $targetGrid - $itemsControl = Initialize-AppArea -TargetGrid $dockPanelContainer - $sync.ItemsControl = $itemsControl - New-CategoryAppList -TargetGrid $itemsControl -Apps $Apps + $mainStackPanel = Initialize-AppStackPanel -TargetGridName $TargetGridName + $null = Initialize-InstallHeader -TargetElement $mainStackPanel + $sync.ItemsControl = Initialize-InstallAppArea -TargetElement $mainStackPanel + Initialize-InstallCategoryAppList -TargetElement $sync.ItemsControl -Apps $Apps } default { Write-Output "$TargetGridName not yet implemented" diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 3a2a55e6..54326bdc 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -127,13 +127,9 @@ $sync.WPFToggleView.Add_Click({ $sync.CompactView = -not $sync.CompactView Update-AppTileProperties if ($sync.SearchBar.Text -eq "") { - Set-CategoryVisibility -Category "*" -ItemsControl $sync.ItemsControl -automaticVisibility + Set-CategoryVisibility -Category "*" } }) -# Add logic to handle click to the Filter Button on the Install Tab -$sync.WPFSelectedFilter.Add_Click{( - Show-OnlyCheckedApps -appKeys $sync.SelectedApps -ItemsControl $sync.ItemsControl -)} Invoke-WPFUIApps -Apps $sync.configs.applicationsHashtable -targetGridName "appspanel" Invoke-WPFUIElements -configVariable $sync.configs.tweaks -targetGridName "tweakspanel" -columncount 2