Skip to content

Commit de3dd4c

Browse files
authored
DYN-8541: Add single and cluster icons, refactor (#16189)
1 parent 35b7d01 commit de3dd4c

File tree

7 files changed

+124
-143
lines changed

7 files changed

+124
-143
lines changed

src/DynamoCoreWpf/DynamoCoreWpf.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,7 @@
13081308
<Resource Include="UI\Images\closetab_hover.png" />
13091309
</ItemGroup>
13101310
<ItemGroup>
1311+
<Resource Include="UI\Images\cluster_32px.png" />
13111312
<Resource Include="UI\Images\gripper-default.png" />
13121313
<Resource Include="UI\Images\gripper-hover.png" />
13131314
<Resource Include="UI\Images\caret-left-disabled.png" />
629 Bytes
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Windows.Media;
2+
3+
namespace Dynamo.NodeAutoComplete.ViewModels
4+
{
5+
public class DNADropdownViewModel
6+
{
7+
public string Description { get; set; }
8+
public ImageSource SmallIcon { get; set; }
9+
}
10+
}

src/NodeAutoCompleteViewExtension/ViewModels/NodeAutoCompleteBarViewModel.cs

Lines changed: 58 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
using Dynamo.Core;
3737
using Dynamo.Graph.Workspaces;
3838
using Dynamo.Graph;
39+
using System.Windows.Media;
40+
using System.Windows.Media.Imaging;
3941

4042
namespace Dynamo.NodeAutoComplete.ViewModels
4143
{
@@ -124,19 +126,19 @@ public bool HideAutocompleteMethodOptions
124126
}
125127
}
126128

127-
private IEnumerable<NodeAutoCompleteClusterResult> clusterResults;
129+
private IEnumerable<DNADropdownViewModel> dropdownResults;
128130
/// <summary>
129131
/// Cluster autocomplete search results.
130132
/// </summary>
131-
public IEnumerable<NodeAutoCompleteClusterResult> DropdownResults
133+
public IEnumerable<DNADropdownViewModel> DropdownResults
132134
{
133135
get
134136
{
135-
return clusterResults;
137+
return dropdownResults;
136138
}
137139
set
138140
{
139-
clusterResults = value;
141+
dropdownResults = value;
140142
RaisePropertyChanged(nameof(DropdownResults));
141143
RaisePropertyChanged(nameof(NthofTotal));
142144
RaisePropertyChanged(nameof(ResultsLoaded));
@@ -346,6 +348,7 @@ public bool DisplayLowConfidence
346348
internal event Action<NodeModel> ParentNodeRemoved;
347349

348350
internal MLNodeClusterAutoCompletionResponse FullResults { private set; get; }
351+
internal List<SingleResultItem> FullSingleResults { set; get; }
349352

350353
/// <summary>
351354
/// Constructor
@@ -472,14 +475,14 @@ internal MLNodeAutoCompletionRequest GenerateRequestForMLAutocomplete()
472475
return request;
473476
}
474477

475-
internal IEnumerable<NodeSearchElementViewModel> GetNodeAutocompleMLResults()
478+
private IEnumerable<SingleResultItem> GetNodeAutocompleMLResults()
476479
{
477480
MLNodeAutoCompletionResponse MLresults = null;
478481

479482
// Get results from the ML API.
480483
try
481484
{
482-
MLresults = GetMLNodeAutocompleteResults();
485+
MLresults = GetGenericAutocompleteResult<MLNodeAutoCompletionResponse>(nodeAutocompleteMLEndpoint);
483486
}
484487
catch (Exception ex)
485488
{
@@ -488,7 +491,7 @@ internal IEnumerable<NodeSearchElementViewModel> GetNodeAutocompleMLResults()
488491
AutocompleteMLTitle = Resources.LoginNeededTitle;
489492
AutocompleteMLMessage = Resources.LoginNeededMessage;
490493
Analytics.TrackEvent(Actions.View, Categories.NodeAutoCompleteOperations, "UnabletoFetch");
491-
return new List<NodeSearchElementViewModel>();
494+
return new List<SingleResultItem>();
492495
}
493496

494497
// no results
@@ -498,10 +501,10 @@ internal IEnumerable<NodeSearchElementViewModel> GetNodeAutocompleMLResults()
498501
AutocompleteMLTitle = Resources.AutocompleteNoRecommendationsTitle;
499502
AutocompleteMLMessage = Resources.AutocompleteNoRecommendationsMessage;
500503
Analytics.TrackEvent(Actions.View, Categories.NodeAutoCompleteOperations, "NoRecommendation");
501-
return new List<NodeSearchElementViewModel>();
504+
return new List<SingleResultItem>();
502505
}
503506
ServiceVersion = MLresults.Version;
504-
var results = new List<NodeSearchElementViewModel>();
507+
var results = new List<SingleResultItem>();
505508

506509
var zeroTouchSearchElements = Model.Entries.OfType<ZeroTouchSearchElement>().Where(x => x.IsVisibleInSearch);
507510
var nodeModelSearchElements = Model.Entries.OfType<NodeModelSearchElement>().Where(x => x.IsVisibleInSearch);
@@ -521,13 +524,10 @@ internal IEnumerable<NodeSearchElementViewModel> GetNodeAutocompleMLResults()
521524
if (element != null)
522525
{
523526
nodeSearchElement = (NodeSearchElement)element.Clone();
524-
}
525527

526-
// Set PortToConnect for each element based on port-index and port-name
527-
if (nodeSearchElement != null)
528-
{
528+
// Set PortToConnect for each element based on port-index and port-name
529529
nodeSearchElement.AutoCompletionNodeElementInfo = new AutoCompletionNodeElementInfo
530-
{
530+
{
531531
PortToConnect = portIndex
532532
};
533533

@@ -539,13 +539,9 @@ internal IEnumerable<NodeSearchElementViewModel> GetNodeAutocompleMLResults()
539539
break;
540540
}
541541
}
542-
}
543542

