Skip to content

Commit

Permalink
Merge pull request #200 from Checkmarx/feature/addFilterToCombobox
Browse files Browse the repository at this point in the history
Add filter in project, branch and scan ComboBoxes(AST-64166)
  • Loading branch information
sarahCx authored Sep 11, 2024
2 parents 1bca6de + 88cae12 commit 495540e
Show file tree
Hide file tree
Showing 12 changed files with 246 additions and 73 deletions.
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/ast-visual-studio-extension.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions ast-visual-studio-extension/CxExtension/CxWindowControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -421,20 +421,20 @@
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>

<ScrollViewer Grid.Row="0" Grid.Column="0" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" theming:ImageThemingUtilities.ImageBackgroundColor="{Binding Background, ElementName=CxWindow, Converter={StaticResource BrushToColorConverter}}">

<ScrollViewer Grid.Row="0" Grid.Column="0" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" theming:ImageThemingUtilities.ImageBackgroundColor="{Binding Background, ElementName=CxWindow, Converter={StaticResource BrushToColorConverter}}">

<TextBlock VerticalAlignment="Center" Text="Project:" Grid.Column="1" Margin="4"/>
<ComboBox VerticalAlignment="Center" IsTextSearchEnabled="False" IsEnabled="False" IsEditable="True" IsReadOnly="True" Text="Loading projects..." Name="ProjectsCombobox" Margin="4" SelectionChanged="OnChangeProject"/>
<ComboBox VerticalAlignment="Center" IsTextSearchEnabled="False" IsEnabled="True" IsEditable="True" IsReadOnly="False" Text="Loading projects..." Name="ProjectsCombobox" Margin="4" MinWidth="100" SelectionChanged="OnChangeProject" KeyUp="OnProjectTextChanged"/>

<TextBlock Text="Branch:" Grid.Column="1" VerticalAlignment="Center" Margin="4"/>
<ComboBox VerticalAlignment="Center" IsEnabled="False" IsEditable="True" IsReadOnly="True" Text="Select a branch" Name="BranchesCombobox" Margin="4" SelectionChanged="OnChangeBranch"></ComboBox>
<ComboBox VerticalAlignment="Center" IsTextSearchEnabled="False" IsEnabled="True" IsEditable="True" IsReadOnly="False" Text="Select a branch" Name="BranchesCombobox" Margin="4" MinWidth="100" SelectionChanged="OnChangeBranch" KeyUp="OnBranchTextChanged"/>

<TextBlock Text="Scan:" Grid.Column="1" VerticalAlignment="Center" Margin="4"/>
<ComboBox VerticalAlignment="Center" IsTextSearchEnabled="False" IsEnabled="False" IsEditable="True" IsReadOnly="False" Text="Select a scan" Name="ScansCombobox" Margin="4" SelectionChanged="OnChangeScan" KeyDown="OnTypeScan"></ComboBox>
<ComboBox VerticalAlignment="Center" IsTextSearchEnabled="False" IsEnabled="True" IsEditable="True" IsReadOnly="False" Text="Select a scan" Name="ScansCombobox" Margin="4" MinWidth="100" SelectionChanged="OnChangeScan" KeyUp="OnScanTextChanged"/>
</StackPanel>
</ScrollViewer>

<StackPanel Height="35" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal" >
<StackPanel Orientation="Horizontal">
<Separator Style="{StaticResource SeparatorStyle}" />
Expand Down
37 changes: 35 additions & 2 deletions ast-visual-studio-extension/CxExtension/CxWindowControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Threading;
using System.Threading.Tasks;
using System;

