Add search bar to tweak page (#440)

This commit is contained in:
Jeffrey
2026-02-02 21:54:40 +01:00
committed by GitHub
parent 1ef8992320
commit 6a1a091a87
2 changed files with 210 additions and 59 deletions

View File

@@ -212,7 +212,16 @@
<Style x:Key="LabelStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{DynamicResource FgColor}"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Margin" Value="0,0,0,3"/>
<Setter Property="Margin" Value="0,0,0,2"/>
</Style>
<!-- Label Border Style for ComboBox labels -->
<Style x:Key="LabelBorderStyle" TargetType="Border">
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="Padding" Value="6,2"/>
<Setter Property="Margin" Value="-4,-2,-4,0"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
<!-- Category card border style -->
@@ -221,7 +230,7 @@
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="Background" Value="{DynamicResource CardBgColor}"/>
<Setter Property="Padding" Value="16,12"/>
<Setter Property="Padding" Value="16,12,16,2"/>
<Setter Property="Margin" Value="0,0,0,16"/>
</Style>
@@ -268,7 +277,7 @@
<Border x:Name="CheckBoxBorder" Grid.Column="0" Width="18" Height="18" Background="{DynamicResource CheckBoxBgColor}" BorderBrush="{DynamicResource CheckBoxBorderColor}" BorderThickness="1" CornerRadius="4" Margin="0,0,8,0">
<TextBlock x:Name="CheckMark" Text="&#xE73E;" FontFamily="Segoe MDL2 Assets" FontSize="12" Foreground="{DynamicResource ButtonBg}" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed"/>
</Border>
<ContentPresenter Grid.Column="1" VerticalAlignment="Center" Margin="0,0,0,1"/>
<ContentPresenter Grid.Column="1" VerticalAlignment="Center" Margin="0,0,0,2"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
@@ -297,8 +306,8 @@
<!-- CheckBox style for feature toggles -->
<Style x:Key="FeatureCheckboxStyle" TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
<Setter Property="Margin" Value="0,0,0,10"/>
<Setter Property="Padding" Value="0,2"/>
<Setter Property="Margin" Value="-4,-2,-4,10"/>
<Setter Property="Padding" Value="4,2"/>
</Style>
<!-- CheckBox style for apps panels -->
@@ -608,17 +617,35 @@
<!-- Filter Options -->
<Grid Margin="0,0,0,12">
<StackPanel Orientation="Horizontal">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<Button x:Name="LoadDefaultsBtn" Content="Select Default Settings" ToolTip="Select the settings that are recommended for most people" Style="{StaticResource Win11ButtonSecondary}" Padding="10,0" Height="32" Margin="0,0,10,0" AutomationProperties.Name="Select Default Settings"/>
<Button x:Name="LoadLastUsedBtn" Content="Select Last Used Settings" ToolTip="Select the settings that were used the last time Win11Debloat was run" Style="{StaticResource Win11ButtonSecondary}" Padding="10,0" Height="32" Margin="0,0,10,0" AutomationProperties.Name="Select Last Used Settings"/>
<Button x:Name="ClearAllTweaksBtn" Content="Clear Selection" ToolTip="Clear all selected tweaks" Style="{StaticResource Win11ButtonSecondary}" Padding="10,0" Height="32" Margin="0,0,10,0" AutomationProperties.Name="Clear Selection"/>
</StackPanel>
<Border Grid.Column="2" BorderBrush="{DynamicResource ButtonBorderColor}" BorderThickness="1" CornerRadius="4" Background="{DynamicResource ComboBgColor}" Width="300" Padding="8,6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="&#xE721;" FontFamily="Segoe MDL2 Assets" FontSize="14" VerticalAlignment="Center" Margin="4,0,8,0" Foreground="{DynamicResource FgColor}"/>
<TextBlock x:Name="TweakSearchPlaceholder" Grid.Column="1" Text="Search setting" Foreground="{DynamicResource FgColor}" Opacity="0.5" FontSize="13" Margin="3,0,0,1" VerticalAlignment="Center" IsHitTestVisible="False"/>
<TextBox x:Name="TweakSearchBox" Grid.Column="1" Background="Transparent" Foreground="{DynamicResource FgColor}" BorderThickness="0" FontSize="13" Margin="1,0,0,1" VerticalAlignment="Center" Text=""/>
</Grid>
</Border>
</Grid>
</StackPanel>
</Border>
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="0,-20,0,0" Padding="20,10,20,0">
<Grid Margin="0,10,0,5">
<ScrollViewer x:Name="TweaksScrollViewer" VerticalScrollBarVisibility="Auto" Margin="0,-20,0,0" Padding="20,10,20,0">
<Grid x:Name="TweaksGrid" Margin="0,10,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>

View File

@@ -685,17 +685,25 @@ function OpenGUI {
}
# Otherwise use a combobox for multiple options
# Wrap label in a Border for search highlighting
$lblBorder = New-Object System.Windows.Controls.Border
$lblBorder.Style = $window.Resources['LabelBorderStyle']
$lblBorderName = "$comboName`_LabelBorder"
$lblBorder.Name = $lblBorderName
$lbl = New-Object System.Windows.Controls.TextBlock
$lbl.Text = $labelText
$lbl.Style = $window.Resources['LabelStyle']
$labelName = "$comboName`_Label"
$lbl.Name = $labelName
$parent.Children.Add($lbl) | Out-Null
# Register the label with the window's name scope
$lblBorder.Child = $lbl
$parent.Children.Add($lblBorder) | Out-Null
# Register the label border with the window's name scope
try {
[System.Windows.NameScope]::SetNameScope($lbl, [System.Windows.NameScope]::GetNameScope($window))
$window.RegisterName($labelName, $lbl)
[System.Windows.NameScope]::SetNameScope($lblBorder, [System.Windows.NameScope]::GetNameScope($window))
$window.RegisterName($lblBorderName, $lblBorder)
}
catch {
# Name might already be registered, ignore
@@ -985,21 +993,74 @@ function OpenGUI {
}
})
# Shared search highlighting configuration
$script:SearchHighlightColor = [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#FFF4CE"))
$script:SearchHighlightColorDark = [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#4A4A2A"))
# Helper function to get the appropriate highlight brush based on theme
function GetSearchHighlightBrush {
if ($usesDarkMode) { return $script:SearchHighlightColorDark }
return $script:SearchHighlightColor
}
# Helper function to scroll to an item if it's not visible, centering it in the viewport
function ScrollToItemIfNotVisible {
param (
[System.Windows.Controls.ScrollViewer]$scrollViewer,
[System.Windows.UIElement]$item,
[System.Windows.UIElement]$container
)
if (-not $scrollViewer -or -not $item -or -not $container) { return }
try {
$itemPosition = $item.TransformToAncestor($container).Transform([System.Windows.Point]::new(0, 0)).Y
$viewportHeight = $scrollViewer.ViewportHeight
$itemHeight = $item.ActualHeight
$currentOffset = $scrollViewer.VerticalOffset
# Check if the item is currently visible in the viewport
$itemTop = $itemPosition - $currentOffset
$itemBottom = $itemTop + $itemHeight
$isVisible = ($itemTop -ge 0) -and ($itemBottom -le $viewportHeight)
# Only scroll if the item is not visible
if (-not $isVisible) {
# Center the item in the viewport
$targetOffset = $itemPosition - ($viewportHeight / 2) + ($itemHeight / 2)
$scrollViewer.ScrollToVerticalOffset([Math]::Max(0, $targetOffset))
}
}
catch {
# Fallback to simple bring into view
$item.BringIntoView()
}
}
# Helper function to find the parent ScrollViewer of an element
function FindParentScrollViewer {
param ([System.Windows.UIElement]$element)
$parent = [System.Windows.Media.VisualTreeHelper]::GetParent($element)
while ($null -ne $parent) {
if ($parent -is [System.Windows.Controls.ScrollViewer]) {
return $parent
}
$parent = [System.Windows.Media.VisualTreeHelper]::GetParent($parent)
}
return $null
}
# App Search Box functionality
$appSearchBox = $window.FindName('AppSearchBox')
$appSearchPlaceholder = $window.FindName('AppSearchPlaceholder')
$highlightColor = [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#FFF4CE"))
$highlightColorDark = [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#4A4A2A"))
$appSearchBox.Add_TextChanged({
$searchText = $appSearchBox.Text.ToLower().Trim()
# Show/hide placeholder
if ([string]::IsNullOrWhiteSpace($appSearchBox.Text)) {
$appSearchPlaceholder.Visibility = 'Visible'
} else {
$appSearchPlaceholder.Visibility = 'Collapsed'
}
$appSearchPlaceholder.Visibility = if ([string]::IsNullOrWhiteSpace($appSearchBox.Text)) { 'Visible' } else { 'Collapsed' }
# Clear all highlights first
foreach ($child in $appsPanel.Children) {
@@ -1008,61 +1069,124 @@ function OpenGUI {
}
}
if ([string]::IsNullOrWhiteSpace($searchText)) {
return
}
if ([string]::IsNullOrWhiteSpace($searchText)) { return }
# Find and highlight all matching apps
$firstMatch = $null
$highlightBrush = if ($usesDarkMode) { $highlightColorDark } else { $highlightColor }
$highlightBrush = GetSearchHighlightBrush
foreach ($child in $appsPanel.Children) {
if ($child -is [System.Windows.Controls.CheckBox]) {
# Only consider visible apps (not filtered out by installed filter)
if ($child.Visibility -eq 'Visible') {
$appName = $child.Content.ToString().ToLower()
if ($appName.Contains($searchText)) {
# Highlight the matching app
if ($child -is [System.Windows.Controls.CheckBox] -and $child.Visibility -eq 'Visible') {
if ($child.Content.ToString().ToLower().Contains($searchText)) {
$child.Background = $highlightBrush
# Remember first match for scrolling
if ($null -eq $firstMatch) {
$firstMatch = $child
}
}
if ($null -eq $firstMatch) { $firstMatch = $child }
}
}
}
# Scroll to first match - centered
# Scroll to first match if not visible
if ($firstMatch) {
# Get the ScrollViewer that contains the apps panel
$scrollViewer = $null
$parent = [System.Windows.Media.VisualTreeHelper]::GetParent($appsPanel)
while ($null -ne $parent) {
if ($parent -is [System.Windows.Controls.ScrollViewer]) {
$scrollViewer = $parent
break
}
$parent = [System.Windows.Media.VisualTreeHelper]::GetParent($parent)
}
$scrollViewer = FindParentScrollViewer -element $appsPanel
if ($scrollViewer) {
# Calculate the position to scroll to for centering
$itemPosition = $firstMatch.TransformToAncestor($appsPanel).Transform([System.Windows.Point]::new(0, 0)).Y
$viewportHeight = $scrollViewer.ViewportHeight
$itemHeight = $firstMatch.ActualHeight
# Center the item in the viewport
$targetOffset = $itemPosition - ($viewportHeight / 2) + ($itemHeight / 2)
$scrollViewer.ScrollToVerticalOffset([Math]::Max(0, $targetOffset))
} else {
# Fallback to simple bring into view
$firstMatch.BringIntoView()
ScrollToItemIfNotVisible -scrollViewer $scrollViewer -item $firstMatch -container $appsPanel
}
}
})
# Tweak Search Box functionality
$tweakSearchBox = $window.FindName('TweakSearchBox')
$tweakSearchPlaceholder = $window.FindName('TweakSearchPlaceholder')
$tweaksScrollViewer = $window.FindName('TweaksScrollViewer')
$tweaksGrid = $window.FindName('TweaksGrid')
$col0 = $window.FindName('Column0Panel')
$col1 = $window.FindName('Column1Panel')
$col2 = $window.FindName('Column2Panel')
# Helper function to clear all tweak highlights
function ClearTweakHighlights {
$columns = @($col0, $col1, $col2) | Where-Object { $_ -ne $null }
foreach ($column in $columns) {
foreach ($card in $column.Children) {
if ($card -is [System.Windows.Controls.Border] -and $card.Child -is [System.Windows.Controls.StackPanel]) {
foreach ($control in $card.Child.Children) {
if ($control -is [System.Windows.Controls.CheckBox] -or
($control -is [System.Windows.Controls.Border] -and $control.Name -like '*_LabelBorder')) {
$control.Background = [System.Windows.Media.Brushes]::Transparent
}
}
}
}
}
}
# Helper function to check if a ComboBox contains matching items
function ComboBoxContainsMatch {
param ([System.Windows.Controls.ComboBox]$comboBox, [string]$searchText)
foreach ($item in $comboBox.Items) {
$itemText = if ($item -is [System.Windows.Controls.ComboBoxItem]) { $item.Content.ToString().ToLower() } else { $item.ToString().ToLower() }
if ($itemText.Contains($searchText)) { return $true }
}
return $false
}
$tweakSearchBox.Add_TextChanged({
$searchText = $tweakSearchBox.Text.ToLower().Trim()
# Show/hide placeholder
$tweakSearchPlaceholder.Visibility = if ([string]::IsNullOrWhiteSpace($tweakSearchBox.Text)) { 'Visible' } else { 'Collapsed' }
# Clear all highlights
ClearTweakHighlights
if ([string]::IsNullOrWhiteSpace($searchText)) { return }
# Find and highlight all matching tweaks
$firstMatch = $null
$highlightBrush = GetSearchHighlightBrush
$columns = @($col0, $col1, $col2) | Where-Object { $_ -ne $null }
foreach ($column in $columns) {
foreach ($card in $column.Children) {
if ($card -is [System.Windows.Controls.Border] -and $card.Child -is [System.Windows.Controls.StackPanel]) {
$controlsList = @($card.Child.Children)
for ($i = 0; $i -lt $controlsList.Count; $i++) {
$control = $controlsList[$i]
$matchFound = $false
$controlToHighlight = $null
if ($control -is [System.Windows.Controls.CheckBox]) {
if ($control.Content.ToString().ToLower().Contains($searchText)) {
$matchFound = $true
$controlToHighlight = $control
}
}
elseif ($control -is [System.Windows.Controls.Border] -and $control.Name -like '*_LabelBorder') {
$labelText = if ($control.Child) { $control.Child.Text.ToLower() } else { "" }
$comboBox = if ($i + 1 -lt $controlsList.Count -and $controlsList[$i + 1] -is [System.Windows.Controls.ComboBox]) { $controlsList[$i + 1] } else { $null }
# Check label text or combo box items
if ($labelText.Contains($searchText) -or ($comboBox -and (ComboBoxContainsMatch -comboBox $comboBox -searchText $searchText))) {
$matchFound = $true
$controlToHighlight = $control
}
}
if ($matchFound -and $controlToHighlight) {
$controlToHighlight.Background = $highlightBrush
if ($null -eq $firstMatch) { $firstMatch = $controlToHighlight }
}
}
}
}
}
# Scroll to first match if not visible
if ($firstMatch -and $tweaksScrollViewer) {
ScrollToItemIfNotVisible -scrollViewer $tweaksScrollViewer -item $firstMatch -container $tweaksGrid
}
})
# Wizard Navigation
$tabControl = $window.FindName('MainTabControl')
$previousBtn = $window.FindName('PreviousBtn')