544-
var viewModelElement = GetViewModelForNodeSearchElement(nodeSearchElement);
543+
var viewModelElement = new SingleResultItem(nodeSearchElement, result.Score);
545544

546-
if (viewModelElement != null)
547-
{
548-
viewModelElement.AutoCompletionNodeMachineLearningInfo = new AutoCompletionNodeMachineLearningInfo(true, true, Math.Round(result.Score * 100));
549545
results.Add(viewModelElement);
550546
}
551547
}
@@ -564,29 +560,21 @@ internal IEnumerable<NodeSearchElementViewModel> GetNodeAutocompleMLResults()
564560
if (element != null)
565561
{
566562
nodeSearchElement = (NodeSearchElement)element.Clone();
567-
}
568563

569-
if (nodeSearchElement != null)
570-
{
571564
nodeSearchElement.AutoCompletionNodeElementInfo = new AutoCompletionNodeElementInfo
572565
{
573566
PortToConnect = portIndex
574567
};
575-
}
576568

577-
var viewModelElement = GetViewModelForNodeSearchElement(nodeSearchElement);
578-
579-
if (viewModelElement != null)
580-
{
581-
viewModelElement.AutoCompletionNodeMachineLearningInfo = new AutoCompletionNodeMachineLearningInfo(true, true, Math.Round(result.Score * 100));
569+
var viewModelElement = new SingleResultItem(nodeSearchElement, result.Score);
582570
results.Add(viewModelElement);
583571
}
584572
}
585573
}
586574

587575
return results;
588576
}
589-
internal T GetGenericAutocompleteResult<T>(string endpoint)
577+
private T GetGenericAutocompleteResult<T>(string endpoint)
590578
{
591579
var requestDTO = GenerateRequestForMLAutocomplete();
592580
var jsonRequest = JsonConvert.SerializeObject(requestDTO);
@@ -642,16 +630,6 @@ internal T GetGenericAutocompleteResult<T>(string endpoint)
642630
return results;
643631
}
644632

