Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WorkspaceViewModel fast node and connector lookup #15857

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 6 additions & 15 deletions src/DynamoCoreWpf/ViewModels/Core/AnnotationViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -959,10 +959,7 @@ private void CollapseConnectors()

foreach (var connector in connectorsToHide)
{
var connectorViewModel = WorkspaceViewModel
.Connectors
.Where(x => connector.GUID == x.ConnectorModel.GUID)
.FirstOrDefault();
var connectorViewModel = WorkspaceViewModel.FindConnector(connector.GUID);

connectorViewModel.IsCollapsed = true;
}
Expand All @@ -977,10 +974,7 @@ private void RedrawConnectors()

foreach (var connector in allNodes.SelectMany(x => x.AllConnectors))
{
var connectorViewModel = WorkspaceViewModel
.Connectors
.Where(x => connector.GUID == x.ConnectorModel.GUID)
.FirstOrDefault();
var connectorViewModel = WorkspaceViewModel.FindConnector(connector.GUID);

connectorViewModel.Redraw();
connector.Start.Owner.ReportPosition();
Expand Down Expand Up @@ -1031,14 +1025,11 @@ private void UpdateConnectorsAndPortsOnShowContents(IEnumerable<ModelBase> nodes
{
foreach (var nodeModel in nodes.OfType<NodeModel>())
{
var connectorGuids = nodeModel.AllConnectors
.Select(x => x.GUID);
var connectorViewModels = nodeModel.AllConnectors
.Select(x => WorkspaceViewModel.FindConnector(x.GUID))
.Where(c => c != null);

var connectorViewModels = WorkspaceViewModel.Connectors
.Where(x => connectorGuids.Contains(x.ConnectorModel.GUID))
.ToList();

connectorViewModels.ForEach(x => x.IsCollapsed = false);
foreach(var c in connectorViewModels) c.IsCollapsed = false;

// Set IsProxyPort back to false when the group is expanded.
nodeModel.InPorts.ToList().ForEach(x => x.IsProxyPort = false);
Expand Down
4 changes: 2 additions & 2 deletions src/DynamoCoreWpf/ViewModels/Core/ConnectorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -483,15 +483,15 @@ public NodeViewModel Nodevm
{
get
{
return workspaceViewModel.Nodes?.FirstOrDefault(x => x.NodeLogic.GUID == model.Start.Owner.GUID);
return workspaceViewModel.FindNode(model.Start.Owner.GUID);
}
}

public NodeViewModel NodeEnd
{
get
{
return workspaceViewModel.Nodes?.FirstOrDefault(x => x.NodeLogic.GUID == model.End.Owner.GUID);
return workspaceViewModel.FindNode(model.End.Owner.GUID);
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/DynamoCoreWpf/ViewModels/Core/HomeWorkspaceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,7 @@ private void UpdateNodesDeltaState(List<Guid> nodeGuids, bool graphExecuted)

foreach (Guid t in nodeGuids)
{
var nodeViewModel = Nodes.FirstOrDefault(x => x.NodeModel.GUID == t);
if (nodeViewModel != null)
if (FindNode(t) is NodeViewModel nodeViewModel)
{
nodeViewModel.ShowExecutionPreview = nodeViewModel.DynamoViewModel.ShowRunPreview;
nodeViewModel.IsNodeAddedRecently = false;
Expand Down Expand Up @@ -358,7 +357,7 @@ private void UpdateNodeInfoBubbleContent(EvaluationCompletedEventArgs evalargs)

foreach (var messageID in evalargs.MessageKeys)
{
var node = Nodes.FirstOrDefault(n => n.Id == messageID);
var node = FindNode(messageID);
if (node == null) continue;

node.UpdateBubbleContent();
Expand Down
2 changes: 1 addition & 1 deletion src/DynamoCoreWpf/ViewModels/Core/NodeViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1970,7 +1970,7 @@ private void RaisePropertyChangedOnDownStreamNodes()

foreach (var inode in nodes)
{
var current = this.WorkspaceViewModel.Nodes.FirstOrDefault(x => x.NodeLogic == inode);
var current = WorkspaceViewModel.FindNode(inode.GUID);
if (current != null)
{
current.RaisePropertyChanged("IsFrozen");
Expand Down
4 changes: 1 addition & 3 deletions src/DynamoCoreWpf/ViewModels/Core/NoteViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,7 @@ public NodeViewModel PinnedNode
return null;
}

return WorkspaceViewModel.Nodes
.Where(x => x.Id == Model.PinnedNode.GUID)
.FirstOrDefault();
return WorkspaceViewModel.FindNode(Model.PinnedNode.GUID);
}
}

Expand Down
7 changes: 3 additions & 4 deletions src/DynamoCoreWpf/ViewModels/Core/OutPortViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,9 @@ private void BreakConnections(object parameter)
Analytics.TrackEvent(Actions.Break, Categories.ConnectorOperations, port.PortType.ToString(), port.Connectors.Count);
for (var i = port.Connectors.Count - 1; i >= 0; i--)
{
var portConnectorGuid = port.Connectors[i].GUID;
// Attempting to get the relevant ConnectorViewModel via matching GUID
ConnectorViewModel connectorViewModel = node.WorkspaceViewModel.Connectors
.FirstOrDefault(x => x.ConnectorModel.GUID == port.Connectors[i].GUID);
ConnectorViewModel connectorViewModel = node.WorkspaceViewModel.FindConnector(portConnectorGuid);

if (connectorViewModel == null)
{
Expand All @@ -325,8 +325,7 @@ private void HideConnections(object parameter)
foreach(var connector in port.Connectors)
{
// Attempting to get the relevant ConnectorViewModel via matching GUID
var connectorViewModel = node.WorkspaceViewModel.Connectors
.FirstOrDefault(x => x.ConnectorModel.GUID == connector.GUID);
var connectorViewModel = node.WorkspaceViewModel.FindConnector(connector.GUID);
connectorViewModel?.ShowhideConnectorCommand.Execute(!AreConnectorsHidden);
}
if (AreConnectorsHidden)
Expand Down
45 changes: 36 additions & 9 deletions src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,17 @@ public bool IsCursorForced

[JsonIgnore]
public CompositeCollection WorkspaceElements { get; } = new CompositeCollection();

[JsonIgnore]
public ObservableCollection<ConnectorViewModel> Connectors { get; } = new ObservableCollection<ConnectorViewModel>();

private Dictionary<Guid, ConnectorViewModel> connectorDict = new();

[JsonProperty("NodeViews")]
public ObservableCollection<NodeViewModel> Nodes { get; } = new ObservableCollection<NodeViewModel>();

private Dictionary<Guid, NodeViewModel> nodeDict = new();

// Do not serialize notes, they will be converted to annotations during serialization
[JsonIgnore]
public ObservableCollection<NoteViewModel> Notes { get; } = new ObservableCollection<NoteViewModel>();
Expand Down Expand Up @@ -713,9 +719,11 @@ public override void Dispose()
Connectors.ToList().ForEach(connectorViewmModel => connectorViewmModel.Dispose());
Annotations.ToList().ForEach(AnnotationViewModel => AnnotationViewModel.Dispose());
Nodes.Clear();
nodeDict.Clear();
Notes.Clear();
Pins.Clear();
Connectors.Clear();
connectorDict.Clear();
Errors.Clear();
Annotations.Clear();
InCanvasSearchViewModel?.Dispose();
Expand Down Expand Up @@ -860,15 +868,18 @@ void CopyPasteChanged(object sender, EventArgs e)

void Connectors_ConnectorAdded(ConnectorModel c)
{
var viewModel = new ConnectorViewModel(this, c);
if (Connectors.All(x => x.ConnectorModel != c))
if (!connectorDict.ContainsKey(c.GUID))
{
// Only create the view model if needed. This prevents event handler leaks
var viewModel = new ConnectorViewModel(this, c);
connectorDict[c.GUID] = viewModel;
Connectors.Add(viewModel);
}
}

void Connectors_ConnectorDeleted(ConnectorModel c)
{
var connector = Connectors.FirstOrDefault(x => x.ConnectorModel == c);
if (connector != null)
if (connectorDict.Remove(c.GUID, out var connector))
{
Connectors.Remove(connector);
connector.Dispose();
Expand Down Expand Up @@ -930,6 +941,7 @@ void Model_NodesCleared()
nodeViewModel.Dispose();
}
Nodes.Clear();
nodeDict.Clear();
}
Errors.Clear();

Expand All @@ -948,7 +960,7 @@ void Model_NodeRemoved(NodeModel node)
NodeViewModel nodeViewModel;
lock (Nodes)
{
nodeViewModel = Nodes.First(x => x.NodeLogic == node);
nodeDict.Remove(node.GUID, out nodeViewModel);
if (nodeViewModel.ErrorBubble != null)
Errors.Remove(nodeViewModel.ErrorBubble);
Nodes.Remove(nodeViewModel);
Expand All @@ -970,6 +982,7 @@ void Model_NodeAdded(NodeModel node)
lock (Nodes)
{
Nodes.Add(nodeViewModel);
nodeDict[node.GUID] = nodeViewModel;
}
if (nodeViewModel.ErrorBubble != null)
Errors.Add(nodeViewModel.ErrorBubble);
Expand All @@ -979,6 +992,20 @@ void Model_NodeAdded(NodeModel node)
SetStopNodeZoomAnimationBehavior(zoomAnimationThresholdFeatureFlagVal);
}

internal NodeViewModel? FindNode(Guid nodeGuid)
{
return nodeDict.TryGetValue(nodeGuid, out var nodeModel)
? nodeModel
: null;
}

internal ConnectorViewModel? FindConnector(Guid connectorGuid)
{
return connectorDict.TryGetValue(connectorGuid, out var connectorModel)
? connectorModel
: null;
}

void PostNodeChangeActions()
{
if (RunSettingsViewModel == null) return;
Expand Down Expand Up @@ -1896,10 +1923,10 @@ private void RefreshViewOnSelectionChange(object sender, NotifyCollectionChanged
/// <returns>Found <see cref="ViewModelBase"/> object.</returns>
internal ViewModelBase GetViewModelInternal(Guid modelGuid)
{
ViewModelBase foundModel = (Connectors.FirstOrDefault(c => c.ConnectorModel.GUID == modelGuid)
?? Nodes.FirstOrDefault(node => node.NodeModel.GUID == modelGuid) as ViewModelBase)
?? (Notes.FirstOrDefault(note => note.Model.GUID == modelGuid)
?? Annotations.FirstOrDefault(annotation => annotation.AnnotationModel.GUID == modelGuid) as ViewModelBase);
ViewModelBase foundModel = FindConnector(modelGuid) as ViewModelBase
?? FindNode(modelGuid) as ViewModelBase
?? Notes.FirstOrDefault(note => note.Model.GUID == modelGuid) as ViewModelBase
?? Annotations.FirstOrDefault(annotation => annotation.AnnotationModel.GUID == modelGuid) as ViewModelBase;

return foundModel;
}
Expand Down
Loading