From 4402c5cf31640ae35980ad95adcd4d43607033a8 Mon Sep 17 00:00:00 2001 From: MyDrift Date: Sat, 27 Jul 2024 12:31:34 +0200 Subject: [PATCH 01/41] try1: apps panel --- Compile.ps1 | 2 +- scripts/main.ps1 | 179 +++++++++++++++++++++++++++++++++++++++++++++ xaml/inputXML.xaml | 3 +- 3 files changed, 181 insertions(+), 3 deletions(-) diff --git a/Compile.ps1 b/Compile.ps1 index e539947525..a50636fb11 100644 --- a/Compile.ps1 +++ b/Compile.ps1 @@ -108,7 +108,7 @@ $featuresXamlContent = Get-TabXaml "feature" Update-Progress "Adding: Xaml " 90 # Replace the placeholder in $inputXML with the content of inputApp.xaml -$xaml = $xaml -replace "{{InstallPanel_applications}}", $appXamlContent +#$xaml = $xaml -replace "{{InstallPanel_applications}}", $appXamlContent $xaml = $xaml -replace "{{InstallPanel_tweaks}}", $tweaksXamlContent $xaml = $xaml -replace "{{InstallPanel_features}}", $featuresXamlContent diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 248bf6055b..fa6d1320c5 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -83,6 +83,185 @@ try { Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed." } + + + + + +# Ensure we have a reference to the main window +$mainWindow = $sync["Form"] + +# Reference to the Grid named 'appspanel' +$appspanel = $mainWindow.FindName("appspanel") + +if ($appspanel -eq $null) { + throw "The Grid named 'appspanel' was not found in the main window." +} + +# Clear any existing children from the Grid +$appspanel.Children.Clear() +$appspanel.ColumnDefinitions.Clear() +$appspanel.RowDefinitions.Clear() + +# Set the number of columns +$columnCount = 5 + +# Create the required number of columns +for ($i = 0; $i -lt $columnCount; $i++) { + $colDef = New-Object System.Windows.Controls.ColumnDefinition + $colDef.Width = [System.Windows.GridLength]::new(1, [System.Windows.GridUnitType]::Star) + $appspanel.ColumnDefinitions.Add($colDef) +} + +# Create a single row (since all columns will be in the same row) +$rowDef = New-Object System.Windows.Controls.RowDefinition +$rowDef.Height = [System.Windows.GridLength]::Auto +$appspanel.RowDefinitions.Add($rowDef) + +# Create a StackPanel for each column +$columnPanels = @() +for ($i = 0; $i -lt $columnCount; $i++) { + $border = New-Object System.Windows.Controls.Border + $border.Margin = New-Object System.Windows.Thickness(10) + $border.BorderThickness = New-Object System.Windows.Thickness(1) + $border.BorderBrush = [System.Windows.Media.Brushes]::LightGray + + $stackPanel = New-Object System.Windows.Controls.StackPanel + $stackPanel.Orientation = "Vertical" + $border.Child = $stackPanel + + [System.Windows.Controls.Grid]::SetColumn($border, $i) + $appspanel.Children.Add($border) | Out-Null + + $columnPanels += $stackPanel +} + +# Group applications by category +$applicationsByCategory = @{} +foreach ($appName in $sync.configs.applications.PSObject.Properties.Name) { + $appInfo = $sync.configs.applications.$appName + if (-not $applicationsByCategory.ContainsKey($appInfo.Category)) { + $applicationsByCategory[$appInfo.Category] = @() + } + $applicationsByCategory[$appInfo.Category] += [PSCustomObject]@{ + Name = $appName + Info = $appInfo + } +} + +# Sort categories alphabetically +$sortedCategories = $applicationsByCategory.Keys | Sort-Object + +# Collect all applications in sorted order by category +$allApplications = @() +foreach ($category in $sortedCategories) { + $allApplications += [PSCustomObject]@{ + IsCategory = $true + Category = $category + App = $null + } + $allApplications += $applicationsByCategory[$category] | Sort-Object { $_.Info.Content } | ForEach-Object { + [PSCustomObject]@{ + IsCategory = $false + Category = $category + App = $_ + } + } +} + +# Flatten the applications list to maintain the correct order +$flatAppsList = @() +foreach ($categoryGroup in $allApplications) { + # Add a label for the category + if ($categoryGroup.IsCategory) { + $flatAppsList += $categoryGroup + } else { + # Add the applications + $flatAppsList += $categoryGroup + } +} + +# Calculate number of apps per column +$appsPerColumn = [math]::Ceiling($flatAppsList.Count / $columnCount) + +# Distribute the flat apps list evenly across columns +$columnApps = @(@(), @(), @(), @(), @()) # Initialize an array of arrays for columns + +$currentColumn = 0 +$currentCount = 0 + +foreach ($item in $flatAppsList) { + if ($currentCount -ge $appsPerColumn) { + $currentColumn++ + $currentCount = 0 + } + $columnApps[$currentColumn] += $item + $currentCount++ +} + +# Add applications to the respective columns +for ($i = 0; $i -lt $columnApps.Count; $i++) { + foreach ($item in $columnApps[$i]) { + if ($item.IsCategory) { + $categoryLabel = New-Object System.Windows.Controls.Label + $categoryLabel.Content = $item.Category + $categoryLabel.FontSize = 16 # Adjust the font size as needed + $categoryLabel.FontFamily = "Arial" # Adjust the font family as needed + $categoryLabel.Margin = New-Object System.Windows.Thickness(5, 10, 5, 5) + $columnPanels[$i].Children.Add($categoryLabel) | Out-Null + } else { + $appInfo = $item.App.Info + + # Create a new StackPanel for the app entry + $appStackPanel = New-Object System.Windows.Controls.StackPanel + $appStackPanel.Orientation = "Horizontal" + $appStackPanel.Margin = New-Object System.Windows.Thickness(2) # Reduced margin + + # Create a new CheckBox for the app install option + $checkBox = New-Object System.Windows.Controls.CheckBox + $checkBox.Name = $item.App.Name + $checkBox.Content = $appInfo.Content + $checkBox.ToolTip = $appInfo.Description + $checkBox.Margin = New-Object System.Windows.Thickness(0, 0, 2, 0) + + # Create a new Hyperlink for the app link + $hyperlink = New-Object System.Windows.Documents.Hyperlink + $hyperlink.Inlines.Add(" ?") + $hyperlink.NavigateUri = [Uri]$appInfo.Link + + # Attach the RequestNavigate event handler + if ($hyperlink -ne $null) { + $hyperlink.AddHandler([System.Windows.Documents.Hyperlink]::RequestNavigateEvent, + [System.Windows.Navigation.RequestNavigateEventHandler]{ + param($sender, $e) + [System.Diagnostics.Process]::Start("explorer.exe", $e.Uri.AbsoluteUri) | Out-Null + }) + } + + # Add the Hyperlink to a TextBlock + $hyperlinkBlock = New-Object System.Windows.Controls.TextBlock + $hyperlinkBlock.Inlines.Add($hyperlink) + $hyperlinkBlock.ToolTip = $appInfo.Link + $hyperlinkBlock.Margin = New-Object System.Windows.Thickness(0, 0, 0, 0) + + # Add elements to the app StackPanel + $appStackPanel.Children.Add($checkBox) | Out-Null + $appStackPanel.Children.Add($hyperlinkBlock) | Out-Null + + # Add the app StackPanel to the appropriate column StackPanel + $columnPanels[$i].Children.Add($appStackPanel) | Out-Null + } + } +} + + + + + + + + + #=========================================================================== # Store Form Objects In PowerShell #=========================================================================== diff --git a/xaml/inputXML.xaml b/xaml/inputXML.xaml index 3c0eaf8fb6..2385649e66 100644 --- a/xaml/inputXML.xaml +++ b/xaml/inputXML.xaml @@ -734,8 +734,7 @@ - - {{InstallPanel_applications}} + From dfe7dc4044a89e7f61f7774c92d45d2edd5c8309 Mon Sep 17 00:00:00 2001 From: MyDrift Date: Wed, 31 Jul 2024 19:21:45 +0200 Subject: [PATCH 02/41] refractor - removed Get-TabXaml.ps1 - removed compilation part from compile.ps1 - removed existing changes from main.ps1 - added Invoke-WinUtilUIElements.ps1 - refractor existing changes into new function - modified inputXML to call function --- Compile.ps1 | 9 - functions/private/Get-TabXaml.ps1 | 217 -------------- .../private/Invoke-WinUtilUIElements.ps1 | 283 ++++++++++++++++++ scripts/main.ps1 | 180 +---------- xaml/inputXML.xaml | 7 +- 5 files changed, 290 insertions(+), 406 deletions(-) delete mode 100644 functions/private/Get-TabXaml.ps1 create mode 100644 functions/private/Invoke-WinUtilUIElements.ps1 diff --git a/Compile.ps1 b/Compile.ps1 index a50636fb11..39567cf900 100644 --- a/Compile.ps1 +++ b/Compile.ps1 @@ -97,15 +97,6 @@ Get-ChildItem .\config | Where-Object {$psitem.extension -eq ".json"} | ForEach- $xaml = (Get-Content .\xaml\inputXML.xaml).replace("'","''") -# Dot-source the Get-TabXaml function -. .\functions\private\Get-TabXaml.ps1 - -Update-Progress "Building: Xaml " 75 -$appXamlContent = Get-TabXaml "applications" 5 -$tweaksXamlContent = Get-TabXaml "tweaks" -$featuresXamlContent = Get-TabXaml "feature" - - Update-Progress "Adding: Xaml " 90 # Replace the placeholder in $inputXML with the content of inputApp.xaml #$xaml = $xaml -replace "{{InstallPanel_applications}}", $appXamlContent diff --git a/functions/private/Get-TabXaml.ps1 b/functions/private/Get-TabXaml.ps1 deleted file mode 100644 index 231af7af39..0000000000 --- a/functions/private/Get-TabXaml.ps1 +++ /dev/null @@ -1,217 +0,0 @@ -function Get-TabXaml { - <# - .SYNOPSIS - Generates XAML for a tab in the WinUtil GUI - This function is used to generate the XAML for the applications tab in the WinUtil GUI - It takes the tabname and the number of columns to display the applications in as input and returns the XAML for the tab as output - .PARAMETER tabname - The name of the tab to generate XAML for - Note: the 'tabname' parameter must equal one of the json files found in $sync.configs variable - Otherwise, it'll throw an exception - .PARAMETER columncount - The number of columns to display the applications in, default is 0 - .OUTPUTS - The XAML for the tab - .EXAMPLE - Get-TabXaml "applications" 3 - #> - - - param( - [Parameter(Mandatory, position=0)] - [string]$tabname, - - [Parameter(position=1)] - [ValidateRange(0,10)] # 10 panels as max number is more then enough - [int]$columncount = 0 - ) - - # Validate tabname - if ($sync.configs.$tabname -eq $null) { - throw "Invalid parameter passed, can't find '$tabname' in '`$sync.configs' variable, please double check any calls to 'Get-TabXaml' function." - } - - $organizedData = @{} - # Iterate through JSON data and organize by panel and category - foreach ($appName in $sync.configs.$tabname.PSObject.Properties.Name) { - $appInfo = $sync.configs.$tabname.$appName - - # Create an object for the application - $appObject = [PSCustomObject]@{ - Name = $appName - Category = $appInfo.Category - Content = $appInfo.Content - Choco = $appInfo.choco - Winget = $appInfo.winget - Panel = if ($columncount -gt 0 ) { "0" } else {$appInfo.panel} - Link = $appInfo.link - Description = $appInfo.description - # Type is (Checkbox,Toggle,Button,Combobox ) (Default is Checkbox) - Type = $appInfo.type - ComboItems = $appInfo.ComboItems - # Checked is the property to set startup checked status of checkbox (Default is false) - Checked = $appInfo.Checked - ButtonWidth = $appInfo.ButtonWidth - } - - if (-not $organizedData.ContainsKey($appObject.panel)) { - $organizedData[$appObject.panel] = @{} - } - - if (-not $organizedData[$appObject.panel].ContainsKey($appObject.Category)) { - $organizedData[$appObject.panel][$appObject.Category] = @{} - } - - # Store application data in a sub-array under the category - # Add Order property to keep the original order of tweaks and features - $organizedData[$appObject.panel][$appInfo.Category]["$($appInfo.order)$appName"] = $appObject - } - - # Same tab amount in last line of 'inputXML.xaml' file - # TODO: Get the base repeat (amount) of tabs from last line (or even lines) - # so it can dynamicly react to whatever is before this generated XML string. - # .. may be solve this even before calling this function, and pass the result as a parameter? - $tab_repeat = 7 - $spaces_per_tab = 4 # The convenction used across the code base - $tab_as_spaces = $(" " * $spaces_per_tab) - $precal_indent = $($tab_as_spaces * $tab_repeat) - $precal_indent_p1 = $($tab_as_spaces * ($tab_repeat + 1)) - $precal_indent_p2 = $($tab_as_spaces * ($tab_repeat + 2)) - $precal_indent_m1 = $($tab_as_spaces * ($tab_repeat - 1)) - $precal_indent_m2 = $($tab_as_spaces * ($tab_repeat - 2)) - - # Calculate the needed number of panels - $panelcount = 0 - $paneltotal = $organizedData.Keys.Count - if ($columncount -gt 0) { - $appcount = $sync.configs.$tabname.PSObject.Properties.Name.count + $organizedData["0"].Keys.count - $maxcount = [Math]::Round( $appcount / $columncount + 0.5) - $paneltotal = $columncount - } - # add ColumnDefinitions to evenly draw colums - $blockXml = "" - $blockXml += $("`r`n" + " " * ($spaces_per_tab * $tab_repeat) + - "") * $paneltotal - $blockXml += $("`r`n" + " " * ($spaces_per_tab * ($tab_repeat - 1))) + - "" + "`r`n" - - # Iterate through 'organizedData' by panel, category, and application - $count = 0 - foreach ($panel in ($organizedData.Keys | Sort-Object)) { - $blockXml += $precal_indent_m1 + "" + "`r`n" - $blockXml += $precal_indent + "" + "`r`n" - $panelcount++ - foreach ($category in ($organizedData[$panel].Keys | Sort-Object)) { - $count++ - if ($columncount -gt 0) { - $panelcount2 = [Int](($count)/$maxcount-0.5) - if ($panelcount -eq $panelcount2 ) { - $blockXml += $precal_indent_p2 + "" + "`r`n" - $blockXml += $precal_indent_p1 + "" + "`r`n" - $blockXml += $precal_indent_p1 + "" + "`r`n" - $blockXml += $precal_indent_p2 + "" + "`r`n" - $panelcount++ - } - } - - # Dot-source the Get-WPFObjectName function - . .\functions\private\Get-WPFObjectName - - $categorycontent = $($category -replace '^.__', '') - $categoryname = Get-WPFObjectName -type "Label" -name $categorycontent - $blockXml += $("`r`n" + " " * ($spaces_per_tab * $tab_repeat)) + - "" + "`r`n" - $blockXml += $precal_indent_m2 + - "" + "`r`n" - $blockXml += $precal_indent_m2 + - "" + "`r`n" - $blockXml += $precal_indent_m1 + - "" + "`r`n" - $panelcount++ - } - } - - $appInfo = $organizedData[$panel][$category][$appName] - switch ($appInfo.Type) { - "Toggle" { - $blockXml += $precal_indent_m1 + - "" + "`r`n" - $blockXml += $precal_indent + - "" + "`r`n" - $blockXml += $precal_indent + - "" + "`r`n" - } - - "Combobox" { - $blockXml += $precal_indent_m1 + - "" + "`r`n" - $blockXml += $precal_indent + "" + "`r`n" - } - - "Button" { - if ($appInfo.ButtonWidth -ne $null) { - $ButtonWidthStr = "Width=""$($appInfo.ButtonWidth)""" - } - $blockXml += $precal_indent + - "