645-
private MLNodeAutoCompletionResponse GetMLNodeAutocompleteResults()
646-
{
647-
return GetGenericAutocompleteResult<MLNodeAutoCompletionResponse>(nodeAutocompleteMLEndpoint);
648-
}
649-
650-
private MLNodeClusterAutoCompletionResponse GetMLNodeClusterAutocompleteResults()
651-
{
652-
return GetGenericAutocompleteResult<MLNodeClusterAutoCompletionResponse>(nodeClusterAutocompleteMLEndpoint);
653-
}
654-
655633
/// <summary>
656634
/// Show the low confidence ML results.
657635
/// </summary>
@@ -708,7 +686,7 @@ internal HostNames GetHostNameEnum(string HostName)
708686
/// <summary>
709687
/// Key function to populate node autocomplete results to display
710688
/// </summary>
711-
internal IEnumerable<NodeSearchElementViewModel> GetSingleAutocompleteResults()
689+
internal IEnumerable<SingleResultItem> GetSingleAutocompleteResults()
712690
{
713691
if (PortViewModel == null) return null;
714692

@@ -734,11 +712,11 @@ internal IEnumerable<NodeSearchElementViewModel> GetSingleAutocompleteResults()
734712
// These default suggestions will be populated based on the port type.
735713
if (!objectTypeMatchingElements.Any())
736714
{
737-
return DefaultAutoCompleteCandidates();
715+
return DefaultAutoCompleteCandidates().Select(x => new SingleResultItem(x));
738716
}
739717
else
740718
{
741-
return GetViewModelForNodeSearchElements(objectTypeMatchingElements);
719+
return objectTypeMatchingElements.Select(x => new SingleResultItem(x));
742720
}
743721
}
744722
}
@@ -894,38 +872,37 @@ internal void PopulateAutoComplete()
894872
{
895873
DropdownResults = null;
896874
}
875+
897876
Task.Run(() =>
898877
{
899-
IEnumerable<NodeAutoCompleteClusterResult> comboboxResults;
900878
if (IsSingleAutocomplete)
901879
{
902-
var fullSingleResults = GetSingleAutocompleteResults().ToList();
880+
FullSingleResults = GetSingleAutocompleteResults().ToList();
903881
FullResults = new MLNodeClusterAutoCompletionResponse
904882
{
905883
Version = "0.0",
906-
NumberOfResults = fullSingleResults.Count,
907-
Results = fullSingleResults.Select(x => new ClusterResultItem
884+
NumberOfResults = FullSingleResults.Count,
885+
Results = FullSingleResults.Select(x => new ClusterResultItem
908886
{
909887
Description = x.Description,
910-
Title = x.Description,
911-
Probability = (x.AutoCompletionNodeMachineLearningInfo.ConfidenceScore / 100).ToString(),
888+
Title = x.Description,
889+
Probability = x.Score.ToString(),
912890
EntryNodeIndex = 0,
913-
EntryNodeInPort = x.Model.AutoCompletionNodeElementInfo.PortToConnect,
891+
EntryNodeInPort = x.PortToConnect,
914892
Topology = new TopologyItem
915893
{
916894
Nodes = new List<NodeItem> { new NodeItem {
917895
Id = new Guid().ToString(),
918-
Type = new NodeType { Id = x.Model.CreationName } } },
896+
Type = new NodeType { Id = x.CreationName } } },
919897
Connections = new List<ConnectionItem>()
920898
}
921899
})
922900
};
923901
}
924902
else
925903
{
926-
FullResults = GetMLNodeClusterAutocompleteResults();
904+
FullResults = GetGenericAutocompleteResult<MLNodeClusterAutoCompletionResponse>(nodeClusterAutocompleteMLEndpoint);
927905
}
928-
comboboxResults = QualifiedResults.Select(x => new NodeAutoCompleteClusterResult { Description = x.Description });
929906

930907
dynamoViewModel.UIDispatcher.BeginInvoke(() =>
931908
{
@@ -936,6 +913,35 @@ internal void PopulateAutoComplete()
936913
return;
937914
}
938915

916+
IEnumerable<DNADropdownViewModel> comboboxResults;
917+
if (IsSingleAutocomplete)
918+
{
919+
//getting bitmaps from resources necessarily has to be done in the UI thread
920+
Dictionary<string, ImageSource> dict = [];
921+
foreach (var singleResult in FullSingleResults)
922+
{
923+
if (dict.ContainsKey(singleResult.CreationName))
924+
{
925+
continue;
926+
}
927+
var iconRequest = new IconRequestEventArgs(singleResult.Assembly, singleResult.IconName + Configurations.SmallIconPostfix);
928+
SearchViewModelRequestBitmapSource(iconRequest);
929+
dict[singleResult.CreationName] = iconRequest.Icon;
930+
}
931+
comboboxResults = QualifiedResults.Select(x => new DNADropdownViewModel
932+
{
933+
Description = x.Description,
934+
SmallIcon = dict[x.Topology.Nodes.First().Type.Id],
935+
});
936+
}
937+
else
938+
{
939+
comboboxResults = QualifiedResults.Select(x => new DNADropdownViewModel
940+
{
941+
Description = x.Description
942+
//default icon (cluster) is set in the xaml view
943+
});
944+
}
939945
// this runs synchronously on the UI thread, so the UI can't disappear during execution
940946
DropdownResults = comboboxResults;
941947
SelectedIndex = 0;
@@ -992,84 +998,6 @@ internal void NodeViewModel_Removed(NodeModel node)
992998
ParentNodeRemoved?.Invoke(node);
993999
}
9941000

995-
/// <summary>
996-
/// Returns a IEnumberable of NodeSearchElementViewModel for respective NodeSearchElements.
997-
/// </summary>
998-
private IEnumerable<NodeSearchElementViewModel> GetViewModelForNodeSearchElements(List<NodeSearchElement> searchElementsCache)
999-
{
1000-
return searchElementsCache.Select(e =>
1001-
{
1002-
var vm = new NodeSearchElementViewModel(e, this);
1003-
vm.RequestBitmapSource += SearchViewModelRequestBitmapSource;
1004-
return vm;
1005-
});
1006-
}
1007-
1008-
/// <summary>
1009-
/// Returns a NodeSearchElementViewModel for a NodeSearchElement
1010-
/// </summary>
1011-
private NodeSearchElementViewModel GetViewModelForNodeSearchElement(NodeSearchElement nodeSearchElement)
1012-
{
1013-
if (nodeSearchElement != null)
1014-
{
1015-
var vm = new NodeSearchElementViewModel(nodeSearchElement, this);
1016-
vm.RequestBitmapSource += SearchViewModelRequestBitmapSource;
1017-
return vm;
1018-
}
1019-
return null;
1020-
}
1021-
1022-
1023-
/// <summary>
1024-
/// Performs a search using the given string as query and subset, if provided.
1025-
/// </summary>
1026-
/// <returns> Returns a list with a maximum MaxNumSearchResults elements.</returns>
1027-
/// <param name="search"> The search query </param>
1028-
internal IEnumerable<NodeSearchElementViewModel> SearchNodeAutocomplete(string search)
1029-
{
1030-
if (LuceneUtility != null)
1031-
{
1032-
//The DirectoryReader and IndexSearcher have to be assigned after commiting indexing changes and before executing the Searcher.Search() method, otherwise new indexed info won't be reflected
1033-
LuceneUtility.dirReader = LuceneUtility.writer?.GetReader(applyAllDeletes: true);
1034-
if (LuceneUtility.dirReader == null) return null;
1035-
1036-
LuceneUtility.Searcher = new IndexSearcher(LuceneUtility.dirReader);
1037-
1038-
string searchTerm = search.Trim();
1039-
var candidates = new List<NodeSearchElementViewModel>();
1040-
var parser = new MultiFieldQueryParser(LuceneConfig.LuceneNetVersion, LuceneConfig.NodeIndexFields, LuceneUtility.Analyzer)
1041-
{
1042-
AllowLeadingWildcard = true,
1043-
DefaultOperator = LuceneConfig.DefaultOperator,
1044-
FuzzyMinSim = LuceneConfig.MinimumSimilarity
1045-
};
1046-
1047-
Query query = parser.Parse(LuceneUtility.CreateSearchQuery(LuceneConfig.NodeIndexFields, searchTerm));
1048-
TopDocs topDocs = LuceneUtility.Searcher.Search(query, n: LuceneConfig.DefaultResultsCount);
1049-
1050-
for (int i = 0; i < topDocs.ScoreDocs.Length; i++)
1051-
{
1052-
// read back a Lucene doc from results
1053-
Document resultDoc = LuceneUtility.Searcher.Doc(topDocs.ScoreDocs[i].Doc);
1054-
1055-
string name = resultDoc.Get(nameof(LuceneConfig.NodeFieldsEnum.Name));
1056-
string docName = resultDoc.Get(nameof(LuceneConfig.NodeFieldsEnum.DocName));
1057-
string cat = resultDoc.Get(nameof(LuceneConfig.NodeFieldsEnum.FullCategoryName));
1058-
string parameters = resultDoc.Get(nameof(LuceneConfig.NodeFieldsEnum.Parameters));
1059-
1060-
1061-
var foundNode = FindViewModelForNodeNameAndCategory(name, cat, parameters);
1062-
if (foundNode != null)
1063-
{
1064-
candidates.Add(foundNode);
1065-
}
1066-
}
1067-
1068-
return candidates;
1069-
}
1070-
return null;
1071-
}
1072-
10731001
/// <summary>
10741002
/// Returns a collection of node search elements for nodes
10751003
/// that output a type compatible with the port type if it's an input port.

src/NodeAutoCompleteViewExtension/ViewModels/NodeAutoCompleteClusterResult.cs

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)