namespace ast_visual_studio_extension.CxExtension
{
Expand All @@ -19,6 +22,7 @@ public partial class CxWindowControl : UserControl
private readonly ResultInfoPanel resultInfoPanel;
private readonly AsyncPackage package;
private readonly ResultVulnerabilitiesPanel resultsVulnPanel;
private CancellationTokenSource typingCts;
public CxWindowControl(AsyncPackage package)
{
InitializeComponent();
Expand Down Expand Up @@ -138,6 +142,10 @@ private void OnChangeProject(object sender, SelectionChangedEventArgs e)
{
cxToolbar.ProjectsCombobox.OnChangeProject(sender, e);
}
private async void OnProjectTextChanged(object sender, KeyEventArgs e)
{
await HandleTextChangedAsync(() => cxToolbar.ProjectsCombobox.OnComboBoxTextChanged(sender, e));
}

/// <summary>
/// On change event for Branches combobox
Expand All @@ -148,6 +156,10 @@ private void OnChangeBranch(object sender, SelectionChangedEventArgs e)
{
cxToolbar.BranchesCombobox.OnChangeBranch(sender, e);
}
private async void OnBranchTextChanged(object sender, KeyEventArgs e)
{
await HandleTextChangedAsync(() => cxToolbar.BranchesCombobox.OnComboBoxTextChanged(sender, e));
}

/// <summary>
/// On change event for Scans combobox
Expand All @@ -164,9 +176,30 @@ private void OnChangeScan(object sender, SelectionChangedEventArgs e)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnTypeScan(object sender, KeyEventArgs e)
private async void OnScanTextChanged(object sender, KeyEventArgs e)
{
await HandleTextChangedAsync(() => cxToolbar.ScansCombobox.OnComboBoxTextChanged(sender, e));
}

private async Task HandleTextChangedAsync(Action onTextChangedAction)
{
_ = cxToolbar.ScansCombobox.OnTypeScanAsync(sender, e);
typingCts?.Cancel();
typingCts?.Dispose();

typingCts = new CancellationTokenSource();
var token = typingCts.Token;
try
{
await Task.Delay(500, token);
if (!token.IsCancellationRequested)
{
onTextChangedAction();
}
}
catch (TaskCanceledException)
{
// Ignore the exception if the task was canceled
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
using ast_visual_studio_extension.CxExtension.Utils;
using ast_visual_studio_extension.CxWrapper.Models;
using Microsoft.VisualStudio.Shell;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Controls;
using ast_visual_studio_extension.CxWrapper.Models;

namespace ast_visual_studio_extension.CxExtension.Toolbar
{
internal class BranchesCombobox
internal class BranchesCombobox : ComboboxBase
{
private readonly ScansCombobox scansCombobox;

private readonly CxToolbar cxToolbar;
private bool initialized = false;

public BranchesCombobox(CxToolbar cxToolbar, ScansCombobox scansCombobox)
: base(cxToolbar, cxToolbar.BranchesCombo)
{
this.cxToolbar = cxToolbar;
this.scansCombobox = scansCombobox;
}

Expand Down Expand Up @@ -59,7 +58,7 @@ public async Task LoadBranchesAsync(string projectId)
}

cxToolbar.BranchesCombo.Items.Clear();

allItems.Clear();
for (int i = 0; i < branches.Count; i++)
{
ComboBoxItem comboBoxItem = new ComboBoxItem
Expand All @@ -68,12 +67,13 @@ public async Task LoadBranchesAsync(string projectId)
};

cxToolbar.BranchesCombo.Items.Add(comboBoxItem);
allItems.Add(comboBoxItem);
}

cxToolbar.BranchesCombo.Text = CxConstants.TOOLBAR_SELECT_BRANCH;
cxToolbar.EnableCombos(true);

if(CxToolbar.reverseSearch)
if (CxToolbar.reverseSearch)
{
cxToolbar.BranchesCombo.SelectedIndex = CxUtils.GetItemIndexInCombo(CxToolbar.currentBranch, cxToolbar.BranchesCombo, Enums.ComboboxType.BRANCHES);
}
Expand All @@ -99,11 +99,14 @@ public void OnChangeBranch(object sender, SelectionChangedEventArgs e)
{
if (!(sender is ComboBox branchesCombo) || branchesCombo.SelectedItem == null || branchesCombo.SelectedIndex == -1) return;

ResetFilteringState(branchesCombo.SelectedItem as ComboBoxItem);

string selectedBranch = (branchesCombo.SelectedItem as ComboBoxItem).Content as string;

cxToolbar.EnableCombos(false);
cxToolbar.ScansCombo.Text = string.IsNullOrEmpty(CxToolbar.currentScanId) ? CxConstants.TOOLBAR_LOADING_SCANS : CxToolbar.currentScanId;
cxToolbar.ResultsTreePanel.ClearAll();

string selectedBranch = (branchesCombo.SelectedItem as ComboBoxItem).Content as string;
string projectId = ((cxToolbar.ProjectsCombo.SelectedItem as ComboBoxItem).Tag as Project).Id;

SettingsUtils.StoreToolbarValue(cxToolbar.Package, SettingsUtils.toolbarCollection, SettingsUtils.branchProperty, selectedBranch);
Expand All @@ -117,5 +120,13 @@ public void OnChangeBranch(object sender, SelectionChangedEventArgs e)

cxToolbar.ScanButtonByCombos();
}
protected override void ResetOthersComboBoxesAndResults()
{
cxToolbar.ScansCombo.IsEnabled = false;
cxToolbar.ScansCombo.Items.Clear();
cxToolbar.ScansCombo.Text = string.IsNullOrEmpty(CxToolbar.currentScanId) ? CxConstants.TOOLBAR_SELECT_SCAN : CxToolbar.currentScanId;

cxToolbar.ResultsTreePanel.ClearAll();
}
}
}
105 changes: 105 additions & 0 deletions ast-visual-studio-extension/CxExtension/Toolbar/ComboboxBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;

namespace ast_visual_studio_extension.CxExtension.Toolbar
{
internal abstract class ComboboxBase
{
protected CxToolbar cxToolbar;
protected ComboBox comboBox;
protected string previousText = string.Empty;
protected bool isFiltered = false;
protected List<ComboBoxItem> allItems;
public ComboboxBase(CxToolbar cxToolbar, ComboBox comboBox)
{
this.cxToolbar = cxToolbar;
this.comboBox = comboBox;
allItems = new List<ComboBoxItem>();
}
protected void ResetFilteringState(ComboBoxItem selectedItem)
{
previousText = selectedItem.Content.ToString();
if (isFiltered)
{
Mouse.OverrideCursor = Cursors.Wait;
isFiltered = false;
UpdateCombobox(allItems);
comboBox.SelectedItem = selectedItem;
Mouse.OverrideCursor = null;
}
}
public void OnComboBoxTextChanged(object sender, EventArgs e)
{

if (comboBox == null || IsTextUnchanged()) return;

Mouse.OverrideCursor = Cursors.Wait;

TextBox textBox = GetTextBoxFromComboBox();

if (textBox != null)
{
string newText = textBox.Text;
int savedSelectionStart = textBox.SelectionStart;

ResetOthersComboBoxesAndResults();

UpdateComboBoxWithFilteredItems(newText);

comboBox.IsDropDownOpen = true;
RestoreTextBoxState(textBox, savedSelectionStart, newText);
}
Mouse.OverrideCursor = null;
}
private TextBox GetTextBoxFromComboBox()
{
return (TextBox)comboBox.Template.FindName("PART_EditableTextBox", comboBox);
}
private bool IsTextUnchanged()
{

if (comboBox.Text == previousText) return true;

previousText = comboBox.Text;
return false;
}
private void UpdateComboBoxWithFilteredItems(string newText)
{
comboBox.SelectedItem = null;

if (string.IsNullOrEmpty(newText))
{
UpdateCombobox(allItems);
}
else
{
var filteredItems = allItems.Where(item => item.Content.ToString()
.IndexOf(newText, StringComparison.OrdinalIgnoreCase) >= 0)
.ToList();
UpdateCombobox(filteredItems);
isFiltered = true;
}
}

private void RestoreTextBoxState(TextBox textBox, int selectionStart, string text)
{
textBox.Text = text;
textBox.SelectionStart = Math.Min(selectionStart, text.Length);
textBox.SelectionLength = 0;
}

protected void UpdateCombobox(List<ComboBoxItem> items)
{
comboBox.Items.Clear();
foreach (var item in items)
{
comboBox.Items.Add(item);
}
}

protected abstract void ResetOthersComboBoxesAndResults();
}
}
Loading

0 comments on commit 495540e

Please sign in to comment.