Skip to content

Commit

Permalink
Add search functionality to Node Autocomplete window. (DynamoDS#11192)
Browse files Browse the repository at this point in the history
* First commit

* Cache the seeach elements after the matching nodes have been calculated.

* Add comments

* some comments.

* Adding a test

* Addressing some comments.

* Some refactoring.
  • Loading branch information
reddyashish authored Nov 5, 2020
1 parent b7d98b4 commit f00b2f7
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 10 deletions.
10 changes: 8 additions & 2 deletions src/DynamoCoreWpf/Controls/NodeAutoCompleteSearchControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,14 @@ private void OnSearchTextBoxTextChanged(object sender, TextChangedEventArgs e)
if (binding != null)
binding.UpdateSource();

if (ViewModel != null)
ViewModel.SearchCommand.Execute(null);
// Search the filtered results to match the user input.
if (ViewModel != null)
{
Dispatcher.BeginInvoke(new Action(() =>
{
ViewModel.SearchAutoCompleteCandidates(SearchTextBox.Text);
}), DispatcherPriority.Loaded);
}
}

private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
Expand All @@ -17,6 +18,7 @@ public class NodeAutoCompleteSearchViewModel : SearchViewModel
{

internal PortViewModel PortViewModel { get; set; }
private List<NodeSearchElement> searchElementsCache;

/// <summary>
/// Cache of default node suggestions, use it in case where
Expand Down Expand Up @@ -53,23 +55,56 @@ internal void PopulateAutoCompleteCandidates()
{
if (PortViewModel == null) return;

var searchElements = GetMatchingSearchElements();
searchElementsCache = GetMatchingSearchElements().ToList();

// If node match searchElements found, use default suggestions
if (!searchElements.Any())
if (!searchElementsCache.Any())
{
searchElementsCache = DefaultResults.Select(e => e.Model).ToList();
FilteredResults = DefaultResults;
}
else
{
FilteredResults = searchElements.Select(e =>
{
var vm = new NodeSearchElementViewModel(e, this);
vm.RequestBitmapSource += SearchViewModelRequestBitmapSource;
return vm;
});
FilteredResults = GetViewModelForNodeSearchElements(searchElementsCache);
}
}

/// <summary>
/// Returns a IEnumberable of NodeSearchElementViewModel for respective NodeSearchElements.
/// </summary>
private IEnumerable<NodeSearchElementViewModel> GetViewModelForNodeSearchElements(List<NodeSearchElement> searchElementsCache)
{
return searchElementsCache.Select(e =>
{
var vm = new NodeSearchElementViewModel(e, this);
vm.RequestBitmapSource += SearchViewModelRequestBitmapSource;
return vm;
});
}

/// <summary>
/// Filters the matching node search elements based on user input in the search field.
/// </summary>
internal void SearchAutoCompleteCandidates(string input)
{
if (PortViewModel == null) return;

var queriedSearchElements = searchElementsCache.Where(e => QuerySearchElements(e, input)).ToList();

FilteredResults = GetViewModelForNodeSearchElements(queriedSearchElements);
}

/// <summary>
/// Returns true if the user input matches the name of the filtered node element.
/// </summary>
/// <returns>True or false</returns>
private bool QuerySearchElements(NodeSearchElement e, string input)
{
StringComparison stringComparison = StringComparison.CurrentCultureIgnoreCase;

return e.Name.IndexOf(input, stringComparison) >= 0;
}

/// <summary>
/// Returns a collection of node search elements for nodes
/// that output a type compatible with the port type if it's an input port.
Expand Down
28 changes: 28 additions & 0 deletions test/DynamoCoreWpfTests/NodeAutoCompleteSearchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ public void NodeSearchElementComparerSortsBasedOnTypeDistance_MultiReturnNodeMod
var comparer = new NodeAutoCompleteSearchViewModel.NodeSearchElementComparer(inputType, core);
Assert.AreEqual(0, comparer.Compare(type1, type2));
}

[Test]
public void NodeSuggestions_DefaultSuggestions()
{
Expand Down Expand Up @@ -264,6 +265,33 @@ public void NodeSuggestions_DefaultSuggestions()
Assert.AreEqual("String", searchViewModel.FilteredResults.FirstOrDefault().Name);
}

[Test]
public void SearchNodeAutocompletionSuggestions()
{
Open(@"UI\builtin_inputport_suggestion.dyn");

// Get the node view for a specific node in the graph
NodeView nodeView = NodeViewWithGuid(Guid.Parse("77aad5875f124bf59a4ece6b30813d3b").ToString());

var inPorts = nodeView.ViewModel.InPorts;
Assert.AreEqual(2, inPorts.Count());
var port = inPorts[0].PortModel;
var type = port.GetInputPortType();
Assert.AreEqual("DSCore.Color[]", type);

var searchViewModel = (ViewModel.CurrentSpaceViewModel.NodeAutoCompleteSearchViewModel as NodeAutoCompleteSearchViewModel);
searchViewModel.PortViewModel = inPorts[0];

var suggestions = searchViewModel.GetMatchingSearchElements();

// Get the matching node elements for the specific node port.
searchViewModel.PopulateAutoCompleteCandidates();

// Filter the node elements using the search field.
searchViewModel.SearchAutoCompleteCandidates("der");
Assert.AreEqual(2 , searchViewModel.FilteredResults.Count());
}

[Test]
public void NodeSuggestions_SkippedSuggestions()
{
Expand Down

0 comments on commit f00b2f7

Please sign in to comment.